efi_selftest: unit test for event groups
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Sun, 18 Feb 2018 14:17:53 +0000 (15:17 +0100)
committerAlexander Graf <agraf@suse.de>
Wed, 4 Apr 2018 09:00:07 +0000 (11:00 +0200)
Supply a unit test for event groups.

Create multiple events in an event group. Signal each event once and check
that all events are notified once in each round.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
lib/efi_selftest/Makefile
lib/efi_selftest/efi_selftest_event_groups.c [new file with mode: 0644]

index 2c442517040ea8af838976ca9bdfb4c611ef1312..31b444fc8b18dcad6aca77c2012daf67e49714be 100644 (file)
@@ -19,6 +19,7 @@ efi_selftest_controllers.o \
 efi_selftest_console.o \
 efi_selftest_devicepath.o \
 efi_selftest_events.o \
+efi_selftest_event_groups.o \
 efi_selftest_exitbootservices.o \
 efi_selftest_fdt.o \
 efi_selftest_gop.o \
diff --git a/lib/efi_selftest/efi_selftest_event_groups.c b/lib/efi_selftest/efi_selftest_event_groups.c
new file mode 100644 (file)
index 0000000..79e4ea1
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * efi_selftest_event_groups
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the notification of group events and the
+ * following services:
+ * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
+ */
+
+#include <efi_selftest.h>
+
+#define GROUP_SIZE 16
+
+static struct efi_boot_services *boottime;
+static efi_guid_t event_group =
+       EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
+                0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
+
+/*
+ * Notification function, increments the notfication count if parameter
+ * context is provided.
+ *
+ * @event      notified event
+ * @context    pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+       unsigned int *count = context;
+
+       if (count)
+               ++*count;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:    handle of the loaded image
+ * @systable:  system table
+ * @return:    EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+                const struct efi_system_table *systable)
+{
+       boottime = systable->boottime;
+
+       return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Create multiple events in an event group. Signal each event once and check
+ * that all events are notified once in each round.
+ *
+ * @return:    EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+       unsigned int counter[GROUP_SIZE] = {0};
+       struct efi_event *events[GROUP_SIZE];
+       size_t i, j;
+       efi_status_t ret;
+
+       for (i = 0; i < GROUP_SIZE; ++i) {
+               ret = boottime->create_event_ex(0, TPL_NOTIFY,
+                                               notify, (void *)&counter[i],
+                                               &event_group, &events[i]);
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("Failed to create event\n");
+                       return EFI_ST_FAILURE;
+               }
+       }
+
+       for (i = 0; i < GROUP_SIZE; ++i) {
+               ret = boottime->signal_event(events[i]);
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("Failed to signal event\n");
+                       return EFI_ST_FAILURE;
+               }
+               for (j = 0; j < GROUP_SIZE; ++j) {
+                       if (counter[j] != i) {
+                               efi_st_printf("i %u, j %u, count %u\n",
+                                             (unsigned int)i, (unsigned int)j,
+                                             (unsigned int)counter[j]);
+                               efi_st_error(
+                                       "Notification function was called\n");
+                               return EFI_ST_FAILURE;
+                       }
+                       /* Clear signaled state */
+                       ret = boottime->check_event(events[j]);
+                       if (ret != EFI_SUCCESS) {
+                               efi_st_error("Event was not signaled\n");
+                               return EFI_ST_FAILURE;
+                       }
+                       if (counter[j] != i) {
+                               efi_st_printf("i %u, j %u, count %u\n",
+                                             (unsigned int)i, (unsigned int)j,
+                                             (unsigned int)counter[j]);
+                               efi_st_error(
+                                       "Notification function was called\n");
+                               return EFI_ST_FAILURE;
+                       }
+                       /* Call notification function  */
+                       ret = boottime->check_event(events[j]);
+                       if (ret != EFI_NOT_READY) {
+                               efi_st_error(
+                                       "Signaled state not cleared\n");
+                               return EFI_ST_FAILURE;
+                       }
+                       if (counter[j] != i + 1) {
+                               efi_st_printf("i %u, j %u, count %u\n",
+                                             (unsigned int)i, (unsigned int)j,
+                                             (unsigned int)counter[j]);
+                               efi_st_error(
+                                       "Nofification function not called\n");
+                               return EFI_ST_FAILURE;
+                       }
+               }
+       }
+
+       for (i = 0; i < GROUP_SIZE; ++i) {
+               ret = boottime->close_event(events[i]);
+               if (ret != EFI_SUCCESS) {
+                       efi_st_error("Failed to close event\n");
+                       return EFI_ST_FAILURE;
+               }
+       }
+
+       return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(eventgoups) = {
+       .name = "event groups",
+       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+       .setup = setup,
+       .execute = execute,
+};