source: rtems/testsuites/fstests/fsimfsgeneric01/init.c @ fa44c39

5
Last change on this file since fa44c39 was fa44c39, checked in by Sebastian Huber <sebastian.huber@…>, on 02/29/20 at 15:14:31

imfs: Add IMFS_add_node()

Update #3894.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 * Copyright (C) 2012, 2020 embedded brains GmbH (http://www.embedded-brains.de)
3 *
4 * The license and distribution terms for this file may be
5 * found in the file LICENSE in this distribution or at
6 * http://www.rtems.org/license/LICENSE.
7 */
8
9#ifdef HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <sys/stat.h>
14#include <sys/ioctl.h>
15#include <sys/uio.h>
16#include <fcntl.h>
17#include <unistd.h>
18#include <errno.h>
19
20#include <rtems/imfs.h>
21#include <rtems/malloc.h>
22#include <rtems/libcsupport.h>
23
24#include <tmacros.h>
25
26const char rtems_test_name[] = "FSIMFSGENERIC 1";
27
28typedef enum {
29  TEST_NEW,
30  TEST_INITIALIZED,
31  TEST_FSTAT_OPEN_0,
32  TEST_FSTAT_OPEN_1,
33  TEST_OPEN,
34  TEST_READ,
35  TEST_WRITE,
36  TEST_IOCTL,
37  TEST_LSEEK,
38  TEST_FTRUNCATE,
39  TEST_FSYNC,
40  TEST_FDATASYNC,
41  TEST_FCNTL,
42  TEST_READV,
43  TEST_WRITEV,
44  TEST_CLOSED,
45  TEST_FSTAT_UNLINK,
46  TEST_REMOVED,
47  TEST_DESTROYED
48} test_state;
49
50static int handler_open(
51  rtems_libio_t *iop,
52  const char *path,
53  int oflag,
54  mode_t mode
55)
56{
57  test_state *state = IMFS_generic_get_context_by_iop(iop);
58
59  rtems_test_assert(*state == TEST_FSTAT_OPEN_1);
60  *state = TEST_OPEN;
61
62  return 0;
63}
64
65static int handler_close(
66  rtems_libio_t *iop
67)
68{
69  test_state *state = IMFS_generic_get_context_by_iop(iop);
70
71  rtems_test_assert(*state == TEST_WRITEV);
72  *state = TEST_CLOSED;
73
74  return 0;
75}
76
77static ssize_t handler_read(
78  rtems_libio_t *iop,
79  void *buffer,
80  size_t count
81)
82{
83  test_state *state = IMFS_generic_get_context_by_iop(iop);
84
85  rtems_test_assert(*state == TEST_OPEN);
86  *state = TEST_READ;
87
88  return 0;
89}
90
91static ssize_t handler_write(
92  rtems_libio_t *iop,
93  const void *buffer,
94  size_t count
95)
96{
97  test_state *state = IMFS_generic_get_context_by_iop(iop);
98
99  rtems_test_assert(*state == TEST_READ);
100  *state = TEST_WRITE;
101
102  return 0;
103}
104
105static int handler_ioctl(
106  rtems_libio_t *iop,
107  ioctl_command_t request,
108  void *buffer
109)
110{
111  test_state *state = IMFS_generic_get_context_by_iop(iop);
112
113  rtems_test_assert(*state == TEST_WRITE);
114  *state = TEST_IOCTL;
115
116  return 0;
117}
118
119static off_t handler_lseek(
120  rtems_libio_t *iop,
121  off_t length,
122  int whence
123)
124{
125  test_state *state = IMFS_generic_get_context_by_iop(iop);
126
127  rtems_test_assert(*state == TEST_IOCTL);
128  *state = TEST_LSEEK;
129
130  return 0;
131}
132
133static int handler_fstat(
134  const rtems_filesystem_location_info_t *loc,
135  struct stat *buf
136)
137{
138  test_state *state = IMFS_generic_get_context_by_location(loc);
139
140  switch (*state) {
141    case TEST_INITIALIZED:
142      *state = TEST_FSTAT_OPEN_0;
143      break;
144    case TEST_FSTAT_OPEN_0:
145      *state = TEST_FSTAT_OPEN_1;
146      break;
147    case TEST_CLOSED:
148      *state = TEST_FSTAT_UNLINK;
149      break;
150    default:
151      rtems_test_assert(0);
152      break;
153  }
154
155  buf->st_mode = S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO;
156
157  return 0;
158}
159
160static int handler_ftruncate(
161  rtems_libio_t *iop,
162  off_t length
163)
164{
165  test_state *state = IMFS_generic_get_context_by_iop(iop);
166
167  rtems_test_assert(*state == TEST_LSEEK);
168  *state = TEST_FTRUNCATE;
169
170  return 0;
171}
172
173static int handler_fsync(
174  rtems_libio_t *iop
175)
176{
177  test_state *state = IMFS_generic_get_context_by_iop(iop);
178
179  rtems_test_assert(*state == TEST_FTRUNCATE);
180  *state = TEST_FSYNC;
181
182  return 0;
183}
184
185static int handler_fdatasync(
186  rtems_libio_t *iop
187)
188{
189  test_state *state = IMFS_generic_get_context_by_iop(iop);
190
191  rtems_test_assert(*state == TEST_FSYNC);
192  *state = TEST_FDATASYNC;
193
194  return 0;
195}
196
197static int handler_fcntl(
198  rtems_libio_t *iop,
199  int cmd
200)
201{
202  test_state *state = IMFS_generic_get_context_by_iop(iop);
203
204  rtems_test_assert(*state == TEST_FDATASYNC);
205  *state = TEST_FCNTL;
206
207  return 0;
208}
209
210static ssize_t handler_readv(
211  rtems_libio_t *iop,
212  const struct iovec *iov,
213  int iovcnt,
214  ssize_t total
215)
216{
217  test_state *state = IMFS_generic_get_context_by_iop(iop);
218
219  rtems_test_assert(*state == TEST_FCNTL);
220  *state = TEST_READV;
221
222  return 0;
223}
224
225static ssize_t handler_writev(
226  rtems_libio_t *iop,
227  const struct iovec *iov,
228  int iovcnt,
229  ssize_t total
230)
231{
232  test_state *state = IMFS_generic_get_context_by_iop(iop);
233
234  rtems_test_assert(*state == TEST_READV);
235  *state = TEST_WRITEV;
236
237  return 0;
238}
239
240static const rtems_filesystem_file_handlers_r node_handlers = {
241  .open_h = handler_open,
242  .close_h = handler_close,
243  .read_h = handler_read,
244  .write_h = handler_write,
245  .ioctl_h = handler_ioctl,
246  .lseek_h = handler_lseek,
247  .fstat_h = handler_fstat,
248  .ftruncate_h = handler_ftruncate,
249  .fsync_h = handler_fsync,
250  .fdatasync_h = handler_fdatasync,
251  .fcntl_h = handler_fcntl,
252  .readv_h = handler_readv,
253  .writev_h = handler_writev
254};
255
256static IMFS_jnode_t *node_initialize(
257  IMFS_jnode_t *node,
258  void *arg
259)
260{
261  test_state *state = NULL;
262
263  node = IMFS_node_initialize_generic(node, arg);
264  state = IMFS_generic_get_context_by_node(node);
265
266  rtems_test_assert(*state == TEST_NEW);
267  *state = TEST_INITIALIZED;
268
269  return node;
270}
271
272static IMFS_jnode_t *node_remove(IMFS_jnode_t *node)
273{
274  test_state *state = IMFS_generic_get_context_by_node(node);
275
276  rtems_test_assert(*state == TEST_FSTAT_UNLINK);
277  *state = TEST_REMOVED;
278
279  return node;
280}
281
282static void node_destroy(IMFS_jnode_t *node)
283{
284  test_state *state = IMFS_generic_get_context_by_node(node);
285
286  rtems_test_assert(*state == TEST_REMOVED);
287  *state = TEST_DESTROYED;
288
289  IMFS_node_destroy_default(node);
290}
291
292static const IMFS_node_control node_control = {
293  .handlers = &node_handlers,
294  .node_initialize = node_initialize,
295  .node_remove = node_remove,
296  .node_destroy = node_destroy
297};
298
299static void test_node_operations(const char *path)
300{
301  int rv;
302  int fd;
303  char buf[1];
304  ssize_t n;
305  off_t off;
306  struct iovec iov = {
307    .iov_base = &buf[0],
308    .iov_len = (int) sizeof(buf)
309  };
310
311  fd = open(path, O_RDWR);
312  rtems_test_assert(fd >= 0);
313
314  n = read(fd, buf, sizeof(buf));
315  rtems_test_assert(n == 0);
316
317  n = write(fd, buf, sizeof(buf));
318  rtems_test_assert(n == 0);
319
320  rv = ioctl(fd, 0);
321  rtems_test_assert(rv == 0);
322
323  off = lseek(fd, 0, SEEK_SET);
324  rtems_test_assert(off == 0);
325
326  rv = ftruncate(fd, 0);
327  rtems_test_assert(rv == 0);
328
329  rv = fsync(fd);
330  rtems_test_assert(rv == 0);
331
332  rv = fdatasync(fd);
333  rtems_test_assert(rv == 0);
334
335  rv = fcntl(fd, F_GETFD);
336  rtems_test_assert(rv >= 0);
337
338  rv = readv(fd, &iov, 1);
339  rtems_test_assert(rv == 0);
340
341  rv = writev(fd, &iov, 1);
342  rtems_test_assert(rv == 0);
343
344  rv = close(fd);
345  rtems_test_assert(rv == 0);
346
347  rv = unlink(path);
348  rtems_test_assert(rv == 0);
349}
350
351static void test_imfs_make_generic_node(void)
352{
353  static const char path[] = "generic";
354  test_state state;
355  int rv;
356
357  state = TEST_NEW;
358  rv = IMFS_make_generic_node(
359    path,
360    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
361    &node_control,
362    &state
363  );
364  rtems_test_assert(rv == 0);
365
366  test_node_operations(path);
367  rtems_test_assert(state == TEST_DESTROYED);
368}
369
370static IMFS_jnode_t *node_initialize_error(
371  IMFS_jnode_t *node,
372  void *arg
373)
374{
375  errno = EIO;
376
377  return NULL;
378}
379
380static IMFS_jnode_t *node_remove_inhibited(IMFS_jnode_t *node)
381{
382  rtems_test_assert(false);
383
384  return node;
385}
386
387static void node_destroy_inhibited(IMFS_jnode_t *node)
388{
389  rtems_test_assert(false);
390}
391
392static const IMFS_node_control node_initialization_error_control = {
393  .handlers = &node_handlers,
394  .node_initialize = node_initialize_error,
395  .node_remove = node_remove_inhibited,
396  .node_destroy = node_destroy_inhibited
397};
398
399static const rtems_filesystem_operations_table *imfs_ops;
400
401static int other_clone(rtems_filesystem_location_info_t *loc)
402{
403  return (*imfs_ops->clonenod_h)(loc);
404}
405
406static rtems_filesystem_mount_table_entry_t *get_imfs_mt_entry(void)
407{
408  return (rtems_filesystem_mount_table_entry_t *)
409    rtems_chain_first(&rtems_filesystem_mount_table);
410}
411
412static void test_imfs_make_generic_node_errors(void)
413{
414  static const char path[] = "generic";
415  rtems_filesystem_mount_table_entry_t *mt_entry;
416  rtems_filesystem_operations_table other_ops;
417  rtems_resource_snapshot before;
418  void *opaque;
419  int rv;
420
421  rtems_resource_snapshot_take(&before);
422
423  errno = 0;
424  rv = IMFS_make_generic_node(
425    path,
426    S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO,
427    &node_control,
428    NULL
429  );
430  rtems_test_assert(rv == -1);
431  rtems_test_assert(errno == EINVAL);
432  rtems_test_assert(rtems_resource_snapshot_check(&before));
433
434  errno = 0;
435  mt_entry = get_imfs_mt_entry();
436  imfs_ops = mt_entry->ops;
437  other_ops = *imfs_ops;
438  other_ops.clonenod_h = other_clone;
439  mt_entry->ops = &other_ops;
440  rv = IMFS_make_generic_node(
441    path,
442    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
443    &node_control,
444    NULL
445  );
446  mt_entry->ops = imfs_ops;
447  rtems_test_assert(rv == -1);
448  rtems_test_assert(errno == ENOTSUP);
449  rtems_test_assert(rtems_resource_snapshot_check(&before));
450
451  errno = 0;
452  opaque = rtems_heap_greedy_allocate(NULL, 0);
453  rv = IMFS_make_generic_node(
454    path,
455    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
456    &node_control,
457    NULL
458  );
459  rtems_heap_greedy_free(opaque);
460  rtems_test_assert(rv == -1);
461  rtems_test_assert(errno == ENOMEM);
462  rtems_test_assert(rtems_resource_snapshot_check(&before));
463
464  errno = 0;
465  rv = IMFS_make_generic_node(
466    path,
467    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
468    &node_initialization_error_control,
469    NULL
470  );
471  rtems_test_assert(rv == -1);
472  rtems_test_assert(errno == EIO);
473  rtems_test_assert(rtems_resource_snapshot_check(&before));
474
475  errno = 0;
476  rv = IMFS_make_generic_node(
477    "/nil/nada",
478    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
479    &node_control,
480    NULL
481  );
482  rtems_test_assert(rv == -1);
483  rtems_test_assert(errno == ENOENT);
484  rtems_test_assert(rtems_resource_snapshot_check(&before));
485}
486
487static void user_node_destroy(IMFS_jnode_t *node)
488{
489  test_state *state = IMFS_generic_get_context_by_node(node);
490
491  rtems_test_assert(*state == TEST_REMOVED);
492  *state = TEST_DESTROYED;
493}
494
495static const IMFS_node_control user_node_control = {
496  .handlers = &node_handlers,
497  .node_initialize = node_initialize,
498  .node_remove = node_remove,
499  .node_destroy = user_node_destroy
500};
501
502static void test_imfs_add_node(void)
503{
504  static const char path[] = "/";
505  static const char name[] = "node";
506  size_t namelen = sizeof(name) - 1;
507  void *opaque;
508  rtems_resource_snapshot before;
509  IMFS_generic_t node = IMFS_GENERIC_NODE_INITIALIZER(
510    &user_node_control,
511    name,
512    namelen,
513    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
514  );
515  test_state state;
516  int rv;
517
518  /* Ensure that sure no dynamic memory is used */
519  opaque = rtems_heap_greedy_allocate(NULL, 0);
520
521  rtems_resource_snapshot_take(&before);
522
523  state = TEST_NEW;
524  rv = IMFS_add_node(path, &node.Node, &state);
525  rtems_test_assert(rv == 0);
526
527  test_node_operations(name);
528  rtems_test_assert(state == TEST_DESTROYED);
529
530  rtems_test_assert(rtems_resource_snapshot_check(&before));
531  rtems_heap_greedy_free(opaque);
532}
533
534static void test_imfs_add_node_errors(void)
535{
536  static const char path[] = "/";
537  static const char name[] = "node";
538  size_t namelen = sizeof(name) - 1;
539  const char invalid_name[] = "/node";
540  size_t invalid_namelen = sizeof(invalid_name) - 1;
541  IMFS_jnode_t node = IMFS_NODE_INITIALIZER(
542    &user_node_control,
543    name,
544    namelen,
545    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
546  );
547  IMFS_jnode_t invalid_mode_node = IMFS_NODE_INITIALIZER(
548    &user_node_control,
549    name,
550    namelen,
551    S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO
552  );
553  IMFS_jnode_t init_error_node = IMFS_NODE_INITIALIZER(
554    &node_initialization_error_control,
555    name,
556    namelen,
557    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
558  );
559  IMFS_jnode_t invalid_name_node = IMFS_NODE_INITIALIZER(
560    &user_node_control,
561    invalid_name,
562    invalid_namelen,
563    S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
564  );
565  rtems_filesystem_mount_table_entry_t *mt_entry;
566  rtems_filesystem_operations_table other_ops;
567  void *opaque;
568  rtems_resource_snapshot before;
569  int rv;
570
571  /* Ensure that sure no dynamic memory is used */
572  opaque = rtems_heap_greedy_allocate(NULL, 0);
573
574  rtems_resource_snapshot_take(&before);
575
576  errno = 0;
577  rv = IMFS_add_node(path, &invalid_mode_node, NULL);
578  rtems_test_assert(rv == -1);
579  rtems_test_assert(errno == EINVAL);
580  rtems_test_assert(rtems_resource_snapshot_check(&before));
581
582  errno = 0;
583  mt_entry = get_imfs_mt_entry();
584  imfs_ops = mt_entry->ops;
585  other_ops = *imfs_ops;
586  other_ops.clonenod_h = other_clone;
587  mt_entry->ops = &other_ops;
588  rv = IMFS_add_node(path, &node, NULL);
589  mt_entry->ops = imfs_ops;
590  rtems_test_assert(rv == -1);
591  rtems_test_assert(errno == ENOTSUP);
592  rtems_test_assert(rtems_resource_snapshot_check(&before));
593
594  errno = 0;
595  rv = IMFS_add_node(path, &init_error_node, NULL);
596  rtems_test_assert(rv == -1);
597  rtems_test_assert(errno == EIO);
598  rtems_test_assert(rtems_resource_snapshot_check(&before));
599
600  errno = 0;
601  rv = IMFS_add_node("/nil/nada", &node, NULL);
602  rtems_test_assert(rv == -1);
603  rtems_test_assert(errno == ENOENT);
604  rtems_test_assert(rtems_resource_snapshot_check(&before));
605
606  errno = 0;
607  rv = IMFS_add_node(path, &invalid_name_node, NULL);
608  rtems_test_assert(rv == -1);
609  rtems_test_assert(errno == EINVAL);
610  rtems_test_assert(rtems_resource_snapshot_check(&before));
611
612  rtems_heap_greedy_free(opaque);
613}
614
615static void Init(rtems_task_argument arg)
616{
617  TEST_BEGIN();
618
619  test_imfs_make_generic_node();
620  test_imfs_make_generic_node_errors();
621  test_imfs_add_node();
622  test_imfs_add_node_errors();
623
624  TEST_END();
625  rtems_test_exit(0);
626}
627
628#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
629#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
630
631#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
632
633#define CONFIGURE_MAXIMUM_TASKS 1
634
635#define CONFIGURE_UNIFIED_WORK_AREAS
636
637#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
638
639#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
640
641#define CONFIGURE_INIT
642
643#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.