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 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 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 PetscVoidFn *func; 58 59 PetscCall(PetscFunctionListAdd(&fl, all_names[i], all_funcs[i])); 60 PetscCall(PetscFunctionListFind(fl, all_names[i], &func)); 61 PetscCheck(func == 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 func(); 64 } 65 66 // ensure that none of them are missing 67 for (size_t i = 0; i < num_funcs; ++i) { 68 PetscVoidFn *func; 69 70 PetscCall(PetscFunctionListFind(fl, all_names[i], &func)); 71 PetscCheck(func == 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 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 PetscVoidFn *fl_func, *fl_dup_func; 82 83 PetscCall(PetscFunctionListFind(fl, all_names[i], &fl_func)); 84 PetscCheck(fl_func == 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 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 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 PetscVoidFn *fl_dup_func; 99 100 PetscCall(PetscFunctionListFind(fl_dup, all_names[i], &fl_dup_func)); 101 PetscCheck(fl_dup_func == 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 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 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 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