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