blob: 0b1726e753342e4e91d8759d7d022666d7460bab [file] [log] [blame]
/*
* task-test.c: a collection of svn_task__* tests
*
* ====================================================================
* 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.
* ====================================================================
*/
/* ====================================================================
To add tests, look toward the bottom of this file.
*/
#include <stdio.h>
#include <string.h>
#include <apr_pools.h>
#include "../svn_test.h"
#include "svn_sorts.h"
#include "private/svn_atomic.h"
#include "private/svn_task.h"
static svn_error_t *
test_null_task(apr_pool_t *pool)
{
SVN_ERR(svn_task__run(1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
pool, pool));
SVN_ERR(svn_task__run(2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
pool, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
noop_process_func(void **result,
svn_task__t *task,
void *thread_context,
void *process_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
*result = NULL;
return SVN_NO_ERROR;
}
static svn_error_t *
noop_output_func(svn_task__t *task,
void *result,
void *output_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
return SVN_NO_ERROR;
}
static svn_error_t *
noop_thead_context_constructor(void **thread_context,
void *baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
*thread_context = NULL;
return SVN_NO_ERROR;
}
static svn_error_t *
noop_cancel_func(void *baton)
{
return SVN_NO_ERROR;
}
static svn_error_t *
test_noop_task(apr_pool_t *pool)
{
SVN_ERR(svn_task__run(1,
noop_process_func, NULL,
noop_output_func, NULL,
noop_thead_context_constructor, NULL,
noop_cancel_func, NULL, pool, pool));
SVN_ERR(svn_task__run(2,
noop_process_func, NULL,
noop_output_func, NULL,
noop_thead_context_constructor, NULL,
noop_cancel_func, NULL, pool, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
counter_func(void **result,
svn_task__t *task,
void *thread_context,
void *process_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_int64_t value = *(apr_int64_t*)process_baton;
apr_pool_t *sub_task_pool;
apr_int64_t *partial_result;
apr_int64_t *partial_baton;
if (value > 1)
{
partial_result = apr_palloc(result_pool, sizeof(*partial_result));
*partial_result = 1;
value -= *partial_result;
sub_task_pool = svn_task__create_process_pool(task);
partial_baton = apr_palloc(sub_task_pool, sizeof(*partial_baton));
*partial_baton = MAX(1, value / 2);
value -= *partial_baton;
SVN_ERR(svn_task__add_similar(task, sub_task_pool,
partial_result, partial_baton));
}
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
if (value > 1)
{
partial_result = apr_palloc(result_pool, sizeof(*partial_result));
*partial_result = 1;
value -= *partial_result;
sub_task_pool = svn_task__create_process_pool(task);
partial_baton = apr_palloc(sub_task_pool, sizeof(*partial_baton));
*partial_baton = value - 1;
value -= *partial_baton;
SVN_ERR(svn_task__add_similar(task, sub_task_pool,
partial_result, partial_baton));
}
partial_result = apr_palloc(result_pool, sizeof(*partial_result));
*partial_result = value;
*result = partial_result;
return SVN_NO_ERROR;
}
static svn_error_t *
sum_func(svn_task__t *task,
void *result,
void *output_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_int64_t *result_p = result;
apr_int64_t *output_p = output_baton;
if (result_p)
*output_p += *result_p;
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
return SVN_NO_ERROR;
}
static svn_error_t *
test_counting(apr_pool_t *pool)
{
apr_int64_t start = 1000000;
apr_int64_t result = 0;
SVN_ERR(svn_task__run(1, counter_func, &start, sum_func, &result,
NULL, NULL, NULL, NULL, pool, pool));
SVN_TEST_ASSERT(result == start);
result = 0;
SVN_ERR(svn_task__run(4, counter_func, &start, sum_func, &result,
NULL, NULL, NULL, NULL, pool, pool));
SVN_TEST_ASSERT(result == start);
return SVN_NO_ERROR;
}
static svn_error_t *
cancel_at_10k(void *baton)
{
if (*(apr_int64_t*)baton == 10000)
return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
return SVN_NO_ERROR;
}
static svn_error_t *
test_cancellation(apr_pool_t *pool)
{
apr_int64_t start = 1000000;
apr_int64_t result = 0;
SVN_TEST_ASSERT_ERROR(svn_task__run(1, counter_func, &start, sum_func, &result,
NULL, NULL, cancel_at_10k, &result,
pool, pool),
SVN_ERR_CANCELLED);
SVN_TEST_ASSERT(result == 10000);
result = 0;
SVN_TEST_ASSERT_ERROR(svn_task__run(8, counter_func, &start, sum_func, &result,
NULL, NULL, cancel_at_10k, &result,
pool, pool),
SVN_ERR_CANCELLED);
SVN_TEST_ASSERT(result == 10000);
return SVN_NO_ERROR;
}
/* An array of all test functions */
static int max_threads = 1;
static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_null_task,
"null-task"),
SVN_TEST_PASS2(test_noop_task,
"no-op task"),
SVN_TEST_PASS2(test_counting,
"concurrent counting"),
SVN_TEST_PASS2(test_cancellation,
"cancelling tasks"),
SVN_TEST_NULL
};
SVN_TEST_MAIN