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