/* * error-test.c -- test the error functions * * ==================================================================== * 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 #include #include #include "svn_error_codes.h" #include "svn_error.h" #include "private/svn_error_private.h" #include "../svn_test.h" static svn_error_t * test_error_root_cause(apr_pool_t *pool) { apr_status_t secondary_err_codes[] = { SVN_ERR_STREAM_UNRECOGNIZED_DATA, SVN_ERR_STREAM_MALFORMED_DATA }; apr_status_t root_cause_err_code = SVN_ERR_STREAM_UNEXPECTED_EOF; int i; svn_error_t *err, *root_err; /* Nest several errors. */ err = svn_error_create(root_cause_err_code, NULL, "root cause"); for (i = 0; i < 2; i++) err = svn_error_create(secondary_err_codes[i], err, NULL); /* Verify that the error is detected at the proper location in the error chain. */ root_err = svn_error_root_cause(err); if (root_err == NULL) { svn_error_clear(err); return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "svn_error_root_cause failed to locate any " "root error in the chain"); } for (i = 0; i < 2; i++) { if (root_err->apr_err == secondary_err_codes[i]) { svn_error_clear(err); return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "svn_error_root_cause returned the " "wrong error from the chain"); } } if (root_err->apr_err != root_cause_err_code) { svn_error_clear(err); return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "svn_error_root_cause failed to locate the " "correct error from the chain"); } svn_error_clear(err); return SVN_NO_ERROR; } static svn_error_t * test_error_purge_tracing(apr_pool_t *pool) { svn_error_t *err, *err2, *child; if (SVN_NO_ERROR != svn_error_purge_tracing(SVN_NO_ERROR)) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "svn_error_purge_tracing() didn't return " "SVN_NO_ERROR after being passed a " "SVN_NO_ERROR."); err = svn_error_trace(svn_error_create(SVN_ERR_BASE, NULL, "root error")); #ifdef SVN_ERR__TRACING if (! svn_error__is_tracing_link(err)) { return svn_error_create(SVN_ERR_TEST_FAILED, err, "The top error is not a tracing link:"); } #endif err = svn_error_trace(svn_error_create(SVN_ERR_BASE, err, "other error")); #ifdef SVN_ERR__TRACING if (! svn_error__is_tracing_link(err)) { return svn_error_create(SVN_ERR_TEST_FAILED, err, "The top error is not a tracing link:"); } #endif err2 = svn_error_purge_tracing(err); for (child = err2; child; child = child->child) if (svn_error__is_tracing_link(child)) { return svn_error_create(SVN_ERR_TEST_FAILED, err, "Tracing link found after purging the " "following chain:"); } svn_error_clear(err); #ifdef SVN_ERR__TRACING /* Make an error chain containing only tracing errors and check that svn_error_purge_tracing() asserts on it. */ { svn_error_t err_copy; svn_error_malfunction_handler_t orig_handler; /* For this test, use a random error status. */ err = svn_error_create(SVN_ERR_BAD_UUID, NULL, ""); err = svn_error_trace(err); err->child->message = err->message; /* Register a malfunction handler that doesn't call abort() to check that a new error chain with an assertion error is returned. */ orig_handler = svn_error_set_malfunction_handler(svn_error_raise_on_malfunction); err2 = svn_error_purge_tracing(err); svn_error_set_malfunction_handler(orig_handler); err_copy = *err; if (err2) { /* If err2 does share the same pool as err, then make a copy of err2 and err3 before err is cleared. */ svn_error_t err2_copy = *err2; svn_error_t *err3 = err2; svn_error_t err3_copy; while (err3 && svn_error__is_tracing_link(err3)) err3 = err3->child; if (err3) err3_copy = *err3; else err3_copy.apr_err = APR_SUCCESS; svn_error_clear(err); /* The returned error is only safe to clear if this assertion holds, otherwise it has the same pool as the original error. */ SVN_TEST_ASSERT(err_copy.pool != err2_copy.pool); svn_error_clear(err2); SVN_TEST_ASSERT(err3); SVN_TEST_ASSERT(SVN_ERROR_IN_CATEGORY(err2_copy.apr_err, SVN_ERR_MALFUNC_CATEGORY_START)); SVN_TEST_ASSERT(err3_copy.apr_err == err2_copy.apr_err); SVN_TEST_ASSERT( SVN_ERR_ASSERTION_ONLY_TRACING_LINKS == err3_copy.apr_err); } else { svn_error_clear(err); SVN_TEST_ASSERT(err2); } } #endif return SVN_NO_ERROR; } static svn_error_t * test_error_symbolic_name(apr_pool_t *pool) { struct { svn_errno_t errcode; const char *errname; } errors[] = { { SVN_ERR_BAD_CONTAINING_POOL, "SVN_ERR_BAD_CONTAINING_POOL" }, { SVN_ERR_BAD_FILENAME, "SVN_ERR_BAD_FILENAME" }, { SVN_ERR_XML_ATTRIB_NOT_FOUND, "SVN_ERR_XML_ATTRIB_NOT_FOUND" }, { SVN_ERR_ENTRY_NOT_FOUND, "SVN_ERR_ENTRY_NOT_FOUND" }, { SVN_ERR_ENTRY_CATEGORY_START + 1, NULL }, /* unused slot */ { SVN_ERR_ENTRY_EXISTS, "SVN_ERR_ENTRY_EXISTS" }, { SVN_ERR_ASSERTION_ONLY_TRACING_LINKS, "SVN_ERR_ASSERTION_ONLY_TRACING_LINKS" }, { SVN_ERR_FS_CORRUPT, "SVN_ERR_FS_CORRUPT" }, /* The following two error codes can return either of their names as the string. For simplicity, test what the current implementation returns; but if it starts returning "SVN_ERR_WC_NOT_DIRECTORY", that's fine (and permitted by the API contract). */ { SVN_ERR_WC_NOT_DIRECTORY, "SVN_ERR_WC_NOT_WORKING_COPY" }, { SVN_ERR_WC_NOT_WORKING_COPY, "SVN_ERR_WC_NOT_WORKING_COPY" }, /* Test an implementation detail. */ { SVN_ERR_BAD_CATEGORY_START, "SVN_ERR_BAD_CONTAINING_POOL" }, #ifdef SVN_DEBUG { ENOENT, "ENOENT" }, { APR_ENOPOOL, "APR_ENOPOOL" }, #endif /* Test non-errors. */ { -1, NULL }, { SVN_ERR_WC_CATEGORY_START - 1, NULL }, /* Whitebox-test exceptional cases. */ { SVN_WARNING, "SVN_WARNING" }, { 0, "SVN_NO_ERROR" } /* No sentinel. */ }; int i; for (i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) SVN_TEST_STRING_ASSERT(svn_error_symbolic_name(errors[i].errcode), errors[i].errname); return SVN_NO_ERROR; } /* The test table. */ static int max_threads = 1; static struct svn_test_descriptor_t test_funcs[] = { SVN_TEST_NULL, SVN_TEST_PASS2(test_error_root_cause, "test svn_error_root_cause"), SVN_TEST_PASS2(test_error_purge_tracing, "test svn_error_purge_tracing"), SVN_TEST_PASS2(test_error_symbolic_name, "test svn_error_symbolic_name"), SVN_TEST_NULL }; SVN_TEST_MAIN