| /* ==================================================================== |
| * 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_version.h> |
| #include <apr_strings.h> |
| #include <openssl/ssl.h> |
| #include <openssl/opensslv.h> |
| |
| #if APR_VERSION_MAJOR < 2 |
| #include <apu_version.h> |
| #endif |
| |
| |
| #include "serf.h" |
| #include "test_serf.h" |
| |
| /* These test cases have access to internal functions. */ |
| #define SERF__TEST_INTERNAL /* Disable SERF__CONV_assert() */ |
| #include "serf_private.h" |
| #include "serf_bucket_util.h" |
| |
| #define PER_CONN_UNKNOWN_KEY SERF_CONFIG_PER_CONNECTION | 0xFF0001 |
| /* #define PER_HOST_UNKNOWN_KEY SERF_CONFIG_PER_HOST | 0xFF0002 */ |
| #define PER_CONTEXT_UNKNOWN_KEY SERF_CONFIG_PER_CONTEXT | 0xFF0003 |
| #define PER_CONN_TEST_KEY SERF_CONFIG_PER_CONNECTION | 0xFFFFFF |
| #define PER_HOST_TEST_KEY SERF_CONFIG_PER_HOST | 0xFFFFFF |
| #define PER_CONTEXT_TEST_KEY SERF_CONFIG_PER_CONTEXT | 0xFFFFFF |
| |
| static void test_config_store_per_context(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_config_t *cfg; |
| |
| serf_context_t *ctx = serf_context_create(tb->pool); |
| |
| /* The config store is empty initially, so we can play all we want */ |
| |
| /* We don't have a serf connection yet, so only the per context config |
| should be available to read and write */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_ctx_config(ctx, &cfg)); |
| CuAssertPtrEquals(tc, NULL, cfg->per_conn); |
| CuAssertPtrEquals(tc, NULL, cfg->per_host); |
| CuAssertPtrNotNull(tc, cfg->per_context); |
| |
| /* Get a non-existing key, value should be NULL */ |
| { |
| const char *actual; |
| |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg, PER_CONTEXT_UNKNOWN_KEY, |
| &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| } |
| |
| /* Store and retrieve a string value for a per-context key */ |
| { |
| const char *actual; |
| |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg, PER_CONTEXT_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg, PER_CONTEXT_TEST_KEY, |
| &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| } |
| } |
| |
| /* Empty implementations, they won't be called. */ |
| static void conn_closed(serf_connection_t *conn, void *closed_baton, |
| apr_status_t why, apr_pool_t *pool) |
| { |
| } |
| |
| static apr_status_t conn_setup(apr_socket_t *skt, |
| serf_bucket_t **input_bkt, |
| serf_bucket_t **output_bkt, |
| void *setup_baton, |
| apr_pool_t *pool) |
| { |
| return APR_SUCCESS; |
| } |
| |
| static void test_config_store_per_connection_different_host(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_config_t *cfg1, *cfg2; |
| apr_uri_t url; |
| const char *actual; |
| |
| serf_context_t *ctx = serf_context_create(tb->pool); |
| serf_connection_t *conn1, *conn2; |
| |
| /* Create two connections conn1 and conn2 to a different host */ |
| apr_uri_parse(tb->pool, "http://localhost:12345", &url); |
| serf_connection_create2(&conn1, ctx, url, conn_setup, NULL, |
| conn_closed, NULL, tb->pool); |
| apr_uri_parse(tb->pool, "http://localhost:54321", &url); |
| serf_connection_create2(&conn2, ctx, url, conn_setup, NULL, |
| conn_closed, NULL, tb->pool); |
| |
| /* Test 1: This should return a config object with per_context, per_host and |
| per_connection hash_table's initialized. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_conn_config(conn1, &cfg1)); |
| CuAssertPtrNotNull(tc, cfg1->per_context); |
| CuAssertPtrNotNull(tc, cfg1->per_host); |
| CuAssertPtrNotNull(tc, cfg1->per_conn); |
| /* Get a config object for the other connection also. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_conn_config(conn2, &cfg2)); |
| |
| /* Test 2: Get a non-existing per connection key, value should be NULL */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_CONN_UNKNOWN_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| /* Test 3: Store and retrieve a string value for a per-connection key */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg1, PER_CONN_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_CONN_TEST_KEY, &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| |
| /* Test that the key was set in the config for the first connection only. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg2, PER_CONN_TEST_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| /* Test 4: Store and retrieve a string value for a per-host key */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg1, PER_HOST_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_HOST_TEST_KEY, &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| |
| /* Test that the key was NOT set in the config for the second connection, |
| since they are to a different host. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg2, PER_HOST_TEST_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| } |
| |
| static void test_config_store_per_connection_same_host(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_config_t *cfg1, *cfg2; |
| apr_uri_t url; |
| const char *actual; |
| |
| serf_context_t *ctx = serf_context_create(tb->pool); |
| serf_connection_t *conn1, *conn2; |
| |
| /* Create two connections conn1 and conn2 to the same host */ |
| apr_uri_parse(tb->pool, "http://localhost:12345", &url); |
| serf_connection_create2(&conn1, ctx, url, conn_setup, NULL, |
| conn_closed, NULL, tb->pool); |
| serf_connection_create2(&conn2, ctx, url, conn_setup, NULL, |
| conn_closed, NULL, tb->pool); |
| |
| /* Test 1: This should return a config object with per_context, per_host and |
| per_connection hash_table's initialized. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_conn_config(conn1, &cfg1)); |
| CuAssertPtrNotNull(tc, cfg1->per_context); |
| CuAssertPtrNotNull(tc, cfg1->per_host); |
| CuAssertPtrNotNull(tc, cfg1->per_conn); |
| /* Get a config object for the other connection also. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_conn_config(conn2, &cfg2)); |
| |
| /* Test 2: Get a non-existing per connection key, value should be NULL */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_CONN_UNKNOWN_KEY, |
| &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| /* Test 3: Store and retrieve a string value for a per-connection key */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg1, PER_CONN_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_CONN_TEST_KEY, &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| |
| /* Test that the key was set in the config for the first connection only. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg2, PER_CONN_TEST_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| /* Test 4: Store and retrieve a string value for a per-host key */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg1, PER_HOST_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg1, PER_HOST_TEST_KEY, &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| |
| /* Test that the key was also set in the config for the second connection, |
| since they are the same host. */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg2, PER_HOST_TEST_KEY, &actual)); |
| CuAssertStrEquals(tc, "test_value", actual); |
| } |
| |
| static void test_config_store_error_handling(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_config_t *cfg; |
| const char *actual; |
| void *actual_obj; |
| |
| serf_context_t *ctx = serf_context_create(tb->pool); |
| |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_ctx_config(ctx, &cfg)); |
| |
| /* Config only has per-context keys, check for no crashes when getting |
| per-connection and per-host keys. */ |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_get_string(cfg, PER_HOST_TEST_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_get_string(cfg, PER_CONN_TEST_KEY, &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_set_string(cfg, PER_CONN_TEST_KEY, |
| "test_value")); |
| |
| /* The same tests with objects instead of strings */ |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_get_object(cfg, PER_HOST_TEST_KEY, &actual_obj)); |
| CuAssertPtrEquals(tc, NULL, actual_obj); |
| |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_get_object(cfg, PER_CONN_TEST_KEY, &actual_obj)); |
| CuAssertPtrEquals(tc, NULL, actual_obj); |
| |
| CuAssertIntEquals(tc, APR_EINVAL, |
| serf_config_set_object(cfg, PER_CONN_TEST_KEY, stderr)); |
| } |
| |
| static void test_config_store_remove_objects(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_config_t *cfg; |
| serf_connection_t *conn; |
| apr_uri_t url; |
| const char *actual; |
| |
| serf_context_t *ctx = serf_context_create(tb->pool); |
| |
| /* Create a connection conn */ |
| apr_uri_parse(tb->pool, "http://localhost:12345", &url); |
| serf_connection_create2(&conn, ctx, url, conn_setup, NULL, |
| conn_closed, NULL, tb->pool); |
| |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf__config_store_create_conn_config(conn, &cfg)); |
| |
| /* Add and remove a key per-context */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg, PER_CONTEXT_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_remove_value(cfg, PER_CONTEXT_TEST_KEY)); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg, PER_CONTEXT_TEST_KEY, |
| &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| /* Add and remove a key per-context */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg, PER_HOST_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_remove_value(cfg, PER_HOST_TEST_KEY)); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg, PER_HOST_TEST_KEY, |
| &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| |
| |
| /* Add and remove a key per-context */ |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_set_string(cfg, PER_CONN_TEST_KEY, |
| "test_value")); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_remove_value(cfg, PER_CONN_TEST_KEY)); |
| CuAssertIntEquals(tc, APR_SUCCESS, |
| serf_config_get_string(cfg, PER_CONN_TEST_KEY, |
| &actual)); |
| CuAssertPtrEquals(tc, NULL, actual); |
| } |
| |
| /* Add and remove some headers from the headers bucket. */ |
| /* Note: serf__bucket_headers_remove is an internal function */ |
| static void test_header_buckets_remove(CuTest *tc) |
| { |
| test_baton_t *tb = tc->testBaton; |
| serf_bucket_alloc_t *alloc = test__create_bucket_allocator(tc, tb->pool); |
| const char *cur; |
| |
| serf_bucket_t *hdrs = serf_bucket_headers_create(alloc); |
| CuAssertTrue(tc, hdrs != NULL); |
| |
| /* empty bucket, delete header */ |
| serf__bucket_headers_remove(hdrs, "Content-Length"); |
| |
| /* bucket with one header, delete a non-existent header */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf__bucket_headers_remove(hdrs, "Content-Length"); |
| cur = "Content-Type: text/plain" CRLF CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| |
| serf_bucket_destroy(hdrs); |
| hdrs = serf_bucket_headers_create(alloc); |
| |
| /* bucket with one header, delete it */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf__bucket_headers_remove(hdrs, "Content-Type"); |
| cur = CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| |
| serf_bucket_destroy(hdrs); |
| hdrs = serf_bucket_headers_create(alloc); |
| |
| /* bucket with two headers, delete the first */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf_bucket_headers_set(hdrs, "Content-Length", "100"); |
| serf__bucket_headers_remove(hdrs, "Content-Type"); |
| cur = "Content-Length: 100" CRLF CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| |
| serf_bucket_destroy(hdrs); |
| hdrs = serf_bucket_headers_create(alloc); |
| |
| /* bucket with two headers, delete the second */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf_bucket_headers_set(hdrs, "Content-Length", "100"); |
| serf__bucket_headers_remove(hdrs, "Content-Length"); |
| cur = "Content-Type: text/plain" CRLF CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| |
| serf_bucket_destroy(hdrs); |
| hdrs = serf_bucket_headers_create(alloc); |
| |
| /* bucket with more headers, delete one in the middle */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf_bucket_headers_set(hdrs, "Content-Location", "/"); |
| serf_bucket_headers_set(hdrs, "Content-Length", "100"); |
| serf__bucket_headers_remove(hdrs, "Content-Location"); |
| cur = "Content-Type: text/plain" CRLF |
| "Content-Length: 100" CRLF CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| |
| serf_bucket_destroy(hdrs); |
| hdrs = serf_bucket_headers_create(alloc); |
| |
| /* bucket with more headers, delete more in the middle */ |
| serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); |
| serf_bucket_headers_set(hdrs, "Content-Location", "/"); |
| serf_bucket_headers_set(hdrs, "Content-Location", "/bla"); |
| serf_bucket_headers_set(hdrs, "Content-Length", "100"); |
| serf_bucket_headers_set(hdrs, "Content-Location", "/blub"); |
| serf__bucket_headers_remove(hdrs, "Content-Location"); |
| cur = "Content-Type: text/plain" CRLF |
| "Content-Length: 100" CRLF CRLF; |
| read_and_check_bucket(tc, hdrs, cur); |
| serf_bucket_destroy(hdrs); |
| } |
| |
| static void test_runtime_versions(CuTest *tc) |
| { |
| apr_version_t version_of_apr; |
| #if APR_MAJOR_VERSION < 2 |
| apr_version_t version_of_aprutil; |
| #endif |
| |
| apr_version(&version_of_apr); |
| |
| CuAssertIntEquals(tc, APR_MAJOR_VERSION, version_of_apr.major); |
| CuAssertTrue(tc, version_of_apr.minor >= APR_MINOR_VERSION); |
| |
| if (version_of_apr.minor == APR_MINOR_VERSION) |
| CuAssertTrue(tc, version_of_apr.patch >= APR_PATCH_VERSION); |
| |
| #if APR_MAJOR_VERSION < 2 |
| apu_version(&version_of_aprutil); |
| |
| CuAssertIntEquals(tc, APU_MAJOR_VERSION, version_of_aprutil.major); |
| CuAssertTrue(tc, version_of_aprutil.minor >= APU_MINOR_VERSION); |
| |
| if (version_of_aprutil.minor == APU_MINOR_VERSION) |
| CuAssertTrue(tc, version_of_aprutil.patch >= APU_PATCH_VERSION); |
| |
| CuAssertIntEquals(tc, APR_MAJOR_VERSION, APU_MAJOR_VERSION); |
| #endif |
| } |
| |
| static void test_narrowing_conversions(CuTest *tc) |
| { |
| int val; |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, 0); |
| CuAssertIntEquals(tc, 0, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, 0); |
| CuAssertIntEquals(tc, 0, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, 1); |
| CuAssertIntEquals(tc, 1, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, 1); |
| CuAssertIntEquals(tc, 1, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, -1); |
| CuAssertIntEquals(tc, INT_MAX, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, -1); |
| CuAssertIntEquals(tc, -1, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, INT_MAX); |
| CuAssertIntEquals(tc, INT_MAX, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, INT_MAX); |
| CuAssertIntEquals(tc, INT_MAX, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, INT_MIN); |
| CuAssertIntEquals(tc, 0, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, INT_MIN); |
| CuAssertIntEquals(tc, INT_MIN, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, APR_INT64_MAX); |
| CuAssertIntEquals(tc, INT_MAX, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, APR_INT64_MAX); |
| CuAssertIntEquals(tc, -1, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, APR_INT64_MIN); |
| CuAssertIntEquals(tc, 0, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, APR_INT64_MIN); |
| CuAssertIntEquals(tc, 0, val); |
| |
| SERF__POSITIVE_TO_INT(val, apr_uint64_t, APR_UINT64_MAX); |
| CuAssertIntEquals(tc, INT_MAX, val); |
| SERF__SIGNED_TO_INT(val, apr_int64_t, APR_UINT64_MAX); |
| CuAssertIntEquals(tc, -1, val); |
| } |
| |
| |
| struct expected_attrs |
| { |
| const char *token; |
| const char *value; |
| }; |
| |
| static void parse_parameters(CuTest *tc, const char *attrs, |
| const struct expected_attrs expected[]) |
| { |
| test_baton_t *const tb = tc->testBaton; |
| apr_hash_t *const dict = serf__parse_authn_parameters(attrs, tb->pool); |
| const short attr_count = apr_hash_count(dict); |
| int i; |
| |
| for (i = 0; expected[i].token; ++i) |
| { |
| const char *token = expected[i].token; |
| const char *value = apr_hash_get(dict, token, APR_HASH_KEY_STRING); |
| CuAssertStrEquals(tc, expected[i].value, value); |
| } |
| CuAssertIntEquals(tc, i, attr_count); |
| } |
| |
| static void test_parse_parameters(CuTest *tc) |
| { |
| static const struct expected_attrs expected[] = { |
| { "realm", "Wonderland" }, |
| { "scope", "Alice" }, |
| { "!#$%&'*+-.^_`|~", "(\"\\)"}, |
| { "empty", "" }, |
| { NULL, NULL } |
| }; |
| |
| parse_parameters(tc, |
| "Realm=\"Wonderland\"," |
| "ScOpE=Alice , " |
| "!#$%&'*+-.^_`|~=\"(\\\"\\\\)\"," |
| "empty=\"\"", |
| expected); |
| } |
| |
| static void test_parse_bad_parameters(CuTest *tc) |
| { |
| static const struct expected_attrs unexpected[] = { |
| { "first", "value" }, |
| { NULL, NULL } |
| }; |
| static const struct expected_attrs *expected = &unexpected[1]; |
| |
| parse_parameters(tc, "", expected); |
| parse_parameters(tc, "\t", expected); |
| parse_parameters(tc, "(comm", expected); |
| parse_parameters(tc, "first=value, key=", unexpected); |
| parse_parameters(tc, "key=\"value", expected); |
| parse_parameters(tc, "key = value", expected); |
| parse_parameters(tc, "key=\"value1\"key=value2", expected); |
| parse_parameters(tc, "key=value1 key=value2", expected); |
| } |
| |
| static void test_parse_repeated_parameters(CuTest *tc) |
| { |
| static const struct expected_attrs expected[] = { |
| { "key", "value2" }, |
| { NULL, NULL } |
| }; |
| |
| parse_parameters(tc, "key=value1, key=value2", expected); |
| } |
| |
| static void test_parse_single_token_parameters(CuTest *tc) |
| { |
| static const struct expected_attrs expected[] = { |
| { "", "Alice/In+Wonderland.==" }, |
| { NULL, NULL } |
| }; |
| |
| parse_parameters(tc, "\tAlice/In+Wonderland.== ", expected); |
| parse_parameters(tc, "Alice=In+Wonderland.=", &expected[1]); |
| } |
| |
| static void test_parameter_case_folding(CuTest *tc) |
| { |
| static const struct expected_attrs expected[] = { |
| { "01234abcdefghijklmnopqrstuvwxyz56789", "Val" }, |
| { NULL, NULL } |
| }; |
| |
| parse_parameters(tc, "01234abcdefghijklmnopqrstuvwxyz56789=Val", expected); |
| parse_parameters(tc, "01234ABCDEFGHIJKLMNOPQRSTUVWXYZ56789=Val", expected); |
| } |
| |
| static void test_find_token(CuTest *tc) |
| { |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 0, "foo")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, "foo")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, " foo")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, "foo ")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, "bar\tfoo")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, "foo\tbar")); |
| CuAssertPtrNotNull(tc, serf__find_token("foo", 3, "bar\t #$@*&^! foo qux")); |
| CuAssertPtrEquals(tc, NULL, serf__find_token("foo", 2, "foo")); |
| CuAssertPtrEquals(tc, NULL, serf__find_token("foo", 3, "\vfoo")); |
| CuAssertPtrEquals(tc, NULL, serf__find_token("foo", 3, "foobar")); |
| CuAssertPtrEquals(tc, NULL, serf__find_token("foo", 3, " qux foobar baz")); |
| CuAssertPtrEquals(tc, NULL, serf__find_token("foo", 3, " qux bar")); |
| } |
| |
| |
| CuSuite *test_internal(void) |
| { |
| CuSuite *suite = CuSuiteNew(); |
| |
| CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); |
| |
| SUITE_ADD_TEST(suite, test_config_store_per_context); |
| SUITE_ADD_TEST(suite, test_config_store_per_connection_different_host); |
| SUITE_ADD_TEST(suite, test_config_store_per_connection_same_host); |
| SUITE_ADD_TEST(suite, test_config_store_error_handling); |
| SUITE_ADD_TEST(suite, test_config_store_remove_objects); |
| SUITE_ADD_TEST(suite, test_header_buckets_remove); |
| SUITE_ADD_TEST(suite, test_runtime_versions); |
| SUITE_ADD_TEST(suite, test_narrowing_conversions); |
| SUITE_ADD_TEST(suite, test_parse_parameters); |
| SUITE_ADD_TEST(suite, test_parse_bad_parameters); |
| SUITE_ADD_TEST(suite, test_parse_repeated_parameters); |
| SUITE_ADD_TEST(suite, test_parse_single_token_parameters); |
| SUITE_ADD_TEST(suite, test_parameter_case_folding); |
| SUITE_ADD_TEST(suite, test_find_token); |
| |
| return suite; |
| } |