summaryrefslogtreecommitdiff
path: root/subversion/tests/libsvn_subr
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/libsvn_subr')
-rw-r--r--subversion/tests/libsvn_subr/auth-test.c25
-rw-r--r--subversion/tests/libsvn_subr/bit-array-test.c140
-rw-r--r--subversion/tests/libsvn_subr/cache-test.c122
-rw-r--r--subversion/tests/libsvn_subr/checksum-test.c248
-rw-r--r--subversion/tests/libsvn_subr/compat-test.c7
-rw-r--r--subversion/tests/libsvn_subr/config-test.c193
-rw-r--r--subversion/tests/libsvn_subr/crypto-test.c6
-rw-r--r--subversion/tests/libsvn_subr/dirent_uri-test.c146
-rw-r--r--subversion/tests/libsvn_subr/error-code-test.c6
-rw-r--r--subversion/tests/libsvn_subr/error-test.c12
-rw-r--r--subversion/tests/libsvn_subr/hashdump-test.c11
-rw-r--r--subversion/tests/libsvn_subr/io-test.c370
-rw-r--r--subversion/tests/libsvn_subr/mergeinfo-test.c31
-rw-r--r--subversion/tests/libsvn_subr/named_atomic-test-common.h245
-rw-r--r--subversion/tests/libsvn_subr/named_atomic-test-proc.c86
-rw-r--r--subversion/tests/libsvn_subr/named_atomic-test.c761
-rw-r--r--subversion/tests/libsvn_subr/opt-test.c6
-rw-r--r--subversion/tests/libsvn_subr/packed-data-test.c577
-rw-r--r--subversion/tests/libsvn_subr/path-test.c137
-rw-r--r--subversion/tests/libsvn_subr/prefix-string-test.c154
-rw-r--r--subversion/tests/libsvn_subr/priority-queue-test.c240
-rw-r--r--subversion/tests/libsvn_subr/revision-test.c14
-rw-r--r--subversion/tests/libsvn_subr/root-pools-test.c137
-rw-r--r--subversion/tests/libsvn_subr/skel-test.c8
-rw-r--r--subversion/tests/libsvn_subr/spillbuf-test.c243
-rw-r--r--subversion/tests/libsvn_subr/sqlite-test.c186
-rw-r--r--subversion/tests/libsvn_subr/stream-test.c124
-rw-r--r--subversion/tests/libsvn_subr/string-test.c259
-rw-r--r--subversion/tests/libsvn_subr/subst_translate-test.c11
-rw-r--r--subversion/tests/libsvn_subr/time-test.c12
-rw-r--r--subversion/tests/libsvn_subr/translate-test.c189
-rw-r--r--subversion/tests/libsvn_subr/utf-test.c549
-rw-r--r--subversion/tests/libsvn_subr/x509-test.c848
33 files changed, 4400 insertions, 1703 deletions
diff --git a/subversion/tests/libsvn_subr/auth-test.c b/subversion/tests/libsvn_subr/auth-test.c
index 9d7d866..bbe7933 100644
--- a/subversion/tests/libsvn_subr/auth-test.c
+++ b/subversion/tests/libsvn_subr/auth-test.c
@@ -63,13 +63,14 @@ test_platform_specific_auth_providers(apr_pool_t *pool)
number_of_providers += 2;
#endif
#if defined(WIN32) && !defined(__MINGW32__)
- number_of_providers += 2;
+ number_of_providers += 4;
#endif
if (providers->nelts != number_of_providers)
return svn_error_createf
(SVN_ERR_TEST_FAILED, NULL,
"svn_auth_get_platform_specific_client_providers should return " \
- "an array of %d providers", number_of_providers);
+ "an array of %d providers, but returned %d providers",
+ number_of_providers, providers->nelts);
/* Test Keychain auth providers */
#ifdef SVN_HAVE_KEYCHAIN_SERVICES
@@ -219,8 +220,8 @@ cleanup_callback(svn_boolean_t *delete_cred,
{
svn_auth_baton_t *b = walk_baton;
- SVN_TEST_ASSERT(strcmp(cred_kind, SVN_AUTH_CRED_SIMPLE) == 0);
- SVN_TEST_ASSERT(strcmp(realmstring, "<http://my.host> My realm") == 0);
+ SVN_TEST_STRING_ASSERT(cred_kind, SVN_AUTH_CRED_SIMPLE);
+ SVN_TEST_STRING_ASSERT(realmstring, "<http://my.host> My realm");
SVN_ERR(svn_auth_forget_credentials(b, cred_kind, realmstring, scratch_pool));
@@ -271,7 +272,7 @@ test_auth_clear(apr_pool_t *pool)
pool));
creds = credentials;
- SVN_TEST_ASSERT(strcmp(creds->username, "jrandom") == 0);
+ SVN_TEST_STRING_ASSERT(creds->username, "jrandom");
SVN_TEST_ASSERT(creds->may_save);
/* And tell that they are ok and can be saved */
@@ -291,7 +292,7 @@ test_auth_clear(apr_pool_t *pool)
SVN_TEST_ASSERT(credentials);
creds = credentials;
- SVN_TEST_ASSERT(strcmp(creds->username, "jrandom") == 0);
+ SVN_TEST_STRING_ASSERT(creds->username, "jrandom");
SVN_TEST_ASSERT(creds->may_save);
/* Use our walker function to delete credentials (and forget them
@@ -314,18 +315,16 @@ test_auth_clear(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_platform_specific_auth_providers,
"test retrieving platform-specific auth providers"),
-#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
SVN_TEST_PASS2(test_auth_clear,
"test svn_auth_clear()"),
-#else
- SVN_TEST_WIMP(test_auth_clear,
- "test svn_auth_clear()",
- "Needs testing with SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE"),
-#endif
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/bit-array-test.c b/subversion/tests/libsvn_subr/bit-array-test.c
new file mode 100644
index 0000000..e6fe528
--- /dev/null
+++ b/subversion/tests/libsvn_subr/bit-array-test.c
@@ -0,0 +1,140 @@
+/*
+ * bit-array-test.c: a collection of svn_bit_array__* 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_error.h"
+#include "svn_string.h" /* This includes <apr_*.h> */
+#include "private/svn_subr_private.h"
+
+static svn_error_t *
+test_zero_defaults(apr_pool_t *pool)
+{
+ svn_bit_array__t *array = svn_bit_array__create(0, pool);
+
+ /* Test (default) allocation boundaries */
+ SVN_TEST_ASSERT(svn_bit_array__get(array, 0x7ffff) == 0);
+ SVN_TEST_ASSERT(svn_bit_array__get(array, 0x80000) == 0);
+
+ /* Test address boundaries */
+ SVN_TEST_ASSERT(svn_bit_array__get(array, 0) == 0);
+ SVN_TEST_ASSERT(svn_bit_array__get(array, APR_SIZE_MAX) == 0);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_get_set(apr_pool_t *pool)
+{
+ svn_bit_array__t *array = svn_bit_array__create(0, pool);
+ apr_size_t i, min = 0x7ff00, max = 0x7ff00 + 1025;
+
+ /* All values default to 0. */
+ for (i = min; i < max; ++i)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, i) == 0);
+
+ /* Create a pattern, setting every other bit. Array will also auto-grow. */
+ for (i = min; i < max; ++i)
+ if (i % 2)
+ svn_bit_array__set(array, i, 1);
+
+ /* Verify pattern */
+ for (i = min; i < max; ++i)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
+
+ /* Zero the zeros in the pattern -> should be no change. */
+ for (i = min; i < max; ++i)
+ if (i % 2 == 0)
+ svn_bit_array__set(array, i, 0);
+
+ /* Verify pattern */
+ for (i = min; i < max; ++i)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
+
+ /* Write an inverted pattern while verifying the old one. */
+ for (i = min; i < max; ++i)
+ {
+ SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
+ svn_bit_array__set(array, i, 1 - (i % 2));
+ }
+
+ /* Verify pattern */
+ for (i = min; i < max; ++i)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, i) == 1 - (i % 2));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_sparse(apr_pool_t *pool)
+{
+ svn_bit_array__t *array = svn_bit_array__create(0, pool);
+ apr_size_t i, k, min = 0x7ff00, max = 0x7ff00 + 1025, SCALE = 0x10000000;
+
+ /* All values default to 0. */
+ for (i = 0; i < 15; ++i)
+ for (k = i * SCALE + min; k < i * SCALE + max; ++k)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, k) == 0);
+
+ /* Create a pattern, setting every other bit. Array will also auto-grow. */
+ for (i = 0; i < 15; ++i)
+ for (k = i * SCALE + min; k < i * SCALE + max; ++k)
+ if (k % 2)
+ svn_bit_array__set(array, k, 1);
+
+ /* Verify pattern */
+ for (i = 0; i < 15; ++i)
+ for (k = i * SCALE + min; k < i * SCALE + max; ++k)
+ SVN_TEST_ASSERT(svn_bit_array__get(array, k) == k % 2);
+
+ 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_zero_defaults,
+ "check entries to default to zero"),
+ SVN_TEST_PASS2(test_get_set,
+ "get / set entries"),
+ SVN_TEST_PASS2(test_sparse,
+ "get / set sparse entries"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/cache-test.c b/subversion/tests/libsvn_subr/cache-test.c
index 9e7a7b3..1616441 100644
--- a/subversion/tests/libsvn_subr/cache-test.c
+++ b/subversion/tests/libsvn_subr/cache-test.c
@@ -157,7 +157,8 @@ test_memcache_basic(const svn_test_opts_t *opts,
{
SVN_ERR(svn_config_read3(&config, opts->config_file,
TRUE, FALSE, FALSE, pool));
- SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config, pool));
+ SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config,
+ pool, pool));
}
if (! memcache)
@@ -193,8 +194,9 @@ test_membuffer_cache_basic(apr_pool_t *pool)
deserialize_revnum,
APR_HASH_KEY_STRING,
"cache:",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
FALSE,
- pool));
+ pool, pool));
return basic_cache_test(cache, FALSE, pool);
}
@@ -220,6 +222,16 @@ raise_error_partial_getter_func(void **out,
return svn_error_create(APR_EGENERAL, NULL, NULL);
}
+/* Implements svn_cache__partial_setter_func_t */
+static svn_error_t *
+raise_error_partial_setter_func(void **data,
+ apr_size_t *data_len,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ return svn_error_create(APR_EGENERAL, NULL, NULL);
+}
+
static svn_error_t *
test_membuffer_serializer_error_handling(apr_pool_t *pool)
{
@@ -239,8 +251,9 @@ test_membuffer_serializer_error_handling(apr_pool_t *pool)
raise_error_deserialize_func,
APR_HASH_KEY_STRING,
"cache:",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
FALSE,
- pool));
+ pool, pool));
SVN_ERR(svn_cache__set(cache, "twenty", &twenty, pool));
@@ -258,6 +271,30 @@ test_membuffer_serializer_error_handling(apr_pool_t *pool)
NULL, pool),
APR_EGENERAL);
+ /* Create a new cache. */
+ SVN_ERR(svn_cache__membuffer_cache_create(&membuffer, 10*1024, 1, 0,
+ TRUE, TRUE, pool));
+ SVN_ERR(svn_cache__create_membuffer_cache(&cache,
+ membuffer,
+ serialize_revnum,
+ deserialize_revnum,
+ APR_HASH_KEY_STRING,
+ "cache:",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ FALSE,
+ pool, pool));
+
+ /* Store one entry in cache. */
+ SVN_ERR(svn_cache__set(cache, "twenty", &twenty, pool));
+
+ /* Test setting data in cache using partial setter that
+ always raises an error. */
+ SVN_TEST_ASSERT_ERROR(
+ svn_cache__set_partial(cache, "twenty",
+ raise_error_partial_setter_func,
+ NULL, pool),
+ APR_EGENERAL);
+
return SVN_NO_ERROR;
}
@@ -286,7 +323,8 @@ test_memcache_long_key(const svn_test_opts_t *opts,
{
SVN_ERR(svn_config_read3(&config, opts->config_file,
TRUE, FALSE, FALSE, pool));
- SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config, pool));
+ SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config,
+ pool, pool));
}
if (! memcache)
@@ -316,10 +354,80 @@ test_memcache_long_key(const svn_test_opts_t *opts,
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_membuffer_cache_clearing(apr_pool_t *pool)
+{
+ svn_cache__t *cache;
+ svn_membuffer_t *membuffer;
+ svn_boolean_t found;
+ svn_revnum_t *value;
+ svn_revnum_t valueA = 12345;
+ svn_revnum_t valueB = 67890;
+
+ /* Create a simple cache for strings, keyed by strings. */
+ SVN_ERR(svn_cache__membuffer_cache_create(&membuffer, 10*1024, 1, 0,
+ TRUE, TRUE, pool));
+ SVN_ERR(svn_cache__create_membuffer_cache(&cache,
+ membuffer,
+ serialize_revnum,
+ deserialize_revnum,
+ APR_HASH_KEY_STRING,
+ "cache:",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ FALSE,
+ pool, pool));
+
+ /* Initially, the cache is empty. */
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key A", pool));
+ SVN_TEST_ASSERT(!found);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key B", pool));
+ SVN_TEST_ASSERT(!found);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key C", pool));
+ SVN_TEST_ASSERT(!found);
+
+ /* Add entries. */
+ SVN_ERR(svn_cache__set(cache, "key A", &valueA, pool));
+ SVN_ERR(svn_cache__set(cache, "key B", &valueB, pool));
+
+ /* Added entries should be cached (too small to get evicted already). */
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key A", pool));
+ SVN_TEST_ASSERT(found);
+ SVN_TEST_ASSERT(*value == valueA);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key B", pool));
+ SVN_TEST_ASSERT(found);
+ SVN_TEST_ASSERT(*value == valueB);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key C", pool));
+ SVN_TEST_ASSERT(!found);
+
+ /* Clear the cache. */
+ SVN_ERR(svn_cache__membuffer_clear(membuffer));
+
+ /* The cache is empty again. */
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key A", pool));
+ SVN_TEST_ASSERT(!found);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key B", pool));
+ SVN_TEST_ASSERT(!found);
+ SVN_ERR(svn_cache__get((void **) &value, &found, cache, "key C", pool));
+ SVN_TEST_ASSERT(!found);
+
+ /* But still functional: */
+ SVN_ERR(svn_cache__set(cache, "key B", &valueB, pool));
+ SVN_ERR(svn_cache__has_key(&found, cache, "key A", pool));
+ SVN_TEST_ASSERT(!found);
+ SVN_ERR(svn_cache__has_key(&found, cache, "key B", pool));
+ SVN_TEST_ASSERT(found);
+ SVN_ERR(svn_cache__has_key(&found, cache, "key C", pool));
+ SVN_TEST_ASSERT(!found);
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_inprocess_cache_basic,
@@ -332,5 +440,9 @@ struct svn_test_descriptor_t test_funcs[] =
"basic membuffer svn_cache test"),
SVN_TEST_PASS2(test_membuffer_serializer_error_handling,
"test for error handling in membuffer svn_cache"),
+ SVN_TEST_PASS2(test_membuffer_cache_clearing,
+ "test clearing a membuffer svn_cache"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/checksum-test.c b/subversion/tests/libsvn_subr/checksum-test.c
index c5e2409..4c6d993 100644
--- a/subversion/tests/libsvn_subr/checksum-test.c
+++ b/subversion/tests/libsvn_subr/checksum-test.c
@@ -27,38 +27,47 @@
#include "svn_error.h"
#include "svn_io.h"
-#include "private/svn_pseudo_md5.h"
#include "../svn_test.h"
+/* Verify that DIGEST of checksum type KIND can be parsed and
+ * converted back to a string matching DIGEST. NAME will be used
+ * to identify the type of checksum in error messages.
+ */
static svn_error_t *
-test_checksum_parse(apr_pool_t *pool)
+checksum_parse_kind(const char *digest,
+ svn_checksum_kind_t kind,
+ const char *name,
+ apr_pool_t *pool)
{
- const char *md5_digest = "8518b76f7a45fe4de2d0955085b41f98";
- const char *sha1_digest = "74d82379bcc6771454377db03b912c2b62704139";
const char *checksum_display;
svn_checksum_t *checksum;
- SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, md5_digest, pool));
+ SVN_ERR(svn_checksum_parse_hex(&checksum, kind, digest, pool));
checksum_display = svn_checksum_to_cstring_display(checksum, pool);
- if (strcmp(checksum_display, md5_digest) != 0)
+ if (strcmp(checksum_display, digest) != 0)
return svn_error_createf
(SVN_ERR_CHECKSUM_MISMATCH, NULL,
- "verify-checksum: md5 checksum mismatch:\n"
+ "verify-checksum: %s checksum mismatch:\n"
" expected: %s\n"
- " actual: %s\n", md5_digest, checksum_display);
+ " actual: %s\n", name, digest, checksum_display);
- SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, sha1_digest,
- pool));
- checksum_display = svn_checksum_to_cstring_display(checksum, pool);
+ return SVN_NO_ERROR;
+}
- if (strcmp(checksum_display, sha1_digest) != 0)
- return svn_error_createf
- (SVN_ERR_CHECKSUM_MISMATCH, NULL,
- "verify-checksum: sha1 checksum mismatch:\n"
- " expected: %s\n"
- " actual: %s\n", sha1_digest, checksum_display);
+static svn_error_t *
+test_checksum_parse(apr_pool_t *pool)
+{
+ SVN_ERR(checksum_parse_kind("8518b76f7a45fe4de2d0955085b41f98",
+ svn_checksum_md5, "md5", pool));
+ SVN_ERR(checksum_parse_kind("74d82379bcc6771454377db03b912c2b62704139",
+ svn_checksum_sha1, "sha1", pool));
+ SVN_ERR(checksum_parse_kind("deadbeef",
+ svn_checksum_fnv1a_32, "fnv-1a", pool));
+ SVN_ERR(checksum_parse_kind("cafeaffe",
+ svn_checksum_fnv1a_32x4,
+ "modified fnv-1a", pool));
return SVN_NO_ERROR;
}
@@ -66,94 +75,97 @@ test_checksum_parse(apr_pool_t *pool)
static svn_error_t *
test_checksum_empty(apr_pool_t *pool)
{
- svn_checksum_t *checksum;
- char data = '\0';
-
- checksum = svn_checksum_empty_checksum(svn_checksum_md5, pool);
- SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
-
- checksum = svn_checksum_empty_checksum(svn_checksum_sha1, pool);
- SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+ svn_checksum_kind_t kind;
+ for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+ {
+ svn_checksum_t *checksum;
+ char data = '\0';
- SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, &data, 0, pool));
- SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+ checksum = svn_checksum_empty_checksum(kind, pool);
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
- SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1, &data, 0, pool));
- SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+ SVN_ERR(svn_checksum(&checksum, kind, &data, 0, pool));
+ SVN_TEST_ASSERT(svn_checksum_is_empty_checksum(checksum));
+ }
return SVN_NO_ERROR;
}
+/* Verify that "zero" checksums work properly for the given checksum KIND.
+ */
static svn_error_t *
-test_pseudo_md5(apr_pool_t *pool)
+zero_match_kind(svn_checksum_kind_t kind, apr_pool_t *pool)
{
- apr_uint32_t input[16] = { 0 };
- apr_uint32_t digest_15[4] = { 0 };
- apr_uint32_t digest_31[4] = { 0 };
- apr_uint32_t digest_63[4] = { 0 };
- svn_checksum_t *checksum;
+ svn_checksum_t *zero;
+ svn_checksum_t *A;
+ svn_checksum_t *B;
- /* input is all 0s but the hash shall be different
- (due to different input sizes)*/
- svn__pseudo_md5_15(digest_15, input);
- svn__pseudo_md5_31(digest_31, input);
- svn__pseudo_md5_63(digest_63, input);
+ zero = svn_checksum_create(kind, pool);
+ SVN_ERR(svn_checksum_clear(zero));
+ SVN_ERR(svn_checksum(&A, kind, "A", 1, pool));
+ SVN_ERR(svn_checksum(&B, kind, "B", 1, pool));
- SVN_TEST_ASSERT(memcmp(digest_15, digest_31, sizeof(digest_15)));
- SVN_TEST_ASSERT(memcmp(digest_15, digest_63, sizeof(digest_15)));
- SVN_TEST_ASSERT(memcmp(digest_31, digest_63, sizeof(digest_15)));
+ /* Different non-zero don't match. */
+ SVN_TEST_ASSERT(!svn_checksum_match(A, B));
- /* the checksums shall also be different from "proper" MD5 */
- SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 15, pool));
- SVN_TEST_ASSERT(memcmp(digest_15, checksum->digest, sizeof(digest_15)));
+ /* Zero matches anything of the same kind. */
+ SVN_TEST_ASSERT(svn_checksum_match(A, zero));
+ SVN_TEST_ASSERT(svn_checksum_match(zero, B));
- SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 31, pool));
- SVN_TEST_ASSERT(memcmp(digest_31, checksum->digest, sizeof(digest_15)));
+ return SVN_NO_ERROR;
+}
- SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 63, pool));
- SVN_TEST_ASSERT(memcmp(digest_63, checksum->digest, sizeof(digest_15)));
+static svn_error_t *
+zero_match(apr_pool_t *pool)
+{
+ svn_checksum_kind_t kind;
+ for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+ SVN_ERR(zero_match_kind(kind, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
-zero_match(apr_pool_t *pool)
+zero_cross_match(apr_pool_t *pool)
{
- svn_checksum_t *zero_md5;
- svn_checksum_t *zero_sha1;
- svn_checksum_t *A_md5;
- svn_checksum_t *B_md5;
- svn_checksum_t *A_sha1;
- svn_checksum_t *B_sha1;
+ svn_checksum_kind_t i_kind;
+ svn_checksum_kind_t k_kind;
+ for (i_kind = svn_checksum_md5;
+ i_kind <= svn_checksum_fnv1a_32x4;
+ ++i_kind)
+ {
+ svn_checksum_t *i_zero;
+ svn_checksum_t *i_A;
- zero_md5 = svn_checksum_create(svn_checksum_md5, pool);
- SVN_ERR(svn_checksum_clear(zero_md5));
- SVN_ERR(svn_checksum(&A_md5, svn_checksum_md5, "A", 1, pool));
- SVN_ERR(svn_checksum(&B_md5, svn_checksum_md5, "B", 1, pool));
+ i_zero = svn_checksum_create(i_kind, pool);
+ SVN_ERR(svn_checksum_clear(i_zero));
+ SVN_ERR(svn_checksum(&i_A, i_kind, "A", 1, pool));
- zero_sha1 = svn_checksum_create(svn_checksum_sha1, pool);
- SVN_ERR(svn_checksum_clear(zero_sha1));
- SVN_ERR(svn_checksum(&A_sha1, svn_checksum_sha1, "A", 1, pool));
- SVN_ERR(svn_checksum(&B_sha1, svn_checksum_sha1, "B", 1, pool));
+ for (k_kind = svn_checksum_md5;
+ k_kind <= svn_checksum_fnv1a_32x4;
+ ++k_kind)
+ {
+ svn_checksum_t *k_zero;
+ svn_checksum_t *k_A;
+ if (i_kind == k_kind)
+ continue;
- /* Different non-zero don't match. */
- SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_md5));
- SVN_TEST_ASSERT(!svn_checksum_match(A_sha1, B_sha1));
- SVN_TEST_ASSERT(!svn_checksum_match(A_md5, A_sha1));
- SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_sha1));
+ k_zero = svn_checksum_create(k_kind, pool);
+ SVN_ERR(svn_checksum_clear(k_zero));
+ SVN_ERR(svn_checksum(&k_A, k_kind, "A", 1, pool));
- /* Zero matches anything of the same kind. */
- SVN_TEST_ASSERT(svn_checksum_match(A_md5, zero_md5));
- SVN_TEST_ASSERT(svn_checksum_match(zero_md5, B_md5));
- SVN_TEST_ASSERT(svn_checksum_match(A_sha1, zero_sha1));
- SVN_TEST_ASSERT(svn_checksum_match(zero_sha1, B_sha1));
+ /* Different non-zero don't match. */
+ SVN_TEST_ASSERT(!svn_checksum_match(i_A, k_A));
+
+ /* Zero doesn't match anything of a different kind... */
+ SVN_TEST_ASSERT(!svn_checksum_match(i_zero, k_A));
+ SVN_TEST_ASSERT(!svn_checksum_match(i_A, k_zero));
- /* Zero doesn't match anything of a different kind... */
- SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, A_sha1));
- SVN_TEST_ASSERT(!svn_checksum_match(zero_sha1, A_md5));
- /* ...even another zero. */
- SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, zero_sha1));
+ /* ...even another zero. */
+ SVN_TEST_ASSERT(!svn_checksum_match(i_zero, k_zero));
+ }
+ }
return SVN_NO_ERROR;
}
@@ -163,12 +175,14 @@ zlib_expansion_test(const svn_test_opts_t *opts,
apr_pool_t *pool)
{
const char *data_path;
+ const char *srcdir;
svn_stringbuf_t *deflated;
Byte dst_buffer[256 * 1024];
Byte *src_buffer;
- apr_size_t sz;
+ uInt sz;
- data_path = svn_dirent_join(opts->srcdir, "zlib.deflated", pool);
+ SVN_ERR(svn_test_get_srcdir(&srcdir, opts, pool));
+ data_path = svn_dirent_join(srcdir, "zlib.deflated", pool);
SVN_ERR(svn_stringbuf_from_file2(&deflated, data_path, pool));
src_buffer = (Byte*)deflated->data;
@@ -177,6 +191,7 @@ zlib_expansion_test(const svn_test_opts_t *opts,
for (sz = 1; sz < 256; sz++)
{
z_stream stream;
+ uLong crc = crc32(0, Z_NULL, 0);
memset(&stream, 0, sizeof(stream));
inflateInit2(&stream, -15 /* DEFLATE_WINDOW_SIZE */);
@@ -193,12 +208,15 @@ zlib_expansion_test(const svn_test_opts_t *opts,
{
return svn_error_createf(
SVN_ERR_TEST_FAILED, NULL,
- "Failure decompressing with blocksize %d", (int)sz);
+ "Failure decompressing with blocksize %u", sz);
}
+ crc = crc32(crc, dst_buffer, sizeof(dst_buffer) - stream.avail_out);
+ stream.avail_out = sizeof(dst_buffer);
+ stream.next_out = dst_buffer;
stream.avail_in += sz;
} while (stream.next_in + stream.avail_in < src_buffer + deflated->len);
- stream.avail_in = (src_buffer + deflated->len) - stream.next_in;
+ stream.avail_in = (uInt) (deflated->len - stream.total_in);
{
int zr = inflate(&stream, Z_NO_FLUSH);
@@ -207,8 +225,9 @@ zlib_expansion_test(const svn_test_opts_t *opts,
{
return svn_error_createf(
SVN_ERR_TEST_FAILED, NULL,
- "Final flush failed with blocksize %d", (int)sz);
+ "Final flush failed with blocksize %u", sz);
}
+ crc = crc32(crc, dst_buffer, sizeof(dst_buffer) - stream.avail_out);
zr = inflateEnd(&stream);
@@ -216,42 +235,65 @@ zlib_expansion_test(const svn_test_opts_t *opts,
{
return svn_error_createf(
SVN_ERR_TEST_FAILED, NULL,
- "End of stream handling failed with blocksize %d",
- (int)sz);
+ "End of stream handling failed with blocksize %u",
+ sz);
}
}
- {
- apr_uint32_t crc = crc32(0, dst_buffer, stream.total_out);
-
- if (stream.total_out != 242014 || crc != 0x8f03d934)
- {
- return svn_error_createf(
- SVN_ERR_TEST_FAILED, NULL,
- "Decompressed data doesn't match expected size or crc with "
- "blocksize %d: Found crc32=0x%08x, size=%d.\n"
- "Verify your ZLib installation, as this should never happen",
- (int)sz, (unsigned)crc, (int)stream.total_out);
- }
- }
+ if (stream.total_out != 242014 || crc != 0x8f03d934)
+ {
+ return svn_error_createf(
+ SVN_ERR_TEST_FAILED, NULL,
+ "Decompressed data doesn't match expected size or crc with "
+ "blocksize %u: Found crc32=0x%08lx, size=%lu.\n"
+ "Verify your ZLib installation, as this should never happen",
+ sz, crc, stream.total_out);
+ }
}
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_serialization(apr_pool_t *pool)
+{
+ svn_checksum_kind_t kind;
+ for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+ {
+ const svn_checksum_t *parsed_checksum;
+ svn_checksum_t *checksum = svn_checksum_empty_checksum(kind, pool);
+ const char *serialized = svn_checksum_serialize(checksum, pool, pool);
+
+ SVN_ERR(svn_checksum_deserialize(&parsed_checksum, serialized, pool,
+ pool));
+
+ SVN_TEST_ASSERT(parsed_checksum->kind == kind);
+ SVN_TEST_ASSERT(svn_checksum_match(checksum, parsed_checksum));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_checksum_parse,
"checksum parse"),
SVN_TEST_PASS2(test_checksum_empty,
"checksum emptiness"),
- SVN_TEST_PASS2(test_pseudo_md5,
- "pseudo-md5 compatibility"),
SVN_TEST_PASS2(zero_match,
"zero checksum matching"),
SVN_TEST_OPTS_PASS(zlib_expansion_test,
"zlib expansion test (zlib regression)"),
+ SVN_TEST_PASS2(zero_cross_match,
+ "zero checksum cross-type matching"),
+ SVN_TEST_PASS2(test_serialization,
+ "checksum (de-)serialization"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/compat-test.c b/subversion/tests/libsvn_subr/compat-test.c
index 9ff8099..8414847 100644
--- a/subversion/tests/libsvn_subr/compat-test.c
+++ b/subversion/tests/libsvn_subr/compat-test.c
@@ -209,7 +209,10 @@ test_version_at_least(apr_pool_t *pool)
}
/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_version_compatibility,
@@ -220,3 +223,5 @@ struct svn_test_descriptor_t test_funcs[] =
"svn_version__at_least"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/config-test.c b/subversion/tests/libsvn_subr/config-test.c
index 8938457..919893e 100644
--- a/subversion/tests/libsvn_subr/config-test.c
+++ b/subversion/tests/libsvn_subr/config-test.c
@@ -33,48 +33,14 @@
#include <apr_getopt.h>
#include <apr_pools.h>
+#include "svn_dirent_uri.h"
#include "svn_error.h"
#include "svn_config.h"
+#include "private/svn_subr_private.h"
#include "../svn_test.h"
-/* Initialize parameters for the tests. */
-extern int test_argc;
-extern const char **test_argv;
-
-static const apr_getopt_option_t opt_def[] =
- {
- {"srcdir", 'S', 1, "the source directory for VPATH test runs"},
- {0, 0, 0, 0}
- };
-static const char *srcdir = NULL;
-
-static svn_error_t *init_params(apr_pool_t *pool)
-{
- apr_getopt_t *opt;
- int optch;
- const char *opt_arg;
- apr_status_t status;
-
- apr_getopt_init(&opt, pool, test_argc, test_argv);
- while (!(status = apr_getopt_long(opt, opt_def, &optch, &opt_arg)))
- {
- switch (optch)
- {
- case 'S':
- srcdir = opt_arg;
- break;
- }
- }
-
- if (!srcdir)
- return svn_error_create(SVN_ERR_TEST_FAILED, 0,
- "missing required parameter '--srcdir'");
-
- return SVN_NO_ERROR;
-}
-
/* A quick way to create error messages. */
static svn_error_t *
fail(apr_pool_t *pool, const char *fmt, ...)
@@ -89,6 +55,18 @@ fail(apr_pool_t *pool, const char *fmt, ...)
return svn_error_create(SVN_ERR_TEST_FAILED, SVN_NO_ERROR, msg);
}
+static svn_error_t *
+get_config_file_path(const char **cfg_file,
+ const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ const char *srcdir;
+
+ SVN_ERR(svn_test_get_srcdir(&srcdir, opts, pool));
+ *cfg_file = svn_dirent_join(srcdir, "config-test.cfg", pool);
+
+ return SVN_NO_ERROR;
+}
static const char *config_keys[] = { "foo", "a", "b", "c", "d", "e", "f", "g",
"h", "i", NULL };
@@ -99,16 +77,14 @@ static const char *config_values[] = { "bar", "Aa", "100", "bar",
"Aa 100", NULL };
static svn_error_t *
-test_text_retrieval(apr_pool_t *pool)
+test_text_retrieval(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
int i;
const char *cfg_file;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, FALSE, FALSE, pool));
/* Test values retrieved from our ConfigParser instance against
@@ -150,16 +126,14 @@ static const char *false_keys[] = {"false1", "false2", "false3", "false4",
NULL};
static svn_error_t *
-test_boolean_retrieval(apr_pool_t *pool)
+test_boolean_retrieval(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
int i;
const char *cfg_file;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, FALSE, FALSE, pool));
for (i = 0; true_keys[i] != NULL; i++)
@@ -211,15 +185,13 @@ test_boolean_retrieval(apr_pool_t *pool)
}
static svn_error_t *
-test_has_section_case_insensitive(apr_pool_t *pool)
+test_has_section_case_insensitive(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
const char *cfg_file;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, FALSE, FALSE, pool));
if (! svn_config_has_section(cfg, "section1"))
@@ -241,15 +213,13 @@ test_has_section_case_insensitive(apr_pool_t *pool)
}
static svn_error_t *
-test_has_section_case_sensitive(apr_pool_t *pool)
+test_has_section_case_sensitive(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
const char *cfg_file;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, FALSE, pool));
if (! svn_config_has_section(cfg, "section1"))
@@ -271,7 +241,8 @@ test_has_section_case_sensitive(apr_pool_t *pool)
}
static svn_error_t *
-test_has_option_case_sensitive(apr_pool_t *pool)
+test_has_option_case_sensitive(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
const char *cfg_file;
@@ -289,10 +260,7 @@ test_has_option_case_sensitive(apr_pool_t *pool)
};
static const int test_data_size = sizeof(test_data)/sizeof(*test_data);
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, TRUE, pool));
for (i = 0; i < test_data_size; ++i)
@@ -313,16 +281,14 @@ test_has_option_case_sensitive(apr_pool_t *pool)
}
static svn_error_t *
-test_stream_interface(apr_pool_t *pool)
+test_stream_interface(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_config_t *cfg;
const char *cfg_file;
svn_stream_t *stream;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_stream_open_readonly(&stream, cfg_file, pool, pool));
SVN_ERR(svn_config_parse(&cfg, stream, TRUE, TRUE, pool));
@@ -353,16 +319,42 @@ test_ignore_bom(apr_pool_t *pool)
}
static svn_error_t *
+test_read_only_mode(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_config_t *cfg;
+ svn_config_t *cfg2;
+ const char *cfg_file;
+
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
+ SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, FALSE, pool));
+
+ /* setting CFG to r/o mode shall toggle the r/o mode and expand values */
+
+ SVN_TEST_ASSERT(!svn_config__is_read_only(cfg));
+ SVN_TEST_ASSERT(!svn_config__is_expanded(cfg, "section1", "i"));
+
+ svn_config__set_read_only(cfg, pool);
+
+ SVN_TEST_ASSERT(svn_config__is_read_only(cfg));
+ SVN_TEST_ASSERT(svn_config__is_expanded(cfg, "section1", "i"));
+
+ /* copies should be r/w with values */
+
+ SVN_ERR(svn_config_dup(&cfg2, cfg, pool));
+ SVN_TEST_ASSERT(!svn_config__is_read_only(cfg2));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
test_expand(const svn_test_opts_t *opts,
apr_pool_t *pool)
{
svn_config_t *cfg;
const char *cfg_file, *val;
- if (!srcdir)
- SVN_ERR(init_params(pool));
-
- cfg_file = apr_pstrcat(pool, srcdir, "/", "config-test.cfg", (char *)NULL);
+ SVN_ERR(get_config_file_path(&cfg_file, opts, pool));
SVN_ERR(svn_config_read3(&cfg, cfg_file, TRUE, TRUE, FALSE, pool));
/* Get expanded "g" which requires expanding "c". */
@@ -371,13 +363,34 @@ test_expand(const svn_test_opts_t *opts,
/* Get expanded "c". */
svn_config_get(cfg, &val, "section1", "c", NULL);
- /* With pool debugging enabled this ensures that the expanded value
+ /* With pool debugging enabled this ensures that the expanded value
of "c" was not created in a temporary pool when expanding "g". */
SVN_TEST_STRING_ASSERT(val, "bar");
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_invalid_bom(apr_pool_t *pool)
+{
+ svn_config_t *cfg;
+ svn_error_t *err;
+ svn_string_t *cfg_string;
+ svn_stream_t *stream;
+
+ cfg_string = svn_string_create("\xEF", pool);
+ stream = svn_stream_from_string(cfg_string, pool);
+ err = svn_config_parse(&cfg, stream, TRUE, TRUE, pool);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_MALFORMED_FILE);
+
+ cfg_string = svn_string_create("\xEF\xBB", pool);
+ stream = svn_stream_from_string(cfg_string, pool);
+ err = svn_config_parse(&cfg, stream, TRUE, TRUE, pool);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_MALFORMED_FILE);
+
+ return SVN_NO_ERROR;
+}
+
/*
====================================================================
If you add a new test to this file, update this array.
@@ -386,23 +399,33 @@ test_expand(const svn_test_opts_t *opts,
*/
/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
- SVN_TEST_PASS2(test_text_retrieval,
- "test svn_config"),
- SVN_TEST_PASS2(test_boolean_retrieval,
- "test svn_config boolean conversion"),
- SVN_TEST_PASS2(test_has_section_case_insensitive,
- "test svn_config_has_section (case insensitive)"),
- SVN_TEST_PASS2(test_has_section_case_sensitive,
- "test svn_config_has_section (case sensitive)"),
- SVN_TEST_PASS2(test_has_option_case_sensitive,
- "test case-sensitive option name lookup"),
- SVN_TEST_PASS2(test_stream_interface,
- "test svn_config_parse"),
- SVN_TEST_PASS2(test_ignore_bom, "test parsing config file with BOM"),
+ SVN_TEST_OPTS_PASS(test_text_retrieval,
+ "test svn_config"),
+ SVN_TEST_OPTS_PASS(test_boolean_retrieval,
+ "test svn_config boolean conversion"),
+ SVN_TEST_OPTS_PASS(test_has_section_case_insensitive,
+ "test svn_config_has_section (case insensitive)"),
+ SVN_TEST_OPTS_PASS(test_has_section_case_sensitive,
+ "test svn_config_has_section (case sensitive)"),
+ SVN_TEST_OPTS_PASS(test_has_option_case_sensitive,
+ "test case-sensitive option name lookup"),
+ SVN_TEST_OPTS_PASS(test_stream_interface,
+ "test svn_config_parse"),
+ SVN_TEST_PASS2(test_ignore_bom,
+ "test parsing config file with BOM"),
+ SVN_TEST_OPTS_PASS(test_read_only_mode,
+ "test r/o mode"),
SVN_TEST_OPTS_PASS(test_expand,
"test variable expansion"),
+ SVN_TEST_PASS2(test_invalid_bom,
+ "test parsing config file with invalid BOM"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/crypto-test.c b/subversion/tests/libsvn_subr/crypto-test.c
index 0c52804..91fd6c7 100644
--- a/subversion/tests/libsvn_subr/crypto-test.c
+++ b/subversion/tests/libsvn_subr/crypto-test.c
@@ -177,7 +177,9 @@ test_passphrase_check(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = -1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_encrypt_decrypt_password,
@@ -186,3 +188,5 @@ struct svn_test_descriptor_t test_funcs[] =
"password checktext generation/validation"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/dirent_uri-test.c b/subversion/tests/libsvn_subr/dirent_uri-test.c
index 992d288..61d9e24 100644
--- a/subversion/tests/libsvn_subr/dirent_uri-test.c
+++ b/subversion/tests/libsvn_subr/dirent_uri-test.c
@@ -270,7 +270,7 @@ test_dirent_join(apr_pool_t *pool)
"\"%s\". expected \"%s\"",
base, comp, result, expect);
- result = svn_dirent_join_many(pool, base, comp, NULL);
+ result = svn_dirent_join_many(pool, base, comp, SVN_VA_NULL);
if (strcmp(result, expect))
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
"svn_dirent_join_many(\"%s\", \"%s\") returned "
@@ -286,72 +286,72 @@ test_dirent_join(apr_pool_t *pool)
"expected \"%s\"", \
result, expect);
- TEST_MANY((pool, "abc", NULL), "abc");
- TEST_MANY((pool, "/abc", NULL), "/abc");
- TEST_MANY((pool, "/", NULL), "/");
-
- TEST_MANY((pool, "abc", "def", "ghi", NULL), "abc/def/ghi");
- TEST_MANY((pool, "abc", "/def", "ghi", NULL), "/def/ghi");
- TEST_MANY((pool, "/abc", "def", "ghi", NULL), "/abc/def/ghi");
- TEST_MANY((pool, "abc", "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "/def", "/ghi", NULL), "/ghi");
-
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", "ghi", NULL), "def/ghi");
- TEST_MANY((pool, "abc", SVN_EMPTY_PATH, "ghi", NULL), "abc/ghi");
- TEST_MANY((pool, "abc", "def", SVN_EMPTY_PATH, NULL), "abc/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", SVN_EMPTY_PATH, NULL), "def");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "ghi", NULL), "ghi");
- TEST_MANY((pool, "abc", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "abc");
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/ghi", NULL), "/ghi");
-
- TEST_MANY((pool, "/", "def", "ghi", NULL), "/def/ghi");
- TEST_MANY((pool, "abc", "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "abc", "def", "/", NULL), "/");
- TEST_MANY((pool, "/", "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "/", "/", NULL), "/");
- TEST_MANY((pool, "/", SVN_EMPTY_PATH, "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "def", SVN_EMPTY_PATH, NULL), "/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "/");
- TEST_MANY((pool, SVN_EMPTY_PATH, "/", SVN_EMPTY_PATH, NULL), "/");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/", NULL), "/");
+ TEST_MANY((pool, "abc", SVN_VA_NULL), "abc");
+ TEST_MANY((pool, "/abc", SVN_VA_NULL), "/abc");
+ TEST_MANY((pool, "/", SVN_VA_NULL), "/");
+
+ TEST_MANY((pool, "abc", "def", "ghi", SVN_VA_NULL), "abc/def/ghi");
+ TEST_MANY((pool, "abc", "/def", "ghi", SVN_VA_NULL), "/def/ghi");
+ TEST_MANY((pool, "/abc", "def", "ghi", SVN_VA_NULL), "/abc/def/ghi");
+ TEST_MANY((pool, "abc", "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "/def", "/ghi", SVN_VA_NULL), "/ghi");
+
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", "ghi", SVN_VA_NULL), "def/ghi");
+ TEST_MANY((pool, "abc", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "abc/ghi");
+ TEST_MANY((pool, "abc", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "abc/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", SVN_EMPTY_PATH, SVN_VA_NULL), "def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "ghi");
+ TEST_MANY((pool, "abc", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "abc");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/ghi", SVN_VA_NULL), "/ghi");
+
+ TEST_MANY((pool, "/", "def", "ghi", SVN_VA_NULL), "/def/ghi");
+ TEST_MANY((pool, "abc", "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "abc", "def", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "/", "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "/", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "/", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "/", SVN_EMPTY_PATH, SVN_VA_NULL), "/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/", SVN_VA_NULL), "/");
#ifdef SVN_USE_DOS_PATHS
- TEST_MANY((pool, "X:/", "def", "ghi", NULL), "X:/def/ghi");
- TEST_MANY((pool, "abc", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "abc", "def", "X:/", NULL), "X:/");
- TEST_MANY((pool, "X:/", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", "X:/", "/", NULL), "/");
- TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", "def", SVN_EMPTY_PATH, NULL), "X:/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "X:/");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", SVN_EMPTY_PATH, NULL), "X:/");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "X:/", NULL), "X:/");
-
- TEST_MANY((pool, "X:", "def", "ghi", NULL), "X:def/ghi");
- TEST_MANY((pool, "X:", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:", "X:/", "/", NULL), "/");
- TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", NULL), "X:ghi");
- TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, NULL), "X:def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", NULL), "X:ghi");
- TEST_MANY((pool, "//srv/shr", "def", "ghi", NULL), "//srv/shr/def/ghi");
- TEST_MANY((pool, "//srv/shr/fld", "def", "ghi", NULL), "//srv/shr/fld/def/ghi");
- TEST_MANY((pool, "//srv/shr/fld", "def", "//srv/shr", NULL), "//srv/shr");
- TEST_MANY((pool, "//srv/s r/fld", "def", "//srv/s r", NULL), "//srv/s r");
- TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "ghi", NULL), "//srv/shr/fld/def/ghi");
- TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "//srv/shr", NULL), "//srv/shr");
-
- TEST_MANY((pool, "abcd", "/dir", "A:", "file", NULL), "A:file");
- TEST_MANY((pool, "abcd", "A:", "/dir", "file", NULL), "A:/dir/file");
+ TEST_MANY((pool, "X:/", "def", "ghi", SVN_VA_NULL), "X:/def/ghi");
+ TEST_MANY((pool, "abc", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "abc", "def", "X:/", SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, "X:/", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", "X:/", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "X:/", SVN_VA_NULL), "X:/");
+
+ TEST_MANY((pool, "X:", "def", "ghi", SVN_VA_NULL), "X:def/ghi");
+ TEST_MANY((pool, "X:", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "X:/", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:ghi");
+ TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", SVN_VA_NULL), "X:ghi");
+ TEST_MANY((pool, "//srv/shr", "def", "ghi", SVN_VA_NULL), "//srv/shr/def/ghi");
+ TEST_MANY((pool, "//srv/shr/fld", "def", "ghi", SVN_VA_NULL), "//srv/shr/fld/def/ghi");
+ TEST_MANY((pool, "//srv/shr/fld", "def", "//srv/shr", SVN_VA_NULL), "//srv/shr");
+ TEST_MANY((pool, "//srv/s r/fld", "def", "//srv/s r", SVN_VA_NULL), "//srv/s r");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "ghi", SVN_VA_NULL), "//srv/shr/fld/def/ghi");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "//srv/shr", SVN_VA_NULL), "//srv/shr");
+
+ TEST_MANY((pool, "abcd", "/dir", "A:", "file", SVN_VA_NULL), "A:file");
+ TEST_MANY((pool, "abcd", "A:", "/dir", "file", SVN_VA_NULL), "A:/dir/file");
#else /* !SVN_USE_DOS_PATHS */
- TEST_MANY((pool, "X:", "def", "ghi", NULL), "X:/def/ghi");
- TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, NULL), "X:/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "def", "ghi", SVN_VA_NULL), "X:/def/ghi");
+ TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", SVN_VA_NULL), "X:/ghi");
#endif /* SVN_USE_DOS_PATHS */
/* ### probably need quite a few more tests... */
@@ -809,6 +809,9 @@ static const testcase_canonicalize_t uri_canonical_tests[] =
{ "http://hst/foo/../bar","http://hst/foo/../bar" },
{ "http://hst/", "http://hst" },
{ "http:///", "http://" },
+ { "http:///example.com/", "http:///example.com" },
+ { "http:////example.com/", "http:///example.com" },
+ { "http://///////example.com/", "http:///example.com" },
{ "https://", "https://" },
{ "file:///", "file://" },
{ "file://", "file://" },
@@ -1109,6 +1112,7 @@ test_relpath_is_canonical(apr_pool_t *pool)
static const testcase_is_canonical_t tests[] = {
{ "", TRUE },
{ ".", FALSE },
+ { "..", TRUE },
{ "/", FALSE },
{ "/.", FALSE },
{ "./", FALSE },
@@ -1937,13 +1941,13 @@ test_dirent_get_absolute(apr_pool_t *pool)
expect_abs = expect;
if (*expect == '%')
- expect_abs = apr_pstrcat(pool, curdir, expect + 1, (char *)NULL);
+ expect_abs = apr_pstrcat(pool, curdir, expect + 1, SVN_VA_NULL);
#ifdef SVN_USE_DOS_PATHS
if (*expect == '@')
- expect_abs = apr_pstrcat(pool, curdironc, expect + 1, NULL);
+ expect_abs = apr_pstrcat(pool, curdironc, expect + 1, SVN_VA_NULL);
if (*expect == '$')
- expect_abs = apr_pstrcat(pool, curdrive, expect + 1, NULL);
+ expect_abs = apr_pstrcat(pool, curdrive, expect + 1, SVN_VA_NULL);
/* Remove double '/' when CWD was the root dir (E.g. C:/) */
expect_abs = svn_dirent_canonicalize(expect_abs, pool);
@@ -1987,8 +1991,8 @@ test_dirent_get_absolute_from_lc_drive(apr_pool_t *pool)
for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi))
{
- const char *dir = svn__apr_hash_index_key(hi);
- svn_io_dirent2_t *de = svn__apr_hash_index_val(hi);
+ const char *dir = apr_hash_this_key(hi);
+ svn_io_dirent2_t *de = apr_hash_this_val(hi);
if (de->kind == svn_node_dir &&
strcmp(dir, current_dir_on_C))
@@ -2857,7 +2861,9 @@ test_rule3(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_dirent_is_root,
@@ -2958,3 +2964,5 @@ struct svn_test_descriptor_t test_funcs[] =
"test match with RFC 6125 s. 6.4.3 Rule 3"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/error-code-test.c b/subversion/tests/libsvn_subr/error-code-test.c
index e996616..8dada36 100644
--- a/subversion/tests/libsvn_subr/error-code-test.c
+++ b/subversion/tests/libsvn_subr/error-code-test.c
@@ -74,10 +74,14 @@ check_error_codes_unique(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(check_error_codes_unique,
"check that error codes are unique"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/error-test.c b/subversion/tests/libsvn_subr/error-test.c
index 18dacde..ea3291b 100644
--- a/subversion/tests/libsvn_subr/error-test.c
+++ b/subversion/tests/libsvn_subr/error-test.c
@@ -205,8 +205,12 @@ test_error_symbolic_name(apr_pool_t *pool)
{ 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 },
+ { -1, NULL },
{ SVN_ERR_WC_CATEGORY_START - 1, NULL },
/* Whitebox-test exceptional cases. */
{ SVN_WARNING, "SVN_WARNING" },
@@ -225,7 +229,9 @@ test_error_symbolic_name(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_error_root_cause,
@@ -236,3 +242,5 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_error_symbolic_name"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/hashdump-test.c b/subversion/tests/libsvn_subr/hashdump-test.c
index a80b1c1..57a8535 100644
--- a/subversion/tests/libsvn_subr/hashdump-test.c
+++ b/subversion/tests/libsvn_subr/hashdump-test.c
@@ -38,9 +38,9 @@
/* Our own global variables */
-apr_hash_t *proplist, *new_proplist;
+static apr_hash_t *proplist, *new_proplist;
-const char *review =
+static const char *review =
"A forthright entrance, yet coquettish on the tongue, its deceptively\n"
"fruity exterior hides the warm mahagony undercurrent that is the\n"
"hallmark of Chateau Fraisant-Pitre. Connoisseurs of the region will\n"
@@ -177,7 +177,10 @@ test3(apr_pool_t *pool)
*/
/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test1,
@@ -188,3 +191,5 @@ struct svn_test_descriptor_t test_funcs[] =
"write hash out, read back in, compare"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/io-test.c b/subversion/tests/libsvn_subr/io-test.c
index 82e8630..e9de6fb 100644
--- a/subversion/tests/libsvn_subr/io-test.c
+++ b/subversion/tests/libsvn_subr/io-test.c
@@ -26,10 +26,14 @@
#include <stdio.h>
#include <apr.h>
+#include <apr_version.h>
#include "svn_pools.h"
#include "svn_string.h"
+#include "svn_io.h"
#include "private/svn_skel.h"
+#include "private/svn_dep_compat.h"
+#include "private/svn_io_private.h"
#include "../svn_test.h"
#include "../svn_test_fs.h"
@@ -37,7 +41,7 @@
/* Helpers to create the test data directory. */
-#define TEST_DIR "io-test-temp"
+#define TEST_DIR_PREFIX "io-test-temp"
/* The definition for the test data files. */
struct test_file_definition_t
@@ -64,7 +68,7 @@ struct test_file_definition_t
char* created_path;
};
-struct test_file_definition_t test_file_definitions[] =
+static struct test_file_definition_t test_file_definitions_template[] =
{
{"empty", "", 0},
{"single_a", "a", 1},
@@ -119,6 +123,7 @@ struct test_file_definition_t test_file_definitions[] =
static svn_error_t *
create_test_file(struct test_file_definition_t* definition,
+ const char *testname,
apr_pool_t *pool,
apr_pool_t *scratch_pool)
{
@@ -127,6 +132,7 @@ create_test_file(struct test_file_definition_t* definition,
apr_off_t midpos = definition->size / 2;
svn_error_t *err = NULL;
int i;
+ const char *test_dir = apr_pstrcat(pool, TEST_DIR_PREFIX, testname, NULL);
if (definition->size < 5)
SVN_ERR_ASSERT(strlen(definition->data) >= (apr_size_t)definition->size);
@@ -134,9 +140,9 @@ create_test_file(struct test_file_definition_t* definition,
SVN_ERR_ASSERT(strlen(definition->data) >= 5);
- definition->created_path = svn_dirent_join(TEST_DIR,
- definition->name,
- pool);
+ definition->created_path = svn_dirent_join(test_dir,
+ definition->name,
+ pool);
SVN_ERR(svn_io_file_open(&file_h,
definition->created_path,
@@ -174,37 +180,47 @@ create_test_file(struct test_file_definition_t* definition,
/* Function to prepare the whole set of on-disk files to be compared. */
static svn_error_t *
-create_comparison_candidates(apr_pool_t *scratch_pool)
+create_comparison_candidates(struct test_file_definition_t **definitions,
+ const char *testname,
+ apr_pool_t *pool)
{
svn_node_kind_t kind;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *iterpool = svn_pool_create(pool);
struct test_file_definition_t *candidate;
svn_error_t *err = SVN_NO_ERROR;
+ apr_size_t count = 0;
+ const char *test_dir = apr_pstrcat(pool, TEST_DIR_PREFIX,
+ testname, NULL);
/* If there's already a directory named io-test-temp, delete it.
Doing things this way means that repositories stick around after
a failure for postmortem analysis, but also that tests can be
re-run without cleaning out the repositories created by prior
runs. */
- SVN_ERR(svn_io_check_path(TEST_DIR, &kind, scratch_pool));
+ SVN_ERR(svn_io_check_path(test_dir, &kind, pool));
if (kind == svn_node_dir)
- SVN_ERR(svn_io_remove_dir2(TEST_DIR, TRUE, NULL, NULL, scratch_pool));
+ SVN_ERR(svn_io_remove_dir2(test_dir, TRUE, NULL, NULL, pool));
else if (kind != svn_node_none)
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
"There is already a file named '%s'",
- TEST_DIR);
+ test_dir);
- SVN_ERR(svn_io_dir_make(TEST_DIR, APR_OS_DEFAULT, scratch_pool));
+ SVN_ERR(svn_io_dir_make(test_dir, APR_OS_DEFAULT, pool));
- svn_test_add_dir_cleanup(TEST_DIR);
+ svn_test_add_dir_cleanup(test_dir);
- for (candidate = test_file_definitions;
+ for (candidate = test_file_definitions_template;
candidate->name != NULL;
candidate += 1)
+ count++;
+
+ *definitions = apr_pmemdup(pool, test_file_definitions_template,
+ (count + 1) * sizeof(**definitions));
+ for (candidate = *definitions; candidate->name != NULL; candidate += 1)
{
svn_pool_clear(iterpool);
- err = create_test_file(candidate, scratch_pool, iterpool);
+ err = create_test_file(candidate, testname, pool, iterpool);
if (err)
break;
}
@@ -227,8 +243,11 @@ test_two_file_size_comparison(apr_pool_t *scratch_pool)
svn_error_t *err = SVN_NO_ERROR;
svn_error_t *cmp_err;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct test_file_definition_t *test_file_definitions;
- SVN_ERR(create_comparison_candidates(scratch_pool));
+ SVN_ERR(create_comparison_candidates(&test_file_definitions,
+ "test_two_file_size_comparison",
+ scratch_pool));
for (outer = test_file_definitions; outer->name != NULL; outer += 1)
{
@@ -278,8 +297,11 @@ test_two_file_content_comparison(apr_pool_t *scratch_pool)
svn_error_t *err = SVN_NO_ERROR;
svn_error_t *cmp_err;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct test_file_definition_t *test_file_definitions;
- SVN_ERR(create_comparison_candidates(scratch_pool));
+ SVN_ERR(create_comparison_candidates(&test_file_definitions,
+ "test_two_file_content_comparison",
+ scratch_pool));
for (outer = test_file_definitions; outer->name != NULL; outer += 1)
{
@@ -331,8 +353,11 @@ test_three_file_size_comparison(apr_pool_t *scratch_pool)
svn_error_t *err = SVN_NO_ERROR;
svn_error_t *cmp_err;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct test_file_definition_t *test_file_definitions;
- SVN_ERR(create_comparison_candidates(scratch_pool));
+ SVN_ERR(create_comparison_candidates(&test_file_definitions,
+ "test_three_file_size_comparison",
+ scratch_pool));
for (outer = test_file_definitions; outer->name != NULL; outer += 1)
{
@@ -411,8 +436,11 @@ test_three_file_content_comparison(apr_pool_t *scratch_pool)
svn_error_t *err = SVN_NO_ERROR;
svn_error_t *cmp_err;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct test_file_definition_t *test_file_definitions;
- SVN_ERR(create_comparison_candidates(scratch_pool));
+ SVN_ERR(create_comparison_candidates(&test_file_definitions,
+ "test_three_file_content_comparison",
+ scratch_pool));
for (outer = test_file_definitions; outer->name != NULL; outer += 1)
{
@@ -507,10 +535,304 @@ read_length_line_shouldnt_loop(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+/* Move the read pointer in FILE to absolute position OFFSET and align
+ * the read buffer to multiples of BLOCK_SIZE. BUFFERED is set only if
+ * FILE actually uses a read buffer. Use POOL for allocations.
+ */
+static svn_error_t *
+aligned_seek(apr_file_t *file,
+ apr_size_t block_size,
+ apr_size_t offset,
+ svn_boolean_t buffered,
+ apr_pool_t *pool)
+{
+ apr_off_t block_start;
+ apr_off_t current;
+
+ SVN_ERR(svn_io_file_aligned_seek(file, (apr_off_t)block_size,
+ &block_start, (apr_off_t)offset, pool));
+
+ /* block start shall be aligned to multiples of block_size.
+ If it isn't, it must be aligned to APR's default block size(pre-1.3 APR)
+ */
+ if (buffered)
+ {
+ SVN_TEST_ASSERT(block_start % block_size == 0);
+ SVN_TEST_ASSERT(offset - block_start < block_size);
+ }
+
+ /* we must be at the desired offset */
+ current = 0;
+ SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, pool));
+ SVN_TEST_ASSERT(current == (apr_off_t)offset);
+
+ return SVN_NO_ERROR;
+}
+
+/* Move the read pointer in FILE to absolute position OFFSET, align the
+ * read buffer to multiples of BLOCK_SIZE and read one byte from that
+ * position. Verify that it matches the CONTENTS for that offset.
+ * BUFFERED is set only if FILE actually uses a read buffer.
+ * Use POOL for allocations.
+ */
+static svn_error_t *
+aligned_read_at(apr_file_t *file,
+ svn_stringbuf_t *contents,
+ apr_size_t block_size,
+ apr_size_t offset,
+ svn_boolean_t buffered,
+ apr_pool_t *pool)
+{
+ char c;
+ SVN_ERR(aligned_seek(file, block_size, offset, buffered, pool));
+
+ /* the data we read must match whatever we wrote there */
+ SVN_ERR(svn_io_file_getc(&c, file, pool));
+ SVN_TEST_ASSERT(c == contents->data[offset]);
+
+ return SVN_NO_ERROR;
+}
+
+/* Verify that aligned seek with the given BLOCK_SIZE works for FILE.
+ * CONTENTS is the data expected from FILE. BUFFERED is set only if FILE
+ * actually uses a read buffer. Use POOL for allocations.
+ */
+static svn_error_t *
+aligned_read(apr_file_t *file,
+ svn_stringbuf_t *contents,
+ apr_size_t block_size,
+ svn_boolean_t buffered,
+ apr_pool_t *pool)
+{
+ apr_size_t i;
+ apr_size_t offset = 0;
+ const apr_size_t prime = 78427;
+
+ /* "random" access to different offsets */
+ for (i = 0, offset = prime; i < 10; ++i, offset += prime)
+ SVN_ERR(aligned_read_at(file, contents, block_size,
+ offset % contents->len, buffered, pool));
+
+ /* we can seek to EOF */
+ SVN_ERR(aligned_seek(file, contents->len, block_size, buffered, pool));
+
+ /* reversed order access to all bytes */
+ for (i = contents->len; i > 0; --i)
+ SVN_ERR(aligned_read_at(file, contents, block_size, i - 1, buffered,
+ pool));
+
+ /* forward order access to all bytes */
+ for (i = 0; i < contents->len; ++i)
+ SVN_ERR(aligned_read_at(file, contents, block_size, i, buffered, pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+aligned_seek_test(apr_pool_t *pool)
+{
+ apr_size_t i;
+ const char *tmp_dir;
+ const char *tmp_file;
+ apr_file_t *f;
+ svn_stringbuf_t *contents;
+ const apr_size_t file_size = 100000;
+
+ /* create a temp folder & schedule it for automatic cleanup */
+
+ SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "aligned_seek_tmp", pool));
+ SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+ svn_test_add_dir_cleanup(tmp_dir);
+
+ /* create a temp file with know contents */
+
+ contents = svn_stringbuf_create_ensure(file_size, pool);
+ for (i = 0; i < file_size; ++i)
+ svn_stringbuf_appendbyte(contents, (char)rand());
+
+ SVN_ERR(svn_io_write_unique(&tmp_file, tmp_dir, contents->data,
+ contents->len,
+ svn_io_file_del_on_pool_cleanup, pool));
+
+ /* now, access read data with varying alignment sizes */
+ SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ | APR_BUFFERED,
+ APR_OS_DEFAULT, pool));
+ SVN_ERR(aligned_read(f, contents, 0x1000, TRUE, pool)); /* APR default */
+ SVN_ERR(aligned_read(f, contents, 0x8000, TRUE, pool)); /* "unusual" 32K */
+ SVN_ERR(aligned_read(f, contents, 0x10000, TRUE, pool)); /* FSX default */
+ SVN_ERR(aligned_read(f, contents, 0x100000, TRUE, pool)); /* larger than file */
+ SVN_ERR(aligned_read(f, contents, 10001, TRUE, pool)); /* odd, larger than
+ APR default */
+ SVN_ERR(aligned_read(f, contents, 1003, TRUE, pool)); /* odd, smaller than
+ APR default */
+ SVN_ERR(svn_io_file_close(f, pool));
+
+ /* now, try read data with buffering disabled.
+ That are a special case because APR reports a buffer size of 0. */
+ SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ, APR_OS_DEFAULT, pool));
+ SVN_ERR(aligned_read(f, contents, 0x1000, FALSE, pool));
+ SVN_ERR(aligned_read(f, contents, 0x8000, FALSE, pool));
+ SVN_ERR(aligned_read(f, contents, 0x10000, FALSE, pool));
+ SVN_ERR(aligned_read(f, contents, 0x100000, FALSE, pool));
+ SVN_ERR(aligned_read(f, contents, 10001, FALSE, pool));
+ SVN_ERR(aligned_read(f, contents, 1003, FALSE, pool));
+ SVN_ERR(svn_io_file_close(f, pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ignore_enoent(apr_pool_t *pool)
+{
+ const char *tmp_dir, *path;
+ const svn_io_dirent2_t *dirent_p;
+ apr_file_t *file;
+
+ /* Create an empty directory. */
+ SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "ignore_enoent", pool));
+ SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+ svn_test_add_dir_cleanup(tmp_dir);
+
+ /* Path does not exist. */
+ path = svn_dirent_join(tmp_dir, "not-present", pool);
+ SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
+
+ /* Neither path nor parent exists. */
+ path = svn_dirent_join(path, "not-present", pool);
+ SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
+
+ /* File does exist. */
+ path = svn_dirent_join(tmp_dir, "present", pool);
+ SVN_ERR(svn_io_file_open(&file, path,
+ APR_WRITE | APR_CREATE | APR_TRUNCATE,
+ APR_OS_DEFAULT,
+ pool));
+ SVN_ERR(svn_io_file_close(file, pool));
+
+ /* Path does not exist as child of file. */
+ path = svn_dirent_join(path, "not-present", pool);
+ SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_only(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
+ SVN_ERR(svn_io_set_file_executable(path, FALSE, TRUE, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, TRUE, TRUE, pool, pool));
+ SVN_ERR(svn_io_stat_dirent2(&dirent_p, path, FALSE, TRUE, pool, pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_install_stream_to_longpath(apr_pool_t *pool)
+{
+ const char *tmp_dir;
+ const char *final_abspath;
+ const char *deep_dir;
+ svn_stream_t *stream;
+ svn_stringbuf_t *actual_content;
+ int i;
+
+ /* Create an empty directory. */
+ SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_install_stream_to_longpath",
+ pool));
+ SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+ svn_test_add_dir_cleanup(tmp_dir);
+
+ deep_dir = tmp_dir;
+
+ /* Generate very long path (> 260 symbols) */
+ for (i = 0; i < 26; i++)
+ {
+ deep_dir = svn_dirent_join(deep_dir, "1234567890", pool);
+ SVN_ERR(svn_io_make_dir_recursively(deep_dir, pool));
+ }
+
+ final_abspath = svn_dirent_join(deep_dir, "stream1", pool);
+ SVN_ERR(svn_stream__create_for_install(&stream, deep_dir, pool, pool));
+ SVN_ERR(svn_stream_puts(stream, "stream1 content"));
+ SVN_ERR(svn_stream_close(stream));
+ SVN_ERR(svn_stream__install_stream(stream,
+ final_abspath,
+ TRUE,
+ pool));
+
+ SVN_ERR(svn_stringbuf_from_file2(&actual_content,
+ final_abspath,
+ pool));
+
+ SVN_TEST_STRING_ASSERT(actual_content->data, "stream1 content");
+
+ return SVN_NO_ERROR;
+}
+static svn_error_t *
+test_apr_trunc_workaround(apr_pool_t *pool)
+{
+ const char *tmp_dir;
+ const char *tmp_file;
+ apr_file_t *f;
+ apr_size_t len;
+ apr_off_t offset;
+ char dummy;
+
+ /* create a temp folder & schedule it for automatic cleanup */
+ SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_apr_trunc_workaround",
+ pool));
+ SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+ svn_test_add_dir_cleanup(tmp_dir);
+
+ /* create an r/w file */
+ tmp_file = svn_dirent_join(tmp_dir, "file", pool);
+ SVN_ERR(svn_io_file_open(&f, tmp_file,
+ APR_READ | APR_WRITE | APR_BUFFERED | APR_CREATE |
+ APR_TRUNCATE,
+ APR_OS_DEFAULT, pool));
+
+ /* write some content and put it internally into read mode */
+ len = 10;
+ SVN_ERR(svn_io_file_write(f, "0123456789", &len, pool));
+
+ offset = 0;
+ SVN_ERR(svn_io_file_seek(f, APR_SET, &offset, pool));
+ SVN_ERR(svn_io_file_getc(&dummy, f, pool));
+
+ /* clear the file and write some new content */
+ SVN_ERR(svn_io_file_trunc(f, 0, pool));
+ len = 3;
+ SVN_ERR(svn_io_file_write(f, "abc", &len, pool));
+
+ /* we should now be positioned at the end of the new content */
+ offset = 0;
+ SVN_ERR(svn_io_file_seek(f, APR_CUR, &offset, pool));
+ SVN_TEST_ASSERT(offset == (int)len);
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 3;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_two_file_size_comparison,
@@ -523,5 +845,15 @@ struct svn_test_descriptor_t test_funcs[] =
"three file content comparison"),
SVN_TEST_PASS2(read_length_line_shouldnt_loop,
"svn_io_read_length_line() shouldn't loop"),
+ SVN_TEST_PASS2(aligned_seek_test,
+ "test aligned seek"),
+ SVN_TEST_PASS2(ignore_enoent,
+ "test ignore-enoent"),
+ SVN_TEST_PASS2(test_install_stream_to_longpath,
+ "test svn_stream__install_stream to long path"),
+ SVN_TEST_PASS2(test_apr_trunc_workaround,
+ "test workaround for APR in svn_io_file_trunc"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/mergeinfo-test.c b/subversion/tests/libsvn_subr/mergeinfo-test.c
index ecfcd02..5f4d37e 100644
--- a/subversion/tests/libsvn_subr/mergeinfo-test.c
+++ b/subversion/tests/libsvn_subr/mergeinfo-test.c
@@ -104,7 +104,7 @@ verify_mergeinfo_parse(const char *input,
/* Were we expecting any more ranges? */
if (j < MAX_NBR_RANGES - 1
- && !expected_ranges[j].end == 0)
+ && expected_ranges[j].end != 0)
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
"svn_mergeinfo_parse (%s) failed to "
"produce the expected number of ranges",
@@ -114,11 +114,7 @@ verify_mergeinfo_parse(const char *input,
}
-/* Some of our own global variables (for simplicity), which map paths
- -> merge ranges. */
-static apr_hash_t *info1, *info2;
-
-#define NBR_MERGEINFO_VALS 24
+#define NBR_MERGEINFO_VALS 25
/* Valid mergeinfo values. */
static const char * const mergeinfo_vals[NBR_MERGEINFO_VALS] =
@@ -152,7 +148,8 @@ static const char * const mergeinfo_vals[NBR_MERGEINFO_VALS] =
"/A/:7-8",
"/A///:7-8",
"/A/.:7-8",
- "/A/./B:7-8"
+ "/A/./B:7-8",
+ ":7-8",
};
/* Paths corresponding to mergeinfo_vals. */
static const char * const mergeinfo_paths[NBR_MERGEINFO_VALS] =
@@ -185,7 +182,8 @@ static const char * const mergeinfo_paths[NBR_MERGEINFO_VALS] =
"/A",
"/A",
"/A",
- "/A/B"
+ "/A/B",
+ "/",
};
/* First ranges from the paths identified by mergeinfo_paths. */
static svn_merge_range_t mergeinfo_ranges[NBR_MERGEINFO_VALS][MAX_NBR_RANGES] =
@@ -216,6 +214,7 @@ static svn_merge_range_t mergeinfo_ranges[NBR_MERGEINFO_VALS][MAX_NBR_RANGES] =
{ {6, 8, TRUE} },
{ {6, 8, TRUE} },
{ {6, 8, TRUE} },
+ { {6, 8, TRUE} },
};
static svn_error_t *
@@ -268,6 +267,7 @@ test_parse_combine_rangeinfo(apr_pool_t *pool)
{
apr_array_header_t *result;
svn_merge_range_t *resultrange;
+ apr_hash_t *info1;
SVN_ERR(svn_mergeinfo_parse(&info1, single_mergeinfo, pool));
@@ -301,7 +301,7 @@ test_parse_combine_rangeinfo(apr_pool_t *pool)
}
-#define NBR_BROKEN_MERGEINFO_VALS 27
+#define NBR_BROKEN_MERGEINFO_VALS 26
/* Invalid mergeinfo values. */
static const char * const broken_mergeinfo_vals[NBR_BROKEN_MERGEINFO_VALS] =
{
@@ -333,8 +333,6 @@ static const char * const broken_mergeinfo_vals[NBR_BROKEN_MERGEINFO_VALS] =
"/trunk:",
"/trunk:2-9\n/branch:",
"::",
- /* No path */
- ":1-3",
/* Invalid revisions */
"trunk:a-3",
"branch:3-four",
@@ -346,6 +344,7 @@ test_parse_broken_mergeinfo(apr_pool_t *pool)
{
int i;
svn_error_t *err;
+ apr_hash_t *info1;
/* Trigger some error(s) with mal-formed input. */
for (i = 0; i < NBR_BROKEN_MERGEINFO_VALS; i++)
@@ -565,6 +564,7 @@ test_mergeinfo_intersect(apr_pool_t *pool)
{ {0, 1, TRUE}, {2, 4, TRUE}, {11, 12, TRUE} };
svn_rangelist_t *rangelist;
apr_hash_t *intersection;
+ apr_hash_t *info1, *info2;
SVN_ERR(svn_mergeinfo_parse(&info1, "/trunk: 1-6,12-16\n/foo: 31", pool));
SVN_ERR(svn_mergeinfo_parse(&info2, "/trunk: 1,3-4,7,9,11-12", pool));
@@ -701,6 +701,7 @@ test_merge_mergeinfo(apr_pool_t *pool)
{
int j;
svn_string_t *info2_starting, *info2_ending;
+ apr_hash_t *info1, *info2;
SVN_ERR(svn_mergeinfo_parse(&info1, mergeinfo[i].mergeinfo1, pool));
SVN_ERR(svn_mergeinfo_parse(&info2, mergeinfo[i].mergeinfo2, pool));
@@ -1109,6 +1110,7 @@ test_rangelist_to_string(apr_pool_t *pool)
svn_rangelist_t *result;
svn_string_t *output;
svn_string_t *expected = svn_string_create("3,5,7-11,13-14", pool);
+ apr_hash_t *info1;
SVN_ERR(svn_mergeinfo_parse(&info1, mergeinfo1, pool));
@@ -1129,6 +1131,7 @@ test_mergeinfo_to_string(apr_pool_t *pool)
{
svn_string_t *output;
svn_string_t *expected;
+ apr_hash_t *info1, *info2;
expected = svn_string_create("/fred:8-10\n/trunk:3,5,7-11,13-14", pool);
SVN_ERR(svn_mergeinfo_parse(&info1, mergeinfo1, pool));
@@ -1670,7 +1673,9 @@ test_remove_prefix_from_catalog(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_parse_single_line_mergeinfo,
@@ -1711,3 +1716,5 @@ struct svn_test_descriptor_t test_funcs[] =
"removal of prefix paths from catalog keys"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/named_atomic-test-common.h b/subversion/tests/libsvn_subr/named_atomic-test-common.h
deleted file mode 100644
index 2ada4ee..0000000
--- a/subversion/tests/libsvn_subr/named_atomic-test-common.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * named_atomic-test-common.h: shared function implementations for
- * named_atomic-test
- *
- * ====================================================================
- * 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 "svn_pools.h"
-#include "private/svn_named_atomic.h"
-
-/* Some constants that we will use in our tests */
-
-/* All our atomics start with that name */
-#define ATOMIC_NAME "MyTestAtomic"
-
-/* Factor used to create non-trivial 64 bit numbers */
-#define HUGE_VALUE 1234567890123456ll
-
-/* to separate this code from any production environment */
-const char *name_namespace = NULL;
-const char *name_namespace1 = NULL;
-const char *name_namespace2 = NULL;
-
-/* data structure containing all information we need to check for
- * a) passing some deadline
- * b) reaching the maximum iteration number
- */
-typedef struct watchdog_t
-{
- apr_time_t deadline;
- svn_named_atomic__t *atomic_counter;
- int iterations;
- int call_count; /* don't call apr_time_now() too often '*/
-} watchdog_t;
-
-/* init the WATCHDOG data structure for checking ATOMIC_COUNTER to reach
- * ITERATIONS and for the system time to pass a deadline MAX_DURATION
- * microsecs in the future.
- */
-static void
-init_watchdog(watchdog_t *watchdog,
- svn_named_atomic__t *atomic_counter,
- int iterations,
- apr_time_t max_duration)
-{
- watchdog->deadline = apr_time_now() + max_duration;
- watchdog->atomic_counter = atomic_counter;
- watchdog->iterations = iterations;
- watchdog->call_count = 0;
-}
-
-/* test for watchdog conditions */
-static svn_error_t *
-check_watchdog(watchdog_t *watchdog, svn_boolean_t *done)
-{
- apr_int64_t counter = 0;
-
- /* check for normal end of loop.
- * We are a watchdog, so don't check for errors. */
- *done = FALSE;
- svn_error_clear(svn_named_atomic__read(&counter,
- watchdog->atomic_counter));
- if (counter >= watchdog->iterations)
- {
- *done = TRUE;
- return SVN_NO_ERROR;
- }
-
- /* Check the system time and indicate when deadline has passed */
- if (++watchdog->call_count > 100)
- {
- watchdog->call_count = 100;
- if (apr_time_now() > watchdog->deadline)
- return svn_error_createf(SVN_ERR_TEST_FAILED,
- 0,
- "Deadline has passed at iteration %d/%d",
- (int)counter, watchdog->iterations);
- }
-
- /* no problem so far */
- return SVN_NO_ERROR;
-}
-
-/* "pipeline" test: initialization code executed by the worker with ID 0.
- * Pushes COUNT tokens into ATOMIC_OUT and checks for ATOMIC_COUNTER not to
- * exceed ITERATIONS (early termination).
- */
-static svn_error_t *
-test_pipeline_prepare(svn_named_atomic__t *atomic_out,
- int count,
- watchdog_t *watchdog)
-{
- apr_int64_t value = 0;
- int i;
- svn_boolean_t done = FALSE;
-
- /* Initialize values in thread 0, pass them along in other threads */
-
- for (i = 1; i <= count; ++i)
- do
- {
- /* Generate new token (once the old one has been removed)*/
- SVN_ERR(svn_named_atomic__cmpxchg(&value,
- i,
- 0,
- atomic_out));
- SVN_ERR(check_watchdog(watchdog, &done));
- if (done) return SVN_NO_ERROR;
- }
- while (value != 0);
-
- return SVN_NO_ERROR;
-}
-
-/* "pipeline" test: the main loop. Each one of the COUNT workers receives
- * data in its ATOMIC_IN and passes it on to ATOMIC_OUT until ATOMIC_COUNTER
- * exceeds ITERATIONS.
- */
-static svn_error_t *
-test_pipeline_loop(svn_named_atomic__t *atomic_in,
- svn_named_atomic__t *atomic_out,
- svn_named_atomic__t *atomic_counter,
- int count,
- int iterations,
- watchdog_t *watchdog)
-{
- apr_int64_t value = 0, old_value, last_value = 0;
- apr_int64_t counter;
- svn_boolean_t done = FALSE;
-
- /* Pass the tokens along */
-
- do
- {
- /* Wait for and consume incoming token. */
- do
- {
- SVN_ERR(svn_named_atomic__write(&value, 0, atomic_in));
- SVN_ERR(check_watchdog(watchdog, &done));
- if (done) return SVN_NO_ERROR;
- }
- while (value == 0);
-
- /* All tokes must come in in the same order */
- SVN_TEST_ASSERT((last_value % count) == (value - 1));
- last_value = value;
-
- /* Wait for the target atomic to become vacant and write the token */
- do
- {
- SVN_ERR(svn_named_atomic__cmpxchg(&old_value,
- value,
- 0,
- atomic_out));
- SVN_ERR(check_watchdog(watchdog, &done));
- if (done) return SVN_NO_ERROR;
- }
- while (old_value != 0);
-
- /* Count the number of operations */
- SVN_ERR(svn_named_atomic__add(&counter, 1, atomic_counter));
- }
- while (counter < iterations);
-
- /* done */
-
- return SVN_NO_ERROR;
-}
-
-/* "pipeline" test: worker with ID 0 initializes the data; all workers
- * (COUNT in total) have one input and one output bucket that form a ring
- * spanning all workers. Each worker passes the value along ITERATIONS times.
- */
-static svn_error_t *
-test_pipeline(int id, int count, int iterations, apr_pool_t *pool)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic_in;
- svn_named_atomic__t *atomic_out;
- svn_named_atomic__t *atomic_counter;
- svn_error_t *err = SVN_NO_ERROR;
- watchdog_t watchdog;
-
- /* get the two I/O atomics for this thread */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, pool));
- SVN_ERR(svn_named_atomic__get(&atomic_in,
- ns,
- apr_pstrcat(pool,
- ATOMIC_NAME,
- apr_itoa(pool,
- id),
- NULL),
- FALSE));
- SVN_ERR(svn_named_atomic__get(&atomic_out,
- ns,
- apr_pstrcat(pool,
- ATOMIC_NAME,
- apr_itoa(pool,
- (id + 1) % count),
- NULL),
- FALSE));
-
- /* our iteration counter */
- SVN_ERR(svn_named_atomic__get(&atomic_counter, ns, "counter", FALSE));
-
- /* safeguard our execution time. Limit it to 20s */
- init_watchdog(&watchdog, atomic_counter, iterations, 20000000);
-
- /* fill pipeline */
- if (id == 0)
- err = test_pipeline_prepare(atomic_out, count, &watchdog);
-
- /* Pass the tokens along */
- if (!err)
- err = test_pipeline_loop(atomic_in, atomic_out, atomic_counter,
- count, iterations, &watchdog);
-
- /* if we experienced an error, cause everybody to exit */
- if (err)
- svn_error_clear(svn_named_atomic__write(NULL, iterations, atomic_counter));
-
- /* done */
-
- return err;
-}
diff --git a/subversion/tests/libsvn_subr/named_atomic-test-proc.c b/subversion/tests/libsvn_subr/named_atomic-test-proc.c
deleted file mode 100644
index 534247c..0000000
--- a/subversion/tests/libsvn_subr/named_atomic-test-proc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * named_atomic-test-proc.c: a collection of svn_named_atomic__t 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>
-
-/* shared test implementation */
-#include "named_atomic-test-common.h"
-
-/* Very simple process frame around the actual test code */
-int
-main(int argc, const char *argv[])
-{
- svn_boolean_t got_error = FALSE;
- apr_pool_t *pool;
- svn_error_t *err;
-
- int id = 0;
- int count = 0;
- int iterations = 0;
-
- /* Initialize APR (Apache pools) */
- if (apr_initialize() != APR_SUCCESS)
- {
- printf("apr_initialize() failed.\n");
- exit(1);
- }
-
- pool = svn_pool_create(NULL);
-
- /* lean & mean parameter parsing */
- if (argc != 5)
- {
- if (argc == 1) /* used to test that this executable can be started */
- exit(0);
-
- printf("Usage: named_atomic-proc-test ID COUNT ITERATIONS NS.\n");
- exit(1);
- }
-
- id = (int)apr_atoi64(argv[1]);
- count = (int)apr_atoi64(argv[2]);
- iterations = (int)apr_atoi64(argv[3]);
- name_namespace = argv[4];
-
- /* run test routine */
-
- err = test_pipeline(id, count, iterations, pool);
- if (err)
- {
- const char *prefix = apr_psprintf(pool, "Process %d: ", id);
- got_error = TRUE;
- svn_handle_error2(err, stdout, FALSE, prefix);
- svn_error_clear(err);
- }
-
- /* Clean up APR */
- svn_pool_destroy(pool);
- apr_terminate();
-
- return got_error;
-}
diff --git a/subversion/tests/libsvn_subr/named_atomic-test.c b/subversion/tests/libsvn_subr/named_atomic-test.c
deleted file mode 100644
index 05604d2..0000000
--- a/subversion/tests/libsvn_subr/named_atomic-test.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * named_atomic-test.c: a collection of svn_named_atomic__t 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 <apr_file_io.h>
-
-#include "svn_io.h"
-
-/* shared test implementation */
-#include "named_atomic-test-common.h"
-
-/* Name of the worker process executable */
-#define TEST_PROC "named_atomic-proc-test"
-
-/* number of hardware threads (logical cores) that we may use.
- * Will be set to at least 2 - even on unicore machines. */
-static int hw_thread_count = 0;
-
-/* number of iterations that we should perform on concurrency tests
- * (will be calibrated to about 1s runtime)*/
-static int suggested_iterations = 0;
-
-/* If possible, translate PROC to a global path and set DIRECTORY to
- * the current directory.
- */
-static svn_error_t *
-adjust_proc_path(const char **proc, const char **directory, apr_pool_t *pool)
-{
-#ifdef WIN32
- /* Under Windows, the test will not be in the current directory
- * and neither will be PROC. Therefore, determine its full path */
- char path [MAX_PATH] = { 0 };
- GetModuleFileNameA(NULL, path, sizeof(path));
- *(strrchr(path, '\\') + 1) = 0;
- *proc = apr_pstrcat(pool, path, *proc, ".exe", NULL);
-
- /* And we need to set the working dir to our working dir to make
- * our sub-processes find all DLLs. */
- GetCurrentDirectoryA(sizeof(path), path);
- *directory = apr_pstrdup(pool, path);
-#endif
-
- return SVN_NO_ERROR;
-}
-
-/* Returns true if PROC can be found and executed.
- */
-static svn_boolean_t
-proc_found(const char *proc, apr_pool_t *pool)
-{
- static svn_tristate_t result = svn_tristate_unknown;
-
- if (result == svn_tristate_unknown)
- {
- svn_error_t *error = SVN_NO_ERROR;
- const char * directory = NULL;
-
- /* all processes and their I/O data */
- apr_proc_t process;
- const char * args[2];
-
- args[0] = proc;
- args[1] = NULL;
- svn_error_clear(adjust_proc_path(&args[0], &directory, pool));
-
- /* try to start the process */
- error = svn_io_start_cmd3(&process,
- directory, /* working directory */
- args[0],
- args,
- NULL, /* environment */
- FALSE, /* no handle inheritance */
- FALSE, /* no STDIN pipe */
- NULL,
- FALSE, /* no STDOUT pipe */
- NULL,
- FALSE, /* no STDERR pipe */
- NULL,
- pool);
- if (!error)
- error = svn_io_wait_for_cmd(&process, proc, NULL, NULL, pool);
-
- result = error ? svn_tristate_false : svn_tristate_true;
- svn_error_clear(error);
- }
-
- return result == svn_tristate_true;
-}
-
-/* Remove temporary files from disk.
- */
-static apr_status_t
-cleanup_test_shm(void *arg)
-{
- apr_pool_t *pool = arg;
-
- svn_error_clear(svn_atomic_namespace__cleanup(name_namespace, pool));
- svn_error_clear(svn_atomic_namespace__cleanup(name_namespace1, pool));
- svn_error_clear(svn_atomic_namespace__cleanup(name_namespace2, pool));
-
- return 0;
-}
-
-/* Bring shared memory to a defined state. This is very useful in case of
- * lingering problems from previous tests or test runs.
- */
-static svn_error_t *
-init_test_shm(apr_pool_t *pool)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic;
- apr_pool_t *scratch = svn_pool_create(pool);
-
- if (name_namespace == NULL)
- {
- apr_pool_t *global_pool = svn_pool_create(NULL);
- SVN_ERR(svn_io_open_unique_file3(NULL,
- &name_namespace,
- NULL,
- svn_io_file_del_on_pool_cleanup,
- global_pool,
- pool));
- SVN_ERR(svn_io_open_unique_file3(NULL,
- &name_namespace1,
- NULL,
- svn_io_file_del_on_pool_cleanup,
- global_pool,
- pool));
- SVN_ERR(svn_io_open_unique_file3(NULL,
- &name_namespace2,
- NULL,
- svn_io_file_del_on_pool_cleanup,
- global_pool,
- pool));
- }
-
- /* skip tests if the current user does not have the required privileges */
- if (!svn_named_atomic__is_supported())
- return svn_error_wrap_apr(SVN_ERR_TEST_SKIPPED,
- "user has insufficient privileges");
-
- /* destroy temp files after usage */
-
- apr_pool_cleanup_register(pool, pool,
- cleanup_test_shm, apr_pool_cleanup_null);
-
- /* get the two I/O atomics for this thread */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, scratch));
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME "1", TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME "2", TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
-
- svn_pool_clear(scratch);
-
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace1, scratch));
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- svn_pool_clear(scratch);
-
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace2, scratch));
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- svn_pool_clear(scratch);
-
- /* done */
-
- return SVN_NO_ERROR;
-}
-
-/* Prepare the shared memory for a run with COUNT workers.
- */
-static svn_error_t *
-init_concurrency_test_shm(apr_pool_t *pool, int count)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic;
- int i;
-
- /* get the two I/O atomics for this thread */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, pool));
-
- /* reset the I/O atomics for all threads */
- for (i = 0; i < count; ++i)
- {
- SVN_ERR(svn_named_atomic__get(&atomic,
- ns,
- apr_pstrcat(pool,
- ATOMIC_NAME,
- apr_itoa(pool, i),
- NULL),
- TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- }
-
- SVN_ERR(svn_named_atomic__get(&atomic, ns, "counter", TRUE));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
-
- return SVN_NO_ERROR;
-}
-
-#if APR_HAS_THREADS
-
-/* our thread function type
- */
-typedef svn_error_t *(*thread_func_t)(int, int, int, apr_pool_t *);
-
-/* Per-thread input and output data.
- */
-struct thread_baton
-{
- int thread_count;
- int thread_no;
- int iterations;
- svn_error_t *result;
- thread_func_t func;
-};
-
-/* APR thread function implementation: A wrapper around baton->func that
- * handles the svn_error_t return value.
- */
-static void *
-APR_THREAD_FUNC test_thread(apr_thread_t *thread, void *baton)
-{
- struct thread_baton *params = baton;
- apr_pool_t *pool = svn_pool_create_ex(NULL, NULL);
-
- params->result = (*params->func)(params->thread_no,
- params->thread_count,
- params->iterations,
- pool);
- svn_pool_destroy(pool);
- apr_thread_exit(thread, APR_SUCCESS);
-
- return NULL;
-}
-
-/* Runs FUNC in COUNT concurrent threads ITERATION times and combines the
- * results.
- */
-static svn_error_t *
-run_threads(apr_pool_t *pool, int count, int iterations, thread_func_t func)
-{
- apr_status_t status;
- int i;
- svn_error_t *error = SVN_NO_ERROR;
-
- /* all threads and their I/O data */
- apr_thread_t **threads = apr_palloc(pool, count * sizeof(*threads));
- struct thread_baton *batons = apr_palloc(pool, count * sizeof(*batons));
-
- /* start threads */
- for (i = 0; i < count; ++i)
- {
- batons[i].thread_count = count;
- batons[i].thread_no = i;
- batons[i].iterations = iterations;
- batons[i].func = func;
-
- status = apr_thread_create(&threads[i],
- NULL,
- test_thread,
- &batons[i],
- pool);
- if (status != APR_SUCCESS)
- SVN_ERR(svn_error_wrap_apr(status, "could not create a thread"));
- }
-
- /* Wait for threads to finish and return result. */
- for (i = 0; i < count; ++i)
- {
- apr_status_t retval;
- status = apr_thread_join(&retval, threads[i]);
- if (status != APR_SUCCESS)
- SVN_ERR(svn_error_wrap_apr(status, "waiting for thread's end failed"));
-
- if (batons[i].result)
- error = svn_error_compose_create (error, svn_error_quick_wrap
- (batons[i].result, apr_psprintf(pool, "Thread %d failed", i)));
- }
-
- return error;
-}
-#endif
-
-/* Runs PROC in COUNT concurrent worker processes and check the results.
- */
-static svn_error_t *
-run_procs(apr_pool_t *pool, const char *proc, int count, int iterations)
-{
- int i, k;
- svn_error_t *error = SVN_NO_ERROR;
- const char * directory = NULL;
-
- /* all processes and their I/O data */
- apr_proc_t *process = apr_palloc(pool, count * sizeof(*process));
- apr_file_t *common_stdout = NULL;
- apr_file_open_stdout(&common_stdout, pool);
-
- SVN_ERR(adjust_proc_path(&proc, &directory, pool));
-
- /* start sub-processes */
- for (i = 0; i < count; ++i)
- {
- const char * args[6];
-
- args[0] = proc;
- args[1] = apr_itoa(pool, i);
- args[2] = apr_itoa(pool, count);
- args[3] = apr_itoa(pool, iterations);
- args[4] = name_namespace;
- args[5] = NULL;
-
- error = svn_io_start_cmd3(&process[i],
- directory, /* working directory */
- args[0],
- args,
- NULL, /* environment */
- FALSE, /* no handle inheritance */
- FALSE, /* no STDIN pipe */
- NULL,
- FALSE, /* consolidate into 1 STDOUT */
- common_stdout,
- FALSE, /* no STDERR pipe */
- NULL,
- pool);
- if (error)
- {
- /* dump program name and parameters */
- for (k = 0; k < sizeof(args) / sizeof(args[0]); ++k)
- if (args[k])
- printf(k == 0 ? "%s\n" : " %s\n", args[k]);
-
- if (directory)
- printf("working folder %s:\n", directory);
-
- return error;
- }
- }
-
- /* Wait for sub-processes to finish and return result. */
- for (i = 0; i < count; ++i)
- {
- const char *cmd = apr_psprintf(pool,
- "named_atomic-test-proc %d %d %d",
- i, count, iterations);
- error = svn_error_compose_create(error,
- svn_io_wait_for_cmd(&process[i],
- cmd, NULL, NULL,
- pool));
- }
-
- return error;
-}
-
-/* Set SUGGESTED_ITERATIONS to a value that COUNT workers will take
- * about 1 second to execute.
- */
-static svn_error_t *
-calibrate_iterations(apr_pool_t *pool, int count)
-{
- apr_time_t start;
- int calib_iterations;
- double taken = 0.0;
-
- /* increase iterations until we pass the 100ms mark */
-
- for (calib_iterations = 10; taken < 100000.0; calib_iterations *= 2)
- {
- apr_pool_t *scratch = svn_pool_create(pool);
- SVN_ERR(init_concurrency_test_shm(scratch, count));
-
- start = apr_time_now();
- SVN_ERR(run_procs(pool, TEST_PROC, count, calib_iterations));
-
- taken = (double)(apr_time_now() - start);
- svn_pool_destroy(scratch);
- }
-
- /* scale that to 1s */
-
- suggested_iterations = (int)(1000000.0 / taken * calib_iterations);
-
- return SVN_NO_ERROR;
-}
-
-/* Find out how far the system will scale, i.e. how many workers can be
- * run concurrently without experiencing significant slowdowns.
- * Sets HW_THREAD_COUNT to a value of 2 .. 32 (limit the system impact in
- * case our heuristics fail) and determines the number of iterations.
- * Can be called multiple times but will skip the calculations after the
- * first successful run.
- */
-static svn_error_t *
-calibrate_concurrency(apr_pool_t *pool)
-{
- if (hw_thread_count == 0)
- {
- /* these parameters should be ok even on very slow machines */
- hw_thread_count = 2;
- suggested_iterations = 100;
-
- /* if we've got a proper machine and OS setup, let's prepare for
- * some real testing */
- if (svn_named_atomic__is_efficient() && proc_found(TEST_PROC, pool))
- {
- SVN_ERR(calibrate_iterations(pool, 2));
- for (; hw_thread_count < 32; hw_thread_count *= 2)
- {
- int saved_suggestion = suggested_iterations;
-
- /* run with an additional core to spare
- * (even low CPU usage might cause heavy context switching) */
- SVN_ERR(calibrate_iterations(pool, hw_thread_count * 2 + 1));
- if (suggested_iterations < 100000)
- {
- /* Machines with only a small number of cores are prone
- * to inconsistent performance due context switching.
- * Reduce the number of iterations on those machines. */
- suggested_iterations = hw_thread_count > 2
- ? saved_suggestion
- : saved_suggestion / 2;
- break;
- }
- }
- }
-
- printf("using %d cores for %d iterations\n", hw_thread_count,
- suggested_iterations);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* The individual tests */
-
-static svn_error_t *
-test_basics(apr_pool_t *pool)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic;
- apr_int64_t value;
-
- SVN_ERR(init_test_shm(pool));
-
- /* Use a separate namespace for our tests isolate them from production */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, pool));
-
- /* Test a non-existing atomic */
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME "x", FALSE));
- SVN_TEST_ASSERT(atomic == NULL);
-
- /* Now, we auto-create it */
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
- SVN_TEST_ASSERT(atomic != NULL);
-
- /* The default value should be 0 */
- SVN_TEST_ASSERT_ERROR(svn_named_atomic__read(&value, NULL),
- SVN_ERR_BAD_ATOMIC);
- value = 1;
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 0);
-
- /* Write should return the previous value. */
- SVN_TEST_ASSERT_ERROR(svn_named_atomic__write(&value, 0, NULL),
- SVN_ERR_BAD_ATOMIC);
- value = 1;
- SVN_ERR(svn_named_atomic__write(&value, 21, atomic));
- SVN_TEST_ASSERT(value == 0);
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 21);
-
- SVN_ERR(svn_named_atomic__write(&value, 42, atomic));
- SVN_TEST_ASSERT(value == 21);
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 42);
-
- SVN_ERR(svn_named_atomic__write(NULL, 17, atomic));
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 17);
-
- /* Adding & subtracting values */
- SVN_TEST_ASSERT_ERROR(svn_named_atomic__add(&value, 0, NULL),
- SVN_ERR_BAD_ATOMIC);
- SVN_ERR(svn_named_atomic__add(&value, 25, atomic));
- SVN_TEST_ASSERT(value == 42);
- SVN_ERR(svn_named_atomic__add(NULL, 47, atomic));
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 89);
-
- SVN_ERR(svn_named_atomic__add(&value, -25, atomic));
- SVN_TEST_ASSERT(value == 64);
- SVN_ERR(svn_named_atomic__add(NULL, -22, atomic));
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 42);
-
- /* Compare-and-exchange */
- SVN_TEST_ASSERT_ERROR(svn_named_atomic__cmpxchg(&value, 0, 0, NULL),
- SVN_ERR_BAD_ATOMIC);
- value = 1;
- SVN_ERR(svn_named_atomic__cmpxchg(&value, 99, 41, atomic));
- SVN_TEST_ASSERT(value == 42);
-
- value = 1;
- SVN_ERR(svn_named_atomic__cmpxchg(&value, 98, 42, atomic));
- SVN_TEST_ASSERT(value == 42);
- SVN_ERR(svn_named_atomic__cmpxchg(&value, 67, 98, atomic));
- SVN_TEST_ASSERT(value == 98);
-
- SVN_ERR(svn_named_atomic__cmpxchg(NULL, 42, 67, atomic));
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 42);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-test_bignums(apr_pool_t *pool)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic;
- apr_int64_t value;
-
- SVN_ERR(init_test_shm(pool));
-
- /* Use a separate namespace for our tests isolate them from production */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, pool));
-
- /* Auto-create our atomic variable */
- SVN_ERR(svn_named_atomic__get(&atomic, ns, ATOMIC_NAME, TRUE));
- SVN_TEST_ASSERT(atomic != NULL);
-
- /* Write should return the previous value. */
-
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic));
- value = 1;
- SVN_ERR(svn_named_atomic__write(&value, 21 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 0 * HUGE_VALUE);
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 21 * HUGE_VALUE);
-
- SVN_ERR(svn_named_atomic__write(&value, 17 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 21 * HUGE_VALUE);
-
- /* Adding & subtracting values */
- SVN_ERR(svn_named_atomic__add(&value, 25 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 42 * HUGE_VALUE);
- SVN_ERR(svn_named_atomic__add(&value, -25 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 17 * HUGE_VALUE);
-
- /* Compare-and-exchange */
- value = 1;
- SVN_ERR(svn_named_atomic__cmpxchg(&value, 99 * HUGE_VALUE, 41 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 17 * HUGE_VALUE);
-
- value = 1;
- SVN_ERR(svn_named_atomic__cmpxchg(&value, 98 * HUGE_VALUE, 17 * HUGE_VALUE, atomic));
- SVN_TEST_ASSERT(value == 17 * HUGE_VALUE);
- SVN_ERR(svn_named_atomic__read(&value, atomic));
- SVN_TEST_ASSERT(value == 98 * HUGE_VALUE);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-test_multiple_atomics(apr_pool_t *pool)
-{
- svn_atomic_namespace__t *ns;
- svn_named_atomic__t *atomic1;
- svn_named_atomic__t *atomic2;
- svn_named_atomic__t *atomic1_alias;
- svn_named_atomic__t *atomic2_alias;
- apr_int64_t value1;
- apr_int64_t value2;
-
- SVN_ERR(init_test_shm(pool));
-
- /* Use a separate namespace for our tests isolate them from production */
- SVN_ERR(svn_atomic_namespace__create(&ns, name_namespace, pool));
-
- /* Create two atomics */
- SVN_ERR(svn_named_atomic__get(&atomic1, ns, ATOMIC_NAME "1", TRUE));
- SVN_ERR(svn_named_atomic__get(&atomic2, ns, ATOMIC_NAME "2", TRUE));
- SVN_TEST_ASSERT(atomic1 != NULL);
- SVN_TEST_ASSERT(atomic2 != NULL);
- SVN_TEST_ASSERT(atomic1 != atomic2);
-
- /* Get aliases to those */
- SVN_ERR(svn_named_atomic__get(&atomic1_alias, ns, ATOMIC_NAME "1", TRUE));
- SVN_ERR(svn_named_atomic__get(&atomic2_alias, ns, ATOMIC_NAME "2", TRUE));
- SVN_TEST_ASSERT(atomic1 == atomic1_alias);
- SVN_TEST_ASSERT(atomic2 == atomic2_alias);
-
- /* The atomics shall not overlap, i.e. changes to one do not affect the other */
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic1));
- SVN_ERR(svn_named_atomic__write(NULL, 0, atomic2));
- SVN_ERR(svn_named_atomic__write(&value1, 21 * HUGE_VALUE, atomic1));
- SVN_ERR(svn_named_atomic__write(&value2, 42 * HUGE_VALUE, atomic2));
- SVN_TEST_ASSERT(value1 == 0);
- SVN_TEST_ASSERT(value2 == 0);
-
- SVN_ERR(svn_named_atomic__read(&value1, atomic1));
- SVN_ERR(svn_named_atomic__read(&value2, atomic2));
- SVN_TEST_ASSERT(value1 == 21 * HUGE_VALUE);
- SVN_TEST_ASSERT(value2 == 42 * HUGE_VALUE);
-
- SVN_ERR(svn_named_atomic__add(&value1, 25 * HUGE_VALUE, atomic1));
- SVN_ERR(svn_named_atomic__add(&value2, -25 * HUGE_VALUE, atomic2));
- SVN_TEST_ASSERT(value1 == 46 * HUGE_VALUE);
- SVN_TEST_ASSERT(value2 == 17 * HUGE_VALUE);
-
- value1 = 1;
- value2 = 1;
- SVN_ERR(svn_named_atomic__cmpxchg(&value1, 4 * HUGE_VALUE, 46 * HUGE_VALUE, atomic1));
- SVN_ERR(svn_named_atomic__cmpxchg(&value2, 98 * HUGE_VALUE, 17 * HUGE_VALUE, atomic2));
- SVN_TEST_ASSERT(value1 == 46 * HUGE_VALUE);
- SVN_TEST_ASSERT(value2 == 17 * HUGE_VALUE);
-
- SVN_ERR(svn_named_atomic__read(&value1, atomic1));
- SVN_ERR(svn_named_atomic__read(&value2, atomic2));
- SVN_TEST_ASSERT(value1 == 4 * HUGE_VALUE);
- SVN_TEST_ASSERT(value2 == 98 * HUGE_VALUE);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-test_namespaces(apr_pool_t *pool)
-{
- svn_atomic_namespace__t *test_namespace1;
- svn_atomic_namespace__t *test_namespace1_alias;
- svn_atomic_namespace__t *test_namespace2;
- svn_atomic_namespace__t *test_namespace2_alias;
- svn_named_atomic__t *atomic1;
- svn_named_atomic__t *atomic2;
- svn_named_atomic__t *atomic1_alias;
- svn_named_atomic__t *atomic2_alias;
- apr_int64_t value;
-
- SVN_ERR(init_test_shm(pool));
-
- /* Use a separate namespace for our tests isolate them from production */
- SVN_ERR(svn_atomic_namespace__create(&test_namespace1, name_namespace1, pool));
- SVN_ERR(svn_atomic_namespace__create(&test_namespace1_alias, name_namespace1, pool));
- SVN_ERR(svn_atomic_namespace__create(&test_namespace2, name_namespace2, pool));
- SVN_ERR(svn_atomic_namespace__create(&test_namespace2_alias, name_namespace2, pool));
-
- /* Create two atomics with the same name in different namespaces */
- SVN_ERR(svn_named_atomic__get(&atomic1, test_namespace1, ATOMIC_NAME, TRUE));
- SVN_ERR(svn_named_atomic__get(&atomic1_alias, test_namespace1_alias, ATOMIC_NAME, FALSE));
- SVN_ERR(svn_named_atomic__get(&atomic2, test_namespace2, ATOMIC_NAME, TRUE));
- SVN_ERR(svn_named_atomic__get(&atomic2_alias, test_namespace2_alias, ATOMIC_NAME, FALSE));
- SVN_TEST_ASSERT(atomic1 != atomic1_alias);
- SVN_TEST_ASSERT(atomic1_alias != NULL);
- SVN_TEST_ASSERT(atomic2 != atomic2_alias);
- SVN_TEST_ASSERT(atomic2_alias != NULL);
-
- /* Write data to our atomics */
- SVN_ERR(svn_named_atomic__write(NULL, 21 * HUGE_VALUE, atomic1));
- SVN_ERR(svn_named_atomic__write(NULL, 42 * HUGE_VALUE, atomic2));
-
- /* Now check who sees which value */
- SVN_ERR(svn_named_atomic__read(&value, atomic1));
- SVN_TEST_ASSERT(value == 21 * HUGE_VALUE);
- SVN_ERR(svn_named_atomic__read(&value, atomic2));
- SVN_TEST_ASSERT(value == 42 * HUGE_VALUE);
-
- SVN_ERR(svn_named_atomic__read(&value, atomic1_alias));
- SVN_TEST_ASSERT(value == 21 * HUGE_VALUE);
- SVN_ERR(svn_named_atomic__read(&value, atomic2_alias));
- SVN_TEST_ASSERT(value == 42 * HUGE_VALUE);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-test_multithreaded(apr_pool_t *pool)
-{
-#if APR_HAS_THREADS
- SVN_ERR(init_test_shm(pool));
-
- SVN_ERR(calibrate_concurrency(pool));
-
- SVN_ERR(init_concurrency_test_shm(pool, hw_thread_count));
- SVN_ERR(run_threads(pool, hw_thread_count, suggested_iterations, test_pipeline));
-
- return SVN_NO_ERROR;
-#else
- return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
-#endif
-}
-
-static svn_error_t *
-test_multiprocess(apr_pool_t *pool)
-{
- if (!proc_found(TEST_PROC, pool))
- return svn_error_wrap_apr(SVN_ERR_TEST_SKIPPED,
- "executable '%s' not found", TEST_PROC);
-
- SVN_ERR(init_test_shm(pool));
-
- SVN_ERR(calibrate_concurrency(pool));
-
- SVN_ERR(init_concurrency_test_shm(pool, hw_thread_count));
- SVN_ERR(run_procs(pool, TEST_PROC, hw_thread_count, suggested_iterations));
-
- return SVN_NO_ERROR;
-}
-
-/*
- ====================================================================
- If you add a new test to this file, update this array.
-
- (These globals are required by our included main())
-*/
-
-/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
- {
- SVN_TEST_NULL,
- SVN_TEST_PASS2(test_basics,
- "basic r/w access to a single atomic"),
- SVN_TEST_PASS2(test_bignums,
- "atomics must be 64 bits"),
- SVN_TEST_PASS2(test_multiple_atomics,
- "basic r/w access to multiple atomics"),
- SVN_TEST_PASS2(test_namespaces,
- "use different namespaces"),
- SVN_TEST_PASS2(test_multithreaded,
- "multithreaded access to atomics"),
- SVN_TEST_PASS2(test_multiprocess,
- "multi-process access to atomics"),
- SVN_TEST_NULL
- };
diff --git a/subversion/tests/libsvn_subr/opt-test.c b/subversion/tests/libsvn_subr/opt-test.c
index a7c570a..c336d81 100644
--- a/subversion/tests/libsvn_subr/opt-test.c
+++ b/subversion/tests/libsvn_subr/opt-test.c
@@ -193,7 +193,9 @@ test_svn_opt_args_to_target_array2(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_parse_peg_rev,
@@ -202,3 +204,5 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_opt_args_to_target_array2"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/packed-data-test.c b/subversion/tests/libsvn_subr/packed-data-test.c
new file mode 100644
index 0000000..d5d6a20
--- /dev/null
+++ b/subversion/tests/libsvn_subr/packed-data-test.c
@@ -0,0 +1,577 @@
+/*
+ * packed-data-test.c: a collection of svn_packed__* 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_error.h"
+#include "svn_string.h" /* This includes <apr_*.h> */
+#include "private/svn_packed_data.h"
+
+/* Take the WRITE_ROOT, serialize its contents, parse it again into a new
+ * data root and return it in *READ_ROOT. Allocate it in POOL.
+ */
+static svn_error_t*
+get_read_root(svn_packed__data_root_t **read_root,
+ svn_packed__data_root_t *write_root,
+ 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_packed__data_write(stream, write_root, pool));
+ SVN_ERR(svn_stream_close(stream));
+
+ stream = svn_stream_from_stringbuf(stream_buffer, pool);
+ SVN_ERR(svn_packed__data_read(read_root, stream, pool, pool));
+ SVN_ERR(svn_stream_close(stream));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_empty_container(apr_pool_t *pool)
+{
+ /* create an empty, readable container */
+ svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+ SVN_ERR(get_read_root(&root, root, pool));
+
+ /* there should be no sub-streams */
+ SVN_TEST_ASSERT(svn_packed__first_int_stream(root) == NULL);
+ SVN_TEST_ASSERT(svn_packed__first_byte_stream(root) == NULL);
+
+ return SVN_NO_ERROR;
+}
+
+/* Check that COUNT numbers from VALUES can be written as uints to a
+ * packed data stream and can be read from that stream again. Deltify
+ * data in the stream if DIFF is set. Use POOL for allocations.
+ */
+static svn_error_t *
+verify_uint_stream(const apr_uint64_t *values,
+ apr_size_t count,
+ svn_boolean_t diff,
+ apr_pool_t *pool)
+{
+ svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+ svn_packed__int_stream_t *stream
+ = svn_packed__create_int_stream(root, diff, FALSE);
+
+ apr_size_t i;
+ for (i = 0; i < count; ++i)
+ svn_packed__add_uint(stream, values[i]);
+
+ SVN_ERR(get_read_root(&root, root, pool));
+
+ /* the container should contain exactly one int stream */
+ stream = svn_packed__first_int_stream(root);
+ SVN_TEST_ASSERT(stream);
+ SVN_TEST_ASSERT(!svn_packed__next_int_stream(stream));
+ SVN_TEST_ASSERT(!svn_packed__first_byte_stream(root));
+
+ /* the stream shall contain exactly the items we put into it */
+ SVN_TEST_ASSERT(svn_packed__int_count(stream) == count);
+ for (i = 0; i < count; ++i)
+ SVN_TEST_ASSERT(svn_packed__get_uint(stream) == values[i]);
+
+ /* reading beyond eos should return 0 values */
+ SVN_TEST_ASSERT(svn_packed__get_uint(stream) == 0);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_uint_stream(apr_pool_t *pool)
+{
+ enum { COUNT = 8 };
+ const apr_uint64_t values[COUNT] =
+ {
+ APR_UINT64_MAX,
+ 0,
+ APR_UINT64_MAX,
+ APR_UINT64_C(0x8000000000000000),
+ 0,
+ APR_UINT64_C(0x7fffffffffffffff),
+ APR_UINT64_C(0x1234567890abcdef),
+ APR_UINT64_C(0x0fedcba987654321),
+ };
+
+ SVN_ERR(verify_uint_stream(values, COUNT, FALSE, pool));
+ SVN_ERR(verify_uint_stream(values, COUNT, TRUE, pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Check that COUNT numbers from VALUES can be written as signed ints to a
+ * packed data stream and can be read from that stream again. Deltify
+ * data in the stream if DIFF is set. Use POOL for allocations.
+ */
+static svn_error_t *
+verify_int_stream(const apr_int64_t *values,
+ apr_size_t count,
+ svn_boolean_t diff,
+ apr_pool_t *pool)
+{
+ svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+ svn_packed__int_stream_t *stream
+ = svn_packed__create_int_stream(root, diff, TRUE);
+
+ apr_size_t i;
+ for (i = 0; i < count; ++i)
+ svn_packed__add_int(stream, values[i]);
+
+ SVN_ERR(get_read_root(&root, root, pool));
+
+ /* the container should contain exactly one int stream */
+ stream = svn_packed__first_int_stream(root);
+ SVN_TEST_ASSERT(stream);
+ SVN_TEST_ASSERT(!svn_packed__next_int_stream(stream));
+ SVN_TEST_ASSERT(!svn_packed__first_byte_stream(root));
+
+ /* the stream shall contain exactly the items we put into it */
+ SVN_TEST_ASSERT(svn_packed__int_count(stream) == count);
+ for (i = 0; i < count; ++i)
+ SVN_TEST_ASSERT(svn_packed__get_int(stream) == values[i]);
+
+ /* reading beyond eos should return 0 values */
+ SVN_TEST_ASSERT(svn_packed__get_int(stream) == 0);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_int_stream(apr_pool_t *pool)
+{
+ enum { COUNT = 7 };
+ const apr_int64_t values[COUNT] =
+ {
+ APR_INT64_MAX, /* extreme value */
+ APR_INT64_MIN, /* other extreme, creating maximum delta to predecessor */
+ 0, /* delta to predecessor > APR_INT64_MAX */
+ APR_INT64_MAX, /* max value, again */
+ -APR_INT64_MAX, /* _almost_ min value, almost max delta */
+ APR_INT64_C(0x1234567890abcdef), /* some arbitrary value */
+ -APR_INT64_C(0x0fedcba987654321), /* arbitrary value, different sign */
+ };
+
+ SVN_ERR(verify_int_stream(values, COUNT, FALSE, pool));
+ SVN_ERR(verify_int_stream(values, COUNT, TRUE, pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_byte_stream(apr_pool_t *pool)
+{
+ enum { COUNT = 6 };
+ const svn_string_t values[COUNT] =
+ {
+ { "", 0 },
+ { "\0", 1 },
+ { "\0", 1 },
+ { "some text", 9 },
+ { "", 0 },
+ { "some more", 9 }
+ };
+
+ svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+ svn_packed__byte_stream_t *stream
+ = svn_packed__create_bytes_stream(root);
+
+ apr_size_t i;
+ for (i = 0; i < COUNT; ++i)
+ svn_packed__add_bytes(stream, values[i].data, values[i].len);
+
+ SVN_ERR(get_read_root(&root, root, pool));
+
+ /* the container should contain exactly one byte stream */
+ stream = svn_packed__first_byte_stream(root);
+ SVN_TEST_ASSERT(stream);
+ SVN_TEST_ASSERT(!svn_packed__next_byte_stream(stream));
+
+ /* the stream shall contain exactly the items we put into it */
+ SVN_TEST_ASSERT(svn_packed__byte_count(stream) == 20);
+ for (i = 0; i < COUNT; ++i)
+ {
+ svn_string_t string;
+ string.data = svn_packed__get_bytes(stream, &string.len);
+
+ SVN_TEST_ASSERT(string.len == values[i].len);
+ SVN_TEST_ASSERT(!memcmp(string.data, values[i].data, string.len));
+ }
+
+ /* reading beyond eos should return 0 values */
+ SVN_TEST_ASSERT(svn_packed__byte_count(stream) == 0);
+
+ return SVN_NO_ERROR;
+}
+
+/* Some simple structure that we use as sub-structure to BASE_RECORD_T.
+ * Have it contain numbers and strings.
+ */
+typedef struct sub_record_t
+{
+ int sub_counter;
+ svn_string_t text;
+} sub_record_t;
+
+/* signed / unsigned, 64 bits and shorter, diff-able and not, multiple
+ * strings, multiple sub-records. */
+typedef struct base_record_t
+{
+ int counter;
+ svn_string_t description;
+ apr_uint64_t large_unsigned1;
+ apr_uint64_t large_unsigned2;
+ const sub_record_t *left_subs;
+ apr_int64_t large_signed1;
+ apr_int64_t large_signed2;
+ unsigned prime;
+ const sub_record_t *right_subs;
+ svn_string_t binary;
+} base_record_t;
+
+/* our test data */
+enum {SUB_RECORD_COUNT = 7};
+enum {BASE_RECORD_COUNT = 4};
+
+static const sub_record_t sub_records[SUB_RECORD_COUNT] =
+{
+ { 6, { "this is quite a longish piece of text", 37} },
+ { 5, { "x", 1} },
+ { 4, { "not empty", 9} },
+ { 3, { "another bit of text", 19} },
+ { 2, { "", 0} },
+ { 1, { "first sub-record", 16} },
+ { 0 }
+};
+
+static const base_record_t test_data[BASE_RECORD_COUNT] =
+{
+ { 1, { "maximum", 7},
+ APR_UINT64_MAX, APR_UINT64_MAX, sub_records,
+ APR_INT64_MAX, APR_INT64_MAX, 9967, sub_records + 1,
+ { "\0\1\2\3\4\5\6\7\x8\x9\xa", 11} },
+
+ { 2, { "minimum", 7},
+ 0, 0, sub_records + 6,
+ APR_INT64_MIN, APR_INT64_MIN, 6029, sub_records + 5,
+ { "X\0\0Y", 4} },
+
+ { 3, { "mean", 4},
+ APR_UINT64_C(0x8000000000000000), APR_UINT64_C(0x8000000000000000),
+ sub_records + 2,
+ 0, 0, 653, sub_records + 3,
+ { "\xff\0\1\2\3\4\5\6\7\x8\x9\xa", 12} },
+
+ { 4, { "random", 6},
+ APR_UINT64_C(0x1234567890abcdef), APR_UINT64_C(0xfedcba987654321),
+ sub_records + 4,
+ APR_INT64_C(0x1234567890abcd), APR_INT64_C(-0xedcba987654321), 7309,
+ sub_records + 1,
+ { "\x80\x7f\0\1\6", 5} }
+};
+
+/* Serialize RECORDS into INT_STREAM and TEXT_STREAM. Stop when the
+ * current record's SUB_COUNTER is 0.
+ */
+static unsigned
+pack_subs(svn_packed__int_stream_t *int_stream,
+ svn_packed__byte_stream_t *text_stream,
+ const sub_record_t *records)
+{
+ unsigned count;
+ for (count = 0; records[count].sub_counter; ++count)
+ {
+ svn_packed__add_int(int_stream, records[count].sub_counter);
+ svn_packed__add_bytes(text_stream,
+ records[count].text.data,
+ records[count].text.len);
+ }
+
+ return count;
+}
+
+/* Serialize COUNT records starting from DATA into a packed data container
+ * allocated in POOL and return the container root.
+ */
+static svn_packed__data_root_t *
+pack(const base_record_t *data,
+ apr_size_t count,
+ apr_pool_t *pool)
+{
+ apr_size_t i;
+ svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+ svn_packed__int_stream_t *base_stream
+ = svn_packed__create_int_stream(root, FALSE, FALSE);
+ svn_packed__int_stream_t *sub_count_stream
+ = svn_packed__create_int_stream(root, TRUE, FALSE);
+
+ svn_packed__int_stream_t *left_sub_stream
+ = svn_packed__create_int_stream(root, FALSE, TRUE);
+ svn_packed__int_stream_t *right_sub_stream
+ = svn_packed__create_int_stream(root, FALSE, TRUE);
+
+ svn_packed__byte_stream_t *base_description_stream
+ = svn_packed__create_bytes_stream(root);
+ svn_packed__byte_stream_t *base_binary_stream
+ = svn_packed__create_bytes_stream(root);
+ svn_packed__byte_stream_t *sub_text_stream
+ = svn_packed__create_bytes_stream(root);
+
+ svn_packed__create_int_substream(base_stream, TRUE, TRUE); /* counter */
+ svn_packed__create_int_substream(base_stream, TRUE, FALSE); /* large_unsigned1 */
+ svn_packed__create_int_substream(base_stream, FALSE, FALSE); /* large_unsigned2 */
+ svn_packed__create_int_substream(base_stream, TRUE, TRUE); /* large_signed1 */
+ svn_packed__create_int_substream(base_stream, FALSE, TRUE); /* large_signed2 */
+ svn_packed__create_int_substream(base_stream, TRUE, FALSE); /* prime */
+
+ for (i = 0; i < count; ++i)
+ {
+ svn_packed__add_int(base_stream, data[i].counter);
+ svn_packed__add_bytes(base_description_stream,
+ data[i].description.data,
+ data[i].description.len);
+ svn_packed__add_uint(base_stream, data[i].large_unsigned1);
+ svn_packed__add_uint(base_stream, data[i].large_unsigned2);
+ svn_packed__add_uint(sub_count_stream,
+ pack_subs(left_sub_stream, sub_text_stream,
+ data[i].left_subs));
+
+ svn_packed__add_int(base_stream, data[i].large_signed1);
+ svn_packed__add_int(base_stream, data[i].large_signed2);
+ svn_packed__add_uint(base_stream, data[i].prime);
+ svn_packed__add_uint(sub_count_stream,
+ pack_subs(right_sub_stream, sub_text_stream,
+ data[i].right_subs));
+
+ svn_packed__add_bytes(base_binary_stream,
+ data[i].binary.data,
+ data[i].binary.len);
+ }
+
+ return root;
+}
+
+/* Deserialize COUNT records from INT_STREAM and TEXT_STREAM and return
+ * the result allocated in POOL.
+ */
+static sub_record_t *
+unpack_subs(svn_packed__int_stream_t *int_stream,
+ svn_packed__byte_stream_t *text_stream,
+ apr_size_t count,
+ apr_pool_t *pool)
+{
+ sub_record_t *records = apr_pcalloc(pool, (count + 1) * sizeof(*records));
+
+ apr_size_t i;
+ for (i = 0; i < count; ++i)
+ {
+ records[i].sub_counter = (int) svn_packed__get_int(int_stream);
+ records[i].text.data = svn_packed__get_bytes(text_stream,
+ &records[i].text.len);
+ }
+
+ return records;
+}
+
+/* Deserialize all records from the packed data container ROOT, allocate
+ * them in POOL and return them. Set *COUNT to the number of records read.
+ */
+static base_record_t *
+unpack(apr_size_t *count,
+ svn_packed__data_root_t *root,
+ apr_pool_t *pool)
+{
+ svn_packed__int_stream_t *base_stream
+ = svn_packed__first_int_stream(root);
+ svn_packed__int_stream_t *sub_count_stream
+ = svn_packed__next_int_stream(base_stream);
+ svn_packed__byte_stream_t *base_description_stream
+ = svn_packed__first_byte_stream(root);
+ svn_packed__byte_stream_t *base_binary_stream
+ = svn_packed__next_byte_stream(base_description_stream);
+ svn_packed__byte_stream_t *sub_text_stream
+ = svn_packed__next_byte_stream(base_binary_stream);
+
+ svn_packed__int_stream_t *left_sub_stream
+ = svn_packed__next_int_stream(sub_count_stream);
+ svn_packed__int_stream_t *right_sub_stream
+ = svn_packed__next_int_stream(left_sub_stream);
+
+ apr_size_t i;
+ base_record_t *data;
+ *count = svn_packed__int_count(sub_count_stream) / 2;
+ data = apr_pcalloc(pool, *count * sizeof(*data));
+
+ for (i = 0; i < *count; ++i)
+ {
+ data[i].counter = (int) svn_packed__get_int(base_stream);
+ data[i].description.data
+ = svn_packed__get_bytes(base_description_stream,
+ &data[i].description.len);
+ data[i].large_unsigned1 = svn_packed__get_uint(base_stream);
+ data[i].large_unsigned2 = svn_packed__get_uint(base_stream);
+ data[i].left_subs = unpack_subs(left_sub_stream, sub_text_stream,
+ (apr_size_t)svn_packed__get_uint(sub_count_stream),
+ pool);
+
+ data[i].large_signed1 = svn_packed__get_int(base_stream);
+ data[i].large_signed2 = svn_packed__get_int(base_stream);
+ data[i].prime = (unsigned) svn_packed__get_uint(base_stream);
+ data[i].right_subs = unpack_subs(right_sub_stream, sub_text_stream,
+ (apr_size_t)svn_packed__get_uint(sub_count_stream),
+ pool);
+
+ data[i].binary.data
+ = svn_packed__get_bytes(base_binary_stream,
+ &data[i].binary.len);
+ }
+
+ return data;
+}
+
+/* Assert that LHS and RHS contain the same binary data (i.e. don't test
+ * for a terminating NUL).
+ */
+static svn_error_t *
+compare_binary(const svn_string_t *lhs,
+ const svn_string_t *rhs)
+{
+ SVN_TEST_ASSERT(lhs->len == rhs->len);
+ SVN_TEST_ASSERT(!memcmp(lhs->data, rhs->data, rhs->len));
+
+ return SVN_NO_ERROR;
+}
+
+/* Assert that LHS and RHS contain the same number of records with the
+ * same contents.
+ */
+static svn_error_t *
+compare_subs(const sub_record_t *lhs,
+ const sub_record_t *rhs)
+{
+ for (; lhs->sub_counter; ++lhs, ++rhs)
+ {
+ SVN_TEST_ASSERT(lhs->sub_counter == rhs->sub_counter);
+ SVN_ERR(compare_binary(&lhs->text, &rhs->text));
+ }
+
+ SVN_TEST_ASSERT(lhs->sub_counter == rhs->sub_counter);
+ return SVN_NO_ERROR;
+}
+
+/* Assert that the first COUNT records in LHS and RHS have the same contents.
+ */
+static svn_error_t *
+compare(const base_record_t *lhs,
+ const base_record_t *rhs,
+ apr_size_t count)
+{
+ apr_size_t i;
+ for (i = 0; i < count; ++i)
+ {
+ SVN_TEST_ASSERT(lhs[i].counter == rhs[i].counter);
+ SVN_ERR(compare_binary(&lhs[i].description, &rhs[i].description));
+ SVN_TEST_ASSERT(lhs[i].large_unsigned1 == rhs[i].large_unsigned1);
+ SVN_TEST_ASSERT(lhs[i].large_unsigned2 == rhs[i].large_unsigned2);
+ SVN_ERR(compare_subs(lhs[i].left_subs, rhs[i].left_subs));
+ SVN_TEST_ASSERT(lhs[i].counter == rhs[i].counter);
+ SVN_TEST_ASSERT(lhs[i].large_signed1 == rhs[i].large_signed1);
+ SVN_TEST_ASSERT(lhs[i].large_signed2 == rhs[i].large_signed2);
+ SVN_TEST_ASSERT(lhs[i].prime == rhs[i].prime);
+ SVN_ERR(compare_subs(lhs[i].right_subs, rhs[i].right_subs));
+ SVN_ERR(compare_binary(&lhs[i].binary, &rhs[i].binary));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_empty_structure(apr_pool_t *pool)
+{
+ base_record_t *unpacked;
+ apr_size_t count;
+
+ /* create an empty, readable container */
+ svn_packed__data_root_t *root = pack(test_data, 0, pool);
+
+ SVN_ERR(get_read_root(&root, root, pool));
+ unpacked = unpack(&count, root, pool);
+ SVN_TEST_ASSERT(count == 0);
+ SVN_ERR(compare(unpacked, test_data, count));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_full_structure(apr_pool_t *pool)
+{
+ base_record_t *unpacked;
+ apr_size_t count;
+
+ /* create an empty, readable container */
+ svn_packed__data_root_t *root = pack(test_data, BASE_RECORD_COUNT, pool);
+
+ SVN_ERR(get_read_root(&root, root, pool));
+ unpacked = unpack(&count, root, pool);
+ SVN_TEST_ASSERT(count == BASE_RECORD_COUNT);
+ SVN_ERR(compare(unpacked, test_data, count));
+
+ 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_empty_container,
+ "test empty container"),
+ SVN_TEST_PASS2(test_uint_stream,
+ "test a single uint stream"),
+ SVN_TEST_PASS2(test_int_stream,
+ "test a single int stream"),
+ SVN_TEST_PASS2(test_byte_stream,
+ "test a single bytes stream"),
+ SVN_TEST_PASS2(test_empty_structure,
+ "test empty, nested structure"),
+ SVN_TEST_PASS2(test_full_structure,
+ "test nested structure"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/path-test.c b/subversion/tests/libsvn_subr/path-test.c
index ec35176..6f0a996 100644
--- a/subversion/tests/libsvn_subr/path-test.c
+++ b/subversion/tests/libsvn_subr/path-test.c
@@ -315,9 +315,9 @@ test_uri_decode(apr_pool_t *pool)
const char *path;
const char *result;
} tests[] = {
- { "http://c.r.a/s%\0008me",
+ { "http://c.r.a/s%\0" "8me",
"http://c.r.a/s%"},
- { "http://c.r.a/s%6\000me",
+ { "http://c.r.a/s%6\0" "me",
"http://c.r.a/s%6" },
{ "http://c.r.a/s%68me",
"http://c.r.a/shme" },
@@ -489,7 +489,7 @@ test_path_join(apr_pool_t *pool)
if (svn_path_is_url(base))
continue;
- result = svn_path_join_many(pool, base, comp, NULL);
+ result = svn_path_join_many(pool, base, comp, SVN_VA_NULL);
if (strcmp(result, expect))
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
"svn_path_join_many(\"%s\", \"%s\") returned "
@@ -505,74 +505,74 @@ test_path_join(apr_pool_t *pool)
"expected \"%s\"", \
result, expect);
- TEST_MANY((pool, "abc", NULL), "abc");
- TEST_MANY((pool, "/abc", NULL), "/abc");
- TEST_MANY((pool, "/", NULL), "/");
-
- TEST_MANY((pool, "abc", "def", "ghi", NULL), "abc/def/ghi");
- TEST_MANY((pool, "abc", "/def", "ghi", NULL), "/def/ghi");
- TEST_MANY((pool, "/abc", "def", "ghi", NULL), "/abc/def/ghi");
- TEST_MANY((pool, "abc", "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "/def", "/ghi", NULL), "/ghi");
-
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", "ghi", NULL), "def/ghi");
- TEST_MANY((pool, "abc", SVN_EMPTY_PATH, "ghi", NULL), "abc/ghi");
- TEST_MANY((pool, "abc", "def", SVN_EMPTY_PATH, NULL), "abc/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", SVN_EMPTY_PATH, NULL), "def");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "ghi", NULL), "ghi");
- TEST_MANY((pool, "abc", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "abc");
- TEST_MANY((pool, SVN_EMPTY_PATH, "def", "/ghi", NULL), "/ghi");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/ghi", NULL), "/ghi");
-
- TEST_MANY((pool, "/", "def", "ghi", NULL), "/def/ghi");
- TEST_MANY((pool, "abc", "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "abc", "def", "/", NULL), "/");
- TEST_MANY((pool, "/", "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "/", "/", NULL), "/");
- TEST_MANY((pool, "/", SVN_EMPTY_PATH, "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", "def", SVN_EMPTY_PATH, NULL), "/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "/", "ghi", NULL), "/ghi");
- TEST_MANY((pool, "/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "/");
- TEST_MANY((pool, SVN_EMPTY_PATH, "/", SVN_EMPTY_PATH, NULL), "/");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/", NULL), "/");
+ TEST_MANY((pool, "abc", SVN_VA_NULL), "abc");
+ TEST_MANY((pool, "/abc", SVN_VA_NULL), "/abc");
+ TEST_MANY((pool, "/", SVN_VA_NULL), "/");
+
+ TEST_MANY((pool, "abc", "def", "ghi", SVN_VA_NULL), "abc/def/ghi");
+ TEST_MANY((pool, "abc", "/def", "ghi", SVN_VA_NULL), "/def/ghi");
+ TEST_MANY((pool, "/abc", "def", "ghi", SVN_VA_NULL), "/abc/def/ghi");
+ TEST_MANY((pool, "abc", "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "/def", "/ghi", SVN_VA_NULL), "/ghi");
+
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", "ghi", SVN_VA_NULL), "def/ghi");
+ TEST_MANY((pool, "abc", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "abc/ghi");
+ TEST_MANY((pool, "abc", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "abc/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", SVN_EMPTY_PATH, SVN_VA_NULL), "def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "ghi");
+ TEST_MANY((pool, "abc", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "abc");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "def", "/ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/ghi", SVN_VA_NULL), "/ghi");
+
+ TEST_MANY((pool, "/", "def", "ghi", SVN_VA_NULL), "/def/ghi");
+ TEST_MANY((pool, "abc", "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "abc", "def", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "/", "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "/", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "/", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "/", "ghi", SVN_VA_NULL), "/ghi");
+ TEST_MANY((pool, "/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "/", SVN_EMPTY_PATH, SVN_VA_NULL), "/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/", SVN_VA_NULL), "/");
#ifdef SVN_USE_DOS_PATHS
/* These will fail, see issue #2028
- TEST_MANY((pool, "X:", "def", "ghi", NULL), "X:def/ghi");
- TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", NULL), "X:ghi");
- TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, NULL), "X:def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", NULL), "X:ghi");
- TEST_MANY((pool, "X:/", "def", "ghi", NULL), "X:/def/ghi");
- TEST_MANY((pool, "abc", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "abc", "def", "X:/", NULL), "X:/");
- TEST_MANY((pool, "X:/", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", "X:/", "/", NULL), "/");
- TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", "def", SVN_EMPTY_PATH, NULL), "X:/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, NULL), "X:/");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", SVN_EMPTY_PATH, NULL), "X:/");
- TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "X:/", NULL), "X:/");
- TEST_MANY((pool, "X:", "X:/", "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:", "X:/", "/", NULL), "/");
-
- TEST_MANY((pool, "//srv/shr", "def", "ghi", NULL), "//srv/shr/def/ghi");
- TEST_MANY((pool, "//srv", "shr", "def", "ghi", NULL), "//srv/shr/def/ghi");
- TEST_MANY((pool, "//srv/shr/fld", "def", "ghi", NULL),
+ TEST_MANY((pool, "X:", "def", "ghi", SVN_VA_NULL), "X:def/ghi");
+ TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:ghi");
+ TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", SVN_VA_NULL), "X:ghi");
+ TEST_MANY((pool, "X:/", "def", "ghi", SVN_VA_NULL), "X:/def/ghi");
+ TEST_MANY((pool, "abc", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "abc", "def", "X:/", SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, "X:/", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", "X:/", "/", SVN_VA_NULL), "/");
+ TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:/", SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:/", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "X:/", SVN_VA_NULL), "X:/");
+ TEST_MANY((pool, "X:", "X:/", "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "X:/", "/", SVN_VA_NULL), "/");
+
+ TEST_MANY((pool, "//srv/shr", "def", "ghi", SVN_VA_NULL), "//srv/shr/def/ghi");
+ TEST_MANY((pool, "//srv", "shr", "def", "ghi", SVN_VA_NULL), "//srv/shr/def/ghi");
+ TEST_MANY((pool, "//srv/shr/fld", "def", "ghi", SVN_VA_NULL),
"//srv/shr/fld/def/ghi");
- TEST_MANY((pool, "//srv/shr/fld", "def", "//srv/shr", NULL), "//srv/shr");
- TEST_MANY((pool, "//srv", "shr", "//srv/shr", NULL), "//srv/shr");
- TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "ghi", NULL),
+ TEST_MANY((pool, "//srv/shr/fld", "def", "//srv/shr", SVN_VA_NULL), "//srv/shr");
+ TEST_MANY((pool, "//srv", "shr", "//srv/shr", SVN_VA_NULL), "//srv/shr");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "ghi", SVN_VA_NULL),
"//srv/shr/fld/def/ghi");
- TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "//srv/shr", NULL),
+ TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "//srv/shr", SVN_VA_NULL),
"//srv/shr");
*/
#else /* WIN32 or Cygwin */
- TEST_MANY((pool, "X:", "def", "ghi", NULL), "X:/def/ghi");
- TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", NULL), "X:/ghi");
- TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, NULL), "X:/def");
- TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "def", "ghi", SVN_VA_NULL), "X:/def/ghi");
+ TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", SVN_VA_NULL), "X:/ghi");
+ TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, SVN_VA_NULL), "X:/def");
+ TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", SVN_VA_NULL), "X:/ghi");
#endif /* non-WIN32 */
/* ### probably need quite a few more tests... */
@@ -1210,6 +1210,7 @@ test_path_splitext(apr_pool_t *pool)
{ "yep.still/no-ext", "yep.still/no-ext", "" },
{ "folder.with/period.log", "folder.with/period.", "log" },
{ "period.", "period.", "" },
+ { "dir/period.", "dir/period.", "" },
{ "file.ends-with/period.", "file.ends-with/period.", "" },
{ "two-periods..txt", "two-periods..", "txt" },
{ ".dot-file", ".dot-file", "" },
@@ -1527,7 +1528,7 @@ condense_targets_tests_helper(const char* title,
/* Verify the common part with the expected (prefix with cwd). */
if (*exp_common == '%')
- exp_common_abs = apr_pstrcat(pool, curdir, exp_common + 1, (char *)NULL);
+ exp_common_abs = apr_pstrcat(pool, curdir, exp_common + 1, SVN_VA_NULL);
if (strcmp(common_path, exp_common_abs) != 0)
{
@@ -1544,7 +1545,7 @@ condense_targets_tests_helper(const char* title,
{
const char * target = APR_ARRAY_IDX(condensed_targets, i, const char*);
if (token && (*token == '%'))
- token = apr_pstrcat(pool, curdir, token + 1, (char *)NULL);
+ token = apr_pstrcat(pool, curdir, token + 1, SVN_VA_NULL);
if (! token ||
(target && (strcmp(target, token) != 0)))
{
@@ -1700,7 +1701,9 @@ test_path_resolve_repos_relative_url(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_path_is_child,
@@ -1759,3 +1762,5 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_path_resolve_repos_relative_url"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/prefix-string-test.c b/subversion/tests/libsvn_subr/prefix-string-test.c
new file mode 100644
index 0000000..e420cff
--- /dev/null
+++ b/subversion/tests/libsvn_subr/prefix-string-test.c
@@ -0,0 +1,154 @@
+/*
+ * prefix-string-test.c: a collection of svn_prefix_string__* 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_error.h"
+#include "svn_string.h" /* This includes <apr_*.h> */
+#include "private/svn_string_private.h"
+
+static svn_error_t *
+test_empty_string(apr_pool_t *pool)
+{
+ svn_prefix_tree__t *tree = svn_prefix_tree__create(pool);
+ svn_prefix_string__t *empty = svn_prefix_string__create(tree, "");
+
+ /* same instance for all strings of the same value */
+ SVN_TEST_ASSERT(empty == svn_prefix_string__create(tree, ""));
+
+ /* does it actually have the right contents? */
+ SVN_TEST_ASSERT(svn_prefix_string__expand(empty, pool)->len == 0);
+ SVN_TEST_STRING_ASSERT(svn_prefix_string__expand(empty, pool)->data, "");
+
+ /* strings shall be equal to themselves */
+ SVN_TEST_ASSERT(0 == svn_prefix_string__compare(empty, empty));
+
+ return SVN_NO_ERROR;
+}
+
+enum {TEST_CASE_COUNT = 9};
+
+static const char *test_cases[TEST_CASE_COUNT] =
+{
+ "a longish string of sorts, longer than 7 anyway",
+ "some other string",
+ "more stuff on root",
+ "some shorter string",
+ "some short string",
+ "some short str",
+ "some short str2",
+ "a longish string of sorts, longer than ?! anyway",
+ "a"
+};
+
+static svn_error_t *
+test_string_creation(apr_pool_t *pool)
+{
+ svn_prefix_tree__t *tree = svn_prefix_tree__create(pool);
+ svn_prefix_string__t *strings[TEST_CASE_COUNT];
+ int i;
+
+ /* create strings and remember their initial references */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ strings[i] = svn_prefix_string__create(tree, test_cases[i]);
+
+ /* doing this again must yield the same pointers */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ SVN_TEST_ASSERT(strings[i]
+ == svn_prefix_string__create(tree, test_cases[i]));
+
+ /* converting them back to strings must be the initial values */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ {
+ svn_string_t *expanded = svn_prefix_string__expand(strings[i], pool);
+
+ SVN_TEST_ASSERT(expanded->len == strlen(test_cases[i]));
+ SVN_TEST_STRING_ASSERT(expanded->data, test_cases[i]);
+
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_string_comparison(apr_pool_t *pool)
+{
+ svn_prefix_tree__t *tree = svn_prefix_tree__create(pool);
+ svn_prefix_string__t *strings[TEST_CASE_COUNT];
+ int i, k;
+
+ /* create strings */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ strings[i] = svn_prefix_string__create(tree, test_cases[i]);
+
+ /* comparing them with themselves */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ SVN_TEST_ASSERT(! svn_prefix_string__compare(strings[i], strings[i]));
+
+ /* compare with all other strings */
+ for (i = 0; i < TEST_CASE_COUNT; ++i)
+ {
+ svn_string_t *lhs = svn_prefix_string__expand(strings[i], pool);
+ for (k = 0; k < TEST_CASE_COUNT; ++k)
+ {
+ svn_string_t *rhs = svn_prefix_string__expand(strings[k], pool);
+ int expected_diff = strcmp(lhs->data, rhs->data);
+ int actual_diff = svn_prefix_string__compare(strings[i], strings[k]);
+
+ SVN_TEST_ASSERT((actual_diff < 0) == (expected_diff < 0));
+ SVN_TEST_ASSERT((actual_diff > 0) == (expected_diff > 0));
+ SVN_TEST_ASSERT(!actual_diff == !expected_diff);
+ }
+ }
+
+ 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_empty_string,
+ "check empty strings"),
+ SVN_TEST_PASS2(test_string_creation,
+ "create many strings"),
+ SVN_TEST_PASS2(test_string_comparison,
+ "compare strings"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/priority-queue-test.c b/subversion/tests/libsvn_subr/priority-queue-test.c
new file mode 100644
index 0000000..bd2d991
--- /dev/null
+++ b/subversion/tests/libsvn_subr/priority-queue-test.c
@@ -0,0 +1,240 @@
+/*
+ * priority-queue-test.c: a collection of svn_priority_queue__* 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_error.h"
+#include "private/svn_sorts_private.h"
+
+/* priority queue test:
+ * items in the queue are simple integers, in ascending order */
+
+/* number of items to put into the queue */
+enum {NUMBER_COUNT = 11};
+
+/* the actual values in the order we add them to the queue */
+static const int numbers[NUMBER_COUNT]
+ = { 8395, 0, -1, 3885, 1, -435, 99993, 10, 0, 1, 8395 };
+
+/* test_update will modify in-queue data and expects the queue to return
+ the values in the following order: */
+static const int expected_modified[NUMBER_COUNT]
+ = { -431, 0, 1, 3, 5, 10, 16, 3889, 8395, 8403, 99997 };
+
+/* standard compare function for integers */
+static int
+compare_func(const void *lhs, const void *rhs)
+{
+ return *(const int *)lhs - *(const int *)rhs;
+}
+
+/* Check that QUEUE is empty and the usual operations still work */
+static svn_error_t *
+verify_empty_queue(svn_priority_queue__t *queue)
+{
+ /* it's an empty queue */
+ SVN_TEST_ASSERT(svn_priority_queue__size(queue) == 0);
+ SVN_TEST_ASSERT(svn_priority_queue__peek(queue) == NULL);
+
+ /* these should be no-ops */
+ svn_priority_queue__update(queue);
+ svn_priority_queue__pop(queue);
+
+ return SVN_NO_ERROR;
+}
+
+/* check that the tip of QUEUE equals EXPECTED and remove the first element */
+static svn_error_t *
+extract_expected(svn_priority_queue__t *queue, int expected)
+{
+ int value = *(int *)svn_priority_queue__peek(queue);
+ SVN_TEST_ASSERT(value == expected);
+ svn_priority_queue__pop(queue);
+
+ return SVN_NO_ERROR;
+}
+
+/* Verify that QUEUE returns all elements in the proper order.
+ Also check that data can be added & removed without disturbing the order.
+ */
+static svn_error_t *
+verify_queue_order(svn_priority_queue__t *queue)
+{
+ int sorted[NUMBER_COUNT];
+ int i;
+
+ /* reference order */
+ memcpy(sorted, numbers, sizeof(numbers));
+ qsort(sorted, NUMBER_COUNT, sizeof(sorted[0]), compare_func);
+
+ /* verify that the queue returns the data in the same order */
+ for (i = 0; i < NUMBER_COUNT; ++i)
+ {
+ int item = *(int *)svn_priority_queue__peek(queue);
+ int to_insert;
+
+ /* is this the value we expected? */
+ SVN_TEST_ASSERT(item == sorted[i]);
+
+ /* add two items at the tip of the queue */
+ to_insert = item - 1;
+ svn_priority_queue__push(queue, &to_insert);
+ svn_priority_queue__push(queue, &item);
+
+ /* check queue length */
+ SVN_TEST_ASSERT(svn_priority_queue__size(queue) == NUMBER_COUNT-i+2);
+
+ /* now, lets extract all 3 of them */
+ SVN_ERR(extract_expected(queue, item-1));
+ SVN_ERR(extract_expected(queue, item));
+ SVN_ERR(extract_expected(queue, item));
+
+ /* check queue length */
+ SVN_TEST_ASSERT(svn_priority_queue__size(queue) == NUMBER_COUNT-i-1);
+ }
+
+ /* the queue should now be empty */
+ verify_empty_queue(queue);
+
+ return SVN_NO_ERROR;
+}
+
+/* return a queue allocated in POOL containing all items of NUMBERS */
+static svn_priority_queue__t *
+create_standard_queue(apr_pool_t *pool)
+{
+ apr_array_header_t *elements
+ = apr_array_make(pool, 11, sizeof(numbers[0]));
+
+ /* build queue */
+ int i;
+ for (i = 0; i < NUMBER_COUNT; ++i)
+ APR_ARRAY_PUSH(elements, int) = numbers[i];
+
+ return svn_priority_queue__create(elements, compare_func);
+}
+
+
+static svn_error_t *
+test_empty_queue(apr_pool_t *pool)
+{
+ apr_array_header_t *elements
+ = apr_array_make(pool, 0, sizeof(int));
+ svn_priority_queue__t *queue
+ = svn_priority_queue__create(elements, compare_func);
+
+ verify_empty_queue(queue);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_sort_queue(apr_pool_t *pool)
+{
+ svn_priority_queue__t *queue = create_standard_queue(pool);
+
+ /* data should come out of the queue in sorted order */
+ SVN_ERR(verify_queue_order(queue));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_push(apr_pool_t *pool)
+{
+ apr_array_header_t *elements
+ = apr_array_make(pool, 3, sizeof(int));
+ svn_priority_queue__t *queue
+ = svn_priority_queue__create(elements, compare_func);
+
+ /* build queue */
+ int i;
+ for (i = 0; i < NUMBER_COUNT; ++i)
+ svn_priority_queue__push(queue, &numbers[i]);
+
+ /* data should come out of the queue in sorted order */
+ SVN_ERR(verify_queue_order(queue));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_update(apr_pool_t *pool)
+{
+ svn_priority_queue__t *queue = create_standard_queue(pool);
+
+ /* modify all items in the queue */
+ int i;
+ for (i = 0; i < NUMBER_COUNT; ++i)
+ {
+ int *tip = svn_priority_queue__peek(queue);
+ *tip += 4;
+ svn_priority_queue__update(queue);
+
+ /* extract and verify tip */
+ SVN_TEST_ASSERT(*(int *)svn_priority_queue__peek(queue)
+ == expected_modified[i]);
+ svn_priority_queue__pop(queue);
+
+ /* this should be a no-op now */
+ svn_priority_queue__update(queue);
+
+ SVN_TEST_ASSERT(svn_priority_queue__size(queue) == NUMBER_COUNT-i-1);
+ }
+
+ /* the queue should now be empty */
+ verify_empty_queue(queue);
+
+ 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_empty_queue,
+ "test empty queue"),
+ SVN_TEST_PASS2(test_sort_queue,
+ "data returned by a priority queue shall be ordered"),
+ SVN_TEST_PASS2(test_push,
+ "priority queues can be built up incrementally"),
+ SVN_TEST_PASS2(test_update,
+ "updating the head of the queue"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/revision-test.c b/subversion/tests/libsvn_subr/revision-test.c
index 7e5d752..53ca8da 100644
--- a/subversion/tests/libsvn_subr/revision-test.c
+++ b/subversion/tests/libsvn_subr/revision-test.c
@@ -34,6 +34,12 @@ test_revnum_parse(apr_pool_t *pool)
"",
"abc",
"-456",
+ "2147483648",
+ "4294967295",
+ "4300000000",
+ "00000000001",
+ "21474836470",
+ "999999999999999999999999",
NULL
};
@@ -41,6 +47,8 @@ test_revnum_parse(apr_pool_t *pool)
"0",
"12345",
"12345ABC",
+ "0000000001",
+ "2147483647x",
NULL
};
@@ -115,10 +123,14 @@ test_revnum_parse(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_revnum_parse,
"test svn_revnum_parse"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/root-pools-test.c b/subversion/tests/libsvn_subr/root-pools-test.c
new file mode 100644
index 0000000..8116418
--- /dev/null
+++ b/subversion/tests/libsvn_subr/root-pools-test.c
@@ -0,0 +1,137 @@
+/*
+ * root-pools-test.c -- test the svn_root_pools__* API
+ *
+ * ====================================================================
+ * 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 <apr_pools.h>
+#include <apr_thread_proc.h>
+#include <apr_thread_cond.h>
+
+#include "private/svn_atomic.h"
+#include "private/svn_subr_private.h"
+
+#include "../svn_test.h"
+
+/* do a few allocations of various sizes from POOL */
+static void
+do_some_allocations(apr_pool_t *pool)
+{
+ int i;
+ apr_size_t fib = 1, fib1 = 0, fib2 = 0;
+ for (i = 0; i < 25; ++i) /* fib(25) = 75025 */
+ {
+ apr_pcalloc(pool, fib1);
+ fib2 = fib1;
+ fib1 = fib;
+ fib += fib2;
+ }
+}
+
+/* allocate, use and recycle a pool from POOLs a few times */
+static void
+use_root_pool(svn_root_pools__t *pools)
+{
+ int i;
+ for (i = 0; i < 1000; ++i)
+ {
+ apr_pool_t *pool = svn_root_pools__acquire_pool(pools);
+ do_some_allocations(pool);
+ svn_root_pools__release_pool(pool, pools);
+ }
+}
+
+#if APR_HAS_THREADS
+static void *
+APR_THREAD_FUNC thread_func(apr_thread_t *tid, void *data)
+{
+ /* give all threads a good chance to get started by the scheduler */
+ apr_thread_yield();
+
+ use_root_pool(data);
+ apr_thread_exit(tid, APR_SUCCESS);
+
+ return NULL;
+}
+#endif
+
+static svn_error_t *
+test_root_pool(apr_pool_t *pool)
+{
+ svn_root_pools__t *pools;
+ SVN_ERR(svn_root_pools__create(&pools));
+ use_root_pool(pools);
+
+ return SVN_NO_ERROR;
+}
+
+#define APR_ERR(expr) \
+ do { \
+ apr_status_t status = (expr); \
+ if (status) \
+ return svn_error_wrap_apr(status, NULL); \
+ } while (0)
+
+static svn_error_t *
+test_root_pool_concurrency(apr_pool_t *pool)
+{
+#if APR_HAS_THREADS
+ /* The svn_root_pools__t container is supposed to be thread-safe.
+ Do some multi-threaded access and hope that there are no segfaults.
+ */
+ enum { THREAD_COUNT = 10 };
+ svn_root_pools__t *pools;
+ apr_thread_t *threads[THREAD_COUNT];
+ int i;
+
+ SVN_ERR(svn_root_pools__create(&pools));
+
+ for (i = 0; i < THREAD_COUNT; ++i)
+ APR_ERR(apr_thread_create(&threads[i], NULL, thread_func, pools, pool));
+
+ /* wait for the threads to finish */
+ for (i = 0; i < THREAD_COUNT; ++i)
+ {
+ apr_status_t retval;
+ APR_ERR(apr_thread_join(&retval, threads[i]));
+ APR_ERR(retval);
+ }
+#endif
+
+ 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_root_pool,
+ "test root pool recycling"),
+ SVN_TEST_SKIP2(test_root_pool_concurrency,
+ ! APR_HAS_THREADS,
+ "test concurrent root pool recycling"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/skel-test.c b/subversion/tests/libsvn_subr/skel-test.c
index 49fe1a3..9839e6a 100644
--- a/subversion/tests/libsvn_subr/skel-test.c
+++ b/subversion/tests/libsvn_subr/skel-test.c
@@ -59,7 +59,7 @@ get_empty_string(apr_pool_t *pool)
{
svn_pool_clear(pool);
- return svn_stringbuf_ncreate(0, 0, pool);
+ return svn_stringbuf_create_empty(pool);
}
/* Parse a skeleton from a Subversion string. */
@@ -886,7 +886,9 @@ unparse_list(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(parse_implicit_length,
@@ -903,3 +905,5 @@ struct svn_test_descriptor_t test_funcs[] =
"unparse lists"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/spillbuf-test.c b/subversion/tests/libsvn_subr/spillbuf-test.c
index c928dc3..16021b1 100644
--- a/subversion/tests/libsvn_subr/spillbuf-test.c
+++ b/subversion/tests/libsvn_subr/spillbuf-test.c
@@ -57,10 +57,8 @@ check_read(svn_spillbuf_t *buf,
static svn_error_t *
-test_spillbuf_basic(apr_pool_t *pool)
+test_spillbuf__basic(apr_pool_t *pool, apr_size_t len, svn_spillbuf_t *buf)
{
- apr_size_t len = strlen(basic_data); /* Don't include basic_data's NUL */
- svn_spillbuf_t *buf = svn_spillbuf__create(len, 10 * len, pool);
int i;
const char *readptr;
apr_size_t readlen;
@@ -87,6 +85,22 @@ test_spillbuf_basic(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_spillbuf_basic(apr_pool_t *pool)
+{
+ apr_size_t len = strlen(basic_data); /* Don't include basic_data's NUL */
+ svn_spillbuf_t *buf = svn_spillbuf__create(len, 10 * len, pool);
+ return test_spillbuf__basic(pool, len, buf);
+}
+
+static svn_error_t *
+test_spillbuf_basic_spill_all(apr_pool_t *pool)
+{
+ apr_size_t len = strlen(basic_data); /* Don't include basic_data's NUL */
+ svn_spillbuf_t *buf =
+ svn_spillbuf__create_extended(len, 10 * len, TRUE, TRUE, NULL, pool);
+ return test_spillbuf__basic(pool, len, buf);
+}
static svn_error_t *
read_callback(svn_boolean_t *stop,
@@ -107,12 +121,8 @@ read_callback(svn_boolean_t *stop,
static svn_error_t *
-test_spillbuf_callback(apr_pool_t *pool)
+test_spillbuf__callback(apr_pool_t *pool, svn_spillbuf_t *buf)
{
- svn_spillbuf_t *buf = svn_spillbuf__create(
- sizeof(basic_data) /* blocksize */,
- 10 * sizeof(basic_data) /* maxsize */,
- pool);
int i;
int counter;
svn_boolean_t exhausted;
@@ -133,15 +143,31 @@ test_spillbuf_callback(apr_pool_t *pool)
return SVN_NO_ERROR;
}
-
static svn_error_t *
-test_spillbuf_file(apr_pool_t *pool)
+test_spillbuf_callback(apr_pool_t *pool)
{
- apr_size_t altsize = sizeof(basic_data) + 2;
svn_spillbuf_t *buf = svn_spillbuf__create(
- altsize /* blocksize */,
- 2 * sizeof(basic_data) /* maxsize */,
+ sizeof(basic_data) /* blocksize */,
+ 10 * sizeof(basic_data) /* maxsize */,
pool);
+ return test_spillbuf__callback(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf_callback_spill_all(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ sizeof(basic_data) /* blocksize */,
+ 10 * sizeof(basic_data) /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__callback(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf__file(apr_pool_t *pool, apr_size_t altsize, svn_spillbuf_t *buf)
+{
int i;
const char *readptr;
apr_size_t readlen;
@@ -203,14 +229,33 @@ test_spillbuf_file(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_spillbuf_file(apr_pool_t *pool)
+{
+ apr_size_t altsize = sizeof(basic_data) + 2;
+ svn_spillbuf_t *buf = svn_spillbuf__create(
+ altsize /* blocksize */,
+ 2 * sizeof(basic_data) /* maxsize */,
+ pool);
+ return test_spillbuf__file(pool, altsize, buf);
+}
static svn_error_t *
-test_spillbuf_interleaving(apr_pool_t *pool)
+test_spillbuf_file_spill_all(apr_pool_t *pool)
{
- svn_spillbuf_t *buf = svn_spillbuf__create(8 /* blocksize */,
- 15 /* maxsize */,
- pool);
+ apr_size_t altsize = sizeof(basic_data) + 2;
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ altsize /* blocksize */,
+ 2 * sizeof(basic_data) /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__file(pool, altsize, buf);
+}
+static svn_error_t *
+test_spillbuf__interleaving(apr_pool_t *pool, svn_spillbuf_t* buf)
+{
SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
/* now: two blocks: 8 and 4 bytes */
@@ -238,18 +283,36 @@ test_spillbuf_interleaving(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_spillbuf_interleaving(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create(8 /* blocksize */,
+ 15 /* maxsize */,
+ pool);
+ return test_spillbuf__interleaving(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf_interleaving_spill_all(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ 8 /* blocksize */,
+ 15 /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__interleaving(pool, buf);
+}
static svn_error_t *
test_spillbuf_reader(apr_pool_t *pool)
{
- svn_spillbuf_reader_t *sbr;
+ svn_spillbuf_reader_t *sbr = svn_spillbuf__reader_create(4 /* blocksize */,
+ 100 /* maxsize */,
+ pool);
apr_size_t amt;
char buf[10];
- sbr = svn_spillbuf__reader_create(4 /* blocksize */,
- 100 /* maxsize */,
- pool);
-
SVN_ERR(svn_spillbuf__reader_write(sbr, "abcdef", 6, pool));
/* Get a buffer from the underlying reader, and grab a couple bytes. */
@@ -270,13 +333,13 @@ test_spillbuf_reader(apr_pool_t *pool)
return SVN_NO_ERROR;
}
-
static svn_error_t *
test_spillbuf_stream(apr_pool_t *pool)
{
- svn_stream_t *stream = svn_stream__from_spillbuf(8 /* blocksize */,
- 15 /* maxsize */,
- pool);
+ svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
+ 100 /* maxsize */,
+ pool);
+ svn_stream_t *stream = svn_stream__from_spillbuf(buf, pool);
char readbuf[256];
apr_size_t readlen;
apr_size_t writelen;
@@ -287,7 +350,7 @@ test_spillbuf_stream(apr_pool_t *pool)
/* now: two blocks: 8 and 4 bytes */
readlen = 8;
- SVN_ERR(svn_stream_read(stream, readbuf, &readlen));
+ SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
SVN_TEST_ASSERT(readlen == 8
&& memcmp(readbuf, "abcdefgh", 8) == 0);
/* now: one block: 4 bytes */
@@ -295,7 +358,7 @@ test_spillbuf_stream(apr_pool_t *pool)
SVN_ERR(svn_stream_write(stream, "mnopqr", &writelen));
/* now: two blocks: 8 and 2 bytes */
- SVN_ERR(svn_stream_read(stream, readbuf, &readlen));
+ SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
SVN_TEST_ASSERT(readlen == 8
&& memcmp(readbuf, "ijklmnop", 8) == 0);
/* now: one block: 2 bytes */
@@ -305,28 +368,23 @@ test_spillbuf_stream(apr_pool_t *pool)
SVN_ERR(svn_stream_write(stream, "GHIJKL", &writelen));
/* now: two blocks: 8 and 6 bytes, and 6 bytes spilled to a file */
- SVN_ERR(svn_stream_read(stream, readbuf, &readlen));
+ SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
SVN_TEST_ASSERT(readlen == 8
&& memcmp(readbuf, "qrstuvwx", 8) == 0);
readlen = 6;
- SVN_ERR(svn_stream_read(stream, readbuf, &readlen));
+ SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
SVN_TEST_ASSERT(readlen == 6
&& memcmp(readbuf, "ABCDEF", 6) == 0);
- SVN_ERR(svn_stream_read(stream, readbuf, &readlen));
+ SVN_ERR(svn_stream_read_full(stream, readbuf, &readlen));
SVN_TEST_ASSERT(readlen == 6
&& memcmp(readbuf, "GHIJKL", 6) == 0);
return SVN_NO_ERROR;
}
-
static svn_error_t *
-test_spillbuf_rwfile(apr_pool_t *pool)
+test_spillbuf__rwfile(apr_pool_t *pool, svn_spillbuf_t *buf)
{
- svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
- 10 /* maxsize */,
- pool);
-
SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
@@ -360,14 +418,30 @@ test_spillbuf_rwfile(apr_pool_t *pool)
return SVN_NO_ERROR;
}
-
static svn_error_t *
-test_spillbuf_eof(apr_pool_t *pool)
+test_spillbuf_rwfile(apr_pool_t *pool)
{
svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
10 /* maxsize */,
pool);
+ return test_spillbuf__rwfile(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf_rwfile_spill_all(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ 4 /* blocksize */,
+ 10 /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__rwfile(pool, buf);
+}
+static svn_error_t *
+test_spillbuf__eof(apr_pool_t *pool, svn_spillbuf_t *buf)
+{
SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
/* now: two blocks: 4 and 2 bytes, and 6 bytes in spill file. */
@@ -415,19 +489,108 @@ test_spillbuf_eof(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_spillbuf_eof(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
+ 10 /* maxsize */,
+ pool);
+ return test_spillbuf__eof(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf_eof_spill_all(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ 4 /* blocksize */,
+ 10 /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__eof(pool, buf);
+}
+
+static svn_error_t *
+test_spillbuf__file_attrs(apr_pool_t *pool, svn_boolean_t spill_all,
+ svn_spillbuf_t *buf)
+{
+ apr_finfo_t finfo;
+
+ SVN_ERR(svn_spillbuf__write(buf, "abcdef", 6, pool));
+ SVN_ERR(svn_spillbuf__write(buf, "ghijkl", 6, pool));
+ SVN_ERR(svn_spillbuf__write(buf, "mnopqr", 6, pool));
+
+ /* Check that the spillbuf size is what we expect it to be */
+ SVN_TEST_ASSERT(svn_spillbuf__get_size(buf) == 18);
+
+ /* Check file existence */
+ SVN_TEST_ASSERT(svn_spillbuf__get_filename(buf) != NULL);
+ SVN_TEST_ASSERT(svn_spillbuf__get_file(buf) != NULL);
+
+ /* The size of the file must match expectations */
+ SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE,
+ svn_spillbuf__get_file(buf), pool));
+ if (spill_all)
+ SVN_TEST_ASSERT(finfo.size == svn_spillbuf__get_size(buf));
+ else
+ SVN_TEST_ASSERT(finfo.size == (svn_spillbuf__get_size(buf)
+ - svn_spillbuf__get_memory_size(buf)));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_spillbuf_file_attrs(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create(4 /* blocksize */,
+ 10 /* maxsize */,
+ pool);
+ return test_spillbuf__file_attrs(pool, FALSE, buf);
+}
+
+static svn_error_t *
+test_spillbuf_file_attrs_spill_all(apr_pool_t *pool)
+{
+ svn_spillbuf_t *buf = svn_spillbuf__create_extended(
+ 4 /* blocksize */,
+ 10 /* maxsize */,
+ TRUE /* delte on close */,
+ TRUE /* spill all data */,
+ NULL, pool);
+ return test_spillbuf__file_attrs(pool, TRUE, buf);
+}
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_spillbuf_basic, "basic spill buffer test"),
+ SVN_TEST_PASS2(test_spillbuf_basic_spill_all,
+ "basic spill buffer test (spill-all-data)"),
SVN_TEST_PASS2(test_spillbuf_callback, "spill buffer read callback"),
+ SVN_TEST_PASS2(test_spillbuf_callback_spill_all,
+ "spill buffer read callback (spill-all-data)"),
SVN_TEST_PASS2(test_spillbuf_file, "spill buffer file test"),
+ SVN_TEST_PASS2(test_spillbuf_file_spill_all,
+ "spill buffer file test (spill-all-data)"),
SVN_TEST_PASS2(test_spillbuf_interleaving,
"interleaving reads and writes"),
+ SVN_TEST_PASS2(test_spillbuf_interleaving_spill_all,
+ "interleaving reads and writes (spill-all-data)"),
SVN_TEST_PASS2(test_spillbuf_reader, "spill buffer reader test"),
SVN_TEST_PASS2(test_spillbuf_stream, "spill buffer stream test"),
SVN_TEST_PASS2(test_spillbuf_rwfile, "read/write spill file"),
+ SVN_TEST_PASS2(test_spillbuf_rwfile_spill_all,
+ "read/write spill file (spill-all-data)"),
SVN_TEST_PASS2(test_spillbuf_eof, "validate reaching EOF of spill file"),
+ SVN_TEST_PASS2(test_spillbuf_eof_spill_all,
+ "validate reaching EOF (spill-all-data)"),
+ SVN_TEST_PASS2(test_spillbuf_file_attrs, "check spill file properties"),
+ SVN_TEST_PASS2(test_spillbuf_file_attrs_spill_all,
+ "check spill file properties (spill-all-data)"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/sqlite-test.c b/subversion/tests/libsvn_subr/sqlite-test.c
new file mode 100644
index 0000000..f44aa8d
--- /dev/null
+++ b/subversion/tests/libsvn_subr/sqlite-test.c
@@ -0,0 +1,186 @@
+/*
+ * sqlite-test.c -- test the stream 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 "private/svn_sqlite.h"
+#include "../svn_test.h"
+
+static svn_error_t *
+open_db(svn_sqlite__db_t **sdb,
+ const char **db_abspath_p,
+ const char *db_name,
+ const char *const *statements,
+ apr_int32_t timeout,
+ apr_pool_t *pool)
+{
+ const char *db_dir, *db_abspath;
+
+ SVN_ERR(svn_dirent_get_absolute(&db_dir, "sqlite-test-tmp", pool));
+ SVN_ERR(svn_io_remove_dir2(db_dir, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(db_dir, pool));
+ svn_test_add_dir_cleanup(db_dir);
+
+ db_abspath = svn_dirent_join(db_dir, db_name, pool);
+
+ SVN_ERR(svn_sqlite__open(sdb, db_abspath, svn_sqlite__mode_rwcreate,
+ statements, 0, NULL, timeout, pool, pool));
+
+ if (db_abspath_p)
+ *db_abspath_p = db_abspath;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+error_second(svn_sqlite__context_t *sctx,
+ int argc,
+ svn_sqlite__value_t *values[],
+ void *baton)
+{
+ static int i = 0;
+
+ if (++i == 2)
+ svn_sqlite__result_error(sctx, "fake error", 0);
+ else
+ svn_sqlite__result_int64(sctx, 1);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_sqlite_reset(apr_pool_t *pool)
+{
+ svn_sqlite__db_t *sdb;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ const char *value;
+
+ static const char *const statements[] = {
+ "CREATE TABLE reset ("
+ " one TEXT NOT NULL PRIMARY KEY,"
+ " two TEXT"
+ ");"
+ "INSERT INTO reset(one, two) VALUES ('foo', 'bar');"
+ "INSERT INTO reset(one, two) VALUES ('zig', 'zag')",
+
+ "SELECT one FROM reset WHERE two IS NOT NULL AND error_second(one) "
+ "ORDER BY one",
+
+ NULL
+ };
+
+ SVN_ERR(open_db(&sdb, NULL, "reset", statements, 0, pool));
+ SVN_ERR(svn_sqlite__create_scalar_function(sdb, "error_second",
+ 1, FALSE /* deterministic */,
+ error_second, NULL));
+ SVN_ERR(svn_sqlite__exec_statements(sdb, 0));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, 1));
+
+ /* First step is OK. */
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_TEST_ASSERT(have_row);
+ value = svn_sqlite__column_text(stmt, 0, NULL);
+ SVN_TEST_ASSERT(value && !strcmp(value, "foo"));
+
+ /* Second step fails. */
+ SVN_TEST_ASSERT_ERROR(svn_sqlite__step(&have_row, stmt),
+ SVN_ERR_SQLITE_ERROR);
+
+ /* The svn_sqlite__step wrapper calls svn_sqlite__reset when step
+ fails so the reset call here is a no-op. The first step can be
+ repeated. */
+ SVN_ERR(svn_sqlite__reset(stmt));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_TEST_ASSERT(have_row);
+ value = svn_sqlite__column_text(stmt, 0, NULL);
+ SVN_TEST_ASSERT(value && !strcmp(value, "foo"));
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_sqlite_txn_commit_busy(apr_pool_t *pool)
+{
+ svn_sqlite__db_t *sdb1;
+ svn_sqlite__db_t *sdb2;
+ const char *db_abspath;
+ svn_error_t *err;
+
+ static const char *const statements[] = {
+ "CREATE TABLE test (one TEXT NOT NULL PRIMARY KEY)",
+
+ "INSERT INTO test(one) VALUES ('foo')",
+
+ "SELECT one from test",
+
+ NULL
+ };
+
+ /* Open two db connections.
+
+ Use a small busy_timeout of 250ms, since we're about to receive an
+ SVN_ERR_SQLITE_BUSY error, and retrying for the default 10 seconds
+ would be a waste of time. */
+ SVN_ERR(open_db(&sdb1, &db_abspath, "txn_commit_busy",
+ statements, 250, pool));
+ SVN_ERR(svn_sqlite__open(&sdb2, db_abspath, svn_sqlite__mode_readwrite,
+ statements, 0, NULL, 250, pool, pool));
+ SVN_ERR(svn_sqlite__exec_statements(sdb1, 0));
+
+ /* Begin two deferred transactions. */
+ SVN_ERR(svn_sqlite__begin_transaction(sdb1));
+ SVN_ERR(svn_sqlite__exec_statements(sdb1, 1 /* INSERT */));
+ SVN_ERR(svn_sqlite__begin_transaction(sdb2));
+ SVN_ERR(svn_sqlite__exec_statements(sdb2, 2 /* SELECT */));
+
+ /* Try to COMMIT the first write transaction; this should fail due to
+ the concurrent read transaction that holds a shared lock on the db. */
+ err = svn_sqlite__finish_transaction(sdb1, SVN_NO_ERROR);
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_SQLITE_BUSY);
+
+ /* We failed to COMMIT the first transaction, but COMMIT-ting the
+ second transaction through a different db connection should succeed.
+ Upgrade it to a write transaction by executing the INSERT statement,
+ and then commit. */
+ SVN_ERR(svn_sqlite__exec_statements(sdb2, 1 /* INSERT */));
+ SVN_ERR(svn_sqlite__finish_transaction(sdb2, SVN_NO_ERROR));
+
+ SVN_ERR(svn_sqlite__close(sdb2));
+ SVN_ERR(svn_sqlite__close(sdb1));
+
+ return SVN_NO_ERROR;
+}
+
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_PASS2(test_sqlite_reset,
+ "sqlite reset"),
+ SVN_TEST_PASS2(test_sqlite_txn_commit_busy,
+ "sqlite busy on transaction commit"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/stream-test.c b/subversion/tests/libsvn_subr/stream-test.c
index c8dba13..aaa9bf1 100644
--- a/subversion/tests/libsvn_subr/stream-test.c
+++ b/subversion/tests/libsvn_subr/stream-test.c
@@ -73,7 +73,7 @@ test_stream_from_string(apr_pool_t *pool)
while (len == TEST_BUF_SIZE)
{
/* Read a chunk ... */
- SVN_ERR(svn_stream_read(stream, buffer, &len));
+ SVN_ERR(svn_stream_read_full(stream, buffer, &len));
/* ... and append the chunk to the stringbuf. */
svn_stringbuf_appendbytes(outbuf, buffer, len);
@@ -206,7 +206,7 @@ test_stream_compressed(apr_pool_t *pool)
while (len >= TEST_BUF_SIZE)
{
len = TEST_BUF_SIZE;
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
if (len > 0)
svn_stringbuf_appendbytes(inbuf, buf, len);
}
@@ -332,17 +332,17 @@ test_stream_seek_stringbuf(apr_pool_t *pool)
stringbuf = svn_stringbuf_create("OneTwo", pool);
stream = svn_stream_from_stringbuf(stringbuf, pool);
len = 3;
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
buf[3] = '\0';
SVN_TEST_STRING_ASSERT(buf, "One");
SVN_ERR(svn_stream_mark(stream, &mark, pool));
len = 3;
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
buf[3] = '\0';
SVN_TEST_STRING_ASSERT(buf, "Two");
SVN_ERR(svn_stream_seek(stream, mark));
len = 3;
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
buf[3] = '\0';
SVN_TEST_STRING_ASSERT(buf, "Two");
@@ -351,7 +351,7 @@ test_stream_seek_stringbuf(apr_pool_t *pool)
SVN_ERR(svn_stream_skip(stream, 2));
/* The remaining line should be empty */
len = 3;
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
buf[len] = '\0';
SVN_TEST_ASSERT(len == 1);
SVN_TEST_STRING_ASSERT(buf, "o");
@@ -381,7 +381,7 @@ test_stream_seek_translated(apr_pool_t *pool)
FALSE, keywords, TRUE, pool);
/* Seek from outside of keyword to inside of keyword. */
len = 25;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 25);
buf[25] = '\0';
SVN_TEST_STRING_ASSERT(buf, "One$MyKeyword: my keyword");
@@ -389,7 +389,7 @@ test_stream_seek_translated(apr_pool_t *pool)
SVN_ERR(svn_stream_reset(translated_stream));
SVN_ERR(svn_stream_seek(translated_stream, mark));
len = 4;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 4);
buf[4] = '\0';
SVN_TEST_STRING_ASSERT(buf, " was");
@@ -397,7 +397,7 @@ test_stream_seek_translated(apr_pool_t *pool)
SVN_ERR(svn_stream_seek(translated_stream, mark));
SVN_ERR(svn_stream_skip(translated_stream, 2));
len = 2;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 2);
buf[len] = '\0';
SVN_TEST_STRING_ASSERT(buf, "as");
@@ -405,13 +405,13 @@ test_stream_seek_translated(apr_pool_t *pool)
/* Seek from inside of keyword to inside of keyword. */
SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
len = 9;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 9);
buf[9] = '\0';
SVN_TEST_STRING_ASSERT(buf, " expanded");
SVN_ERR(svn_stream_seek(translated_stream, mark));
len = 9;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 9);
buf[9] = '\0';
SVN_TEST_STRING_ASSERT(buf, " expanded");
@@ -419,7 +419,7 @@ test_stream_seek_translated(apr_pool_t *pool)
SVN_ERR(svn_stream_seek(translated_stream, mark));
SVN_ERR(svn_stream_skip(translated_stream, 6));
len = 3;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 3);
buf[len] = '\0';
SVN_TEST_STRING_ASSERT(buf, "ded");
@@ -427,13 +427,13 @@ test_stream_seek_translated(apr_pool_t *pool)
/* Seek from inside of keyword to outside of keyword. */
SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
len = 4;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 4);
buf[4] = '\0';
SVN_TEST_STRING_ASSERT(buf, " $Tw");
SVN_ERR(svn_stream_seek(translated_stream, mark));
len = 4;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 4);
buf[4] = '\0';
SVN_TEST_STRING_ASSERT(buf, " $Tw");
@@ -441,7 +441,7 @@ test_stream_seek_translated(apr_pool_t *pool)
SVN_ERR(svn_stream_seek(translated_stream, mark));
SVN_ERR(svn_stream_skip(translated_stream, 2));
len = 2;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 2);
buf[len] = '\0';
SVN_TEST_STRING_ASSERT(buf, "Tw");
@@ -449,13 +449,13 @@ test_stream_seek_translated(apr_pool_t *pool)
/* Seek from outside of keyword to outside of keyword. */
SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
len = 1;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 1);
buf[1] = '\0';
SVN_TEST_STRING_ASSERT(buf, "o");
SVN_ERR(svn_stream_seek(translated_stream, mark));
len = 1;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 1);
buf[1] = '\0';
SVN_TEST_STRING_ASSERT(buf, "o");
@@ -463,7 +463,7 @@ test_stream_seek_translated(apr_pool_t *pool)
SVN_ERR(svn_stream_seek(translated_stream, mark));
SVN_ERR(svn_stream_skip(translated_stream, 2));
len = 1;
- SVN_ERR(svn_stream_read(translated_stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
SVN_TEST_ASSERT(len == 0);
buf[len] = '\0';
SVN_TEST_STRING_ASSERT(buf, "");
@@ -524,7 +524,7 @@ test_stream_compressed_empty_file(apr_pool_t *pool)
pool, pool));
stream = svn_stream_compressed(empty_file_stream, pool);
len = sizeof(buf);
- SVN_ERR(svn_stream_read(stream, buf, &len));
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
if (len > 0)
return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
"Got unexpected result.");
@@ -727,9 +727,87 @@ test_stream_base64_2(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_stringbuf_from_stream(apr_pool_t *pool)
+{
+ const char *test_cases[] =
+ {
+ "",
+ "x",
+ "this string is longer than the default 64 minimum block size used"
+ "by the function under test",
+ NULL
+ };
+
+ const char **test_case;
+ for (test_case = test_cases; *test_case; ++test_case)
+ {
+ svn_stringbuf_t *result1, *result2, *result3, *result4;
+ svn_stringbuf_t *original = svn_stringbuf_create(*test_case, pool);
+
+ svn_stream_t *stream1 = svn_stream_from_stringbuf(original, pool);
+ svn_stream_t *stream2 = svn_stream_from_stringbuf(original, pool);
+
+ SVN_ERR(svn_stringbuf_from_stream(&result1, stream1, 0, pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result2, stream1, 0, pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result3, stream2, original->len,
+ pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result4, stream2, original->len,
+ pool));
+
+ /* C-string contents must match */
+ SVN_TEST_STRING_ASSERT(result1->data, original->data);
+ SVN_TEST_STRING_ASSERT(result2->data, "");
+ SVN_TEST_STRING_ASSERT(result3->data, original->data);
+ SVN_TEST_STRING_ASSERT(result4->data, "");
+
+ /* assumed length must match */
+ SVN_TEST_ASSERT(result1->len == original->len);
+ SVN_TEST_ASSERT(result2->len == 0);
+ SVN_TEST_ASSERT(result3->len == original->len);
+ SVN_TEST_ASSERT(result4->len == 0);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+empty_read_full_fn(void *baton, char *buffer, apr_size_t *len)
+{
+ *len = 0;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_stream_compressed_read_full(apr_pool_t *pool)
+{
+ svn_stream_t *stream, *empty_stream;
+ char buf[1];
+ apr_size_t len;
+
+ /* Reading an empty stream with read_full only support should not error. */
+ empty_stream = svn_stream_create(NULL, pool);
+
+ /* Create stream with only full read support. */
+ svn_stream_set_read2(empty_stream, NULL, empty_read_full_fn);
+
+ stream = svn_stream_compressed(empty_stream, pool);
+ len = sizeof(buf);
+ SVN_ERR(svn_stream_read_full(stream, buf, &len));
+ if (len > 0)
+ return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+ "Got unexpected result.");
+
+ SVN_ERR(svn_stream_close(stream));
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_stream_from_string,
@@ -752,5 +830,11 @@ struct svn_test_descriptor_t test_funcs[] =
"test base64 encoding/decoding streams"),
SVN_TEST_PASS2(test_stream_base64_2,
"base64 decoding allocation problem"),
+ SVN_TEST_PASS2(test_stringbuf_from_stream,
+ "test svn_stringbuf_from_stream"),
+ SVN_TEST_PASS2(test_stream_compressed_read_full,
+ "test compression for streams without partial read"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/string-test.c b/subversion/tests/libsvn_subr/string-test.c
index 735db18..ab0cc44 100644
--- a/subversion/tests/libsvn_subr/string-test.c
+++ b/subversion/tests/libsvn_subr/string-test.c
@@ -38,6 +38,7 @@
#include "svn_io.h"
#include "svn_error.h"
+#include "svn_sorts.h" /* MIN / MAX */
#include "svn_string.h" /* This includes <apr_*.h> */
#include "private/svn_string_private.h"
@@ -58,9 +59,8 @@ fail(apr_pool_t *pool, const char *fmt, ...)
/* Some of our own global variables, for simplicity. Yes,
simplicity. */
-svn_stringbuf_t *a = NULL, *b = NULL, *c = NULL;
-const char *phrase_1 = "hello, ";
-const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
+static const char *phrase_1 = "hello, ";
+static const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
@@ -68,7 +68,7 @@ const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
static svn_error_t *
test1(apr_pool_t *pool)
{
- a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
/* Test that length, data, and null-termination are correct. */
if ((a->len == strlen(phrase_1)) && ((strcmp(a->data, phrase_1)) == 0))
@@ -81,7 +81,7 @@ test1(apr_pool_t *pool)
static svn_error_t *
test2(apr_pool_t *pool)
{
- b = svn_stringbuf_ncreate(phrase_2, 16, pool);
+ svn_stringbuf_t *b = svn_stringbuf_ncreate(phrase_2, 16, pool);
/* Test that length, data, and null-termination are correct. */
if ((b->len == 16) && ((strncmp(b->data, phrase_2, 16)) == 0))
@@ -97,8 +97,8 @@ test3(apr_pool_t *pool)
char *tmp;
size_t old_len;
- a = svn_stringbuf_create(phrase_1, pool);
- b = svn_stringbuf_ncreate(phrase_2, 16, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *b = svn_stringbuf_ncreate(phrase_2, 16, pool);
tmp = apr_palloc(pool, (a->len + b->len + 1));
strcpy(tmp, a->data);
@@ -117,7 +117,7 @@ test3(apr_pool_t *pool)
static svn_error_t *
test4(apr_pool_t *pool)
{
- a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
svn_stringbuf_appendcstr(a, "new bytes to append");
/* Test that length, data, and null-termination are correct. */
@@ -132,7 +132,7 @@ test4(apr_pool_t *pool)
static svn_error_t *
test5(apr_pool_t *pool)
{
- a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
svn_stringbuf_appendbytes(a, "new bytes to append", 9);
/* Test that length, data, and null-termination are correct. */
@@ -147,9 +147,9 @@ test5(apr_pool_t *pool)
static svn_error_t *
test6(apr_pool_t *pool)
{
- a = svn_stringbuf_create(phrase_1, pool);
- b = svn_stringbuf_create(phrase_2, pool);
- c = svn_stringbuf_dup(a, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *b = svn_stringbuf_create(phrase_2, pool);
+ svn_stringbuf_t *c = svn_stringbuf_dup(a, pool);
/* Test that length, data, and null-termination are correct. */
if ((svn_stringbuf_compare(a, c)) && (! svn_stringbuf_compare(b, c)))
@@ -165,7 +165,7 @@ test7(apr_pool_t *pool)
char *tmp;
size_t tmp_len;
- c = svn_stringbuf_create(phrase_2, pool);
+ svn_stringbuf_t *c = svn_stringbuf_create(phrase_2, pool);
tmp_len = c->len;
tmp = apr_palloc(pool, c->len + 1);
@@ -185,7 +185,7 @@ test7(apr_pool_t *pool)
static svn_error_t *
test8(apr_pool_t *pool)
{
- c = svn_stringbuf_create(phrase_2, pool);
+ svn_stringbuf_t *c = svn_stringbuf_create(phrase_2, pool);
svn_stringbuf_setempty(c);
@@ -199,7 +199,7 @@ test8(apr_pool_t *pool)
static svn_error_t *
test9(apr_pool_t *pool)
{
- a = svn_stringbuf_create(phrase_1, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(phrase_1, pool);
svn_stringbuf_fillchar(a, '#');
@@ -379,7 +379,7 @@ test_find_char_backward(const char* data,
{
apr_size_t i;
- a = svn_stringbuf_create(data, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(data, pool);
i = svn_stringbuf_find_char_backward(a, ch);
if (i == pos)
@@ -391,7 +391,7 @@ test_find_char_backward(const char* data,
static svn_error_t *
test13(apr_pool_t *pool)
{
- a = svn_stringbuf_create("test, test", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("test, test", pool);
return test_find_char_backward(a->data, a->len, ',', 4, pool);
}
@@ -399,7 +399,7 @@ test13(apr_pool_t *pool)
static svn_error_t *
test14(apr_pool_t *pool)
{
- a = svn_stringbuf_create(",test test", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(",test test", pool);
return test_find_char_backward(a->data, a->len, ',', 0, pool);
}
@@ -407,7 +407,7 @@ test14(apr_pool_t *pool)
static svn_error_t *
test15(apr_pool_t *pool)
{
- a = svn_stringbuf_create("testing,", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("testing,", pool);
return test_find_char_backward(a->data,
a->len,
@@ -419,7 +419,7 @@ test15(apr_pool_t *pool)
static svn_error_t *
test16(apr_pool_t *pool)
{
- a = svn_stringbuf_create_empty(pool);
+ svn_stringbuf_t *a = svn_stringbuf_create_empty(pool);
return test_find_char_backward(a->data, a->len, ',', 0, pool);
}
@@ -427,7 +427,7 @@ test16(apr_pool_t *pool)
static svn_error_t *
test17(apr_pool_t *pool)
{
- a = svn_stringbuf_create("test test test", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("test test test", pool);
return test_find_char_backward(a->data,
a->len,
@@ -443,7 +443,7 @@ test_first_non_whitespace(const char *str,
{
apr_size_t i;
- a = svn_stringbuf_create(str, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(str, pool);
i = svn_stringbuf_first_non_whitespace(a);
@@ -474,8 +474,8 @@ test20(apr_pool_t *pool)
static svn_error_t *
test21(apr_pool_t *pool)
{
- a = svn_stringbuf_create(" \ttest\t\t \t ", pool);
- b = svn_stringbuf_create("test", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(" \ttest\t\t \t ", pool);
+ svn_stringbuf_t *b = svn_stringbuf_create("test", pool);
svn_stringbuf_strip_whitespace(a);
@@ -490,8 +490,8 @@ test_stringbuf_unequal(const char* str1,
const char* str2,
apr_pool_t *pool)
{
- a = svn_stringbuf_create(str1, pool);
- b = svn_stringbuf_create(str2, pool);
+ svn_stringbuf_t *a = svn_stringbuf_create(str1, pool);
+ svn_stringbuf_t *b = svn_stringbuf_create(str2, pool);
if (svn_stringbuf_compare(a, b))
return fail(pool, "test failed");
@@ -521,23 +521,58 @@ test24(apr_pool_t *pool)
SVN_TEST_ASSERT(length == 1);
SVN_TEST_STRING_ASSERT(buffer, "0");
- length = svn__i64toa(buffer, 0x8000000000000000ll);
+ length = svn__i64toa(buffer, APR_INT64_MIN);
SVN_TEST_ASSERT(length == 20);
SVN_TEST_STRING_ASSERT(buffer, "-9223372036854775808");
- length = svn__i64toa(buffer, 0x7fffffffffffffffll);
+ length = svn__i64toa(buffer, APR_INT64_MAX);
SVN_TEST_ASSERT(length == 19);
SVN_TEST_STRING_ASSERT(buffer, "9223372036854775807");
- length = svn__ui64toa(buffer, 0ull);
+ length = svn__ui64toa(buffer, 0u);
SVN_TEST_ASSERT(length == 1);
SVN_TEST_STRING_ASSERT(buffer, "0");
- length = svn__ui64toa(buffer, 0xffffffffffffffffull);
+ length = svn__ui64toa(buffer, APR_UINT64_MAX);
SVN_TEST_ASSERT(length == 20);
SVN_TEST_STRING_ASSERT(buffer, "18446744073709551615");
- return test_stringbuf_unequal("abc", "abb", pool);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+sub_test_base36(apr_uint64_t value, const char *base36)
+{
+ char buffer[SVN_INT64_BUFFER_SIZE];
+ apr_size_t length;
+ apr_size_t expected_length = strlen(base36);
+ const char *end = buffer;
+ apr_uint64_t result;
+
+ length = svn__ui64tobase36(buffer, value);
+ SVN_TEST_ASSERT(length == expected_length);
+ SVN_TEST_STRING_ASSERT(buffer, base36);
+
+ result = svn__base36toui64(&end, buffer);
+ SVN_TEST_ASSERT(end - buffer == length);
+ SVN_TEST_ASSERT(result == value);
+
+ result = svn__base36toui64(NULL, buffer);
+ SVN_TEST_ASSERT(result == value);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_base36(apr_pool_t *pool)
+{
+ SVN_ERR(sub_test_base36(0, "0"));
+ SVN_ERR(sub_test_base36(APR_UINT64_C(1234567890), "kf12oi"));
+ SVN_ERR(sub_test_base36(APR_UINT64_C(0x7fffffffffffffff), "1y2p0ij32e8e7"));
+ SVN_ERR(sub_test_base36(APR_UINT64_C(0x8000000000000000), "1y2p0ij32e8e8"));
+ SVN_ERR(sub_test_base36(APR_UINT64_MAX, "3w5e11264sgsf"));
+
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -554,7 +589,7 @@ expect_stringbuf_equal(const svn_stringbuf_t* str1,
static svn_error_t *
test_stringbuf_insert(apr_pool_t *pool)
{
- a = svn_stringbuf_create("st , ", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("st , ", pool);
svn_stringbuf_insert(a, 0, "teflon", 2);
SVN_TEST_STRING_ASSERT(a->data, "test , ");
@@ -587,7 +622,7 @@ test_stringbuf_insert(apr_pool_t *pool)
static svn_error_t *
test_stringbuf_remove(apr_pool_t *pool)
{
- a = svn_stringbuf_create("test hello, world!", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("test hello, world!", pool);
svn_stringbuf_remove(a, 0, 2);
SVN_TEST_STRING_ASSERT(a->data, "st hello, world!");
@@ -599,13 +634,21 @@ test_stringbuf_remove(apr_pool_t *pool)
SVN_TEST_STRING_ASSERT(a->data, "stell");
svn_stringbuf_remove(a, 1200, 393);
- return expect_stringbuf_equal(a, "stell", pool);
+ SVN_ERR(expect_stringbuf_equal(a, "stell", pool));
+
+ svn_stringbuf_remove(a, APR_SIZE_MAX, 2);
+ SVN_ERR(expect_stringbuf_equal(a, "stell", pool));
+
+ svn_stringbuf_remove(a, 1, APR_SIZE_MAX);
+ SVN_ERR(expect_stringbuf_equal(a, "s", pool));
+
+ return SVN_NO_ERROR;
}
static svn_error_t *
test_stringbuf_replace(apr_pool_t *pool)
{
- a = svn_stringbuf_create("odd with some world?", pool);
+ svn_stringbuf_t *a = svn_stringbuf_create("odd with some world?", pool);
svn_stringbuf_replace(a, 0, 3, "tester", 4);
SVN_TEST_STRING_ASSERT(a->data, "test with some world?");
@@ -637,6 +680,12 @@ test_stringbuf_replace(apr_pool_t *pool)
svn_stringbuf_ncreate("test hello\0-\0world!\0-\0!",
23, pool)));
+ svn_stringbuf_replace(a, 1, APR_SIZE_MAX, "x", 1);
+ SVN_ERR(expect_stringbuf_equal(a, "tx", pool));
+
+ svn_stringbuf_replace(a, APR_SIZE_MAX, APR_SIZE_MAX, "y", 1);
+ SVN_ERR(expect_stringbuf_equal(a, "txy", pool));
+
return SVN_NO_ERROR;
}
@@ -648,13 +697,14 @@ test_string_similarity(apr_pool_t *pool)
const char *stra;
const char *strb;
apr_size_t lcs;
- int score;
+ unsigned int score;
} tests[] =
{
-#define SCORE(lcs, len) ((2000 * (lcs) + (len)/2) / (len))
+#define SCORE(lcs, len) \
+ ((2 * SVN_STRING__SIM_RANGE_MAX * (lcs) + (len)/2) / (len))
/* Equality */
- {"", "", 0, 1000},
+ {"", "", 0, SVN_STRING__SIM_RANGE_MAX},
{"quoth", "quoth", 5, SCORE(5, 5+5)},
/* Deletion at start */
@@ -708,17 +758,20 @@ test_string_similarity(apr_pool_t *pool)
for (t = tests; t->stra; ++t)
{
apr_size_t lcs;
- const unsigned int score =
+ const apr_size_t score =
svn_cstring__similarity(t->stra, t->strb, &buffer, &lcs);
/*
fprintf(stderr,
- "lcs %s ~ %s score %.3f (%"APR_SIZE_T_FMT
- ") expected %.3f (%"APR_SIZE_T_FMT"))\n",
- t->stra, t->strb, score/1000.0, lcs, t->score/1000.0, t->lcs);
+ "lcs %s ~ %s score %.6f (%"APR_SIZE_T_FMT
+ ") expected %.6f (%"APR_SIZE_T_FMT"))\n",
+ t->stra, t->strb, score/1.0/SVN_STRING__SIM_RANGE_MAX,
+ lcs, t->score/1.0/SVN_STRING__SIM_RANGE_MAX, t->lcs);
*/
if (score != t->score)
- return fail(pool, "%s ~ %s score %.3f <> expected %.3f",
- t->stra, t->strb, score/1000.0, t->score/1000.0);
+ return fail(pool, "%s ~ %s score %.6f <> expected %.6f",
+ t->stra, t->strb,
+ score/1.0/SVN_STRING__SIM_RANGE_MAX,
+ t->score/1.0/SVN_STRING__SIM_RANGE_MAX);
if (lcs != t->lcs)
return fail(pool,
@@ -731,7 +784,8 @@ test_string_similarity(apr_pool_t *pool)
{
const svn_string_t foo = {"svn:foo", 4};
const svn_string_t bar = {"svn:bar", 4};
- if (1000 != svn_string__similarity(&foo, &bar, &buffer, NULL))
+ if (SVN_STRING__SIM_RANGE_MAX
+ != svn_string__similarity(&foo, &bar, &buffer, NULL))
return fail(pool, "'%s'[:4] ~ '%s'[:4] found different",
foo.data, bar.data);
}
@@ -739,6 +793,106 @@ test_string_similarity(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_string_matching(apr_pool_t *pool)
+{
+ const struct test_data_t
+ {
+ const char *a;
+ const char *b;
+ apr_size_t match_len;
+ apr_size_t rmatch_len;
+ }
+ tests[] =
+ {
+ /* edge cases */
+ {"", "", 0, 0},
+ {"", "x", 0, 0},
+ {"x", "", 0, 0},
+ {"x", "x", 1, 1},
+ {"", "1234567890abcdef", 0, 0},
+ {"1234567890abcdef", "", 0, 0},
+ {"1234567890abcdef", "1234567890abcdef", 16, 16},
+
+ /* left-side matches */
+ {"x", "y", 0, 0},
+ {"ax", "ay", 1, 0},
+ {"ax", "a", 1, 0},
+ {"a", "ay", 1, 0},
+ {"1234567890abcdef", "1234567890abcdeg", 15, 0},
+ {"1234567890abcdef_", "1234567890abcdefg", 16, 0},
+ {"12345678_0abcdef", "1234567890abcdeg", 8, 0},
+ {"1234567890abcdef", "12345678", 8, 0},
+ {"12345678", "1234567890abcdef", 8, 0},
+ {"12345678_0ab", "1234567890abcdef", 8, 0},
+
+ /* right-side matches */
+ {"xa", "ya", 0, 1},
+ {"xa", "a", 0, 1},
+ {"a", "ya", 0, 1},
+ {"_234567890abcdef", "1234567890abcdef", 0, 15},
+ {"_1234567890abcdef", "x1234567890abcdef", 0, 16},
+ {"1234567_90abcdef", "_1234567890abcdef", 0, 8},
+ {"1234567890abcdef", "90abcdef", 0, 8},
+ {"90abcdef", "1234567890abcdef", 0, 8},
+ {"8_0abcdef", "7890abcdef", 0, 7},
+
+ /* two-side matches */
+ {"bxa", "bya", 1, 1},
+ {"bxa", "ba", 1, 1},
+ {"ba", "bya", 1, 1},
+ {"1234567_90abcdef", "1234567890abcdef", 7, 8},
+ {"12345678_90abcdef", "1234567890abcdef", 8, 8},
+ {"12345678_0abcdef", "1234567890abcdef", 8, 7},
+ {"123456_abcdef", "1234sdffdssdf567890abcdef", 4, 6},
+ {"1234567890abcdef", "12345678ef", 8, 2},
+ {"x_234567890abcdef", "x1234567890abcdef", 1, 15},
+ {"1234567890abcdefx", "1234567890abcdex", 15, 1},
+
+ /* list terminator */
+ {NULL}
+ };
+
+ const struct test_data_t *test;
+ for (test = tests; test->a != NULL; ++test)
+ {
+ apr_size_t a_len = strlen(test->a);
+ apr_size_t b_len = strlen(test->b);
+ apr_size_t max_match = MIN(a_len, b_len);
+ apr_size_t match_len
+ = svn_cstring__match_length(test->a, test->b, max_match);
+ apr_size_t rmatch_len
+ = svn_cstring__reverse_match_length(test->a + a_len, test->b + b_len,
+ max_match);
+
+ SVN_TEST_ASSERT(match_len == test->match_len);
+ SVN_TEST_ASSERT(rmatch_len == test->rmatch_len);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_string_skip_prefix(apr_pool_t *pool)
+{
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "12345"),
+ "");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "123"),
+ "45");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", ""),
+ "12345");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("12345", "23"),
+ NULL);
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("1", "12"),
+ NULL);
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("", ""),
+ "");
+ SVN_TEST_STRING_ASSERT(svn_cstring_skip_prefix("", "12"),
+ NULL);
+
+ return SVN_NO_ERROR;
+}
+
/*
====================================================================
If you add a new test to this file, update this array.
@@ -747,7 +901,10 @@ test_string_similarity(apr_pool_t *pool)
*/
/* An array of all test functions */
-struct svn_test_descriptor_t test_funcs[] =
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test1,
@@ -783,7 +940,7 @@ struct svn_test_descriptor_t test_funcs[] =
SVN_TEST_PASS2(test16,
"find_char_backward; len = 0 case"),
SVN_TEST_PASS2(test17,
- "find_char_backward; no occurence case"),
+ "find_char_backward; no occurrence case"),
SVN_TEST_PASS2(test18,
"check whitespace removal; common case"),
SVN_TEST_PASS2(test19,
@@ -798,6 +955,8 @@ struct svn_test_descriptor_t test_funcs[] =
"compare stringbufs; same length, different content"),
SVN_TEST_PASS2(test24,
"verify i64toa"),
+ SVN_TEST_PASS2(test_base36,
+ "verify base36 conversion"),
SVN_TEST_PASS2(test_stringbuf_insert,
"check inserting into svn_stringbuf_t"),
SVN_TEST_PASS2(test_stringbuf_remove,
@@ -806,5 +965,11 @@ struct svn_test_descriptor_t test_funcs[] =
"check replacement in svn_stringbuf_t"),
SVN_TEST_PASS2(test_string_similarity,
"test string similarity scores"),
+ SVN_TEST_PASS2(test_string_matching,
+ "test string matching"),
+ SVN_TEST_PASS2(test_string_skip_prefix,
+ "test svn_cstring_skip_prefix()"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/subst_translate-test.c b/subversion/tests/libsvn_subr/subst_translate-test.c
index 1e555f2..0c4ee96 100644
--- a/subversion/tests/libsvn_subr/subst_translate-test.c
+++ b/subversion/tests/libsvn_subr/subst_translate-test.c
@@ -115,7 +115,7 @@ test_svn_subst_translate_string2_null_encoding_helper(apr_pool_t *pool)
svn_string_t *new_value = NULL;
svn_boolean_t translated_to_utf8 = FALSE;
svn_boolean_t translated_line_endings = TRUE;
- /* 'Æ', which is 0xc6 in both ISO-8859-1 and Windows-1252 */
+ /* The 'AE' ligature, which is 0xc6 in both ISO-8859-1 and Windows-1252 */
svn_string_t *source_string = svn_string_create("\xc6", pool);
SVN_ERR(svn_subst_translate_string2(&new_value, &translated_to_utf8,
@@ -397,7 +397,7 @@ test_svn_subst_long_keywords(apr_pool_t *pool)
"01234567890123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567";
- /* The longest keyword that can be expanded: the value is empty. */
+ /* The longest keyword that can be expanded: the value is empty. */
const char keyword_z[]
= "Q"
"01234567890123456789012345678901234567890123456789"
@@ -500,7 +500,9 @@ test_svn_subst_long_keywords(apr_pool_t *pool)
return SVN_NO_ERROR;
}
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_svn_subst_translate_string2,
@@ -519,3 +521,6 @@ struct svn_test_descriptor_t test_funcs[] =
"test long keywords (issue 4350)"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
+
diff --git a/subversion/tests/libsvn_subr/time-test.c b/subversion/tests/libsvn_subr/time-test.c
index 82e56b1..51fbe67 100644
--- a/subversion/tests/libsvn_subr/time-test.c
+++ b/subversion/tests/libsvn_subr/time-test.c
@@ -29,10 +29,10 @@
#include "../svn_test.h"
/* All these variables should refer to the same point in time. */
-apr_time_t test_timestamp = APR_TIME_C(1021316450966679);
-const char *test_timestring =
+static apr_time_t test_timestamp = APR_TIME_C(1021316450966679);
+static const char *test_timestring =
"2002-05-13T19:00:50.966679Z";
-const char *test_old_timestring =
+static const char *test_old_timestring =
"Mon 13 May 2002 22:00:50.966679 (day 133, dst 1, gmt_off 010800)";
@@ -339,7 +339,9 @@ test_parse_date(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_time_to_cstring,
@@ -354,3 +356,5 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_parse_date"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/translate-test.c b/subversion/tests/libsvn_subr/translate-test.c
index 9300503..2436bc7 100644
--- a/subversion/tests/libsvn_subr/translate-test.c
+++ b/subversion/tests/libsvn_subr/translate-test.c
@@ -48,7 +48,7 @@
/*** Helpers ***/
/* (Almost) all the tests share the same test data. */
-const char *lines[] =
+static const char *lines[] =
{
"Line 1: fairly boring subst test data... blah blah",
"Line 2: fairly boring subst test data... blah blah.",
@@ -223,15 +223,12 @@ random_eol_marker(void)
static svn_error_t *
create_file(const char *fname, const char *eol_str, apr_pool_t *pool)
{
- apr_status_t apr_err;
apr_file_t *f;
apr_size_t i, j;
- apr_err = apr_file_open(&f, fname,
+ SVN_ERR(svn_io_file_open(&f, fname,
(APR_WRITE | APR_CREATE | APR_EXCL | APR_BINARY),
- APR_OS_DEFAULT, pool);
- if (apr_err)
- return svn_error_create(apr_err, NULL, fname);
+ APR_OS_DEFAULT, pool));
for (i = 0; i < (sizeof(lines) / sizeof(*lines)); i++)
{
@@ -243,45 +240,13 @@ create_file(const char *fname, const char *eol_str, apr_pool_t *pool)
fprintf() doing a newline conversion? */
for (j = 0; this_eol_str[j]; j++)
{
- apr_err = apr_file_putc(this_eol_str[j], f);
- if (apr_err)
- return svn_error_create(apr_err, NULL, fname);
+ SVN_ERR(svn_io_file_putc(this_eol_str[j], f, pool));
}
}
- apr_err = apr_file_close(f);
- if (apr_err)
- return svn_error_create(apr_err, NULL, fname);
-
- return SVN_NO_ERROR;
-}
-
-
-/* If FNAME is a regular file, remove it; if it doesn't exist at all,
- return success. Otherwise, return error. */
-static svn_error_t *
-remove_file(const char *fname, apr_pool_t *pool)
-{
- apr_status_t apr_err;
- apr_finfo_t finfo;
-
- if (apr_stat(&finfo, fname, APR_FINFO_TYPE, pool) == APR_SUCCESS)
- {
- if (finfo.filetype == APR_REG)
- {
- apr_err = apr_file_remove(fname, pool);
- if (apr_err)
- return svn_error_create(apr_err, NULL, fname);
- }
- else
- return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
- "non-file '%s' is in the way", fname);
- }
-
- return SVN_NO_ERROR;
+ return svn_error_trace(svn_io_file_close(f, pool));
}
-
/* Set up, run, and verify the results of a substitution.
*
* Create a file TEST_NAME.src using global `lines' as the initial
@@ -325,14 +290,14 @@ substitute_and_verify(const char *test_name,
apr_size_t idx = 0;
apr_size_t i;
const char *expect[(sizeof(lines) / sizeof(*lines))];
- const char *src_fname = apr_pstrcat(pool, test_name, ".src", (char *)NULL);
- const char *dst_fname = apr_pstrcat(pool, test_name, ".dst", (char *)NULL);
+ const char *src_fname = apr_pstrcat(pool, test_name, ".src", SVN_VA_NULL);
+ const char *dst_fname = apr_pstrcat(pool, test_name, ".dst", SVN_VA_NULL);
svn_string_t *val;
apr_pool_t *subpool = svn_pool_create(pool);
/** Clean up from previous tests, set up src data, and convert. **/
- SVN_ERR(remove_file(src_fname, pool));
- SVN_ERR(remove_file(dst_fname, pool));
+ SVN_ERR(svn_io_remove_file2(src_fname, TRUE, pool));
+ SVN_ERR(svn_io_remove_file2(dst_fname, TRUE, pool));
SVN_ERR(create_file(src_fname, src_eol, pool));
if (rev)
@@ -395,7 +360,7 @@ substitute_and_verify(const char *test_name,
else
{
svn_error_clear(err);
- SVN_ERR(remove_file(src_fname, pool));
+ SVN_ERR(svn_io_remove_file2(src_fname, FALSE, pool));
return SVN_NO_ERROR;
}
@@ -419,27 +384,27 @@ substitute_and_verify(const char *test_name,
"Valid $LastChangedRevision: ",
rev,
" $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[5 - 1] =
apr_pstrcat(pool, "Line 5: ",
"Valid $Rev: ", rev, " $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[26 - 1] =
apr_pstrcat(pool, "Line 26: ",
"Emptily expanded keyword $Rev: ", rev," $.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[29 - 1] =
apr_pstrcat(pool, "Line 29: ",
"Valid $LastChangedRevision: ",
rev,
" $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[30 - 1] =
apr_pstrcat(pool, "Line 30: ",
"Valid $Rev: ",
rev,
" $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
@@ -462,31 +427,31 @@ substitute_and_verify(const char *test_name,
"Valid $LastChangedDate: ",
date,
" $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[13 - 1] =
apr_pstrcat(pool, "Line 13: ",
"Valid $Date: ", date, " $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[33 - 1] =
apr_pstrcat(pool, "Line 33: ",
"Valid $LastChangedDate: ",
date,
" $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[34 - 1] =
apr_pstrcat(pool, "Line 34: ",
"Valid $Date: ", date, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[51 - 1] =
apr_pstrcat(pool, "Line 51: ",
"same, but with embedded keyword ",
"$$$$$$$$Date: ", date, " $$$$$$$$$$.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[52 - 1] =
apr_pstrcat(pool, "Line 52: ",
"same, with expanded, empty keyword ",
"$$$$$$Date: ", date, " $$$$$$.",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
@@ -511,46 +476,46 @@ substitute_and_verify(const char *test_name,
"Valid $LastChangedBy: ",
author,
" $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[9 - 1] =
apr_pstrcat(pool, "Line 9: ",
"Valid $Author: ", author, " $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[37 - 1] =
apr_pstrcat(pool, "Line 37: ",
"Valid $LastChangedBy: ", author,
- " $, started expanded.", (char *)NULL);
+ " $, started expanded.", SVN_VA_NULL);
expect[38 - 1] =
apr_pstrcat(pool, "Line 38: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[46 - 1] =
apr_pstrcat(pool, "Line 46: ",
"Empty $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[71 - 1] =
- apr_pstrcat(pool, ".$veR$Author: ", author, " $", (char *)NULL);
+ apr_pstrcat(pool, ".$veR$Author: ", author, " $", SVN_VA_NULL);
expect[74 - 1] =
apr_pstrcat(pool, "Line 74: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[79 - 1] =
apr_pstrcat(pool, "Line 79: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[80 - 1] =
apr_pstrcat(pool, "Line 80: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[81 - 1] =
apr_pstrcat(pool, "Line 81: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[82 - 1] =
apr_pstrcat(pool, "Line 82: ",
"Valid $Author: ", author, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
@@ -581,23 +546,23 @@ substitute_and_verify(const char *test_name,
expect[16 - 1] =
apr_pstrcat(pool, "Line 16: ",
"Valid $HeadURL: ", url, " $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[17 - 1] =
apr_pstrcat(pool, "Line 17: ",
"Valid $URL: ", url, " $, started unexpanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[41 - 1] =
apr_pstrcat(pool, "Line 41: ",
"Valid $HeadURL: ", url, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[42 - 1] =
apr_pstrcat(pool, "Line 42: ",
"Valid $URL: ", url, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[75 - 1] =
apr_pstrcat(pool, "Line 75: ",
"Valid $URL: ", url, " $, started expanded.",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
@@ -622,14 +587,14 @@ substitute_and_verify(const char *test_name,
"Two keywords back to back: "
"$Author: ", author, " $"
"$Rev: ", rev, " $.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[49 - 1] =
apr_pstrcat(pool, "Line 49: ",
"One keyword, one not, back to back: "
"$Author: ", author, " $Rev$.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[70 - 1] =
- apr_pstrcat(pool, "$Author: ", author, " $Rev$.", (char *)NULL);
+ apr_pstrcat(pool, "$Author: ", author, " $Rev$.", SVN_VA_NULL);
}
/* Else Lines 48, 49, and 70 remain unchanged. */
}
@@ -641,14 +606,14 @@ substitute_and_verify(const char *test_name,
apr_pstrcat(pool, "Line 48: ",
"Two keywords back to back: "
"$Author$$Rev: ", rev, " $.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[49 - 1] =
apr_pstrcat(pool, "Line 49: ",
"One keyword, one not, back to back: "
"$Author$Rev: ", rev, " $.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[70 - 1] =
- apr_pstrcat(pool, "$Author$Rev: ", rev, " $.", (char *)NULL);
+ apr_pstrcat(pool, "$Author$Rev: ", rev, " $.", SVN_VA_NULL);
}
/* Else Lines 48, 49, and 70 remain unchanged. */
}
@@ -660,14 +625,14 @@ substitute_and_verify(const char *test_name,
apr_pstrcat(pool, "Line 48: ",
"Two keywords back to back: "
"$Author: ", author, " $$Rev$.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[49 - 1] =
apr_pstrcat(pool, "Line 49: ",
"One keyword, one not, back to back: "
"$Author: ", author, " $Rev$.",
- (char *)NULL);
+ SVN_VA_NULL);
expect[70 - 1] =
- apr_pstrcat(pool, "$Author: ", author, " $Rev$.", (char *)NULL);
+ apr_pstrcat(pool, "$Author: ", author, " $Rev$.", SVN_VA_NULL);
}
/* Else Lines 48, 49, and 70 remain unchanged. */
}
@@ -684,14 +649,14 @@ substitute_and_verify(const char *test_name,
"keyword in a keyword: $Author: ",
author,
" $Date$ $",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
expect[24 - 1] =
apr_pstrcat(pool, "Line 24: ",
"keyword in a keyword: $Author$Date$ $",
- (char *)NULL);
+ SVN_VA_NULL);
}
}
else if (date && (! author))
@@ -703,7 +668,7 @@ substitute_and_verify(const char *test_name,
"keyword in a keyword: $Author: $Date: ",
date,
" $ $",
- (char *)NULL);
+ SVN_VA_NULL);
}
/* Else Line 24 remains unchanged. */
}
@@ -716,14 +681,14 @@ substitute_and_verify(const char *test_name,
"keyword in a keyword: $Author: ",
author,
" $Date$ $",
- (char *)NULL);
+ SVN_VA_NULL);
}
else /* unexpand */
{
expect[24 - 1] =
apr_pstrcat(pool, "Line 24: ",
"keyword in a keyword: $Author$Date$ $",
- (char *)NULL);
+ SVN_VA_NULL);
}
}
/* Else neither author nor date, so Line 24 remains unchanged. */
@@ -769,8 +734,8 @@ substitute_and_verify(const char *test_name,
}
/* Clean up this test, since successful. */
- SVN_ERR(remove_file(src_fname, pool));
- SVN_ERR(remove_file(dst_fname, pool));
+ SVN_ERR(svn_io_remove_file2(src_fname, FALSE, pool));
+ SVN_ERR(svn_io_remove_file2(dst_fname, FALSE, pool));
return SVN_NO_ERROR;
}
@@ -862,7 +827,7 @@ static svn_error_t *
mixed_to_lf(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool);
+ ("mixed_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool);
}
@@ -1096,10 +1061,10 @@ static svn_error_t *
unexpand_author(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("unexpand_author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("unexpand_author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1109,11 +1074,11 @@ static svn_error_t *
unexpand_date(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("date", "\n", NULL, 0,
+ ("unexpand_date", "\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("date", "\r\n", NULL, 0,
+ ("unexpand_date", "\r\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1124,11 +1089,11 @@ static svn_error_t *
unexpand_author_date(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_date", "\n", NULL, 0,
+ ("unexpand_author_date", "\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author_date", "\r\n", NULL, 0,
+ ("unexpand_author_date", "\r\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1139,11 +1104,11 @@ static svn_error_t *
unexpand_author_rev(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_rev", "\n", NULL, 0,
+ ("unexpand_author_rev", "\n", NULL, 0,
"1729", NULL, "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author_rev", "\r\n", NULL, 0,
+ ("unexpand_author_rev", "\r\n", NULL, 0,
"1729", NULL, "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1154,11 +1119,11 @@ static svn_error_t *
unexpand_rev(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("rev", "\n", NULL, 0,
+ ("unexpand_rev", "\n", NULL, 0,
"1729", NULL, NULL, NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("rev", "\r\n", NULL, 0,
+ ("unexpand_rev", "\r\n", NULL, 0,
"1729", NULL, NULL, NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1169,11 +1134,11 @@ static svn_error_t *
unexpand_rev_url(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("rev_url", "\n", NULL, 0,
+ ("unexpand_rev_url", "\n", NULL, 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
SVN_ERR(substitute_and_verify
- ("rev_url", "\r\n", NULL, 0,
+ ("unexpand_rev_url", "\r\n", NULL, 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
return SVN_NO_ERROR;
@@ -1184,7 +1149,7 @@ static svn_error_t *
unexpand_author_date_rev_url(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_date_rev_url", "\n", NULL, 0,
+ ("unexpand_author_date_rev_url", "\n", NULL, 0,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1192,7 +1157,7 @@ unexpand_author_date_rev_url(apr_pool_t *pool)
1, pool));
SVN_ERR(substitute_and_verify
- ("author_date_rev_url", "\r\n", NULL, 0,
+ ("unexpand_author_date_rev_url", "\r\n", NULL, 0,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1210,7 +1175,7 @@ static svn_error_t *
lf_to_crlf_unexpand_author(apr_pool_t *pool)
{
return substitute_and_verify
- ("lf_to_crlf_author", "\n", "\r\n", 0,
+ ("lf_to_crlf_unexpand_author", "\n", "\r\n", 0,
NULL, NULL, "jrandom", NULL, 0, pool);
}
@@ -1219,7 +1184,7 @@ static svn_error_t *
mixed_to_lf_unexpand_author_date(apr_pool_t *pool)
{
return substitute_and_verify
- ("mixed_to_lf_author_date", NULL, "\n", 1,
+ ("mixed_to_lf_unexpand_author_date", NULL, "\n", 1,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool);
}
@@ -1228,7 +1193,7 @@ static svn_error_t *
crlf_to_cr_unexpand_author_rev(apr_pool_t *pool)
{
return substitute_and_verify
- ("crlf_to_cr_author_rev", "\r\n", "\r", 0,
+ ("crlf_to_cr_unexpand_author_rev", "\r\n", "\r", 0,
"1729", NULL, "jrandom", NULL, 0, pool);
}
@@ -1237,7 +1202,7 @@ static svn_error_t *
cr_to_crlf_unexpand_rev(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_crlf_rev", "\r", "\r\n", 0,
+ ("cr_to_crlf_unexpand_rev", "\r", "\r\n", 0,
"1729", NULL, NULL, NULL, 0, pool);
}
@@ -1246,7 +1211,7 @@ static svn_error_t *
cr_to_crlf_unexpand_rev_url(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_crlf_rev_url", "\r", "\r\n", 0,
+ ("cr_to_crlf_unexpand_rev_url", "\r", "\r\n", 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool);
}
@@ -1255,7 +1220,7 @@ static svn_error_t *
mixed_to_crlf_unexpand_author_date_rev_url(apr_pool_t *pool)
{
return substitute_and_verify
- ("mixed_to_crlf_author_date_rev_url", NULL, "\r\n", 1,
+ ("mixed_to_crlf_unexpand_author_date_rev_url", NULL, "\r\n", 1,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1268,7 +1233,9 @@ mixed_to_crlf_unexpand_author_date_rev_url(apr_pool_t *pool)
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 7;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
/* The no-op conversion. */
@@ -1362,3 +1329,5 @@ struct svn_test_descriptor_t test_funcs[] =
"mixed_to_crlf; unexpand author, date, rev, url"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/utf-test.c b/subversion/tests/libsvn_subr/utf-test.c
index 2028e14..dd81ccd 100644
--- a/subversion/tests/libsvn_subr/utf-test.c
+++ b/subversion/tests/libsvn_subr/utf-test.c
@@ -25,6 +25,7 @@
#include "svn_utf.h"
#include "svn_pools.h"
+#include "private/svn_string_private.h"
#include "private/svn_utf_private.h"
/* Random number seed. Yes, it's global, just pretend you can't see it. */
@@ -226,7 +227,7 @@ test_utf_cstring_to_utf8_ex2(apr_pool_t *pool)
const char *expected_result;
const char *from_page;
} tests[] = {
- {"ascii text\n", "ascii text\n", "unexistant-page"},
+ {"ascii text\n", "ascii text\n", "unexistent-page"},
{"Edelwei\xdf", "Edelwei\xc3\x9f", "ISO-8859-1"}
};
@@ -266,7 +267,7 @@ test_utf_cstring_from_utf8_ex2(apr_pool_t *pool)
const char *expected_result;
const char *to_page;
} tests[] = {
- {"ascii text\n", "ascii text\n", "unexistant-page"},
+ {"ascii text\n", "ascii text\n", "unexistent-page"},
{"Edelwei\xc3\x9f", "Edelwei\xdf", "ISO-8859-1"}
};
@@ -294,10 +295,540 @@ test_utf_cstring_from_utf8_ex2(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+/* Test normalization-independent UTF-8 string comparison */
+static svn_error_t *
+test_utf_collated_compare(apr_pool_t *pool)
+{
+ /* Normalized: NFC */
+ static const char nfc[] =
+ "\xe1\xb9\xa8" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "\xe1\xb8\x87" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "\xe1\xb8\x9d" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "\xc5\xa1" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xe1\xbb\x9d" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ /* Normalized: NFD */
+ static const char nfd[] =
+ "S\xcc\xa3\xcc\x87" /* S with dot above and below */
+ "u\xcc\x8a" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "v\xcc\x83" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "r\xcc\x8f" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "i\xcc\x88\xcc\x81" /* i with diaeresis and acute */
+ "o\xcc\x9b\xcc\x80" /* o with grave and hook */
+ "n\xcc\xad"; /* n with circumflex below */
+
+ /* Mixed, denormalized */
+ static const char mixup[] =
+ "S\xcc\x87\xcc\xa3" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "o\xcc\x80\xcc\x9b" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ static const char longer[] =
+ "\xe1\xb9\xa8" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "\xe1\xb8\x87" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "\xe1\xb8\x9d" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "\xc5\xa1" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xe1\xbb\x9d" /* o with grave and hook */
+ "\xe1\xb9\x8b" /* n with circumflex below */
+ "X";
+
+ static const char shorter[] =
+ "\xe1\xb9\xa8" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "\xe1\xb8\x87" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "\xe1\xb8\x9d" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "\xc5\xa1" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xe1\xbb\x9d"; /* o with grave and hook */
+
+ static const char lowcase[] =
+ "s\xcc\x87\xcc\xa3" /* s with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "o\xcc\x80\xcc\x9b" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ static const struct utfcmp_test_t {
+ const char *stra;
+ char op;
+ const char *strb;
+ const char *taga;
+ const char *tagb;
+ } utfcmp_tests[] = {
+ /* Empty key */
+ {"", '=', "", "empty", "empty"},
+ {"", '<', "a", "empty", "nonempty"},
+ {"a", '>', "", "nonempty", "empty"},
+
+ /* Deterministic ordering */
+ {"a", '<', "b", "a", "b"},
+ {"b", '<', "c", "b", "c"},
+ {"a", '<', "c", "a", "c"},
+
+ /* Normalized equality */
+ {nfc, '=', nfd, "nfc", "nfd"},
+ {nfd, '=', nfc, "nfd", "nfc"},
+ {nfc, '=', mixup, "nfc", "mixup"},
+ {nfd, '=', mixup, "nfd", "mixup"},
+ {mixup, '=', nfd, "mixup", "nfd"},
+ {mixup, '=', nfc, "mixup", "nfc"},
+
+ /* Key length */
+ {nfc, '<', longer, "nfc", "longer"},
+ {longer, '>', nfc, "longer", "nfc"},
+ {nfd, '>', shorter, "nfd", "shorter"},
+ {shorter, '<', nfd, "shorter", "nfd"},
+ {mixup, '<', lowcase, "mixup", "lowcase"},
+ {lowcase, '>', mixup, "lowcase", "mixup"},
+
+ {NULL, 0, NULL, NULL, NULL}
+ };
+
+
+ const struct utfcmp_test_t *ut;
+ svn_membuf_t bufa, bufb;
+ svn_membuf__create(&bufa, 0, pool);
+ svn_membuf__create(&bufb, 0, pool);
+
+ srand(111);
+ for (ut = utfcmp_tests; ut->stra; ++ut)
+ {
+ const svn_boolean_t implicit_size = (rand() % 17) & 1;
+ const apr_size_t lena = (implicit_size
+ ? SVN_UTF__UNKNOWN_LENGTH : strlen(ut->stra));
+ const apr_size_t lenb = (implicit_size
+ ? SVN_UTF__UNKNOWN_LENGTH : strlen(ut->strb));
+ int result;
+
+ SVN_ERR(svn_utf__normcmp(&result,
+ ut->stra, lena, ut->strb, lenb,
+ &bufa, &bufb));
+
+ /* UCS-4 debugging dump of the decomposed strings
+ {
+ const apr_int32_t *const ucsbufa = bufa.data;
+ const apr_int32_t *const ucsbufb = bufb.data;
+ apr_size_t i;
+
+ printf("(%c)%7s %c %s\n", ut->op,
+ ut->taga, (!result ? '=' : (result < 0 ? '<' : '>')), ut->tagb);
+
+ for (i = 0; i < bufa.size || i < bufb.size; ++i)
+ {
+ if (i < bufa.size && i < bufb.size)
+ printf(" U+%04X U+%04X\n", ucsbufa[i], ucsbufb[i]);
+ else if (i < bufa.size)
+ printf(" U+%04X\n", ucsbufa[i]);
+ else
+ printf(" U+%04X\n", ucsbufb[i]);
+ }
+ }
+ */
+
+ if (('=' == ut->op && 0 != result)
+ || ('<' == ut->op && 0 <= result)
+ || ('>' == ut->op && 0 >= result))
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "Ut->Op '%s' %c '%s' but '%s' %c '%s'",
+ ut->taga, ut->op, ut->tagb,
+ ut->taga, (!result ? '=' : (result < 0 ? '<' : '>')), ut->tagb);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+
+static svn_error_t *
+test_utf_pattern_match(apr_pool_t *pool)
+{
+ static const struct glob_test_t {
+ svn_boolean_t sql_like;
+ svn_boolean_t matches;
+ const char *pattern;
+ const char *string;
+ const char *escape;
+ } glob_tests[] = {
+#define LIKE_MATCH TRUE, TRUE
+#define LIKE_FAIL TRUE, FALSE
+#define GLOB_MATCH FALSE, TRUE
+#define GLOB_FAIL FALSE, FALSE
+
+ {LIKE_FAIL, "", "test", NULL},
+ {GLOB_FAIL, "", "test", NULL},
+ {LIKE_FAIL, "", "%", NULL},
+ {GLOB_FAIL, "", "*", NULL},
+ {LIKE_FAIL, "test", "%", NULL},
+ {GLOB_FAIL, "test", "*", NULL},
+ {LIKE_MATCH, "test", "test", NULL},
+ {GLOB_MATCH, "test", "test", NULL},
+ {LIKE_MATCH, "t\xe1\xb8\x9dst", "te\xcc\xa7\xcc\x86st", NULL},
+ {GLOB_MATCH, "te\xcc\xa7\xcc\x86st", "t\xe1\xb8\x9dst", NULL},
+
+ {LIKE_FAIL, "test", "test", "\xe1\xb8\x9d"}, /* escape char not ascii */
+ {LIKE_FAIL, "test", "test", ""}, /* empty escape string */
+
+ {LIKE_MATCH, "te#st", "test", "#"},
+ {LIKE_FAIL, "te#st", "test", NULL},
+ {GLOB_MATCH, "te\\st", "test", NULL},
+ {LIKE_MATCH, "te##st", "te#st", "#"},
+ {LIKE_FAIL, "te##st", "te#st", NULL},
+ {GLOB_MATCH, "te\\\\st", "te\\st", NULL},
+ {GLOB_FAIL, "te\\\\st", "te\\st", "\\"}, /* escape char with glob */
+ {LIKE_FAIL, "te#%t", "te%t", NULL},
+ {LIKE_MATCH, "te#%t", "te%t", "#"},
+ {GLOB_MATCH, "te\\*t", "te*t", NULL},
+ {LIKE_FAIL, "te#%t", "test", NULL},
+ {GLOB_FAIL, "te\\*t", "test", NULL},
+ {LIKE_FAIL, "te#_t", "te_t", NULL},
+ {LIKE_MATCH, "te#_t", "te_t", "#"},
+ {GLOB_MATCH, "te\\?t", "te?t", NULL},
+ {LIKE_FAIL, "te#_t", "test", NULL},
+ {LIKE_FAIL, "te#_t", "test", "#"},
+ {GLOB_FAIL, "te\\?t", "test", NULL},
+
+ {LIKE_MATCH, "_est", "test", NULL},
+ {GLOB_MATCH, "?est", "test", NULL},
+ {LIKE_MATCH, "te_t", "test", NULL},
+ {GLOB_MATCH, "te?t", "test", NULL},
+ {LIKE_MATCH, "tes_", "test", NULL},
+ {GLOB_MATCH, "tes?", "test", NULL},
+ {LIKE_FAIL, "test_", "test", NULL},
+ {GLOB_FAIL, "test?", "test", NULL},
+
+ {LIKE_MATCH, "[s%n]", "[subversion]", NULL},
+ {GLOB_FAIL, "[s*n]", "[subversion]", NULL},
+ {LIKE_MATCH, "#[s%n]", "[subversion]", "#"},
+ {GLOB_MATCH, "\\[s*n]", "[subversion]", NULL},
+
+ {GLOB_MATCH, ".[\\-\\t]", ".t", NULL},
+ {GLOB_MATCH, "test*?*[a-z]*", "testgoop", NULL},
+ {GLOB_MATCH, "te[^x]t", "test", NULL},
+ {GLOB_MATCH, "te[^abc]t", "test", NULL},
+ {GLOB_MATCH, "te[^x]t", "test", NULL},
+ {GLOB_MATCH, "te[!x]t", "test", NULL},
+ {GLOB_FAIL, "te[^x]t", "text", NULL},
+ {GLOB_FAIL, "te[^\\x]t", "text", NULL},
+ {GLOB_FAIL, "te[^x\\", "text", NULL},
+ {GLOB_FAIL, "te[/]t", "text", NULL},
+ {GLOB_MATCH, "te[r-t]t", "test", NULL},
+ {GLOB_MATCH, "te[r-Tz]t", "tezt", NULL},
+ {GLOB_FAIL, "te[R-T]t", "tent", NULL},
+/* {GLOB_MATCH, "tes[]t]", "test", NULL}, */
+ {GLOB_MATCH, "tes[t-]", "test", NULL},
+ {GLOB_MATCH, "tes[t-]]", "test]", NULL},
+ {GLOB_FAIL, "tes[t-]]", "test", NULL},
+ {GLOB_FAIL, "tes[u-]", "test", NULL},
+ {GLOB_FAIL, "tes[t-]", "tes[t-]", NULL},
+ {GLOB_MATCH, "test[/-/]", "test/", NULL},
+ {GLOB_MATCH, "test[\\/-/]", "test/", NULL},
+ {GLOB_MATCH, "test[/-\\/]", "test/", NULL},
+
+#undef LIKE_MATCH
+#undef LIKE_FAIL
+#undef GLOB_MATCH
+#undef GLOB_FAIL
+
+ {FALSE, FALSE, NULL, NULL, NULL}
+ };
+
+ const struct glob_test_t *gt;
+ svn_membuf_t bufa, bufb, bufc;
+ svn_membuf__create(&bufa, 0, pool);
+ svn_membuf__create(&bufb, 0, pool);
+ svn_membuf__create(&bufc, 0, pool);
+
+ srand(79);
+ for (gt = glob_tests; gt->pattern; ++gt)
+ {
+ const svn_boolean_t implicit_size = (rand() % 13) & 1;
+ const apr_size_t lenptn = (implicit_size
+ ? SVN_UTF__UNKNOWN_LENGTH
+ : strlen(gt->pattern));
+ const apr_size_t lenstr = (implicit_size
+ ? SVN_UTF__UNKNOWN_LENGTH
+ : strlen(gt->string));
+ const apr_size_t lenesc = (implicit_size
+ ? SVN_UTF__UNKNOWN_LENGTH
+ : (gt->escape ? strlen(gt->escape) : 0));
+ svn_boolean_t match;
+ svn_error_t *err;
+
+
+ err = svn_utf__glob(&match,
+ gt->pattern, lenptn,
+ gt->string, lenstr,
+ gt->escape, lenesc,
+ gt->sql_like, &bufa, &bufb, &bufc);
+
+ if (!gt->sql_like && gt->escape && !err)
+ return svn_error_create
+ (SVN_ERR_TEST_FAILED, err, "Failed to detect GLOB ESCAPE");
+
+ if ((err && gt->matches)
+ || (!err && !match != !gt->matches))
+ {
+ if (gt->sql_like)
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, err,
+ "Wrong result: %s'%s' LIKE '%s'%s%s%s%s",
+ (gt->matches ? "NOT " : ""), gt->string, gt->pattern,
+ (gt->escape ? " ESCAPE " : ""), (gt->escape ? "'" : ""),
+ (gt->escape ? gt->escape : ""), (gt->escape ? "'" : ""));
+ else
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, err, "Wrong result: %s%s GLOB %s",
+ (gt->matches ? "NOT " : ""), gt->string, gt->pattern);
+ }
+
+ if (err)
+ svn_error_clear(err);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_utf_fuzzy_escape(apr_pool_t *pool)
+{
+
+ /* Accented latin, mixed normalization */
+ static const char mixup[] =
+ "S\xcc\x87\xcc\xa3" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "o\xcc\x80\xcc\x9b" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ /* As above, but latin lowercase 'o' replaced with Greek 'omicron' */
+ static const char greekish[] =
+ "S\xcc\x87\xcc\xa3" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xce\xbf\xcc\x80\xcc\x9b" /* omicron with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ /* More interesting invalid characters. */
+ static const char invalid[] =
+ "Not Unicode: \xef\xb7\x91;" /* U+FDD1 */
+ "Out of range: \xf4\x90\x80\x81;" /* U+110001 */
+ "Not UTF-8: \xe6;"
+ "Null byte: \0;";
+
+ const char *fuzzy;
+
+ fuzzy = svn_utf__fuzzy_escape(mixup, strlen(mixup), pool);
+ SVN_TEST_ASSERT(0 == strcmp(fuzzy, "Subversion"));
+
+ fuzzy = svn_utf__fuzzy_escape(greekish, strlen(greekish), pool);
+ SVN_TEST_ASSERT(0 == strcmp(fuzzy, "Subversi{U+03BF}n"));
+
+ fuzzy = svn_utf__fuzzy_escape(invalid, sizeof(invalid) - 1, pool);
+ /*fprintf(stderr, "%s\n", fuzzy);*/
+ SVN_TEST_ASSERT(0 == strcmp(fuzzy,
+ "Not Unicode: {U?FDD1};"
+ "Out of range: ?\\F4?\\90?\\80?\\81;"
+ "Not UTF-8: ?\\E6;"
+ "Null byte: \\0;"));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_utf_is_normalized(apr_pool_t *pool)
+{
+ /* Normalized: NFC */
+ static const char nfc[] =
+ "\xe1\xb9\xa8" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "\xe1\xb8\x87" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "\xe1\xb8\x9d" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "\xc5\xa1" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xe1\xbb\x9d" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ /* Normalized: NFD */
+ static const char nfd[] =
+ "S\xcc\xa3\xcc\x87" /* S with dot above and below */
+ "u\xcc\x8a" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "v\xcc\x83" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "r\xcc\x8f" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "i\xcc\x88\xcc\x81" /* i with diaeresis and acute */
+ "o\xcc\x9b\xcc\x80" /* o with grave and hook */
+ "n\xcc\xad"; /* n with circumflex below */
+
+ /* Mixed, denormalized */
+ static const char mixup[] =
+ "S\xcc\x87\xcc\xa3" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "b\xcc\xb1" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "e\xcc\xa7\xcc\x86" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "s\xcc\x8c" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "o\xcc\x80\xcc\x9b" /* o with grave and hook */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ /* Invalid UTF-8 */
+ static const char invalid[] =
+ "\xe1\xb9\xa8" /* S with dot above and below */
+ "\xc5\xaf" /* u with ring */
+ "\xe1\xb8\x87" /* b with macron below */
+ "\xe1\xb9\xbd" /* v with tilde */
+ "\xe1\xb8\x9d" /* e with breve and cedilla */
+ "\xc8\x91" /* r with double grave */
+ "\xc5\xa1" /* s with caron */
+ "\xe1\xb8\xaf" /* i with diaeresis and acute */
+ "\xe6" /* Invalid byte */
+ "\xe1\xb9\x8b"; /* n with circumflex below */
+
+ SVN_ERR_ASSERT(svn_utf__is_normalized(nfc, pool));
+ SVN_ERR_ASSERT(!svn_utf__is_normalized(nfd, pool));
+ SVN_ERR_ASSERT(!svn_utf__is_normalized(mixup, pool));
+ SVN_ERR_ASSERT(!svn_utf__is_normalized(invalid, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_utf_conversions(apr_pool_t *pool)
+{
+ static const struct cvt_test_t
+ {
+ svn_boolean_t sixteenbit;
+ svn_boolean_t bigendian;
+ const char *source;
+ const char *result;
+ } tests[] = {
+
+#define UTF_32_LE FALSE, FALSE
+#define UTF_32_BE FALSE, TRUE
+#define UTF_16_LE TRUE, FALSE
+#define UTF_16_BE TRUE, TRUE
+
+ /* Normal character conversion */
+ { UTF_32_LE, "t\0\0\0" "e\0\0\0" "s\0\0\0" "t\0\0\0" "\0\0\0\0", "test" },
+ { UTF_32_BE, "\0\0\0t" "\0\0\0e" "\0\0\0s" "\0\0\0t" "\0\0\0\0", "test" },
+ { UTF_16_LE, "t\0" "e\0" "s\0" "t\0" "\0\0", "test" },
+ { UTF_16_BE, "\0t" "\0e" "\0s" "\0t" "\0\0", "test" },
+
+ /* Valid surrogate pairs */
+ { UTF_16_LE, "\x00\xD8" "\x00\xDC" "\0\0", "\xf0\x90\x80\x80" }, /* U+010000 */
+ { UTF_16_LE, "\x34\xD8" "\x1E\xDD" "\0\0", "\xf0\x9d\x84\x9e" }, /* U+01D11E */
+ { UTF_16_LE, "\xFF\xDB" "\xFD\xDF" "\0\0", "\xf4\x8f\xbf\xbd" }, /* U+10FFFD */
+
+ { UTF_16_BE, "\xD8\x00" "\xDC\x00" "\0\0", "\xf0\x90\x80\x80" }, /* U+010000 */
+ { UTF_16_BE, "\xD8\x34" "\xDD\x1E" "\0\0", "\xf0\x9d\x84\x9e" }, /* U+01D11E */
+ { UTF_16_BE, "\xDB\xFF" "\xDF\xFD" "\0\0", "\xf4\x8f\xbf\xbd" }, /* U+10FFFD */
+
+ /* Swapped, single and trailing surrogate pairs */
+ { UTF_16_LE, "*\0" "\x00\xDC" "\x00\xD8" "*\0\0\0", "*\xed\xb0\x80" "\xed\xa0\x80*" },
+ { UTF_16_LE, "*\0" "\x1E\xDD" "*\0\0\0", "*\xed\xb4\x9e*" },
+ { UTF_16_LE, "*\0" "\xFF\xDB" "*\0\0\0", "*\xed\xaf\xbf*" },
+ { UTF_16_LE, "\x1E\xDD" "\0\0", "\xed\xb4\x9e" },
+ { UTF_16_LE, "\xFF\xDB" "\0\0", "\xed\xaf\xbf" },
+
+ { UTF_16_BE, "\0*" "\xDC\x00" "\xD8\x00" "\0*\0\0", "*\xed\xb0\x80" "\xed\xa0\x80*" },
+ { UTF_16_BE, "\0*" "\xDD\x1E" "\0*\0\0", "*\xed\xb4\x9e*" },
+ { UTF_16_BE, "\0*" "\xDB\xFF" "\0*\0\0", "*\xed\xaf\xbf*" },
+ { UTF_16_BE, "\xDD\x1E" "\0\0", "\xed\xb4\x9e" },
+ { UTF_16_BE, "\xDB\xFF" "\0\0", "\xed\xaf\xbf" },
+
+#undef UTF_32_LE
+#undef UTF_32_BE
+#undef UTF_16_LE
+#undef UTF_16_BE
+
+ { 0 }
+ };
+
+ const struct cvt_test_t *tc;
+ const svn_string_t *result;
+ int i;
+
+ for (i = 1, tc = tests; tc->source; ++tc, ++i)
+ {
+ if (tc->sixteenbit)
+ SVN_ERR(svn_utf__utf16_to_utf8(&result, (const void*)tc->source,
+ SVN_UTF__UNKNOWN_LENGTH,
+ tc->bigendian, pool, pool));
+ else
+ SVN_ERR(svn_utf__utf32_to_utf8(&result, (const void*)tc->source,
+ SVN_UTF__UNKNOWN_LENGTH,
+ tc->bigendian, pool, pool));
+ SVN_ERR_ASSERT(0 == strcmp(result->data, tc->result));
+ }
+
+ /* Test counted strings with NUL characters */
+ SVN_ERR(svn_utf__utf16_to_utf8(
+ &result, (void*)("x\0" "\0\0" "y\0" "*\0"), 3,
+ FALSE, pool, pool));
+ SVN_ERR_ASSERT(0 == memcmp(result->data, "x\0y", 3));
+
+ SVN_ERR(svn_utf__utf32_to_utf8(
+ &result,
+ (void*)("\0\0\0x" "\0\0\0\0" "\0\0\0y" "\0\0\0*"), 3,
+ TRUE, pool, pool));
+ SVN_ERR_ASSERT(0 == memcmp(result->data, "x\0y", 3));
+
+ return SVN_NO_ERROR;
+}
+
+
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(utf_validate,
@@ -308,5 +839,17 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_utf_cstring_to_utf8_ex2"),
SVN_TEST_PASS2(test_utf_cstring_from_utf8_ex2,
"test svn_utf_cstring_from_utf8_ex2"),
+ SVN_TEST_PASS2(test_utf_collated_compare,
+ "test svn_utf__normcmp"),
+ SVN_TEST_PASS2(test_utf_pattern_match,
+ "test svn_utf__glob"),
+ SVN_TEST_PASS2(test_utf_fuzzy_escape,
+ "test svn_utf__fuzzy_escape"),
+ SVN_TEST_PASS2(test_utf_is_normalized,
+ "test svn_utf__is_normalized"),
+ SVN_TEST_PASS2(test_utf_conversions,
+ "test svn_utf__utf{16,32}_to_utf8"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN
diff --git a/subversion/tests/libsvn_subr/x509-test.c b/subversion/tests/libsvn_subr/x509-test.c
new file mode 100644
index 0000000..a3806b8
--- /dev/null
+++ b/subversion/tests/libsvn_subr/x509-test.c
@@ -0,0 +1,848 @@
+/*
+ * x509-test.c -- test the x509 parser 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 <string.h>
+#include "svn_x509.h"
+#include "svn_base64.h"
+#include "svn_time.h"
+#include "svn_pools.h"
+#include "svn_string.h"
+
+#include "../svn_test.h"
+
+struct x509_test {
+ const char *base64_cert; /* Base64 encoded DER X.509 cert */
+ const char *subject; /* Subject Distinguished Name */
+ const char *subject_oids; /* Space separated list of oids in Subject */
+ const char *issuer; /* Issuer Distinguished Name */
+ const char *issuer_oids; /* Space separated list of oids in Issuer */
+
+ /* These timesamps are in the format that svn_time_to_cstring() produces.
+ * This is not the same string as the parser returns since it returns
+ * the ressult of svn_time_to_human_cstring(), which is in the local
+ * timezone. So we can't store exactly what the parser will output. */
+ const char *valid_from;
+ const char *valid_to;
+ const char *hostnames;
+ const char *sha1_digest;
+};
+
+static struct x509_test cert_tests[] = {
+ /* contains extensions and uses a sha256 algorithm */
+ { "MIIEtzCCA5+gAwIBAgIQWGBOrapkezd+BWVsAtmtmTANBgkqhkiG9w0BAQsFADA8"
+ "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMVGhhd3RlLCBJbmMuMRYwFAYDVQQDEw1U"
+ "aGF3dGUgU1NMIENBMB4XDTE0MDQxMTAwMDAwMFoXDTE2MDQwNzIzNTk1OVowgYsx"
+ "CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxQLRm9yZXN0"
+ "IEhpbGwxIzAhBgNVBAoUGkFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRcwFQYD"
+ "VQQLFA5JbmZyYXN0cnVjdHVyZTEVMBMGA1UEAxQMKi5hcGFjaGUub3JnMIIBIjAN"
+ "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Tq4mH+stRoxe4xth8tUCgLt+P4L"
+ "D/JWZz4a2IecaaAk57vIlTxEyP16fUShUfxVJnD0KV11zv2qaEUXNaA6hKd4H/oB"
+ "u2OyGev+quRM+aFCjWqASkXt7fLGsIkHAwP3XwBVBpARbcXJeCjCBxqaYrQqS8LT"
+ "wfPUD9eYncGlQ+ixb3Bosy7TmkWKeLsRdS90cAO/rdgQ8OI7kLT/1tr5GpF9RmXo"
+ "RnVqMP+U0zGd/BNNSneg7emb7TxLzxeMKZ7QbF4MZi8RRN11spvx8/f92CiYrGGu"
+ "y67VdOGPaomYc+VZ2syLwduHGK40ADrEK3+MQpsRFB0dM08j9bhpr5A44wIDAQAB"
+ "o4IBYzCCAV8wFwYDVR0RBBAwDoIMKi5hcGFjaGUub3JnMAkGA1UdEwQCMAAwQgYD"
+ "VR0gBDswOTA3BgpghkgBhvhFAQc2MCkwJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3"
+ "LnRoYXd0ZS5jb20vY3BzLzAOBgNVHQ8BAf8EBAMCBaAwHwYDVR0jBBgwFoAUp6KD"
+ "uzRFQD381TBPErk+oQGf9tswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL3N2ci1v"
+ "di1jcmwudGhhd3RlLmNvbS9UaGF3dGVPVi5jcmwwHQYDVR0lBBYwFAYIKwYBBQUH"
+ "AwEGCCsGAQUFBwMCMGkGCCsGAQUFBwEBBF0wWzAiBggrBgEFBQcwAYYWaHR0cDov"
+ "L29jc3AudGhhd3RlLmNvbTA1BggrBgEFBQcwAoYpaHR0cDovL3N2ci1vdi1haWEu"
+ "dGhhd3RlLmNvbS9UaGF3dGVPVi5jZXIwDQYJKoZIhvcNAQELBQADggEBAF52BLvl"
+ "x5or9/aO7+cPhxuPxwiNRgbvHdCakD7n8vzjNyct9fKp6/XxB6GQiTZ0nZPJOyIu"
+ "Pi1QDLKOXvaPeLKDBilL/+mrn/ev3s/aRQSrUsieKDoQnqtmlxEHc/T3+Ni/RZob"
+ "PD4GzPuNKpK3BIc0fk/95T8R1DjBSQ5/clvkzOKtcl3VffAwnHiE9TZx9js7kZwO"
+ "b9nOKX8DFao3EpQcS7qn63Ibzbq5A6ry8ZNRQSIJK/xlCAWoyUd1uxnqGFnus8wb"
+ "9RVZJQe8YvyytBjgbE3QjnfPOxoEJA3twupnPmH+OCTM6V3TZqpRZj/sZ5rtIQ++"
+ "hI5FdJWUWVSgnSw=",
+ "C=US, ST=Maryland, L=Forest Hill, O=Apache Software Foundation, "
+ "OU=Infrastructure, CN=*.apache.org",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.11 2.5.4.3",
+ "C=US, O=Thawte, Inc., CN=Thawte SSL CA",
+ "2.5.4.6 2.5.4.10 2.5.4.3",
+ "2014-04-11T00:00:00.000000Z",
+ "2016-04-07T23:59:59.000000Z",
+ "*.apache.org",
+ "151d8ad1e1bac21466bc2836ba80b5fcf872f37c" },
+ /* the expiration is after 2049 so the expiration is in the
+ * generalized format, while the start date is still in the UTC
+ * format. Note this is actually a CA cert but that really doesn't
+ * matter here. */
+ { "MIIDtzCCAp+gAwIBAgIJAJKX85dqh3RvMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV"
+ "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX"
+ "aWRnaXRzIFB0eSBMdGQwIBcNMTQwNjI3MTczMTUxWhgPMjExNDA2MDMxNzMxNTFa"
+ "MEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJ"
+ "bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw"
+ "ggEKAoIBAQDaa4gwNBB6vgWrlOIEMdzvD06zmmiocEt6UnTHtmAcfrBuDnKrBwEh"
+ "f5JxneL16XIuKwK6n/4omBtem/PPjjpOLM9PMQuoO0cpQ0UGFnfpmko6PSQoqRHl"
+ "qTbDGv4usn7qdZV+FKz/B9CMonRSzWHMz5YPmqfob6BqaaJY/qJEzHJA24bm4jPH"
+ "IsaVCInEGpqAUpejwBzNujfbLibBNrVX7K846zk+tnsNR90kP5h3IRP3SdWVywKC"
+ "AMN2izzhmaDhuPzaTBobovr+ySJShmX6gdB5PpWkm6rcBl6RJ+tM0ZBSJjQvkYp4"
+ "seV+rcXFgpJP/aQL3vhDON32tjWh3A2JAgMBAAGjgacwgaQwHQYDVR0OBBYEFF+N"
+ "7TyDI8THpAbx1pfzFFtl5z4iMHUGA1UdIwRuMGyAFF+N7TyDI8THpAbx1pfzFFtl"
+ "5z4ioUmkRzBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8G"
+ "A1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkggkAkpfzl2qHdG8wDAYDVR0T"
+ "BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAo4t9fYe2I+XIQn8i/KI9UFEE9fue"
+ "w6rQMnf9yyd8nwL+IcV84hvyNrq0+7SptUBMq3rsEf5UIBIBI4Oa614mJ/Kt976O"
+ "S7Sa1IPH7j+zb/jqH/xGskEVi25dZz7psFCmi7Hm9dnVz9YKa2yLW6R2KZcTVxCx"
+ "SSdDRlD7SonsYeq2fGrAo7Y9xfZsiJ2ZbJ18kHs2coMWuhgSrN9jrML6mb5B+k22"
+ "/rgsCJgFsBDPBYR3ju0Ahqg7v6kwg9O2PJzyb4ljsw8oI0sCwHTZW5I5FMq2D9g6"
+ "hj80N2fhS9QWoLyeKoMTNB2Do6VaNrLrCJiscZWrsnM1f+XBqV8hMuHX8A==",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-06-27T17:31:51.000000Z",
+ "2114-06-03T17:31:51.000000Z",
+ NULL,
+ "db3a959e145acc2741f9eeecbeabce53cc5b7362" },
+ /* The subject (except for country code) is UTF-8 encoded.
+ * created with openssl using utf8-yes and string_mask=utf8only */
+ { "MIIDrTCCApWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET"
+ "MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+ "dHkgTHRkMB4XDTE0MDcwMjE4MzYxMFoXDTE1MDcwMjE4MzYxMFowcjELMAkGA1UE"
+ "BhMCR1IxFTATBgNVBAgMDM6Rz4TPhM65zrrOrjETMBEGA1UEBwwKzpHOuM6uzr3O"
+ "sTEdMBsGA1UECgwUz4DOsc+BzqzOtM61zrnOs868zrExGDAWBgNVBAMMD3d3dy5l"
+ "eGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVPuQPz"
+ "INjsiXl+GeiXMzXV1Bfm8vzbQnMLAFY/ZKKK4gpy58xcNrmur//Fd38naTM/DetO"
+ "PEoDa+vQ48CnUWCDT3CKUA3BnrjtR3/EITC7XRcfk5lyk0IZr9RZB1WedQxK1n5E"
+ "Ecz8EBrm9+1442Nmg/y1F8d/2F2CjKB+PgfOP1WWaIQcsjLsftXec+kGjc34kwbS"
+ "9D9H+bRrPVcOzBZOqC+K0K7MMOxKA5mMi4b/Nlep76gTaUyonclRIADanAyaK5WG"
+ "0IkEI/nxufaP3AcPksCbroWLTkPKIe97Yj6mnzNhK9TA9w5RgdBrjNyfrwUaYiYR"
+ "FxVJN0VrHWSsRnECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYd"
+ "T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFNOobRTPfoWP"
+ "EGgXVkHfwrqz7PVzMB8GA1UdIwQYMBaAFIV8JZkZ88X7MTQSsJ6/qF3KboHKMA0G"
+ "CSqGSIb3DQEBBQUAA4IBAQAam6vJUv6kcWWrEAfdnwwRmmJ4X1Jey3Sp48G35MOE"
+ "KkHtwqbtL+QU1VA2X98bEYobqZinM3e3zrlbpgbe1xoJ00MnT9CgQObXr+cum/Ql"
+ "PwWXB5fK3BrNwqRMRGc9w27FevyFeybdKhc47jEKMOANrB/aziNHaq9gBtU/HZdy"
+ "rm9TEaOHMy6vNrdpOZKpwXPxYqsQxMLpen9D64t/3P6hsV5FMQTaxSFhszidG44t"
+ "xaU4O0BOq4x//THCWguMxzO5RxW/V8wI/rkpvhAH1wljHTusnsAZea4PpstZ7+W7"
+ "43GME1DwjYdUK9HhqRNrDkiJLox4Tmegw9A7m4XLt4zu",
+ "C=GR, ST=\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae, "
+ "L=\xce\x91\xce\xb8\xce\xae\xce\xbd\xce\xb1, "
+ "O=\xcf\x80\xce\xb1\xcf\x81\xce\xac\xce\xb4\xce\xb5\xce\xb9\xce\xb3"
+ "\xce\xbc\xce\xb1, CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-07-02T18:36:10.000000Z",
+ "2015-07-02T18:36:10.000000Z",
+ "www.example.com",
+ "b3b9789d8a53868f418619565f6b56af0033bdd3" },
+ /* The issuer and subject (except for the country code) is
+ * UnversalString encoded. Created with a hacked version of openssl
+ * using utf8=yes and string_mask=MASK:256. In order for that to
+ * output UniversalString encoded data you need to change the
+ * DIRSTRING_TYPE in crypto/asn1/asn1.h to be defined as
+ * B_ASN1_DIRECTORYSTRING so that UnviersalString is available to be
+ * used in the DirectoryStrings. OpenSSL by default avoids
+ * this type (for the reasonable reason that it's wasteful and
+ * UTF-8 can encoded everything it can in the most efficient way).
+ * OU uses the mathematical monospace digits 0-9 to test characters
+ * outside of the range of the Basic Multilingual Plane */
+ { "MIIEnzCCA4egAwIBAgIBATANBgkqhkiG9w0BAQUFADCBqzELMAkGA1UEBhMCQVUx"
+ "MTAvBgNVBAgcKAAAAFMAAABvAAAAbQAAAGUAAAAtAAAAUwAAAHQAAABhAAAAdAAA"
+ "AGUxaTBnBgNVBAocYAAAAEkAAABuAAAAdAAAAGUAAAByAAAAbgAAAGUAAAB0AAAA"
+ "IAAAAFcAAABpAAAAZAAAAGcAAABpAAAAdAAAAHMAAAAgAAAAUAAAAHQAAAB5AAAA"
+ "IAAAAEwAAAB0AAAAZDAeFw0xNDA3MjIyMjM3MzBaFw0xNTA3MjIyMjM3MzBaMIH8"
+ "MQswCQYDVQQGEwJHUjEhMB8GA1UECBwYAAADkQAAA8QAAAPEAAADuQAAA7oAAAOu"
+ "MR0wGwYDVQQHHBQAAAORAAADuAAAA64AAAO9AAADsTExMC8GA1UEChwoAAADwAAA"
+ "A7EAAAPBAAADrAAAA7QAAAO1AAADuQAAA7MAAAO8AAADsTExMC8GA1UECxwoAAHX"
+ "9gAB1/cAAdf4AAHX+QAB1/oAAdf7AAHX/AAB1/0AAdf+AAHX/zFFMEMGA1UEAxw8"
+ "AAAAdwAAAHcAAAB3AAAALgAAAGUAAAB4AAAAYQAAAG0AAABwAAAAbAAAAGUAAAAu"
+ "AAAAYwAAAG8AAABtMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuYUb"
+ "aNt22rsR5Qc/2zsenSvrlbvv1CwwRPNxcWTKdLl4lJEUy5YCnQXIq3qTi+eAFetQ"
+ "MwUOZem6kgNdwmGvCz3lrLwOobd1D5mG9agzKLVUVj72csbNNFzHr8z/7oaHvYYs"
+ "eYxW3oRm6vDYtHw5spXrxTzRIAnG6foxXFYAtDDHQpdjsofxqXO67aUmmGvE5ffX"
+ "gD3dvTvjejzcjjVsLQP/HG4MQOqeIyvyyHg1E3dyOrG+3qR6RN1ZveROdvU38Udm"
+ "s0KSGVX2lDLsUTQSKg5L8CLWDHqgGQWjLZQRgRiKZId/f9ubaJdLN6KfAQ3UvYAP"
+ "bKL5/k2GpsPDE21X0QIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf"
+ "Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUccHhM6C7"
+ "nGMpclkG7YLIRuFueYQwHwYDVR0jBBgwFoAUz0X1b2Ok9MVVzxqxX6MgtTwSKmYw"
+ "DQYJKoZIhvcNAQEFBQADggEBAEpqEa08JkPG+XBlLemnoJsnoaRuQnLZvSCoAwIt"
+ "fugTE8686EigTZyYVFQ+GaI+EqVeiMjpAEhS3IMbhx5VIr61S3Nta2BG9OPjr4Xf"
+ "01oUeh4egL93CpIGNwu6M1SrQv2UVAKTwahxNmNuvx6Ojx5P2tne+KJtRUiwM3dE"
+ "of78/0NJD27OwjW0ruZAifF5CAR7mhy3NOMARpE2kqZk5695OF+QCahe00Y/9ulz"
+ "sCjgjpCUYv87OTbBGC5XGRd/ZopTRqtBVxpEHX/fux5/wqxBawrCuQsVw1Kfw0Ur"
+ "30aYWLsOsRwhiQkukjQfcMra1AHLujWaAHuLIDls1ozc8xo=",
+ "C=GR, ST=\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae, "
+ "L=\xce\x91\xce\xb8\xce\xae\xce\xbd\xce\xb1, "
+ "O=\xcf\x80\xce\xb1\xcf\x81\xce\xac\xce\xb4\xce\xb5\xce\xb9\xce\xb3"
+ "\xce\xbc\xce\xb1, "
+ "OU=\xf0\x9d\x9f\xb6\xf0\x9d\x9f\xb7\xf0\x9d\x9f\xb8\xf0\x9d\x9f\xb9"
+ "\xf0\x9d\x9f\xba\xf0\x9d\x9f\xbb\xf0\x9d\x9f\xbc\xf0\x9d\x9f\xbd"
+ "\xf0\x9d\x9f\xbe\xf0\x9d\x9f\xbf, "
+ "CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.11 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-07-22T22:37:30.000000Z",
+ "2015-07-22T22:37:30.000000Z",
+ "www.example.com",
+ "cfa15310189cf89f1dadc9c989db46f287fff7a7"
+ },
+ /* The issuer and subject (except for the country code) is BMPString
+ * encoded. Created with openssl using utf8-yes and string_mask=MASK:2048.
+ */
+ { "MIID3zCCAsegAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJBVTEd"
+ "MBsGA1UECB4UAFMAbwBtAGUALQBTAHQAYQB0AGUxOTA3BgNVBAoeMABJAG4AdABl"
+ "AHIAbgBlAHQAIABXAGkAZABnAGkAdABzACAAUAB0AHkAIABMAHQAZDAeFw0xNDA3"
+ "MjIyMzAyMDlaFw0xNTA3MjIyMzAyMDlaMIGBMQswCQYDVQQGEwJHUjEVMBMGA1UE"
+ "CB4MA5EDxAPEA7kDugOuMRMwEQYDVQQHHgoDkQO4A64DvQOxMR0wGwYDVQQKHhQD"
+ "wAOxA8EDrAO0A7UDuQOzA7wDsTEnMCUGA1UEAx4eAHcAdwB3AC4AZQB4AGEAbQBw"
+ "AGwAZQAuAGMAbwBtMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzof"
+ "mf9YANAl2I5AcUjfAAJhqc2BL6z6k0J9bWyDL7DZf6AJtD5stRjs8cgiSGfJt9Cg"
+ "YQ0Cvnwz9ztNVXLliMmiJ4V0HzG80GI6SBK0PoCVbddUV/PN7REgPNjTwMYlys5w"
+ "Yt/GR8OJJV+eb02rpAfVigDlh7CFjY/uKMs2ThPi+yQb2V6qxLk3ZKIHh5IbKQjt"
+ "zIX/W1t+hiBjojnuOmhAoEefZ583k7amR5GBZO4GS5Qfj+4kjL5xiwB3bjTC8pnV"
+ "Iv4+mN2F6xKW/9IOWZtdySDADaU2ioyuMDzzjp5N5Nt0ZGhrEG2cDC3CatZaV4U7"
+ "9yBbi6kzlo3fCbCOlQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf"
+ "Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNvwKR1v/"
+ "R0FQU1WnzqT3brNxaQQwHwYDVR0jBBgwFoAUSM/JbJVWuYFp+awSOEXZcKn1ddQw"
+ "DQYJKoZIhvcNAQEFBQADggEBABna/SiYMBJvbnI+lj7j8ddSFihaFheqtouxOB2d"
+ "tiVz5mcc5KsAFlkrxt7YcYB7SEc+K28nqGb3bfbZ18JayRBY3JS/h4WGu4eL5XkX"
+ "rceWUy60zF7DHs6p8E8HZVF1CdCC/LXr2BAdYTc/y1f37bLKVFF4mMJMP4b8/nSL"
+ "z8+oOO9CxaEjzRoCawf2+jaajXTSTDXBgIx1t6bJMAS6S6RKPaCketyAmpsOZVBS"
+ "VtBVfVIOB2zFqs6iqkXtdiOXWlZ0DBQRX0G1VD5G80RlZXs0yEfufCwLUl/TyOhM"
+ "WisUSEOzd4RlbsBj30JQkVG9+jXb2KChPkiMpg0tFi8HU3s=",
+ "C=GR, ST=\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae, "
+ "L=\xce\x91\xce\xb8\xce\xae\xce\xbd\xce\xb1, "
+ "O=\xcf\x80\xce\xb1\xcf\x81\xce\xac\xce\xb4\xce\xb5\xce\xb9\xce\xb3"
+ "\xce\xbc\xce\xb1, CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-07-22T23:02:09.000000Z",
+ "2015-07-22T23:02:09.000000Z",
+ "www.example.com",
+ "6e2cd969350979d3741b9abb66c71159a94ff971"
+ },
+ /* The issuer and subject (except for the country code) is T61String
+ * (aka TeletexString) encoded. Created with openssl using utf8=yes
+ * and string_mask=MASK:4. Note that the example chosen specifically
+ * includes the Norwegian OE (slashed O) to highlight that this is
+ * being treated as ISO-8859-1 despite what the X.509 says.
+ * See the following for the horrible details on
+ * this encoding: https://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
+ */
+ { "MIIDnTCCAoWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET"
+ "MBEGA1UECBQKU29tZS1TdGF0ZTEhMB8GA1UEChQYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+ "dHkgTHRkMB4XDTE0MDcyMjIzNDQxOFoXDTE1MDcyMjIzNDQxOFowYjELMAkGA1UE"
+ "BhMCTk8xGDAWBgNVBAgUD034cmUgb2cgUm9tc2RhbDEQMA4GA1UEBxQHxWxlc3Vu"
+ "ZDENMAsGA1UEChQEZPhtZTEYMBYGA1UEAxQPd3d3LmV4YW1wbGUuY29tMIIBIjAN"
+ "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz8uD5f2KRXvB//mKOpCXM3h/MOjK"
+ "xUgC4TIHi3BmnYR0IDElMPJrC263/eU0hKycyegyMjXkwIN5eEx4/Nl///RrzJBQ"
+ "+uXKfEJ4hTJ5x1uUYxhmtq4djZFxfjFH5yobT/LRDkEw9b/+NiRb30P+WrxhrAKW"
+ "7GRsE2pIdPdbM2IB5v/wORB4TK0kLYkmeEPWNJd63SmX4BEC6dRAaMxLIXKn75r5"
+ "GhMHKbUdt2Yy+5s0JlN9hMWqhnavCmGquzl7y/1E1OOUIm0jhL0sJn6wVTc+UO+Q"
+ "7u/w0xf38J8SU7lW6zbcQyYaSIQCMikgpprUSXdQZZUZGmHS7Gis39SiLwIDAQAB"
+ "o3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl"
+ "ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUQa2QLy+4QUH8hKNdR2LcvDKYImcwHwYD"
+ "VR0jBBgwFoAUpX6YP04yWqNiziUM7h0KgrRHMF4wDQYJKoZIhvcNAQEFBQADggEB"
+ "AElYUTQp5MOQk+ykIV0MHTw9OsEvLc1ZDmChls5WKYAu6KWgBbcjcTlkTpDlydrO"
+ "6JFxvCCg0K13dYOI3K/O9icGRauIrxrJOTtaIMryj7F51C52TOVPzkjL05eZTh+q"
+ "MmP3KI3uYSpXI6D6RI6hOKIRnFiUOQuXW3I8Z7s03KScBc9PSsVrMBLBz/Vpklaf"
+ "Tv/3jVBVIZwCW67SnFQ+vqEzaM4Ns2TBodlVqB1w0enPpow8bNnUwElLQJx3GXnl"
+ "z0JTpA6AwIRCF8n+VJgNN218fo2t2vvDDW/cZ+XMXzGNVhAqQ1F8B36esxy3P8+o"
+ "Bcwx241dxeGSYFHerqrTJIU=",
+ "C=NO, ST=M\xc3\xb8re og Romsdal, L=\xc3\x85lesund, O=d\xc3\xb8me, "
+ "CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-07-22T23:44:18.000000Z",
+ "2015-07-22T23:44:18.000000Z",
+ "www.example.com",
+ "787d1577ae77b79649d8f99cf4ed58a332dc48da"
+ },
+ /* Certificate with several Subject Alt Name dNSNames. Note that
+ * the CommonName is not duplicated in the Subject Alt Name to
+ * test that the Common Name is excluded when Subject Alt Name
+ * exists. */
+ { "MIIEMTCCAxmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJBVTET"
+ "MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+ "dHkgTHRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMB4XDTE0MDcyNTE3"
+ "NDEwNFoXDTE1MDcyNTE3NDEwNFowdDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh"
+ "c2hpbmd0b24xEzARBgNVBAcTCk5vcnRoIEJlbmQxITAfBgNVBAoTGEludGVybmV0"
+ "IFdpZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMIIBIjAN"
+ "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlryoK6hMhGI/UlHi7v1m+Z3tCvg"
+ "ZG1twDFNvBACpFVbJtC/v+fiy1eG7ooZ1PsdCINQ1iXLh1igevlw/4w6iTDpeSZg"
+ "OCPYqK6ejnS0bKtSB4TuP8yiQtqwaVz4yPP88lXuQJDRJzgaAR0VAhooLgEpl1z1"
+ "n9wQO15AW5swzpKcEOi4n6Zmf1t7oxOt9awAOhkL1FfFwkpbiK9yQv3TPVo+xzbx"
+ "BJxwx55RY8Dpiu0kuiTYWsd02pocb0uIqd7a5B4y05PhJseqwyX0Mw57HBBnbru1"
+ "lCetP4PkoM2gf7Uoj9e61nmM1mustKTIPvh7tZHWW3UW9JxAFG+6FkKDewIDAQAB"
+ "o4HeMIHbMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh"
+ "dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ4A9k8VwI0wv7u5rB4+1D9cuHiqTAf"
+ "BgNVHSMEGDAWgBS6O+MdRDDrD715AXdrnuNZ7wDSyjALBgNVHQ8EBAMCBeAwUwYD"
+ "VR0RBEwwSoINKi5leGFtcGxlLmNvbYIRKi5mb28uZXhhbXBsZS5jb22CESouYmFy"
+ "LmV4YW1wbGUuY29tghN6aWctemFnLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUA"
+ "A4IBAQAf4IrSOL741IUkyFQrDdof39Cp87VdNEo4Bl8fUSuCjqZONxJfiAFx7GcB"
+ "Cd7h7Toe6CYCeQLHSEXQ1S1eWYLIq0ZoP3Q/huJdoH7yskDyC5Faexph0obKM5hj"
+ "+EYGW2W/UYBzEZai+eePBovARDlupiMaTJGvtdU/AcgMhXCoGNK6egesXoiNgfFh"
+ "h+lXUNWUWm2gZlKwRJff8tkR7bIG7MGzyL6Rqav2/tQdbFVXN5AFPdYPFLf0Vo5m"
+ "eGYM87TILfSo7n7Kh0aZovwcuF/vPUWRJl3B1HaPt9k6DhcFyAji0SJyZWyM4v88"
+ "GSq5Dk8dnTdL2otToll+r4IqFLlp",
+ "C=US, ST=Washington, L=North Bend, O=Internet Widgits Pty Ltd, "
+ "CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+ "2.5.4.6 2.5.4.8 2.5.4.10 2.5.4.3",
+ "2014-07-25T17:41:04.000000Z",
+ "2015-07-25T17:41:04.000000Z",
+ "*.example.com, *.foo.example.com, *.bar.example.com, zig-zag.example.com",
+ "9c365d27b7b6cc438576a8e465685ea7a4f61129"
+ },
+ /* This is a CA cert that has a Common Name that doesn't look like
+ * a hostname. Make sure that the hostnames field remains blank for it. */
+ { "MIIEEjCCAvqgAwIBAgIJAKJarRWbvbCjMA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNV"
+ "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX"
+ "aWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMTE0ludGVybmV0IFdpZGdpdHMgQ0EwHhcN"
+ "MTQwNzI1MTc0MTAzWhcNMjQwNzIyMTc0MTAzWjBjMQswCQYDVQQGEwJBVTETMBEG"
+ "A1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg"
+ "THRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMIIBIjANBgkqhkiG9w0B"
+ "AQEFAAOCAQ8AMIIBCgKCAQEAv0f0TAiE13WHaFv8j6M9uuniO40+Aj8cuhZtJ1GC"
+ "GI/mW56wq2BJrP6N4+jyxYbZ/13S3ypPu+N087Nc/4xaPtUD/eKqMlU+o8gHM/Lf"
+ "BEs2dUuBsvkNM0KoC04NPNTOYDnfHOrzx8iHhqlDedwmP8FeQn3rNS8k4qDyJpG3"
+ "Ay8ICz5mB07Cy6NISohTxMtatfW5yKmhnhiS92X42QAEgI1pGB7jJl1g3u+KY1Bf"
+ "/10kcramYSYIM1uB7XHQjZI4bhEhQwuIWePMOSCOykdmbemM3ijF9f531Olq+0Nz"
+ "t7lA1b/aW4PGGJsZ6uIIjKMaX4npP+HHUaNGVssgTnTehQIDAQABo4HIMIHFMB0G"
+ "A1UdDgQWBBS6O+MdRDDrD715AXdrnuNZ7wDSyjCBlQYDVR0jBIGNMIGKgBS6O+Md"
+ "RDDrD715AXdrnuNZ7wDSyqFnpGUwYzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNv"
+ "bWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoG"
+ "A1UEAxMTSW50ZXJuZXQgV2lkZ2l0cyBDQYIJAKJarRWbvbCjMAwGA1UdEwQFMAMB"
+ "Af8wDQYJKoZIhvcNAQEFBQADggEBAI442H8CpePFvOtdvcosu2N8juJrzACuayDI"
+ "Ze32EtHFN611azduqkWBgMJ3Fv74o0A7u5Gl8A7RZnfBTMX7cvpfHvWefau0xqgm"
+ "Mn8CcTUGel0qudCCMe+kPppmkgNaZFvawSqcAA/u2yni2yx8BakYYDZzyfmEf9dm"
+ "hZi5SmxFFba5UhNKOye0GKctT13s/7EgfFNyVhZA7hWU26Xm88QnGnN/qxJdpq+e"
+ "+Glctn9tyke4b1VZ2Yr+R4OktrId44ZQcRD44+88v5ThP8DQsvkXcjREMFAIPkvG"
+ "CEDOIem4l9KFfnsHn8/4KvoBRkmCkGaSwOwUdUG+jIjBpY/82kM=",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+ "2.5.4.6 2.5.4.8 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+ "2.5.4.6 2.5.4.8 2.5.4.10 2.5.4.3",
+ "2014-07-25T17:41:03.000000Z",
+ "2024-07-22T17:41:03.000000Z",
+ NULL,
+ "b9decce236aa1da07b2bf088160bffe1469b9a4a"
+ },
+ /* Cert with a IP SAN entry. Make sure we properly skip them. */
+ { "MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJBVTET"
+ "MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+ "dHkgTHRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMB4XDTE0MDcyNTE4"
+ "NDMyOFoXDTE1MDcyNTE4NDMyOFowczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh"
+ "c2hpbmd0b24xEzARBgNVBAcTCk5vcnRoIEJlbmQxITAfBgNVBAoTGEludGVybmV0"
+ "IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOaXAuZXhhbXBsZS5jb20wggEiMA0G"
+ "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXKkSxg89tu5/n+lIC8ajj1T9vsO5B"
+ "nRH5Sne7UPc6pGMTNFi1MOVjdDWkmuCUzoI+HKLDc69/4V5RU12N1QNgsgcOzCSo"
+ "qgxa+dQk2s1shz1zhyaHkpdeMZU3/p9D4v+nRGAdYifwl/VOTwjWWucNzHDBwvb6"
+ "+Wm4pXE94Y5p8fY/lZi7VgtxdoPdSHGkIAps8psZGPjqKpLEjnLMp1n0v9cZhBF6"
+ "OoMUZpQuwcjT8vMQppgIWhZFLiH2jn7FTYWZyB0Dh9nMd097NQA87VtVfNc+g0oY"
+ "qLe3YldJgvVfyeSLhnyv68fBfGcTj310pNrGeE/m4tyxupiUT8BitfxPAgMBAAGj"
+ "geQwgeEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0"
+ "ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFI09JZlhKV44Z+I5d58V/ZDqQ7yZMB8G"
+ "A1UdIwQYMBaAFDjQVnIU9pQI1nM8jjmxYiicMTdGMAsGA1UdDwQEAwIF4DBZBgNV"
+ "HREEUjBQgg0qLmV4YW1wbGUuY29tghEqLmZvby5leGFtcGxlLmNvbYcEfwAAAYIR"
+ "Ki5iYXIuZXhhbXBsZS5jb22CE3ppZy16YWcuZXhhbXBsZS5jb20wDQYJKoZIhvcN"
+ "AQEFBQADggEBAEK+XIGwavf+5Ht44ifHrGog0CDr4ESg7wFjzk+BJwYDtIPp9b8A"
+ "EG8qbfmOS+2trG3zc74baf2rmrfn0YGZ/GV826NMTaf7YU1/tJQTo+RX9g3aHg6f"
+ "pUBfIyAV8ELq84sgwd1PIgleVgIiDrz+a0UZ05Z5S+GbR2pwNH6+fO0O5E9clt2a"
+ "Cute1UMBqAMGKiFaP8HD6SUFTdTKZNxHtQzYmmuvoC1nzVatMFdkTuQgSQ/uNlzg"
+ "+yUFoufMZhs3gPx9PfXGOQ7f3nKE+WCK4KNGv+OILYsk4zUjMznfAwBRs9PyITN2"
+ "BKe64WsF6ZxTq3zLVGy5I8LpbtlvSmAaBp4=",
+ "C=US, ST=Washington, L=North Bend, O=Internet Widgits Pty Ltd, "
+ "CN=ip.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+ "2.5.4.6 2.5.4.8 2.5.4.10 2.5.4.3",
+ "2014-07-25T18:43:28.000000Z",
+ "2015-07-25T18:43:28.000000Z",
+ "*.example.com, *.foo.example.com, *.bar.example.com, zig-zag.example.com",
+ "3525fb617c232fdc738d736c1cbd5d97b19b51e4"
+ },
+ /* Cert with the signature algorithm OID set to sha1WithRSA instead of
+ * sha1WithRSAEncryption. Both have the same meaning but the sha1WithRSA
+ * doesn't seem to be used anymore and is shorter */
+ { "MIIDgDCCAmygAwIBAgIBATAJBgUrDgMCHQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYD"
+ "VQQIFApTb21lLVN0YXRlMSEwHwYDVQQKFBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBM"
+ "dGQwHhcNMTQwODE4MDk1OTQ1WhcNMTUwODE4MDk1OTQ1WjBNMQswCQYDVQQGEwJV"
+ "SzEQMA4GA1UECBQHRW5nbGFuZDESMBAGA1UEBxQJU2hlZmZpZWxkMRgwFgYDVQQD"
+ "FA93d3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB"
+ "AQCkvtieKg33RSzhn5JMDPPRlDS8Q16CN96A4lLI9YrJCy33z46PrbR2mq2hOz5l"
+ "MdgbAaRF0MUGhcKv4msJ0bsWhkybaSBAVgnoC7ObQWPNF7ppMzUjeDAlUBXNfheR"
+ "ZcgcgGWqUkoB1uUMhvmVuPrzvxn+WCwyoP6zQCviYLsR8AygGQgdhV6c9wJ/x9HS"
+ "MRUvUOeo7SCmx9GK5Hc11QV2K3rwKXABeAxXNzbyQe7hFfQYCI2SB5s3bEnhIvg7"
+ "BG0BQmoprHjXWBftc0+msKQTFw7+jZ21NsfwGoPonuVsCOJjJ51jp2oKqk3b1GGc"
+ "DEmmMQ0JtqfHO5a7JACBaHbTAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4"
+ "QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSo"
+ "jICtcIgZL6OCCB5BJ5PGf1UIyTAfBgNVHSMEGDAWgBT5KQMLMylrXSQvhMtONHZc"
+ "22Jm9TAJBgUrDgMCHQUAA4IBAQCvCJ4i2kRzSRhnlDxd0UbQtytVIJFFJlfREPTM"
+ "j8+VqqtCVyPSX8T5NU+HCiEmhVrTlm/W0i8ygJXr8izyIMGRqbyhn2M9b8hAY6Jl"
+ "0edztu/FV/YHsJbPznWkXWpMMaXDEX4wI329f5odccIbB5VSaaoAdKZ6Ne4nf6oV"
+ "95KRFWkXoYjm24TnpALsNnK1Kjjed6h5ApB+IANOpXYFbGcsfbuKhWbFd2nd6t5U"
+ "NpUcv4H9Tgdl6KgrfsbQtAeouWCgoiNzrul8FOaQTdJLZfCsjuE+IkGpM+DX8PiF"
+ "5M41EqkSKia8sChFIln+lkRY41OWP9uQ1VXCfdRIzOnXWh9U",
+ "C=UK, ST=England, L=Sheffield, CN=www.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2014-08-18T09:59:45.000000Z",
+ "2015-08-18T09:59:45.000000Z",
+ "www.example.com",
+ "0e0869961d508b13bb22aa8da675b2e9951c0e70"
+ },
+ /* X.509 v1 certificate, we used to crash on these prior to r1619861. */
+ { "MIIDDTCCAfUCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV"
+ "BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0"
+ "ZDAeFw0xNTAxMTkyMjEyNDhaFw0xNjAxMTkyMjEyNDhaMFQxCzAJBgNVBAYTAlVT"
+ "MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRMwEQYDVQQHEwpOb3J0aCBCZW5kMRswGQYD"
+ "VQQDExJ4NTA5djEuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw"
+ "ggEKAoIBAQDniW3DmGGtA0MoYqE9H55/RmjtTJD2WVmM/STEsw+RW74UGsZ62qfi"
+ "ADedl4ukZYKlk3TwJrGEwDBKOMWHuzCYVxhclyHkHwX7QqamvZRgaOonEu82KHuE"
+ "dZo4FhOWDC9D0yS4RFbfqvSu/JG19FYsnRQn1RPFYji6jG9TRwavplVBiMhR68kc"
+ "8HTW1Wu7uJ5SV0UtTicFes8MGek3+zWceGt+Egwd2UlIYXwTPzB5m7UPuufEdvFL"
+ "ED3pusVatohFzjCbYsuJIR5ppYd49uTxPWGvRidJ2C8GbDf9PCgDduS0Gz91Txnw"
+ "h+WiVYCQ6SxAJWp/xeZWE71k88N0vJEzAgMBAAEwDQYJKoZIhvcNAQEFBQADggEB"
+ "ABoBaObsHnIrkd3RvvGb5q7fnEfiT1DXsufS3ypf4Z8IST/z+NeaUaiRN1oLcvDz"
+ "qC7ygTYZ2BZoEw3ReCGqQWT4iYET+lH8DM+U5val3gVlSWqx1jj/wiV1OAxQsakM"
+ "BnmNs/MDshiv54irvSlqnxEp2o/BU/vMrN656C5DJkZpYoMpIWxdFnd+bzNzuN1k"
+ "pJfTjzWlGckKfdblNPOfdtccTqtQ5d4mWtYNJ8DfL5rRRwCuzXvZtbVHKxqkXaXr"
+ "CYUfFUobapgPfvvMc1QcDY+2nvhC2ij+HAPIHgZPuzJsjZRC1zwg074cfgjZbgbm"
+ "R0HVF486p3vS8HFv4lndRZA=",
+ "C=US, ST=Washington, L=North Bend, CN=x509v1.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2015-01-19T22:12:48.000000Z",
+ "2016-01-19T22:12:48.000000Z",
+ "x509v1.example.com",
+ "5730dd65a7f77fdf0dfd90e5a53119f38854af29"
+ },
+ /* X.509 v1 certificate with an X.509 v3 Subject Alternative Name
+ * extension. Although these are ill-formed per RFC 5280 s. 4.1, we
+ * suspect that they could exist in the real world. Make sure we do
+ * not error out, and that we pick up SAN (b.example.com) from the
+ * extension. */
+ { "MIIDLzCCAhcCAQ8wDQYJKoZIhvcNAQEFBQAwKzEpMCcGA1UEAwwgSW50ZXJuZXQg"
+ "V2lkZ2l0cyBJbnRlcm1lZGlhdGUgQ0EwHhcNMTUwMTI5MDAzMzU1WhcNMTYwMTI5"
+ "MDAzMzU1WjByMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjETMBEG"
+ "A1UEBwwKTm9ydGggQmVuZDEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg"
+ "THRkMRYwFAYDVQQDDA1hLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC"
+ "AQ8AMIIBCgKCAQEAs0hj2xPRQZpecqk0Ih1l4juAuQZeSgv3yD/VtSq/9sTBH6iA"
+ "4XjJQcHROYxYaK0QS/qlCjpl+Q3mOaVIu+59TLy3T2YVgqMYmgB453ntuJPkdF1C"
+ "fJ2j19YAQZHHdOFaP1G+auBwjmHns3+MkG4s7EPuJP7TBCcSFlOmz5D4GUui3NVG"
+ "LBYUog1ZhF4oe/7d4jc2Cn8uypNT/Hc1ViIlCT4rFoAirv9Uob+4zjQ3Z18I1Ql1"
+ "t8oszVCj3kKDboEty2RduwPLx/2ztWYBCvFhd49JGdi/nzMi+j2d5HCI3V8W06pN"
+ "mvrVU4G0ImVRa8wpmQCSm2Tp0s42FAVHWw8yMwIDAQABoxwwGjAYBgNVHREEETAP"
+ "gg1iLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQDI/n0NYakuRP/485/A"
+ "dan71qBy3sljjOreq71IfBdtq+GEjCL1B0TD0V338LXki9NicCLeD/MWfceDjV0u"
+ "AjPTxaZEn/NWqXo0mpNC535Y6G46mIHYDGC8JyvCJjaXF+GVstNt6lXzZp2Yn3Si"
+ "K57uVb+zz5zAGSO982I2HACZPnF/oAtp7bwxzwvBsLqSLw3hh0ATVPp6ktE+WMoI"
+ "X75CVcDmU0zjXqzKiFPKeTVjQG6YxgvplMaag/iNngkgEhX4PIrxdIEsHf8l9ogC"
+ "dz51MFxetsC4D2KRq8IblF9i+9r3hlv+Dbf9ovYe9Hu0usloSinImoWOw42iWWmP"
+ "vT4l",
+ "C=US, ST=Washington, L=North Bend, O=Internet Widgits Pty Ltd, "
+ "CN=a.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.10 2.5.4.3",
+ "CN=Internet Widgits Intermediate CA",
+ "2.5.4.3",
+ "2015-01-29T00:33:55.000000Z",
+ "2016-01-29T00:33:55.000000Z",
+ "b.example.com",
+ "47fa5c76fee6e21e37def6da3746bba84a5a09bf"
+ },
+ /* X.509 certificate with multiple Relative Distinguished Names
+ * Borrowed form the Chromium test suite see thier bug here
+ * https://code.google.com/p/chromium/issues/detail?id=101009
+ */
+ { "MIICsDCCAhmgAwIBAgIJAO9sL1fZ/VoPMA0GCSqGSIb3DQEBBQUAMHExbzAJBgNV"
+ "BAYTAlVTMA8GA1UECgwIQ2hyb21pdW0wFgYKCZImiZPyLGQBGRYIQ2hyb21pdW0w"
+ "GgYDVQQDDBNNdWx0aXZhbHVlIFJETiBUZXN0MB0GA1UECwwWQ2hyb21pdW0gbmV0"
+ "X3VuaXR0ZXN0czAeFw0xMTEyMDIwMzQ3MzlaFw0xMjAxMDEwMzQ3MzlaMHExbzAJ"
+ "BgNVBAYTAlVTMA8GA1UECgwIQ2hyb21pdW0wFgYKCZImiZPyLGQBGRYIQ2hyb21p"
+ "dW0wGgYDVQQDDBNNdWx0aXZhbHVlIFJETiBUZXN0MB0GA1UECwwWQ2hyb21pdW0g"
+ "bmV0X3VuaXR0ZXN0czCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnSMQ7YeC"
+ "sOuk+0n128F7TfDtG/X48sG10oTe65SC8N6LBLfo7YYiQZlWVHEzjsFpaiv0dx4k"
+ "cIFbVghXAky/r5qgM1XiAGuzzFw7R27cBTC9DPlRwHArP3CiEKO3iz8i+qu9x0il"
+ "/9N70LcSSAu/kGLxikDbHRoM9d2SKhy2LGsCAwEAAaNQME4wHQYDVR0OBBYEFI1e"
+ "cfoqc7qfjmMyHF2rh9CrR6u3MB8GA1UdIwQYMBaAFI1ecfoqc7qfjmMyHF2rh9Cr"
+ "R6u3MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGKwN01A47nxVHOkw"
+ "wFdbT8t9FFkY3pIg5meoqO3aATNaSEzkZoUljWtWgWfzr+n4ElwZBxeYv9cPurVk"
+ "a+wXygzWzsOzCUMKBI/aS8ijRervyvh6LpGojPGn1HttnXNLmhy+BLECs7cq6f0Z"
+ "hvImrEWhD5uZGlOxaZk+bFEjQHA=",
+ "C=US, O=Chromium, 0.9.2342.19200300.100.1.25=Chromium, "
+ "CN=Multivalue RDN Test, OU=Chromium net_unittests",
+ "2.5.4.6 2.5.4.10 0.9.2342.19200300.100.1.25 2.5.4.3 2.5.4.11",
+ "C=US, O=Chromium, 0.9.2342.19200300.100.1.25=Chromium, "
+ "CN=Multivalue RDN Test, OU=Chromium net_unittests",
+ "2.5.4.6 2.5.4.10 0.9.2342.19200300.100.1.25 2.5.4.3 2.5.4.11",
+ "2011-12-02T03:47:39.000000Z",
+ "2012-01-01T03:47:39.000000Z",
+ NULL,
+ "99302ca2824f585a117bb41302a388daa0519765"
+ },
+ /* certificate with subject that includes an attribute that has an
+ * object id that has leading zeros. This isn't technically legal
+ * but a simplistic parser might parser it the same as an object
+ * id that doesn't have a leading zero. In this case the object id
+ * with a leading zero could parse to the same object id as the
+ * Common Name. Make sure we don't treat it as such. */
+ { "MIIDDjCCAfYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV"
+ "BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0"
+ "ZDAeFw0xNTAxMjcwNzQ5MDhaFw0xNjAxMjcwNzQ5MDhaMFUxCzAJBgNVBAYTAlVT"
+ "MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRMwEQYDVQQHEwpOb3J0aCBCZW5kMRwwGgYE"
+ "VQSAAxMSbm90YWNuLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A"
+ "MIIBCgKCAQEAvXCJv0gr9d3GNYiukPrbse0FdXmuBx2mPf665WyZVHk9JiPnDcb2"
+ "ng8gHLgJe8izou6I0vN2iJgy91rUPvX9zA3qVhml+cboVY2jHCPWo/v5PQsXAgLV"
+ "5gVjp2POn3N0O1xcS1yNe249LkP0Di3kAMp5gkzdprm3fD3JDW1Q+ocQylnbjzG0"
+ "FtNQSUJLITvPXjR7ny46Fci2mv8scHOvlEXTK5/2RoBaoK2jWQimqGfFj1sr1vqZ"
+ "Wcb6NAdZso64Xg1V6CWX8zymlA7gAhTQWveq+ovUWcXpmR8aj9pYNuy0aZW3BANz"
+ "N6L0G7OZiVUvvzpfnn0V3Z/sR/iQs7q3nQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB"
+ "AQACZwruCiesCRkT08AtHl0WQnQui58e9/7En+iqxNQO6+fx84SfWGcUFYZtvzdO"
+ "KkHNTs06km+471OjLSDcotRkdqO1JxQCkNxbrPat7T6FrO9n2JFivx6eijRqK/jB"
+ "cBYW92dK4BfXU4+FyeB2OIpyPjuqLU2j7S5p7qNU50i/1J7Qt669nXeaPINIfZdW"
+ "sDjjWkFR1VOgXS/zeu/GOxlQFmmcde+X/qkFI+L352VX7Ktf95j4ms4vG2yZgNfe"
+ "jbNb9a7LMcqlop/PlX5WBGv8GGKUNZO0LvukFYOULf1oL8VQsN0x/gRHGC7m9kVM"
+ "3hojWZDXAY4mYqdBCRX7/gkt",
+ "C=US, ST=Washington, L=North Bend, 2.5.4.03=notacn.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.03",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2015-01-27T07:49:08.000000Z",
+ "2016-01-27T07:49:08.000000Z",
+ NULL,
+ "6f24b834ba00fb4ef863df63b8fbeddab25e4838"
+ },
+ /* certificate with subject that includes an attribute that has an
+ * object id that has an overflow such that it calculates to
+ * the same object id as the Common Name (2.5.4.3). OpenSSL
+ * with its bignum support shows this as 2.5.4.2361183241434822606851.
+ * It would be wrong to display this as a Common Name to the user. */
+ { "MIIDGTCCAgECAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV"
+ "BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0"
+ "ZDAeFw0xNTAxMjcwODMxNDNaFw0xNjAxMjcwODMxNDNaMGAxCzAJBgNVBAYTAlVT"
+ "MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRMwEQYDVQQHEwpOb3J0aCBCZW5kMScwJQYN"
+ "VQSCgICAgICAgICAAxMUb3ZlcmZsb3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3"
+ "DQEBAQUAA4IBDwAwggEKAoIBAQDHL1e8zSPyRND3tI42Vqca2FoCiWn881Czv2ct"
+ "tGFwyjUM8R1yHXEP+doS9KN9L29xRWZRxyCQ18S+QbjNQCh6Ay22qnkBu0uPdVB6"
+ "iIVKiW9RzU8dZSFMnveUZYLloG12kK++ooJGIstTJwkI8Naw1X1D29gZaY9oSKAc"
+ "Gs5c92po61RoetB744dUfUbAXi8eEd4ShdsdnCoswpEI4WTLdYLZ/cH/sU1a5Djm"
+ "cAfEBzZSOseEQSG7Fa/HvHyW+jDNnKG2r73M45TDcXAunSFcAYl1ioBaRwwdcTbK"
+ "SMGORThIX5UwpJDZI5sTVmTTRuCjbMxXXki/g9fTYD6mlaavAgMBAAEwDQYJKoZI"
+ "hvcNAQEFBQADggEBABvZSzFniMK4lqJcubzzk410NqZQEDBxdNZTNGrQYIDV8fDU"
+ "LLoQ2/2Y6kOQbx8r3RNcaJ6JtJeVqAq05It9oR5lMJFA2r0YMl4eB2V6o35+eaKY"
+ "FXrJzwx0rki2mX+iKsgRbJTv6mFb4I7vny404WKHNgYIfB8Z5jgbwWgrXH9M6BMb"
+ "FL9gZHMmU+6uqvCPYeIIZaAjT4J4E9322gpcumI9KGVApmbQhi5lC1hBh+eUprG7"
+ "4Brl9GeCLSTnTTf4GHIpqaUsKMtJ1sN/KJGwEB7Z4aszr80P5/sjHXOyqJ78tx46"
+ "pwH7/Fx0pM7nZjJVGvcxGBBOMeKy/o2QUVvEYPU=",
+ "C=US, ST=Washington, L=North Bend, \?\?=overflow.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 \?\?",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2015-01-27T08:31:43.000000Z",
+ "2016-01-27T08:31:43.000000Z",
+ NULL,
+ "c1f063daf23e402fe58bab1a3fa2ba05c1106158"
+ },
+ /* certificate with multiple common names, make sure this behaves
+ * the same way as serf. */
+ { "MIIDJjCCAg4CAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV"
+ "BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0"
+ "ZDAeFw0xNTAxMjExNzUwMDZaFw0xNjAxMjExNzUwMDZaMG0xCzAJBgNVBAYTAlVT"
+ "MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRMwEQYDVQQHEwpOb3J0aCBCZW5kMRkwFwYD"
+ "VQQDExBnb29kLmV4YW1wbGUuY29tMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29t"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5pfrXkiiDGCWSYhMQNHJ"
+ "gNBLEBNcFzsGpW8i6rMKVephwG7p4VqIvc0pSsmpD9IYuIxxq/2E2cziaTWyqCBp"
+ "hKKipqt8eMcu6u45LduHGiCcnN7rHORbQZTdvwzTmiVN1eI1oCVejB4zgHNkHUko"
+ "DyaALCHGRz8l7Qq6hSbiOnhH1qlscIIEsgQEyDlMZpbsWVTQKPxluhtgqVEn7wPN"
+ "qScrf2evq050NuNYYFzCmuqOGKq2gKbD/BlUqCNmEM2JPg/bdcAQxFCf0HcvDiS9"
+ "e29suMKWZAzJkbzrWhlDMG1Xt5c7dd82PcGwnL//Q7muE57luCw38Gp2vQQ3/Uki"
+ "vQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBry9wfxYia/dCSKvDXOBKUgWFQtI8j"
+ "7vYHuouTvIb5m6b62kiUdtuaVKi3jnUbHUFohOi/6o+HIwbXSgz5CbiLjgUvONBU"
+ "BLekaguIYX9tTmg+vhWchcmVMHufj6HdQkzWtyojSQD9GjHGInNDG102KlN1cdL8"
+ "jGTrru4vnef+xA24EvYPdcS2+H2yYH0THL3JPKo1GtO4NCEGWQbS6Ygwcy+BQpbU"
+ "TBIWhlbleuCalB8qhWyijcHeszT7mFR0CarEaSLeZj6FaQpZB636iHuELmxcgiFw"
+ "j3r3QZyAMEGvPPBPKYSTgmol31pX9LYvuFGA9ADQ2in/n9WdMfYzFzOn",
+ "C=US, ST=Washington, L=North Bend, "
+ "CN=good.example.com, CN=evil.example.com",
+ "2.5.4.6 2.5.4.8 2.5.4.7 2.5.4.3 2.5.4.3",
+ "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
+ "2.5.4.6 2.5.4.8 2.5.4.10",
+ "2015-01-21T17:50:06.000000Z",
+ "2016-01-21T17:50:06.000000Z",
+ "good.example.com",
+ "9693f17e59205f41ca2e14450d151b945651b2d7"
+ },
+ { NULL }
+};
+
+static svn_error_t *
+compare_dates(const char *expected,
+ apr_time_t actual,
+ const char *type,
+ const char *subject,
+ apr_pool_t *pool)
+{
+ apr_time_t expected_tm;
+
+ if (!actual)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "No %s for cert '%s'", type, subject);
+
+ SVN_ERR(svn_time_from_cstring(&expected_tm, expected, pool));
+ if (!expected_tm)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Problem converting expected %s '%s' to text "
+ "output for cert '%s'", type, expected,
+ subject);
+
+ if (expected_tm != actual)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "The %s didn't match expected '%s',"
+ " got '%s' for cert '%s'",
+ type, expected,
+ svn_time_to_cstring(actual, pool),
+ subject);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+compare_hostnames(const char *expected,
+ const apr_array_header_t *actual,
+ const char *subject,
+ apr_pool_t *pool)
+{
+
+ int i;
+ svn_stringbuf_t *buf;
+
+ if (!actual)
+ {
+ if (expected)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "The hostnames didn't match expected '%s',"
+ " got NULL for cert '%s'",
+ expected, subject);
+ return SVN_NO_ERROR;
+ }
+
+ buf = svn_stringbuf_create_empty(pool);
+ for (i = 0; i < actual->nelts; ++i)
+ {
+ const char *hostname = APR_ARRAY_IDX(actual, i, const char*);
+ if (i > 0)
+ svn_stringbuf_appendbytes(buf, ", ", 2);
+ svn_stringbuf_appendbytes(buf, hostname, strlen(hostname));
+ }
+
+ if (strcmp(expected, buf->data))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "The hostnames didn't match expected '%s',"
+ " got '%s' for cert '%s'",
+ expected, buf->data, subject);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+compare_oids(const char *expected,
+ const apr_array_header_t *actual,
+ const char *subject,
+ apr_pool_t *pool)
+{
+ int i;
+ svn_stringbuf_t *buf;
+
+ if (!actual)
+ {
+ if (expected)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "The oids didn't match expected '%s',"
+ " got NULL for cert '%s'",
+ expected, subject);
+ return SVN_NO_ERROR;
+ }
+
+ buf = svn_stringbuf_create_empty(pool);
+ for (i = 0; i < actual->nelts; ++i)
+ {
+ apr_size_t len;
+ const svn_x509_name_attr_t *attr = APR_ARRAY_IDX(actual, i, const svn_x509_name_attr_t *);
+ const void *oid = svn_x509_name_attr_get_oid(attr, &len);
+ const char *oid_string = svn_x509_oid_to_string(oid, len, pool, pool);
+ if (i > 0)
+ svn_stringbuf_appendbyte(buf, ' ');
+ if (oid_string)
+ svn_stringbuf_appendcstr(buf, oid_string);
+ else
+ svn_stringbuf_appendcstr(buf, "??");
+ }
+
+ if (strcmp(expected, buf->data))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "The oids didn't match expected '%s',"
+ " got '%s' for cert '%s'",
+ expected, buf->data, subject);
+ return SVN_NO_ERROR;
+
+}
+
+
+static svn_error_t *
+compare_results(struct x509_test *xt,
+ svn_x509_certinfo_t *certinfo,
+ apr_pool_t *pool)
+{
+ const char *v;
+
+ v = svn_x509_certinfo_get_subject(certinfo, pool);
+ if (!v)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "No subject for cert '%s'", xt->subject);
+ if (strcmp(v, xt->subject))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Subject didn't match for cert '%s', "
+ "expected '%s', got '%s'", xt->subject,
+ xt->subject, v);
+
+ SVN_ERR(compare_oids(xt->subject_oids, svn_x509_certinfo_get_subject_attrs(certinfo),
+ xt->subject, pool));
+
+ v = svn_x509_certinfo_get_issuer(certinfo, pool);
+ if (!v)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "No issuer for cert '%s'", xt->subject);
+ if (strcmp(v, xt->issuer))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Issuer didn't match for cert '%s', "
+ "expected '%s', got '%s'", xt->subject,
+ xt->issuer, v);
+
+ SVN_ERR(compare_oids(xt->issuer_oids, svn_x509_certinfo_get_issuer_attrs(certinfo),
+ xt->subject, pool));
+
+ SVN_ERR(compare_dates(xt->valid_from,
+ svn_x509_certinfo_get_valid_from(certinfo),
+ "valid-from",
+ xt->subject,
+ pool));
+
+ SVN_ERR(compare_dates(xt->valid_to,
+ svn_x509_certinfo_get_valid_to(certinfo),
+ "valid-to",
+ xt->subject,
+ pool));
+
+ SVN_ERR(compare_hostnames(xt->hostnames,
+ svn_x509_certinfo_get_hostnames(certinfo),
+ xt->subject,
+ pool));
+
+ v = svn_checksum_to_cstring_display(
+ svn_x509_certinfo_get_digest(certinfo), pool);
+ if (!v)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "No SHA1 digest for cert '%s'", xt->subject);
+ if (strcmp(v, xt->sha1_digest))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "SHA1 digest didn't match for cert '%s', "
+ "expected '%s', got '%s'", xt->subject,
+ xt->sha1_digest, v);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_x509_parse_cert(apr_pool_t *pool)
+{
+ struct x509_test *xt;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ for (xt = cert_tests; xt->base64_cert; xt++)
+ {
+ const svn_string_t *der_cert;
+ svn_x509_certinfo_t *certinfo;
+
+ svn_pool_clear(iterpool);
+
+ /* Convert header-less PEM to DER by undoing base64 encoding. */
+ der_cert = svn_base64_decode_string(svn_string_create(xt->base64_cert,
+ pool),
+ iterpool);
+
+ SVN_ERR(svn_x509_parse_cert(&certinfo, der_cert->data, der_cert->len,
+ iterpool, iterpool));
+
+ SVN_ERR(compare_results(xt, certinfo, iterpool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+#if 0
+static struct x509_test broken_cert_tests[] = {
+ { NULL }
+};
+
+static svn_error_t *
+test_x509_parse_cert_broken(apr_pool_t *pool)
+{
+ struct x509_test *xt;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ for (xt = broken_cert_tests; xt->base64_cert; xt++)
+ {
+ const svn_string_t *der_cert;
+ svn_x509_certinfo_t *certinfo;
+
+ svn_pool_clear(iterpool);
+
+ /* Convert header-less PEM to DER by undoing base64 encoding. */
+ der_cert = svn_base64_decode_string(svn_string_create(xt->base64_cert,
+ pool),
+ iterpool);
+
+ SVN_ERR(svn_x509_parse_cert(&certinfo, der_cert->data, der_cert->len,
+ iterpool, iterpool));
+
+ SVN_ERR(compare_results(xt, certinfo, iterpool));
+ }
+
+ return SVN_NO_ERROR;
+}
+#endif
+
+/* The test table. */
+
+static int max_threads = 1;
+
+static struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_PASS2(test_x509_parse_cert,
+ "test svn_x509_parse_cert"),
+/* SVN_TEST_XFAIL2(test_x509_parse_cert_broken,
+ "test broken certs"), */
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN