[PATCH 1/1] newlib01: Test exit procs for global FILE object

Matthew Joyce matthew.joyce at embedded-brains.de
Fri Mar 25 13:10:33 UTC 2022


From: Matt Joyce <matthew.joyce at embedded-brains.de>

---
 testsuites/libtests/newlib01/init.c | 102 ++++++++++++++++++++++++++--
 1 file changed, 96 insertions(+), 6 deletions(-)

diff --git a/testsuites/libtests/newlib01/init.c b/testsuites/libtests/newlib01/init.c
index c58154023b..c20e0a04ff 100644
--- a/testsuites/libtests/newlib01/init.c
+++ b/testsuites/libtests/newlib01/init.c
@@ -28,6 +28,8 @@ const char rtems_test_name[] = "NEWLIB 1";
 
 static const char file_path[] = "/file";
 
+static const char file_path2[] = "/file2";
+
 typedef enum {
   INIT,
   OPEN,
@@ -39,6 +41,8 @@ typedef struct {
   rtems_id main_task_id;
   rtems_id worker_task_id;
   test_state current;
+  FILE *glob_file_stream;
+  int glob_fd;
 } test_context;
 
 static test_context test_instance;
@@ -59,7 +63,7 @@ static void wait(void)
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 }
 
-static void worker_task(rtems_task_argument arg)
+static void worker_task1(rtems_task_argument arg)
 {
   test_context *ctx = &test_instance;
   struct _reent *reent = _REENT;
@@ -90,6 +94,41 @@ static void worker_task(rtems_task_argument arg)
   rtems_test_assert(0);
 }
 
+static void worker_task2(rtems_task_argument arg)
+{
+  test_context *ctx = &test_instance;
+  struct _reent *reent = _REENT;
+  FILE *fp;
+  char buf[1] = { 'y' };
+  size_t n;
+  int fd;
+
+  rtems_test_assert(reent->__cleanup == NULL);
+
+  fp = ctx->glob_file_stream = fopen(&file_path2[0], "w");
+  rtems_test_assert(fp != NULL);
+
+  /*
+   * Check newlib's __sinit does not touch our assigned file pointer.
+   */
+  rtems_test_assert(reent->__cleanup == NULL);
+  rtems_test_assert(fflush(fp) == 0);
+  rtems_test_assert(reent->__cleanup != NULL);
+  rtems_test_assert(ctx->glob_file_stream == fp);
+
+  /* Get file descriptor of new global file stream, store it in text context */
+  fd = fileno(fp);
+  rtems_test_assert(fd != -1);
+  ctx->glob_fd = fd;
+
+  n = fwrite(&buf[0], sizeof(buf), 1, fp);
+  rtems_test_assert(n == 1);
+
+  wake_up_main(ctx);
+
+  rtems_test_assert(0);
+}
+
 static int handler_open(
   rtems_libio_t *iop,
   const char *path,
@@ -267,7 +306,7 @@ static void test_thread_specific_close(test_context *ctx)
   rtems_test_assert(rv == 0);
 
   sc = rtems_task_create(
-    rtems_build_name('W', 'O', 'R', 'K'),
+    rtems_build_name('W', 'R', 'K', '1'),
     2,
     RTEMS_MINIMUM_STACK_SIZE,
     RTEMS_DEFAULT_MODES,
@@ -276,7 +315,7 @@ static void test_thread_specific_close(test_context *ctx)
   );
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-  sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
+  sc = rtems_task_start(ctx->worker_task_id, worker_task1, 0);
   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
   wait();
@@ -290,6 +329,33 @@ static void test_thread_specific_close(test_context *ctx)
   rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
 }
 
+static void test_global_file_object_close(test_context *ctx)
+{
+  int rv;
+  rtems_status_code sc;
+
+  sc = rtems_task_create(
+  rtems_build_name('W', 'R', 'K', '2'),
+  2,
+  RTEMS_MINIMUM_STACK_SIZE,
+  RTEMS_DEFAULT_MODES,
+  RTEMS_DEFAULT_ATTRIBUTES,
+  &ctx->worker_task_id
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_task_start(ctx->worker_task_id, worker_task2, 0);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  wait();
+
+  sc = rtems_task_delete(ctx->worker_task_id);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rv = unlink(&file_path2[0]);
+  rtems_test_assert(rv == 0);
+}
+
 /*
  * This exit handler will be called last among the functions registered with
  * atexit(). Check that stdio file descriptors are closed. The Newlib cleanup
@@ -298,6 +364,7 @@ static void test_thread_specific_close(test_context *ctx)
  */
 static void check_after_libio_exit(void)
 {
+  test_context *ctx = &test_instance;
   struct stat unused;
   int rv;
 
@@ -319,6 +386,11 @@ static void check_after_libio_exit(void)
   rtems_test_assert(stdin->_flags != 0);
   rtems_test_assert(stdout->_flags != 0);
   rtems_test_assert(stderr->_flags != 0);
+
+  /* Global file tests. Global fd still open at this point. */
+  rv = fstat(ctx->glob_fd, &unused);
+  rtems_test_assert(rv == 0);
+  rtems_test_assert(ctx->glob_file_stream->_flags != 0);
 }
 
 static void register_exit_handler_before_libio_exit(void)
@@ -342,7 +414,7 @@ RTEMS_SYSINIT_ITEM(register_exit_handler_before_libio_exit,
  * cleanup procedures have been called. Therefore, stdio file descriptors
  * should be open and stdio FILE object flags should be non-zero.
  */
-static void test_exit_handling(void)
+static void test_exit_handling(test_context *ctx)
 {
   struct stat unused;
   int rv;
@@ -360,6 +432,14 @@ static void test_exit_handling(void)
   rtems_test_assert(stdout->_flags != 0);
   rtems_test_assert(stderr->_flags != 0);
 
+  /*
+   * Global file descriptor should still be open; global FILE object flags
+   * should still be non-zero.
+   */
+  rv = fstat(ctx->glob_fd, &unused);
+  rtems_test_assert(rv == 0);
+  rtems_test_assert(ctx->glob_file_stream->_flags != 0);
+
   /* Run exit handlers and Newlib cleanup procedures */
   exit(0);
 }
@@ -380,7 +460,8 @@ static void Init(rtems_task_argument arg)
   rtems_test_assert(rv == 0);
 
   test_thread_specific_close(ctx);
-  test_exit_handling();
+  test_global_file_object_close(ctx);
+  test_exit_handling(ctx);
 }
 
 static void fatal_extension(
@@ -400,6 +481,7 @@ static void fatal_extension(
      */
     struct stat unused;
     int rv;
+    test_context *ctx = &test_instance;
 
     errno = 0;
     rv = fstat(0, &unused);
@@ -419,6 +501,14 @@ static void fatal_extension(
     rtems_test_assert(stdin->_flags == 0);
     rtems_test_assert(stdout->_flags == 0);
     rtems_test_assert(stderr->_flags == 0);
+
+    /* Global file tests */
+    errno = 0;
+    rv = fstat(ctx->glob_fd, &unused);
+    rtems_test_assert(rv == -1);
+    rtems_test_assert(errno == EBADF);
+    rtems_test_assert(ctx->glob_file_stream->_flags == 0);
+
     TEST_END();
   }
 }
@@ -426,7 +516,7 @@ static void fatal_extension(
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
 
-#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
+#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 5
 
 #define CONFIGURE_MAXIMUM_TASKS 2
 
-- 
2.31.1



More information about the devel mailing list