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