blob: ea3291b0d2c9141d5dac7336993087c9f333e307 [file] [log] [blame]
/*
* 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 <stdio.h>
#include <string.h>
#include <apr_general.h>
#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