*~
-/tests/lib/test-bitfield
-/tests/lib/test-seeks
+/tests/lib/test_bitfield
+/tests/lib/test_seek
*.o
*.a
*.la
*.lo
+*.exe
.libs
.deps
*.bkp
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = include types lib formats converter bindings tests doc extras
+SUBDIRS = include types compat lib formats converter bindings tests doc extras
dist_doc_DATA = ChangeLog LICENSE mit-license.txt gpl-2.0.txt \
std-ext-lib.txt
dist_noinst_DATA = CodingStyle
pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = babeltrace.pc
+pkgconfig_DATA = babeltrace.pc babeltrace-ctf.pc
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Babeltrace CTF parser
+Description: libbabeltrace-ctf provides the specific bits necessary to read a Common Trace Format (CTF) trace.
+Version: @PACKAGE_VERSION@
+Requires: babeltrace
+Requires.private:
+Libs: -L${libdir} -lbabeltrace-ctf
+Cflags: -I${includedir}
+
Version: @PACKAGE_VERSION@
Requires:
Requires.private: uuid popt
-Libs: -L${libdir} -lbabeltrace -lbabeltrace-ctf
+Libs: -L${libdir} -lbabeltrace
Cflags: -I${includedir}
--- /dev/null
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = libcompat.la
+
+libcompat_la_SOURCES =
+
+libcompat_la_LDFLAGS = \
+ -Wl,--no-as-needed
+
+if BABELTRACE_BUILD_WITH_MINGW
+libcompat_la_SOURCES += compat_uuid.c
+endif
--- /dev/null
+/*
+ * compat/compat_uuid.h
+ *
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This file is only built under MINGW32 */
+
+#include <windows.h>
+#include <stdlib.h>
+#include <babeltrace/compat/uuid.h>
+
+/* MinGW does not provide byteswap - implement our own version. */
+static
+void swap(unsigned char *ptr, unsigned int i, unsigned int j)
+{
+ unsigned char tmp;
+
+ tmp = ptr[i];
+ ptr[i] = ptr[j];
+ ptr[j] = tmp;
+}
+
+static
+void fix_uuid_endian(unsigned char * ptr)
+{
+ swap(ptr, 0, 3)
+ swap(ptr, 1, 2)
+ swap(ptr, 4, 5)
+ swap(ptr, 6, 7)
+}
+
+int babeltrace_uuid_generate(unsigned char *uuid_out)
+{
+ RPC_STATUS status;
+
+ status = UuidCreate((struct UUID *)uuid_out);
+ if (status == RPC_S_OK)
+ return 0;
+ else
+ return -1;
+}
+
+int babeltrace_uuid_unparse(const unsigned char *uuid_in, char *str_out)
+{
+ RPC_STATUS status;
+ unsigned char *alloc_str;
+ int ret;
+ unsigned char copy_of_uuid_in[BABELTRACE_UUID_LEN];
+
+ /* make a modifyable copy of uuid_in */
+ memcpy(copy_of_uuid_in, uuid_in, BABELTRACE_UUID_LEN);
+
+ fix_uuid_endian(copy_of_uuid_in);
+ status = UuidToString((struct UUID *) copy_of_uuid_in, &alloc_str);
+
+ if (status == RPC_S_OK) {
+ strncpy(str_out, (char *) alloc_str, BABELTRACE_UUID_STR_LEN);
+ str_out[BABELTRACE_UUID_STR_LEN - 1] = '\0';
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ RpcStringFree(&alloc_str);
+ return ret;
+}
+
+int babeltrace_uuid_parse(const char *str_in, unsigned char *uuid_out)
+{
+ RPC_STATUS status;
+
+ status = UuidFromString((unsigned char *) str_in,
+ (struct UUID *) uuid_out);
+ fix_uuid_endian(uuid_out);
+
+ if (status == RPC_S_OK)
+ return 0;
+ else
+ return -1;
+}
+
+int babeltrace_uuid_compare(const unsigned char *uuid_a,
+ const unsigned char *uuid_b)
+{
+ RPC_STATUS status;
+
+ if (!UuidCompare((struct UUID *) uuid_a, (struct UUID *) uuid_b,
+ &status)) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
AC_PROG_YACC
AC_PROG_LEX
-AC_DEFUN([AC_PROG_BISON], [AC_CHECK_PROGS(BISON, bison, bison)])
+if test ! -f "$srcdir/formats/ctf/metadata/ctf-parser.h"; then
+ if test x"$YACC" != "xbison -y"; then
+ AC_MSG_ERROR([[bison not found and is required when building from git.
+ Please install bison]])
+ fi
+fi
+
+if test ! -f "$srcdir/formats/ctf/metadata/ctf-lexer.c"; then
+ if test x"$LEX" != "xflex"; then
+ AC_MSG_ERROR([[flex not found and is required when building from git.
+ Please install flex]])
+ fi
+fi
+
AM_PATH_GLIB_2_0(2.22.0, ,AC_MSG_ERROR([glib is required in order to compile BabelTrace - download it from ftp://ftp.gtk.org/pub/gtk]) , gmodule)
AC_FUNC_MMAP
AC_CHECK_FUNCS([bzero gettimeofday munmap strtoul])
+# Check for MinGW32.
+MINGW32=no
+case $host in
+ *-*-mingw*)
+ MINGW32=yes;;
+esac
+
+AM_CONDITIONAL([BABELTRACE_BUILD_WITH_MINGW], [test "x$MINGW32" = "xyes"])
+
# Check for libuuid
AC_CHECK_LIB([uuid], [uuid_generate],
[
have_libc_uuid=yes
],
[
- AC_MSG_ERROR([Cannot find libuuid uuid_generate nor libc uuid_create. Use [LDFLAGS]=-Ldir to specify their location.])
+ # for MinGW32 we have our own internal implemenation of uuid using Windows functions.
+ if test "x$MINGW32" = xno; then
+ AC_MSG_ERROR([Cannot find libuuid uuid_generate nor libc uuid_create. Use [LDFLAGS]=-Ldir to specify their location.])
+ fi
])
]
)
AC_CONFIG_FILES([
Makefile
types/Makefile
+ compat/Makefile
formats/Makefile
formats/ctf/Makefile
formats/ctf/types/Makefile
bindings/Makefile
bindings/python/Makefile
tests/Makefile
+ tests/bin/Makefile
tests/lib/Makefile
+ tests/utils/Makefile
+ tests/utils/tap/Makefile
extras/Makefile
extras/valgrind/Makefile
babeltrace.pc
+ babeltrace-ctf.pc
])
AC_OUTPUT
babeltrace_LDADD = \
$(top_builddir)/lib/libbabeltrace.la \
$(top_builddir)/formats/ctf/libbabeltrace-ctf.la \
+ $(top_builddir)/compat/libcompat.la \
$(top_builddir)/formats/ctf-text/libbabeltrace-ctf-text.la \
$(top_builddir)/formats/ctf-metadata/libbabeltrace-ctf-metadata.la \
$(top_builddir)/formats/bt-dummy/libbabeltrace-dummy.la
babeltrace_log_LDADD = \
$(top_builddir)/lib/libbabeltrace.la \
- $(top_builddir)/formats/ctf/libbabeltrace-ctf.la
+ $(top_builddir)/formats/ctf/libbabeltrace-ctf.la \
+ $(top_builddir)/compat/libcompat.la
if BABELTRACE_BUILD_WITH_LIBUUID
babeltrace_log_LDADD += -luuid
if BABELTRACE_BUILD_WITH_LIBC_UUID
babeltrace_log_LDADD += -lc
endif
+
+if BABELTRACE_BUILD_WITH_MINGW
+babeltrace_log_LDADD += -lrpcrt4 -lintl -liconv -lole32 -lpopt -lpthread
+babeltrace_LDADD += -lrpcrt4 -lintl -liconv -lole32 -lpopt -lpthread
+endif
.PP
Babeltrace is a trace viewer and converter reading and writing the
Common Trace Format (CTF). Its main use is to pretty-print CTF traces
-into a human-readable text output.
+into a human-readable text output ordered by time.
.PP
This program follow the usual GNU command line syntax with long options
if BABELTRACE_BUILD_WITH_LIBC_UUID
libctf_ast_la_LIBADD += -lc
endif
+if BABELTRACE_BUILD_WITH_MINGW
+libctf_ast_la_LIBADD += -lrpcrt4 -lintl -liconv -lole32 -lpopt
+endif
noinst_PROGRAMS = ctf-parser-test
ctf_parser_test_SOURCES = ctf-parser-test.c
ctf_parser_test_LDADD = \
libctf-parser.la \
libctf-ast.la
+
+CLEANFILES = ctf-lexer.c ctf-parser.c ctf-parser.h ctf-parser.output
// data is a pointer to a 'SParserParam' structure
//#define YYPARSE_PARAM scanner
-// the argument for the 'yylex' function
-#define YYLEX_PARAM ((struct ctf_scanner *) scanner)->scanner
-
struct ctf_node;
struct ctf_parser;
}
BT_HIDDEN
-int yyparse(struct ctf_scanner *scanner);
+int yyparse(struct ctf_scanner *scanner, yyscan_t yyscanner);
BT_HIDDEN
-int yylex(union YYSTYPE *yyval, struct ctf_scanner *scanner);
+int yylex(union YYSTYPE *yyval, yyscan_t yyscanner);
BT_HIDDEN
int yylex_init_extra(struct ctf_scanner *scanner, yyscan_t * ptr_yy_globals);
BT_HIDDEN
int yylex_destroy(yyscan_t yyscanner);
BT_HIDDEN
-void yyrestart(FILE * in_str, yyscan_t scanner);
+void yyrestart(FILE * in_str, yyscan_t yyscanner);
BT_HIDDEN
int yyget_lineno(yyscan_t yyscanner);
BT_HIDDEN
}
BT_HIDDEN
-void yyerror(struct ctf_scanner *scanner, const char *str)
+void yyerror(struct ctf_scanner *scanner, yyscan_t yyscanner, const char *str)
{
printfl_error(yyget_lineno(scanner->scanner),
"token \"%s\": %s\n",
#define reparent_error(scanner, str) \
do { \
- yyerror(scanner, YY_("reparent_error: " str)); \
+ yyerror(scanner, scanner->scanner, YY_("reparent_error: " str)); \
YYERROR; \
} while (0)
int ctf_scanner_append_ast(struct ctf_scanner *scanner)
{
- return yyparse(scanner);
+ return yyparse(scanner, scanner->scanner);
}
struct ctf_scanner *ctf_scanner_alloc(FILE *input)
/* %locations */
%error-verbose
%parse-param {struct ctf_scanner *scanner}
-%lex-param {struct ctf_scanner *scanner}
+%parse-param {yyscan_t yyscanner}
+%lex-param {yyscan_t yyscanner}
/*
* Expect two shift-reduce conflicts. Caused by enum name-opt : type {}
* vs struct { int :value; } (unnamed bit-field). The default is to
goto error;
}
clock->absolute = ret;
+ ret = 0;
} else {
fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in clock declaration.\n", __func__, left);
}
babeltrace/trace-handle-internal.h \
babeltrace/compat/uuid.h \
babeltrace/compat/memstream.h \
+ babeltrace/compat/string.h \
babeltrace/compat/utc.h \
babeltrace/endian.h \
babeltrace/mmap-align.h
#include <stdio.h>
#include <glib.h>
#include <stdint.h>
-#include <string.h>
+#include <babeltrace/compat/string.h>
#define PERROR_BUFLEN 200
perrorstr, \
## args)
-#if !defined(__linux__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
-
#define _bt_printf_perror(fp, fmt, args...) \
({ \
char buf[PERROR_BUFLEN] = "Error in strerror_r()"; \
- strerror_r(errno, buf, sizeof(buf)); \
+ compat_strerror_r(errno, buf, sizeof(buf)); \
_bt_printfe(fp, "error", buf, fmt, ## args); \
})
#define _bt_printfl_perror(fp, lineno, fmt, args...) \
({ \
char buf[PERROR_BUFLEN] = "Error in strerror_r()"; \
- strerror_r(errno, buf, sizeof(buf)); \
+ compat_strerror_r(errno, buf, sizeof(buf)); \
_bt_printfle(fp, "error", lineno, buf, fmt, ## args); \
})
-#else
-
-/*
- * Version using GNU strerror_r, for linux with appropriate defines.
- */
-
-#define _bt_printf_perror(fp, fmt, args...) \
- ({ \
- char *buf; \
- char tmp[PERROR_BUFLEN] = "Error in strerror_r()"; \
- buf = strerror_r(errno, tmp, sizeof(tmp)); \
- _bt_printfe(fp, "error", buf, fmt, ## args); \
- })
-
-#define _bt_printfl_perror(fp, lineno, fmt, args...) \
- ({ \
- char *buf; \
- char tmp[PERROR_BUFLEN] = "Error in strerror_r()"; \
- buf = strerror_r(errno, tmp, sizeof(tmp)); \
- _bt_printfle(fp, "error", lineno, buf, fmt, ## args); \
- })
-
-#endif
-
/* printf without lineno information */
#define printf_fatal(fmt, args...) \
_bt_printf(stderr, "fatal", fmt, ## args)
--- /dev/null
+#ifndef _BABELTRACE_COMPAT_STRING_H
+#define _BABELTRACE_COMPAT_STRING_H
+
+/*
+ * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <string.h>
+
+#if !defined(__linux__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
+
+/* XSI-compliant strerror_r */
+static inline
+int compat_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ return strerror_r(errnum, buf, buflen);
+}
+
+#else
+
+/* GNU-compliant strerror_r */
+static inline
+int compat_strerror_r(int errnum, char *buf, size_t buflen)
+{
+ char *retbuf;
+
+ retbuf = strerror_r(errnum, buf, buflen);
+ if (retbuf != buf)
+ strncpy(buf, retbuf, buflen);
+ buf[buflen - 1] = '\0';
+ return 0;
+}
+
+#endif
+
+#endif /* _BABELTRACE_COMPAT_STRING_H */
-#ifndef _BABELTRACE_UUID_H
-#define _BABELTRACE_UUID_H
+#ifndef _BABELTRACE_COMPAT_UUID_H
+#define _BABELTRACE_COMPAT_UUID_H
/*
- * babeltrace/uuid.h
+ * babeltrace/compat/uuid.h
*
* Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
return -1;
}
+#elif defined(__MINGW32__)
+
+int babeltrace_uuid_generate(unsigned char *uuid_out);
+int babeltrace_uuid_unparse(const unsigned char *uuid_in, char *str_out);
+int babeltrace_uuid_parse(const char *str_in, unsigned char *uuid_out);
+int babeltrace_uuid_compare(const unsigned char *uuid_a,
+ const unsigned char *uuid_b);
+
#else
#error "Babeltrace needs to have a UUID generator configured."
#endif
-#endif /* _BABELTRACE_UUID_H */
+#endif /* _BABELTRACE_COMPAT_UUID_H */
#ifdef __FreeBSD__
#include <machine/endian.h>
+#elif defined(__MINGW32__)
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+
+#ifndef __BYTE_ORDER
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+#define BIG_ENDIAN __BIG_ENDIAN
+#define PDP_ENDIAN __PDP_ENDIAN
+#define BYTE_ORDER __BYTE_ORDER
#else
#include <endian.h>
#endif
libbabeltrace_la_LDFLAGS = \
-Wl,--no-as-needed \
prio_heap/libprio_heap.la \
- $(top_builddir)/types/libbabeltrace_types.la
+ $(top_builddir)/types/libbabeltrace_types.la \
+ $(top_builddir)/compat/libcompat.la
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
+SUBDIRS = utils bin lib
-SUBDIRS = lib
+EXTRA_DIST = ctf-traces/** tests
-EXTRA_DIST = runall.sh ctf-traces/**
+SCRIPT_LIST = run.sh
+
+dist_noinst_SCRIPTS = $(SCRIPT_LIST)
+
+all-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ cp -f $(srcdir)/$$script $(builddir); \
+ done; \
+ fi
+
+clean-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ rm -f $(builddir)/$$script; \
+ done; \
+ fi
check-am:
- ./runall.sh
+ ./run.sh tests
--- /dev/null
+SCRIPT_LIST = test_trace_read
+
+dist_noinst_SCRIPTS = $(SCRIPT_LIST)
+
+all-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ cp -f $(srcdir)/$$script $(builddir); \
+ done; \
+ fi
+
+clean-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ rm -f $(builddir)/$$script; \
+ done; \
+ fi
--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) - 2013 Christian Babeux <christian.babeux@efficios.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License, version 2 only, as
+# published by the Free Software Foundation.
+#
+# 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, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+CURDIR=$(dirname $0)
+TESTDIR=$CURDIR/..
+
+BABELTRACE_BIN=$CURDIR/../../converter/babeltrace
+
+CTF_TRACES=$TESTDIR/ctf-traces
+
+source $TESTDIR/utils/tap/tap.sh
+
+SUCCESS_TRACES=(${CTF_TRACES}/succeed/*)
+FAIL_TRACES=(${CTF_TRACES}/fail/*)
+
+NUM_TESTS=$((${#SUCCESS_TRACES[@]} + ${#FAIL_TRACES[@]}))
+
+plan_tests $NUM_TESTS
+
+for path in ${SUCCESS_TRACES[@]}; do
+ trace=$(basename ${path})
+ $BABELTRACE_BIN ${path} > /dev/null 2>&1
+ ok $? "Run babeltrace with trace ${trace}"
+done
+
+for path in ${FAIL_TRACES[@]}; do
+ trace=$(basename ${path})
+ $BABELTRACE_BIN ${path} > /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ fail "Run babeltrace with invalid trace ${trace}"
+ else
+ pass "Run babeltrace with invalid trace ${trace}"
+ fi
+done
major = 0;
minor = 1;
test = "\"";
- test2 = "?\x20\o040?";
+ test2 = "?\x20\040?";
test3 = '\n';
uuid = "2a6422d0-6cee-11e0-8c08-cb07d7b3a564";
byte_order = le;
-AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
+AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/tests/utils
noinst_LIBRARIES = libtestcommon.a
-libtestcommon_a_SOURCES = tap.c tap.h common.c common.h
+LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
-test_seeks_LDADD = libtestcommon.a \
+libtestcommon_a_SOURCES = common.c common.h
+
+# -Wl,--no-as-needed is needed for recent gold linker who seems to think
+# it knows better and considers libraries with constructors having
+# side-effects as dead code.
+test_seek_LDFLAGS = -Wl,--no-as-needed
+test_seek_LDADD = $(LIBTAP) libtestcommon.a \
$(top_builddir)/lib/libbabeltrace.la \
$(top_builddir)/formats/ctf/libbabeltrace-ctf.la
-test_bitfield_LDADD = libtestcommon.a
+test_bitfield_LDADD = $(LIBTAP) libtestcommon.a
+
+noinst_PROGRAMS = test_seek test_bitfield
+
+test_seek_SOURCES = test_seek.c
+test_bitfield_SOURCES = test_bitfield.c
-noinst_PROGRAMS = test-seeks test-bitfield
+SCRIPT_LIST = test_seek_big_trace test_seek_empty_packet
-test_seeks_SOURCES = test-seeks.c
-test_bitfield_SOURCES = test-bitfield.c
+dist_noinst_SCRIPTS = $(SCRIPT_LIST)
-EXTRA_DIST = README.tap runall.sh
+all-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ cp -f $(srcdir)/$$script $(builddir); \
+ done; \
+ fi
-check-am:
- ./runall.sh
+clean-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ rm -f $(builddir)/$$script; \
+ done; \
+ fi
+++ /dev/null
-tap.c and tap.h were taken from
-http://jc.ngo.org.uk/trac-bin/trac.cgi/wiki/LibTap
+++ /dev/null
-#!/bin/sh
-# run Seeks tests
-# With a trace than contains empty packets
-./test-seeks ../ctf-traces/succeed/wk-heartbeat-u/ 1351532897586558519 1351532897591331194
-# With a bigger trace
-./test-seeks ../ctf-traces/succeed/lttng-modules-2.0-pre5/ 61334174524234 61336381998396
-
-# run bitfield tests
-./test-bitfield
+++ /dev/null
-/*-
- * Copyright (c) 2004 Nik Clayton
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "tap.h"
-
-static int no_plan = 0;
-static int skip_all = 0;
-static int have_plan = 0;
-static unsigned int test_count = 0; /* Number of tests that have been run */
-static unsigned int e_tests = 0; /* Expected number of tests to run */
-static unsigned int failures = 0; /* Number of tests that failed */
-static char *todo_msg = NULL;
-static char *todo_msg_fixed = "libtap malloc issue";
-static int todo = 0;
-static int test_died = 0;
-
-/* Encapsulate the pthread code in a conditional. In the absence of
- libpthread the code does nothing */
-#ifdef HAVE_LIBPTHREAD
-#include <pthread.h>
-static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
-# define LOCK pthread_mutex_lock(&M);
-# define UNLOCK pthread_mutex_unlock(&M);
-#else
-# define LOCK
-# define UNLOCK
-#endif
-
-static void _expected_tests(unsigned int);
-static void _tap_init(void);
-static void _cleanup(void);
-
-/*
- * Generate a test result.
- *
- * ok -- boolean, indicates whether or not the test passed.
- * test_name -- the name of the test, may be NULL
- * test_comment -- a comment to print afterwards, may be NULL
- */
-unsigned int
-_gen_result(int ok, const char *func, char *file, unsigned int line,
- char *test_name, ...)
-{
- va_list ap;
- char *local_test_name = NULL;
- char *c;
- int name_is_digits;
-
- LOCK;
-
- test_count++;
-
- /* Start by taking the test name and performing any printf()
- expansions on it */
- if(test_name != NULL) {
- va_start(ap, test_name);
- vasprintf(&local_test_name, test_name, ap);
- va_end(ap);
-
- /* Make sure the test name contains more than digits
- and spaces. Emit an error message and exit if it
- does */
- if(local_test_name) {
- name_is_digits = 1;
- for(c = local_test_name; *c != '\0'; c++) {
- if(!isdigit(*c) && !isspace(*c)) {
- name_is_digits = 0;
- break;
- }
- }
-
- if(name_is_digits) {
- diag(" You named your test '%s'. You shouldn't use numbers for your test names.", local_test_name);
- diag(" Very confusing.");
- }
- }
- }
-
- if(!ok) {
- printf("not ");
- failures++;
- }
-
- printf("ok %d", test_count);
-
- if(test_name != NULL) {
- printf(" - ");
-
- /* Print the test name, escaping any '#' characters it
- might contain */
- if(local_test_name != NULL) {
- flockfile(stdout);
- for(c = local_test_name; *c != '\0'; c++) {
- if(*c == '#')
- fputc('\\', stdout);
- fputc((int)*c, stdout);
- }
- funlockfile(stdout);
- } else { /* vasprintf() failed, use a fixed message */
- printf("%s", todo_msg_fixed);
- }
- }
-
- /* If we're in a todo_start() block then flag the test as being
- TODO. todo_msg should contain the message to print at this
- point. If it's NULL then asprintf() failed, and we should
- use the fixed message.
-
- This is not counted as a failure, so decrement the counter if
- the test failed. */
- if(todo) {
- printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
- if(!ok)
- failures--;
- }
-
- printf("\n");
-
- if(!ok) {
- if(getenv("HARNESS_ACTIVE") != NULL)
- fputs("\n", stderr);
-
- diag(" Failed %stest (%s:%s() at line %d)",
- todo ? "(TODO) " : "", file, func, line);
- }
- free(local_test_name);
-
- UNLOCK;
-
- /* We only care (when testing) that ok is positive, but here we
- specifically only want to return 1 or 0 */
- return ok ? 1 : 0;
-}
-
-/*
- * Initialise the TAP library. Will only do so once, however many times it's
- * called.
- */
-void
-_tap_init(void)
-{
- static int run_once = 0;
-
- if(!run_once) {
- atexit(_cleanup);
-
- /* stdout needs to be unbuffered so that the output appears
- in the same place relative to stderr output as it does
- with Test::Harness */
- setbuf(stdout, 0);
- run_once = 1;
- }
-}
-
-/*
- * Note that there's no plan.
- */
-int
-plan_no_plan(void)
-{
-
- LOCK;
-
- _tap_init();
-
- if(have_plan != 0) {
- fprintf(stderr, "You tried to plan twice!\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- have_plan = 1;
- no_plan = 1;
-
- UNLOCK;
-
- return 1;
-}
-
-/*
- * Note that the plan is to skip all tests
- */
-int
-plan_skip_all(char *reason)
-{
-
- LOCK;
-
- _tap_init();
-
- skip_all = 1;
-
- printf("1..0");
-
- if(reason != NULL)
- printf(" # Skip %s", reason);
-
- printf("\n");
-
- UNLOCK;
-
- exit(0);
-}
-
-/*
- * Note the number of tests that will be run.
- */
-int
-plan_tests(unsigned int tests)
-{
-
- LOCK;
-
- _tap_init();
-
- if(have_plan != 0) {
- fprintf(stderr, "You tried to plan twice!\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- if(tests == 0) {
- fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
- test_died = 1;
- UNLOCK;
- exit(255);
- }
-
- have_plan = 1;
-
- _expected_tests(tests);
-
- UNLOCK;
-
- return e_tests;
-}
-
-unsigned int
-diag(char *fmt, ...)
-{
- va_list ap;
-
- fputs("# ", stderr);
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fputs("\n", stderr);
-
- return 0;
-}
-
-void
-_expected_tests(unsigned int tests)
-{
-
- printf("1..%d\n", tests);
- e_tests = tests;
-}
-
-int
-skip(unsigned int n, char *fmt, ...)
-{
- va_list ap;
- char *skip_msg;
-
- LOCK;
-
- va_start(ap, fmt);
- asprintf(&skip_msg, fmt, ap);
- va_end(ap);
-
- while(n-- > 0) {
- test_count++;
- printf("ok %d # skip %s\n", test_count,
- skip_msg != NULL ?
- skip_msg : "libtap():malloc() failed");
- }
-
- free(skip_msg);
-
- UNLOCK;
-
- return 1;
-}
-
-void
-todo_start(char *fmt, ...)
-{
- va_list ap;
-
- LOCK;
-
- va_start(ap, fmt);
- vasprintf(&todo_msg, fmt, ap);
- va_end(ap);
-
- todo = 1;
-
- UNLOCK;
-}
-
-void
-todo_end(void)
-{
-
- LOCK;
-
- todo = 0;
- free(todo_msg);
-
- UNLOCK;
-}
-
-int
-exit_status(void)
-{
- int r;
-
- LOCK;
-
- /* If there's no plan, just return the number of failures */
- if(no_plan || !have_plan) {
- UNLOCK;
- return failures;
- }
-
- /* Ran too many tests? Return the number of tests that were run
- that shouldn't have been */
- if(e_tests < test_count) {
- r = test_count - e_tests;
- UNLOCK;
- return r;
- }
-
- /* Return the number of tests that failed + the number of tests
- that weren't run */
- r = failures + e_tests - test_count;
- UNLOCK;
-
- return r;
-}
-
-/*
- * Cleanup at the end of the run, produce any final output that might be
- * required.
- */
-void
-_cleanup(void)
-{
-
- LOCK;
-
- /* If plan_no_plan() wasn't called, and we don't have a plan,
- and we're not skipping everything, then something happened
- before we could produce any output */
- if(!no_plan && !have_plan && !skip_all) {
- diag("Looks like your test died before it could output anything.");
- UNLOCK;
- return;
- }
-
- if(test_died) {
- diag("Looks like your test died just after %d.", test_count);
- UNLOCK;
- return;
- }
-
-
- /* No plan provided, but now we know how many tests were run, and can
- print the header at the end */
- if(!skip_all && (no_plan || !have_plan)) {
- printf("1..%d\n", test_count);
- }
-
- if((have_plan && !no_plan) && e_tests < test_count) {
- diag("Looks like you planned %d %s but ran %d extra.",
- e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
- UNLOCK;
- return;
- }
-
- if((have_plan || !no_plan) && e_tests > test_count) {
- diag("Looks like you planned %d %s but only ran %d.",
- e_tests, e_tests == 1 ? "test" : "tests", test_count);
- UNLOCK;
- return;
- }
-
- if(failures)
- diag("Looks like you failed %d %s of %d.",
- failures, failures == 1 ? "test" : "tests", test_count);
-
- UNLOCK;
-}
+++ /dev/null
-/*-
- * Copyright (c) 2004 Nik Clayton
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
- and requires the caller to add the final comma if they've ommitted
- the optional arguments */
-#ifdef __GNUC__
-# define ok(e, test, ...) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, \
- test, ## __VA_ARGS__) : \
- _gen_result(0, __func__, __FILE__, __LINE__, \
- test, ## __VA_ARGS__))
-
-# define ok1(e) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
- _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
-
-# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
-# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
-
-# define skip_start(test, n, fmt, ...) \
- do { \
- if((test)) { \
- skip(n, fmt, ## __VA_ARGS__); \
- continue; \
- }
-#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
-# define ok(e, ...) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, \
- __VA_ARGS__) : \
- _gen_result(0, __func__, __FILE__, __LINE__, \
- __VA_ARGS__))
-
-# define ok1(e) ((e) ? \
- _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
- _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
-
-# define pass(...) ok(1, __VA_ARGS__);
-# define fail(...) ok(0, __VA_ARGS__);
-
-# define skip_start(test, n, ...) \
- do { \
- if((test)) { \
- skip(n, __VA_ARGS__); \
- continue; \
- }
-#else /* __STDC_VERSION__ */
-# error "Needs gcc or C99 compiler for variadic macros."
-#endif /* __STDC_VERSION__ */
-
-#define skip_end() } while(0);
-
-unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
-
-int plan_no_plan(void);
-int plan_skip_all(char *);
-int plan_tests(unsigned int);
-
-unsigned int diag(char *, ...);
-
-int skip(unsigned int, char *, ...);
-
-void todo_start(char *, ...);
-void todo_end(void);
-
-int exit_status(void);
+++ /dev/null
-/*
- * test-bitfield.c
- *
- * BabelTrace - bitfield test program
- *
- * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * 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; under version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#define _GNU_SOURCE
-#include <babeltrace/bitfield.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "tap.h"
-
-unsigned int glob;
-
-/*
- * This function is only declared to show the size of a bitfield write in
- * objdump.
- */
-void fct(void)
-{
- bt_bitfield_write(&glob, unsigned int, 12, 15, 0x12345678);
-}
-
-/* Test array size, in bytes */
-#define TEST_LEN 128
-#define NR_TESTS 10
-#define SIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, signed"
-#define UNSIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, unsigned"
-#define DIAG_FMT_STR "Failed reading value written \"%s\"-wise, with start=%i" \
- " and length=%i. Read %llX"
-
-unsigned int srcrand;
-
-#if defined(__i386) || defined(__x86_64)
-
-static inline int fls(int x)
-{
- int r;
- asm("bsrl %1,%0\n\t"
- "cmovzl %2,%0"
- : "=&r" (r) : "rm" (x), "rm" (-1));
- return r + 1;
-}
-
-#elif defined(__PPC__)
-
-static __inline__ int fls(unsigned int x)
-{
- int lz;
-
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
- return 32 - lz;
-}
-
-#else
-
-static int fls(unsigned int x)
-{
- int r = 32;
-
- if (!x)
- return 0;
- if (!(x & 0xFFFF0000U)) {
- x <<= 16;
- r -= 16;
- }
- if (!(x & 0xFF000000U)) {
- x <<= 8;
- r -= 8;
- }
- if (!(x & 0xF0000000U)) {
- x <<= 4;
- r -= 4;
- }
- if (!(x & 0xC0000000U)) {
- x <<= 2;
- r -= 2;
- }
- if (!(x & 0x80000000U)) {
- x <<= 1;
- r -= 1;
- }
- return r;
-}
-
-#endif
-
-#define print_byte_array(c, len) \
-do { \
- unsigned long i; \
- \
- for (i = 0; i < (len); i++) { \
- printf("0x%X", (c)[i]); \
- if (i != (len) - 1) \
- printf(" "); \
- } \
- printf("\n"); \
-} while (0)
-
-#define init_byte_array(c, len, val) \
-do { \
- unsigned long i; \
- \
- for (i = 0; i < (len); i++) \
- (c)[i] = (val); \
-} while (0)
-
-#define check_result(ref, val, buffer, typename, start, len, \
- desc_fmt_str) \
-({ \
- if ((val) != (ref)) { \
- fail(desc_fmt_str, ref); \
- diag(DIAG_FMT_STR, #typename, start, len, val); \
- printf("# "); \
- print_byte_array(buffer, TEST_LEN); \
- } \
- (val) != (ref); \
-})
-
-void run_test_unsigned(void)
-{
- unsigned int src, nrbits;
- union {
- unsigned char c[TEST_LEN];
- unsigned short s[TEST_LEN/sizeof(unsigned short)];
- unsigned int i[TEST_LEN/sizeof(unsigned int)];
- unsigned long l[TEST_LEN/sizeof(unsigned long)];
- unsigned long long ll[TEST_LEN/sizeof(unsigned long long)];
- } target;
- unsigned long long readval;
- unsigned int s, l;
-
- src = srcrand;
- nrbits = fls(src);
-
- for (s = 0; s < CHAR_BIT * TEST_LEN; s++) {
- for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) {
- init_byte_array(target.c, TEST_LEN, 0xFF);
- bt_bitfield_write(target.c, unsigned char, s, l, src);
- bt_bitfield_read(target.c, unsigned char, s, l, &readval);
- if (check_result(src, readval, target.c, unsigned char,
- s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0xFF);
- bt_bitfield_write(target.s, unsigned short, s, l, src);
- bt_bitfield_read(target.c, unsigned char, s, l, &readval);
- if (check_result(src, readval, target.c, unsigned short,
- s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0xFF);
- bt_bitfield_write(target.i, unsigned int, s, l, src);
- bt_bitfield_read(target.c, unsigned char, s, l, &readval);
- if (check_result(src, readval, target.c, unsigned int,
- s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0xFF);
- bt_bitfield_write(target.l, unsigned long, s, l, src);
- bt_bitfield_read(target.c, unsigned char, s, l, &readval);
- if (check_result(src, readval, target.c, unsigned long,
- s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0xFF);
- bt_bitfield_write(target.ll, unsigned long long, s, l, src);
- bt_bitfield_read(target.c, unsigned char, s, l, &readval);
- if (check_result(src, readval, target.c, unsigned long long,
- s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
- }
- }
-
- pass(UNSIGNED_TEST_DESC_FMT_STR, src);
-}
-
-void run_test_signed(void)
-{
- int src, nrbits;
- union {
- signed char c[TEST_LEN];
- short s[TEST_LEN/sizeof(short)];
- int i[TEST_LEN/sizeof(int)];
- long l[TEST_LEN/sizeof(long)];
- long long ll[TEST_LEN/sizeof(long long)];
- } target;
- long long readval;
- unsigned int s, l;
-
- src = srcrand;
- if (src & 0x80000000U)
- nrbits = fls(~src) + 1; /* Find least significant bit conveying sign */
- else
- nrbits = fls(src) + 1; /* Keep sign at 0 */
-
- for (s = 0; s < CHAR_BIT * TEST_LEN; s++) {
- for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) {
- init_byte_array(target.c, TEST_LEN, 0x0);
- bt_bitfield_write(target.c, signed char, s, l, src);
- bt_bitfield_read(target.c, signed char, s, l, &readval);
- if (check_result(src, readval, target.c, signed char,
- s, l, SIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0x0);
- bt_bitfield_write(target.s, short, s, l, src);
- bt_bitfield_read(target.c, signed char, s, l, &readval);
- if (check_result(src, readval, target.c, short,
- s, l, SIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0x0);
- bt_bitfield_write(target.i, int, s, l, src);
- bt_bitfield_read(target.c, signed char, s, l, &readval);
- if (check_result(src, readval, target.c, int,
- s, l, SIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0x0);
- bt_bitfield_write(target.l, long, s, l, src);
- bt_bitfield_read(target.c, signed char, s, l, &readval);
- if (check_result(src, readval, target.c, long,
- s, l, SIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
-
- init_byte_array(target.c, TEST_LEN, 0x0);
- bt_bitfield_write(target.ll, long long, s, l, src);
- bt_bitfield_read(target.c, signed char, s, l, &readval);
- if (check_result(src, readval, target.c, long long,
- s, l, SIGNED_TEST_DESC_FMT_STR)) {
- return;
- }
- }
- }
-
- pass(SIGNED_TEST_DESC_FMT_STR, src);
-}
-
-void run_test(void)
-{
- int i;
- plan_tests(NR_TESTS * 2 + 6);
-
- srand(time(NULL));
-
- srcrand = 0;
- run_test_unsigned();
- srcrand = 0;
- run_test_signed();
-
- srcrand = 1;
- run_test_unsigned();
-
- srcrand = ~0U;
- run_test_unsigned();
-
- srcrand = -1;
- run_test_signed();
-
- srcrand = (int)0x80000000U;
- run_test_signed();
-
- for (i = 0; i < NR_TESTS; i++) {
- srcrand = rand();
- run_test_unsigned();
- run_test_signed();
- }
-}
-
-static
-int print_encodings(unsigned long src, unsigned int shift, unsigned int len)
-{
- union {
- unsigned char c[8];
- unsigned short s[4];
- unsigned int i[2];
- unsigned long l[2];
- unsigned long long ll[1];
- } target;
- unsigned long long readval;
-
- init_byte_array(target.c, 8, 0xFF);
- bt_bitfield_write(target.c, unsigned char, shift, len, src);
- printf("bytewise\n");
- print_byte_array(target.c, 8);
-
- init_byte_array(target.c, 8, 0xFF);
- bt_bitfield_write(target.s, unsigned short, shift, len, src);
- printf("shortwise\n");
- print_byte_array(target.c, 8);
-
- init_byte_array(target.c, 8, 0xFF);
- bt_bitfield_write(target.i, unsigned int, shift, len, src);
- printf("intwise\n");
- print_byte_array(target.c, 8);
-
- init_byte_array(target.c, 8, 0xFF);
- bt_bitfield_write(target.l, unsigned long, shift, len, src);
- printf("longwise\n");
- print_byte_array(target.c, 8);
-
- init_byte_array(target.c, 8, 0xFF);
- bt_bitfield_write(target.ll, unsigned long long, shift, len, src);
- printf("lluwise\n");
- print_byte_array(target.c, 8);
-
- bt_bitfield_read(target.c, unsigned char, shift, len, &readval);
- printf("read: %llX\n", readval);
- print_byte_array(target.c, 8);
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- if (argc > 1) {
- /* Print encodings */
- unsigned long src;
- unsigned int shift, len;
-
- src = atoi(argv[1]);
- if (argc > 2)
- shift = atoi(argv[2]);
- else
- shift = 12;
- if (argc > 3)
- len = atoi(argv[3]);
- else
- len = 40;
- return print_encodings(src, shift, len);
- }
-
- /* Run tap-formated tests */
- run_test();
- return exit_status();
-}
+++ /dev/null
-/*
- * test-seeks.c
- *
- * Lib BabelTrace - Seeks test program
- *
- * Copyright 2012 - Yannick Brosseau <yannick.brosseau@gmail.com>
- *
- * 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; under version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#define _GNU_SOURCE
-#include <babeltrace/context.h>
-#include <babeltrace/iterator.h>
-#include <babeltrace/ctf/iterator.h>
-#include <babeltrace/ctf/events.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "common.h"
-#include "tap.h"
-
-#define NR_TESTS 29
-
-void run_seek_begin(char *path, uint64_t expected_begin)
-{
- struct bt_context *ctx;
- struct bt_ctf_iter *iter;
- struct bt_ctf_event *event;
- struct bt_iter_pos newpos;
- int ret;
- uint64_t timestamp_begin;
- uint64_t timestamp_seek_begin;
-
- /* Open the trace */
- ctx = create_context_with_path(path);
- if (!ctx) {
- plan_skip_all("Cannot create valid context");
- }
-
- /* Create iterator with null begin and end */
- iter = bt_ctf_iter_create(ctx, NULL, NULL);
- if (!iter) {
- plan_skip_all("Cannot create valid iterator");
- }
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid");
-
- /* Validate that the first timestamp is right */
- timestamp_begin = bt_ctf_get_timestamp(event);
-
- ok1(timestamp_begin == expected_begin);
-
- /* Validate that we get the same value after a seek begin */
- newpos.type = BT_SEEK_BEGIN;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek begin retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid");
-
- timestamp_seek_begin = bt_ctf_get_timestamp(event);
-
- ok1(timestamp_begin == timestamp_seek_begin);
-
- bt_context_put(ctx);
-}
-
-
-void run_seek_last(char *path, uint64_t expected_last)
-{
- struct bt_context *ctx;
- struct bt_ctf_iter *iter;
- struct bt_ctf_event *event;
- struct bt_iter_pos newpos;
- int ret;
- uint64_t timestamp_last;
-
- /* Open the trace */
- ctx = create_context_with_path(path);
- if (!ctx) {
- plan_skip_all("Cannot create valid context");
- }
-
- /* Create iterator with null last and end */
- iter = bt_ctf_iter_create(ctx, NULL, NULL);
- if (!iter) {
- plan_skip_all("Cannot create valid iterator");
- }
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at beginning");
-
- /* Seek to last */
- newpos.type = BT_SEEK_LAST;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek last retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at last position");
-
- timestamp_last = bt_ctf_get_timestamp(event);
-
- ok1(timestamp_last == expected_last);
-
- /* Try to read next event */
- ret = bt_iter_next(bt_ctf_get_iter(iter));
-
- ok(ret == 0, "iter next should return an error");
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event == 0, "Event after last should be invalid");
-
- bt_context_put(ctx);
-}
-
-void run_seek_time_at_last(char *path, uint64_t expected_last)
-{
- struct bt_context *ctx;
- struct bt_ctf_iter *iter;
- struct bt_ctf_event *event;
- struct bt_iter_pos newpos;
- int ret;
- uint64_t timestamp_last;
-
- /* Open the trace */
- ctx = create_context_with_path(path);
- if (!ctx) {
- plan_skip_all("Cannot create valid context");
- }
-
- /* Create iterator with null last and end */
- iter = bt_ctf_iter_create(ctx, NULL, NULL);
- if (!iter) {
- plan_skip_all("Cannot create valid iterator");
- }
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at beginning");
-
- /* Seek to last */
- newpos.type = BT_SEEK_TIME;
- newpos.u.seek_time = expected_last;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek time at last retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at last position");
-
- timestamp_last = bt_ctf_get_timestamp(event);
-
- ok1(timestamp_last == expected_last);
-
- /* Try to read next event */
- ret = bt_iter_next(bt_ctf_get_iter(iter));
-
- ok(ret == 0, "iter next should return an error");
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event == 0, "Event after last should be invalid");
-
- bt_context_put(ctx);
-}
-
-void run_seek_cycles(char *path,
- uint64_t expected_begin,
- uint64_t expected_last)
-{
- struct bt_context *ctx;
- struct bt_ctf_iter *iter;
- struct bt_ctf_event *event;
- struct bt_iter_pos newpos;
- int ret;
- uint64_t timestamp;
-
- /* Open the trace */
- ctx = create_context_with_path(path);
- if (!ctx) {
- plan_skip_all("Cannot create valid context");
- }
-
- /* Create iterator with null last and end */
- iter = bt_ctf_iter_create(ctx, NULL, NULL);
- if (!iter) {
- plan_skip_all("Cannot create valid iterator");
- }
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at beginning");
-
- /* Seek to last */
- newpos.type = BT_SEEK_LAST;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek last retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at last position");
-
- timestamp = bt_ctf_get_timestamp(event);
-
- ok1(timestamp == expected_last);
-
- /* Try to read next event */
- ret = bt_iter_next(bt_ctf_get_iter(iter));
-
- ok(ret == 0, "iter next should return an error");
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event == 0, "Event after last should be invalid");
-
- /* Seek to BEGIN */
- newpos.type = BT_SEEK_BEGIN;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek begin retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at first position");
-
- timestamp = bt_ctf_get_timestamp(event);
-
- ok1(timestamp == expected_begin);
-
- /* Seek last again */
- newpos.type = BT_SEEK_LAST;
- ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
-
- ok(ret == 0, "Seek last retval %d", ret);
-
- event = bt_ctf_iter_read_event(iter);
-
- ok(event, "Event valid at last position");
-
- timestamp = bt_ctf_get_timestamp(event);
-
- ok1(timestamp == expected_last);
-
- bt_context_put(ctx);
-}
-
-int main(int argc, char **argv)
-{
- char *path;
- uint64_t expected_begin;
- uint64_t expected_last;
-
- plan_tests(NR_TESTS);
-
- if (argc < 4) {
- plan_skip_all("Invalid arguments: need a trace path and the start and last timestamp");
-
- }
-
- /* Parse arguments (Trace, begin timestamp) */
- path = argv[1];
-
- expected_begin = strtoull(argv[2], NULL, 0);
- if (ULLONG_MAX == expected_begin && errno == ERANGE) {
- plan_skip_all("Invalid value for begin timestamp");
- }
-
- expected_last = strtoull(argv[3], NULL, 0);
- if (ULLONG_MAX == expected_last && errno == ERANGE) {
- plan_skip_all("Invalid value for last timestamp");
- }
-
- run_seek_begin(path, expected_begin);
- run_seek_time_at_last(path, expected_last);
- run_seek_last(path, expected_last);
- run_seek_cycles(path, expected_begin, expected_last);
-
- return exit_status();
-}
--- /dev/null
+/*
+ * test-bitfield.c
+ *
+ * BabelTrace - bitfield test program
+ *
+ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * 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; under version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <babeltrace/bitfield.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <tap/tap.h>
+
+unsigned int glob;
+
+/*
+ * This function is only declared to show the size of a bitfield write in
+ * objdump.
+ */
+void fct(void)
+{
+ bt_bitfield_write(&glob, unsigned int, 12, 15, 0x12345678);
+}
+
+/* Test array size, in bytes */
+#define TEST_LEN 128
+#define NR_TESTS 10
+#define SIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, signed"
+#define UNSIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, unsigned"
+#define DIAG_FMT_STR "Failed reading value written \"%s\"-wise, with start=%i" \
+ " and length=%i. Read %llX"
+
+unsigned int srcrand;
+
+#if defined(__i386) || defined(__x86_64)
+
+static inline int fls(int x)
+{
+ int r;
+ asm("bsrl %1,%0\n\t"
+ "cmovzl %2,%0"
+ : "=&r" (r) : "rm" (x), "rm" (-1));
+ return r + 1;
+}
+
+#elif defined(__PPC__)
+
+static __inline__ int fls(unsigned int x)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 32 - lz;
+}
+
+#else
+
+static int fls(unsigned int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xFFFF0000U)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xFF000000U)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xF0000000U)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xC0000000U)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000U)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+#endif
+
+#define print_byte_array(c, len) \
+do { \
+ unsigned long i; \
+ \
+ for (i = 0; i < (len); i++) { \
+ printf("0x%X", (c)[i]); \
+ if (i != (len) - 1) \
+ printf(" "); \
+ } \
+ printf("\n"); \
+} while (0)
+
+#define init_byte_array(c, len, val) \
+do { \
+ unsigned long i; \
+ \
+ for (i = 0; i < (len); i++) \
+ (c)[i] = (val); \
+} while (0)
+
+#define check_result(ref, val, buffer, typename, start, len, \
+ desc_fmt_str) \
+({ \
+ if ((val) != (ref)) { \
+ fail(desc_fmt_str, ref); \
+ diag(DIAG_FMT_STR, #typename, start, len, val); \
+ printf("# "); \
+ print_byte_array(buffer, TEST_LEN); \
+ } \
+ (val) != (ref); \
+})
+
+void run_test_unsigned(void)
+{
+ unsigned int src, nrbits;
+ union {
+ unsigned char c[TEST_LEN];
+ unsigned short s[TEST_LEN/sizeof(unsigned short)];
+ unsigned int i[TEST_LEN/sizeof(unsigned int)];
+ unsigned long l[TEST_LEN/sizeof(unsigned long)];
+ unsigned long long ll[TEST_LEN/sizeof(unsigned long long)];
+ } target;
+ unsigned long long readval;
+ unsigned int s, l;
+
+ src = srcrand;
+ nrbits = fls(src);
+
+ for (s = 0; s < CHAR_BIT * TEST_LEN; s++) {
+ for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) {
+ init_byte_array(target.c, TEST_LEN, 0xFF);
+ bt_bitfield_write(target.c, unsigned char, s, l, src);
+ bt_bitfield_read(target.c, unsigned char, s, l, &readval);
+ if (check_result(src, readval, target.c, unsigned char,
+ s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0xFF);
+ bt_bitfield_write(target.s, unsigned short, s, l, src);
+ bt_bitfield_read(target.c, unsigned char, s, l, &readval);
+ if (check_result(src, readval, target.c, unsigned short,
+ s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0xFF);
+ bt_bitfield_write(target.i, unsigned int, s, l, src);
+ bt_bitfield_read(target.c, unsigned char, s, l, &readval);
+ if (check_result(src, readval, target.c, unsigned int,
+ s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0xFF);
+ bt_bitfield_write(target.l, unsigned long, s, l, src);
+ bt_bitfield_read(target.c, unsigned char, s, l, &readval);
+ if (check_result(src, readval, target.c, unsigned long,
+ s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0xFF);
+ bt_bitfield_write(target.ll, unsigned long long, s, l, src);
+ bt_bitfield_read(target.c, unsigned char, s, l, &readval);
+ if (check_result(src, readval, target.c, unsigned long long,
+ s, l, UNSIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+ }
+ }
+
+ pass(UNSIGNED_TEST_DESC_FMT_STR, src);
+}
+
+void run_test_signed(void)
+{
+ int src, nrbits;
+ union {
+ signed char c[TEST_LEN];
+ short s[TEST_LEN/sizeof(short)];
+ int i[TEST_LEN/sizeof(int)];
+ long l[TEST_LEN/sizeof(long)];
+ long long ll[TEST_LEN/sizeof(long long)];
+ } target;
+ long long readval;
+ unsigned int s, l;
+
+ src = srcrand;
+ if (src & 0x80000000U)
+ nrbits = fls(~src) + 1; /* Find least significant bit conveying sign */
+ else
+ nrbits = fls(src) + 1; /* Keep sign at 0 */
+
+ for (s = 0; s < CHAR_BIT * TEST_LEN; s++) {
+ for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) {
+ init_byte_array(target.c, TEST_LEN, 0x0);
+ bt_bitfield_write(target.c, signed char, s, l, src);
+ bt_bitfield_read(target.c, signed char, s, l, &readval);
+ if (check_result(src, readval, target.c, signed char,
+ s, l, SIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0x0);
+ bt_bitfield_write(target.s, short, s, l, src);
+ bt_bitfield_read(target.c, signed char, s, l, &readval);
+ if (check_result(src, readval, target.c, short,
+ s, l, SIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0x0);
+ bt_bitfield_write(target.i, int, s, l, src);
+ bt_bitfield_read(target.c, signed char, s, l, &readval);
+ if (check_result(src, readval, target.c, int,
+ s, l, SIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0x0);
+ bt_bitfield_write(target.l, long, s, l, src);
+ bt_bitfield_read(target.c, signed char, s, l, &readval);
+ if (check_result(src, readval, target.c, long,
+ s, l, SIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+
+ init_byte_array(target.c, TEST_LEN, 0x0);
+ bt_bitfield_write(target.ll, long long, s, l, src);
+ bt_bitfield_read(target.c, signed char, s, l, &readval);
+ if (check_result(src, readval, target.c, long long,
+ s, l, SIGNED_TEST_DESC_FMT_STR)) {
+ return;
+ }
+ }
+ }
+
+ pass(SIGNED_TEST_DESC_FMT_STR, src);
+}
+
+void run_test(void)
+{
+ int i;
+ plan_tests(NR_TESTS * 2 + 6);
+
+ srand(time(NULL));
+
+ srcrand = 0;
+ run_test_unsigned();
+ srcrand = 0;
+ run_test_signed();
+
+ srcrand = 1;
+ run_test_unsigned();
+
+ srcrand = ~0U;
+ run_test_unsigned();
+
+ srcrand = -1;
+ run_test_signed();
+
+ srcrand = (int)0x80000000U;
+ run_test_signed();
+
+ for (i = 0; i < NR_TESTS; i++) {
+ srcrand = rand();
+ run_test_unsigned();
+ run_test_signed();
+ }
+}
+
+static
+int print_encodings(unsigned long src, unsigned int shift, unsigned int len)
+{
+ union {
+ unsigned char c[8];
+ unsigned short s[4];
+ unsigned int i[2];
+ unsigned long l[2];
+ unsigned long long ll[1];
+ } target;
+ unsigned long long readval;
+
+ init_byte_array(target.c, 8, 0xFF);
+ bt_bitfield_write(target.c, unsigned char, shift, len, src);
+ printf("bytewise\n");
+ print_byte_array(target.c, 8);
+
+ init_byte_array(target.c, 8, 0xFF);
+ bt_bitfield_write(target.s, unsigned short, shift, len, src);
+ printf("shortwise\n");
+ print_byte_array(target.c, 8);
+
+ init_byte_array(target.c, 8, 0xFF);
+ bt_bitfield_write(target.i, unsigned int, shift, len, src);
+ printf("intwise\n");
+ print_byte_array(target.c, 8);
+
+ init_byte_array(target.c, 8, 0xFF);
+ bt_bitfield_write(target.l, unsigned long, shift, len, src);
+ printf("longwise\n");
+ print_byte_array(target.c, 8);
+
+ init_byte_array(target.c, 8, 0xFF);
+ bt_bitfield_write(target.ll, unsigned long long, shift, len, src);
+ printf("lluwise\n");
+ print_byte_array(target.c, 8);
+
+ bt_bitfield_read(target.c, unsigned char, shift, len, &readval);
+ printf("read: %llX\n", readval);
+ print_byte_array(target.c, 8);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1) {
+ /* Print encodings */
+ unsigned long src;
+ unsigned int shift, len;
+
+ src = atoi(argv[1]);
+ if (argc > 2)
+ shift = atoi(argv[2]);
+ else
+ shift = 12;
+ if (argc > 3)
+ len = atoi(argv[3]);
+ else
+ len = 40;
+ return print_encodings(src, shift, len);
+ }
+
+ /* Run tap-formated tests */
+ run_test();
+ return exit_status();
+}
--- /dev/null
+/*
+ * test-seeks.c
+ *
+ * Lib BabelTrace - Seeks test program
+ *
+ * Copyright 2012 - Yannick Brosseau <yannick.brosseau@gmail.com>
+ *
+ * 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; under version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#define _GNU_SOURCE
+#include <babeltrace/context.h>
+#include <babeltrace/iterator.h>
+#include <babeltrace/ctf/iterator.h>
+#include <babeltrace/ctf/events.h>
+#include <babeltrace/babeltrace-internal.h> /* For symbol side-effects */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <tap/tap.h>
+#include "common.h"
+
+#define NR_TESTS 29
+
+void run_seek_begin(char *path, uint64_t expected_begin)
+{
+ struct bt_context *ctx;
+ struct bt_ctf_iter *iter;
+ struct bt_ctf_event *event;
+ struct bt_iter_pos newpos;
+ int ret;
+ uint64_t timestamp_begin;
+ uint64_t timestamp_seek_begin;
+
+ /* Open the trace */
+ ctx = create_context_with_path(path);
+ if (!ctx) {
+ plan_skip_all("Cannot create valid context");
+ }
+
+ /* Create iterator with null begin and end */
+ iter = bt_ctf_iter_create(ctx, NULL, NULL);
+ if (!iter) {
+ plan_skip_all("Cannot create valid iterator");
+ }
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid");
+
+ /* Validate that the first timestamp is right */
+ timestamp_begin = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp_begin == expected_begin);
+
+ /* Validate that we get the same value after a seek begin */
+ newpos.type = BT_SEEK_BEGIN;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek begin retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid");
+
+ timestamp_seek_begin = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp_begin == timestamp_seek_begin);
+
+ bt_context_put(ctx);
+}
+
+
+void run_seek_last(char *path, uint64_t expected_last)
+{
+ struct bt_context *ctx;
+ struct bt_ctf_iter *iter;
+ struct bt_ctf_event *event;
+ struct bt_iter_pos newpos;
+ int ret;
+ uint64_t timestamp_last;
+
+ /* Open the trace */
+ ctx = create_context_with_path(path);
+ if (!ctx) {
+ plan_skip_all("Cannot create valid context");
+ }
+
+ /* Create iterator with null last and end */
+ iter = bt_ctf_iter_create(ctx, NULL, NULL);
+ if (!iter) {
+ plan_skip_all("Cannot create valid iterator");
+ }
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at beginning");
+
+ /* Seek to last */
+ newpos.type = BT_SEEK_LAST;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek last retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at last position");
+
+ timestamp_last = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp_last == expected_last);
+
+ /* Try to read next event */
+ ret = bt_iter_next(bt_ctf_get_iter(iter));
+
+ ok(ret == 0, "iter next should return an error");
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event == 0, "Event after last should be invalid");
+
+ bt_context_put(ctx);
+}
+
+void run_seek_time_at_last(char *path, uint64_t expected_last)
+{
+ struct bt_context *ctx;
+ struct bt_ctf_iter *iter;
+ struct bt_ctf_event *event;
+ struct bt_iter_pos newpos;
+ int ret;
+ uint64_t timestamp_last;
+
+ /* Open the trace */
+ ctx = create_context_with_path(path);
+ if (!ctx) {
+ plan_skip_all("Cannot create valid context");
+ }
+
+ /* Create iterator with null last and end */
+ iter = bt_ctf_iter_create(ctx, NULL, NULL);
+ if (!iter) {
+ plan_skip_all("Cannot create valid iterator");
+ }
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at beginning");
+
+ /* Seek to last */
+ newpos.type = BT_SEEK_TIME;
+ newpos.u.seek_time = expected_last;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek time at last retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at last position");
+
+ timestamp_last = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp_last == expected_last);
+
+ /* Try to read next event */
+ ret = bt_iter_next(bt_ctf_get_iter(iter));
+
+ ok(ret == 0, "iter next should return an error");
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event == 0, "Event after last should be invalid");
+
+ bt_context_put(ctx);
+}
+
+void run_seek_cycles(char *path,
+ uint64_t expected_begin,
+ uint64_t expected_last)
+{
+ struct bt_context *ctx;
+ struct bt_ctf_iter *iter;
+ struct bt_ctf_event *event;
+ struct bt_iter_pos newpos;
+ int ret;
+ uint64_t timestamp;
+
+ /* Open the trace */
+ ctx = create_context_with_path(path);
+ if (!ctx) {
+ plan_skip_all("Cannot create valid context");
+ }
+
+ /* Create iterator with null last and end */
+ iter = bt_ctf_iter_create(ctx, NULL, NULL);
+ if (!iter) {
+ plan_skip_all("Cannot create valid iterator");
+ }
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at beginning");
+
+ /* Seek to last */
+ newpos.type = BT_SEEK_LAST;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek last retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at last position");
+
+ timestamp = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp == expected_last);
+
+ /* Try to read next event */
+ ret = bt_iter_next(bt_ctf_get_iter(iter));
+
+ ok(ret == 0, "iter next should return an error");
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event == 0, "Event after last should be invalid");
+
+ /* Seek to BEGIN */
+ newpos.type = BT_SEEK_BEGIN;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek begin retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at first position");
+
+ timestamp = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp == expected_begin);
+
+ /* Seek last again */
+ newpos.type = BT_SEEK_LAST;
+ ret = bt_iter_set_pos(bt_ctf_get_iter(iter), &newpos);
+
+ ok(ret == 0, "Seek last retval %d", ret);
+
+ event = bt_ctf_iter_read_event(iter);
+
+ ok(event, "Event valid at last position");
+
+ timestamp = bt_ctf_get_timestamp(event);
+
+ ok1(timestamp == expected_last);
+
+ bt_context_put(ctx);
+}
+
+int main(int argc, char **argv)
+{
+ char *path;
+ uint64_t expected_begin;
+ uint64_t expected_last;
+
+ /*
+ * Side-effects ensuring libs are not optimized away by static
+ * linking.
+ */
+ babeltrace_debug = 0; /* libbabeltrace.la */
+ opt_clock_offset = 0; /* libbabeltrace-ctf.la */
+
+ plan_tests(NR_TESTS);
+
+ if (argc < 4) {
+ plan_skip_all("Invalid arguments: need a trace path and the start and last timestamp");
+
+ }
+
+ /* Parse arguments (Trace, begin timestamp) */
+ path = argv[1];
+
+ expected_begin = strtoull(argv[2], NULL, 0);
+ if (ULLONG_MAX == expected_begin && errno == ERANGE) {
+ plan_skip_all("Invalid value for begin timestamp");
+ }
+
+ expected_last = strtoull(argv[3], NULL, 0);
+ if (ULLONG_MAX == expected_last && errno == ERANGE) {
+ plan_skip_all("Invalid value for last timestamp");
+ }
+
+ run_seek_begin(path, expected_begin);
+ run_seek_time_at_last(path, expected_last);
+ run_seek_last(path, expected_last);
+ run_seek_cycles(path, expected_begin, expected_last);
+
+ return exit_status();
+}
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2013 - Christian Babeux <christian.babeux@efficios.com>
+#
+# 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; only version 2
+# of the License.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+CURDIR=$(dirname $0)/
+TESTDIR=$CURDIR/../
+CTF_TRACES=$TESTDIR/ctf-traces
+
+$CURDIR/test_seek $CTF_TRACES/succeed/lttng-modules-2.0-pre5/ 61334174524234 61336381998396
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2013 - Christian Babeux <christian.babeux@efficios.com>
+#
+# 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; only version 2
+# of the License.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+CURDIR=$(dirname $0)/
+TESTDIR=$CURDIR/../
+CTF_TRACES=$TESTDIR/ctf-traces
+
+$CURDIR/test_seek $CTF_TRACES/succeed/wk-heartbeat-u/ 1351532897586558519 1351532897591331194
--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) 2013 - Christian Babeux <christian.babeux@efficios.com>
+#
+# 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; only version 2
+# of the License.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+[ -z "$1" ] && echo "Error: No testlist. Please specify a testlist to run." && exit 1
+
+prove --merge --exec '' - < $1
+++ /dev/null
-#!/bin/bash
-
-TESTDIR=$(dirname $0)
-DIR=$(readlink -f ${TESTDIR})
-BABELTRACE_BIN=${DIR}/../converter/babeltrace
-CTF_TRACES=${DIR}/ctf-traces
-
-function test_check_success ()
-{
- if [ $? -ne 0 ] ; then
- return 1
- else
- return 0
- fi
-}
-
-function test_check_fail ()
-{
- if [ $? -eq 0 ] ; then
- return 1
- else
- return 0
- fi
-}
-
-function run_babeltrace ()
-{
- ${BABELTRACE_BIN} $* > /dev/null 2>&1
- return $?
-}
-
-function print_test_result ()
-{
- if [ $# -ne 3 ] ; then
- echo "Invalid arguments provided"
- exit 1
- fi
-
- if [ ${2} -eq 0 ] ; then
- echo -n "ok"
- else
- echo -n "not ok"
- fi
- echo -e " "${1}" - "${3}
-}
-
-successTraces=(${CTF_TRACES}/succeed/*)
-failTraces=(${CTF_TRACES}/fail/*)
-testCount=$((2 + ${#successTraces[@]} + ${#failTraces[@]}))
-
-currentTestIndex=1
-echo -e 1..${testCount}
-
-#run babeltrace, expects success
-run_babeltrace
-test_check_success
-print_test_result $((currentTestIndex++)) $? "Running babeltrace without arguments"
-
-#run babeltrace with a bogus argument, expects failure
-run_babeltrace --bogusarg
-test_check_fail
-print_test_result $((currentTestIndex++)) $? "Running babeltrace with a bogus argument"
-
-for tracePath in ${successTraces[@]}; do
- run_babeltrace ${tracePath}
- test_check_success
- print_test_result $((currentTestIndex++)) $? "Running babeltrace with trace ${tracePath}"
-done
-
-for tracePath in ${failTraces[@]}; do
- run_babeltrace ${tracePath}
- test_check_fail
- print_test_result $((currentTestIndex++)) $? "Running babeltrace with trace ${tracePath}"
-done
-
-exit 0
--- /dev/null
+bin/test_trace_read
+lib/test_bitfield
+lib/test_seek_empty_packet
+lib/test_seek_big_trace
\ No newline at end of file
--- /dev/null
+SUBDIRS = tap
--- /dev/null
+noinst_LTLIBRARIES = libtap.la
+libtap_la_SOURCES = tap.c tap.h
+
+SCRIPT_LIST = tap.sh
+
+dist_noinst_SCRIPTS = $(SCRIPT_LIST)
+
+all-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ cp -f $(srcdir)/$$script $(builddir); \
+ done; \
+ fi
+
+clean-local:
+ @if [ x"$(srcdir)" != x"$(builddir)" ]; then \
+ for script in $(SCRIPT_LIST); do \
+ rm -f $(builddir)/$$script; \
+ done; \
+ fi
--- /dev/null
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+static int no_plan = 0;
+static int skip_all = 0;
+static int have_plan = 0;
+static unsigned int test_count = 0; /* Number of tests that have been run */
+static unsigned int e_tests = 0; /* Expected number of tests to run */
+static unsigned int failures = 0; /* Number of tests that failed */
+static char *todo_msg = NULL;
+static char *todo_msg_fixed = "libtap malloc issue";
+static int todo = 0;
+static int test_died = 0;
+
+/* Encapsulate the pthread code in a conditional. In the absence of
+ libpthread the code does nothing */
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK pthread_mutex_lock(&M);
+# define UNLOCK pthread_mutex_unlock(&M);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static void _expected_tests(unsigned int);
+static void _tap_init(void);
+static void _cleanup(void);
+
+/*
+ * Generate a test result.
+ *
+ * ok -- boolean, indicates whether or not the test passed.
+ * test_name -- the name of the test, may be NULL
+ * test_comment -- a comment to print afterwards, may be NULL
+ */
+unsigned int
+_gen_result(int ok, const char *func, char *file, unsigned int line,
+ char *test_name, ...)
+{
+ va_list ap;
+ char *local_test_name = NULL;
+ char *c;
+ int name_is_digits;
+
+ LOCK;
+
+ test_count++;
+
+ /* Start by taking the test name and performing any printf()
+ expansions on it */
+ if(test_name != NULL) {
+ va_start(ap, test_name);
+ if (vasprintf(&local_test_name, test_name, ap) == -1) {
+ local_test_name = NULL;
+ }
+ va_end(ap);
+
+ /* Make sure the test name contains more than digits
+ and spaces. Emit an error message and exit if it
+ does */
+ if(local_test_name) {
+ name_is_digits = 1;
+ for(c = local_test_name; *c != '\0'; c++) {
+ if(!isdigit(*c) && !isspace(*c)) {
+ name_is_digits = 0;
+ break;
+ }
+ }
+
+ if(name_is_digits) {
+ diag(" You named your test '%s'. You shouldn't use numbers for your test names.", local_test_name);
+ diag(" Very confusing.");
+ }
+ }
+ }
+
+ if(!ok) {
+ printf("not ");
+ failures++;
+ }
+
+ printf("ok %d", test_count);
+
+ if(test_name != NULL) {
+ printf(" - ");
+
+ /* Print the test name, escaping any '#' characters it
+ might contain */
+ if(local_test_name != NULL) {
+ flockfile(stdout);
+ for(c = local_test_name; *c != '\0'; c++) {
+ if(*c == '#')
+ fputc('\\', stdout);
+ fputc((int)*c, stdout);
+ }
+ funlockfile(stdout);
+ } else { /* vasprintf() failed, use a fixed message */
+ printf("%s", todo_msg_fixed);
+ }
+ }
+
+ /* If we're in a todo_start() block then flag the test as being
+ TODO. todo_msg should contain the message to print at this
+ point. If it's NULL then asprintf() failed, and we should
+ use the fixed message.
+
+ This is not counted as a failure, so decrement the counter if
+ the test failed. */
+ if(todo) {
+ printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
+ if(!ok)
+ failures--;
+ }
+
+ printf("\n");
+
+ if(!ok) {
+ if(getenv("HARNESS_ACTIVE") != NULL)
+ fputs("\n", stderr);
+
+ diag(" Failed %stest (%s:%s() at line %d)",
+ todo ? "(TODO) " : "", file, func, line);
+ }
+ free(local_test_name);
+
+ UNLOCK;
+
+ /* We only care (when testing) that ok is positive, but here we
+ specifically only want to return 1 or 0 */
+ return ok ? 1 : 0;
+}
+
+/*
+ * Initialise the TAP library. Will only do so once, however many times it's
+ * called.
+ */
+void
+_tap_init(void)
+{
+ static int run_once = 0;
+
+ if(!run_once) {
+ atexit(_cleanup);
+
+ /* stdout needs to be unbuffered so that the output appears
+ in the same place relative to stderr output as it does
+ with Test::Harness */
+ setbuf(stdout, 0);
+ run_once = 1;
+ }
+}
+
+/*
+ * Note that there's no plan.
+ */
+int
+plan_no_plan(void)
+{
+
+ LOCK;
+
+ _tap_init();
+
+ if(have_plan != 0) {
+ fprintf(stderr, "You tried to plan twice!\n");
+ test_died = 1;
+ UNLOCK;
+ exit(255);
+ }
+
+ have_plan = 1;
+ no_plan = 1;
+
+ UNLOCK;
+
+ return 1;
+}
+
+/*
+ * Note that the plan is to skip all tests
+ */
+int
+plan_skip_all(char *reason)
+{
+
+ LOCK;
+
+ _tap_init();
+
+ skip_all = 1;
+
+ printf("1..0");
+
+ if(reason != NULL)
+ printf(" # Skip %s", reason);
+
+ printf("\n");
+
+ UNLOCK;
+
+ exit(0);
+}
+
+/*
+ * Note the number of tests that will be run.
+ */
+int
+plan_tests(unsigned int tests)
+{
+
+ LOCK;
+
+ _tap_init();
+
+ if(have_plan != 0) {
+ fprintf(stderr, "You tried to plan twice!\n");
+ test_died = 1;
+ UNLOCK;
+ exit(255);
+ }
+
+ if(tests == 0) {
+ fprintf(stderr, "You said to run 0 tests! You've got to run something.\n");
+ test_died = 1;
+ UNLOCK;
+ exit(255);
+ }
+
+ have_plan = 1;
+
+ _expected_tests(tests);
+
+ UNLOCK;
+
+ return e_tests;
+}
+
+unsigned int
+diag(char *fmt, ...)
+{
+ va_list ap;
+
+ fputs("# ", stderr);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fputs("\n", stderr);
+
+ return 0;
+}
+
+void
+_expected_tests(unsigned int tests)
+{
+
+ printf("1..%d\n", tests);
+ e_tests = tests;
+}
+
+int
+skip(unsigned int n, char *fmt, ...)
+{
+ va_list ap;
+ char *skip_msg = NULL;
+
+ LOCK;
+
+ va_start(ap, fmt);
+ if (asprintf(&skip_msg, fmt, ap) == -1) {
+ skip_msg = NULL;
+ }
+ va_end(ap);
+
+ while(n-- > 0) {
+ test_count++;
+ printf("ok %d # skip %s\n", test_count,
+ skip_msg != NULL ?
+ skip_msg : "libtap():malloc() failed");
+ }
+
+ free(skip_msg);
+
+ UNLOCK;
+
+ return 1;
+}
+
+void
+todo_start(char *fmt, ...)
+{
+ va_list ap;
+
+ LOCK;
+
+ va_start(ap, fmt);
+ if (vasprintf(&todo_msg, fmt, ap) == -1) {
+ todo_msg = NULL;
+ }
+ va_end(ap);
+
+ todo = 1;
+
+ UNLOCK;
+}
+
+void
+todo_end(void)
+{
+
+ LOCK;
+
+ todo = 0;
+ free(todo_msg);
+
+ UNLOCK;
+}
+
+int
+exit_status(void)
+{
+ int r;
+
+ LOCK;
+
+ /* If there's no plan, just return the number of failures */
+ if(no_plan || !have_plan) {
+ UNLOCK;
+ return failures;
+ }
+
+ /* Ran too many tests? Return the number of tests that were run
+ that shouldn't have been */
+ if(e_tests < test_count) {
+ r = test_count - e_tests;
+ UNLOCK;
+ return r;
+ }
+
+ /* Return the number of tests that failed + the number of tests
+ that weren't run */
+ r = failures + e_tests - test_count;
+ UNLOCK;
+
+ return r;
+}
+
+/*
+ * Cleanup at the end of the run, produce any final output that might be
+ * required.
+ */
+void
+_cleanup(void)
+{
+
+ LOCK;
+
+ /* If plan_no_plan() wasn't called, and we don't have a plan,
+ and we're not skipping everything, then something happened
+ before we could produce any output */
+ if(!no_plan && !have_plan && !skip_all) {
+ diag("Looks like your test died before it could output anything.");
+ UNLOCK;
+ return;
+ }
+
+ if(test_died) {
+ diag("Looks like your test died just after %d.", test_count);
+ UNLOCK;
+ return;
+ }
+
+
+ /* No plan provided, but now we know how many tests were run, and can
+ print the header at the end */
+ if(!skip_all && (no_plan || !have_plan)) {
+ printf("1..%d\n", test_count);
+ }
+
+ if((have_plan && !no_plan) && e_tests < test_count) {
+ diag("Looks like you planned %d %s but ran %d extra.",
+ e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
+ UNLOCK;
+ return;
+ }
+
+ if((have_plan || !no_plan) && e_tests > test_count) {
+ diag("Looks like you planned %d %s but only ran %d.",
+ e_tests, e_tests == 1 ? "test" : "tests", test_count);
+ UNLOCK;
+ return;
+ }
+
+ if(failures)
+ diag("Looks like you failed %d %s of %d.",
+ failures, failures == 1 ? "test" : "tests", test_count);
+
+ UNLOCK;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
+ and requires the caller to add the final comma if they've ommitted
+ the optional arguments */
+#ifdef __GNUC__
+# define ok(e, test, ...) ((e) ? \
+ _gen_result(1, __func__, __FILE__, __LINE__, \
+ test, ## __VA_ARGS__) : \
+ _gen_result(0, __func__, __FILE__, __LINE__, \
+ test, ## __VA_ARGS__))
+
+# define ok1(e) ((e) ? \
+ _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+ _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
+# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
+
+# define skip_start(test, n, fmt, ...) \
+ do { \
+ if((test)) { \
+ skip(n, fmt, ## __VA_ARGS__); \
+ continue; \
+ }
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+# define ok(e, ...) ((e) ? \
+ _gen_result(1, __func__, __FILE__, __LINE__, \
+ __VA_ARGS__) : \
+ _gen_result(0, __func__, __FILE__, __LINE__, \
+ __VA_ARGS__))
+
+# define ok1(e) ((e) ? \
+ _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+ _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(...) ok(1, __VA_ARGS__);
+# define fail(...) ok(0, __VA_ARGS__);
+
+# define skip_start(test, n, ...) \
+ do { \
+ if((test)) { \
+ skip(n, __VA_ARGS__); \
+ continue; \
+ }
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
+
+#define skip_end() } while(0);
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
+
+int plan_no_plan(void);
+int plan_skip_all(char *);
+int plan_tests(unsigned int);
+
+unsigned int diag(char *, ...);
+
+int skip(unsigned int, char *, ...);
+
+void todo_start(char *, ...);
+void todo_end(void);
+
+int exit_status(void);
--- /dev/null
+#!/bin/bash
+#
+# Copyright 2010 Patrick LeBoutillier <patrick.leboutillier@gmail.com>
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU 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 <http://www.gnu.org/licenses/>.
+
+
+_version='1.01'
+
+_plan_set=0
+_no_plan=0
+_skip_all=0
+_test_died=0
+_expected_tests=0
+_executed_tests=0
+_failed_tests=0
+TODO=
+
+
+usage(){
+ cat <<'USAGE'
+tap-functions: A TAP-producing BASH library
+
+PLAN:
+ plan_no_plan
+ plan_skip_all [REASON]
+ plan_tests NB_TESTS
+
+TEST:
+ ok RESULT [NAME]
+ okx COMMAND
+ is RESULT EXPECTED [NAME]
+ isnt RESULT EXPECTED [NAME]
+ like RESULT PATTERN [NAME]
+ unlike RESULT PATTERN [NAME]
+ pass [NAME]
+ fail [NAME]
+
+SKIP:
+ skip [CONDITION] [REASON] [NB_TESTS=1]
+
+ skip $feature_not_present "feature not present" 2 || {
+ is $a "a"
+ is $b "b"
+ }
+
+TODO:
+ Specify TODO mode by setting $TODO:
+ TODO="not implemented yet"
+ ok $result "some not implemented test"
+ unset TODO
+
+OTHER:
+ diag MSG
+
+EXAMPLE:
+ #!/bin/bash
+
+ . tap-functions
+
+ plan_tests 7
+
+ me=$USER
+ is $USER $me "I am myself"
+ like $HOME $me "My home is mine"
+ like "`id`" $me "My id matches myself"
+
+ /bin/ls $HOME 1>&2
+ ok $? "/bin/ls $HOME"
+ # Same thing using okx shortcut
+ okx /bin/ls $HOME
+
+ [[ "`id -u`" != "0" ]]
+ i_am_not_root=$?
+ skip $i_am_not_root "Must be root" || {
+ okx ls /root
+ }
+
+ TODO="figure out how to become root..."
+ okx [ "$HOME" == "/root" ]
+ unset TODO
+USAGE
+ exit
+}
+
+opt=
+set_u=
+while getopts ":sx" opt ; do
+ case $_opt in
+ u) set_u=1 ;;
+ *) usage ;;
+ esac
+done
+shift $(( OPTIND - 1 ))
+# Don't allow uninitialized variables if requested
+[[ -n "$set_u" ]] && set -u
+unset opt set_u
+
+# Used to call _cleanup on shell exit
+trap _exit EXIT
+
+
+plan_no_plan(){
+ (( _plan_set != 0 )) && "You tried to plan twice!"
+
+ _plan_set=1
+ _no_plan=1
+
+ return 0
+}
+
+
+plan_skip_all(){
+ local reason=${1:-''}
+
+ (( _plan_set != 0 )) && _die "You tried to plan twice!"
+
+ _print_plan 0 "Skip $reason"
+
+ _skip_all=1
+ _plan_set=1
+ _exit 0
+
+ return 0
+}
+
+plan_tests(){
+ local tests=${1:?}
+
+ (( _plan_set != 0 )) && _die "You tried to plan twice!"
+ (( tests == 0 )) && _die "You said to run 0 tests! You've got to run something."
+
+ _print_plan $tests
+ _expected_tests=$tests
+ _plan_set=1
+
+ return $tests
+}
+
+
+_print_plan(){
+ local tests=${1:?}
+ local directive=${2:-''}
+
+ echo -n "1..$tests"
+ [[ -n "$directive" ]] && echo -n " # $directive"
+ echo
+}
+
+
+pass(){
+ local name=$1
+ ok 0 "$name"
+}
+
+
+fail(){
+ local name=$1
+ ok 1 "$name"
+}
+
+# This is the workhorse method that actually
+# prints the tests result.
+ok(){
+ local result=${1:?}
+ local name=${2:-''}
+
+ (( _plan_set == 0 )) && _die "You tried to run a test without a plan! Gotta have a plan."
+
+ _executed_tests=$(( $_executed_tests + 1 ))
+
+ if [[ -n "$name" ]] ; then
+ if _matches "$name" "^[0-9]+$" ; then
+ diag " You named your test '$name'. You shouldn't use numbers for your test names."
+ diag " Very confusing."
+ fi
+ fi
+
+ if (( result != 0 )) ; then
+ echo -n "not "
+ _failed_tests=$(( _failed_tests + 1 ))
+ fi
+ echo -n "ok $_executed_tests"
+
+ if [[ -n "$name" ]] ; then
+ local ename=${name//\#/\\#}
+ echo -n " - $ename"
+ fi
+
+ if [[ -n "$TODO" ]] ; then
+ echo -n " # TODO $TODO" ;
+ if (( result != 0 )) ; then
+ _failed_tests=$(( _failed_tests - 1 ))
+ fi
+ fi
+
+ echo
+ if (( result != 0 )) ; then
+ local file='tap-functions'
+ local func=
+ local line=
+
+ local i=0
+ local bt=$(caller $i)
+ while _matches "$bt" "tap-functions$" ; do
+ i=$(( $i + 1 ))
+ bt=$(caller $i)
+ done
+ local backtrace=
+ eval $(caller $i | (read line func file ; echo "backtrace=\"$file:$func() at line $line.\""))
+
+ local t=
+ [[ -n "$TODO" ]] && t="(TODO) "
+
+ if [[ -n "$name" ]] ; then
+ diag " Failed ${t}test '$name'"
+ diag " in $backtrace"
+ else
+ diag " Failed ${t}test in $backtrace"
+ fi
+ fi
+
+ return $result
+}
+
+
+okx(){
+ local command="$@"
+
+ local line=
+ diag "Output of '$command':"
+ "$@" | while read line ; do
+ diag "$line"
+ done
+ ok ${PIPESTATUS[0]} "$command"
+}
+
+
+_equals(){
+ local result=${1:?}
+ local expected=${2:?}
+
+ if [[ "$result" == "$expected" ]] ; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+
+# Thanks to Aaron Kangas for the patch to allow regexp matching
+# under bash < 3.
+ _bash_major_version=${BASH_VERSION%%.*}
+_matches(){
+ local result=${1:?}
+ local pattern=${2:?}
+
+ if [[ -z "$result" || -z "$pattern" ]] ; then
+ return 1
+ else
+ if (( _bash_major_version >= 3 )) ; then
+ [[ "$result" =~ "$pattern" ]]
+ else
+ echo "$result" | egrep -q "$pattern"
+ fi
+ fi
+}
+
+
+_is_diag(){
+ local result=${1:?}
+ local expected=${2:?}
+
+ diag " got: '$result'"
+ diag " expected: '$expected'"
+}
+
+
+is(){
+ local result=${1:?}
+ local expected=${2:?}
+ local name=${3:-''}
+
+ _equals "$result" "$expected"
+ (( $? == 0 ))
+ ok $? "$name"
+ local r=$?
+ (( r != 0 )) && _is_diag "$result" "$expected"
+ return $r
+}
+
+
+isnt(){
+ local result=${1:?}
+ local expected=${2:?}
+ local name=${3:-''}
+
+ _equals "$result" "$expected"
+ (( $? != 0 ))
+ ok $? "$name"
+ local r=$?
+ (( r != 0 )) && _is_diag "$result" "$expected"
+ return $r
+}
+
+
+like(){
+ local result=${1:?}
+ local pattern=${2:?}
+ local name=${3:-''}
+
+ _matches "$result" "$pattern"
+ (( $? == 0 ))
+ ok $? "$name"
+ local r=$?
+ (( r != 0 )) && diag " '$result' doesn't match '$pattern'"
+ return $r
+}
+
+
+unlike(){
+ local result=${1:?}
+ local pattern=${2:?}
+ local name=${3:-''}
+
+ _matches "$result" "$pattern"
+ (( $? != 0 ))
+ ok $? "$name"
+ local r=$?
+ (( r != 0 )) && diag " '$result' matches '$pattern'"
+ return $r
+}
+
+
+skip(){
+ local condition=${1:?}
+ local reason=${2:-''}
+ local n=${3:-1}
+
+ if (( condition == 0 )) ; then
+ local i=
+ for (( i=0 ; i<$n ; i++ )) ; do
+ _executed_tests=$(( _executed_tests + 1 ))
+ echo "ok $_executed_tests # skip: $reason"
+ done
+ return 0
+ else
+ return
+ fi
+}
+
+
+diag(){
+ local msg=${1:?}
+
+ if [[ -n "$msg" ]] ; then
+ echo "# $msg"
+ fi
+
+ return 1
+}
+
+
+_die(){
+ local reason=${1:-'<unspecified error>'}
+
+ echo "$reason" >&2
+ _test_died=1
+ _exit 255
+}
+
+
+BAIL_OUT(){
+ local reason=${1:-''}
+
+ echo "Bail out! $reason" >&2
+ _exit 255
+}
+
+
+_cleanup(){
+ local rc=0
+
+ if (( _plan_set == 0 )) ; then
+ diag "Looks like your test died before it could output anything."
+ return $rc
+ fi
+
+ if (( _test_died != 0 )) ; then
+ diag "Looks like your test died just after $_executed_tests."
+ return $rc
+ fi
+
+ if (( _skip_all == 0 && _no_plan != 0 )) ; then
+ _print_plan $_executed_tests
+ fi
+
+ local s=
+ if (( _no_plan == 0 && _expected_tests < _executed_tests )) ; then
+ s= ; (( _expected_tests > 1 )) && s=s
+ local extra=$(( _executed_tests - _expected_tests ))
+ diag "Looks like you planned $_expected_tests test$s but ran $extra extra."
+ rc=1 ;
+ fi
+
+ if (( _no_plan == 0 && _expected_tests > _executed_tests )) ; then
+ s= ; (( _expected_tests > 1 )) && s=s
+ diag "Looks like you planned $_expected_tests test$s but only ran $_executed_tests."
+ fi
+
+ if (( _failed_tests > 0 )) ; then
+ s= ; (( _failed_tests > 1 )) && s=s
+ diag "Looks like you failed $_failed_tests test$s of $_executed_tests."
+ fi
+
+ return $rc
+}
+
+
+_exit_status(){
+ if (( _no_plan != 0 || _plan_set == 0 )) ; then
+ return $_failed_tests
+ fi
+
+ if (( _expected_tests < _executed_tests )) ; then
+ return $(( _executed_tests - _expected_tests ))
+ fi
+
+ return $(( _failed_tests + ( _expected_tests - _executed_tests )))
+}
+
+
+_exit(){
+ local rc=${1:-''}
+ if [[ -z "$rc" ]] ; then
+ _exit_status
+ rc=$?
+ fi
+
+ _cleanup
+ local alt_rc=$?
+ (( alt_rc != 0 )) && rc=$alt_rc
+ trap - EXIT
+ exit $rc
+}