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 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 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 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 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