src_test_libdbuspolicy1_method_LDADD = $(CYNARA_LIBS) \
src/libinternal.a
+if ENABLE_STANDALONE_TESTS
+bin_PROGRAMS = test_runner
+test_runner_SOURCES = src/test_runner.c
+
+alonetestdir = ${bindir}/tests/
+alonetest_PROGRAMS = dbus_daemon stest_ownership stest_method_call stest_signal stest_cynara
+
+dbus_daemon_SOURCES = src/dbus_daemon.c
+stest_ownership_SOURCES = src/stest_ownership.c src/stest_common.c
+stest_method_call_SOURCES = src/stest_method_call.c src/stest_common.c
+stest_signal_SOURCES = src/stest_signal.c src/stest_common.c
+stest_cynara_SOURCES = src/stest_cynara.c src/stest_common.c
+
+stest_ownership_LDADD = src/libdbuspolicy1.la
+stest_method_call_LDADD = src/libdbuspolicy1.la
+stest_signal_LDADD = src/libdbuspolicy1.la
+stest_cynara_LDADD = src/libdbuspolicy1.la
+endif
+
if ENABLE_DOXYGEN
CLEANFILES += documentation
AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests], [Add API function that allows to change credentials during execution]),
[with_tests=yes],
with_tests=no)
+AM_CONDITIONAL([ENABLE_STANDALONE_TESTS], [test x$with_tests = xyes])
if test "x$with_tests" = "xyes"; then
AC_DEFINE(LIBDBUSPOLICY_TESTS_API, 1, [Define if tests are enabled])
fi
--- /dev/null
+Name: libdbuspolicy-tests
+Summary: Helper library
+License: Apache-2.0
+Group: Base/IPC
+Version: 1.0.0
+Release: 0
+Source: %{name}-%{version}.tar.gz
+BuildRequires: boost-devel
+BuildRequires: pkgconfig(cynara-client)
+
+
+%description
+This package contains contains integration tests for libdbuspolicy.
+
+%prep
+%setup -q
+
+%build
+
+%reconfigure --libdir=%{_libdir} --prefix=/usr --enable-tests
+
+make
+make check
+
+%install
+make DESTDIR=%{buildroot} install
+rm %{buildroot}%{_libdir}/libdbuspolicy1.la
+rm %{buildroot}%{_includedir}/dbuspolicy/libdbuspolicy1.h
+rm %{buildroot}%{_libdir}/pkgconfig/libdbuspolicy1.pc
+rm %{buildroot}%{_libdir}/libdbuspolicy1.so
+
+mkdir -p %{buildroot}%{_libdir}/dbus-tests/lib/%{name}
+mv %{buildroot}%{_libdir}/libdbuspolicy1.so.* %{buildroot}%{_libdir}/dbus-tests/lib/%{name}
+
+mkdir -p %{buildroot}%{_libdir}/dbus-tests/runner
+mv %{buildroot}%{_bindir}/test_runner %{buildroot}%{_libdir}/dbus-tests/runner/%{name}
+
+mkdir -p %{buildroot}%{_libdir}/dbus-tests/test-suites/%{name}
+mv %{buildroot}%{_bindir}/tests/* %{buildroot}%{_libdir}/dbus-tests/test-suites/%{name}/
+
+mkdir -p %{buildroot}%{_libdir}/dbus-tests/configs/%{name}
+install -m 0644 tests/system.conf %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/
+
+mkdir -p %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/system.d/
+install -m 0644 tests/system.d/ownerships.test.conf %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/system.d/
+install -m 0644 tests/system.d/signals.test.conf %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/system.d/
+install -m 0644 tests/system.d/methods.test.conf %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/system.d/
+install -m 0644 tests/system.d/cynara.test.conf %{buildroot}%{_libdir}/dbus-tests/configs/%{name}/system.d/
+install -m 0654 src/cynara_prepare.sh %{buildroot}%{_libdir}/dbus-tests/test-suites/%{name}/
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root)
+%{_libdir}/dbus-tests/lib/%{name}/libdbuspolicy1.so.*
+%{_libdir}/dbus-tests/runner/%{name}
+%{_libdir}/dbus-tests/test-suites/%{name}/*
+%{_libdir}/dbus-tests/configs/%{name}/*
--- /dev/null
+#!/bin/sh
+if [ -z "${1}" ]; then
+ cyad -e "MANIFESTS" -u 200 -c L -p t -r y
+ cyad -e "USER_TYPE_ADMIN" -u 200 -c L -p t -r y
+else
+ cyad -s -k "MANIFESTS" -u 200 -c L -p t -t $1
+ cyad -s -k "USER_TYPE_ADMIN" -u 200 -c L -p t -t $1
+fi
--- /dev/null
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include "kdbus.h"
+
+#define KDBUS_SYSTEM_BUS_PATH "/sys/fs/kdbus/0-system/bus"
+
+#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
+#define KDBUS_ITEM_NEXT(item) \
+ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
+#define KDBUS_FOREACH(iter, first, _size) \
+ for (iter = (first); \
+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \
+ iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
+
+#define POOL_SIZE (16 * 1024 * 1024)
+
+#define err_r(_r, _msg) fprintf(stderr, "log: %d, %s, %s, %d, %s\n",(_r), (_msg), __func__, __LINE__, __FILE__)
+#define err(_msg) err_r(errno, (_msg))
+
+static uint8_t* pool;
+static char* server_names[16];
+int ready_fd = 0;
+
+static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd)
+{
+ int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd);
+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
+}
+
+static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd)
+{
+ int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd);
+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
+}
+
+static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd)
+{
+ int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
+ return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
+}
+
+static void bus_poool_free_slice(int fd, uint64_t offset)
+{
+ struct kdbus_cmd_free cmd = {
+ .size = sizeof(cmd),
+ .offset = offset,
+ };
+ int r;
+ r = kdbus_cmd_free(fd, &cmd);
+ if (r < 0)
+ err_r(r, "cannot free pool slice");
+}
+
+static int bus_open_connection(const char *name,
+ uint64_t recv_flags)
+{
+ struct kdbus_cmd_hello hello;
+ int r;
+ int fd;
+
+ fd = open(name, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ r = err("cannot open bus");
+ goto error;
+ }
+
+ memset(&hello, 0, sizeof(hello));
+ hello.size = sizeof(hello);
+ hello.attach_flags_send = _KDBUS_ATTACH_ALL;
+ hello.attach_flags_recv = recv_flags;
+ hello.pool_size = POOL_SIZE;
+ r = kdbus_cmd_hello(fd, &hello);
+ if (r < 0) {
+ err_r(r, "HELLO failed");
+ goto error;
+ }
+
+ bus_poool_free_slice(fd, hello.offset);
+
+ /*
+ * Map the pool of the connection. Its size has been set in the
+ * command struct above. See kdbus.pool(7).
+ */
+ pool = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
+ if (pool == MAP_FAILED) {
+ r = err("cannot mmap pool");
+ goto error;
+ }
+
+ return fd;
+
+error:
+ return -1;
+}
+
+
+
+static int bus_acquire_name(int fd, const char *name)
+{
+ struct kdbus_item *item;
+ struct kdbus_cmd *cmd;
+ size_t size;
+ int r;
+
+ /*
+ * This function acquires a well-known name on the bus through the
+ * KDBUS_CMD_NAME_ACQUIRE ioctl. This ioctl takes an argument of type
+ * 'struct kdbus_cmd', which is assembled below. See kdbus.name(7).
+ */
+ size = sizeof(*cmd);
+ size += KDBUS_ITEM_SIZE(strlen(name) + 1);
+
+ cmd = alloca(size);
+ memset(cmd, 0, size);
+ cmd->size = size;
+
+ /*
+ * The command requires an item of type KDBUS_ITEM_NAME, and its
+ * content must be a valid bus name.
+ */
+ item = cmd->items;
+ item->type = KDBUS_ITEM_NAME;
+ item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
+ strcpy(item->str, name);
+
+ /*
+ * Employ the command on the connection owner file descriptor.
+ */
+ r = kdbus_cmd_name_acquire(fd, cmd);
+ if (r < 0)
+ return err_r(r, "cannot acquire name");
+
+ return 0;
+}
+
+
+int parse_args(int argc, char** argv)
+{
+ char state = 0;
+ unsigned long int uid = 0;
+ unsigned long int gid = 0;
+ int i = 1;
+ int r = 0;
+ int fdl = -1;
+ int count = 0;
+
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ state = argv[i][1];
+ else {
+ switch (state) {
+
+ case 'n':
+ server_names[count++] = argv[i];
+ break;
+
+ case 'u':
+ uid = strtoul(argv[i],NULL,10);
+ r = setuid((uid_t)uid);
+ if (r< 0) {
+ fprintf(stderr, "Cannot set uid");
+ exit(-3245);
+ }
+ break;
+
+ case 'g':
+ gid = strtoul(argv[i],NULL,10);
+ r = setgid((gid_t)gid);
+ if (r< 0) {
+ fprintf(stderr, "Cannot set gid");
+ exit(-3245);
+ }
+ break;
+
+ case 'l':
+ fdl = open("/proc/self/attr/current", 0, S_IWUSR);
+ if (fdl < 0)
+ {
+ fprintf(stderr,"Cannot open /proc/self/attr/current\n");
+ exit(-345);
+ }
+
+ r = write(fdl, argv[i], strlen(argv[i]));
+ if (r < 0)
+ {
+ fprintf(stderr, "Cannot write to /proc/self/attr/current\n");
+ close(fdl);
+ exit(-345);
+ }
+ close(fdl);
+ break;
+ case 'q':
+ ready_fd = strtol(argv[i], NULL, 10);
+ break;
+ }
+ }
+ i++;
+ }
+ return 0;
+}
+
+int main(int argc, char* argv[]) {
+ int j = 0;
+ int fd;
+ parse_args(argc, argv);
+ fd = bus_open_connection(KDBUS_SYSTEM_BUS_PATH, KDBUS_ATTACH_PIDS);
+ if (fd < 0) {
+ return -1;
+ }
+
+ while(server_names[j] != '\0')
+ {
+ if (bus_acquire_name(fd, server_names[j]))
+ return -1;
+ j++;
+ }
+
+ close(ready_fd);
+
+ for(;;);
+ return 0;
+}
#define UID_INVALID ((uid_t) -1)
#define GID_INVALID ((gid_t) -1)
+#ifdef LIBDBUSPOLICY_TESTS_API
+#undef SYSTEM_BUS_CONF_FILE_PRIMARY
+#undef SESSION_BUS_CONF_FILE_PRIMARY
+#define SYSTEM_BUS_CONF_FILE_PRIMARY "/usr/lib/dbus-tests/configs/libdbuspolicy-tests/system.conf"
+#define SESSION_BUS_CONF_FILE_PRIMARY "/usr/lib/dbus-tests/configs/libdbuspolicy-tests/session.conf"
+#endif
+
/** A process ID */
typedef unsigned long dbus_pid_t;
/** A user ID */
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+uint64_t test_cases_mask = ~(0ULL);
+int test_count = 0;
+
+void assert_printf(int res, int tc, const char* value, int line, const char* file)
+{
+ if (res) {
+ printf("[r][%d]1\n", tc);
+ } else {
+ printf("[r][%d]0\n", tc);
+ fprintf(stderr, "[r][%d]0<-w=%s, line=%d, file=%s\n", tc, value, line, file);
+ }
+}
+
+void prepare_mask(int argc, char* argv[])
+{
+ if (argc > 1)
+ {
+ int i = 1;
+ test_cases_mask = 0;
+ for (;i < argc; i++) {
+ int val = strtol(argv[i], NULL, 10);
+ if (val >= 0)
+ test_cases_mask |= (1<<val);
+ }
+ }
+ return;
+}
--- /dev/null
+#include <stdint.h>
+
+#define assert(v) \
+ do { \
+ if (test_cases_mask & (1 << test_count)) \
+ { \
+ int ___r = (v); \
+ assert_printf(___r, test_count, #v, __LINE__, __FILE__); \
+ } \
+ test_count++; \
+ } while (0)
+
+enum {
+ false,
+ true
+};
+
+extern uint64_t test_cases_mask;
+extern int test_count;
+void prepare_mask(int argc, char* argv[]);
+void assert_printf(int res, int tc, const char* value, int line, const char* file);
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "stest_common.h"
+
+#define NEGATIVE_MATCH "negative"
+
+void __dbuspolicy1_change_creds(void* configuration, uid_t uid, gid_t gid,const char* label);
+
+int main(int argc, char* argv[])
+{
+ void* c = NULL;
+ int result = true;
+
+ prepare_mask(argc,argv);
+
+ if (!strncmp(argv[0], NEGATIVE_MATCH, sizeof(NEGATIVE_MATCH)-1))
+ result = false;
+
+ printf("---result: %d %s\n\n", result, argv[0]);
+ assert(((c = dbuspolicy1_init("/sys/fs/kdbus/0-system/bus")) != NULL));
+
+ __dbuspolicy1_change_creds(c,200,0,"L");
+ assert(dbuspolicy1_check_in(c, "cynara.destination", "cynara.sender", "L", 200, 0, NULL, "cynara.interface", "cynara.method", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == result);
+
+ assert(dbuspolicy1_check_in(c, "cynara.destination", "cynara.sender", "L", 200, 0, NULL, "cynara.interface", "cynara.method", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == result);
+ return 0;
+}
--- /dev/null
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "stest_common.h"
+
+void __dbuspolicy1_change_creds(void* configuration, uid_t uid, gid_t gid,const char* label);
+
+int main(int argc, char* argv[])
+{
+ void* c = NULL;
+
+ prepare_mask(argc,argv);
+
+ assert(((c = dbuspolicy1_init("/sys/fs/kdbus/0-system/bus")) != NULL));
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test2", "org.test.test3", NULL, "org.test.Itest1", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test2", "org.test.test3", NULL, 0, 0, "", "org.test.Itest1", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test2", "org.test.test3", "", "org.test.Itest1", "DontDoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test2", "org.test.test3", "", 0, 0, "", "org.test.Itest1", "DontDoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test2", "org.test.test3", "", "org.test.Itest1", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test2", "org.test.test3", "", 0, 0, "", "org.test.Itest1", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test2", "org.test.test3", "", "org.test.Itest2", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test2", "org.test.test3", "", 0, 0, "", "org.test.Itest2", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test3", "org.test.test2", "", "org.test.Itest3", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test3", "org.test.test2", "", 5001, 100, "", "org.test.Itest3", "NotKnown", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test3", "org.test.test2", "", "org.test.Itest3", "DontDoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test3", "org.test.test2", "", 5001, 100, "", "org.test.Itest3", "DontDoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == false);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test3", "org.test.test2", "", "org.test.Itest3", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test3", "org.test.test2", "", 5001, 100, "" ,"org.test.Itest3", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test3", "org.test.test2", "", "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test3", "org.test.test2", "", 5001, 100, NULL, "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test9", "org.test.test10", "", "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test9", "org.test.test10", "", 5001, 100, NULL, "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "org.test.test10", "org.test.test9", "", "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,5001,100,NULL);
+ assert(dbuspolicy1_check_in(c, "org.test.test10", "org.test.test9", "", 0, 0, NULL, "org.test.Itest4", "DoIt", DBUSPOLICY_MESSAGE_TYPE_METHOD_CALL, "", 0, 0) == true);
+
+ return 0;
+}
--- /dev/null
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "stest_common.h"
+
+void __dbuspolicy1_change_creds(void* configuration, uid_t uid, gid_t gid,const char* label);
+
+int main(int argc, char* argv[])
+{
+ void* c = NULL;
+
+ prepare_mask(argc,argv);
+
+ assert(((c = dbuspolicy1_init("/sys/fs/kdbus/0-system/bus")) != NULL));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(dbuspolicy1_can_own(c, "org.test.test1"));
+
+ __dbuspolicy1_change_creds(c, 5009, 0, NULL);
+ assert(dbuspolicy1_can_own(c, "org.test.test1"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test2"));
+
+ __dbuspolicy1_change_creds(c, 5009, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test2"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test3"));
+
+ __dbuspolicy1_change_creds(c, 5009, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test3"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test4"));
+
+ __dbuspolicy1_change_creds(c, 5009, 0, NULL);
+ assert(dbuspolicy1_can_own(c, "org.test.test4"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(!dbuspolicy1_can_own(c, "org.test.test5"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(dbuspolicy1_can_own(c, "org.test.test6"));
+
+ __dbuspolicy1_change_creds(c, 0, 0, NULL);
+ assert(dbuspolicy1_can_own(c, "org.test.test7"));
+
+ assert(dbuspolicy1_can_own(c, "a.b.c"));
+ assert(dbuspolicy1_can_own(c, "a.b"));
+ assert(!dbuspolicy1_can_own(c, "c"));
+ assert(!dbuspolicy1_can_own(c, "a.c"));
+ assert(!dbuspolicy1_can_own(c, "b.c"));
+
+ return 0;
+}
--- /dev/null
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dbuspolicy1/libdbuspolicy1.h>
+#include "stest_common.h"
+
+void __dbuspolicy1_change_creds(void* configuration, uid_t uid, gid_t gid,const char* label);
+
+int main(int argc, char* argv[])
+{
+ void* c = NULL;
+
+ prepare_mask(argc,argv);
+
+ assert(((c = dbuspolicy1_init("/sys/fs/kdbus/0-system/bus")) != NULL));
+
+ __dbuspolicy1_change_creds(c,0,0,NULL);
+ assert(dbuspolicy1_check_out(c, "", "bli.bla.blubb test.test1 test.tes3", "", "/an/object/path", "", DBUSPOLICY_MESSAGE_TYPE_SIGNAL, "", 0, 0) == true);
+
+ __dbuspolicy1_change_creds(c,5010,0,NULL);
+ assert(dbuspolicy1_check_out(c, "", "bli.bla.blubb", "", "/an/object/path", "", DBUSPOLICY_MESSAGE_TYPE_SIGNAL, "", 0, 0) == false);
+
+ return 0;
+}
--- /dev/null
+/* This file contains test-runner for libdbuspolicy
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Author: Kazimierz Krosman <k.krosman@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/select.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include "test_runner.h"
+
+enum {
+ PIPE_READ,
+ PIPE_WRITE,
+};
+
+/*****************CUSTOM SECTION***********************************/
+/*custom function that parse stdout of binary and result of binary*/
+void parse_test_state(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+void parse_one_test_one_binary(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+char** prepare_args_for_binary(const struct binary* b, const char* test_name);
+int daemon_init(void);
+int daemon_clear(void);
+int cynara_init(void);
+int cynara_clear(void);
+int cynara_n_init(void);
+int cynara_n_clear(void);
+
+static struct test_case ownership_test_cases[] = {
+ {"0", "Libdbuspolicy1 init function call"},
+ {"1", "Simple check for ownership in default context"},
+ {"2", "Simple check for ownership in default context"},
+ {"3", "Ownership check in user context"},
+ {"4", "Ownership check in user context (negative test)"},
+ {"5", "Ownership check in mandatory context with user context (context priority check)"},
+ {"6", "Ownership check in mandatory context with user context (for another user)"},
+ {"7", "Ownership check for not root user context (negative test)"},
+ {"8", "Ownership check for not root user context"},
+ {"9", "Ownership check for group context"},
+ {"10", "Ownership check for all context (priority check)"},
+ {"11", "Ownership check for all context (priority check)"},
+ {"12", "Ownership check for own_prefix case (1)"},
+ {"13", "Ownership check for own_prefix case (2)"},
+ {"14", "Ownership check for own_prefix case (negative test)"},
+ {"15", "Ownership check for own_prefix case (negative test)"},
+ {"16", "Ownership check for own_prefix case (negative test)"},
+ {NULL, NULL}
+};
+
+static struct test_case method_call_test_cases[] = {
+ {"0", "Libdbuspolicy1 init function call"},
+ {"1", "check_out test"},
+ {"2", "check_in test"},
+ {"3", "check_out test"},
+ {"4", "check_in test"},
+ {"5", "check_out test"},
+ {"6", "check_in test"},
+ {"7", "check_out test"},
+ {"8", "check_in test"},
+ {"9", "check_out test"},
+ {"10", "check_in test"},
+ {"11", "check_out test"},
+ {"12", "check_in test"},
+ {"13", "check_out test"},
+ {"14", "check_in test"},
+ {"15", "check_out test"},
+ {"16", "check_in test"},
+ {"17", "check_out test"},
+ {"18", "check_in test"},
+ {"19", "check_out test"},
+ {"20", "check_in test"},
+ {NULL, NULL}
+};
+
+static struct test_case signal_test_cases[] = {
+ {"1", "Libdbuspolicy1 init"},
+ {"2", "Check out for signal"},
+ {"3", "Check out for signal (negative)"},
+ {NULL, NULL}
+};
+
+static struct test_case cynara_test_cases[] = {
+ {"0", "Libdbuspolicy1 init function call"},
+ {"1", "Check cynara for result"},
+ {"2", "Check cynara for result (second attempt to use cache)"},
+ {NULL, NULL}
+};
+
+static struct test_case negative_cynara_test_cases[] = {
+ {"0", "Libdbuspolicy1 init function call"},
+ {"1", "Check cynara for result (negative test)"},
+ {"2", "Check cynara for result (second attempt to use cache) (negative test)"},
+ {NULL, NULL}
+};
+
+/* This table is used to start binaries */
+struct binary tests[] = {
+/*path, name, TC_table, timeout in us, prepare_args_handler, parse_function_handler, init_handler, clean_handler*/
+ {TEST_PATH "stest_ownership", "ownership", ownership_test_cases, 1000*1000, prepare_args_for_binary, parse_test_state, daemon_init, daemon_clear},
+ {TEST_PATH "stest_method_call", "method_call", method_call_test_cases, 1000*1000, prepare_args_for_binary, parse_test_state, daemon_init, daemon_clear},
+ {TEST_PATH "stest_signal", "signal", signal_test_cases, 1000*1000, prepare_args_for_binary, parse_test_state, daemon_init, daemon_clear},
+ {TEST_PATH "stest_cynara", "cynara", cynara_test_cases, 1000*1000, prepare_args_for_binary, parse_test_state, cynara_init, cynara_clear},
+ {TEST_PATH "stest_cynara", "negative_cynara", negative_cynara_test_cases, 1000*1000, prepare_args_for_binary, parse_test_state, cynara_n_init, cynara_n_clear},
+};
+
+
+static const char result_pattern[] = "[r][%0]%1";
+static struct state {
+ unsigned int i; // index of input buffer
+ unsigned int j; // index in results[n]
+ unsigned int n; //index in results buffer (0 or 1)
+ char results[2][MAX_COMMENT];
+} g_state;
+
+static void sm_reset(void)
+{
+ memset(&g_state, 0, sizeof (g_state));
+}
+
+static int sm_update(char* buffer, int i)
+{
+ int l = strlen(buffer) + 1;
+ while (i < l && g_state.i < sizeof(result_pattern) - 1) {
+ if (result_pattern[g_state.i] == '%') {
+ g_state.n = result_pattern[g_state.i+1] - '0';
+ if (g_state.n > 1) {
+ sm_reset();
+ i--;
+ } else if (isalnum(buffer[i])) {
+ g_state.results[g_state.n][g_state.j++] = buffer[i];
+ } else if (buffer[i] == result_pattern[g_state.i+2] || buffer[i] == '\n') {
+ g_state.results[g_state.n][g_state.j] = 0;
+ g_state.i += 3;
+ g_state.j = 0;
+ if (g_state.n == 1)
+ return i;
+ } else {
+ g_state.i = 0;
+ g_state.j = 0;
+ }
+ } else if (result_pattern[g_state.i] == buffer[i]) {
+ g_state.i++;
+ } else {
+ sm_reset();
+ }
+ i++;
+ }
+
+ if (g_state.i >= sizeof(result_pattern) - 1) {
+ g_state.results[g_state.n][g_state.j] = 0;
+ g_state.i += 3;
+ g_state.j = 0;
+ if (g_state.n == 1)
+ return i;
+ }
+
+ return 0;
+}
+
+static const char* sm_get_result(int i)
+{
+ return g_state.results[i];
+}
+
+static pid_t daemon_pids[4] ={0};
+static int daemons_pipe[4][2];
+static char* daemon_argv1[] = {TEST_PATH "dbus_daemon", "-q", NULL, "-n","org.test.test3", NULL};
+static char* daemon_argv2[] = {TEST_PATH "dbus_daemon", "-q", NULL,"-n", "org.test.test2", "-g", "100", "-u", "5001", NULL};
+static char* daemon_argv3[] = {TEST_PATH "dbus_daemon", "-q", NULL,"-n", "org.test.test12", "org.test.test9", NULL};
+static char* daemon_argv4[] = {TEST_PATH "dbus_daemon", "-q", NULL, "-n", "org.test.test13", "org.test.test10", "org.test.test11", "-g", "100", "-u", "5001", NULL};
+static char** daemons[] = { daemon_argv1, daemon_argv2, daemon_argv3, daemon_argv4};
+
+int daemon_init(void)
+{
+ int i = 0;
+ int ready_proc = 0;
+ struct timeval tv;
+ fd_set rfds;
+ int nfds = -1;
+ int proc_num = sizeof(daemons)/sizeof(daemons[0]);
+
+ for (;i < proc_num;i++) {
+ if (pipe(daemons_pipe[i]) < 0) {
+ perror("cannot create pipe");
+ goto error1;
+ }
+
+ daemon_pids[i] = fork();
+ if (!daemon_pids[i]) {
+ char fdd[15];
+ sprintf(fdd,"%d",daemons_pipe[i][PIPE_WRITE]);
+ daemons[i][2] = fdd;
+ close (daemons_pipe[i][PIPE_READ]);
+ (void)execv(daemons[i][0],daemons[i]);
+ exit(0);
+ } else if (daemon_pids[i] > 0){
+ close (daemons_pipe[i][PIPE_WRITE]);
+ } else
+ goto error1;
+ }
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ while(1) {
+ FD_ZERO(&rfds);
+ for (i = 0; i < proc_num;i++) {
+ if (daemons_pipe[i][PIPE_READ] > -1)
+ FD_SET(daemons_pipe[i][PIPE_READ], &rfds);
+ }
+
+ if (ready_proc >= proc_num)
+ break;
+
+ nfds = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ if (nfds > 0) {
+ for (i = 0; i < proc_num;i++) {
+ if (daemons_pipe[i][PIPE_READ] > -1 && FD_ISSET(daemons_pipe[i][PIPE_READ], &rfds)) {
+ ++ready_proc;
+ close (daemons_pipe[i][PIPE_READ]);
+ daemons_pipe[i][PIPE_READ] = -1;
+ }
+ }
+ } else
+ goto error1;
+ }
+
+ return 1;
+error1:
+ daemon_clear();
+ return 0;
+}
+
+int daemon_clear(void)
+{
+ unsigned int i = 0;
+ for (;i < sizeof(daemons)/sizeof(daemons[0]);i++) {
+ if (daemon_pids[i])
+ kill(daemon_pids[i], SIGKILL);
+ }
+ return 0;
+}
+
+static int call_script(char* path, char* argv[])
+{
+ int status;
+ int r;
+ pid_t pid = fork();
+
+ if (pid < 0)
+ return 0;
+ else if (!pid) {
+ (void)execv(path, argv);
+ exit(-1);
+ }
+
+ r = waitpid(pid, &status, 0);
+ if (r > 0) {
+ if (WIFEXITED(status))
+ return !(WEXITSTATUS(status));
+ else if (WIFCONTINUED(status))
+ kill(pid, SIGKILL);
+ }
+
+ /* fail */
+ return 0;
+}
+
+int cynara_n_init(void)
+{
+ char* argv[] = {CYNARA_PATH, "DENY", NULL};
+ return call_script(argv[0],argv);
+}
+
+int cynara_n_clear(void)
+{
+ return cynara_clear();
+}
+
+int cynara_init(void)
+{
+ char* argv[] = {CYNARA_PATH, "ALLOW", NULL};
+ return call_script(argv[0],argv);
+}
+
+int cynara_clear(void)
+{
+ char* argv[] = {CYNARA_PATH, NULL};
+ return call_script(argv[0],argv);
+}
+
+static char* args[3];
+char** prepare_args_for_binary(const struct binary* b, const char* test_name)
+{
+ args[0] = (char*)b->name;
+ if (!test_name[0])
+ args[1] = NULL;
+ else {
+ args[1] = (char*)test_name;
+ args[2] = NULL;
+ }
+ return args;
+}
+
+
+/*
+ * Example of test_result detector function implementation
+ */
+void parse_test_state(const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option)
+{
+ char test_id[MAX_COMMENT];
+
+ switch(state_change) {
+ case INIT_TEST:
+ sm_reset();
+ break;
+ case NEW_STDOUT:
+ {
+ int k = 0;
+ buffer[state_option] = 0;
+ get_test_id(test_id, b, test_name);
+ fprintf(stderr, "[stdout][%s]%s\n",test_id, buffer);
+ while ( (k = sm_update(buffer, k))) {
+ const char* t_name = sm_get_result(0);
+ const char* result_code = sm_get_result(1);
+ bool is_successful = result_code[0] == '1' && result_code[1] == 0;
+ const char* result_text = is_successful ? "PASS" : "FAIL";
+
+ get_test_id(test_id, b, t_name);
+ add_test_result(test_id, result_text, "", is_successful);
+ sm_reset();
+ }
+ }
+ break;
+ case NEW_STDERR:
+ buffer[state_option] = 0;
+ get_test_id(test_id, b, test_name);
+ fprintf(stderr, "[stderr][%s]%s\n",test_id, buffer);
+ break;
+ case RESULT_CODE:
+ if (state_option != 0)
+ add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Test exited with error code", 0);
+ break;
+ case RESULT_SIGNAL:
+ add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Finished by SIGNAL", 0);
+ break;
+ case RESULT_TIMEOUT:
+ add_test_result(get_test_id(test_id, b, test_name), "FAIL", "Test TIMEOUT", 0);
+ break;
+ }
+}
+
+/****************************END of CUSTOM FUNCTIONS************************/
+
+
+static struct option long_options[] = {
+ {"list", no_argument, 0, 'l'},
+ {"run", required_argument, 0, 'r'},
+ {"description", required_argument, 0, 'd'},
+ {0, 0, 0, 0 }
+};
+
+static int stdin_pipe[2];
+static int stdout_pipe[2];
+static int stderr_pipe[2];
+static struct test_result test_results[MAX_TC_NUM];
+static int test_results_i;
+static char buffer[MAX_BUFFER];
+static const char* requested_tc[MAX_TC_NUM];
+
+char* get_test_id(char* dest, const struct binary* b, const char* test_name)
+{
+ int len = strlen(b->name);
+ memcpy(dest, b->name, len);
+ memcpy(dest + len, test_name, strlen(test_name)+1);
+ return dest;
+}
+
+static void print_description(const char* name, const char* description)
+{
+ printf("%s;%s\n",name, description);
+}
+
+static void print_list(const char* test_name)
+{
+ unsigned int i;
+ char full_name[MAX_COMMENT];
+ for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++) {
+ int j = 0;
+ int l = strlen(tests[i].name);
+ memcpy(full_name, tests[i].name, l+1);
+ if (test_name && strncmp(test_name, full_name, l) != 0)
+ continue;
+
+ while (tests[i].test_cases[j].name) {
+ memcpy(full_name + l, tests[i].test_cases[j].name, strlen(tests[i].test_cases[j].name) + 1);
+ if (!test_name || strcmp(full_name, test_name) == 0)
+ print_description(full_name,tests[i].test_cases[j].description);
+ j++;
+ }
+ }
+}
+
+
+static void stop_binary(const struct binary* b, pid_t pid, const char* test_name)
+{
+ int status = 0;
+ int res = 0;
+ res = waitpid(pid, &status, 0);
+ if (res == 0) {
+ //timeouted
+ kill(pid, SIGKILL);
+ res = waitpid(pid, &status, WNOHANG);
+ b->parse(b, test_name, buffer, RESULT_TIMEOUT, res);
+ } else if (res < 0) {
+ //errno check
+ kill(pid, SIGKILL);
+ res = waitpid(pid, &status, WNOHANG);
+ b->parse(b, test_name, buffer, RESULT_ERROR, res);
+ } else if (res > 0) {
+ if (WIFEXITED(status)) {
+ b->parse(b, test_name, buffer, RESULT_CODE, WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ b->parse(b, test_name, buffer, RESULT_SIGNAL, WTERMSIG(status));
+ } else if (WIFSTOPPED(status)) {
+ b->parse(b, test_name, buffer, RESULT_SIGNAL, WSTOPSIG(status));
+ } else if (WIFCONTINUED(status)) {
+ kill(pid, SIGKILL);
+ b->parse(b, test_name, buffer, RESULT_SIGNAL, -1);
+ }
+ }
+}
+
+static void parse_output_with_timeout(const struct binary* b, pid_t pid, const char* test_name)
+{
+ struct timeval tv;
+ fd_set rfds;
+ int nfds;
+ int res;
+ tv.tv_sec = b->timeout/(1000*1000);
+ tv.tv_usec = (b->timeout-tv.tv_sec*1000*1000);
+ while (1) {
+ FD_ZERO(&rfds);
+ FD_SET(stdout_pipe[PIPE_READ], &rfds);
+ FD_SET(stderr_pipe[PIPE_READ], &rfds);
+ nfds = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ if (nfds == -1) {
+ if (errno != EINTR)
+ break;
+ } else if (nfds > 0) {
+ if (FD_ISSET(stdout_pipe[PIPE_READ], &rfds)) {
+ res = read(stdout_pipe[PIPE_READ], buffer, MAX_BUFFER-1);
+ if (res == 0 || (res < 0 && errno != EINTR))
+ break;
+ else if (res >=0)
+ b->parse(b, test_name, buffer, NEW_STDOUT, res);
+ }
+
+ if (FD_ISSET(stderr_pipe[PIPE_READ], &rfds)) {
+ res = read(stderr_pipe[PIPE_READ], buffer, MAX_BUFFER-1);
+ if (res == 0 || (res < 0 && errno != EINTR))
+ break;
+ b->parse(b, test_name, buffer, NEW_STDERR, res);
+ }
+ } else {
+ //timeout
+ break;
+ }
+ }
+ stop_binary(b, pid, test_name);
+}
+
+static int create_child(const char* path, char* const arguments[])
+{
+ int child;
+ int nResult;
+ if (pipe(stdin_pipe) < 0) {
+ perror("allocating pipe for child input redirect failed");
+ goto error1;
+ }
+
+ if (pipe(stdout_pipe) < 0) {
+ perror("allocating pipe for child output redirect failed");
+ goto error2;
+ }
+
+ if (pipe(stderr_pipe) < 0) {
+ perror("allocating pipe for child output redirect failed");
+ goto error3;
+ }
+
+ child = fork();
+ if (!child) {
+ char ld_path[512];
+ sprintf(ld_path, "/usr/lib/dbus-tests/lib/libdbuspolicy-tests/:");
+ // redirect stdin
+ if (dup2(stdin_pipe[PIPE_READ], STDIN_FILENO) == -1) {
+ perror("redirecting stdin failed");
+ return -1;
+ }
+
+ // redirect stdout
+ if (dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
+ perror("redirecting stdout failed");
+ return -1;
+ }
+
+ // redirect stderr
+ if (dup2(stderr_pipe[PIPE_WRITE], STDERR_FILENO) == -1) {
+ perror("redirecting stderr failed");
+ return -1;
+ }
+
+ // all these are for use by parent only
+ close(stdin_pipe[PIPE_READ]);
+ close(stdin_pipe[PIPE_WRITE]);
+ close(stdout_pipe[PIPE_READ]);
+ close(stdout_pipe[PIPE_WRITE]);
+ close(stderr_pipe[PIPE_READ]);
+ close(stderr_pipe[PIPE_WRITE]);
+
+ char* ld_path_b = getenv("LD_LIBRARY_PATH");
+ if (ld_path_b != NULL)
+ memcpy(ld_path + strlen(ld_path), ld_path_b, strlen(ld_path_b)+1);
+ setenv("LD_LIBRARY_PATH", ld_path, 1);
+ // run child process image
+ nResult = execv(path, arguments);
+
+ // if we get here at all, an error occurred, but we are in the child
+ // process, so just exit
+ perror("exec of the child process failed");
+ exit(nResult);
+ } else if (child > 0) {
+ // parent continues here
+
+ // close unused file descriptors, these are for child only
+ close(stdin_pipe[PIPE_READ]);
+ close(stdout_pipe[PIPE_WRITE]);
+ close(stderr_pipe[PIPE_WRITE]);
+ } else {
+ // failed to create child
+ goto error4;
+ }
+
+ return child;
+
+error4:
+ close(stderr_pipe[PIPE_READ]);
+ close(stderr_pipe[PIPE_WRITE]);
+error3:
+ close(stdout_pipe[PIPE_READ]);
+ close(stdout_pipe[PIPE_WRITE]);
+error2:
+ close(stdin_pipe[PIPE_READ]);
+ close(stdin_pipe[PIPE_WRITE]);
+error1:
+ return -1;
+}
+
+static void run_test(const struct binary* b, const char* test_name)
+{
+ int res = -1;
+ char** arg;
+ char test_id[MAX_COMMENT];
+
+ assert(b);
+ assert(b->name);
+ assert(b->path);
+ assert(test_name);
+
+ arg = b->prepare_args(b, test_name);
+
+ if (b->init)
+ if (!b->init()) {
+ add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Internal error: Cannot init test", 0);
+ return;
+ }
+
+ res = create_child(b->path, arg);
+ if (res > 0)
+ parse_output_with_timeout(b, res, test_name);
+ else
+ add_test_result(get_test_id(test_id, b, test_name), "ERROR", "Internal error: Cannot start test", 0);
+
+ if (b->clean)
+ b->clean();
+}
+
+static void parse_run_test(const char* tc) {
+ unsigned int i = 0;
+ for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++) {
+ int len = strlen(tests[i].name);
+ if (strncmp(tc, tests[i].name, len) == 0) {
+ if (tc[len] == '*' || tc[len] == '\0')
+ run_test(&tests[i], "");
+ else
+ run_test(&tests[i], tc + len);
+ }
+ }
+}
+
+static int parse_option(int argc, char* argv[])
+{
+ int ch = 0;
+ int c = 0;
+ while ((ch = getopt_long(argc, argv, "lr:d:", long_options, NULL)) != -1) {
+ switch (ch) {
+ case 'l':
+ print_list(NULL);
+ return 1;
+ case 'r':
+ if (c >= MAX_TC_NUM - 1) //NULL at the end
+ return 0;
+
+ if (optarg)
+ requested_tc[c++] = optarg;
+
+ break;
+ case 'd':
+ print_list(optarg);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+//output_new/fail/success
+void add_test_result(const char* test_id, const char* result, const char* comment, int res)
+{
+ test_results[test_results_i].is_positive = res;
+ strcpy(test_results[test_results_i].result, result);
+ strcpy(test_results[test_results_i].comment, comment);
+ strcpy(test_results[test_results_i++].name, test_id);
+}
+
+static void prepare_results(void)
+{
+ //todo
+}
+
+static void print_results()
+{
+ int i = 0;
+ for (i = 0; i < test_results_i; i++)
+ {
+ printf("%s;%s;%s\n", test_results[i].name, test_results[i].result, test_results[i].comment);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ unsigned int i;
+ signal(SIGPIPE, SIG_IGN);
+ if (parse_option(argc, argv))
+ return 0;
+
+ prepare_results();
+
+ if (!requested_tc[0]) {
+ for (i = 0;i < sizeof(tests)/sizeof(struct binary); i++)
+ run_test(&tests[i], "");
+ } else {
+ i = 0;
+ while(requested_tc[i]) {
+ parse_run_test(requested_tc[i]);
+ i++;
+ }
+ }
+
+ print_results();
+ return 0;
+}
--- /dev/null
+/* This file is part of test-runner (see template.c)
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Author: Kazimierz Krosman <k.krosman@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef TEST_RUNNER_H
+#define TEST_RUNNER_H
+#include <stdbool.h>
+
+#define TC_NAME "libdbuspolicy-tests"
+#define TEST_PATH "/usr/lib/dbus-tests/test-suites/libdbuspolicy-tests/"
+#define CYNARA_PATH TEST_PATH "cynara_prepare.sh"
+#define MAX_TC_NUM 1024
+#define MAX_BUFFER (64*1024)
+#define MAX_COMMENT 1024
+
+enum {
+ INIT_TEST,
+ NEW_STDOUT,
+ NEW_STDERR,
+ RESULT_CODE,
+ RESULT_SIGNAL,
+ RESULT_ERROR,
+ RESULT_TIMEOUT
+};
+
+struct test_result {
+ bool is_positive;
+ char comment[MAX_COMMENT];
+ char result[MAX_COMMENT];
+ char name[MAX_COMMENT];
+};
+
+struct test_case {
+ const char* name;
+ const char* description;
+};
+
+struct binary {
+ const char* path;
+ const char* name;
+ /* can be filled by asking binary */
+ struct test_case* test_cases;
+ int timeout;
+
+ char** (*prepare_args) (const struct binary* b, const char* test_name);
+ void (*parse) (const struct binary* b, const char* test_name, char* buffer, int state_change, int state_option);
+ int (*init)(void);
+ int (*clean)(void);
+};
+
+char* get_test_id(char* dest, const struct binary* b, const char* test_name);
+void add_test_result(const char* test_id, const char* result, const char* comment, int res);
+
+
+#endif /* TEST_RUNNER_H */