/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "abts.h" #include "testutil.h" #define APR_HOOK_PROBES_ENABLED #define APR_HOOK_PROBE_ENTRY(ud,ns,name,args) \ ud = toy_hook_probe_entry(#name) #define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args) \ toy_hook_probe_return(ud, #name, rv) #define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args) \ toy_hook_probe_invoke(ud, #name, src) #define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args) \ toy_hook_probe_complete(ud, #name, src, rv) #include "apr_hooks.h" #define TEST_DECLARE(type) type APR_DECLARE_EXTERNAL_HOOK(test,TEST,int, toyhook, (char *x, apr_size_t s)) APR_HOOK_STRUCT( APR_HOOK_LINK(toyhook) ) static void *toy_hook_probe_entry(const char *name); static void toy_hook_probe_return(void *ud, const char *name, int rv); static void toy_hook_probe_invoke(void *ud, const char *name, const char *src); static void toy_hook_probe_complete(void *ud, const char *name, const char *src, int rv); APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(test,TEST,int, toyhook, (char *x, apr_size_t s), (x, s), 0, -1) typedef struct { char *buf; apr_size_t buf_size; } hook_probe_data_t; static apr_pool_t *probe_buf_pool; static char *probe_buf; static void safe_concat(char *buf, apr_size_t buf_size, const char *append) { if (strlen(buf) + strlen(append) + 1 <= buf_size) { strcat(buf, append); } } static void *toy_hook_probe_entry(const char *name) { hook_probe_data_t *ud = apr_palloc(probe_buf_pool, sizeof *ud); ud->buf_size = 18; ud->buf = (char *)apr_palloc(probe_buf_pool, ud->buf_size); ud->buf[0] = '\0'; safe_concat(ud->buf, ud->buf_size, "E"); return (void *)ud; } static void toy_hook_probe_return(void *vud, const char *name, int rv) { hook_probe_data_t *ud = vud; safe_concat(ud->buf, ud->buf_size, "R"); probe_buf = ud->buf; } static void toy_hook_probe_invoke(void *vud, const char *name, const char *src) { hook_probe_data_t *ud = vud; safe_concat(ud->buf, ud->buf_size, "I"); safe_concat(ud->buf, ud->buf_size, src); } static void toy_hook_probe_complete(void *vud, const char *name, const char *src, int rv) { hook_probe_data_t *ud = vud; safe_concat(ud->buf, ud->buf_size, "C"); } static int toyhook_1(char *x, apr_size_t buf_size) { safe_concat(x, buf_size, "1"); return 0; } static int toyhook_2(char *x, apr_size_t buf_size) { safe_concat(x, buf_size, "2"); return 0; } static int toyhook_3(char *x, apr_size_t buf_size) { safe_concat(x, buf_size, "3"); return 0; } static int toyhook_4(char *x, apr_size_t buf_size) { safe_concat(x, buf_size, "4"); return 0; } static int toyhook_5(char *x, apr_size_t buf_size) { safe_concat(x, buf_size, "5"); return 0; } static void test_basic_ordering(abts_case *tc, void *data) { char buf[6] = {0}; apr_hook_global_pool = p; apr_hook_deregister_all(); apr_hook_debug_current = "5"; test_hook_toyhook(toyhook_5, NULL, NULL, APR_HOOK_MIDDLE + 2); apr_hook_debug_current = "1"; test_hook_toyhook(toyhook_1, NULL, NULL, APR_HOOK_MIDDLE - 2); apr_hook_debug_current = "3"; test_hook_toyhook(toyhook_3, NULL, NULL, APR_HOOK_MIDDLE); apr_hook_debug_current = "2"; test_hook_toyhook(toyhook_2, NULL, NULL, APR_HOOK_MIDDLE - 1); apr_hook_debug_current = "4"; test_hook_toyhook(toyhook_4, NULL, NULL, APR_HOOK_MIDDLE + 1); apr_hook_sort_all(); probe_buf_pool = p; test_run_toyhook(buf, sizeof buf); ABTS_STR_EQUAL(tc, "12345", buf); ABTS_STR_EQUAL(tc, "EI1CI2CI3CI4CI5CR", probe_buf); } static void test_pred_ordering(abts_case *tc, void *data) { char buf[10] = {0}; static const char *hook2_predecessors[] = {"1", NULL}; static const char *hook3_predecessors[] = {"2", NULL}; apr_hook_global_pool = p; apr_hook_deregister_all(); apr_hook_debug_current = "1"; test_hook_toyhook(toyhook_1, NULL, NULL, APR_HOOK_MIDDLE); apr_hook_debug_current = "3"; test_hook_toyhook(toyhook_3, hook3_predecessors, NULL, APR_HOOK_MIDDLE); apr_hook_debug_current = "2"; test_hook_toyhook(toyhook_2, hook2_predecessors, NULL, APR_HOOK_MIDDLE); apr_hook_debug_current = "2"; test_hook_toyhook(toyhook_2, hook2_predecessors, NULL, APR_HOOK_MIDDLE); apr_hook_sort_all(); probe_buf_pool = p; test_run_toyhook(buf, sizeof buf); /* FAILS ABTS_STR_EQUAL(tc, "1223", buf); */ } abts_suite *testhooks(abts_suite *suite) { suite = ADD_SUITE(suite); abts_run_test(suite, test_basic_ordering, NULL); abts_run_test(suite, test_pred_ordering, NULL); return suite; }