aboutsummaryrefslogtreecommitdiff
path: root/libstb/secvar
diff options
context:
space:
mode:
authorEric Richter <erichte@linux.ibm.com>2019-11-04 22:20:10 -0600
committerOliver O'Halloran <oohall@gmail.com>2019-11-07 17:46:33 +1100
commit127db3a6c292dbf6022831d79b480f0a480d7e18 (patch)
tree3b3229e7a95c46a979ecb3cf3f4ed0d4470ce0d4 /libstb/secvar
parentbc1f1e446ab40d6de6874b9afe1c6407906f2e57 (diff)
downloadskiboot-127db3a6c292dbf6022831d79b480f0a480d7e18.zip
skiboot-127db3a6c292dbf6022831d79b480f0a480d7e18.tar.gz
skiboot-127db3a6c292dbf6022831d79b480f0a480d7e18.tar.bz2
secvar/test: add rudimentary secvar API unit testing
This patch adds an initial port of the userspace unit tests for exercising the API that were originally developed out of tree. Future revisions will adjust the naming schemes and general formatting to match that of other tests within skiboot. Signed-off-by: Eric Richter <erichte@linux.ibm.com> [oliver: Use SPDX headers] Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'libstb/secvar')
-rw-r--r--libstb/secvar/test/Makefile.check47
-rw-r--r--libstb/secvar/test/secvar-test-enqueue.c148
-rw-r--r--libstb/secvar/test/secvar-test-getvar.c100
-rw-r--r--libstb/secvar/test/secvar-test-nextvar.c120
-rw-r--r--libstb/secvar/test/secvar-test-void.c12
-rw-r--r--libstb/secvar/test/secvar_api_test.c78
-rw-r--r--libstb/secvar/test/secvar_common_test.c52
7 files changed, 557 insertions, 0 deletions
diff --git a/libstb/secvar/test/Makefile.check b/libstb/secvar/test/Makefile.check
new file mode 100644
index 0000000..6dc24f1
--- /dev/null
+++ b/libstb/secvar/test/Makefile.check
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: Apache-2.0
+# -*-Makefile-*-
+SECVAR_TEST_DIR = libstb/secvar/test
+#SUBDIRS = $(SECVAR_TEST_DIR)
+
+SECVAR_TEST = $(patsubst %.c, %, $(wildcard $(SECVAR_TEST_DIR)/secvar-test-*.c))
+
+HOSTCFLAGS+=-I . -I include
+
+.PHONY : secvar-check
+secvar-check: $(SECVAR_TEST:%=%-check) $(SECVAR_TEST:%=%-gcov-run)
+secvar-check: $(SECVAR_TEST_NOSTUB:%=%-check) $(SECVAR_TEST_NOSTUB:%=%-gcov-run)
+
+.PHONY : secvar-coverage
+secvar-coverage: $(SECVAR_TEST:%=%-gcov-run)
+secvar-coverage: $(SECVAR_TEST_NOSTUB:%=%-gcov-run)
+
+check: secvar-check
+coverage: secvar-coverage
+
+# TODO: create pnor image for only tests that need it
+$(SECVAR_TEST:%=%-gcov-run) : %-run: %
+ @dd if=/dev/zero of=secboot.img bs=128k count=1 2> /dev/null
+ $(call QTEST, TEST-COVERAGE ,$< , $<)
+ @$(RM) -f secboot.img
+
+$(SECVAR_TEST:%=%-check) : %-check: %
+ @dd if=/dev/zero of=secboot.img bs=128k count=1 2> /dev/null
+ $(call QTEST, RUN-TEST ,$(VALGRIND) $<, $<)
+ @$(RM) -f secboot.img
+
+$(SECVAR_TEST) : core/test/stubs.o
+
+$(SECVAR_TEST) : % : %.c
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -o $@ $< core/test/stubs.o, $<)
+
+$(SECVAR_TEST:%=%-gcov): %-gcov : %.c %
+ $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I include -I . -I libfdt -lgcov -o $@ $< core/test/stubs.o, $<)
+
+-include $(wildcard libstb/secvar/test/*.d)
+
+clean: secvar-test-clean
+
+secvar-test-clean:
+ $(RM) -f libstb/secvar/test/*.[od] $(SECVAR_TEST) $(SECVAR_TEST:%=%-gcov)
+ $(RM) -f libstb/secvar/test/*.gcda libstb/secvar/test/*.gcno
+ $(RM) -f secboot.img
diff --git a/libstb/secvar/test/secvar-test-enqueue.c b/libstb/secvar/test/secvar-test-enqueue.c
new file mode 100644
index 0000000..ba37ddb
--- /dev/null
+++ b/libstb/secvar/test/secvar-test-enqueue.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+
+#include "secvar_api_test.c"
+
+const char *secvar_test_name = "enqueue";
+
+// Stub storage function, enqueue only cares that this succeeds
+static int temp_write_bank(struct list_head *bank, int section)
+{
+ (void) bank, (void) section;
+ return OPAL_SUCCESS;
+}
+
+int run_test(void)
+{
+ int64_t rc;
+
+ struct secvar_node *node;
+ char key[1024] = {0};
+
+ uint64_t data_size = 128;
+ char *data = zalloc(data_size);
+
+ secvar_storage.max_var_size = 1024;
+
+ /*** Bad cases first this time ***/
+ // No write bank hook set
+ secvar_storage.write_bank = NULL;
+ memcpy(key, "meow", 4); // ascii
+ rc = secvar_enqueue(key, 4, data, data_size);
+ ASSERT(rc == OPAL_HARDWARE);
+
+ // Set a stub bank writer, so the rest runs ok
+ secvar_storage.write_bank = temp_write_bank;
+
+ // Parameter checks
+ // null key
+ rc = secvar_enqueue(NULL, 5, data, data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // key is empty
+ memset(key, 0, sizeof(key));
+ rc = secvar_enqueue(key, 5, data, data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // keylen is zero
+ rc = secvar_enqueue(key, 0, data, data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // keylen is excessive
+ rc = secvar_enqueue(key, 5000, data, data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // null data
+ rc = secvar_enqueue(key, 5, NULL, data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // data_size is excessive
+ rc = secvar_enqueue(key, 5, data, 50000);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // data_size is zero
+ rc = secvar_enqueue(key, 5, data, 0);
+ ASSERT(rc == OPAL_PARAMETER);
+ ASSERT(list_empty(&update_bank));
+
+ // secvar is disabled
+ secvar_enabled = 0;
+ rc = secvar_enqueue(key, 5, data, data_size);
+ ASSERT(rc == OPAL_UNSUPPORTED);
+ secvar_enabled = 1;
+
+ // secvar is not ready
+ secvar_ready = 0;
+ rc = secvar_enqueue(key, 5, data, data_size);
+ ASSERT(rc == OPAL_RESOURCE);
+ secvar_ready = 1;
+
+
+ /*** Good cases ***/
+ // TODO: add data?
+ memcpy(key, "test", 4); // ascii
+ rc = secvar_enqueue(key, 4, data, data_size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(list_length(&update_bank) == 1);
+
+ memcpy(key, "f\0o\0o\0b\0a\0r\0", 6*2); // "unicode"
+ rc = secvar_enqueue(key, 6*2, data, data_size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(list_length(&update_bank) == 2);
+
+ memcpy(key, "meep", 4);
+ rc = secvar_enqueue(key, 4, data, data_size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(list_length(&update_bank) == 3); // should not increase
+
+ // Re-add the same variable
+ memcpy(key, "meep", 4);
+ rc = secvar_enqueue(key, 4, data, data_size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(list_length(&update_bank) == 3); // should not increase
+ node = list_tail(&update_bank, struct secvar_node, link);
+ ASSERT(!memcmp(node->var->key, key, 4)) // should be at end
+
+ // Unstage the variable update
+ rc = secvar_enqueue(key, 4, NULL, 0);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(list_length(&update_bank) == 2);
+
+ // Unstage a bogus variable update
+ rc = secvar_enqueue("nada", 4, NULL, 0);
+ ASSERT(rc == OPAL_EMPTY);
+ ASSERT(list_length(&update_bank) == 2);
+
+
+ // Empty the in-memory cache, and reload from "pnor"
+ // Removed to drop dependency on a storage backend
+ // Probably not actually necessary to test, that's the
+ // job of the storage backend tests
+ /*
+ clear_bank_list(&update_bank);
+ ASSERT(list_empty(&update_bank));
+ secvar_storage.load_bank(&update_bank, SECVAR_UPDATE_BANK);
+ printf("list_length = %d\n", list_length(&update_bank));
+ ASSERT(list_length(&update_bank) == 2);
+
+ node = list_top(&update_bank, struct secvar_node, link);
+ ASSERT(node);
+ ASSERT(!memcmp(node->var->key, "test", 4));
+ node = list_next(&update_bank, node, link);
+ ASSERT(node);
+ ASSERT(!memcmp(node->var->key, "f\0o\0o\0b\0a\0r\0", 6*2));
+ */
+
+ /*** ONE more bad case... ***/
+
+ free(data);
+
+ return 0;
+
+}
diff --git a/libstb/secvar/test/secvar-test-getvar.c b/libstb/secvar/test/secvar-test-getvar.c
new file mode 100644
index 0000000..da37cd2
--- /dev/null
+++ b/libstb/secvar/test/secvar-test-getvar.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+
+#include "secvar_api_test.c"
+
+const char *secvar_test_name = "getvar";
+
+// Run tests on the less obvious features of secvar_get
+// Includes:
+// - Partial reads
+// - Size queries (NULL buffer)
+//int run_test_helper(uint64_t bank_enum)
+int run_test(void)
+{
+ int64_t rc;
+
+ uint64_t size = 4;
+ char *temp = zalloc(100);
+ char key[1024] = {0};
+
+ struct secvar_node *node = zalloc(sizeof(struct secvar_node));
+ struct secvar *var = zalloc(sizeof(struct secvar) + 1024); // over-allocate for now, this should be rewritten
+ size_t data_size = sizeof("foobar");
+ char *data = zalloc(data_size);
+ uint64_t key_len = 4;
+ memcpy(data, "foobar", data_size);
+
+ memcpy(key, "test", 4);
+
+ // List should be empty at start
+ rc = secvar_get(key, key_len, data, &data_size);
+ ASSERT(rc == OPAL_EMPTY);
+ ASSERT(list_length(&variable_bank) == 0);
+
+ // Manually add variables, and check get_variable call
+ var->key_len = key_len;
+ memcpy(var->key, key, key_len);
+ var->data_size = data_size;
+ memcpy(var->data, data, data_size);
+
+ node->var = var;
+ list_add_tail(&variable_bank, &node->link);
+
+ ASSERT(list_length(&variable_bank) == 1);
+
+ // TEST ONLY DATA
+ // Test actual variable get
+ size = data_size;
+ rc = secvar_get(key, key_len, temp, &size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(0 == memcmp("foobar", var->data, size));
+
+ // Test buffer too small
+ size = data_size / 2;
+ memset(temp, 0, 100);
+ rc = secvar_get(key, key_len, temp, &size);
+ ASSERT(rc == OPAL_PARTIAL);
+
+ size = 0;
+ rc = secvar_get(key, key_len, temp, &size);
+ ASSERT(rc == OPAL_PARTIAL);
+ ASSERT(size == data_size);
+
+ // Test size query w/ no data
+ size = 0;
+ rc = secvar_get(key, key_len, NULL, &size);
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(size == data_size);
+
+ /**** Error/Bad param cases ****/
+ // NULL key
+ rc = secvar_get(NULL, key_len, data, &data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ // zero key_len
+ rc = secvar_get(key, 0, data, &data_size);
+ ASSERT(rc == OPAL_PARAMETER);
+ // NULL size, valid data
+ rc = secvar_get(key, key_len, data, NULL);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ secvar_enabled = 0;
+ rc = secvar_get(key, key_len, data, &data_size);
+ ASSERT(rc == OPAL_UNSUPPORTED);
+ secvar_enabled = 1;
+
+ secvar_ready = 0;
+ rc = secvar_get(key, key_len, data, &data_size);
+ ASSERT(rc == OPAL_RESOURCE);
+ secvar_ready = 1;
+
+ list_del(&node->link);
+
+ free(var);
+ free(node);
+ free(data);
+ free(temp);
+
+ return 0;
+}
+
diff --git a/libstb/secvar/test/secvar-test-nextvar.c b/libstb/secvar/test/secvar-test-nextvar.c
new file mode 100644
index 0000000..0d46858
--- /dev/null
+++ b/libstb/secvar/test/secvar-test-nextvar.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+
+#include "secvar_api_test.c"
+
+const char *secvar_test_name = "nextvar";
+
+int run_test(void)
+{
+ int64_t rc;
+
+ struct secvar *tmpvar;
+ struct secvar_node *tmpnode;
+
+ char key[1024] = {0};
+ uint64_t key_len = 16;
+
+
+ // Load up the bank with some variables.
+ // If these fail, we have bigger issues.
+ ASSERT(list_length(&variable_bank) == 0);
+ tmpvar = zalloc(sizeof(struct secvar) + 6);
+ tmpnode = zalloc(sizeof(struct secvar_node));
+ memcpy(tmpvar->key, "test1", 6); // ascii w/ null
+ tmpvar->key_len = 6;
+ tmpnode->var = tmpvar;
+ list_add_tail(&variable_bank, &tmpnode->link);
+ ASSERT(list_length(&variable_bank) == 1);
+
+ tmpvar = zalloc(sizeof(struct secvar) + 5);
+ tmpnode = zalloc(sizeof(struct secvar_node));
+ memcpy(tmpvar->key, "test2", 5); // ascii w/o null
+ tmpvar->key_len = 5;
+ tmpnode->var = tmpvar;
+ list_add_tail(&variable_bank, &tmpnode->link);
+ ASSERT(list_length(&variable_bank) == 2);
+
+ tmpvar = zalloc(sizeof(struct secvar) + 5*2);
+ tmpnode = zalloc(sizeof(struct secvar_node));
+ memcpy(tmpvar->key, L"test3", 5*2); // wide char "unicode"
+ tmpvar->key_len = 10;
+ tmpnode->var = tmpvar;
+ list_add_tail(&variable_bank, &tmpnode->link);
+ ASSERT(list_length(&variable_bank) == 3);
+
+ // Test sequential nexts
+ // first item
+ memset(key, 0, sizeof(key));
+ key_len = 0;
+ rc = secvar_get_next(key, &key_len, sizeof(key));
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(key_len == 6);
+ ASSERT(!memcmp(key, "test1", key_len));
+
+ // second item
+ rc = secvar_get_next(key, &key_len, sizeof(key));
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(key_len == 5);
+ ASSERT(!memcmp(key, "test2", key_len));
+
+ // last item
+ rc = secvar_get_next(key, &key_len, sizeof(key));
+ ASSERT(rc == OPAL_SUCCESS);
+ ASSERT(key_len == 5*2);
+ ASSERT(!memcmp(key, L"test3", key_len));
+
+ // end-of-list
+ rc = secvar_get_next(key, &key_len, sizeof(key));
+ ASSERT(rc == OPAL_EMPTY);
+
+
+ memset(key, 0, sizeof(key));
+ /*** Time for a break to test bad parameters ***/
+ // null key
+ rc = secvar_get_next(NULL, &key_len, 1024);
+ ASSERT(rc == OPAL_PARAMETER);
+ // Size too small
+ key_len = 0;
+ rc = secvar_get_next(key, &key_len, 1);
+ ASSERT(rc == OPAL_PARTIAL);
+ ASSERT(key_len == 6);
+ // Supplied key length is larger than the buffer
+ key_len = 6;
+ rc = secvar_get_next(key, &key_len, 1);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ // NULL key_len pointer
+ rc = secvar_get_next(key, NULL, 1024);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ // NULL key_len pointer
+ key_len = ~0;
+ rc = secvar_get_next(key, &key_len, 1024);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ // zero key_len
+ key_len = 0;
+ rc = secvar_get_next(key, &key_len, 0);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ // Non-existing previous variable
+ key_len = 1024;
+ memcpy(key, L"foobar", 7*2);
+ rc = secvar_get_next(key, &key_len, 1024);
+ ASSERT(rc == OPAL_PARAMETER);
+
+ secvar_enabled = 0;
+ rc = secvar_get_next(key, &key_len, 1024);
+ ASSERT(rc == OPAL_UNSUPPORTED);
+ secvar_enabled = 1;
+
+ secvar_ready = 0;
+ rc = secvar_get_next(key, &key_len, 1024);
+ ASSERT(rc == OPAL_RESOURCE);
+ secvar_ready = 1;
+
+ clear_bank_list(&variable_bank);
+
+ return 0;
+}
diff --git a/libstb/secvar/test/secvar-test-void.c b/libstb/secvar/test/secvar-test-void.c
new file mode 100644
index 0000000..b45e8cb
--- /dev/null
+++ b/libstb/secvar/test/secvar-test-void.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+
+#include "secvar_api_test.c"
+
+const char *secvar_test_name = "void";
+
+int run_test()
+{
+ // Do nothing... ensure testing framework is...working.
+ return 0;
+}
diff --git a/libstb/secvar/test/secvar_api_test.c b/libstb/secvar/test/secvar_api_test.c
new file mode 100644
index 0000000..2e959c9
--- /dev/null
+++ b/libstb/secvar/test/secvar_api_test.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+#include "secvar_common_test.c"
+
+// Hack to include the code we actually want to test here...
+#include "../secvar_api.c"
+#include "../secvar_util.c"
+
+// Stuff from secvar_main that we need, but not enough to
+// include that file
+int secvar_enabled = 0;
+int secvar_ready = 0;
+
+
+/**** Helper wrappers, so the caller doesn't have to cast ****/
+
+static int64_t secvar_get(const char *k_key, uint64_t k_key_len, void *k_data, uint64_t *k_data_size)
+{
+ return opal_secvar_get( k_key,
+ k_key_len,
+ k_data,
+ k_data_size);
+}
+
+static int64_t secvar_get_next(char *k_key, uint64_t *k_key_len, uint64_t k_key_size)
+{
+
+ return opal_secvar_get_next( k_key,
+ k_key_len,
+ k_key_size);
+}
+
+
+
+static int64_t secvar_enqueue(const char *k_key, uint64_t k_key_len, void *k_data, uint64_t k_data_size)
+{
+ return opal_secvar_enqueue_update(k_key,
+ k_key_len,
+ k_data,
+ k_data_size);
+
+}
+
+
+
+// Entry point
+// TODO: do some real argparsing
+int main(int argc, char **argv)
+{
+ int ret;
+
+ (void) secvar_get;
+ (void) secvar_get_next;
+ (void) secvar_enqueue;
+ (void) argc;
+ (void) argv;
+
+ secvar_enabled = 1;
+
+ list_head_init(&variable_bank);
+ list_head_init(&update_bank);
+
+ secvar_ready = 1;
+
+ printf("Running test '%s'...", secvar_test_name);
+ ret = run_test();
+ if (ret)
+ printf(COLOR_RED "FAILED" COLOR_RESET "\n");
+ else
+ printf(COLOR_GREEN "OK" COLOR_RESET "\n");
+
+ // Clean up for the test cases
+ clear_bank_list(&variable_bank);
+ clear_bank_list(&update_bank);
+
+ return ret;
+}
+
diff --git a/libstb/secvar/test/secvar_common_test.c b/libstb/secvar/test/secvar_common_test.c
new file mode 100644
index 0000000..fbc2314
--- /dev/null
+++ b/libstb/secvar/test/secvar_common_test.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2019 IBM Corp. */
+
+#define SECBOOT_FILE "secboot.img"
+#define SECBOOT_SIZE 128000
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <skiboot.h>
+#include <ccan/list/list.h>
+#include <stdarg.h>
+#include <secvar.h>
+
+// Force p9
+enum proc_gen proc_gen = proc_gen_p9;
+
+// Replace memalign with regular old malloc
+#define memalign(a, b) malloc(b)
+#define zalloc(a) calloc(1, a)
+
+
+
+struct list_head variable_bank;
+struct list_head update_bank;
+
+struct secvar_storage_driver secvar_storage;
+
+
+// For log file output instead of stdout
+FILE *outfile;
+
+#ifndef NO_COLOR
+#define COLOR_RED "\033[0;31m"
+#define COLOR_GREEN "\033[1;32m"
+#define COLOR_RESET "\033[0m"
+#else
+#define COLOR_RED ""
+#define COLOR_GREEN ""
+#define COLOR_RESET ""
+#endif
+
+// Helper functions and macros to make test case writing easier
+
+// Semi-configurable assert, can use to jump to a clean up step on fail
+#define ASSERT_POST(a,b) if(!(a)){fprintf(stdout, "Assert '%s' failed at %s:%d...", #a, __FILE__, __LINE__);b;}
+#define ASSERT(a) ASSERT_POST(a, return 1)
+
+// To be defined by test case
+int run_test(void);
+const char *secvar_test_name;
+