| /* string-table-test.c --- tests for string tables |
| * |
| * ==================================================================== |
| * 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 "../svn_test.h" |
| #include "../../libsvn_fs_x/string_table.h" |
| #include "svn_pools.h" |
| #include "svn_sorts.h" |
| |
| /* Some tests use this list of strings as is. They are all "short strings" |
| * in the terminology of string tables. We use them also as an input to |
| * generate strings of arbitrary length. |
| */ |
| enum { STRING_COUNT = 12 }; |
| static const char *basic_strings[STRING_COUNT] = |
| { |
| "some string", |
| "this is another string", |
| "this is a duplicate", |
| "some longer string", |
| "this is a very long string", |
| "and here is another", |
| "this is a duplicate", |
| "/some/path/to/a/dir", |
| "/some/path/to/a/file", |
| "/some/other/dir", |
| "/some/other/file", |
| "" |
| }; |
| |
| /* Generate a string of exactly LEN chars (plus terminating NUL). KEY is |
| * an arbitrary integer that will be transformed into a character sequence |
| * using entries of BASIC_STRINGS. The result will be allocated in POOL. |
| */ |
| static svn_stringbuf_t * |
| generate_string(apr_uint64_t key, apr_size_t len, apr_pool_t *pool) |
| { |
| svn_stringbuf_t *result = svn_stringbuf_create_ensure(len, pool); |
| apr_uint64_t temp = key; |
| apr_uint64_t run = 0; |
| |
| while (len) |
| { |
| apr_size_t idx; |
| apr_size_t add_len; |
| |
| if (temp == 0) |
| { |
| temp = key; |
| run++; |
| } |
| |
| idx = (temp + run) % STRING_COUNT; |
| temp /= STRING_COUNT; |
| |
| add_len = strlen(basic_strings[idx]); |
| add_len = MIN(len, add_len); |
| |
| svn_stringbuf_appendbytes(result, basic_strings[idx], add_len); |
| len -= add_len; |
| } |
| |
| return result; |
| } |
| |
| static svn_error_t * |
| store_and_load_table(string_table_t **table, apr_pool_t *pool) |
| { |
| svn_stringbuf_t *stream_buffer = svn_stringbuf_create_empty(pool); |
| svn_stream_t *stream; |
| |
| stream = svn_stream_from_stringbuf(stream_buffer, pool); |
| SVN_ERR(svn_fs_x__write_string_table(stream, *table, pool)); |
| SVN_ERR(svn_stream_close(stream)); |
| |
| *table = NULL; |
| |
| stream = svn_stream_from_stringbuf(stream_buffer, pool); |
| SVN_ERR(svn_fs_x__read_string_table(table, stream, pool, pool)); |
| SVN_ERR(svn_stream_close(stream)); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| create_empty_table_body(svn_boolean_t do_load_store, |
| apr_pool_t *pool) |
| { |
| string_table_builder_t *builder |
| = svn_fs_x__string_table_builder_create(pool); |
| string_table_t *table |
| = svn_fs_x__string_table_create(builder, pool); |
| |
| SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, 0, NULL, pool), ""); |
| |
| if (do_load_store) |
| SVN_ERR(store_and_load_table(&table, pool)); |
| |
| SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, 0, NULL, pool), ""); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| short_string_table_body(svn_boolean_t do_load_store, |
| apr_pool_t *pool) |
| { |
| apr_size_t indexes[STRING_COUNT] = { 0 }; |
| |
| string_table_builder_t *builder; |
| string_table_t *table; |
| int i; |
| |
| builder = svn_fs_x__string_table_builder_create(pool); |
| for (i = 0; i < STRING_COUNT; ++i) |
| indexes[i] = svn_fs_x__string_table_builder_add(builder, basic_strings[i], 0); |
| |
| table = svn_fs_x__string_table_create(builder, pool); |
| if (do_load_store) |
| SVN_ERR(store_and_load_table(&table, pool)); |
| |
| SVN_TEST_ASSERT(indexes[2] == indexes[6]); |
| for (i = 0; i < STRING_COUNT; ++i) |
| { |
| apr_size_t len; |
| const char *string |
| = svn_fs_x__string_table_get(table, indexes[i], &len, pool); |
| |
| SVN_TEST_STRING_ASSERT(string, basic_strings[i]); |
| SVN_TEST_ASSERT(len == strlen(string)); |
| SVN_TEST_ASSERT(len == strlen(basic_strings[i])); |
| } |
| |
| SVN_TEST_STRING_ASSERT(svn_fs_x__string_table_get(table, STRING_COUNT, |
| NULL, pool), ""); |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| large_string_table_body(svn_boolean_t do_load_store, |
| apr_pool_t *pool) |
| { |
| enum { COUNT = 10 }; |
| |
| svn_stringbuf_t *strings[COUNT] = { 0 }; |
| apr_size_t indexes[COUNT] = { 0 }; |
| |
| string_table_builder_t *builder; |
| string_table_t *table; |
| int i; |
| |
| builder = svn_fs_x__string_table_builder_create(pool); |
| for (i = 0; i < COUNT; ++i) |
| { |
| strings[i] = generate_string(APR_UINT64_C(0x1234567876543210) * (i + 1), |
| 73000 + 1000 * i, pool); |
| indexes[i] = svn_fs_x__string_table_builder_add(builder, |
| strings[i]->data, |
| strings[i]->len); |
| } |
| |
| table = svn_fs_x__string_table_create(builder, pool); |
| if (do_load_store) |
| SVN_ERR(store_and_load_table(&table, pool)); |
| |
| for (i = 0; i < COUNT; ++i) |
| { |
| apr_size_t len; |
| const char *string |
| = svn_fs_x__string_table_get(table, indexes[i], &len, pool); |
| |
| SVN_TEST_STRING_ASSERT(string, strings[i]->data); |
| SVN_TEST_ASSERT(len == strlen(string)); |
| SVN_TEST_ASSERT(len == strings[i]->len); |
| } |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| many_strings_table_body(svn_boolean_t do_load_store, |
| apr_pool_t *pool) |
| { |
| /* cause multiple sub-tables (6 to be exact) to be created */ |
| enum { COUNT = 100 }; |
| |
| svn_stringbuf_t *strings[COUNT] = { 0 }; |
| apr_size_t indexes[COUNT] = { 0 }; |
| |
| string_table_builder_t *builder; |
| string_table_t *table; |
| int i; |
| |
| builder = svn_fs_x__string_table_builder_create(pool); |
| for (i = 0; i < COUNT; ++i) |
| { |
| strings[i] = generate_string(APR_UINT64_C(0x1234567876543210) * (i + 1), |
| (i * i) % 23000, pool); |
| indexes[i] = svn_fs_x__string_table_builder_add(builder, |
| strings[i]->data, |
| strings[i]->len); |
| } |
| |
| table = svn_fs_x__string_table_create(builder, pool); |
| if (do_load_store) |
| SVN_ERR(store_and_load_table(&table, pool)); |
| |
| for (i = 0; i < COUNT; ++i) |
| { |
| apr_size_t len; |
| const char *string |
| = svn_fs_x__string_table_get(table, indexes[i], &len, pool); |
| |
| SVN_TEST_STRING_ASSERT(string, strings[i]->data); |
| SVN_TEST_ASSERT(len == strlen(string)); |
| SVN_TEST_ASSERT(len == strings[i]->len); |
| } |
| |
| return SVN_NO_ERROR; |
| } |
| |
| static svn_error_t * |
| create_empty_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(create_empty_table_body(FALSE, pool)); |
| } |
| |
| static svn_error_t * |
| short_string_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(short_string_table_body(FALSE, pool)); |
| } |
| |
| static svn_error_t * |
| large_string_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(large_string_table_body(FALSE, pool)); |
| } |
| |
| static svn_error_t * |
| many_strings_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(many_strings_table_body(FALSE, pool)); |
| } |
| |
| static svn_error_t * |
| store_load_short_string_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(short_string_table_body(TRUE, pool)); |
| } |
| |
| static svn_error_t * |
| store_load_large_string_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(large_string_table_body(TRUE, pool)); |
| } |
| |
| static svn_error_t * |
| store_load_empty_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(create_empty_table_body(TRUE, pool)); |
| } |
| |
| static svn_error_t * |
| store_load_many_strings_table(apr_pool_t *pool) |
| { |
| return svn_error_trace(many_strings_table_body(TRUE, pool)); |
| } |
| |
| |
| /* ------------------------------------------------------------------------ */ |
| |
| /* The test table. */ |
| |
| static int max_threads = 4; |
| |
| static struct svn_test_descriptor_t test_funcs[] = |
| { |
| SVN_TEST_NULL, |
| SVN_TEST_PASS2(create_empty_table, |
| "create an empty string table"), |
| SVN_TEST_PASS2(short_string_table, |
| "string table with short strings only"), |
| SVN_TEST_PASS2(large_string_table, |
| "string table with large strings only"), |
| SVN_TEST_PASS2(many_strings_table, |
| "string table with many strings"), |
| SVN_TEST_PASS2(store_load_empty_table, |
| "store and load an empty string table"), |
| SVN_TEST_PASS2(store_load_short_string_table, |
| "store and load table with short strings only"), |
| SVN_TEST_PASS2(store_load_large_string_table, |
| "store and load table with large strings only"), |
| SVN_TEST_PASS2(store_load_many_strings_table, |
| "store and load string table with many strings"), |
| SVN_TEST_NULL |
| }; |
| |
| SVN_TEST_MAIN |