source: rtems/testsuites/fstests/fsclose01/init.c @ 4ac5ffbb

Last change on this file since 4ac5ffbb was 4ac5ffbb, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 5, 2018 at 8:31:32 AM

fsclose01: Add tmpfile() test case

Close #1971.

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
2 * Copyright (c) 2012, 2018 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <sys/stat.h>
20#include <sys/ioctl.h>
21#include <sys/uio.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <errno.h>
25
26#include <rtems/imfs.h>
27#include <rtems/malloc.h>
28#include <rtems/libcsupport.h>
29
30#include <tmacros.h>
31
32const char rtems_test_name[] = "FSCLOSE 1";
33
34typedef enum {
35  ACTION_ClOSE,
36  ACTION_FCNTL,
37  ACTION_FDATASYNC,
38  ACTION_FCHDIR,
39  ACTION_FCHMOD,
40  ACTION_FCHOWN,
41  /* ACTION_FPATHCONF, not easy to test */
42  ACTION_FSTAT,
43  ACTION_FSYNC,
44  ACTION_FTRUNCATE,
45  ACTION_IOCTL,
46  ACTION_LSEEK,
47  ACTION_READ,
48  ACTION_READV,
49  ACTION_WRITE,
50  ACTION_WRITEV
51} test_action;
52
53typedef struct {
54  rtems_id worker_id;
55  int fd;
56  test_action action;
57  bool wait_in_close;
58  bool wait_in_fstat;
59  int close_count;
60  int fcntl_count;
61  int fdatasync_count;
62  int fstat_count;
63  int fsync_count;
64  int ftruncate_count;
65  int ioctl_count;
66  int lseek_count;
67  int open_count;
68  int read_count;
69  int readv_count;
70  int write_count;
71  int writev_count;
72} test_context;
73
74static test_context test_instance;
75
76static void wait(void)
77{
78  rtems_status_code sc;
79
80  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
81  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
82}
83
84static void wakeup_worker(const test_context *ctx)
85{
86  rtems_status_code sc;
87
88  sc = rtems_event_transient_send(ctx->worker_id);
89  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
90}
91
92static int handler_open(
93  rtems_libio_t *iop,
94  const char *path,
95  int oflag,
96  mode_t mode
97)
98{
99  test_context *ctx;
100
101  ctx = IMFS_generic_get_context_by_iop(iop);
102  ++ctx->open_count;
103
104  return 0;
105}
106
107static int handler_close(
108  rtems_libio_t *iop
109)
110{
111  test_context *ctx;
112
113  ctx = IMFS_generic_get_context_by_iop(iop);
114  ++ctx->close_count;
115
116  if (ctx->wait_in_close) {
117    ctx->wait_in_close = false;
118    wait();
119  }
120
121  return 0;
122}
123
124static ssize_t handler_read(
125  rtems_libio_t *iop,
126  void *buffer,
127  size_t count
128)
129{
130  test_context *ctx;
131
132  ctx = IMFS_generic_get_context_by_iop(iop);
133  ++ctx->read_count;
134
135  wait();
136  return 0;
137}
138
139static ssize_t handler_write(
140  rtems_libio_t *iop,
141  const void *buffer,
142  size_t count
143)
144{
145  test_context *ctx;
146
147  ctx = IMFS_generic_get_context_by_iop(iop);
148  ++ctx->write_count;
149
150  wait();
151  return 0;
152}
153
154static int handler_ioctl(
155  rtems_libio_t *iop,
156  ioctl_command_t request,
157  void *buffer
158)
159{
160  test_context *ctx;
161
162  ctx = IMFS_generic_get_context_by_iop(iop);
163  ++ctx->ioctl_count;
164
165  wait();
166  return 0;
167}
168
169static off_t handler_lseek(
170  rtems_libio_t *iop,
171  off_t length,
172  int whence
173)
174{
175  test_context *ctx;
176
177  ctx = IMFS_generic_get_context_by_iop(iop);
178  ++ctx->lseek_count;
179
180  wait();
181  return 0;
182}
183
184static int handler_fstat(
185  const rtems_filesystem_location_info_t *loc,
186  struct stat *buf
187)
188{
189  test_context *ctx;
190
191  buf->st_mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;
192  ctx = IMFS_generic_get_context_by_location(loc);
193  ++ctx->fstat_count;
194
195  if (ctx->wait_in_fstat) {
196    ctx->wait_in_fstat = false;
197    wait();
198  }
199
200  return 0;
201}
202
203static int handler_ftruncate(
204  rtems_libio_t *iop,
205  off_t length
206)
207{
208  test_context *ctx;
209
210  ctx = IMFS_generic_get_context_by_iop(iop);
211  ++ctx->ftruncate_count;
212
213  wait();
214  return 0;
215}
216
217static int handler_fsync(
218  rtems_libio_t *iop
219)
220{
221  test_context *ctx;
222
223  ctx = IMFS_generic_get_context_by_iop(iop);
224  ++ctx->fsync_count;
225
226  wait();
227  return 0;
228}
229
230static int handler_fdatasync(
231  rtems_libio_t *iop
232)
233{
234  test_context *ctx;
235
236  ctx = IMFS_generic_get_context_by_iop(iop);
237  ++ctx->fdatasync_count;
238
239  wait();
240  return 0;
241}
242
243static int handler_fcntl(
244  rtems_libio_t *iop,
245  int cmd
246)
247{
248  test_context *ctx;
249
250  ctx = IMFS_generic_get_context_by_iop(iop);
251  ++ctx->fcntl_count;
252
253  wait();
254  return 0;
255}
256
257static ssize_t handler_readv(
258  rtems_libio_t *iop,
259  const struct iovec *iov,
260  int iovcnt,
261  ssize_t total
262)
263{
264  test_context *ctx;
265
266  ctx = IMFS_generic_get_context_by_iop(iop);
267  ++ctx->readv_count;
268
269  wait();
270  return 0;
271}
272
273static ssize_t handler_writev(
274  rtems_libio_t *iop,
275  const struct iovec *iov,
276  int iovcnt,
277  ssize_t total
278)
279{
280  test_context *ctx;
281
282  ctx = IMFS_generic_get_context_by_iop(iop);
283  ++ctx->writev_count;
284
285  wait();
286  return 0;
287}
288
289static const rtems_filesystem_file_handlers_r node_handlers = {
290  .open_h = handler_open,
291  .close_h = handler_close,
292  .read_h = handler_read,
293  .write_h = handler_write,
294  .ioctl_h = handler_ioctl,
295  .lseek_h = handler_lseek,
296  .fstat_h = handler_fstat,
297  .ftruncate_h = handler_ftruncate,
298  .fsync_h = handler_fsync,
299  .fdatasync_h = handler_fdatasync,
300  .fcntl_h = handler_fcntl,
301  .readv_h = handler_readv,
302  .writev_h = handler_writev
303};
304
305static const IMFS_node_control node_control = {
306  .handlers = &node_handlers,
307  .node_initialize = IMFS_node_initialize_generic,
308  .node_remove = IMFS_node_remove_default,
309  .node_destroy = IMFS_node_destroy_default
310};
311
312static void worker_task(rtems_task_argument arg)
313{
314  test_context *ctx;
315  int rv;
316  char buf[1];
317  ssize_t n;
318  off_t off;
319  struct iovec iov = {
320    .iov_base = &buf[0],
321    .iov_len = sizeof(buf)
322  };
323  struct stat st;
324
325  ctx = (test_context *) arg;
326
327  while (true) {
328    wait();
329
330    switch (ctx->action) {
331      case ACTION_ClOSE:
332        ctx->wait_in_close = true;
333        rv = close(ctx->fd);
334        rtems_test_assert(rv == 0);
335        break;
336      case ACTION_FCNTL:
337        rv = fcntl(ctx->fd, F_GETFD);
338        rtems_test_assert(rv >= 0);
339        break;
340      case ACTION_FDATASYNC:
341        rv = fdatasync(ctx->fd);
342        rtems_test_assert(rv == 0);
343        break;
344      case ACTION_FCHDIR:
345        ctx->wait_in_fstat = true;
346        rv = fchdir(ctx->fd);
347        rtems_test_assert(rv == -1);
348        rtems_test_assert(errno == ENOTDIR);
349        break;
350      case ACTION_FCHMOD:
351        rv = fstat(ctx->fd, &st);
352        rtems_test_assert(rv == 0);
353        ctx->wait_in_fstat = true;
354        rv = fchmod(ctx->fd, st.st_mode);
355        rtems_test_assert(rv == 0);
356        break;
357      case ACTION_FCHOWN:
358        rv = fstat(ctx->fd, &st);
359        rtems_test_assert(rv == 0);
360        ctx->wait_in_fstat = true;
361        rv = fchown(ctx->fd, st.st_uid, st.st_gid);
362        rtems_test_assert(rv == 0);
363        break;
364      case ACTION_FSTAT:
365        ctx->wait_in_fstat = true;
366        rv = fstat(ctx->fd, &st);
367        rtems_test_assert(rv == 0);
368        break;
369      case ACTION_FSYNC:
370        rv = fsync(ctx->fd);
371        rtems_test_assert(rv == 0);
372        break;
373      case ACTION_FTRUNCATE:
374        rv = ftruncate(ctx->fd, 0);
375        rtems_test_assert(rv == 0);
376        break;
377      case ACTION_IOCTL:
378        rv = ioctl(ctx->fd, 0);
379        rtems_test_assert(rv == 0);
380        break;
381      case ACTION_LSEEK:
382        off = lseek(ctx->fd, off, SEEK_SET);
383        rtems_test_assert(off == 0);
384        break;
385      case ACTION_READ:
386        n = read(ctx->fd, buf, sizeof(buf));
387        rtems_test_assert(n == 0);
388        break;
389      case ACTION_READV:
390        n = readv(ctx->fd, &iov, 1);
391        rtems_test_assert(n == 0);
392        break;
393      case ACTION_WRITE:
394        n = write(ctx->fd, buf, sizeof(buf));
395        rtems_test_assert(n == 0);
396        break;
397      case ACTION_WRITEV:
398        n = writev(ctx->fd, &iov, 1);
399        rtems_test_assert(n == 0);
400        break;
401      default:
402        rtems_test_assert(0);
403        break;
404    }
405  }
406}
407
408static void test_fd_free_fifo(const char *path)
409{
410  int a;
411  int b;
412  int rv;
413
414  a = open(path, O_RDWR);
415  rtems_test_assert(a >= 0);
416
417  rv = close(a);
418  rtems_test_assert(rv == 0);
419
420  b = open(path, O_RDWR);
421  rtems_test_assert(b >= 0);
422
423  rv = close(b);
424  rtems_test_assert(rv == 0);
425
426  rtems_test_assert(a != b);
427}
428
429static void test_close(test_context *ctx)
430{
431  const char *path = "generic";
432  int rv;
433  rtems_status_code sc;
434  test_action ac;
435
436  rv = IMFS_make_generic_node(
437    path,
438    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
439    &node_control,
440    ctx
441  );
442  rtems_test_assert(rv == 0);
443
444  test_fd_free_fifo(path);
445
446  sc = rtems_task_create(
447    rtems_build_name('W', 'O', 'R', 'K'),
448    1,
449    RTEMS_MINIMUM_STACK_SIZE,
450    RTEMS_DEFAULT_MODES,
451    RTEMS_DEFAULT_ATTRIBUTES,
452    &ctx->worker_id
453  );
454  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
455
456  sc = rtems_task_start(
457    ctx->worker_id,
458    worker_task,
459    (rtems_task_argument) ctx
460  );
461  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
462
463  for (ac = ACTION_ClOSE; ac <= ACTION_WRITEV; ++ac) {
464    ctx->action = ac;
465    ctx->fd = open(path, O_RDWR);
466    rtems_test_assert(ctx->fd >= 0);
467
468    wakeup_worker(ctx);
469    rv = close(ctx->fd);
470    rtems_test_assert(rv == -1);
471
472    if (ac == ACTION_ClOSE) {
473      rtems_test_assert(errno == EBADF);
474    } else {
475      rtems_test_assert(errno == EBUSY);
476    }
477
478    wakeup_worker(ctx);
479    rv = close(ctx->fd);
480
481    if (ac == ACTION_ClOSE) {
482      rtems_test_assert(rv == -1);
483      rtems_test_assert(errno == EBADF);
484    } else {
485      rtems_test_assert(rv == 0);
486    }
487  }
488
489  sc = rtems_task_delete(ctx->worker_id);
490  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
491
492  rv = unlink(path);
493  rtems_test_assert(rv == 0);
494
495  rtems_test_assert(ctx->close_count == 17);
496  rtems_test_assert(ctx->fcntl_count == 1);
497  rtems_test_assert(ctx->fdatasync_count == 1);
498  rtems_test_assert(ctx->fstat_count == 42);
499  rtems_test_assert(ctx->fsync_count == 1);
500  rtems_test_assert(ctx->ftruncate_count == 1);
501  rtems_test_assert(ctx->ioctl_count == 1);
502  rtems_test_assert(ctx->lseek_count == 1);
503  rtems_test_assert(ctx->open_count == 17);
504  rtems_test_assert(ctx->read_count == 1);
505  rtems_test_assert(ctx->readv_count == 1);
506  rtems_test_assert(ctx->write_count == 1);
507  rtems_test_assert(ctx->writev_count == 1);
508}
509
510static void test_tmpfile(test_context *ctx)
511{
512  rtems_resource_snapshot before;
513  FILE *f;
514  int rv;
515
516  rv = mkdir("/tmp", S_IRWXU | S_IRWXG | S_IRWXO);
517  rtems_test_assert(rv == 0);
518
519  f = tmpfile();
520  rtems_test_assert(f != NULL);
521  rv = fclose(f);
522  rtems_test_assert(rv == 0);
523
524  rtems_resource_snapshot_take(&before);
525  f = tmpfile();
526  rtems_test_assert(f != NULL);
527  rv = fclose(f);
528  rtems_test_assert(rv == 0);
529  rtems_test_assert(rtems_resource_snapshot_check(&before));
530}
531
532static void Init(rtems_task_argument arg)
533{
534  TEST_BEGIN();
535  test_close(&test_instance);
536  test_tmpfile(&test_instance);
537  TEST_END();
538  rtems_test_exit(0);
539}
540
541#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
542#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
543
544#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5
545
546#define CONFIGURE_MAXIMUM_TASKS 2
547
548#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
549
550#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
551
552#define CONFIGURE_INIT_TASK_PRIORITY 2
553#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
554
555#define CONFIGURE_INIT
556
557#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.