selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] libsemanage: add tests
@ 2019-06-12  8:03 Jan Zarsky
  2019-06-12  8:03 ` [PATCH 01/11] libsemanage: add helper functions to tests Jan Zarsky
                   ` (11 more replies)
  0 siblings, 12 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

This series adds new test suites for libsemanage. In the first patch, common
helper functions are added. The other patches are independent and each adds a
new test suite.

The test suites are testing only the public API and aim for line coverage. They
test only correct usage of the functions. Together with valgrind, the test
suites can be used for detecting memory leaks.

The tests run fine in Travis CI and do not require an SELinux-enabled system.

I welcome any suggestions.

Jan Zarsky (11):
  libsemanage: add helper functions to tests
  libsemanage: test semanage_handle_* functions
  libsemanage: test semanage_bool_* functions
  libsemanage: test semanage_fcontext functions
  libsemanage: test semanage_iface_* functions
  libsemanage: test semanage_ibendport_* functions
  libsemanage: test semanage_node_* functions
  libsemanage: test semanage_port_* functions
  libsemanage: test semanage_user_* functions
  libsemanage: test semanage_context_* functions
  libsemanage: test semanage_msg_default_handler

 libsemanage/tests/.gitignore            |    1 +
 libsemanage/tests/Makefile              |   11 +-
 libsemanage/tests/libsemanage-tests.c   |   18 +
 libsemanage/tests/test_bool.c           |  932 +++++++++++++++++++++++++++
 libsemanage/tests/test_bool.cil         |   24 +
 libsemanage/tests/test_bool.h           |   31 +
 libsemanage/tests/test_fcontext.c       | 1045 +++++++++++++++++++++++++++++++
 libsemanage/tests/test_fcontext.cil     |   25 +
 libsemanage/tests/test_fcontext.h       |   30 +
 libsemanage/tests/test_handle.c         |  329 ++++++++++
 libsemanage/tests/test_handle.cil       |   21 +
 libsemanage/tests/test_handle.h         |   30 +
 libsemanage/tests/test_ibendport.c      |  525 ++++++++++++++++
 libsemanage/tests/test_ibendport.cil    |   28 +
 libsemanage/tests/test_ibendport.h      |   30 +
 libsemanage/tests/test_iface.c          |  666 ++++++++++++++++++++
 libsemanage/tests/test_iface.cil        |   28 +
 libsemanage/tests/test_iface.h          |   30 +
 libsemanage/tests/test_node.c           |  807 ++++++++++++++++++++++++
 libsemanage/tests/test_node.cil         |   28 +
 libsemanage/tests/test_node.h           |   30 +
 libsemanage/tests/test_other.c          |  120 ++++
 libsemanage/tests/test_other.h          |   30 +
 libsemanage/tests/test_port.c           |  909 +++++++++++++++++++++++++++
 libsemanage/tests/test_port.cil         |   27 +
 libsemanage/tests/test_port.h           |   30 +
 libsemanage/tests/test_semanage_store.c |    2 +-
 libsemanage/tests/test_user.c           |  690 ++++++++++++++++++++
 libsemanage/tests/test_user.cil         |   27 +
 libsemanage/tests/test_user.h           |   30 +
 libsemanage/tests/utilities.c           |  254 +++++++-
 libsemanage/tests/utilities.h           |   53 +-
 32 files changed, 6831 insertions(+), 10 deletions(-)



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/11] libsemanage: add helper functions to tests
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:03 ` [PATCH 02/11] libsemanage: test semanage_handle_* functions Jan Zarsky
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

- Add functions for creating and destroying test semanage store.
- Add functions for writing SELinux policy to the test store.
- Add functions for creating semanage handle, connecting to the store and for
  beginning a transaction.
- Update Makefile to compile test policies from CIL source.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/.gitignore            |   1 +
 libsemanage/tests/Makefile              |  11 +-
 libsemanage/tests/test_semanage_store.c |   2 +-
 libsemanage/tests/utilities.c           | 254 +++++++++++++++++++++++-
 libsemanage/tests/utilities.h           |  53 ++++-
 5 files changed, 311 insertions(+), 10 deletions(-)

diff --git a/libsemanage/tests/.gitignore b/libsemanage/tests/.gitignore
index f07111db..8a2a866a 100644
--- a/libsemanage/tests/.gitignore
+++ b/libsemanage/tests/.gitignore
@@ -1 +1,2 @@
 libsemanage-tests
+*.policy
diff --git a/libsemanage/tests/Makefile b/libsemanage/tests/Makefile
index 324766a0..69f49a36 100644
--- a/libsemanage/tests/Makefile
+++ b/libsemanage/tests/Makefile
@@ -1,5 +1,6 @@
 # Add your test source files here:
 SOURCES = $(sort $(wildcard *.c))
+CILS = $(sort $(wildcard *.cil))
 
 ###########################################################################
 
@@ -8,15 +9,19 @@ CFLAGS += -g -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute
 override CFLAGS += -I../src -I../include
 override LDLIBS += -lcunit -lbz2 -laudit -lselinux -lsepol
 
-OBJECTS = $(SOURCES:.c=.o) 
+OBJECTS = $(SOURCES:.c=.o)
+POLICIES = $(CILS:.cil=.policy)
 
-all: $(EXECUTABLE) 
+all: $(EXECUTABLE) $(POLICIES)
 
 $(EXECUTABLE): $(OBJECTS) ../src/libsemanage.a
 	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 
+%.policy: %.cil
+	../../secilc/secilc $*.cil -o $*.policy -f /dev/null
+
 clean distclean: 
-	rm -rf $(OBJECTS) $(EXECUTABLE)
+	rm -rf $(OBJECTS) $(POLICIES) $(EXECUTABLE)
 
 test: all 
 	./$(EXECUTABLE)
diff --git a/libsemanage/tests/test_semanage_store.c b/libsemanage/tests/test_semanage_store.c
index b324d502..92085361 100644
--- a/libsemanage/tests/test_semanage_store.c
+++ b/libsemanage/tests/test_semanage_store.c
@@ -43,7 +43,7 @@
 #include <unistd.h>
 #include <CUnit/Basic.h>
 
-semanage_handle_t *sh = NULL;
+extern semanage_handle_t *sh;
 const char *rootpath = "./test-policy";
 const char *polpath = "./test-policy/store/";
 const char *readlockpath = "./test-policy/store/semanage.read.LOCK";
diff --git a/libsemanage/tests/utilities.c b/libsemanage/tests/utilities.c
index 7cc726c6..18393215 100644
--- a/libsemanage/tests/utilities.c
+++ b/libsemanage/tests/utilities.c
@@ -1,6 +1,7 @@
 /* Authors: Christopher Ashworth <cashworth@tresys.com>
  *
  * Copyright (C) 2006 Tresys Technology, LLC
+ * Copyright (C) 2019 Red Hat, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -17,16 +18,261 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*  The purpose of this file is to provide some functions commonly needed 
+/*  The purpose of this file is to provide some functions commonly needed
  *  by our unit tests.
  */
 
 #include "utilities.h"
 
+int test_store_enabled = 0;
+
+semanage_handle_t *sh = NULL;
+
 /* Silence any error output caused by our tests
- * by using this dummy function to catch messages. 
+ * by using this dummy function to catch messages.
  */
-void test_msg_handler(void *varg,
-		      semanage_handle_t * handle, const char *fmt, ...)
+void test_msg_handler(void *varg, semanage_handle_t *handle, const char *fmt,
+		      ...)
 {
 }
+
+int create_test_store() {
+	FILE *fptr;
+
+	if (mkdir("test-policy", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active/modules", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/etc", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/etc/selinux", 0700) < 0)
+		return -1;
+
+	fptr = fopen("test-policy/etc/selinux/semanage.conf", "w+");
+
+	if (!fptr)
+		return -1;
+
+	fclose(fptr);
+
+	enable_test_store();
+	return 0;
+}
+
+void disable_test_store(void) {
+	test_store_enabled = 0;
+}
+
+void enable_test_store(void) {
+	test_store_enabled = 1;
+}
+
+int write_test_policy(char *data, size_t data_len) {
+	FILE *fptr = fopen("test-policy/store/active/policy.kern", "wb+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite(data, data_len, 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	return 0;
+}
+
+int write_test_policy_from_file(const char *filename) {
+	char *buf = NULL;
+	size_t len = 0;
+	FILE *fptr = fopen(filename, "rb");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	fseek(fptr, 0, SEEK_END);
+	len = ftell(fptr);
+	fseek(fptr, 0, SEEK_SET);
+
+	buf = (char *) malloc(len);
+
+	if (!buf) {
+		perror("malloc");
+		fclose(fptr);
+		return -1;
+	}
+
+	fread(buf, len, 1, fptr);
+	fclose(fptr);
+
+	return write_test_policy(buf, len);
+}
+
+int write_test_policy_src(unsigned char *data, unsigned int data_len) {
+	if (mkdir("test-policy/store/active/modules/100", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active/modules/100/base", 0700) < 0)
+		return -1;
+
+	FILE *fptr = fopen("test-policy/store/active/modules/100/base/cil",
+			   "w+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite(data, data_len, 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	fptr = fopen("test-policy/store/active/modules/100/base/lang_ext",
+		     "w+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite("cil", sizeof("cil"), 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	return 0;
+}
+
+int destroy_test_store() {
+	FTS *ftsp = NULL;
+	FTSENT *curr = NULL;
+	int ret = 0;
+
+	disable_test_store();
+
+	char *files[] = { (char *) "test-policy", NULL };
+
+	ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
+
+	if (!ftsp)
+		return -1;
+
+	while ((curr = fts_read(ftsp)))
+		switch (curr->fts_info) {
+		case FTS_DP:
+		case FTS_F:
+		case FTS_SL:
+		case FTS_SLNONE:
+		case FTS_DEFAULT:
+			if (remove(curr->fts_accpath) < 0)
+				ret = -1;
+		default:
+			break;
+		}
+
+	fts_close(ftsp);
+
+	return ret;
+}
+
+void helper_handle_create(void) {
+	if (test_store_enabled)
+		semanage_set_root("test-policy");
+
+	sh = semanage_handle_create();
+	CU_ASSERT_PTR_NOT_NULL(sh);
+
+	semanage_msg_set_callback(sh, test_msg_handler, NULL);
+
+	if (test_store_enabled) {
+		semanage_set_create_store(sh, 1);
+		semanage_set_reload(sh, 0);
+		semanage_set_store_root(sh, "");
+		semanage_select_store(sh, (char *) "store",
+				      SEMANAGE_CON_DIRECT);
+	}
+}
+
+void helper_handle_destroy(void) {
+	semanage_handle_destroy(sh);
+}
+
+void helper_connect(void) {
+	CU_ASSERT(semanage_connect(sh) >= 0);
+}
+
+void helper_disconnect(void) {
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+}
+
+void helper_begin_transaction(void) {
+	CU_ASSERT(semanage_begin_transaction(sh) >= 0);
+}
+
+void helper_commit(void) {
+	CU_ASSERT(semanage_commit(sh) >= 0);
+}
+
+void setup_handle(level_t level) {
+	if (level >= SH_NULL)
+		sh = NULL;
+
+	if (level >= SH_HANDLE)
+		helper_handle_create();
+
+	if (level >= SH_CONNECT)
+		helper_connect();
+
+	if (level >= SH_TRANS)
+		helper_begin_transaction();
+}
+
+void cleanup_handle(level_t level) {
+	if (level >= SH_TRANS)
+		helper_commit();
+
+	if (level >= SH_CONNECT)
+		helper_disconnect();
+
+	if (level >= SH_HANDLE)
+		helper_handle_destroy();
+
+	if (level >= SH_NULL)
+		sh = NULL;
+}
+
+void setup_handle_invalid_store(level_t level) {
+	CU_ASSERT(level >= SH_HANDLE);
+
+	helper_handle_create();
+
+	semanage_select_store(sh, (char *) "", SEMANAGE_CON_INVALID);
+
+	if (level >= SH_CONNECT)
+		helper_connect();
+
+	if (level >= SH_TRANS)
+		helper_begin_transaction();
+}
diff --git a/libsemanage/tests/utilities.h b/libsemanage/tests/utilities.h
index 781867d1..c9d54d1e 100644
--- a/libsemanage/tests/utilities.h
+++ b/libsemanage/tests/utilities.h
@@ -1,6 +1,7 @@
 /* Authors: Christopher Ashworth <cashworth@tresys.com>
  *
  * Copyright (C) 2006 Tresys Technology, LLC
+ * Copyright (C) 2019 Red Hat, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,55 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include "handle.h"
+#ifndef __UTILITIES_H__
+#define __UTILITIES_H__
 
-void test_msg_handler(void *varg, semanage_handle_t * handle, const char *fmt,
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fts.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <CUnit/Basic.h>
+
+#include "semanage/semanage.h"
+
+#define CU_ASSERT_CONTEXT_EQUAL(CON1,CON2) \
+	do { \
+		char *__str; \
+		char *__str2; \
+		CU_ASSERT(semanage_context_to_string(sh, CON1, &__str) >= 0); \
+		CU_ASSERT(semanage_context_to_string(sh, CON2, &__str2) >= 0); \
+		CU_ASSERT_STRING_EQUAL(__str, __str2); \
+	} while (0)
+
+#define I_NULL  -1
+#define I_FIRST  0
+#define I_SECOND 1
+#define I_THIRD  2
+
+typedef enum { SH_NULL, SH_HANDLE, SH_CONNECT, SH_TRANS } level_t;
+
+void test_msg_handler(void *varg, semanage_handle_t *handle, const char *fmt,
 		      ...);
+
+void setup_handle(level_t level);
+void cleanup_handle(level_t level);
+void setup_handle_invalid_store(level_t level);
+
+void helper_handle_create(void);
+void helper_handle_destroy(void);
+void helper_connect(void);
+void helper_disconnect(void);
+void helper_begin_transaction(void);
+void helper_commit(void);
+
+int create_test_store(void);
+int write_test_policy_from_file(const char *filename);
+int write_test_policy_src(unsigned char *data, unsigned int data_len);
+int destroy_test_store(void);
+void enable_test_store(void);
+void disable_test_store(void);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/11] libsemanage: test semanage_handle_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
  2019-06-12  8:03 ` [PATCH 01/11] libsemanage: add helper functions to tests Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:03 ` [PATCH 03/11] libsemanage: test semanage_bool_* functions Jan Zarsky
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_handle_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_handle.c       | 329 ++++++++++++++++++++++++++
 libsemanage/tests/test_handle.cil     |  21 ++
 libsemanage/tests/test_handle.h       |  30 +++
 4 files changed, 382 insertions(+)
 create mode 100644 libsemanage/tests/test_handle.c
 create mode 100644 libsemanage/tests/test_handle.cil
 create mode 100644 libsemanage/tests/test_handle.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index 048751b8..0fb3991b 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -21,6 +21,7 @@
 
 #include "test_semanage_store.h"
 #include "test_utilities.h"
+#include "test_handle.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -59,6 +60,7 @@ static bool do_tests(int interactive, int verbose)
 
 	DECLARE_SUITE(semanage_store);
 	DECLARE_SUITE(semanage_utilities);
+	DECLARE_SUITE(handle);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_handle.c b/libsemanage/tests/test_handle.c
new file mode 100644
index 00000000..2fab29be
--- /dev/null
+++ b/libsemanage/tests/test_handle.c
@@ -0,0 +1,329 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_handle.h"
+
+void test_handle_create(void);
+void test_connect(void);
+void test_disconnect(void);
+void test_transaction(void);
+void test_commit(void);
+void test_is_connected(void);
+void test_access_check(void);
+void test_is_managed(void);
+void test_mls_enabled(void);
+void test_msg_set_callback(void);
+void test_root(void);
+void test_select_store(void);
+
+extern semanage_handle_t *sh;
+
+int handle_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_handle.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int handle_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int handle_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "test_handle_create", test_handle_create);
+	CU_add_test(suite, "test_connect", test_connect);
+	CU_add_test(suite, "test_disconnect", test_disconnect);
+	CU_add_test(suite, "test_transaction", test_transaction);
+	CU_add_test(suite, "test_commit", test_commit);
+	CU_add_test(suite, "test_is_connected", test_is_connected);
+	CU_add_test(suite, "test_access_check", test_access_check);
+	CU_add_test(suite, "test_is_managed", test_is_managed);
+	CU_add_test(suite, "test_mls_enabled", test_mls_enabled);
+	CU_add_test(suite, "msg_set_callback", test_msg_set_callback);
+	CU_add_test(suite, "test_root", test_root);
+	CU_add_test(suite, "test_select_store", test_select_store);
+
+	return 0;
+}
+
+/* Function semanage_handle_create */
+void test_handle_create(void)
+{
+	sh = semanage_handle_create();
+	CU_ASSERT_PTR_NOT_NULL(sh);
+	semanage_handle_destroy(sh);
+}
+
+/* Function semanage_connect */
+void test_connect(void)
+{
+	/* test handle created */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_connect(sh) >= 0);
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* test invalid store */
+	setup_handle_invalid_store(SH_HANDLE);
+	CU_ASSERT(semanage_connect(sh) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* test normal use */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_connect(sh) >= 0);
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+	cleanup_handle(SH_HANDLE);
+}
+
+/* Function semanage_disconnect */
+void test_disconnect(void)
+{
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+	cleanup_handle(SH_HANDLE);
+}
+
+/* Function semanage_begin_transaction */
+void test_transaction(void)
+{
+	/* test disconnected */
+	setup_handle(SH_CONNECT);
+	helper_disconnect();
+	CU_ASSERT(semanage_begin_transaction(sh) < 0);
+
+	cleanup_handle(SH_HANDLE);
+
+	/* test normal use */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_begin_transaction(sh) >= 0);
+	CU_ASSERT(semanage_commit(sh) >= 0);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_commit */
+void test_commit(void)
+{
+	/* test without transaction */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_commit(sh) < 0);
+
+	/* test with transaction */
+	helper_begin_transaction();
+	CU_ASSERT(semanage_commit(sh) >= 0);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_is_connected */
+void test_is_connected(void)
+{
+	/* test disconnected */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_is_connected(sh) == 0);
+
+	/* test connected */
+	helper_connect();
+	CU_ASSERT(semanage_is_connected(sh) == 1);
+
+	/* test in transaction */
+	helper_begin_transaction();
+	CU_ASSERT(semanage_is_connected(sh) == 1);
+
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_access_check */
+void test_access_check(void)
+{
+	int res = 0;
+
+	/* test with handle */
+	setup_handle(SH_HANDLE);
+	res = semanage_access_check(sh);
+	CU_ASSERT(res == 0 || res == SEMANAGE_CAN_READ
+		  || res == SEMANAGE_CAN_WRITE);
+	cleanup_handle(SH_HANDLE);
+
+	/* test with invalid store */
+	setup_handle_invalid_store(SH_HANDLE);
+	CU_ASSERT(semanage_access_check(sh) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* test connected */
+	setup_handle(SH_CONNECT);
+	res = semanage_access_check(sh);
+	CU_ASSERT(res == 0 || res == SEMANAGE_CAN_READ
+		  || res == SEMANAGE_CAN_WRITE);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_is_managed */
+void test_is_managed(void)
+{
+	int res = 0;
+
+	/* test with handle */
+	setup_handle(SH_HANDLE);
+	res = semanage_is_managed(sh);
+	CU_ASSERT(res == 0 || res == 1);
+
+	/* test connected */
+	helper_connect();
+	res = semanage_is_managed(sh);
+	CU_ASSERT(res < 0);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_mls_enabled */
+void test_mls_enabled(void)
+{
+	int res = 0;
+
+	/* test with handle */
+	setup_handle(SH_HANDLE);
+	res = semanage_mls_enabled(sh);
+	CU_ASSERT(res == 0 || res == 1);
+	cleanup_handle(SH_HANDLE);
+
+	/* test with invalid store */
+	setup_handle_invalid_store(SH_HANDLE);
+	CU_ASSERT(semanage_mls_enabled(sh) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* test connected */
+	setup_handle(SH_CONNECT);
+	res = semanage_mls_enabled(sh);
+	CU_ASSERT(res == 0 || res == 1);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_set_callback */
+int msg_set_callback_count = 0;
+
+void helper_msg_set_callback(void *varg, semanage_handle_t *handle,
+			     const char *fmt, ...)
+{
+	msg_set_callback_count++;
+}
+
+void test_msg_set_callback(void)
+{
+	setup_handle(SH_CONNECT);
+
+	semanage_msg_set_callback(sh, helper_msg_set_callback, NULL);
+
+	/* produce error message */
+	semanage_commit(sh);
+	CU_ASSERT(msg_set_callback_count == 1);
+	semanage_msg_set_callback(sh, NULL, NULL);
+
+	/* produce error message */
+	semanage_commit(sh);
+	CU_ASSERT(msg_set_callback_count == 1);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_root, semanage_set_root */
+void helper_root(void)
+{
+	const char *root = NULL;
+
+	CU_ASSERT(semanage_set_root("asdf") >= 0);
+	root = semanage_root();
+	CU_ASSERT_STRING_EQUAL(root, "asdf");
+
+	CU_ASSERT(semanage_set_root("") >= 0);
+	root = semanage_root();
+	CU_ASSERT_STRING_EQUAL(root, "");
+}
+
+void test_root(void)
+{
+	/* test without handle */
+	setup_handle(SH_NULL);
+	helper_root();
+
+	/* test with handle */
+	helper_handle_create();
+	helper_root();
+
+	/* test connected */
+	helper_connect();
+	helper_root();
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_select_store */
+void helper_select_store(const char *name, enum semanage_connect_type type,
+			 int exp_res)
+{
+	setup_handle(SH_HANDLE);
+
+	/* FIXME: the storename parameter of semanage_select_store should be
+	 * 'const char *'
+	 */
+	semanage_select_store(sh, (char *) name, type);
+
+	int res = semanage_connect(sh);
+
+	if (exp_res < 0) {
+		CU_ASSERT(res < 0);
+	} else {
+		CU_ASSERT(res >= 0);
+	}
+
+	if (res >= 0)
+		cleanup_handle(SH_CONNECT);
+	else
+		cleanup_handle(SH_HANDLE);
+}
+
+void test_select_store(void)
+{
+	helper_select_store("asdf", SEMANAGE_CON_INVALID - 1, -1);
+	helper_select_store("asdf", SEMANAGE_CON_POLSERV_REMOTE + 1, -1);
+	helper_select_store("", SEMANAGE_CON_DIRECT, 0);
+
+	helper_select_store("asdf", SEMANAGE_CON_INVALID, -1);
+	helper_select_store("asdf", SEMANAGE_CON_DIRECT, 0);
+	helper_select_store("asdf", SEMANAGE_CON_POLSERV_LOCAL, -1);
+	helper_select_store("asdf", SEMANAGE_CON_POLSERV_REMOTE, -1);
+}
diff --git a/libsemanage/tests/test_handle.cil b/libsemanage/tests/test_handle.cil
new file mode 100644
index 00000000..81690b88
--- /dev/null
+++ b/libsemanage/tests/test_handle.cil
@@ -0,0 +1,21 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r test_t)
+(type test_t)
+(sidcontext security (system_u object_r test_t ((s0) (s0))))
+(class test_class (test_perm))
+(classorder (test_class))
+(allow test_t self (test_class (test_perm)))
diff --git a/libsemanage/tests/test_handle.h b/libsemanage/tests/test_handle.h
new file mode 100644
index 00000000..f927bd6a
--- /dev/null
+++ b/libsemanage/tests/test_handle.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_HANDLE_H__
+#define __TEST_HANDLE_H__
+
+#include <CUnit/Basic.h>
+
+int handle_test_init(void);
+int handle_test_cleanup(void);
+int handle_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/11] libsemanage: test semanage_bool_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
  2019-06-12  8:03 ` [PATCH 01/11] libsemanage: add helper functions to tests Jan Zarsky
  2019-06-12  8:03 ` [PATCH 02/11] libsemanage: test semanage_handle_* functions Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:03 ` [PATCH 04/11] libsemanage: test semanage_fcontext functions Jan Zarsky
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_bool_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_bool.c         | 932 ++++++++++++++++++++++++++
 libsemanage/tests/test_bool.cil       |  24 +
 libsemanage/tests/test_bool.h         |  31 +
 4 files changed, 989 insertions(+)
 create mode 100644 libsemanage/tests/test_bool.c
 create mode 100644 libsemanage/tests/test_bool.cil
 create mode 100644 libsemanage/tests/test_bool.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index 0fb3991b..83754fe4 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -22,6 +22,7 @@
 #include "test_semanage_store.h"
 #include "test_utilities.h"
 #include "test_handle.h"
+#include "test_bool.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -61,6 +62,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(semanage_store);
 	DECLARE_SUITE(semanage_utilities);
 	DECLARE_SUITE(handle);
+	DECLARE_SUITE(bool);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_bool.c b/libsemanage/tests/test_bool.c
new file mode 100644
index 00000000..dbcdeddb
--- /dev/null
+++ b/libsemanage/tests/test_bool.c
@@ -0,0 +1,932 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_bool.h"
+
+#define BOOL_COUNT 3
+#define BOOL1_NAME "first_bool"
+#define BOOL1_VALUE 1
+#define BOOL2_NAME "second_bool"
+#define BOOL2_VALUE 0
+#define BOOL3_NAME "third_bool"
+#define BOOL3_VALUE 0
+#define BOOL_NONEXISTENT "asdf"
+
+/* boolean_record.h */
+void test_bool_key_create(void);
+void test_bool_key_extract(void);
+void test_bool_compare(void);
+void test_bool_compare2(void);
+void test_bool_get_set_name(void);
+void test_bool_get_set_value(void);
+void test_bool_create(void);
+void test_bool_clone(void);
+
+/* booleans_policy.h */
+void test_bool_query(void);
+void test_bool_exists(void);
+void test_bool_count(void);
+void test_bool_iterate(void);
+void test_bool_list(void);
+
+/* booleans_local.h */
+void test_bool_modify_del_local(void);
+void test_bool_query_local(void);
+void test_bool_exists_local(void);
+void test_bool_count_local(void);
+void test_bool_iterate_local(void);
+void test_bool_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int bool_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_bool.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int bool_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int bool_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "bool_key_create", test_bool_key_create);
+	CU_add_test(suite, "bool_key_extract", test_bool_key_extract);
+	CU_add_test(suite, "bool_compare", test_bool_compare);
+	CU_add_test(suite, "bool_compare2", test_bool_compare2);
+	CU_add_test(suite, "bool_get_set_name", test_bool_get_set_name);
+	CU_add_test(suite, "bool_get_set_value", test_bool_get_set_value);
+	CU_add_test(suite, "bool_create", test_bool_create);
+	CU_add_test(suite, "bool_clone", test_bool_clone);
+
+	CU_add_test(suite, "bool_query", test_bool_query);
+	CU_add_test(suite, "bool_exists", test_bool_exists);
+	CU_add_test(suite, "bool_count", test_bool_count);
+	CU_add_test(suite, "bool_iterate", test_bool_iterate);
+	CU_add_test(suite, "bool_list", test_bool_list);
+
+	CU_add_test(suite, "bool_modify_del_local", test_bool_modify_del_local);
+	CU_add_test(suite, "bool_query_local", test_bool_query_local);
+	CU_add_test(suite, "bool_exists_local", test_bool_exists_local);
+	CU_add_test(suite, "bool_count_local", test_bool_count_local);
+	CU_add_test(suite, "bool_iterate_local", test_bool_iterate_local);
+	CU_add_test(suite, "bool_list_local", test_bool_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_bool_t *get_bool_nth(int idx)
+{
+	int res;
+	semanage_bool_t **records;
+	semanage_bool_t *boolean;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	res = semanage_bool_list(sh, &records, &count);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	boolean = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_bool_free(records[i]);
+
+	return boolean;
+}
+
+semanage_bool_t *get_bool_new(void)
+{
+	int res;
+	semanage_bool_t *boolean;
+
+	res = semanage_bool_create(sh, &boolean);
+
+	CU_ASSERT_FATAL(res >= 0);
+
+	return boolean;
+}
+
+semanage_bool_key_t *get_bool_key_nth(int idx)
+{
+	semanage_bool_key_t *key;
+	semanage_bool_t *boolean;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	boolean = get_bool_nth(idx);
+
+	res = semanage_bool_key_extract(sh, boolean, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+semanage_bool_key_t *get_bool_key_from_str(const char *str)
+{
+	semanage_bool_key_t *key;
+	int res;
+
+	if (str == NULL)
+		return NULL;
+
+	res = semanage_bool_key_create(sh, str, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_bool(const char *name)
+{
+	semanage_bool_t *boolean;
+	semanage_bool_key_t *key = NULL;
+
+	CU_ASSERT_PTR_NOT_NULL_FATAL(name);
+
+	CU_ASSERT_FATAL(semanage_bool_key_create(sh, name, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_bool_query(sh, key, &boolean) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(boolean);
+
+	CU_ASSERT_FATAL(semanage_bool_modify_local(sh, key, boolean) >= 0);
+}
+
+void delete_local_bool(const char *name)
+{
+	semanage_bool_key_t *key = NULL;
+
+	CU_ASSERT_PTR_NOT_NULL_FATAL(name);
+
+	CU_ASSERT_FATAL(semanage_bool_key_create(sh, name, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_bool_del_local(sh, key) >= 0);
+}
+
+/* Function bool_key_create */
+
+void helper_bool_key_create(level_t level)
+{
+	semanage_bool_key_t *key = NULL;
+
+	setup_handle(level);
+
+	CU_ASSERT(semanage_bool_key_create(sh, "", &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	semanage_bool_key_free(key);
+
+	key = NULL;
+
+	CU_ASSERT(semanage_bool_key_create(sh, "testbool", &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	semanage_bool_key_free(key);
+
+	cleanup_handle(level);
+}
+
+void test_bool_key_create(void)
+{
+	helper_bool_key_create(SH_CONNECT);
+	helper_bool_key_create(SH_TRANS);
+}
+
+/* Function bool_key_extract */
+#define SK_NULL 1
+#define SK_NEW 2
+#define SK_INDEX 3
+#define SK_KEY_NULL 4
+void helper_bool_key_extract(level_t level, int mode)
+{
+	semanage_bool_t *boolean = NULL;
+	semanage_bool_key_t *key = NULL;
+	int res;
+
+	setup_handle(level);
+
+	switch (mode) {
+	case SK_NULL:
+		boolean = NULL;
+		break;
+	case SK_NEW:
+		boolean = get_bool_new();
+		break;
+	case SK_INDEX:
+		boolean = get_bool_nth(0);
+		break;
+	case SK_KEY_NULL:
+		boolean = get_bool_nth(0);
+		break;
+	default:
+		CU_FAIL_FATAL("Invalid mode\n");
+	}
+
+	if (mode == SK_KEY_NULL)
+		res = semanage_bool_key_extract(sh, boolean, NULL);
+	else
+		res = semanage_bool_key_extract(sh, boolean, &key);
+
+	CU_ASSERT(res >= 0);
+
+	res = semanage_bool_compare(boolean, key);
+
+	CU_ASSERT(res == 0);
+
+	semanage_bool_key_free(key);
+	semanage_bool_free(boolean);
+
+	cleanup_handle(level);
+}
+
+void test_bool_key_extract(void)
+{
+	helper_bool_key_extract(SH_CONNECT, SK_INDEX);
+	helper_bool_key_extract(SH_TRANS, SK_INDEX);
+}
+#undef SK_NULL
+#undef SK_NEW
+#undef SK_INDEX
+#undef SK_KEY_NULL
+
+/* Function bool_compare */
+void helper_bool_compare(level_t level, int bool_idx1, int bool_idx2)
+{
+	semanage_bool_t *boolean;
+	semanage_bool_key_t *key;
+	int res;
+
+	setup_handle(level);
+
+	boolean = get_bool_nth(bool_idx1);
+	key = get_bool_key_nth(bool_idx2);
+
+	res = semanage_bool_compare(boolean, key);
+
+	if (bool_idx1 == bool_idx2) {
+		CU_ASSERT(res == 0);
+	} else {
+		CU_ASSERT(res != 0);
+	}
+
+	semanage_bool_free(boolean);
+	semanage_bool_key_free(key);
+	cleanup_handle(level);
+}
+
+void test_bool_compare(void)
+{
+	helper_bool_compare(SH_CONNECT, I_FIRST,  I_FIRST);
+	helper_bool_compare(SH_CONNECT, I_FIRST,  I_SECOND);
+	helper_bool_compare(SH_CONNECT, I_SECOND, I_FIRST);
+	helper_bool_compare(SH_CONNECT, I_SECOND, I_SECOND);
+
+	helper_bool_compare(SH_TRANS, I_FIRST,  I_FIRST);
+	helper_bool_compare(SH_TRANS, I_FIRST,  I_SECOND);
+	helper_bool_compare(SH_TRANS, I_SECOND, I_FIRST);
+	helper_bool_compare(SH_TRANS, I_SECOND, I_SECOND);
+}
+
+/* Function bool_compare2 */
+void helper_bool_compare2(level_t level, int bool_idx1, int bool_idx2)
+{
+	semanage_bool_t *bool1;
+	semanage_bool_t *bool2;
+	int res;
+
+	setup_handle(level);
+
+	bool1 = get_bool_nth(bool_idx1);
+	bool2 = get_bool_nth(bool_idx2);
+
+	res = semanage_bool_compare2(bool1, bool2);
+
+	if (bool_idx1 == bool_idx2) {
+		CU_ASSERT(res == 0);
+	} else {
+		CU_ASSERT(res != 0);
+	}
+
+	semanage_bool_free(bool1);
+	semanage_bool_free(bool2);
+	cleanup_handle(level);
+}
+
+void test_bool_compare2(void)
+{
+	helper_bool_compare2(SH_CONNECT, I_FIRST,  I_FIRST);
+	helper_bool_compare2(SH_CONNECT, I_FIRST,  I_SECOND);
+	helper_bool_compare2(SH_CONNECT, I_SECOND, I_FIRST);
+	helper_bool_compare2(SH_CONNECT, I_SECOND, I_SECOND);
+
+	helper_bool_compare2(SH_TRANS, I_FIRST,  I_FIRST);
+	helper_bool_compare2(SH_TRANS, I_FIRST,  I_SECOND);
+	helper_bool_compare2(SH_TRANS, I_SECOND, I_FIRST);
+	helper_bool_compare2(SH_TRANS, I_SECOND, I_SECOND);
+}
+
+/* Function bool_get_name, bool_set_name */
+void helper_bool_get_set_name(level_t level, int bool_idx, const char *name)
+{
+	semanage_bool_t *boolean;
+	const char *new_name = NULL;
+
+	setup_handle(level);
+
+	boolean = get_bool_nth(bool_idx);
+
+	CU_ASSERT(semanage_bool_set_name(sh, boolean, name) >= 0);
+
+	new_name = semanage_bool_get_name(boolean);
+
+	CU_ASSERT_PTR_NOT_NULL(new_name);
+	/* Use assert to silence the clang analyzer */
+	assert(new_name);
+	CU_ASSERT_STRING_EQUAL(new_name, name);
+
+	semanage_bool_free(boolean);
+	cleanup_handle(level);
+}
+
+void test_bool_get_set_name(void)
+{
+	helper_bool_get_set_name(SH_CONNECT, I_FIRST, "testbool");
+	helper_bool_get_set_name(SH_CONNECT, I_FIRST, "");
+	helper_bool_get_set_name(SH_CONNECT, I_SECOND, "testbool");
+	helper_bool_get_set_name(SH_CONNECT, I_SECOND, "");
+
+	helper_bool_get_set_name(SH_TRANS, I_FIRST, "testbool");
+	helper_bool_get_set_name(SH_TRANS, I_FIRST, "");
+	helper_bool_get_set_name(SH_TRANS, I_SECOND, "testbool");
+	helper_bool_get_set_name(SH_TRANS, I_SECOND, "");
+}
+
+/* Function bool_get_value, bool_set_value */
+void helper_bool_get_set_value(int bool_idx, int val)
+{
+	semanage_bool_t *boolean;
+	int new_val = 0;
+
+	setup_handle(SH_CONNECT);
+	boolean = get_bool_nth(bool_idx);
+	cleanup_handle(SH_CONNECT);
+
+	semanage_bool_set_value(boolean, val);
+
+	new_val = semanage_bool_get_value(boolean);
+
+	CU_ASSERT(new_val == val);
+
+	semanage_bool_free(boolean);
+}
+
+void test_bool_get_set_value(void)
+{
+	helper_bool_get_set_value(I_FIRST, 1);
+	helper_bool_get_set_value(I_FIRST, 0);
+	helper_bool_get_set_value(I_SECOND, 1);
+	helper_bool_get_set_value(I_SECOND, 0);
+}
+
+/* Function bool_create */
+void helper_bool_create(level_t level)
+{
+	semanage_bool_t *boolean;
+
+	setup_handle(level);
+
+	CU_ASSERT(semanage_bool_create(sh, &boolean) >= 0);
+
+	CU_ASSERT_PTR_NULL(semanage_bool_get_name(boolean));
+	CU_ASSERT(semanage_bool_get_value(boolean) == 0);
+
+	cleanup_handle(level);
+}
+
+void test_bool_create(void)
+{
+	helper_bool_create(SH_HANDLE);
+	helper_bool_create(SH_CONNECT);
+	helper_bool_create(SH_TRANS);
+}
+
+/* Function bool_clone */
+void helper_bool_clone(level_t level, int bool_idx)
+{
+	semanage_bool_t *boolean;
+	semanage_bool_t *boolean_clone;
+	const char *str;
+	const char *str_clone;
+	int val;
+	int val_clone;
+
+	setup_handle(level);
+
+	boolean = get_bool_nth(bool_idx);
+
+	CU_ASSERT(semanage_bool_clone(sh, boolean, &boolean_clone) >= 0);
+
+	str = semanage_bool_get_name(boolean);
+	str_clone = semanage_bool_get_name(boolean_clone);
+
+	CU_ASSERT_STRING_EQUAL(str, str_clone);
+
+	val = semanage_bool_get_value(boolean);
+	val_clone = semanage_bool_get_value(boolean_clone);
+
+	CU_ASSERT_EQUAL(val, val_clone);
+
+	cleanup_handle(level);
+}
+
+void test_bool_clone(void)
+{
+	helper_bool_clone(SH_CONNECT, I_FIRST);
+	helper_bool_clone(SH_CONNECT, I_SECOND);
+
+	helper_bool_clone(SH_TRANS, I_FIRST);
+	helper_bool_clone(SH_TRANS, I_SECOND);
+}
+
+/* Function bool_query */
+void helper_bool_query(level_t level, const char *bool_str, int exp_res)
+{
+	semanage_bool_key_t *key;
+	semanage_bool_t *resp = (void *) 42;
+
+	setup_handle(level);
+
+	key = get_bool_key_from_str(bool_str);
+
+	CU_ASSERT(semanage_bool_query(sh, key, &resp) >= 0);
+
+	if (exp_res >= 0) {
+		const char *name = semanage_bool_get_name(resp);
+		CU_ASSERT_STRING_EQUAL(name, bool_str);
+	} else {
+		CU_ASSERT_PTR_NULL(resp);
+	}
+
+	cleanup_handle(level);
+}
+
+void test_bool_query(void)
+{
+	helper_bool_query(SH_CONNECT, BOOL1_NAME,  1);
+	helper_bool_query(SH_CONNECT, BOOL2_NAME, 1);
+	helper_bool_query(SH_CONNECT, BOOL_NONEXISTENT, -1);
+
+	helper_bool_query(SH_TRANS, BOOL1_NAME,  1);
+	helper_bool_query(SH_TRANS, BOOL2_NAME, 1);
+	helper_bool_query(SH_TRANS, BOOL_NONEXISTENT, -1);
+}
+
+/* Functon bool_exists */
+void helper_bool_exists(level_t level, const char *bool_str, int exp_resp)
+{
+	semanage_bool_key_t *key;
+	int resp;
+
+	setup_handle(level);
+
+	key = get_bool_key_from_str(bool_str);
+
+	CU_ASSERT(semanage_bool_exists(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == exp_resp);
+
+	semanage_bool_key_free(key);
+
+	cleanup_handle(level);
+}
+
+void test_bool_exists(void)
+{
+	helper_bool_exists(SH_CONNECT, BOOL1_NAME,  1);
+	helper_bool_exists(SH_CONNECT, BOOL2_NAME, 1);
+	helper_bool_exists(SH_CONNECT, BOOL_NONEXISTENT, 0);
+
+	helper_bool_exists(SH_TRANS, BOOL1_NAME,  1);
+	helper_bool_exists(SH_TRANS, BOOL2_NAME, 1);
+	helper_bool_exists(SH_TRANS, BOOL_NONEXISTENT, 0);
+}
+
+/* Function bool_count */
+void test_bool_count(void)
+{
+	unsigned int resp;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_bool_count(sh, &resp) < 0);
+	CU_ASSERT(semanage_bool_count(sh, NULL) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	resp = 0;
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_bool_count(sh, &resp) >= 0);
+	CU_ASSERT(resp == BOOL_COUNT);
+	cleanup_handle(SH_CONNECT);
+
+	/* trans */
+	resp = 0;
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_bool_count(sh, &resp) >= 0);
+	CU_ASSERT(resp == BOOL_COUNT);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function bool_iterate */
+unsigned int counter_bool_iterate = 0;
+
+int handler_bool_iterate(const semanage_bool_t *record, void *varg)
+{
+	counter_bool_iterate++;
+	return 0;
+}
+
+void helper_bool_iterate_invalid(void)
+{
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_bool_iterate(sh, &handler_bool_iterate, NULL) < 0);
+	CU_ASSERT(semanage_bool_iterate(sh, NULL, NULL) < 0);
+	cleanup_handle(SH_HANDLE);
+}
+
+void helper_bool_iterate(level_t level)
+{
+	setup_handle(level);
+	counter_bool_iterate = 0;
+	CU_ASSERT(semanage_bool_iterate(sh, &handler_bool_iterate, NULL) >= 0);
+	CU_ASSERT(counter_bool_iterate == BOOL_COUNT);
+	cleanup_handle(level);
+}
+
+void test_bool_iterate(void)
+{
+	helper_bool_iterate_invalid();
+	helper_bool_iterate(SH_CONNECT);
+	helper_bool_iterate(SH_TRANS);
+}
+
+/* Function bool_list */
+void helper_bool_list_invalid(void)
+{
+	semanage_bool_t **records;
+	unsigned int count;
+
+	setup_handle(SH_HANDLE);
+
+	CU_ASSERT(semanage_bool_list(sh, &records, &count) < 0);
+	CU_ASSERT(semanage_bool_list(sh, NULL, &count) < 0);
+	CU_ASSERT(semanage_bool_list(sh, &records, NULL) < 0);
+
+	cleanup_handle(SH_HANDLE);
+}
+
+void helper_bool_list(level_t level)
+{
+	semanage_bool_t **records;
+	unsigned int count;
+
+	setup_handle(level);
+
+	CU_ASSERT(semanage_bool_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == BOOL_COUNT);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	for (unsigned int i = 0; i < count; i++)
+		semanage_bool_free(records[i]);
+
+	cleanup_handle(level);
+}
+
+void test_bool_list(void)
+{
+	helper_bool_list_invalid();
+	helper_bool_list(SH_CONNECT);
+	helper_bool_list(SH_TRANS);
+}
+
+/* Function bool_modify_local, bool_del_local */
+void helper_bool_modify_del_local(level_t level, const char *name,
+				  int old_val, int exp_res)
+{
+	semanage_bool_t *boolean;
+	semanage_bool_t *boolean_local;
+	semanage_bool_key_t *key = NULL;
+	int res;
+	int new_val;
+
+	/* setup */
+	setup_handle(level);
+
+	CU_ASSERT(semanage_bool_key_create(sh, name, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	CU_ASSERT(semanage_bool_query(sh, key, &boolean) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(boolean);
+
+	new_val = !old_val;
+	semanage_bool_set_value(boolean, new_val);
+
+	/* test */
+	res = semanage_bool_modify_local(sh, key, boolean);
+
+	if (exp_res < 0) {
+		CU_ASSERT(res < 0);
+	} else {
+		CU_ASSERT(res >= 0);
+
+		/* write changes to file */
+		if (level == SH_TRANS) {
+			helper_commit();
+			helper_begin_transaction();
+		}
+
+		CU_ASSERT(semanage_bool_query_local(sh, key,
+					            &boolean_local) >= 0);
+		CU_ASSERT(semanage_bool_compare2(boolean_local, boolean) == 0);
+		CU_ASSERT(semanage_bool_del_local(sh, key) >= 0);
+		CU_ASSERT(semanage_bool_query_local(sh, key,
+						    &boolean_local) < 0);
+	}
+
+	/* cleanup */
+	semanage_bool_key_free(key);
+	semanage_bool_free(boolean);
+
+	cleanup_handle(level);
+}
+
+void test_bool_modify_del_local(void)
+{
+	helper_bool_modify_del_local(SH_CONNECT, BOOL1_NAME, BOOL1_VALUE, -1);
+	helper_bool_modify_del_local(SH_CONNECT, BOOL2_NAME, BOOL2_VALUE, -1);
+	helper_bool_modify_del_local(SH_TRANS, BOOL1_NAME, BOOL1_VALUE, 1);
+	helper_bool_modify_del_local(SH_TRANS, BOOL2_NAME, BOOL2_VALUE, 1);
+}
+
+/* Function bool_query_local */
+void test_bool_query_local(void)
+{
+	semanage_bool_key_t *key = NULL;
+	semanage_bool_t *resp = NULL;
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_bool_key_create(sh, BOOL1_NAME, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	CU_ASSERT(semanage_bool_query_local(sh, key, &resp) < 0);
+	CU_ASSERT_PTR_NULL(resp);
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_bool_key_create(sh, BOOL1_NAME, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	CU_ASSERT(semanage_bool_query_local(sh, key, &resp) < 0);
+	CU_ASSERT_PTR_NULL(resp);
+
+	add_local_bool(BOOL1_NAME);
+	CU_ASSERT(semanage_bool_query_local(sh, key, &resp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(resp);
+
+	semanage_bool_key_free(key);
+	CU_ASSERT(semanage_bool_key_create(sh, BOOL2_NAME, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	add_local_bool(BOOL2_NAME);
+	CU_ASSERT(semanage_bool_query_local(sh, key, &resp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(resp);
+
+	/* cleanup */
+	delete_local_bool(BOOL1_NAME);
+	delete_local_bool(BOOL2_NAME);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function bool_exists_local */
+void test_bool_exists_local(void)
+{
+	int resp = -1;
+	semanage_bool_key_t *key;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_bool_key_create(sh, BOOL1_NAME, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* test */
+	CU_ASSERT(semanage_bool_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	add_local_bool(BOOL1_NAME);
+	resp = -1;
+	CU_ASSERT(semanage_bool_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 1);
+
+	delete_local_bool(BOOL1_NAME);
+	resp = -1;
+	CU_ASSERT(semanage_bool_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function bool_count_local */
+void test_bool_count_local(void)
+{
+	unsigned int resp;
+	unsigned int init_count;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	init_count = resp;
+
+	add_local_bool(BOOL1_NAME);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == init_count + 1);
+
+	add_local_bool(BOOL2_NAME);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == init_count + 2);
+
+	delete_local_bool(BOOL2_NAME);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == init_count + 1);
+
+	delete_local_bool(BOOL1_NAME);
+	CU_ASSERT(semanage_bool_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == init_count);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function bool_iterate_local */
+unsigned int counter_bool_iterate_local = 0;
+
+int handler_bool_iterate_local(const semanage_bool_t *record, void *varg)
+{
+	counter_bool_iterate_local++;
+	return 0;
+}
+
+void test_bool_iterate_local(void)
+{
+	unsigned int init_count;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_bool_iterate_local(sh, &handler_bool_iterate_local,
+					      NULL) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+
+	counter_bool_iterate_local = 0;
+	CU_ASSERT(semanage_bool_iterate_local(sh, &handler_bool_iterate_local,
+					      NULL) >= 0);
+	init_count = counter_bool_iterate_local;
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	counter_bool_iterate_local = 0;
+	CU_ASSERT(semanage_bool_iterate_local(sh, &handler_bool_iterate_local,
+					      NULL) >= 0);
+	CU_ASSERT(counter_bool_iterate_local == init_count);
+
+	add_local_bool(BOOL1_NAME);
+	counter_bool_iterate_local = 0;
+	CU_ASSERT(semanage_bool_iterate_local(sh, &handler_bool_iterate_local,
+					      NULL) >= 0);
+	CU_ASSERT(counter_bool_iterate_local == init_count + 1);
+
+	add_local_bool(BOOL2_NAME);
+	counter_bool_iterate_local = 0;
+	CU_ASSERT(semanage_bool_iterate_local(sh, &handler_bool_iterate_local,
+					      NULL) >= 0);
+	CU_ASSERT(counter_bool_iterate_local == init_count + 2);
+
+	/* cleanup */
+	delete_local_bool(BOOL1_NAME);
+	delete_local_bool(BOOL2_NAME);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Functtion bool_list_local */
+void test_bool_list_local(void)
+{
+	semanage_bool_t **records;
+	unsigned int count;
+	unsigned int init_count;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+
+	CU_ASSERT(semanage_bool_list_local(sh, &records, &count) < 0);
+	CU_ASSERT(semanage_bool_list_local(sh, NULL, &count) < 0);
+	CU_ASSERT(semanage_bool_list_local(sh, &records, NULL) < 0);
+
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+
+	CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
+	init_count = count;
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == init_count);
+
+	add_local_bool(BOOL1_NAME);
+	CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == init_count + 1);
+	CU_ASSERT_PTR_NOT_NULL(records[0]);
+
+	add_local_bool(BOOL2_NAME);
+	CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == init_count + 2);
+	CU_ASSERT_PTR_NOT_NULL(records[0]);
+	CU_ASSERT_PTR_NOT_NULL(records[1]);
+
+	/* cleanup */
+	delete_local_bool(BOOL1_NAME);
+	delete_local_bool(BOOL2_NAME);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_bool.cil b/libsemanage/tests/test_bool.cil
new file mode 100644
index 00000000..4174751c
--- /dev/null
+++ b/libsemanage/tests/test_bool.cil
@@ -0,0 +1,24 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r test_t)
+(type test_t)
+(sidcontext security (system_u object_r test_t ((s0) (s0))))
+(class test_class (test_perm))
+(classorder (test_class))
+(allow test_t self (test_class (test_perm)))
+(boolean first_bool true)
+(boolean second_bool false)
+(boolean third_bool false)
diff --git a/libsemanage/tests/test_bool.h b/libsemanage/tests/test_bool.h
new file mode 100644
index 00000000..b5b5a603
--- /dev/null
+++ b/libsemanage/tests/test_bool.h
@@ -0,0 +1,31 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_BOOL_H__
+#define __TEST_BOOL_H__
+
+#include <CUnit/Basic.h>
+#include "semanage/semanage.h"
+
+int bool_test_init(void);
+int bool_test_cleanup(void);
+int bool_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/11] libsemanage: test semanage_fcontext functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (2 preceding siblings ...)
  2019-06-12  8:03 ` [PATCH 03/11] libsemanage: test semanage_bool_* functions Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:03 ` [PATCH 05/11] libsemanage: test semanage_iface_* functions Jan Zarsky
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_fcontext_* functions. The test suite aims for
line coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |    2 +
 libsemanage/tests/test_fcontext.c     | 1045 +++++++++++++++++++++++++
 libsemanage/tests/test_fcontext.cil   |   25 +
 libsemanage/tests/test_fcontext.h     |   30 +
 4 files changed, 1102 insertions(+)
 create mode 100644 libsemanage/tests/test_fcontext.c
 create mode 100644 libsemanage/tests/test_fcontext.cil
 create mode 100644 libsemanage/tests/test_fcontext.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index 83754fe4..c5f42b9e 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -23,6 +23,7 @@
 #include "test_utilities.h"
 #include "test_handle.h"
 #include "test_bool.h"
+#include "test_fcontext.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -63,6 +64,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(semanage_utilities);
 	DECLARE_SUITE(handle);
 	DECLARE_SUITE(bool);
+	DECLARE_SUITE(fcontext);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_fcontext.c b/libsemanage/tests/test_fcontext.c
new file mode 100644
index 00000000..62af711f
--- /dev/null
+++ b/libsemanage/tests/test_fcontext.c
@@ -0,0 +1,1045 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_fcontext.h"
+
+char FCONTEXTS[] =
+    "/etc/selinux(/.*) -s system_u:object_r:first_t:s0\n"
+    "/etc/selinux/targeted -- system_u:object_r:second_t:s0\n"
+    "/etc/selinux(/.*) -b system_u:object_r:third_t:s0\n";
+unsigned int FCONTEXTS_LEN = sizeof(FCONTEXTS);
+
+#define FCONTEXTS_COUNT 3
+
+#define FCONTEXT1_EXPR "/etc/selinux(/.*)"
+#define FCONTEXT1_TYPE SEMANAGE_FCONTEXT_SOCK
+#define FCONTEXT1_CON "system_u:object_r:first_t:s0"
+
+#define FCONTEXT2_EXPR "/etc/selinux/targeted"
+#define FCONTEXT2_TYPE SEMANAGE_FCONTEXT_REG
+#define FCONTEXT2_CON "system_u:object_r:second_t:s0"
+
+#define FCONTEXT3_EXPR "/etc/selinux(/.*)"
+#define FCONTEXT3_TYPE SEMANAGE_FCONTEXT_BLOCK
+#define FCONTEXT3_CON "system_u:object_r:third_t:s0"
+
+#define FCONTEXT_NONEXISTENT_EXPR "/asdf"
+#define FCONTEXT_NONEXISTENT_TYPE SEMANAGE_FCONTEXT_ALL
+
+/* fcontext_record.h */
+void test_fcontext_compare(void);
+void test_fcontext_compare2(void);
+void test_fcontext_key_create(void);
+void test_fcontext_key_extract(void);
+void test_fcontext_get_set_expr(void);
+void test_fcontext_get_set_type(void);
+void test_fcontext_get_type_str(void);
+void test_fcontext_get_set_con(void);
+void test_fcontext_create(void);
+void test_fcontext_clone(void);
+
+/* fcontext_policy.h */
+void test_fcontext_query(void);
+void test_fcontext_exists(void);
+void test_fcontext_count(void);
+void test_fcontext_iterate(void);
+void test_fcontext_list(void);
+
+/* fcontext_local.h */
+void test_fcontext_modify_del_local(void);
+void test_fcontext_query_local(void);
+void test_fcontext_exists_local(void);
+void test_fcontext_count_local(void);
+void test_fcontext_iterate_local(void);
+void test_fcontext_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int get_type(char *t)
+{
+	if (strcmp(t, "--") == 0)
+		return SEMANAGE_FCONTEXT_ALL;
+	else if (strcmp(t, "-f") == 0)
+		return SEMANAGE_FCONTEXT_REG;
+	else if (strcmp(t, "-d") == 0)
+		return SEMANAGE_FCONTEXT_DIR;
+	else if (strcmp(t, "-c") == 0)
+		return SEMANAGE_FCONTEXT_CHAR;
+	else if (strcmp(t, "-b") == 0)
+		return SEMANAGE_FCONTEXT_BLOCK;
+	else if (strcmp(t, "-s") == 0)
+		return SEMANAGE_FCONTEXT_SOCK;
+	else if (strcmp(t, "-l") == 0)
+		return SEMANAGE_FCONTEXT_LINK;
+	else if (strcmp(t, "-p") == 0)
+		return SEMANAGE_FCONTEXT_PIPE;
+	else
+		return -1;
+}
+
+int write_file_contexts(const char *data, unsigned int data_len)
+{
+	FILE *fptr = fopen("test-policy/store/active/file_contexts", "w+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite(data, data_len, 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	return 0;
+}
+
+int fcontext_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_fcontext.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	if (write_file_contexts(FCONTEXTS, FCONTEXTS_LEN) < 0) {
+		fprintf(stderr, "Could not write file contexts\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int fcontext_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int fcontext_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "test_fcontext_compare", test_fcontext_compare);
+	CU_add_test(suite, "test_fcontext_compare2", test_fcontext_compare2);
+	CU_add_test(suite, "test_fcontext_key_create",
+		    test_fcontext_key_create);
+	CU_add_test(suite, "test_fcontext_key_extract",
+		    test_fcontext_key_extract);
+	CU_add_test(suite, "test_fcontext_get_set_expr",
+		    test_fcontext_get_set_expr);
+	CU_add_test(suite, "test_fcontext_get_set_type",
+		    test_fcontext_get_set_type);
+	CU_add_test(suite, "test_fcontext_get_type_str",
+		    test_fcontext_get_type_str);
+	CU_add_test(suite, "test_fcontext_get_set_con",
+		    test_fcontext_get_set_con);
+	CU_add_test(suite, "test_fcontext_create", test_fcontext_create);
+	CU_add_test(suite, "test_fcontext_clone", test_fcontext_clone);
+
+	CU_add_test(suite, "test_fcontext_query", test_fcontext_query);
+	CU_add_test(suite, "test_fcontext_exists", test_fcontext_exists);
+	CU_add_test(suite, "test_fcontext_count", test_fcontext_count);
+	CU_add_test(suite, "test_fcontext_iterate", test_fcontext_iterate);
+	CU_add_test(suite, "test_fcontext_list", test_fcontext_list);
+	CU_add_test(suite, "test_fcontext_modify_del_local",
+		    test_fcontext_modify_del_local);
+	CU_add_test(suite, "test_fcontext_query_local",
+		    test_fcontext_query_local);
+	CU_add_test(suite, "test_fcontext_exists_local",
+		    test_fcontext_exists_local);
+	CU_add_test(suite, "test_fcontext_count_local",
+		    test_fcontext_count_local);
+	CU_add_test(suite, "test_fcontext_iterate_local",
+		    test_fcontext_iterate_local);
+	CU_add_test(suite, "test_fcontext_list_local",
+		    test_fcontext_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_fcontext_t *get_fcontext_new(void)
+{
+	semanage_fcontext_t *fcontext;
+
+	CU_ASSERT_FATAL(semanage_fcontext_create(sh, &fcontext) >= 0);
+
+	return fcontext;
+}
+
+semanage_fcontext_t *get_fcontext_nth(int idx)
+{
+	semanage_fcontext_t **records;
+	semanage_fcontext_t *fcontext;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	CU_ASSERT_FATAL(semanage_fcontext_list(sh, &records, &count) >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	fcontext = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_fcontext_free(records[i]);
+
+	return fcontext;
+}
+
+semanage_fcontext_key_t *get_fcontext_key_nth(int idx)
+{
+	semanage_fcontext_key_t *key;
+	semanage_fcontext_t *fcontext;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	fcontext = get_fcontext_nth(idx);
+
+	CU_ASSERT_FATAL(semanage_fcontext_key_extract(sh, fcontext, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_fcontext(int fcontext_idx)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(fcontext_idx != I_NULL);
+
+	fcontext = get_fcontext_nth(fcontext_idx);
+
+	CU_ASSERT_FATAL(semanage_fcontext_key_extract(sh, fcontext, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_fcontext_modify_local(sh, key, fcontext) >= 0);
+}
+
+void delete_local_fcontext(int fcontext_idx)
+{
+	semanage_fcontext_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(fcontext_idx != I_NULL);
+
+	key = get_fcontext_key_nth(fcontext_idx);
+
+	CU_ASSERT_FATAL(semanage_fcontext_del_local(sh, key) >= 0);
+}
+
+semanage_fcontext_key_t *get_fcontext_key_from_str(const char *str, int type)
+{
+	semanage_fcontext_key_t *key;
+	int res;
+
+	if (str == NULL)
+		return NULL;
+
+	res = semanage_fcontext_key_create(sh, str, type, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+/* Function semanage_fcontext_compare */
+void test_fcontext_compare(void)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_key_t *key1;
+	semanage_fcontext_key_t *key2;
+	semanage_fcontext_key_t *key3;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	fcontext = get_fcontext_nth(I_FIRST);
+
+	key1 = get_fcontext_key_nth(I_FIRST);
+	key2 = get_fcontext_key_nth(I_SECOND);
+	key3 = get_fcontext_key_nth(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_compare(fcontext, key1) == 0);
+	CU_ASSERT(semanage_fcontext_compare(fcontext, key2) < 0);
+	CU_ASSERT(semanage_fcontext_compare(fcontext, key3) > 0);
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	semanage_fcontext_key_free(key1);
+	semanage_fcontext_key_free(key2);
+	semanage_fcontext_key_free(key3);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_compare2 */
+void test_fcontext_compare2(void)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_t *fcontext1;
+	semanage_fcontext_t *fcontext2;
+	semanage_fcontext_t *fcontext3;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	fcontext = get_fcontext_nth(I_FIRST);
+	fcontext1 = get_fcontext_nth(I_FIRST);
+	fcontext2 = get_fcontext_nth(I_SECOND);
+	fcontext3 = get_fcontext_nth(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_compare2(fcontext, fcontext1) == 0);
+	CU_ASSERT(semanage_fcontext_compare2(fcontext, fcontext2) < 0);
+	CU_ASSERT(semanage_fcontext_compare2(fcontext, fcontext3) > 0);
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	semanage_fcontext_free(fcontext1);
+	semanage_fcontext_free(fcontext2);
+	semanage_fcontext_free(fcontext3);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_key_create */
+void test_fcontext_key_create(void)
+{
+	semanage_fcontext_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_key_create(sh, "", SEMANAGE_FCONTEXT_ALL,
+					       &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	semanage_fcontext_key_free(key);
+
+	key = NULL;
+
+	CU_ASSERT(semanage_fcontext_key_create(sh, "testfcontext",
+					     SEMANAGE_FCONTEXT_ALL, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	semanage_fcontext_key_free(key);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_key_extract */
+void test_fcontext_key_extract(void)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_key_t *key;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	fcontext = get_fcontext_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_key_extract(sh, fcontext, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_fcontext_key_free(key);
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_get_expr, semanage_fcontext_set_expr */
+void test_fcontext_get_set_expr(void)
+{
+	semanage_fcontext_t *fcontext;
+	const char *expr = NULL;
+	const char *expr_exp = "/asdf";
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	fcontext = get_fcontext_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_set_expr(sh, fcontext, expr_exp) >= 0);
+	expr = semanage_fcontext_get_expr(fcontext);
+	CU_ASSERT_PTR_NOT_NULL(expr);
+	assert(expr);
+	CU_ASSERT_STRING_EQUAL(expr, expr_exp);
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_get_type, semanage_fcontext_set_type */
+void test_fcontext_get_set_type(void)
+{
+	semanage_fcontext_t *fcontext;
+	int type_exp = SEMANAGE_FCONTEXT_SOCK;
+	int type;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	fcontext = get_fcontext_nth(I_FIRST);
+
+	/* test */
+	semanage_fcontext_set_type(fcontext, type_exp);
+	type = semanage_fcontext_get_type(fcontext);
+	CU_ASSERT(type == type_exp);
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_fcontext_get_type_str */
+void helper_fcontext_get_type_str(int type, const char *exp_str)
+{
+	CU_ASSERT_STRING_EQUAL(semanage_fcontext_get_type_str(type), exp_str);
+}
+
+void test_fcontext_get_type_str(void)
+{
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_ALL, "all files");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_REG, "regular file");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_DIR, "directory");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_CHAR,
+				     "character device");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_BLOCK, "block device");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_SOCK, "socket");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_LINK, "symbolic link");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_PIPE, "named pipe");
+
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_ALL - 1, "????");
+	helper_fcontext_get_type_str(SEMANAGE_FCONTEXT_PIPE + 1, "????");
+}
+
+/* Function semanage_fcontext_get_con, semanage_fcontext_set_con */
+void helper_fcontext_get_set_con(level_t level, int fcontext_idx,
+				 const char *con_str)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_context_t *con = NULL;
+	semanage_context_t *new_con = NULL;
+
+	/* setup */
+	setup_handle(level);
+	fcontext = get_fcontext_nth(fcontext_idx);
+
+	if (con_str != NULL) {
+		CU_ASSERT(semanage_context_from_string(sh, con_str, &con) >= 0);
+		CU_ASSERT_PTR_NOT_NULL(con);
+	} else {
+		con = NULL;
+	}
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_set_con(sh, fcontext, con) >= 0);
+	new_con = semanage_fcontext_get_con(fcontext);
+
+	if (con_str != NULL) {
+		CU_ASSERT_CONTEXT_EQUAL(con, new_con);
+	} else {
+		CU_ASSERT_PTR_NULL(new_con);
+	}
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(level);
+}
+
+void test_fcontext_get_set_con(void)
+{
+	helper_fcontext_get_set_con(SH_CONNECT, I_FIRST, NULL);
+	helper_fcontext_get_set_con(SH_CONNECT, I_FIRST,
+				    "user_u:role_r:type_t:s0");
+	helper_fcontext_get_set_con(SH_CONNECT, I_SECOND,
+				    "user_u:role_r:type_t:s0");
+	helper_fcontext_get_set_con(SH_TRANS, I_FIRST, NULL);
+	helper_fcontext_get_set_con(SH_TRANS, I_FIRST,
+				    "user_u:role_r:type_t:s0");
+	helper_fcontext_get_set_con(SH_TRANS, I_SECOND,
+				    "user_u:role_r:type_t:s0");
+}
+
+/* Function semanage_fcontext_create */
+void helper_fcontext_create(level_t level)
+{
+	semanage_fcontext_t *fcontext;
+
+	/* setup */
+	setup_handle(level);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_create(sh, &fcontext) >= 0);
+	CU_ASSERT_PTR_NULL(semanage_fcontext_get_expr(fcontext));
+	CU_ASSERT(semanage_fcontext_get_type(fcontext)
+		  == SEMANAGE_FCONTEXT_ALL);
+	CU_ASSERT_PTR_NULL(semanage_fcontext_get_con(fcontext));
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(level);
+}
+
+void test_fcontext_create(void)
+{
+	helper_fcontext_create(SH_NULL);
+	helper_fcontext_create(SH_HANDLE);
+	helper_fcontext_create(SH_CONNECT);
+	helper_fcontext_create(SH_TRANS);
+}
+
+/* Function semanage_fcontext_clone */
+void helper_fcontext_clone(level_t level, int fcontext_idx)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_t *fcontext_clone;
+	const char *expr;
+	const char *expr_clone;
+	int type;
+	int type_clone;
+	semanage_context_t *con;
+	semanage_context_t *con_clone;
+
+	/* setup */
+	setup_handle(level);
+	fcontext = get_fcontext_nth(fcontext_idx);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_clone(sh, fcontext, &fcontext_clone) >= 0);
+
+	expr = semanage_fcontext_get_expr(fcontext);
+	expr_clone = semanage_fcontext_get_expr(fcontext_clone);
+	CU_ASSERT_STRING_EQUAL(expr, expr_clone);
+
+	type = semanage_fcontext_get_type(fcontext);
+	type_clone = semanage_fcontext_get_type(fcontext_clone);
+	CU_ASSERT_EQUAL(type, type_clone);
+
+	con = semanage_fcontext_get_con(fcontext);
+	con_clone = semanage_fcontext_get_con(fcontext_clone);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_clone);
+
+	/* cleanup */
+	semanage_fcontext_free(fcontext);
+	semanage_fcontext_free(fcontext_clone);
+	cleanup_handle(level);
+}
+
+void test_fcontext_clone(void)
+{
+	helper_fcontext_clone(SH_CONNECT, I_FIRST);
+	helper_fcontext_clone(SH_CONNECT, I_SECOND);
+	helper_fcontext_clone(SH_TRANS, I_FIRST);
+	helper_fcontext_clone(SH_TRANS, I_SECOND);
+}
+
+/* Function semanage_fcontext_query */
+void helper_fcontext_query(level_t level, const char *fcontext_expr,
+			   int fcontext_type, int exp_res)
+{
+	semanage_fcontext_key_t *key;
+	semanage_fcontext_t *resp = (void *) 42;
+	int res;
+
+	/* setup */
+	setup_handle(level);
+	key = get_fcontext_key_from_str(fcontext_expr, fcontext_type);
+
+	/* test */
+	res = semanage_fcontext_query(sh, key, &resp);
+
+	if (exp_res >= 0) {
+		CU_ASSERT(res >= 0);
+		const char *expr = semanage_fcontext_get_expr(resp);
+		CU_ASSERT_STRING_EQUAL(expr, fcontext_expr);
+	} else {
+		CU_ASSERT(res < 0);
+		CU_ASSERT(resp == (void *) 42);
+	}
+
+	/* cleanup */
+	cleanup_handle(level);
+}
+
+void test_fcontext_query(void)
+{
+	helper_fcontext_query(SH_CONNECT, FCONTEXT_NONEXISTENT_EXPR,
+			      FCONTEXT_NONEXISTENT_TYPE, -1);
+	helper_fcontext_query(SH_CONNECT, FCONTEXT2_EXPR, FCONTEXT1_TYPE, -1);
+	helper_fcontext_query(SH_CONNECT, FCONTEXT1_EXPR, FCONTEXT1_TYPE, 1);
+	helper_fcontext_query(SH_CONNECT, FCONTEXT2_EXPR, FCONTEXT2_TYPE, 1);
+	helper_fcontext_query(SH_TRANS, FCONTEXT_NONEXISTENT_EXPR,
+			      FCONTEXT_NONEXISTENT_TYPE, -1);
+	helper_fcontext_query(SH_TRANS, FCONTEXT2_EXPR, FCONTEXT1_TYPE, -1);
+	helper_fcontext_query(SH_TRANS, FCONTEXT1_EXPR, FCONTEXT1_TYPE, 1);
+	helper_fcontext_query(SH_TRANS, FCONTEXT2_EXPR, FCONTEXT2_TYPE, 1);
+}
+
+/* Function semanage_fcontext_exists */
+void helper_fcontext_exists(level_t level, const char *fcontext_expr,
+			    int fcontext_type, int exp_resp)
+{
+	semanage_fcontext_key_t *key;
+	int resp;
+
+	/* setup */
+	setup_handle(level);
+	key = get_fcontext_key_from_str(fcontext_expr, fcontext_type);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_exists(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == exp_resp);
+
+	/* cleanup */
+	semanage_fcontext_key_free(key);
+	cleanup_handle(level);
+}
+
+void test_fcontext_exists(void)
+{
+	helper_fcontext_exists(SH_CONNECT, FCONTEXT_NONEXISTENT_EXPR,
+			       FCONTEXT_NONEXISTENT_TYPE, 0);
+	helper_fcontext_exists(SH_CONNECT, FCONTEXT2_EXPR, FCONTEXT1_TYPE, 0);
+	helper_fcontext_exists(SH_CONNECT, FCONTEXT1_EXPR, FCONTEXT1_TYPE, 1);
+	helper_fcontext_exists(SH_CONNECT, FCONTEXT2_EXPR, FCONTEXT2_TYPE, 1);
+	helper_fcontext_exists(SH_TRANS, FCONTEXT_NONEXISTENT_EXPR,
+			       FCONTEXT_NONEXISTENT_TYPE, 0);
+	helper_fcontext_exists(SH_TRANS, FCONTEXT2_EXPR, FCONTEXT1_TYPE, 0);
+	helper_fcontext_exists(SH_TRANS, FCONTEXT1_EXPR, FCONTEXT1_TYPE, 1);
+	helper_fcontext_exists(SH_TRANS, FCONTEXT2_EXPR, FCONTEXT2_TYPE, 1);
+}
+
+/* Function semanage_fcontext_count */
+void test_fcontext_count(void)
+{
+	unsigned int resp;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_fcontext_count(sh, &resp) < 0);
+	CU_ASSERT(semanage_fcontext_count(sh, NULL) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	resp = 0;
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_fcontext_count(sh, &resp) >= 0);
+	CU_ASSERT(resp == FCONTEXTS_COUNT);
+	cleanup_handle(SH_CONNECT);
+
+	/* trans */
+	resp = 0;
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_fcontext_count(sh, &resp) >= 0);
+	CU_ASSERT(resp == FCONTEXTS_COUNT);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_fcontext_iterate */
+unsigned int counter_fcontext_iterate = 0;
+
+int handler_fcontext_iterate(const semanage_fcontext_t *record, void *varg)
+{
+	CU_ASSERT_PTR_NOT_NULL(record);
+	counter_fcontext_iterate++;
+	return 0;
+}
+
+void helper_fcontext_iterate_invalid(void)
+{
+	/* setup */
+	setup_handle(SH_HANDLE);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_iterate(sh, &handler_fcontext_iterate,
+				            NULL) < 0);
+	CU_ASSERT(semanage_fcontext_iterate(sh, NULL, NULL) < 0);
+
+	/* cleanup */
+	cleanup_handle(SH_HANDLE);
+}
+
+void helper_fcontext_iterate(level_t level)
+{
+	/* setup */
+	setup_handle(level);
+	counter_fcontext_iterate = 0;
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_iterate(sh, &handler_fcontext_iterate,
+					    NULL) >= 0);
+	CU_ASSERT(counter_fcontext_iterate == FCONTEXTS_COUNT);
+
+	/* cleanup */
+	cleanup_handle(level);
+}
+
+void test_fcontext_iterate(void)
+{
+	helper_fcontext_iterate_invalid();
+	helper_fcontext_iterate(SH_CONNECT);
+	helper_fcontext_iterate(SH_TRANS);
+}
+
+/* Function semanage_fcontext_list */
+void helper_fcontext_list_invalid(void)
+{
+	semanage_fcontext_t **records;
+	unsigned int count;
+
+	/* setup */
+	setup_handle(SH_HANDLE);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_list(sh, &records, &count) < 0);
+	CU_ASSERT(semanage_fcontext_list(sh, NULL, &count) < 0);
+	CU_ASSERT(semanage_fcontext_list(sh, &records, NULL) < 0);
+
+	/* cleanup */
+	cleanup_handle(SH_HANDLE);
+}
+
+void helper_fcontext_list(level_t level)
+{
+	semanage_fcontext_t **records;
+	unsigned int count;
+
+	/* setup */
+	setup_handle(level);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == FCONTEXTS_COUNT);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	for (unsigned int i = 0; i < count; i++)
+		semanage_fcontext_free(records[i]);
+
+	/* cleanup */
+	cleanup_handle(level);
+}
+
+void test_fcontext_list(void)
+{
+	helper_fcontext_list_invalid();
+	helper_fcontext_list(SH_CONNECT);
+	helper_fcontext_list(SH_TRANS);
+}
+
+/* Function semanage_fcontext_modify_local, semanage_fcontext_del_local */
+void helper_fcontext_modify_del_local(level_t level, int fcontext_idx,
+				      const char *con_str, int exp_res)
+{
+	semanage_fcontext_t *fcontext;
+	semanage_fcontext_t *fcontext_local;
+	semanage_fcontext_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	int res;
+
+	/* setup */
+	setup_handle(level);
+	fcontext = get_fcontext_nth(fcontext_idx);
+	CU_ASSERT(semanage_fcontext_key_extract(sh, fcontext, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	if (con_str != NULL) {
+		CU_ASSERT(semanage_context_from_string(sh, con_str, &con) >= 0);
+		CU_ASSERT_PTR_NOT_NULL(con);
+	} else {
+		con = NULL;
+	}
+
+	CU_ASSERT(semanage_fcontext_set_con(sh, fcontext, con) >= 0);
+
+	/* test */
+	res = semanage_fcontext_modify_local(sh, key, fcontext);
+
+	if (exp_res >= 0) {
+		CU_ASSERT(res >= 0);
+
+		if (level == SH_TRANS) {
+			helper_commit();
+			helper_begin_transaction();
+		}
+
+		CU_ASSERT(semanage_fcontext_query_local(sh, key,
+					                &fcontext_local) >= 0);
+		CU_ASSERT(semanage_fcontext_compare2(fcontext_local,
+						     fcontext) == 0);
+		CU_ASSERT(semanage_fcontext_del_local(sh, key) >= 0);
+		CU_ASSERT(semanage_fcontext_query_local(sh, key,
+					                &fcontext_local) < 0);
+	} else {
+		CU_ASSERT(res < 0);
+	}
+
+	/* cleanup */
+	semanage_fcontext_key_free(key);
+	semanage_fcontext_free(fcontext);
+	cleanup_handle(level);
+}
+
+void test_fcontext_modify_del_local(void)
+{
+	helper_fcontext_modify_del_local(SH_CONNECT, I_FIRST,
+					 "system_u:object_r:tmp_t:s0", -1);
+	helper_fcontext_modify_del_local(SH_CONNECT, I_SECOND,
+					 "system_u:object_r:tmp_t:s0", -1);
+	helper_fcontext_modify_del_local(SH_TRANS, I_FIRST,
+					 "system_u:object_r:tmp_t:s0", 1);
+	helper_fcontext_modify_del_local(SH_TRANS, I_SECOND,
+					 "system_u:object_r:tmp_t:s0", 1);
+}
+
+/* Function semanage_fcontext_query_local */
+void test_fcontext_query_local(void)
+{
+	semanage_fcontext_key_t *key = NULL;
+	semanage_fcontext_t *resp = NULL;
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+
+	key = get_fcontext_key_nth(I_FIRST);
+	CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) < 0);
+	CU_ASSERT_PTR_NULL(resp);
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	key = get_fcontext_key_nth(I_FIRST);
+	CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) < 0);
+	CU_ASSERT_PTR_NULL(resp);
+
+	add_local_fcontext(I_FIRST);
+	CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(resp);
+
+	semanage_fcontext_key_free(key);
+	key = get_fcontext_key_nth(I_SECOND);
+	add_local_fcontext(I_SECOND);
+	CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(resp);
+
+	/* cleanup */
+	delete_local_fcontext(I_FIRST);
+	delete_local_fcontext(I_SECOND);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_fcontext_exists_local */
+void test_fcontext_exists_local(void)
+{
+	int resp = -1;
+	semanage_fcontext_key_t *key;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	key = get_fcontext_key_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_fcontext_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	add_local_fcontext(I_FIRST);
+	resp = -1;
+
+	CU_ASSERT(semanage_fcontext_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 1);
+
+	delete_local_fcontext(I_FIRST);
+	resp = -1;
+
+	CU_ASSERT(semanage_fcontext_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	resp = -1;
+
+	CU_ASSERT(semanage_fcontext_exists_local(sh, NULL, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_fcontext_count_local */
+void test_fcontext_count_local(void)
+{
+	unsigned int resp;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) < 0);
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == 0);
+
+	add_local_fcontext(I_FIRST);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == 1);
+
+	add_local_fcontext(I_SECOND);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == 2);
+
+	delete_local_fcontext(I_SECOND);
+	CU_ASSERT(semanage_fcontext_count_local(sh, &resp) >= 0);
+	CU_ASSERT(resp == 1);
+
+	/* cleanup */
+	delete_local_fcontext(I_FIRST);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_fcontext_iterate_local */
+unsigned int counter_fcontext_iterate_local = 0;
+
+int handler_fcontext_iterate_local(const semanage_fcontext_t *record,
+				   void *varg)
+{
+	CU_ASSERT_PTR_NOT_NULL(record);
+	counter_fcontext_iterate_local++;
+	return 0;
+}
+
+void test_fcontext_iterate_local(void)
+{
+	/* handle */
+	setup_handle(SH_HANDLE);
+
+	CU_ASSERT(semanage_fcontext_iterate_local(sh,
+				    &handler_fcontext_iterate_local, NULL) < 0);
+	CU_ASSERT(semanage_fcontext_iterate_local(sh, NULL, NULL) < 0);
+
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+
+	counter_fcontext_iterate_local = 0;
+	CU_ASSERT(semanage_fcontext_iterate_local(sh,
+				   &handler_fcontext_iterate_local, NULL) >= 0);
+	CU_ASSERT(counter_fcontext_iterate_local == 0);
+	CU_ASSERT(semanage_fcontext_iterate_local(sh, NULL, NULL) >= 0);
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	counter_fcontext_iterate_local = 0;
+	CU_ASSERT(semanage_fcontext_iterate_local(sh,
+				   &handler_fcontext_iterate_local, NULL) >= 0);
+	CU_ASSERT(counter_fcontext_iterate_local == 0);
+
+	add_local_fcontext(I_FIRST);
+	counter_fcontext_iterate_local = 0;
+	CU_ASSERT(semanage_fcontext_iterate_local(sh,
+				   &handler_fcontext_iterate_local, NULL) >= 0);
+	CU_ASSERT(counter_fcontext_iterate_local == 1);
+
+	add_local_fcontext(I_SECOND);
+	counter_fcontext_iterate_local = 0;
+	CU_ASSERT(semanage_fcontext_iterate_local(sh,
+				   &handler_fcontext_iterate_local, NULL) >= 0);
+	CU_ASSERT(counter_fcontext_iterate_local == 2);
+
+	/* cleanup */
+	delete_local_fcontext(I_FIRST);
+	delete_local_fcontext(I_SECOND);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_fcontext_list_local */
+void test_fcontext_list_local(void)
+{
+	semanage_fcontext_t **records;
+	unsigned int count;
+
+	/* handle */
+	setup_handle(SH_HANDLE);
+
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) < 0);
+	CU_ASSERT(semanage_fcontext_list_local(sh, NULL, &count) < 0);
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, NULL) < 0);
+
+	cleanup_handle(SH_HANDLE);
+
+	/* connect */
+	setup_handle(SH_CONNECT);
+
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	cleanup_handle(SH_CONNECT);
+
+	/* transaction */
+	setup_handle(SH_TRANS);
+
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	add_local_fcontext(I_FIRST);
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 1);
+	CU_ASSERT_PTR_NOT_NULL(records[0]);
+
+	add_local_fcontext(I_SECOND);
+	CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 2);
+	CU_ASSERT_PTR_NOT_NULL(records[0]);
+	CU_ASSERT_PTR_NOT_NULL(records[1]);
+
+	/* cleanup */
+	delete_local_fcontext(I_FIRST);
+	delete_local_fcontext(I_SECOND);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_fcontext.cil b/libsemanage/tests/test_fcontext.cil
new file mode 100644
index 00000000..1c62b893
--- /dev/null
+++ b/libsemanage/tests/test_fcontext.cil
@@ -0,0 +1,25 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r first_t)
+(roletype object_r second_t)
+(roletype object_r third_t)
+(type first_t)
+(type second_t)
+(type third_t)
+(sidcontext security (system_u object_r first_t ((s0) (s0))))
+(class test_class (test_perm))
+(classorder (test_class))
+(allow first_t self (test_class (test_perm)))
diff --git a/libsemanage/tests/test_fcontext.h b/libsemanage/tests/test_fcontext.h
new file mode 100644
index 00000000..64aba991
--- /dev/null
+++ b/libsemanage/tests/test_fcontext.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_FCONTEXT_H__
+#define __TEST_FCONTEXT_H__
+
+#include <CUnit/Basic.h>
+
+int fcontext_test_init(void);
+int fcontext_test_cleanup(void);
+int fcontext_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/11] libsemanage: test semanage_iface_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (3 preceding siblings ...)
  2019-06-12  8:03 ` [PATCH 04/11] libsemanage: test semanage_fcontext functions Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:03 ` [PATCH 06/11] libsemanage: test semanage_ibendport_* functions Jan Zarsky
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_iface_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_iface.c        | 666 ++++++++++++++++++++++++++
 libsemanage/tests/test_iface.cil      |  28 ++
 libsemanage/tests/test_iface.h        |  30 ++
 4 files changed, 726 insertions(+)
 create mode 100644 libsemanage/tests/test_iface.c
 create mode 100644 libsemanage/tests/test_iface.cil
 create mode 100644 libsemanage/tests/test_iface.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index c5f42b9e..e590f7bd 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -24,6 +24,7 @@
 #include "test_handle.h"
 #include "test_bool.h"
 #include "test_fcontext.h"
+#include "test_iface.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -65,6 +66,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(handle);
 	DECLARE_SUITE(bool);
 	DECLARE_SUITE(fcontext);
+	DECLARE_SUITE(iface);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_iface.c b/libsemanage/tests/test_iface.c
new file mode 100644
index 00000000..d5d530a8
--- /dev/null
+++ b/libsemanage/tests/test_iface.c
@@ -0,0 +1,666 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_iface.h"
+
+#define IFACE_COUNT 3
+
+#define IFACE1_NAME "eth0"
+#define IFACE1_IFCON "system_u:object_r:first_netif_t:s0"
+#define IFACE1_MSGCON IFACE1_IFCON
+
+#define IFACE2_NAME "eth1"
+#define IFACE2_IFCON "system_u:object_r:second_netif_t:s0"
+#define IFACE2_MSGCON IFACE2_IFCON
+
+#define IFACE3_NAME "eth2"
+#define IFACE3_IFCON "system_u:object_r:third_netif_t:s0"
+#define IFACE3_MSGCON IFACE3_IFCON
+
+
+/* iface_record.h */
+void test_iface_compare(void);
+void test_iface_compare2(void);
+void test_iface_key_create(void);
+void test_iface_key_extract(void);
+void test_iface_get_set_name(void);
+void test_iface_get_set_ifcon(void);
+void test_iface_get_set_msgcon(void);
+void test_iface_create(void);
+void test_iface_clone(void);
+
+/* iterfaces_policy.h */
+void test_iface_query(void);
+void test_iface_exists(void);
+void test_iface_count(void);
+void test_iface_iterate(void);
+void test_iface_list(void);
+
+/* interfaces_local.h */
+void test_iface_modify_del_query_local(void);
+void test_iface_exists_local(void);
+void test_iface_count_local(void);
+void test_iface_iterate_local(void);
+void test_iface_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int iface_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_iface.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int iface_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int iface_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "iface_compare", test_iface_compare);
+	CU_add_test(suite, "iface_compare2", test_iface_compare2);
+	CU_add_test(suite, "iface_key_create", test_iface_key_create);
+	CU_add_test(suite, "iface_key_extract", test_iface_key_extract);
+	CU_add_test(suite, "iface_get_set_name", test_iface_get_set_name);
+	CU_add_test(suite, "iface_get_set_ifcon", test_iface_get_set_ifcon);
+	CU_add_test(suite, "iface_get_set_msgcon", test_iface_get_set_msgcon);
+	CU_add_test(suite, "iface_create)", test_iface_create);
+	CU_add_test(suite, "iface_clone);", test_iface_clone);
+
+	CU_add_test(suite, "iface_query", test_iface_query);
+	CU_add_test(suite, "iface_exists", test_iface_exists);
+	CU_add_test(suite, "iface_count", test_iface_count);
+	CU_add_test(suite, "iface_iterate", test_iface_iterate);
+	CU_add_test(suite, "iface_list", test_iface_list);
+
+	CU_add_test(suite, "iface_modify_del_query_local",
+				test_iface_modify_del_query_local);
+	CU_add_test(suite, "iface_exists_local", test_iface_exists_local);
+	CU_add_test(suite, "iface_count_local", test_iface_count_local);
+	CU_add_test(suite, "iface_iterate_local", test_iface_iterate_local);
+	CU_add_test(suite, "iface_list_local", test_iface_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_iface_t *get_iface_nth(int idx)
+{
+	int res;
+	semanage_iface_t **records;
+	semanage_iface_t *iface;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	res = semanage_iface_list(sh, &records, &count);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	iface = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_iface_free(records[i]);
+
+	return iface;
+}
+
+semanage_iface_key_t *get_iface_key_nth(int idx)
+{
+	semanage_iface_key_t *key;
+	semanage_iface_t *iface;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	iface = get_iface_nth(idx);
+	res = semanage_iface_key_extract(sh, iface, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_iface(int idx)
+{
+	semanage_iface_t *iface;
+	semanage_iface_key_t *key = NULL;
+
+	iface = get_iface_nth(idx);
+
+	CU_ASSERT_FATAL(semanage_iface_key_extract(sh, iface, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_iface_modify_local(sh, key, iface) >= 0);
+}
+
+void delete_local_iface(int idx)
+{
+	semanage_iface_key_t *key = NULL;
+	key = get_iface_key_nth(idx);
+	CU_ASSERT_FATAL(semanage_iface_del_local(sh, key) >= 0);
+}
+
+/* Function semanage_iface_compare */
+void test_iface_compare(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_iface_key_t *key1 = NULL;
+	semanage_iface_key_t *key2 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface = get_iface_nth(I_FIRST);
+	key1 = get_iface_key_nth(I_FIRST);
+	CU_ASSERT(semanage_iface_key_create(sh, "qwerty", &key2) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key2);
+
+	/* test */
+	res = semanage_iface_compare(iface, key1);
+	CU_ASSERT(res == 0);
+	res = semanage_iface_compare(iface, key2);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	semanage_iface_key_free(key1);
+	semanage_iface_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_compare2 */
+void test_iface_compare2(void)
+{
+	semanage_iface_t *iface1 = NULL;
+	semanage_iface_t *iface2 = NULL;
+	semanage_iface_t *iface3 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface1 = get_iface_nth(I_FIRST);
+	iface2 = get_iface_nth(I_FIRST);
+	iface3 = get_iface_nth(I_SECOND);
+
+	/* test */
+	res = semanage_iface_compare2(iface1, iface2);
+	CU_ASSERT(res == 0);
+	res = semanage_iface_compare2(iface1, iface3);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_iface_free(iface1);
+	semanage_iface_free(iface2);
+	semanage_iface_free(iface3);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_create */
+void test_iface_key_create(void)
+{
+	semanage_iface_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_iface_key_create(sh, "asdf", &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_iface_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_extract */
+void test_iface_key_extract(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_iface_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface = get_iface_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_iface_key_extract(sh, iface, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	semanage_iface_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_get_name, semanage_iface_set_name */
+void test_iface_get_set_name(void)
+{
+	semanage_iface_t *iface = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface = get_iface_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_iface_set_name(sh, iface, "my_asdf") == 0);
+	CU_ASSERT_STRING_EQUAL(semanage_iface_get_name(iface), "my_asdf");
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_get_ifcon, semanage_iface_set_ifcon */
+void test_iface_get_set_ifcon(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface = get_iface_nth(I_FIRST);
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "my_user_u:my_role_r:my_type_t:s0", &con1) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_iface_set_ifcon(sh, iface, con1) == 0);
+	con2 = semanage_iface_get_ifcon(iface);
+	CU_ASSERT_CONTEXT_EQUAL(con1, con2);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_get_msgcon, semanage_iface_set_msgcon */
+void test_iface_get_set_msgcon(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	iface = get_iface_nth(I_FIRST);
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "my_user_u:my_role_r:my_type_t:s0", &con1) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_iface_set_msgcon(sh, iface, con1) == 0);
+	con2 = semanage_iface_get_msgcon(iface);
+	CU_ASSERT_CONTEXT_EQUAL(con1, con2);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_create */
+void test_iface_create(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_context_t *ifcon = NULL;
+	semanage_context_t *msgcon = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_iface_create(sh, &iface) >= 0);
+	CU_ASSERT(semanage_iface_set_name(sh, iface, "asdf") >= 0);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:type_t:s0",
+					       &ifcon) >= 0);
+	CU_ASSERT(semanage_iface_set_ifcon(sh, iface, ifcon) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:type_t:s0",
+					       &msgcon) >= 0);
+	CU_ASSERT(semanage_iface_set_msgcon(sh, iface, msgcon) >= 0);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_clone */
+void test_iface_clone(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_iface_t *iface_clone = NULL;
+	semanage_context_t *ifcon = NULL;
+	semanage_context_t *ifcon2 = NULL;
+	semanage_context_t *msgcon = NULL;
+	semanage_context_t *msgcon2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_iface_create(sh, &iface) >= 0);
+	CU_ASSERT(semanage_iface_set_name(sh, iface, "asdf") >= 0);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:if_type_t:s0",
+					       &ifcon) >= 0);
+	CU_ASSERT(semanage_iface_set_ifcon(sh, iface, ifcon) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:msg_type_t:s0",
+					       &msgcon) >= 0);
+	CU_ASSERT(semanage_iface_set_msgcon(sh, iface, msgcon) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_iface_clone(sh, iface, &iface_clone) >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_iface_get_name(iface_clone), "asdf");
+
+	ifcon2 = semanage_iface_get_ifcon(iface_clone);
+	CU_ASSERT_CONTEXT_EQUAL(ifcon, ifcon2);
+
+	msgcon2 = semanage_iface_get_msgcon(iface_clone);
+	CU_ASSERT_CONTEXT_EQUAL(msgcon, msgcon2);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	semanage_iface_free(iface_clone);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_query */
+void test_iface_query(void)
+{
+	semanage_iface_t *iface = NULL;
+	semanage_iface_t *iface_exp = NULL;
+	semanage_iface_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_exp = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key = get_iface_key_nth(I_FIRST);
+	iface_exp = get_iface_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_iface_query(sh, key, &iface) >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_iface_get_name(iface),
+		semanage_iface_get_name(iface_exp));
+
+	con = semanage_iface_get_ifcon(iface);
+	con_exp = semanage_iface_get_ifcon(iface_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	con = semanage_iface_get_msgcon(iface);
+	con_exp = semanage_iface_get_msgcon(iface_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	semanage_iface_free(iface_exp);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_exists */
+void test_iface_exists(void)
+{
+	semanage_iface_key_t *key1 = NULL;
+	semanage_iface_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key1 = get_iface_key_nth(I_FIRST);
+	CU_ASSERT(semanage_iface_key_create(sh, "asdf", &key2) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_iface_exists(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_iface_exists(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	semanage_iface_key_free(key1);
+	semanage_iface_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_count */
+void test_iface_count(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_iface_count(sh, &count) >= 0);
+	CU_ASSERT(count == IFACE_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_iterate */
+
+unsigned int counter_iface_iterate = 0;
+
+int handler_iface_iterate(const semanage_iface_t *record, void *varg)
+{
+	counter_iface_iterate++;
+	return 0;
+}
+
+void test_iface_iterate(void)
+{
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	semanage_iface_iterate(sh, handler_iface_iterate, NULL);
+	CU_ASSERT(counter_iface_iterate == IFACE_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_list */
+void test_iface_list(void)
+{
+	semanage_iface_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_iface_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == IFACE_COUNT);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	for (unsigned int i = 0; i < count; i++)
+		semanage_iface_free(records[i]);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_iface_modify_local, semanage_iface_del_local,
+ * semanage_iface_query_local
+ */
+void test_iface_modify_del_query_local(void)
+{
+	semanage_iface_t *iface;
+	semanage_iface_t *iface_local;
+	semanage_iface_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	iface = get_iface_nth(I_FIRST);
+	CU_ASSERT(semanage_iface_key_extract(sh, iface, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* test */
+	CU_ASSERT(semanage_iface_modify_local(sh, key, iface) >= 0);
+
+	/* write changes to file */
+	helper_commit();
+	helper_begin_transaction();
+
+	CU_ASSERT(semanage_iface_query_local(sh, key, &iface_local) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(iface_local);
+
+	CU_ASSERT(semanage_iface_del_local(sh, key) >= 0);
+	CU_ASSERT(semanage_iface_query_local(sh, key, &iface_local) < 0);
+
+	/* cleanup */
+	semanage_iface_free(iface);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_iface_exists_local */
+void test_iface_exists_local(void)
+{
+	semanage_iface_key_t *key1 = NULL;
+	semanage_iface_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_iface(I_FIRST);
+	key1 = get_iface_key_nth(I_FIRST);
+	key2 = get_iface_key_nth(I_SECOND);
+
+	/* test */
+	CU_ASSERT(semanage_iface_exists_local(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_iface_exists_local(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	CU_ASSERT(semanage_iface_del_local(sh, key1) >= 0);
+	semanage_iface_key_free(key1);
+	semanage_iface_key_free(key2);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_iface_count_local */
+void test_iface_count_local(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+
+	/* test */
+	CU_ASSERT(semanage_iface_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	add_local_iface(I_FIRST);
+	CU_ASSERT(semanage_iface_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	add_local_iface(I_SECOND);
+	CU_ASSERT(semanage_iface_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 2);
+
+	delete_local_iface(I_SECOND);
+	CU_ASSERT(semanage_iface_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	delete_local_iface(I_FIRST);
+	CU_ASSERT(semanage_iface_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_iface_iterate_local */
+unsigned int counter_iface_iterate_local = 0;
+
+int handler_iface_iterate_local(const semanage_iface_t *record, void *varg)
+{
+	counter_iface_iterate_local++;
+	return 0;
+}
+
+void test_iface_iterate_local(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_iface(I_FIRST);
+	add_local_iface(I_SECOND);
+	add_local_iface(I_THIRD);
+
+	/* test */
+	semanage_iface_iterate_local(sh, handler_iface_iterate_local, NULL);
+	CU_ASSERT(counter_iface_iterate_local == 3);
+
+	/* cleanup */
+	delete_local_iface(I_FIRST);
+	delete_local_iface(I_SECOND);
+	delete_local_iface(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_iface_list_local */
+void test_iface_list_local(void)
+{
+	semanage_iface_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_iface(I_FIRST);
+	add_local_iface(I_SECOND);
+	add_local_iface(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_iface_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 3);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_iface_free(records[i]);
+
+	delete_local_iface(I_FIRST);
+	delete_local_iface(I_SECOND);
+	delete_local_iface(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_iface.cil b/libsemanage/tests/test_iface.cil
new file mode 100644
index 00000000..13fd8f68
--- /dev/null
+++ b/libsemanage/tests/test_iface.cil
@@ -0,0 +1,28 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r first_netif_t)
+(roletype object_r second_netif_t)
+(roletype object_r third_netif_t)
+(type first_netif_t)
+(type second_netif_t)
+(type third_netif_t)
+(sidcontext security (system_u object_r first_netif_t ((s0) (s0))))
+(class netif (tcp_recv))
+(classorder (netif))
+(allow first_netif_t self (netif (tcp_recv)))
+(netifcon eth0 (system_u object_r first_netif_t ((s0) (s0))) (system_u object_r first_netif_t ((s0) (s0))))
+(netifcon eth1 (system_u object_r second_netif_t ((s0) (s0))) (system_u object_r second_netif_t ((s0) (s0))))
+(netifcon eth2 (system_u object_r third_netif_t ((s0) (s0))) (system_u object_r third_netif_t ((s0) (s0))))
diff --git a/libsemanage/tests/test_iface.h b/libsemanage/tests/test_iface.h
new file mode 100644
index 00000000..5953e9c0
--- /dev/null
+++ b/libsemanage/tests/test_iface.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_IFACE_H__
+#define __TEST_IFACE_H__
+
+#include <CUnit/Basic.h>
+
+int iface_test_init(void);
+int iface_test_cleanup(void);
+int iface_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/11] libsemanage: test semanage_ibendport_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (4 preceding siblings ...)
  2019-06-12  8:03 ` [PATCH 05/11] libsemanage: test semanage_iface_* functions Jan Zarsky
@ 2019-06-12  8:03 ` Jan Zarsky
  2019-06-12  8:04 ` [PATCH 07/11] libsemanage: test semanage_node_* functions Jan Zarsky
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:03 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_ibendport_* functions. The test suite aims for
line coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_ibendport.c    | 525 ++++++++++++++++++++++++++
 libsemanage/tests/test_ibendport.cil  |  28 ++
 libsemanage/tests/test_ibendport.h    |  30 ++
 4 files changed, 585 insertions(+)
 create mode 100644 libsemanage/tests/test_ibendport.c
 create mode 100644 libsemanage/tests/test_ibendport.cil
 create mode 100644 libsemanage/tests/test_ibendport.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index e590f7bd..d395a9fd 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -25,6 +25,7 @@
 #include "test_bool.h"
 #include "test_fcontext.h"
 #include "test_iface.h"
+#include "test_ibendport.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -67,6 +68,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(bool);
 	DECLARE_SUITE(fcontext);
 	DECLARE_SUITE(iface);
+	DECLARE_SUITE(ibendport);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_ibendport.c b/libsemanage/tests/test_ibendport.c
new file mode 100644
index 00000000..79a8e2c8
--- /dev/null
+++ b/libsemanage/tests/test_ibendport.c
@@ -0,0 +1,525 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_ibendport.h"
+
+#define IBENDPORT_COUNT 3
+#define IBENDPORT_1_NAME "mlx4_0"
+#define IBENDPORT_1_PORT 1
+#define IBENDPORT_1_CON "system_u:object_r:first_ibendport_t:s0"
+#define IBENDPORT_2_NAME "mlx4_1"
+#define IBENDPORT_2_PORT 2
+#define IBENDPORT_2_CON "system_u:object_r:second_ibendport_second_t:s0"
+#define IBENDPORT_3_NAME "mlx4_1"
+#define IBENDPORT_3_PORT 3
+#define IBENDPORT_3_CON "system_u:object_r:third_ibendport_second_t:s0"
+
+/* ibendports_policy.h */
+void test_ibendport_query(void);
+void test_ibendport_exists(void);
+void test_ibendport_count(void);
+void test_ibendport_iterate(void);
+void test_ibendport_list(void);
+
+/* ibendports_local.h */
+void test_ibendport_modify_del_query_local(void);
+void test_ibendport_exists_local(void);
+void test_ibendport_count_local(void);
+void test_ibendport_iterate_local(void);
+void test_ibendport_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int ibendport_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_ibendport.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int ibendport_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int ibendport_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "ibendport_query", test_ibendport_query);
+	CU_add_test(suite, "ibendport_exists", test_ibendport_exists);
+	CU_add_test(suite, "ibendport_count", test_ibendport_count);
+	CU_add_test(suite, "ibendport_iterate", test_ibendport_iterate);
+	CU_add_test(suite, "ibendport_list", test_ibendport_list);
+
+	CU_add_test(suite, "ibendport_modify_del_query_local",
+		    test_ibendport_modify_del_query_local);
+	CU_add_test(suite, "ibendport_exists_local",
+		    test_ibendport_exists_local);
+	CU_add_test(suite, "ibendport_count_local", test_ibendport_count_local);
+	CU_add_test(suite, "ibendport_iterate_local",
+		    test_ibendport_iterate_local);
+	CU_add_test(suite, "ibendport_list_local", test_ibendport_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_ibendport_t *get_ibendport_nth(int idx)
+{
+	semanage_ibendport_t **records;
+	semanage_ibendport_t *ibendport;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	CU_ASSERT_FATAL(semanage_ibendport_list(sh, &records, &count) >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	ibendport = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_ibendport_free(records[i]);
+
+	return ibendport;
+}
+
+semanage_ibendport_key_t *get_ibendport_key_nth(int idx)
+{
+	semanage_ibendport_key_t *key;
+	semanage_ibendport_t *ibendport;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	ibendport = get_ibendport_nth(idx);
+
+	res = semanage_ibendport_key_extract(sh, ibendport, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_ibendport(int idx)
+{
+	semanage_ibendport_t *ibendport;
+	semanage_ibendport_key_t *key = NULL;
+
+	ibendport = get_ibendport_nth(idx);
+
+	CU_ASSERT_FATAL(semanage_ibendport_key_extract(sh, ibendport,
+						       &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_ibendport_modify_local(sh, key,
+							ibendport) >= 0);
+}
+
+void delete_local_ibendport(int idx)
+{
+	semanage_ibendport_key_t *key = NULL;
+	key = get_ibendport_key_nth(idx);
+	CU_ASSERT_FATAL(semanage_ibendport_del_local(sh, key) >= 0);
+}
+
+/* Function semanage_ibendport_query */
+void test_ibendport_query(void)
+{
+	semanage_ibendport_t *ibendport = NULL;
+	semanage_ibendport_t *ibendport_exp = NULL;
+	semanage_ibendport_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_exp = NULL;
+	char *name;
+	char *name_exp;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key = get_ibendport_key_nth(I_FIRST);
+	ibendport_exp = get_ibendport_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_query(sh, key, &ibendport) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(ibendport);
+
+	CU_ASSERT(semanage_ibendport_get_ibdev_name(sh, ibendport, &name) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(name);
+	CU_ASSERT(semanage_ibendport_get_ibdev_name(sh, ibendport_exp,
+						    &name_exp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(name_exp);
+	assert(name);
+	CU_ASSERT_STRING_EQUAL(name, name_exp);
+
+	CU_ASSERT(semanage_ibendport_get_port(ibendport) ==
+		  semanage_ibendport_get_port(ibendport_exp));
+
+	con = semanage_ibendport_get_con(ibendport);
+	con_exp = semanage_ibendport_get_con(ibendport_exp);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(con);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(con_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	/* cleanup */
+	free(name);
+	semanage_ibendport_free(ibendport);
+	semanage_ibendport_free(ibendport_exp);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_ibendport_exists */
+void test_ibendport_exists(void)
+{
+	semanage_ibendport_key_t *key1 = NULL;
+	semanage_ibendport_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key1 = get_ibendport_key_nth(I_FIRST);
+	CU_ASSERT(semanage_ibendport_key_create(sh, "asdf", 1, &key2) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_exists(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+
+	CU_ASSERT(semanage_ibendport_exists(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	semanage_ibendport_key_free(key1);
+	semanage_ibendport_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_ibendport_count */
+void test_ibendport_count(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_count(sh, &count) >= 0);
+	CU_ASSERT(count == IBENDPORT_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_ibendport_iterate */
+unsigned int helper_ibendport_iterate_counter = 0;
+
+int helper_ibendport_iterate(const semanage_ibendport_t *ibendport,
+			     void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_counter++;
+	return 0;
+}
+
+int helper_ibendport_iterate_error(const semanage_ibendport_t *ibendport,
+				   void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_counter++;
+	return -1;
+}
+
+int helper_ibendport_iterate_break(const semanage_ibendport_t *ibendport,
+				   void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_counter++;
+	return 1;
+}
+
+void test_ibendport_iterate(void)
+{
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	helper_ibendport_iterate_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate(sh, helper_ibendport_iterate,
+					     (void *) 42) >= 0);
+	CU_ASSERT(helper_ibendport_iterate_counter == IBENDPORT_COUNT);
+
+	/* test function which returns error */
+	helper_ibendport_iterate_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate(sh, helper_ibendport_iterate_error,
+					     (void *) 42) < 0);
+	CU_ASSERT(helper_ibendport_iterate_counter == 1);
+
+	/* test function which requests break */
+	helper_ibendport_iterate_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate(sh, helper_ibendport_iterate_break,
+					     (void *) 42) >= 0);
+	CU_ASSERT(helper_ibendport_iterate_counter == 1);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_ibendport_list */
+void test_ibendport_list(void)
+{
+	semanage_ibendport_t **records = NULL;
+	unsigned int count = 42;
+	char *name = NULL;
+	semanage_context_t *con = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_list(sh, &records, &count) >= 0);
+
+	CU_ASSERT_PTR_NOT_NULL_FATAL(records);
+	assert(records);
+	CU_ASSERT(count == IBENDPORT_COUNT);
+
+	for (unsigned int i = 0; i < count; i++) {
+		CU_ASSERT_PTR_NOT_NULL_FATAL(records[i]);
+		CU_ASSERT(semanage_ibendport_get_ibdev_name(sh, records[i],
+							    &name) >= 0);
+		con = semanage_ibendport_get_con(records[i]);
+		CU_ASSERT_PTR_NOT_NULL_FATAL(con);
+		free(name);
+	}
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_ibendport_free(records[i]);
+
+	free(records);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_ibendport_modify_local, semanage_ibendport_del_local,
+ * semanage_ibendport_query_local
+ */
+void test_ibendport_modify_del_query_local(void)
+{
+	semanage_ibendport_t *ibendport;
+	semanage_ibendport_t *ibendport_local;
+	semanage_ibendport_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	ibendport = get_ibendport_nth(I_FIRST);
+	CU_ASSERT(semanage_ibendport_key_extract(sh, ibendport, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_modify_local(sh, key, ibendport) >= 0);
+
+	/* write changes to file */
+	helper_commit();
+	helper_begin_transaction();
+
+	CU_ASSERT(semanage_ibendport_query_local(sh, key,
+						 &ibendport_local) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(ibendport_local);
+
+	CU_ASSERT(semanage_ibendport_del_local(sh, key) >= 0);
+	CU_ASSERT(semanage_ibendport_query_local(sh, key,
+						 &ibendport_local) < 0);
+
+	/* cleanup */
+	semanage_ibendport_free(ibendport);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_ibendport_exists_local */
+void test_ibendport_exists_local(void)
+{
+	semanage_ibendport_key_t *key1 = NULL;
+	semanage_ibendport_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_ibendport(I_FIRST);
+	key1 = get_ibendport_key_nth(I_FIRST);
+	key2 = get_ibendport_key_nth(I_SECOND);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_exists_local(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+
+	CU_ASSERT(semanage_ibendport_exists_local(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	CU_ASSERT(semanage_ibendport_del_local(sh, key1) >= 0);
+	semanage_ibendport_key_free(key1);
+	semanage_ibendport_key_free(key2);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_ibendport_count_local */
+void test_ibendport_count_local(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	add_local_ibendport(I_FIRST);
+	CU_ASSERT(semanage_ibendport_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	add_local_ibendport(I_SECOND);
+	CU_ASSERT(semanage_ibendport_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 2);
+
+	delete_local_ibendport(I_SECOND);
+	CU_ASSERT(semanage_ibendport_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	delete_local_ibendport(I_FIRST);
+	CU_ASSERT(semanage_ibendport_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_ibendport_iterate_local */
+unsigned int helper_ibendport_iterate_local_counter = 0;
+
+int helper_ibendport_iterate_local(const semanage_ibendport_t *ibendport,
+				   void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_local_counter++;
+	return 0;
+}
+
+int helper_ibendport_iterate_local_error(const semanage_ibendport_t *ibendport,
+					 void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_local_counter++;
+	return -1;
+}
+
+int helper_ibendport_iterate_local_break(const semanage_ibendport_t *ibendport,
+					 void *fn_arg)
+{
+	CU_ASSERT(fn_arg == (void *) 42);
+	helper_ibendport_iterate_local_counter++;
+	return 1;
+}
+
+void test_ibendport_iterate_local(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_ibendport(I_FIRST);
+	add_local_ibendport(I_SECOND);
+	add_local_ibendport(I_THIRD);
+
+	/* test */
+	helper_ibendport_iterate_local_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate_local(sh,
+			     helper_ibendport_iterate_local, (void *) 42) >= 0);
+	CU_ASSERT(helper_ibendport_iterate_local_counter == 3);
+
+	/* test function which returns error */
+	helper_ibendport_iterate_local_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate_local(sh,
+			helper_ibendport_iterate_local_error, (void *) 42) < 0);
+	CU_ASSERT(helper_ibendport_iterate_local_counter == 1);
+
+	/* test function which requests break */
+	helper_ibendport_iterate_local_counter = 0;
+	CU_ASSERT(semanage_ibendport_iterate_local(sh,
+		       helper_ibendport_iterate_local_break, (void *) 42) >= 0);
+
+	/* cleanup */
+	delete_local_ibendport(I_FIRST);
+	delete_local_ibendport(I_SECOND);
+	delete_local_ibendport(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_ibendport_list_local */
+void test_ibendport_list_local(void)
+{
+	semanage_ibendport_t **records = NULL;
+	unsigned int count = 42;
+	char *name = NULL;
+	semanage_context_t *con = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_ibendport(I_FIRST);
+	add_local_ibendport(I_SECOND);
+	add_local_ibendport(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_ibendport_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(records);
+	assert(records);
+	CU_ASSERT(count == 3);
+
+	for (unsigned int i = 0; i < count; i++) {
+		CU_ASSERT_PTR_NOT_NULL_FATAL(records[i]);
+		CU_ASSERT(semanage_ibendport_get_ibdev_name(sh, records[i],
+								   &name) >= 0);
+		con = semanage_ibendport_get_con(records[i]);
+		CU_ASSERT_PTR_NOT_NULL_FATAL(con);
+		free(name);
+	}
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_ibendport_free(records[i]);
+
+	free(records);
+	delete_local_ibendport(I_FIRST);
+	delete_local_ibendport(I_SECOND);
+	delete_local_ibendport(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_ibendport.cil b/libsemanage/tests/test_ibendport.cil
new file mode 100644
index 00000000..b786b913
--- /dev/null
+++ b/libsemanage/tests/test_ibendport.cil
@@ -0,0 +1,28 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r first_ibendport_t)
+(roletype object_r second_ibendport_t)
+(roletype object_r third_ibendport_t)
+(type first_ibendport_t)
+(type second_ibendport_t)
+(type third_ibendport_t)
+(sidcontext security (system_u object_r first_ibendport_t ((s0) (s0))))
+(class test_class (test_perm))
+(classorder (test_class))
+(allow first_ibendport_t self (test_class (test_perm)))
+(ibendportcon mlx4_0 1 (system_u object_r first_ibendport_t ((s0) (s0))))
+(ibendportcon mlx4_1 2 (system_u object_r second_ibendport_t ((s0) (s0))))
+(ibendportcon mlx4_1 3 (system_u object_r third_ibendport_t ((s0) (s0))))
diff --git a/libsemanage/tests/test_ibendport.h b/libsemanage/tests/test_ibendport.h
new file mode 100644
index 00000000..33d7fbd0
--- /dev/null
+++ b/libsemanage/tests/test_ibendport.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_IBENDPORT_H__
+#define __TEST_IBENDPORT_H__
+
+#include <CUnit/Basic.h>
+
+int ibendport_test_init(void);
+int ibendport_test_cleanup(void);
+int ibendport_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/11] libsemanage: test semanage_node_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (5 preceding siblings ...)
  2019-06-12  8:03 ` [PATCH 06/11] libsemanage: test semanage_ibendport_* functions Jan Zarsky
@ 2019-06-12  8:04 ` Jan Zarsky
  2019-06-12  8:04 ` [PATCH 08/11] libsemanage: test semanage_port_* functions Jan Zarsky
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:04 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_node_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_node.c         | 807 ++++++++++++++++++++++++++
 libsemanage/tests/test_node.cil       |  28 +
 libsemanage/tests/test_node.h         |  30 +
 4 files changed, 867 insertions(+)
 create mode 100644 libsemanage/tests/test_node.c
 create mode 100644 libsemanage/tests/test_node.cil
 create mode 100644 libsemanage/tests/test_node.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index d395a9fd..ba24421d 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -26,6 +26,7 @@
 #include "test_fcontext.h"
 #include "test_iface.h"
 #include "test_ibendport.h"
+#include "test_node.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -69,6 +70,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(fcontext);
 	DECLARE_SUITE(iface);
 	DECLARE_SUITE(ibendport);
+	DECLARE_SUITE(node);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_node.c b/libsemanage/tests/test_node.c
new file mode 100644
index 00000000..53c2eb69
--- /dev/null
+++ b/libsemanage/tests/test_node.c
@@ -0,0 +1,807 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_node.h"
+
+#define NODE_COUNT 3
+
+#define NODE1_ADDR "192.168.0.0"
+#define NODE1_MASK "255.255.255.0"
+#define NODE1_PROTO SEPOL_PROTO_IP4
+#define NODE1_CONTEXT "system_u:object_r:first_node_t:s0"
+
+#define NODE2_ADDR "2001:db8:85a3::8a2e:370:7334"
+#define NODE2_MASK "2001:db8:85a3::8a2e:370:7334"
+#define NODE2_PROTO SEPOL_PROTO_IP6
+#define NODE2_CONTEXT "system_u:object_r:second_node_t:s0"
+
+#define NODE3_ADDR "127.0.0.1"
+#define NODE3_MASK "255.255.0.0"
+#define NODE3_PROTO SEPOL_PROTO_IP4
+#define NODE3_CONTEXT "system_u:object_r:third_node_t:s0"
+
+/* node_record.h */
+void test_node_compare(void);
+void test_node_compare2(void);
+void test_node_key_create(void);
+void test_node_key_extract(void);
+void test_node_get_set_addr(void);
+void test_node_get_set_addr_bytes(void);
+void test_node_get_set_mask(void);
+void test_node_get_set_mask_bytes(void);
+void test_node_get_set_proto(void);
+void test_node_get_proto_str(void);
+void test_node_get_set_con(void);
+void test_node_create(void);
+void test_node_clone(void);
+
+/* nodes_policy.h */
+void test_node_query(void);
+void test_node_exists(void);
+void test_node_count(void);
+void test_node_iterate(void);
+void test_node_list(void);
+
+/* nodes_local.h */
+void test_node_modify_del_query_local(void);
+void test_node_exists_local(void);
+void test_node_count_local(void);
+void test_node_iterate_local(void);
+void test_node_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int node_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_node.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int node_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int node_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "node_compare", test_node_compare);
+	CU_add_test(suite, "node_compare2", test_node_compare2);
+	CU_add_test(suite, "node_key_create", test_node_key_create);
+	CU_add_test(suite, "node_key_extract", test_node_key_extract);
+	CU_add_test(suite, "node_get_set_addr", test_node_get_set_addr);
+	CU_add_test(suite, "node_get_set_addr_bytes",
+		    test_node_get_set_addr_bytes);
+	CU_add_test(suite, "node_get_set_mask", test_node_get_set_mask);
+	CU_add_test(suite, "node_get_set_mask_bytes",
+		    test_node_get_set_mask_bytes);
+	CU_add_test(suite, "node_get_set_proto", test_node_get_set_proto);
+	CU_add_test(suite, "node_get_proto_str", test_node_get_proto_str);
+	CU_add_test(suite, "node_get_set_con", test_node_get_set_con);
+	CU_add_test(suite, "node_create", test_node_create);
+	CU_add_test(suite, "node_clone", test_node_clone);
+
+	CU_add_test(suite, "node_query", test_node_query);
+	CU_add_test(suite, "node_exists", test_node_exists);
+	CU_add_test(suite, "node_count", test_node_count);
+	CU_add_test(suite, "node_iterate", test_node_iterate);
+	CU_add_test(suite, "node_list", test_node_list);
+
+	CU_add_test(suite, "node_modify_del_query_local",
+		    test_node_modify_del_query_local);
+	CU_add_test(suite, "node_exists_local", test_node_exists_local);
+	CU_add_test(suite, "node_count_local", test_node_count_local);
+	CU_add_test(suite, "node_iterate_local", test_node_iterate_local);
+	CU_add_test(suite, "node_list_local", test_node_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_node_t *get_node_nth(int idx)
+{
+	semanage_node_t **records;
+	semanage_node_t *node;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	CU_ASSERT_FATAL(semanage_node_list(sh, &records, &count) >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	node = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_node_free(records[i]);
+
+	return node;
+}
+
+semanage_node_key_t *get_node_key_nth(int idx)
+{
+	semanage_node_key_t *key;
+	semanage_node_t *node;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	node = get_node_nth(idx);
+
+	res = semanage_node_key_extract(sh, node, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_node(int idx)
+{
+	semanage_node_t *node;
+	semanage_node_key_t *key = NULL;
+
+	node = get_node_nth(idx);
+
+	CU_ASSERT_FATAL(semanage_node_key_extract(sh, node, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_node_modify_local(sh, key, node) >= 0);
+}
+
+void delete_local_node(int idx)
+{
+	semanage_node_key_t *key = NULL;
+
+	key = get_node_key_nth(idx);
+
+	CU_ASSERT_FATAL(semanage_node_del_local(sh, key) >= 0);
+}
+
+/* Function semanage_node_compare */
+void test_node_compare(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_node_key_t *key1 = NULL;
+	semanage_node_key_t *key2 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	node = get_node_nth(I_FIRST);
+	key1 = get_node_key_nth(I_FIRST);
+	CU_ASSERT(semanage_node_key_create(sh, "192.168.0.1", "255.255.0.0",
+					   SEMANAGE_PROTO_IP4, &key2) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key2);
+
+	/* test */
+	res = semanage_node_compare(node, key1);
+	CU_ASSERT(res == 0);
+	res = semanage_node_compare(node, key2);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_node_free(node);
+	semanage_node_key_free(key1);
+	semanage_node_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_compare2 */
+void test_node_compare2(void)
+{
+	semanage_node_t *node1 = NULL;
+	semanage_node_t *node2 = NULL;
+	semanage_node_t *node3 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	node1 = get_node_nth(I_FIRST);
+	node2 = get_node_nth(I_FIRST);
+	node3 = get_node_nth(I_SECOND);
+
+	/* test */
+	res = semanage_node_compare2(node1, node2);
+	CU_ASSERT(res == 0);
+	res = semanage_node_compare2(node1, node3);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_node_free(node1);
+	semanage_node_free(node2);
+	semanage_node_free(node3);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_key_create */
+void test_node_key_create(void)
+{
+	semanage_node_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_node_key_create(sh, "127.0.0.1", "255.255.255.255",
+					   SEMANAGE_PROTO_IP4, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_node_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_key_extract */
+void test_node_key_extract(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_node_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	node = get_node_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_node_key_extract(sh, node, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_node_free(node);
+	semanage_node_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_addr, semanage_node_set_addr */
+void test_node_get_set_addr(void)
+{
+	semanage_node_t *node = NULL;
+	char *addr = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_set_addr(sh, node, SEMANAGE_PROTO_IP4,
+					 "192.168.0.1") == 0);
+	CU_ASSERT(semanage_node_get_addr(sh, node, &addr) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(addr);
+	assert(addr);
+	CU_ASSERT_STRING_EQUAL(addr, "192.168.0.1");
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_addr_bytes, semanage_node_set_addr_bytes */
+void test_node_get_set_addr_bytes(void)
+{
+	semanage_node_t *node = NULL;
+	char addr1[] = { 192, 168, 0, 1 };
+	size_t addr1_size = sizeof(addr1);
+	char *addr2 = NULL;
+	size_t addr2_size = 0;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_set_addr_bytes(sh, node, addr1,
+					       addr1_size) == 0);
+	CU_ASSERT(semanage_node_get_addr_bytes(sh, node, &addr2,
+					       &addr2_size) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(addr2);
+	assert(addr2);
+
+	for (size_t i = 0; i < addr2_size; i++)
+		CU_ASSERT(addr1[i] == addr2[i]);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_mask, semanage_node_set_mask */
+void test_node_get_set_mask(void)
+{
+	semanage_node_t *node = NULL;
+	char *mask = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_set_mask(sh, node, SEMANAGE_PROTO_IP4,
+					 "255.255.255.0") == 0);
+	CU_ASSERT(semanage_node_get_mask(sh, node, &mask) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(mask);
+	assert(mask);
+	CU_ASSERT_STRING_EQUAL(mask, "255.255.255.0");
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_mask_bytes, semanage_node_set_mask_bytes */
+void test_node_get_set_mask_bytes(void)
+{
+	semanage_node_t *node = NULL;
+	char mask1[] = { 255, 255, 255, 0 };
+	size_t mask1_size = sizeof(mask1);
+	char *mask2 = NULL;
+	size_t mask2_size = 0;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_set_mask_bytes(sh, node, mask1,
+					       mask1_size) == 0);
+	CU_ASSERT(semanage_node_get_mask_bytes(sh, node, &mask2,
+					       &mask2_size) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(mask2);
+	assert(mask2);
+
+	for (size_t i = 0; i < mask2_size; i++)
+		CU_ASSERT(mask1[i] == mask2[i]);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_proto, semanage_node_set_proto */
+void test_node_get_set_proto(void)
+{
+	semanage_node_t *node = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+
+	/* test */
+	semanage_node_set_proto(node, SEMANAGE_PROTO_IP4);
+	CU_ASSERT(semanage_node_get_proto(node) == SEMANAGE_PROTO_IP4);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_get_proto_str */
+void test_node_get_proto_str(void)
+{
+	CU_ASSERT_STRING_EQUAL(semanage_node_get_proto_str(SEMANAGE_PROTO_IP4),
+							   "ipv4");
+	CU_ASSERT_STRING_EQUAL(semanage_node_get_proto_str(SEMANAGE_PROTO_IP6),
+							   "ipv6");
+}
+
+/* Function semanage_node_get_con, semanage_node_set_con */
+void test_node_get_set_con(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "my_user_u:my_role_r:my_type_t:s0", &con1) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_set_con(sh, node, con1) == 0);
+	con2 = semanage_node_get_con(node);
+	CU_ASSERT_CONTEXT_EQUAL(con1, con2);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_create */
+void test_node_create(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_context_t *con = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+	CU_ASSERT(semanage_node_set_addr(sh, node, SEMANAGE_PROTO_IP4,
+					 "127.0.0.1") >= 0);
+	CU_ASSERT(semanage_node_set_mask(sh, node, SEMANAGE_PROTO_IP4,
+					 "255.255.255.0") >= 0);
+	semanage_node_set_proto(node, SEMANAGE_PROTO_IP4);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:type_t:s0",
+					       &con) >= 0);
+	CU_ASSERT(semanage_node_set_con(sh, node, con) >= 0);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_clone */
+void test_node_clone(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_node_t *node_clone = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con2 = NULL;
+	const char *addr1 = "127.0.0.1";
+	char *addr2 = NULL;
+	const char *mask1 = "255.255.255.0";
+	char *mask2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_node_create(sh, &node) >= 0);
+	CU_ASSERT(semanage_node_set_addr(sh, node, SEMANAGE_PROTO_IP4,
+					 addr1) >= 0);
+	CU_ASSERT(semanage_node_set_mask(sh, node, SEMANAGE_PROTO_IP4,
+					 mask1) >= 0);
+	semanage_node_set_proto(node, SEMANAGE_PROTO_IP4);
+	CU_ASSERT(semanage_context_from_string(sh, "user_u:role_r:type_t:s0",
+					       &con) >= 0);
+	CU_ASSERT(semanage_node_set_con(sh, node, con) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_clone(sh, node, &node_clone) >= 0);
+
+	CU_ASSERT(semanage_node_get_addr(sh, node_clone, &addr2) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(addr2);
+	assert(addr2);
+	CU_ASSERT_STRING_EQUAL(addr1, addr2);
+
+	CU_ASSERT(semanage_node_get_mask(sh, node_clone, &mask2) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(mask2);
+	assert(mask2);
+	CU_ASSERT_STRING_EQUAL(mask1, mask2);
+
+	CU_ASSERT(semanage_node_get_proto(node_clone) == SEMANAGE_PROTO_IP4);
+
+	con2 = semanage_node_get_con(node_clone);
+	CU_ASSERT_CONTEXT_EQUAL(con, con2);
+
+	/* cleanup */
+	semanage_node_free(node);
+	semanage_node_free(node_clone);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_query */
+void test_node_query(void)
+{
+	semanage_node_t *node = NULL;
+	semanage_node_t *node_exp = NULL;
+	semanage_node_key_t *key = NULL;
+	char *str = NULL;
+	char *str_exp = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_exp = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key = get_node_key_nth(I_FIRST);
+	node_exp = get_node_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_node_query(sh, key, &node) >= 0);
+
+	CU_ASSERT(semanage_node_get_addr(sh, node, &str) >= 0);
+	CU_ASSERT(semanage_node_get_addr(sh, node_exp, &str_exp) >= 0);
+	CU_ASSERT_STRING_EQUAL(str, str_exp);
+	free(str);
+	free(str_exp);
+
+	CU_ASSERT(semanage_node_get_mask(sh, node, &str) >= 0);
+	CU_ASSERT(semanage_node_get_mask(sh, node_exp, &str_exp) >= 0);
+	CU_ASSERT_STRING_EQUAL(str, str_exp);
+	free(str);
+	free(str_exp);
+
+	CU_ASSERT(semanage_node_get_proto(node) ==
+			  semanage_node_get_proto(node_exp));
+
+	con = semanage_node_get_con(node);
+	con_exp = semanage_node_get_con(node_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	/* cleanup */
+	semanage_node_free(node);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_exists */
+void test_node_exists(void)
+{
+	semanage_node_key_t *key1 = NULL;
+	semanage_node_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key1 = get_node_key_nth(I_FIRST);
+	CU_ASSERT(semanage_node_key_create(sh, "1.2.3.4", "255.255.0.0",
+					   SEMANAGE_PROTO_IP4, &key2) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_node_exists(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_node_exists(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	semanage_node_key_free(key1);
+	semanage_node_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_count */
+void test_node_count(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_node_count(sh, &count) >= 0);
+	CU_ASSERT(count == NODE_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_iterate */
+unsigned int counter_node_iterate = 0;
+
+int handler_node_iterate(const semanage_node_t *record, void *varg)
+{
+	counter_node_iterate++;
+	return 0;
+}
+
+void test_node_iterate(void)
+{
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	semanage_node_iterate(sh, handler_node_iterate, NULL);
+	CU_ASSERT(counter_node_iterate == NODE_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_list */
+void test_node_list(void)
+{
+	semanage_node_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_node_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == NODE_COUNT);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	for (unsigned int i = 0; i < count; i++)
+		semanage_node_free(records[i]);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_node_modify_local, semanage_node_del_local,
+ * semanage_node_query_local
+ */
+void test_node_modify_del_query_local(void)
+{
+	semanage_node_t *node;
+	semanage_node_t *node_local;
+	semanage_node_t *node_tmp;
+	semanage_node_key_t *key = NULL;
+	semanage_node_key_t *key_tmp = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	node = get_node_nth(I_FIRST);
+	CU_ASSERT(semanage_node_key_extract(sh, node, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* add second record, so that semanage_node_compare2_qsort
+	 * will be called
+	 */
+	node_tmp = get_node_nth(I_FIRST);
+
+	CU_ASSERT(semanage_node_set_addr(sh, node_tmp, SEMANAGE_PROTO_IP4,
+					 "10.0.0.1") >= 0);
+	CU_ASSERT(semanage_node_key_extract(sh, node_tmp, &key_tmp) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key_tmp);
+
+	/* test */
+	CU_ASSERT(semanage_node_modify_local(sh, key, node) >= 0);
+	CU_ASSERT(semanage_node_modify_local(sh, key_tmp, node_tmp) >= 0);
+
+	/* write changes to file */
+	helper_commit();
+	helper_begin_transaction();
+
+	CU_ASSERT(semanage_node_query_local(sh, key, &node_local) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(node_local);
+
+	CU_ASSERT(semanage_node_del_local(sh, key) >= 0);
+	CU_ASSERT(semanage_node_del_local(sh, key_tmp) >= 0);
+
+	CU_ASSERT(semanage_node_query_local(sh, key, &node_local) < 0);
+
+	/* cleanup */
+	semanage_node_free(node);
+	semanage_node_free(node_tmp);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_node_exists_local */
+void test_node_exists_local(void)
+{
+	semanage_node_key_t *key1 = NULL;
+	semanage_node_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_node(I_FIRST);
+	key1 = get_node_key_nth(I_FIRST);
+	key2 = get_node_key_nth(I_SECOND);
+
+	/* test */
+	CU_ASSERT(semanage_node_exists_local(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_node_exists_local(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	CU_ASSERT(semanage_node_del_local(sh, key1) >= 0);
+	semanage_node_key_free(key1);
+	semanage_node_key_free(key2);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_node_count_local */
+void test_node_count_local(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+
+	/* test */
+	CU_ASSERT(semanage_node_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	add_local_node(I_FIRST);
+	CU_ASSERT(semanage_node_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	add_local_node(I_SECOND);
+	CU_ASSERT(semanage_node_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 2);
+
+	delete_local_node(I_SECOND);
+	CU_ASSERT(semanage_node_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	delete_local_node(I_FIRST);
+	CU_ASSERT(semanage_node_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_node_iterate_local */
+unsigned int counter_node_iterate_local = 0;
+
+int handler_node_iterate_local(const semanage_node_t *record, void *varg)
+{
+	counter_node_iterate_local++;
+	return 0;
+}
+
+void test_node_iterate_local(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_node(I_FIRST);
+	add_local_node(I_SECOND);
+	add_local_node(I_THIRD);
+
+	/* test */
+	semanage_node_iterate_local(sh, handler_node_iterate_local, NULL);
+	CU_ASSERT(counter_node_iterate_local == 3);
+
+	/* cleanup */
+	delete_local_node(I_FIRST);
+	delete_local_node(I_SECOND);
+	delete_local_node(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_node_list_local */
+void test_node_list_local(void)
+{
+	semanage_node_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_node(I_FIRST);
+	add_local_node(I_SECOND);
+	add_local_node(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_node_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 3);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_node_free(records[i]);
+
+	delete_local_node(I_FIRST);
+	delete_local_node(I_SECOND);
+	delete_local_node(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_node.cil b/libsemanage/tests/test_node.cil
new file mode 100644
index 00000000..1638cd1e
--- /dev/null
+++ b/libsemanage/tests/test_node.cil
@@ -0,0 +1,28 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r first_node_t)
+(roletype object_r second_node_t)
+(roletype object_r third_node_t)
+(type first_node_t)
+(type second_node_t)
+(type third_node_t)
+(sidcontext security (system_u object_r first_node_t ((s0) (s0))))
+(class node (tcp_recv))
+(classorder (node))
+(allow first_node_t self (node (tcp_recv)))
+(nodecon (192.168.0.0) (255.255.255.0) (system_u object_r first_node_t ((s0) (s0))))
+(nodecon (2001:db8:85a3::8a2e:370:7334) (2001:db8:85a3::8a2e:370:7334) (system_u object_r second_node_t ((s0) (s0))))
+(nodecon (127.0.0.1) (255.255.0.0) (system_u object_r third_node_t ((s0) (s0))))
diff --git a/libsemanage/tests/test_node.h b/libsemanage/tests/test_node.h
new file mode 100644
index 00000000..5b329406
--- /dev/null
+++ b/libsemanage/tests/test_node.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_NODE_H__
+#define __TEST_NODE_H__
+
+#include <CUnit/Basic.h>
+
+int node_test_init(void);
+int node_test_cleanup(void);
+int node_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/11] libsemanage: test semanage_port_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (6 preceding siblings ...)
  2019-06-12  8:04 ` [PATCH 07/11] libsemanage: test semanage_node_* functions Jan Zarsky
@ 2019-06-12  8:04 ` Jan Zarsky
  2019-06-12  8:04 ` [PATCH 09/11] libsemanage: test semanage_user_* functions Jan Zarsky
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:04 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_port_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_port.c         | 909 ++++++++++++++++++++++++++
 libsemanage/tests/test_port.cil       |  27 +
 libsemanage/tests/test_port.h         |  30 +
 4 files changed, 968 insertions(+)
 create mode 100644 libsemanage/tests/test_port.c
 create mode 100644 libsemanage/tests/test_port.cil
 create mode 100644 libsemanage/tests/test_port.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index ba24421d..b4a8c122 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -27,6 +27,7 @@
 #include "test_iface.h"
 #include "test_ibendport.h"
 #include "test_node.h"
+#include "test_port.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -71,6 +72,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(iface);
 	DECLARE_SUITE(ibendport);
 	DECLARE_SUITE(node);
+	DECLARE_SUITE(port);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_port.c b/libsemanage/tests/test_port.c
new file mode 100644
index 00000000..0408be4d
--- /dev/null
+++ b/libsemanage/tests/test_port.c
@@ -0,0 +1,909 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_port.h"
+
+#define PORT_COUNT 3
+
+#define PORT1_LOW 80
+#define PORT1_HIGH 80
+#define PORT1_PROTO SEPOL_PROTO_TCP
+
+#define PORT2_LOW 1
+#define PORT2_HIGH 1023
+#define PORT2_PROTO SEPOL_PROTO_UDP
+
+#define PORT3_LOW 12345
+#define PORT3_HIGH 12345
+#define PORT3_PROTO SEPOL_PROTO_TCP
+
+/* port_record.h */
+void test_port_compare(void);
+void test_port_compare2(void);
+void test_port_key_create(void);
+void test_port_key_extract(void);
+void test_port_get_set_proto(void);
+void test_port_get_proto_str(void);
+void test_port_get_set_port(void);
+void test_port_get_set_con(void);
+void test_port_create(void);
+void test_port_clone(void);
+
+/* ports_policy.h */
+void test_port_query(void);
+void test_port_exists(void);
+void test_port_count(void);
+void test_port_iterate(void);
+void test_port_list(void);
+
+/* ports_local.h */
+void test_port_modify_del_local(void);
+void test_port_query_local(void);
+void test_port_exists_local(void);
+void test_port_count_local(void);
+void test_port_iterate_local(void);
+void test_port_list_local(void);
+
+/* internal */
+void test_port_validate_local(void);
+
+extern semanage_handle_t *sh;
+
+int port_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_port.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int port_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int port_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "port_compare", test_port_compare);
+	CU_add_test(suite, "port_compare2", test_port_compare2);
+	CU_add_test(suite, "port_key_create", test_port_key_create);
+	CU_add_test(suite, "port_key_extract", test_port_key_extract);
+	CU_add_test(suite, "port_get_set_proto", test_port_get_set_proto);
+	CU_add_test(suite, "port_get_proto_str", test_port_get_proto_str);
+	CU_add_test(suite, "port_get_set_port", test_port_get_set_port);
+	CU_add_test(suite, "port_get_set_con", test_port_get_set_con);
+	CU_add_test(suite, "port_create", test_port_create);
+	CU_add_test(suite, "port_clone", test_port_clone);
+
+	CU_add_test(suite, "port_query", test_port_query);
+	CU_add_test(suite, "port_exists", test_port_exists);
+	CU_add_test(suite, "port_count", test_port_count);
+	CU_add_test(suite, "port_iterate", test_port_iterate);
+	CU_add_test(suite, "port_list", test_port_list);
+
+	CU_add_test(suite, "port_modify_del_local", test_port_modify_del_local);
+	CU_add_test(suite, "port_query_local", test_port_query_local);
+	CU_add_test(suite, "port_exists_local", test_port_exists_local);
+	CU_add_test(suite, "port_count_local", test_port_count_local);
+	CU_add_test(suite, "port_iterate_local", test_port_iterate_local);
+	CU_add_test(suite, "port_list_local", test_port_list_local);
+
+	CU_add_test(suite, "port_validate_local", test_port_validate_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_port_t *get_port_nth(int idx)
+{
+	int res;
+	semanage_port_t **records;
+	semanage_port_t *port;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	res = semanage_port_list(sh, &records, &count);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	port = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_port_free(records[i]);
+
+	return port;
+}
+
+semanage_port_key_t *get_port_key_nth(int idx)
+{
+	semanage_port_key_t *key;
+	semanage_port_t *port;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	port = get_port_nth(idx);
+
+	res = semanage_port_key_extract(sh, port, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_port(int port_idx)
+{
+	semanage_port_t *port;
+	semanage_port_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(port_idx != I_NULL);
+
+	port = get_port_nth(port_idx);
+
+	CU_ASSERT_FATAL(semanage_port_key_extract(sh, port, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_port_modify_local(sh, key, port) >= 0);
+}
+
+void delete_local_port(int port_idx)
+{
+	semanage_port_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(port_idx != I_NULL);
+
+	key = get_port_key_nth(port_idx);
+
+	CU_ASSERT_FATAL(semanage_port_del_local(sh, key) >= 0);
+}
+
+/* Function semanage_port_compare */
+void helper_port_compare(int idx1, int idx2)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_key_t *key = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	port = get_port_nth(idx1);
+	key = get_port_key_nth(idx2);
+
+	/* test */
+	res = semanage_port_compare(port, key);
+
+	if (idx1 == idx2) {
+		CU_ASSERT(res == 0);
+	} else {
+		CU_ASSERT(res != 0);
+	}
+
+	/* cleanup */
+	semanage_port_free(port);
+	semanage_port_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+void test_port_compare(void)
+{
+	helper_port_compare(I_FIRST,  I_FIRST);
+	helper_port_compare(I_FIRST,  I_SECOND);
+	helper_port_compare(I_SECOND, I_FIRST);
+	helper_port_compare(I_SECOND, I_SECOND);
+}
+
+/* Function semanage_port_compare2 */
+void helper_port_compare2(int idx1, int idx2)
+{
+	semanage_port_t *port1 = NULL;
+	semanage_port_t *port2 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	port1 = get_port_nth(idx1);
+	port2 = get_port_nth(idx2);
+
+	/* test */
+	res = semanage_port_compare2(port1, port2);
+
+	if (idx1 == idx2) {
+		CU_ASSERT(res == 0);
+	} else {
+		CU_ASSERT(res != 0);
+	}
+
+	/* cleanup */
+	semanage_port_free(port1);
+	semanage_port_free(port2);
+	cleanup_handle(SH_CONNECT);
+}
+
+void test_port_compare2(void)
+{
+	helper_port_compare2(I_FIRST,  I_FIRST);
+	helper_port_compare2(I_FIRST,  I_SECOND);
+	helper_port_compare2(I_SECOND, I_FIRST);
+	helper_port_compare2(I_SECOND, I_SECOND);
+}
+
+/* Function semanage_port_create */
+void test_port_key_create(void)
+{
+	semanage_port_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_port_key_create(sh, 1000, 1200, 0, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_port_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_extract */
+void test_port_key_extract(void)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	port = get_port_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_port_key_extract(sh, port, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_port_free(port);
+	semanage_port_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_get_proto, semanage_port_set_proto */
+void helper_port_get_set_proto(int idx)
+{
+	semanage_port_t *port = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	port = get_port_nth(idx);
+
+	/* test */
+	semanage_port_set_proto(port, 0);
+	CU_ASSERT(semanage_port_get_proto(port) == 0);
+	semanage_port_set_proto(port, 1);
+	CU_ASSERT(semanage_port_get_proto(port) == 1);
+
+	/* cleanup */
+	semanage_port_free(port);
+	cleanup_handle(SH_CONNECT);
+}
+
+void test_port_get_set_proto(void)
+{
+	helper_port_get_set_proto(I_FIRST);
+	helper_port_get_set_proto(I_SECOND);
+}
+
+/* Function semanage_port_get_proto_str */
+void test_port_get_proto_str(void)
+{
+	const char *str = NULL;
+
+	str = semanage_port_get_proto_str(-1);
+	CU_ASSERT_STRING_EQUAL(str, "???");
+
+	str = semanage_port_get_proto_str(0);
+	CU_ASSERT_STRING_EQUAL(str, "udp");
+
+	str = semanage_port_get_proto_str(1);
+	CU_ASSERT_STRING_EQUAL(str, "tcp");
+
+	str = semanage_port_get_proto_str(2);
+	CU_ASSERT_STRING_EQUAL(str, "dccp");
+
+	str = semanage_port_get_proto_str(3);
+	CU_ASSERT_STRING_EQUAL(str, "sctp");
+
+	str = semanage_port_get_proto_str(4);
+	CU_ASSERT_STRING_EQUAL(str, "???");
+}
+
+/* Function semanage_port_get_low, semanage_port_get_high, */
+/* semanage_port_set_port, semanage_port_set_range */
+void test_port_get_set_port(void)
+{
+	semanage_port_t *port = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	port = get_port_nth(I_FIRST);
+
+	/* test */
+	semanage_port_set_port(port, 1000);
+	CU_ASSERT(semanage_port_get_low(port) == 1000);
+	CU_ASSERT(semanage_port_get_high(port) == 1000);
+
+	semanage_port_set_range(port, 1000, 1200);
+	CU_ASSERT(semanage_port_get_low(port) == 1000);
+	CU_ASSERT(semanage_port_get_high(port) == 1200);
+
+	/* cleanup */
+	semanage_port_free(port);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_get_con, semanage_port_set_con */
+void test_port_get_set_con(void)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_t *port_tmp = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	port = get_port_nth(I_FIRST);
+	port_tmp = get_port_nth(I_SECOND);
+	con1 = semanage_port_get_con(port_tmp);
+
+	/* test */
+	CU_ASSERT(semanage_port_set_con(sh, port, con1) >= 0);
+	con2 = semanage_port_get_con(port);
+	CU_ASSERT_CONTEXT_EQUAL(con1, con2);
+
+	/* cleanup */
+	semanage_port_free(port);
+	semanage_port_free(port_tmp);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_create */
+void test_port_create(void)
+{
+	semanage_port_t *port = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_port_create(sh, &port) >= 0);
+	CU_ASSERT(semanage_port_get_low(port) == 0);
+	CU_ASSERT(semanage_port_get_high(port) == 0);
+	CU_ASSERT(semanage_port_get_con(port) == NULL);
+	CU_ASSERT(semanage_port_get_proto(port) == 0);
+
+	/* cleanup */
+	semanage_port_free(port);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_clone */
+void test_port_clone(void)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_t *port_clone = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_port_create(sh, &port) >= 0);
+	semanage_port_set_range(port, 1000, 1200);
+	semanage_port_set_proto(port, 1);
+	semanage_context_from_string(sh, "user_u:role_r:type_t:s0", &con);
+	semanage_port_set_con(sh, port, con);
+
+	/* test */
+	CU_ASSERT(semanage_port_clone(sh, port, &port_clone) >= 0);
+	CU_ASSERT(semanage_port_get_low(port_clone) == 1000);
+	CU_ASSERT(semanage_port_get_high(port_clone) == 1200);
+	CU_ASSERT(semanage_port_get_proto(port_clone) == 1);
+
+	con2 = semanage_port_get_con(port_clone);
+	CU_ASSERT_CONTEXT_EQUAL(con, con2);
+
+	/* cleanup */
+	semanage_port_free(port);
+	semanage_port_free(port_clone);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_query */
+void test_port_query(void)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_t *port_exp = NULL;
+	semanage_port_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_exp = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key = get_port_key_nth(I_FIRST);
+	port_exp = get_port_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_port_query(sh, key, &port) >= 0);
+	CU_ASSERT(semanage_port_get_low(port) ==
+			  semanage_port_get_low(port_exp));
+	CU_ASSERT(semanage_port_get_high(port) ==
+			  semanage_port_get_high(port_exp));
+	CU_ASSERT(semanage_port_get_proto(port) ==
+			  semanage_port_get_proto(port_exp));
+
+	con = semanage_port_get_con(port);
+	con_exp = semanage_port_get_con(port_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	/* cleanup */
+	semanage_port_free(port);
+	semanage_port_free(port_exp);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_exists */
+void test_port_exists(void)
+{
+	semanage_port_key_t *key1 = NULL;
+	semanage_port_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key1 = get_port_key_nth(I_FIRST);
+	CU_ASSERT(semanage_port_key_create(sh, 123, 456, 0, &key2) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_port_exists(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_port_exists(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	semanage_port_key_free(key1);
+	semanage_port_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_count */
+void test_port_count(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_port_count(sh, &count) >= 0);
+	CU_ASSERT(count == PORT_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_iterate */
+unsigned int counter_port_iterate = 0;
+
+int handler_port_iterate(const semanage_port_t *record, void *varg)
+{
+	counter_port_iterate++;
+	return 0;
+}
+
+void test_port_iterate(void)
+{
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	semanage_port_iterate(sh, handler_port_iterate, NULL);
+	CU_ASSERT(counter_port_iterate == PORT_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_list */
+void test_port_list(void)
+{
+	semanage_port_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_port_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == PORT_COUNT);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_port_free(records[i]);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_port_modify_local, semanage_port_del_local */
+void test_port_modify_del_local(void)
+{
+	semanage_port_t *port;
+	semanage_port_t *port_local;
+	semanage_port_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_local = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	port = get_port_nth(I_FIRST);
+	semanage_context_from_string(sh, "user_u:role_r:type_t:s0", &con);
+	semanage_port_set_con(sh, port, con);
+	CU_ASSERT(semanage_port_key_extract(sh, port, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* test */
+	CU_ASSERT(semanage_port_modify_local(sh, key, port) >= 0);
+	CU_ASSERT(semanage_port_query_local(sh, key, &port_local) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(port_local);
+
+	con_local = semanage_port_get_con(port_local);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_local);
+
+	CU_ASSERT(semanage_port_del_local(sh, key) >= 0);
+	CU_ASSERT(semanage_port_query_local(sh, key, &port_local) < 0);
+
+	/* cleanup */
+	semanage_port_free(port);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_port_query_local */
+void test_port_query_local(void)
+{
+	semanage_port_t *port = NULL;
+	semanage_port_t *port_exp = NULL;
+	semanage_port_key_t *key = NULL;
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_exp = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+	key = get_port_key_nth(I_FIRST);
+	port_exp = get_port_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_port_query_local(sh, key, &port) >= 0);
+	CU_ASSERT(semanage_port_get_low(port) ==
+			  semanage_port_get_low(port_exp));
+	CU_ASSERT(semanage_port_get_high(port) ==
+			  semanage_port_get_high(port_exp));
+	CU_ASSERT(semanage_port_get_proto(port) ==
+			  semanage_port_get_proto(port_exp));
+
+	con = semanage_port_get_con(port);
+	con_exp = semanage_port_get_con(port_exp);
+	CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
+
+	/* cleanup */
+	delete_local_port(I_FIRST);
+	semanage_port_free(port);
+	semanage_port_free(port_exp);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_port_exists_local */
+void test_port_exists_local(void)
+{
+	semanage_port_key_t *key1 = NULL;
+	semanage_port_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+	key1 = get_port_key_nth(I_FIRST);
+	key2 = get_port_key_nth(I_SECOND);
+
+	/* test */
+	CU_ASSERT(semanage_port_exists_local(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_port_exists_local(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	delete_local_port(I_FIRST);
+	semanage_port_key_free(key1);
+	semanage_port_key_free(key2);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_port_count_local */
+void test_port_count_local(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+
+	/* test */
+	CU_ASSERT(semanage_port_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	add_local_port(I_FIRST);
+	CU_ASSERT(semanage_port_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	add_local_port(I_SECOND);
+	CU_ASSERT(semanage_port_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 2);
+
+	delete_local_port(I_SECOND);
+	CU_ASSERT(semanage_port_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 1);
+
+	delete_local_port(I_FIRST);
+	CU_ASSERT(semanage_port_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 0);
+
+	/* cleanup */
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_port_iterate_local */
+unsigned int counter_port_iterate_local = 0;
+
+int handler_port_iterate_local(const semanage_port_t *record, void *varg)
+{
+	counter_port_iterate_local++;
+	return 0;
+}
+
+void test_port_iterate_local(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+	add_local_port(I_SECOND);
+	add_local_port(I_THIRD);
+
+	/* test */
+	semanage_port_iterate_local(sh, handler_port_iterate_local, NULL);
+	CU_ASSERT(counter_port_iterate_local == 3);
+
+	/* cleanup */
+	delete_local_port(I_FIRST);
+	delete_local_port(I_SECOND);
+	delete_local_port(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_port_list_local */
+void test_port_list_local(void)
+{
+	semanage_port_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+	add_local_port(I_SECOND);
+	add_local_port(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_port_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 3);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_port_free(records[i]);
+
+	delete_local_port(I_FIRST);
+	delete_local_port(I_SECOND);
+	delete_local_port(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Internal function semanage_port_validate_local */
+void helper_port_validate_local_noport(void)
+{
+	semanage_port_key_t *key = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+	helper_commit();
+	key = get_port_key_nth(I_FIRST);
+	CU_ASSERT(semanage_port_exists_local(sh, key, &resp) >= 0);
+	CU_ASSERT(resp);
+
+	/* test */
+	helper_begin_transaction();
+	delete_local_port(I_FIRST);
+	helper_commit();
+
+	/* cleanup */
+	helper_begin_transaction();
+	delete_local_port(I_FIRST);
+	cleanup_handle(SH_TRANS);
+}
+
+void helper_port_validate_local_oneport(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_port(I_FIRST);
+
+	/* test */
+	helper_commit();
+
+	/* cleanup */
+	helper_begin_transaction();
+	delete_local_port(I_FIRST);
+	cleanup_handle(SH_TRANS);
+}
+
+void helper_port_validate_local_twoports(void)
+{
+	semanage_port_key_t *key1 = NULL;
+	semanage_port_key_t *key2 = NULL;
+	semanage_port_t *port1 = NULL;
+	semanage_port_t *port2 = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	CU_ASSERT(semanage_port_key_create(sh, 101, 200, 0, &key1) >= 0);
+	CU_ASSERT(semanage_port_key_create(sh, 201, 300, 0, &key2) >= 0);
+	CU_ASSERT(semanage_port_create(sh, &port1) >= 0);
+	CU_ASSERT(semanage_port_create(sh, &port2) >= 0);
+
+	semanage_port_set_range(port1, 101, 200);
+	semanage_port_set_range(port2, 201, 300);
+	semanage_port_set_proto(port1, 0);
+	semanage_port_set_proto(port2, 0);
+
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "system_u:object_r:user_home_t:s0", &con1) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh,
+				"system_u:object_r:user_tmp_t:s0", &con2) >= 0);
+
+	semanage_port_set_con(sh, port1, con1);
+	semanage_port_set_con(sh, port2, con2);
+
+	CU_ASSERT(semanage_port_modify_local(sh, key1, port1) >= 0);
+	CU_ASSERT(semanage_port_modify_local(sh, key2, port2) >= 0);
+
+	/* test */
+	helper_commit();
+
+	/* cleanup */
+	helper_begin_transaction();
+	CU_ASSERT(semanage_port_del_local(sh, key1) >= 0);
+	CU_ASSERT(semanage_port_del_local(sh, key2) >= 0);
+	semanage_port_key_free(key1);
+	semanage_port_key_free(key2);
+	semanage_port_free(port1);
+	semanage_port_free(port2);
+	cleanup_handle(SH_TRANS);
+}
+
+void helper_port_validate_local_proto(void)
+{
+	semanage_port_key_t *key1 = NULL;
+	semanage_port_key_t *key2 = NULL;
+	semanage_port_key_t *key3 = NULL;
+	semanage_port_t *port1 = NULL;
+	semanage_port_t *port2 = NULL;
+	semanage_port_t *port3 = NULL;
+	semanage_context_t *con1 = NULL;
+	semanage_context_t *con2 = NULL;
+	semanage_context_t *con3 = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+
+	CU_ASSERT(semanage_port_key_create(sh, 101, 200, 0, &key1) >= 0);
+	CU_ASSERT(semanage_port_key_create(sh,  51, 250, 1, &key2) >= 0);
+	CU_ASSERT(semanage_port_key_create(sh, 201, 300, 0, &key3) >= 0);
+
+	CU_ASSERT(semanage_port_create(sh, &port1) >= 0);
+	CU_ASSERT(semanage_port_create(sh, &port2) >= 0);
+	CU_ASSERT(semanage_port_create(sh, &port3) >= 0);
+
+	semanage_port_set_range(port1, 101, 200);
+	semanage_port_set_range(port2,  51, 250);
+	semanage_port_set_range(port3, 201, 300);
+
+	semanage_port_set_proto(port1, 0);
+	semanage_port_set_proto(port2, 0);
+	semanage_port_set_proto(port3, 0);
+
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "system_u:object_r:user_home_t:s0", &con1) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh,
+			       "system_u:object_r:user_home_t:s0", &con2) >= 0);
+	CU_ASSERT(semanage_context_from_string(sh,
+				"system_u:object_r:user_tmp_t:s0", &con3) >= 0);
+
+	semanage_port_set_con(sh, port1, con1);
+	semanage_port_set_con(sh, port2, con2);
+	semanage_port_set_con(sh, port3, con3);
+
+	CU_ASSERT(semanage_port_modify_local(sh, key1, port1) >= 0);
+	CU_ASSERT(semanage_port_modify_local(sh, key2, port2) >= 0);
+	CU_ASSERT(semanage_port_modify_local(sh, key3, port3) >= 0);
+
+	/* test */
+	helper_commit();
+
+	/* cleanup */
+	CU_ASSERT(semanage_port_del_local(sh, key1) >= 0);
+	CU_ASSERT(semanage_port_del_local(sh, key2) >= 0);
+	CU_ASSERT(semanage_port_del_local(sh, key3) >= 0);
+	semanage_port_key_free(key1);
+	semanage_port_key_free(key2);
+	semanage_port_key_free(key3);
+	semanage_port_free(port1);
+	semanage_port_free(port2);
+	semanage_port_free(port3);
+	cleanup_handle(SH_TRANS);
+}
+
+void test_port_validate_local(void)
+{
+	helper_port_validate_local_noport();
+	helper_port_validate_local_oneport();
+	helper_port_validate_local_twoports();
+}
diff --git a/libsemanage/tests/test_port.cil b/libsemanage/tests/test_port.cil
new file mode 100644
index 00000000..7e07a61c
--- /dev/null
+++ b/libsemanage/tests/test_port.cil
@@ -0,0 +1,27 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user system_u)
+(userrole system_u object_r)
+(userlevel system_u (s0))
+(userrange system_u ((s0) (s0)))
+(role object_r)
+(roletype object_r first_port_t)
+(roletype object_r second_port_t)
+(roletype object_r third_port_t)
+(type first_port_t)
+(type second_port_t)
+(type third_port_t)
+(sidcontext security (system_u object_r first_port_t ((s0) (s0))))
+(class file (open))
+(classorder (file))
+(allow first_port_t self (file (open)))
+(portcon tcp 80 (system_u object_r first_port_t ((s0) (s0))))
+(portcon udp (1 1023) (system_u object_r second_port_t ((s0) (s0))))
+(portcon tcp 12345 (system_u object_r third_port_t ((s0) (s0))))
diff --git a/libsemanage/tests/test_port.h b/libsemanage/tests/test_port.h
new file mode 100644
index 00000000..ad26f90b
--- /dev/null
+++ b/libsemanage/tests/test_port.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_PORT_H__
+#define __TEST_PORT_H__
+
+#include <CUnit/Basic.h>
+
+int port_test_init(void);
+int port_test_cleanup(void);
+int port_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/11] libsemanage: test semanage_user_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (7 preceding siblings ...)
  2019-06-12  8:04 ` [PATCH 08/11] libsemanage: test semanage_port_* functions Jan Zarsky
@ 2019-06-12  8:04 ` Jan Zarsky
  2019-06-12  8:04 ` [PATCH 10/11] libsemanage: test semanage_context_* functions Jan Zarsky
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:04 UTC (permalink / raw)
  To: selinux

Add new test suite for semanage_user_* functions. The test suite aims for line
coverage and covers expected usage of functions. The test suite uses custom
semanage store and policy written in CIL, it does not require running on SELinux
enabled system.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |   2 +
 libsemanage/tests/test_user.c         | 690 ++++++++++++++++++++++++++
 libsemanage/tests/test_user.cil       |  27 +
 libsemanage/tests/test_user.h         |  30 ++
 4 files changed, 749 insertions(+)
 create mode 100644 libsemanage/tests/test_user.c
 create mode 100644 libsemanage/tests/test_user.cil
 create mode 100644 libsemanage/tests/test_user.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index b4a8c122..64039b5d 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -28,6 +28,7 @@
 #include "test_ibendport.h"
 #include "test_node.h"
 #include "test_port.h"
+#include "test_user.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -73,6 +74,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(ibendport);
 	DECLARE_SUITE(node);
 	DECLARE_SUITE(port);
+	DECLARE_SUITE(user);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_user.c b/libsemanage/tests/test_user.c
new file mode 100644
index 00000000..cd082030
--- /dev/null
+++ b/libsemanage/tests/test_user.c
@@ -0,0 +1,690 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_user.h"
+
+#define USER_COUNT 3
+
+/* user_record.h */
+void test_user_compare(void);
+void test_user_compare2(void);
+void test_user_key_create(void);
+void test_user_key_extract(void);
+void test_user_get_set_name(void);
+void test_user_get_set_prefix(void);
+void test_user_get_set_mlslevel(void);
+void test_user_get_set_mlsrange(void);
+void test_user_roles(void);
+void test_user_create(void);
+void test_user_clone(void);
+
+/* users_policy.h */
+void test_user_query(void);
+void test_user_exists(void);
+void test_user_count(void);
+void test_user_iterate(void);
+void test_user_list(void);
+
+/* users_local.h */
+void test_user_modify_del_query_local(void);
+void test_user_exists_local(void);
+void test_user_count_local(void);
+void test_user_iterate_local(void);
+void test_user_list_local(void);
+
+extern semanage_handle_t *sh;
+
+int user_test_init(void)
+{
+	if (create_test_store() < 0) {
+		fprintf(stderr, "Could not create test store\n");
+		return 1;
+	}
+
+	if (write_test_policy_from_file("test_user.policy") < 0) {
+		fprintf(stderr, "Could not write test policy\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int user_test_cleanup(void)
+{
+	if (destroy_test_store() < 0) {
+		fprintf(stderr, "Could not destroy test store\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int user_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "user_compare", test_user_compare);
+	CU_add_test(suite, "user_compare2", test_user_compare2);
+	CU_add_test(suite, "user_key_create", test_user_key_create);
+	CU_add_test(suite, "user_key_extract", test_user_key_extract);
+	CU_add_test(suite, "user_get_set_name", test_user_get_set_name);
+	CU_add_test(suite, "user_get_set_prefix", test_user_get_set_prefix);
+	CU_add_test(suite, "user_get_set_mlslevel", test_user_get_set_mlslevel);
+	CU_add_test(suite, "user_get_set_mlsrange", test_user_get_set_mlsrange);
+	CU_add_test(suite, "user_roles", test_user_roles);
+	CU_add_test(suite, "user_create", test_user_create);
+	CU_add_test(suite, "user_clone", test_user_clone);
+
+	CU_add_test(suite, "user_query", test_user_query);
+	CU_add_test(suite, "user_exists", test_user_exists);
+	CU_add_test(suite, "user_count", test_user_count);
+	CU_add_test(suite, "user_iterate", test_user_iterate);
+	CU_add_test(suite, "user_list", test_user_list);
+
+	CU_add_test(suite, "user_modify_del_query_local",
+				test_user_modify_del_query_local);
+	CU_add_test(suite, "user_exists_local", test_user_exists_local);
+	CU_add_test(suite, "user_count_local", test_user_count_local);
+	CU_add_test(suite, "user_iterate_local", test_user_iterate_local);
+	CU_add_test(suite, "user_list_local", test_user_list_local);
+
+	return 0;
+}
+
+/* Helpers */
+
+semanage_user_t *get_user_nth(int idx)
+{
+	int res;
+	semanage_user_t **records;
+	semanage_user_t *user;
+	unsigned int count;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	res = semanage_user_list(sh, &records, &count);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_FATAL(count >= (unsigned int) idx + 1);
+
+	user = records[idx];
+
+	for (unsigned int i = 0; i < count; i++)
+		if (i != (unsigned int) idx)
+			semanage_user_free(records[i]);
+
+	return user;
+}
+
+semanage_user_key_t *get_user_key_nth(int idx)
+{
+	semanage_user_key_t *key;
+	semanage_user_t *user;
+	int res;
+
+	if (idx == I_NULL)
+		return NULL;
+
+	user = get_user_nth(idx);
+
+	res = semanage_user_key_extract(sh, user, &key);
+
+	CU_ASSERT_FATAL(res >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	return key;
+}
+
+void add_local_user(int user_idx)
+{
+	semanage_user_t *user;
+	semanage_user_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(user_idx != I_NULL);
+
+	user = get_user_nth(user_idx);
+
+	CU_ASSERT_FATAL(semanage_user_key_extract(sh, user, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+
+	CU_ASSERT_FATAL(semanage_user_modify_local(sh, key, user) >= 0);
+}
+
+void delete_local_user(int user_idx)
+{
+	semanage_user_key_t *key = NULL;
+
+	CU_ASSERT_FATAL(user_idx != I_NULL);
+
+	key = get_user_key_nth(user_idx);
+
+	CU_ASSERT_FATAL(semanage_user_del_local(sh, key) >= 0);
+}
+
+/* Function semanage_user_compare */
+void test_user_compare(void)
+{
+	semanage_user_t *user = NULL;
+	semanage_user_key_t *key1 = NULL;
+	semanage_user_key_t *key2 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	user = get_user_nth(I_FIRST);
+	key1 = get_user_key_nth(I_FIRST);
+	key2 = get_user_key_nth(I_SECOND);
+
+	/* test */
+	res = semanage_user_compare(user, key1);
+	CU_ASSERT(res == 0);
+	res = semanage_user_compare(user, key2);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_user_free(user);
+	semanage_user_key_free(key1);
+	semanage_user_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_compare2 */
+void test_user_compare2(void)
+{
+	semanage_user_t *user1 = NULL;
+	semanage_user_t *user2 = NULL;
+	semanage_user_t *user3 = NULL;
+	int res = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	user1 = get_user_nth(I_FIRST);
+	user2 = get_user_nth(I_FIRST);
+	user3 = get_user_nth(I_SECOND);
+
+	/* test */
+	res = semanage_user_compare2(user1, user2);
+	CU_ASSERT(res == 0);
+	res = semanage_user_compare2(user1, user3);
+	CU_ASSERT(res != 0);
+
+	/* cleanup */
+	semanage_user_free(user1);
+	semanage_user_free(user2);
+	semanage_user_free(user3);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_key_create */
+void test_user_key_create(void)
+{
+	semanage_user_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_user_key_create(sh, "asdf", &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_user_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_key_extract */
+void test_user_key_extract(void)
+{
+	semanage_user_t *user = NULL;
+	semanage_user_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	user = get_user_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_user_key_extract(sh, user, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* cleanup */
+	semanage_user_free(user);
+	semanage_user_key_free(key);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_get_name, semanage_user_set_name */
+void test_user_get_set_name(void)
+{
+	semanage_user_t *user = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_set_name(sh, user, "user_u") == 0);
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_name(user), "user_u");
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_get_prefix, semanage_user_set_prefix */
+void test_user_get_set_prefix(void)
+{
+	semanage_user_t *user = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_set_prefix(sh, user, "user") == 0);
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_prefix(user), "user");
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_get_mlslevel, semanage_user_set_mlslevel */
+void test_user_get_set_mlslevel(void)
+{
+	semanage_user_t *user = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_set_mlslevel(sh, user, "s0") == 0);
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_mlslevel(user), "s0");
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_get_mlsrange, semanage_user_set_mlsrange */
+void test_user_get_set_mlsrange(void)
+{
+	semanage_user_t *user = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_set_mlsrange(sh, user, "s0-s15") == 0);
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_mlsrange(user), "s0-s15");
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_get_num_roles, semanage_user_add_role,
+ * semanage_user_del_role, semanage_user_has_role, semanage_user_get_roles
+ * semanage_user_set_roles
+ */
+void test_user_roles(void)
+{
+	semanage_user_t *user = NULL;
+	const char **roles_arr = NULL;
+	unsigned int num_roles = 42;
+	const char *new_roles_arr[] = { "new_role_r", "new_my_role_r" };
+	unsigned int new_num_roles = 2;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_get_num_roles(user) == 0);
+
+	CU_ASSERT(semanage_user_add_role(sh, user, "role_r") == 0);
+	CU_ASSERT(semanage_user_get_num_roles(user) == 1);
+
+	CU_ASSERT(semanage_user_has_role(user, "role_r"));
+	CU_ASSERT(!semanage_user_has_role(user, "my_role_r"));
+
+	CU_ASSERT(semanage_user_add_role(sh, user, "my_role_r") == 0);
+	CU_ASSERT(semanage_user_get_num_roles(user) == 2);
+
+	CU_ASSERT(semanage_user_get_roles(sh, user, &roles_arr,
+					  &num_roles) >= 0);
+	CU_ASSERT(num_roles == 2);
+	CU_ASSERT_STRING_EQUAL(roles_arr[0], "role_r");
+	CU_ASSERT_STRING_EQUAL(roles_arr[1], "my_role_r");
+
+	CU_ASSERT(semanage_user_set_roles(sh, user, new_roles_arr,
+					  new_num_roles) >= 0);
+
+	CU_ASSERT(semanage_user_has_role(user, "new_role_r"));
+	CU_ASSERT(semanage_user_has_role(user, "new_my_role_r"));
+
+	CU_ASSERT(!semanage_user_has_role(user, "role_r"));
+	CU_ASSERT(!semanage_user_has_role(user, "my_role_r"));
+
+	semanage_user_del_role(user, "new_my_role_r");
+	CU_ASSERT(semanage_user_get_num_roles(user) == 1);
+
+	semanage_user_del_role(user, "new_role_r");
+	CU_ASSERT(semanage_user_get_num_roles(user) == 0);
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_create */
+void test_user_create(void)
+{
+	semanage_user_t *user = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+	CU_ASSERT(semanage_user_set_name(sh, user, "user_u") >= 0);
+	CU_ASSERT(semanage_user_set_prefix(sh, user, "user") >= 0);
+	CU_ASSERT(semanage_user_set_mlslevel(sh, user, "s0") >= 0);
+	CU_ASSERT(semanage_user_set_mlsrange(sh, user, "s0-s15") >= 0);
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_clone */
+void test_user_clone(void)
+{
+	semanage_user_t *user = NULL;
+	semanage_user_t *user_clone = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	CU_ASSERT(semanage_user_create(sh, &user) >= 0);
+	CU_ASSERT(semanage_user_set_name(sh, user, "user_u") >= 0);
+	CU_ASSERT(semanage_user_set_prefix(sh, user, "user") >= 0);
+	CU_ASSERT(semanage_user_set_mlslevel(sh, user, "s0") >= 0);
+	CU_ASSERT(semanage_user_set_mlsrange(sh, user, "s0-s15") >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_clone(sh, user, &user_clone) >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_name(user), "user_u");
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_prefix(user), "user");
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_mlslevel(user), "s0");
+	CU_ASSERT_STRING_EQUAL(semanage_user_get_mlsrange(user), "s0-s15");
+
+	/* cleanup */
+	semanage_user_free(user);
+	semanage_user_free(user_clone);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_query */
+void test_user_query(void)
+{
+	semanage_user_t *user = NULL;
+	semanage_user_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key = get_user_key_nth(I_FIRST);
+
+	/* test */
+	CU_ASSERT(semanage_user_query(sh, key, &user) >= 0);
+
+	/* TODO: test values */
+	CU_ASSERT_PTR_NOT_NULL(user);
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_exists */
+void test_user_exists(void)
+{
+	semanage_user_key_t *key1 = NULL;
+	semanage_user_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+	key1 = get_user_key_nth(I_FIRST);
+	CU_ASSERT(semanage_user_key_create(sh, "asdf", &key2) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_user_exists(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_user_exists(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	semanage_user_key_free(key1);
+	semanage_user_key_free(key2);
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_count */
+void test_user_count(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_user_count(sh, &count) >= 0);
+	CU_ASSERT(count == USER_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_iterate */
+unsigned int counter_user_iterate = 0;
+
+int handler_user_iterate(const semanage_user_t *record, void *varg)
+{
+	counter_user_iterate++;
+	return 0;
+}
+
+void test_user_iterate(void)
+{
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	semanage_user_iterate(sh, handler_user_iterate, NULL);
+	CU_ASSERT(counter_user_iterate == USER_COUNT);
+
+	/* cleanup */
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_list */
+void test_user_list(void)
+{
+	semanage_user_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_user_list(sh, &records, &count) >= 0);
+	CU_ASSERT(count == USER_COUNT);
+
+	/* TODO: check real values */
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_user_free(records[i]);
+
+	cleanup_handle(SH_CONNECT);
+}
+
+/* Function semanage_user_modify_local, semanage_user_del_local,
+ * semanage_user_query_local
+ */
+void test_user_modify_del_query_local(void)
+{
+	semanage_user_t *user;
+	semanage_user_t *user_local;
+	semanage_user_key_t *key = NULL;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	user = get_user_nth(I_FIRST);
+	CU_ASSERT(semanage_user_key_extract(sh, user, &key) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key);
+
+	/* test */
+	CU_ASSERT(semanage_user_modify_local(sh, key, user) >= 0);
+
+	/* write changes to file */
+	helper_commit();
+	helper_begin_transaction();
+
+	CU_ASSERT(semanage_user_query_local(sh, key, &user_local) >= 0);
+	CU_ASSERT_PTR_NOT_NULL_FATAL(user_local);
+	CU_ASSERT(semanage_user_del_local(sh, key) >= 0);
+	CU_ASSERT(semanage_user_query_local(sh, key, &user_local) < 0);
+
+	/* cleanup */
+	semanage_user_free(user);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_user_exists_local */
+void test_user_exists_local(void)
+{
+	semanage_user_t *user = NULL;
+	semanage_user_key_t *key1 = NULL;
+	semanage_user_key_t *key2 = NULL;
+	int resp = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_user(I_FIRST);
+	key1 = get_user_key_nth(I_FIRST);
+	CU_ASSERT(semanage_user_key_create(sh, "asdf", &key2) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(key2);
+
+	/* test */
+	CU_ASSERT(semanage_user_exists_local(sh, key1, &resp) >= 0);
+	CU_ASSERT(resp);
+	CU_ASSERT(semanage_user_exists_local(sh, key2, &resp) >= 0);
+	CU_ASSERT(!resp);
+
+	/* cleanup */
+	CU_ASSERT(semanage_user_del_local(sh, key1) >= 0);
+	semanage_user_free(user);
+	semanage_user_key_free(key1);
+	semanage_user_key_free(key2);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_user_count_local */
+void test_user_count_local(void)
+{
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_user(I_FIRST);
+	add_local_user(I_SECOND);
+	add_local_user(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_user_count_local(sh, &count) >= 0);
+	CU_ASSERT(count == 3);
+
+	/* cleanup */
+	delete_local_user(I_FIRST);
+	delete_local_user(I_SECOND);
+	delete_local_user(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_user_iterate_local */
+unsigned int counter_user_iterate_local = 0;
+
+int handler_user_iterate_local(const semanage_user_t *record, void *varg)
+{
+	counter_user_iterate_local++;
+	return 0;
+}
+
+void test_user_iterate_local(void)
+{
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_user(I_FIRST);
+	add_local_user(I_SECOND);
+	add_local_user(I_THIRD);
+
+	/* test */
+	semanage_user_iterate_local(sh, handler_user_iterate_local, NULL);
+	CU_ASSERT(counter_user_iterate_local == 3);
+
+	/* cleanup */
+	delete_local_user(I_FIRST);
+	delete_local_user(I_SECOND);
+	delete_local_user(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
+
+/* Function semanage_user_list_local */
+void test_user_list_local(void)
+{
+	semanage_user_t **records = NULL;
+	unsigned int count = 42;
+
+	/* setup */
+	setup_handle(SH_TRANS);
+	add_local_user(I_FIRST);
+	add_local_user(I_SECOND);
+	add_local_user(I_THIRD);
+
+	/* test */
+	CU_ASSERT(semanage_user_list_local(sh, &records, &count) >= 0);
+	CU_ASSERT(count == 3);
+
+	for (unsigned int i = 0; i < count; i++)
+		CU_ASSERT_PTR_NOT_NULL(records[i]);
+
+	/* cleanup */
+	for (unsigned int i = 0; i < count; i++)
+		semanage_user_free(records[i]);
+
+	delete_local_user(I_FIRST);
+	delete_local_user(I_SECOND);
+	delete_local_user(I_THIRD);
+	cleanup_handle(SH_TRANS);
+}
diff --git a/libsemanage/tests/test_user.cil b/libsemanage/tests/test_user.cil
new file mode 100644
index 00000000..1c65b9fc
--- /dev/null
+++ b/libsemanage/tests/test_user.cil
@@ -0,0 +1,27 @@
+(typeattribute cil_gen_require)
+(roleattribute cil_gen_require)
+(handleunknown allow)
+(mls true)
+(policycap network_peer_controls)
+(policycap open_perms)
+(sid security)
+(sidorder (security))
+(sensitivity s0)
+(sensitivityorder (s0))
+(user first_u)
+(user second_u)
+(user third_u)
+(userrole first_u object_r)
+(userlevel first_u (s0))
+(userlevel second_u (s0))
+(userlevel third_u (s0))
+(userrange first_u ((s0) (s0)))
+(userrange second_u ((s0) (s0)))
+(userrange third_u ((s0) (s0)))
+(role object_r)
+(roletype object_r test_t)
+(type test_t)
+(sidcontext security (first_u object_r test_t ((s0) (s0))))
+(class test_class (test_perm))
+(classorder (test_class))
+(allow test_t self (test_class (test_perm)))
diff --git a/libsemanage/tests/test_user.h b/libsemanage/tests/test_user.h
new file mode 100644
index 00000000..014a84aa
--- /dev/null
+++ b/libsemanage/tests/test_user.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_USER_H__
+#define __TEST_USER_H__
+
+#include <CUnit/Basic.h>
+
+int user_test_init(void);
+int user_test_cleanup(void);
+int user_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/11] libsemanage: test semanage_context_* functions
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (8 preceding siblings ...)
  2019-06-12  8:04 ` [PATCH 09/11] libsemanage: test semanage_user_* functions Jan Zarsky
@ 2019-06-12  8:04 ` Jan Zarsky
  2019-06-12  8:04 ` [PATCH 11/11] libsemanage: test semanage_msg_default_handler Jan Zarsky
  2019-06-12 19:57 ` [PATCH 00/11] libsemanage: add tests William Roberts
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:04 UTC (permalink / raw)
  To: selinux

Add new test suite for other libsemanage functions. Add tests for
semanage_context_* functions.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/libsemanage-tests.c |  2 +
 libsemanage/tests/test_other.c        | 97 +++++++++++++++++++++++++++
 libsemanage/tests/test_other.h        | 30 +++++++++
 3 files changed, 129 insertions(+)
 create mode 100644 libsemanage/tests/test_other.c
 create mode 100644 libsemanage/tests/test_other.h

diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index 64039b5d..2ae4a21b 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -29,6 +29,7 @@
 #include "test_node.h"
 #include "test_port.h"
 #include "test_user.h"
+#include "test_other.h"
 
 #include <CUnit/Basic.h>
 #include <CUnit/Console.h>
@@ -75,6 +76,7 @@ static bool do_tests(int interactive, int verbose)
 	DECLARE_SUITE(node);
 	DECLARE_SUITE(port);
 	DECLARE_SUITE(user);
+	DECLARE_SUITE(other);
 
 	if (verbose)
 		CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/libsemanage/tests/test_other.c b/libsemanage/tests/test_other.c
new file mode 100644
index 00000000..437064d2
--- /dev/null
+++ b/libsemanage/tests/test_other.c
@@ -0,0 +1,97 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "utilities.h"
+#include "test_other.h"
+
+/* context_record.h */
+void test_semanage_context(void);
+
+extern semanage_handle_t *sh;
+
+int other_test_init(void)
+{
+	return 0;
+}
+
+int other_test_cleanup(void)
+{
+	return 0;
+}
+
+int other_add_tests(CU_pSuite suite)
+{
+	CU_add_test(suite, "semanage_context", test_semanage_context);
+
+	return 0;
+}
+
+/* Function semanage_context_get_user, semanage_context_set_user,
+ * semanage_context_get_role, semanage_context_set_role,
+ * semanage_context_get_type, semanage_context_set_type,
+ * semanage_context_get_mls, semanage_context_set_mls,
+ * semanage_context_create, semanage_context_clone,
+ * semanage_context_free, semanage_context_from_string
+ * semanage_context_to_string
+ */
+void test_semanage_context(void)
+{
+	semanage_context_t *con = NULL;
+	semanage_context_t *con_clone = NULL;
+	char *str = NULL;
+
+	/* setup */
+	setup_handle(SH_CONNECT);
+
+	/* test */
+	CU_ASSERT(semanage_context_create(sh, &con) >= 0);
+
+	CU_ASSERT(semanage_context_set_user(sh, con, "user_u") >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_user(con), "user_u");
+	CU_ASSERT(semanage_context_set_role(sh, con, "role_r") >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_role(con), "role_r");
+	CU_ASSERT(semanage_context_set_type(sh, con, "type_t") >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_type(con), "type_t");
+	CU_ASSERT(semanage_context_set_mls(sh, con, "s0") >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_mls(con), "s0");
+
+	CU_ASSERT(semanage_context_to_string(sh, con, &str) >= 0);
+	CU_ASSERT_PTR_NOT_NULL(str);
+	assert(str);
+	CU_ASSERT_STRING_EQUAL(str, "user_u:role_r:type_t:s0");
+
+	CU_ASSERT(semanage_context_from_string(sh, "my_u:my_r:my_t:s0",
+					       &con) >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_user(con), "my_u");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_role(con), "my_r");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_type(con), "my_t");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_mls(con), "s0");
+
+	CU_ASSERT(semanage_context_clone(sh, con, &con_clone) >= 0);
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_user(con_clone), "my_u");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_role(con_clone), "my_r");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_type(con_clone), "my_t");
+	CU_ASSERT_STRING_EQUAL(semanage_context_get_mls(con_clone), "s0");
+
+	/* cleanup */
+	semanage_context_free(con);
+	semanage_context_free(con_clone);
+	cleanup_handle(SH_CONNECT);
+}
diff --git a/libsemanage/tests/test_other.h b/libsemanage/tests/test_other.h
new file mode 100644
index 00000000..40d2dcf8
--- /dev/null
+++ b/libsemanage/tests/test_other.h
@@ -0,0 +1,30 @@
+/*
+ * Authors: Jan Zarsky <jzarsky@redhat.com>
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TEST_OTHER_H__
+#define __TEST_OTHER_H__
+
+#include <CUnit/Basic.h>
+
+int other_test_init(void);
+int other_test_cleanup(void);
+int other_add_tests(CU_pSuite suite);
+
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/11] libsemanage: test semanage_msg_default_handler
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (9 preceding siblings ...)
  2019-06-12  8:04 ` [PATCH 10/11] libsemanage: test semanage_context_* functions Jan Zarsky
@ 2019-06-12  8:04 ` Jan Zarsky
  2019-06-12 19:57 ` [PATCH 00/11] libsemanage: add tests William Roberts
  11 siblings, 0 replies; 14+ messages in thread
From: Jan Zarsky @ 2019-06-12  8:04 UTC (permalink / raw)
  To: selinux

Add test for semanage_msg_default_handler.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/test_other.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/libsemanage/tests/test_other.c b/libsemanage/tests/test_other.c
index 437064d2..c4ee0ed8 100644
--- a/libsemanage/tests/test_other.c
+++ b/libsemanage/tests/test_other.c
@@ -24,6 +24,9 @@
 /* context_record.h */
 void test_semanage_context(void);
 
+/* debug.h */
+void test_debug(void);
+
 extern semanage_handle_t *sh;
 
 int other_test_init(void)
@@ -39,6 +42,7 @@ int other_test_cleanup(void)
 int other_add_tests(CU_pSuite suite)
 {
 	CU_add_test(suite, "semanage_context", test_semanage_context);
+	CU_add_test(suite, "debug", test_debug);
 
 	return 0;
 }
@@ -95,3 +99,22 @@ void test_semanage_context(void)
 	semanage_context_free(con_clone);
 	cleanup_handle(SH_CONNECT);
 }
+
+/* Function semanage_msg_default_handler */
+void test_debug(void)
+{
+	semanage_module_info_t *modinfo = NULL;
+
+	/* setup */
+	sh = semanage_handle_create();
+	CU_ASSERT_PTR_NOT_NULL(sh);
+	CU_ASSERT(semanage_connect(sh) >= 0);
+	CU_ASSERT(semanage_module_info_create(sh, &modinfo) >= 0);
+
+	/* test */
+	CU_ASSERT(semanage_module_info_set_priority(sh, modinfo, -42) < 0);
+
+	/* cleanup */
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+	semanage_handle_destroy(sh);
+}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 00/11] libsemanage: add tests
  2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
                   ` (10 preceding siblings ...)
  2019-06-12  8:04 ` [PATCH 11/11] libsemanage: test semanage_msg_default_handler Jan Zarsky
@ 2019-06-12 19:57 ` William Roberts
  2019-06-19 16:04   ` William Roberts
  11 siblings, 1 reply; 14+ messages in thread
From: William Roberts @ 2019-06-12 19:57 UTC (permalink / raw)
  To: Jan Zarsky; +Cc: selinux

On Wed, Jun 12, 2019 at 1:44 AM Jan Zarsky <jzarsky@redhat.com> wrote:
>
> This series adds new test suites for libsemanage. In the first patch, common
> helper functions are added. The other patches are independent and each adds a
> new test suite.
>
> The test suites are testing only the public API and aim for line coverage. They
> test only correct usage of the functions. Together with valgrind, the test
> suites can be used for detecting memory leaks.
>
> The tests run fine in Travis CI and do not require an SELinux-enabled system.
>
> I welcome any suggestions.
>
> Jan Zarsky (11):
>   libsemanage: add helper functions to tests
>   libsemanage: test semanage_handle_* functions
>   libsemanage: test semanage_bool_* functions
>   libsemanage: test semanage_fcontext functions
>   libsemanage: test semanage_iface_* functions
>   libsemanage: test semanage_ibendport_* functions
>   libsemanage: test semanage_node_* functions
>   libsemanage: test semanage_port_* functions
>   libsemanage: test semanage_user_* functions
>   libsemanage: test semanage_context_* functions
>   libsemanage: test semanage_msg_default_handler
>
>  libsemanage/tests/.gitignore            |    1 +
>  libsemanage/tests/Makefile              |   11 +-
>  libsemanage/tests/libsemanage-tests.c   |   18 +
>  libsemanage/tests/test_bool.c           |  932 +++++++++++++++++++++++++++
>  libsemanage/tests/test_bool.cil         |   24 +
>  libsemanage/tests/test_bool.h           |   31 +
>  libsemanage/tests/test_fcontext.c       | 1045 +++++++++++++++++++++++++++++++
>  libsemanage/tests/test_fcontext.cil     |   25 +
>  libsemanage/tests/test_fcontext.h       |   30 +
>  libsemanage/tests/test_handle.c         |  329 ++++++++++
>  libsemanage/tests/test_handle.cil       |   21 +
>  libsemanage/tests/test_handle.h         |   30 +
>  libsemanage/tests/test_ibendport.c      |  525 ++++++++++++++++
>  libsemanage/tests/test_ibendport.cil    |   28 +
>  libsemanage/tests/test_ibendport.h      |   30 +
>  libsemanage/tests/test_iface.c          |  666 ++++++++++++++++++++
>  libsemanage/tests/test_iface.cil        |   28 +
>  libsemanage/tests/test_iface.h          |   30 +
>  libsemanage/tests/test_node.c           |  807 ++++++++++++++++++++++++
>  libsemanage/tests/test_node.cil         |   28 +
>  libsemanage/tests/test_node.h           |   30 +
>  libsemanage/tests/test_other.c          |  120 ++++
>  libsemanage/tests/test_other.h          |   30 +
>  libsemanage/tests/test_port.c           |  909 +++++++++++++++++++++++++++
>  libsemanage/tests/test_port.cil         |   27 +
>  libsemanage/tests/test_port.h           |   30 +
>  libsemanage/tests/test_semanage_store.c |    2 +-
>  libsemanage/tests/test_user.c           |  690 ++++++++++++++++++++
>  libsemanage/tests/test_user.cil         |   27 +
>  libsemanage/tests/test_user.h           |   30 +
>  libsemanage/tests/utilities.c           |  254 +++++++-
>  libsemanage/tests/utilities.h           |   53 +-
>  32 files changed, 6831 insertions(+), 10 deletions(-)
>
>
Ack
Staged: https://github.com/SELinuxProject/selinux/pull/159

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 00/11] libsemanage: add tests
  2019-06-12 19:57 ` [PATCH 00/11] libsemanage: add tests William Roberts
@ 2019-06-19 16:04   ` William Roberts
  0 siblings, 0 replies; 14+ messages in thread
From: William Roberts @ 2019-06-19 16:04 UTC (permalink / raw)
  To: Jan Zarsky; +Cc: selinux

merged

On Wed, Jun 12, 2019 at 12:57 PM William Roberts
<bill.c.roberts@gmail.com> wrote:
>
> On Wed, Jun 12, 2019 at 1:44 AM Jan Zarsky <jzarsky@redhat.com> wrote:
> >
> > This series adds new test suites for libsemanage. In the first patch, common
> > helper functions are added. The other patches are independent and each adds a
> > new test suite.
> >
> > The test suites are testing only the public API and aim for line coverage. They
> > test only correct usage of the functions. Together with valgrind, the test
> > suites can be used for detecting memory leaks.
> >
> > The tests run fine in Travis CI and do not require an SELinux-enabled system.
> >
> > I welcome any suggestions.
> >
> > Jan Zarsky (11):
> >   libsemanage: add helper functions to tests
> >   libsemanage: test semanage_handle_* functions
> >   libsemanage: test semanage_bool_* functions
> >   libsemanage: test semanage_fcontext functions
> >   libsemanage: test semanage_iface_* functions
> >   libsemanage: test semanage_ibendport_* functions
> >   libsemanage: test semanage_node_* functions
> >   libsemanage: test semanage_port_* functions
> >   libsemanage: test semanage_user_* functions
> >   libsemanage: test semanage_context_* functions
> >   libsemanage: test semanage_msg_default_handler
> >
> >  libsemanage/tests/.gitignore            |    1 +
> >  libsemanage/tests/Makefile              |   11 +-
> >  libsemanage/tests/libsemanage-tests.c   |   18 +
> >  libsemanage/tests/test_bool.c           |  932 +++++++++++++++++++++++++++
> >  libsemanage/tests/test_bool.cil         |   24 +
> >  libsemanage/tests/test_bool.h           |   31 +
> >  libsemanage/tests/test_fcontext.c       | 1045 +++++++++++++++++++++++++++++++
> >  libsemanage/tests/test_fcontext.cil     |   25 +
> >  libsemanage/tests/test_fcontext.h       |   30 +
> >  libsemanage/tests/test_handle.c         |  329 ++++++++++
> >  libsemanage/tests/test_handle.cil       |   21 +
> >  libsemanage/tests/test_handle.h         |   30 +
> >  libsemanage/tests/test_ibendport.c      |  525 ++++++++++++++++
> >  libsemanage/tests/test_ibendport.cil    |   28 +
> >  libsemanage/tests/test_ibendport.h      |   30 +
> >  libsemanage/tests/test_iface.c          |  666 ++++++++++++++++++++
> >  libsemanage/tests/test_iface.cil        |   28 +
> >  libsemanage/tests/test_iface.h          |   30 +
> >  libsemanage/tests/test_node.c           |  807 ++++++++++++++++++++++++
> >  libsemanage/tests/test_node.cil         |   28 +
> >  libsemanage/tests/test_node.h           |   30 +
> >  libsemanage/tests/test_other.c          |  120 ++++
> >  libsemanage/tests/test_other.h          |   30 +
> >  libsemanage/tests/test_port.c           |  909 +++++++++++++++++++++++++++
> >  libsemanage/tests/test_port.cil         |   27 +
> >  libsemanage/tests/test_port.h           |   30 +
> >  libsemanage/tests/test_semanage_store.c |    2 +-
> >  libsemanage/tests/test_user.c           |  690 ++++++++++++++++++++
> >  libsemanage/tests/test_user.cil         |   27 +
> >  libsemanage/tests/test_user.h           |   30 +
> >  libsemanage/tests/utilities.c           |  254 +++++++-
> >  libsemanage/tests/utilities.h           |   53 +-
> >  32 files changed, 6831 insertions(+), 10 deletions(-)
> >
> >
> Ack
> Staged: https://github.com/SELinuxProject/selinux/pull/159

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2019-06-19 16:03 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-12  8:03 [PATCH 00/11] libsemanage: add tests Jan Zarsky
2019-06-12  8:03 ` [PATCH 01/11] libsemanage: add helper functions to tests Jan Zarsky
2019-06-12  8:03 ` [PATCH 02/11] libsemanage: test semanage_handle_* functions Jan Zarsky
2019-06-12  8:03 ` [PATCH 03/11] libsemanage: test semanage_bool_* functions Jan Zarsky
2019-06-12  8:03 ` [PATCH 04/11] libsemanage: test semanage_fcontext functions Jan Zarsky
2019-06-12  8:03 ` [PATCH 05/11] libsemanage: test semanage_iface_* functions Jan Zarsky
2019-06-12  8:03 ` [PATCH 06/11] libsemanage: test semanage_ibendport_* functions Jan Zarsky
2019-06-12  8:04 ` [PATCH 07/11] libsemanage: test semanage_node_* functions Jan Zarsky
2019-06-12  8:04 ` [PATCH 08/11] libsemanage: test semanage_port_* functions Jan Zarsky
2019-06-12  8:04 ` [PATCH 09/11] libsemanage: test semanage_user_* functions Jan Zarsky
2019-06-12  8:04 ` [PATCH 10/11] libsemanage: test semanage_context_* functions Jan Zarsky
2019-06-12  8:04 ` [PATCH 11/11] libsemanage: test semanage_msg_default_handler Jan Zarsky
2019-06-12 19:57 ` [PATCH 00/11] libsemanage: add tests William Roberts
2019-06-19 16:04   ` William Roberts

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).