xref: /petsc/src/sys/tests/ex65.c (revision 2286efddd54511ab18e8e2adb1e023c4bf8f0b92)
1 static const char help[] = "Test PetscFunctionList.\n";
2 
3 #include <petscsys.h>
4 #include <petscviewer.h>
5 
6 #define PETSC_DEFINE_FUNCTION_AND_STR(name) \
7   static void name(void) \
8   { \
9     puts("called " PetscStringize(name) "()"); \
10   } \
11   static const char name##_str[] = PetscStringize(name)
12 
13 PETSC_DEFINE_FUNCTION_AND_STR(foo);
14 PETSC_DEFINE_FUNCTION_AND_STR(bar);
15 PETSC_DEFINE_FUNCTION_AND_STR(baz);
16 PETSC_DEFINE_FUNCTION_AND_STR(bop);
17 PETSC_DEFINE_FUNCTION_AND_STR(qux);
18 PETSC_DEFINE_FUNCTION_AND_STR(quux);
19 PETSC_DEFINE_FUNCTION_AND_STR(blip);
20 PETSC_DEFINE_FUNCTION_AND_STR(blap);
21 PETSC_DEFINE_FUNCTION_AND_STR(blop);
22 PETSC_DEFINE_FUNCTION_AND_STR(graulty);
23 PETSC_DEFINE_FUNCTION_AND_STR(quix);
24 
25 static const char *const all_names[]   = {foo_str, bar_str, baz_str, bop_str, qux_str, quux_str, blip_str, blap_str, blop_str, graulty_str, quix_str};
26 static void (*const all_funcs[])(void) = {foo, bar, baz, bop, qux, quux, blip, blap, blop, graulty, quix};
27 static const size_t num_names          = PETSC_STATIC_ARRAY_LENGTH(all_names);
28 static const size_t num_funcs          = PETSC_STATIC_ARRAY_LENGTH(all_funcs);
29 
TestPetscFunctionListCreate(PetscViewer viewer,PetscFunctionList * fl,PetscFunctionList * fl_dup)30 static PetscErrorCode TestPetscFunctionListCreate(PetscViewer viewer, PetscFunctionList *fl, PetscFunctionList *fl_dup)
31 {
32   PetscFunctionBegin;
33   // add the function
34   PetscCall(PetscFunctionListAdd(fl, foo_str, foo));
35   PetscCall(PetscFunctionListView(*fl, NULL));
36   // remove it
37   PetscCall(PetscFunctionListAdd(fl, foo_str, NULL));
38   PetscCheck(*fl, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Emptying PetscFunctionList has destroyed it!");
39   PetscCall(PetscFunctionListView(*fl, NULL));
40   // should not do anything
41   PetscCall(PetscFunctionListClear(*fl));
42   PetscCall(PetscFunctionListView(*fl, viewer));
43   PetscCall(PetscFunctionListDuplicate(*fl, fl_dup));
44   PetscCheck(*fl_dup, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Duplicating empty function list has not allocated a new one");
45   // still empty
46   PetscCall(PetscFunctionListView(*fl, viewer));
47   // also empty
48   PetscCall(PetscFunctionListView(*fl_dup, viewer));
49   PetscFunctionReturn(PETSC_SUCCESS);
50 }
51 
TestPetscFunctionListFind(PetscViewer viewer,PetscFunctionList fl,PetscFunctionList fl_dup,size_t * fl_size,size_t * fl_dup_size)52 static PetscErrorCode TestPetscFunctionListFind(PetscViewer viewer, PetscFunctionList fl, PetscFunctionList fl_dup, size_t *fl_size, size_t *fl_dup_size)
53 {
54   PetscFunctionBegin;
55   // add a bunch of functions, and ensure they are all there
56   for (size_t i = 0; i < num_funcs; ++i) {
57     PetscErrorCodeFn *func;
58 
59     PetscCall(PetscFunctionListAdd(&fl, all_names[i], all_funcs[i]));
60     PetscCall(PetscFunctionListFind(fl, all_names[i], &func));
61     PetscCheck(func == (PetscErrorCodeFn *)all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() immediately after inserting it! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)func, (void *)(PETSC_UINTPTR_T)all_funcs[i]);
62     // make sure the pointer is good
63     (void)func();
64   }
65 
66   // ensure that none of them are missing
67   for (size_t i = 0; i < num_funcs; ++i) {
68     PetscErrorCodeFn *func;
69 
70     PetscCall(PetscFunctionListFind(fl, all_names[i], &func));
71     PetscCheck(func == (PetscErrorCodeFn *)all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() after inserting all functions! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)func, (void *)(PETSC_UINTPTR_T)all_funcs[i]);
72     // make sure the pointer is good
73     (void)func();
74   }
75 
76   // appends to fl_dup
77   PetscCall(PetscFunctionListDuplicate(fl, &fl_dup));
78 
79   // ensure that none of them are missing
80   for (size_t i = 0; i < num_funcs; ++i) {
81     PetscErrorCodeFn *fl_func, *fl_dup_func;
82 
83     PetscCall(PetscFunctionListFind(fl, all_names[i], &fl_func));
84     PetscCheck(fl_func == (PetscErrorCodeFn *)all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() after inserting all functions! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_func, (void *)(PETSC_UINTPTR_T)all_funcs[i]);
85     // make sure the pointer is good
86     (void)fl_func();
87     PetscCall(PetscFunctionListFind(fl_dup, all_names[i], &fl_dup_func));
88     PetscCheck(fl_dup_func == fl_func, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() returned different results for %s() for duplicated function list. returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_dup_func, (void *)(PETSC_UINTPTR_T)fl_func);
89     (void)fl_dup_func();
90   }
91 
92   // same as in fl
93   PetscCall(PetscFunctionListView(fl_dup, viewer));
94   // clearing fl should have no effect on fl_dup
95   PetscCall(PetscFunctionListClear(fl));
96   // ensure that none of them are missing
97   for (size_t i = 0; i < num_funcs; ++i) {
98     PetscErrorCodeFn *fl_dup_func;
99 
100     PetscCall(PetscFunctionListFind(fl_dup, all_names[i], &fl_dup_func));
101     PetscCheck(fl_dup_func == (PetscErrorCodeFn *)all_funcs[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListFind() failed to find %s() in duplicated function list after clearing original list! returned %p != expected %p", all_names[i], (void *)(PETSC_UINTPTR_T)fl_dup_func, (void *)(PETSC_UINTPTR_T)all_funcs[i]);
102     (void)fl_dup_func();
103   }
104   PetscCall(PetscFunctionListView(fl_dup, viewer));
105   *fl_size     = 0;
106   *fl_dup_size = num_funcs;
107   PetscFunctionReturn(PETSC_SUCCESS);
108 }
109 
TestPetscFunctionListGet(PetscViewer viewer,PetscFunctionList fl,PetscFunctionList fl_dup,size_t expected_fl_size,size_t expected_fl_dup_size)110 static PetscErrorCode TestPetscFunctionListGet(PetscViewer viewer, PetscFunctionList fl, PetscFunctionList fl_dup, size_t expected_fl_size, size_t expected_fl_dup_size)
111 {
112   const char **array;
113   int          n;
114 #define PetscCheckArrayPointer(expected_non_null, array) \
115   PetscCheck((expected_non_null) ? (array) != NULL : (array) == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned invalid array (%p) for cleared function list, expected %s", (void *)(array), (expected_non_null) ? "non-null" : "null")
116 
117   PetscFunctionBegin;
118   PetscCall(PetscFunctionListGet(fl, &array, &n));
119   PetscCheck((size_t)n == expected_fl_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned unexpected size %d, expected %zu", n, expected_fl_size);
120   PetscCheckArrayPointer(expected_fl_size, array);
121 
122   PetscCall(PetscFunctionListGet(fl_dup, &array, &n));
123   PetscCheck((size_t)n == expected_fl_dup_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscFunctionListGet() returned unexpected size %d, expected %zu", n, expected_fl_dup_size);
124   PetscCheckArrayPointer(expected_fl_dup_size, array);
125   for (int i = 0; i < n; ++i) PetscCall(PetscViewerASCIIPrintf(viewer, "%d: %s\n", i + 1, array[i]));
126   PetscCall(PetscFree(array));
127   // ensure that free-ing the array is OK
128   PetscCall(PetscFunctionListView(fl_dup, viewer));
129   PetscFunctionReturn(PETSC_SUCCESS);
130 #undef PetscCheckArrayPointer
131 }
132 
main(int argc,char * argv[])133 int main(int argc, char *argv[])
134 {
135   PetscViewer       viewer;
136   PetscFunctionList fl = NULL, fl_dup = NULL;
137   size_t            fl_size, fl_dup_size;
138 
139   PetscFunctionBeginUser;
140   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
141   PetscCheck(num_names == num_funcs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of functions %zu != number of function names %zu", num_funcs, num_names);
142   PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD, &viewer));
143 
144   PetscCall(TestPetscFunctionListCreate(viewer, &fl, &fl_dup));
145   PetscCall(TestPetscFunctionListFind(viewer, fl, fl_dup, &fl_size, &fl_dup_size));
146   PetscCall(TestPetscFunctionListGet(viewer, fl, fl_dup, fl_size, fl_dup_size));
147   PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, PETSC_STDOUT, "my_prefix_", "-petsc_function_type", "Description", "PetscFunctionList", fl_dup, "foo", "bar"));
148 
149   PetscCall(PetscFunctionListDestroy(&fl));
150   PetscCheck(fl == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to destroy PetscFunctionList, pointer (%p) is non-null", (void *)fl);
151   PetscCall(PetscFunctionListDestroy(&fl_dup));
152   PetscCheck(fl_dup == NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to destroy PetscFunctionList, pointer (%p) is non-null", (void *)fl_dup);
153   PetscCall(PetscFinalize());
154   return 0;
155 }
156 
157 /*TEST
158 
159   test:
160 
161 TEST*/
162