| /* 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 "testutil.h" |
| #include "apr.h" |
| #include "apr_strings.h" |
| #include "apr_general.h" |
| #include "apr_pools.h" |
| #include "apr_hash.h" |
| |
| #define MAX_LTH 256 |
| #define MAX_DEPTH 11 |
| |
| static int comp_string(const void *str1, const void *str2) |
| { |
| return strcmp(str1,str2); |
| } |
| |
| static void dump_hash(apr_pool_t *p, apr_hash_t *h, char str[][MAX_LTH]) |
| { |
| apr_hash_index_t *hi; |
| char *val, *key; |
| apr_ssize_t len; |
| int i = 0; |
| |
| for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) { |
| apr_hash_this(hi,(void*) &key, &len, (void*) &val); |
| str[i][0]='\0'; |
| apr_snprintf(str[i], MAX_LTH, "%sKey %s (%" APR_SSIZE_T_FMT ") Value %s\n", |
| str[i], key, len, val); |
| i++; |
| } |
| str[i][0]='\0'; |
| apr_snprintf(str[i], MAX_LTH, "%s#entries %d\n", str[i], i); |
| |
| /* Sort the result strings so that they can be checked for expected results easily, |
| * without having to worry about platform quirks |
| */ |
| qsort( |
| str, /* Pointer to elements */ |
| i, /* number of elements */ |
| MAX_LTH, /* size of one element */ |
| comp_string /* Pointer to comparison routine */ |
| ); |
| } |
| |
| static void sum_hash(apr_pool_t *p, apr_hash_t *h, int *pcount, int *keySum, int *valSum) |
| { |
| apr_hash_index_t *hi; |
| void *val, *key; |
| int count = 0; |
| |
| *keySum = 0; |
| *valSum = 0; |
| *pcount = 0; |
| for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) { |
| apr_hash_this(hi, (void*)&key, NULL, &val); |
| *valSum += *(int *)val; |
| *keySum += *(int *)key; |
| count++; |
| } |
| *pcount=count; |
| } |
| |
| static void hash_make(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| } |
| |
| static void hash_set(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); |
| result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value", result); |
| } |
| |
| static void hash_reset(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); |
| result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value", result); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, "new"); |
| result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "new", result); |
| } |
| |
| static void same_value(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "same1", APR_HASH_KEY_STRING, "same"); |
| result = apr_hash_get(h, "same1", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "same", result); |
| |
| apr_hash_set(h, "same2", APR_HASH_KEY_STRING, "same"); |
| result = apr_hash_get(h, "same2", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "same", result); |
| } |
| |
| static unsigned int hash_custom( const char *key, apr_ssize_t *klen) |
| { |
| unsigned int hash = 0; |
| while( *klen ) { |
| (*klen) --; |
| hash = hash * 33 + key[ *klen ]; |
| } |
| return hash; |
| } |
| |
| static void same_value_custom(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make_custom(p, hash_custom); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "same1", 5, "same"); |
| result = apr_hash_get(h, "same1", 5); |
| ABTS_STR_EQUAL(tc, "same", result); |
| |
| apr_hash_set(h, "same2", 5, "same"); |
| result = apr_hash_get(h, "same2", 5); |
| ABTS_STR_EQUAL(tc, "same", result); |
| } |
| |
| static void key_space(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key with space", APR_HASH_KEY_STRING, "value"); |
| result = apr_hash_get(h, "key with space", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value", result); |
| } |
| |
| static void hash_clear(abts_case *tc, void *data) |
| { |
| apr_hash_t *h; |
| int i, *e; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| for (i = 1; i <= 10; i++) { |
| e = apr_palloc(p, sizeof(int)); |
| *e = i; |
| apr_hash_set(h, e, sizeof(*e), e); |
| } |
| apr_hash_clear(h); |
| i = apr_hash_count(h); |
| ABTS_INT_EQUAL(tc, 0, i); |
| } |
| |
| /* This is kind of a hack, but I am just keeping an existing test. This is |
| * really testing apr_hash_first, apr_hash_next, and apr_hash_this which |
| * should be tested in three separate tests, but this will do for now. |
| */ |
| static void hash_traverse(abts_case *tc, void *data) |
| { |
| apr_hash_t *h; |
| char StrArray[MAX_DEPTH][MAX_LTH]; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "should not see this"); |
| apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3"); |
| apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3"); |
| apr_hash_set(h, "FOO1", APR_HASH_KEY_STRING, "bar1"); |
| apr_hash_set(h, "FOO2", APR_HASH_KEY_STRING, "bar2"); |
| apr_hash_set(h, "FOO4", APR_HASH_KEY_STRING, "bar4"); |
| apr_hash_set(h, "SAME1", APR_HASH_KEY_STRING, "same"); |
| apr_hash_set(h, "SAME2", APR_HASH_KEY_STRING, "same"); |
| apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "Overwrite key"); |
| |
| dump_hash(p, h, StrArray); |
| |
| ABTS_STR_EQUAL(tc, "Key FOO1 (4) Value bar1\n", StrArray[0]); |
| ABTS_STR_EQUAL(tc, "Key FOO2 (4) Value bar2\n", StrArray[1]); |
| ABTS_STR_EQUAL(tc, "Key FOO3 (4) Value bar3\n", StrArray[2]); |
| ABTS_STR_EQUAL(tc, "Key FOO4 (4) Value bar4\n", StrArray[3]); |
| ABTS_STR_EQUAL(tc, "Key OVERWRITE (9) Value Overwrite key\n", StrArray[4]); |
| ABTS_STR_EQUAL(tc, "Key SAME1 (5) Value same\n", StrArray[5]); |
| ABTS_STR_EQUAL(tc, "Key SAME2 (5) Value same\n", StrArray[6]); |
| ABTS_STR_EQUAL(tc, "#entries 7\n", StrArray[7]); |
| } |
| |
| /* This is kind of a hack, but I am just keeping an existing test. This is |
| * really testing apr_hash_first, apr_hash_next, and apr_hash_this which |
| * should be tested in three separate tests, but this will do for now. |
| */ |
| static void summation_test(abts_case *tc, void *data) |
| { |
| apr_hash_t *h; |
| int sumKeys, sumVal, trySumKey, trySumVal; |
| int i, j, *val, *key; |
| |
| h =apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| sumKeys = 0; |
| sumVal = 0; |
| trySumKey = 0; |
| trySumVal = 0; |
| |
| for (i = 0; i < 100; i++) { |
| j = i * 10 + 1; |
| sumKeys += j; |
| sumVal += i; |
| key = apr_palloc(p, sizeof(int)); |
| *key = j; |
| val = apr_palloc(p, sizeof(int)); |
| *val = i; |
| apr_hash_set(h, key, sizeof(int), val); |
| } |
| |
| sum_hash(p, h, &i, &trySumKey, &trySumVal); |
| ABTS_INT_EQUAL(tc, 100, i); |
| ABTS_INT_EQUAL(tc, sumVal, trySumVal); |
| ABTS_INT_EQUAL(tc, sumKeys, trySumKey); |
| } |
| |
| static void delete_key(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| char *result = NULL; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); |
| apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2"); |
| |
| result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value", result); |
| |
| result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value2", result); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, NULL); |
| |
| result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); |
| ABTS_PTR_EQUAL(tc, NULL, result); |
| |
| result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING); |
| ABTS_STR_EQUAL(tc, "value2", result); |
| } |
| |
| static void hash_count_0(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| int count; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| count = apr_hash_count(h); |
| ABTS_INT_EQUAL(tc, 0, count); |
| } |
| |
| static void hash_count_1(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| int count; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); |
| |
| count = apr_hash_count(h); |
| ABTS_INT_EQUAL(tc, 1, count); |
| } |
| |
| static void hash_count_5(abts_case *tc, void *data) |
| { |
| apr_hash_t *h = NULL; |
| int count; |
| |
| h = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, h); |
| |
| apr_hash_set(h, "key1", APR_HASH_KEY_STRING, "value1"); |
| apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2"); |
| apr_hash_set(h, "key3", APR_HASH_KEY_STRING, "value3"); |
| apr_hash_set(h, "key4", APR_HASH_KEY_STRING, "value4"); |
| apr_hash_set(h, "key5", APR_HASH_KEY_STRING, "value5"); |
| |
| count = apr_hash_count(h); |
| ABTS_INT_EQUAL(tc, 5, count); |
| } |
| |
| static void overlay_empty(abts_case *tc, void *data) |
| { |
| apr_hash_t *base = NULL; |
| apr_hash_t *overlay = NULL; |
| apr_hash_t *result = NULL; |
| int count; |
| char StrArray[MAX_DEPTH][MAX_LTH]; |
| |
| base = apr_hash_make(p); |
| overlay = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, base); |
| ABTS_PTR_NOTNULL(tc, overlay); |
| |
| apr_hash_set(base, "key1", APR_HASH_KEY_STRING, "value1"); |
| apr_hash_set(base, "key2", APR_HASH_KEY_STRING, "value2"); |
| apr_hash_set(base, "key3", APR_HASH_KEY_STRING, "value3"); |
| apr_hash_set(base, "key4", APR_HASH_KEY_STRING, "value4"); |
| apr_hash_set(base, "key5", APR_HASH_KEY_STRING, "value5"); |
| |
| result = apr_hash_overlay(p, overlay, base); |
| |
| count = apr_hash_count(result); |
| ABTS_INT_EQUAL(tc, 5, count); |
| |
| dump_hash(p, result, StrArray); |
| |
| ABTS_STR_EQUAL(tc, "Key key1 (4) Value value1\n", StrArray[0]); |
| ABTS_STR_EQUAL(tc, "Key key2 (4) Value value2\n", StrArray[1]); |
| ABTS_STR_EQUAL(tc, "Key key3 (4) Value value3\n", StrArray[2]); |
| ABTS_STR_EQUAL(tc, "Key key4 (4) Value value4\n", StrArray[3]); |
| ABTS_STR_EQUAL(tc, "Key key5 (4) Value value5\n", StrArray[4]); |
| ABTS_STR_EQUAL(tc, "#entries 5\n", StrArray[5]); |
| } |
| |
| static void overlay_2unique(abts_case *tc, void *data) |
| { |
| apr_hash_t *base = NULL; |
| apr_hash_t *overlay = NULL; |
| apr_hash_t *result = NULL; |
| int count; |
| char StrArray[MAX_DEPTH][MAX_LTH]; |
| |
| base = apr_hash_make(p); |
| overlay = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, base); |
| ABTS_PTR_NOTNULL(tc, overlay); |
| |
| apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1"); |
| apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2"); |
| apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3"); |
| apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4"); |
| apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5"); |
| |
| apr_hash_set(overlay, "overlay1", APR_HASH_KEY_STRING, "value1"); |
| apr_hash_set(overlay, "overlay2", APR_HASH_KEY_STRING, "value2"); |
| apr_hash_set(overlay, "overlay3", APR_HASH_KEY_STRING, "value3"); |
| apr_hash_set(overlay, "overlay4", APR_HASH_KEY_STRING, "value4"); |
| apr_hash_set(overlay, "overlay5", APR_HASH_KEY_STRING, "value5"); |
| |
| result = apr_hash_overlay(p, overlay, base); |
| |
| count = apr_hash_count(result); |
| ABTS_INT_EQUAL(tc, 10, count); |
| |
| dump_hash(p, result, StrArray); |
| |
| ABTS_STR_EQUAL(tc, "Key base1 (5) Value value1\n", StrArray[0]); |
| ABTS_STR_EQUAL(tc, "Key base2 (5) Value value2\n", StrArray[1]); |
| ABTS_STR_EQUAL(tc, "Key base3 (5) Value value3\n", StrArray[2]); |
| ABTS_STR_EQUAL(tc, "Key base4 (5) Value value4\n", StrArray[3]); |
| ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n", StrArray[4]); |
| ABTS_STR_EQUAL(tc, "Key overlay1 (8) Value value1\n", StrArray[5]); |
| ABTS_STR_EQUAL(tc, "Key overlay2 (8) Value value2\n", StrArray[6]); |
| ABTS_STR_EQUAL(tc, "Key overlay3 (8) Value value3\n", StrArray[7]); |
| ABTS_STR_EQUAL(tc, "Key overlay4 (8) Value value4\n", StrArray[8]); |
| ABTS_STR_EQUAL(tc, "Key overlay5 (8) Value value5\n", StrArray[9]); |
| ABTS_STR_EQUAL(tc, "#entries 10\n", StrArray[10]); |
| } |
| |
| static void overlay_same(abts_case *tc, void *data) |
| { |
| apr_hash_t *base = NULL; |
| apr_hash_t *result = NULL; |
| int count; |
| char StrArray[MAX_DEPTH][MAX_LTH]; |
| |
| base = apr_hash_make(p); |
| ABTS_PTR_NOTNULL(tc, base); |
| |
| apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1"); |
| apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2"); |
| apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3"); |
| apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4"); |
| apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5"); |
| |
| result = apr_hash_overlay(p, base, base); |
| |
| count = apr_hash_count(result); |
| ABTS_INT_EQUAL(tc, 5, count); |
| |
| dump_hash(p, result, StrArray); |
| |
| ABTS_STR_EQUAL(tc, "Key base1 (5) Value value1\n", StrArray[0]); |
| ABTS_STR_EQUAL(tc, "Key base2 (5) Value value2\n", StrArray[1]); |
| ABTS_STR_EQUAL(tc, "Key base3 (5) Value value3\n", StrArray[2]); |
| ABTS_STR_EQUAL(tc, "Key base4 (5) Value value4\n", StrArray[3]); |
| ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n", StrArray[4]); |
| ABTS_STR_EQUAL(tc, "#entries 5\n", StrArray[5]); |
| } |
| |
| abts_suite *testhash(abts_suite *suite) |
| { |
| suite = ADD_SUITE(suite) |
| |
| abts_run_test(suite, hash_make, NULL); |
| abts_run_test(suite, hash_set, NULL); |
| abts_run_test(suite, hash_reset, NULL); |
| abts_run_test(suite, same_value, NULL); |
| abts_run_test(suite, same_value_custom, NULL); |
| abts_run_test(suite, key_space, NULL); |
| abts_run_test(suite, delete_key, NULL); |
| |
| abts_run_test(suite, hash_count_0, NULL); |
| abts_run_test(suite, hash_count_1, NULL); |
| abts_run_test(suite, hash_count_5, NULL); |
| |
| abts_run_test(suite, hash_clear, NULL); |
| abts_run_test(suite, hash_traverse, NULL); |
| abts_run_test(suite, summation_test, NULL); |
| |
| abts_run_test(suite, overlay_empty, NULL); |
| abts_run_test(suite, overlay_2unique, NULL); |
| abts_run_test(suite, overlay_same, NULL); |
| |
| return suite; |
| } |
| |