unit-tests: Move test suites to its own subfolder
authorMartin Willi <martin@revosec.ch>
Mon, 14 Oct 2013 14:44:27 +0000 (16:44 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 6 Nov 2013 09:30:58 +0000 (10:30 +0100)
39 files changed:
src/libstrongswan/tests/Makefile.am
src/libstrongswan/tests/suites/test_array.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_asn1.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_bio_reader.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_bio_writer.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_chunk.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_ecdsa.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_enum.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_enumerator.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_hashtable.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_host.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_identification.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_linked_list.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_linked_list_enumerator.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_pen.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_printf.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_rsa.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_threading.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_utils.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_vectors.c [new file with mode: 0644]
src/libstrongswan/tests/test_array.c [deleted file]
src/libstrongswan/tests/test_asn1.c [deleted file]
src/libstrongswan/tests/test_bio_reader.c [deleted file]
src/libstrongswan/tests/test_bio_writer.c [deleted file]
src/libstrongswan/tests/test_chunk.c [deleted file]
src/libstrongswan/tests/test_ecdsa.c [deleted file]
src/libstrongswan/tests/test_enum.c [deleted file]
src/libstrongswan/tests/test_enumerator.c [deleted file]
src/libstrongswan/tests/test_hashtable.c [deleted file]
src/libstrongswan/tests/test_host.c [deleted file]
src/libstrongswan/tests/test_identification.c [deleted file]
src/libstrongswan/tests/test_linked_list.c [deleted file]
src/libstrongswan/tests/test_linked_list_enumerator.c [deleted file]
src/libstrongswan/tests/test_pen.c [deleted file]
src/libstrongswan/tests/test_printf.c [deleted file]
src/libstrongswan/tests/test_rsa.c [deleted file]
src/libstrongswan/tests/test_threading.c [deleted file]
src/libstrongswan/tests/test_utils.c [deleted file]
src/libstrongswan/tests/test_vectors.c [deleted file]

index 994619e..54ceaf5 100644 (file)
@@ -4,11 +4,25 @@ check_PROGRAMS = $(TESTS)
 
 test_runner_SOURCES = \
   test_runner.c test_runner.h test_suite.h \
-  test_linked_list.c test_enumerator.c test_linked_list_enumerator.c \
-  test_bio_reader.c test_bio_writer.c test_chunk.c test_enum.c test_hashtable.c \
-  test_identification.c test_threading.c test_utils.c test_vectors.c \
-  test_array.c test_ecdsa.c test_rsa.c test_host.c test_printf.c test_pen.c \
-  test_asn1.c
+  suites/test_linked_list.c \
+  suites/test_enumerator.c \
+  suites/test_linked_list_enumerator.c \
+  suites/test_bio_reader.c \
+  suites/test_bio_writer.c \
+  suites/test_chunk.c \
+  suites/test_enum.c \
+  suites/test_hashtable.c \
+  suites/test_identification.c \
+  suites/test_threading.c \
+  suites/test_utils.c \
+  suites/test_vectors.c \
+  suites/test_array.c \
+  suites/test_ecdsa.c \
+  suites/test_rsa.c \
+  suites/test_host.c \
+  suites/test_pen.c \
+  suites/test_asn1.c \
+  suites/test_printf.c
 
 test_runner_CFLAGS = \
   -I$(top_srcdir)/src/libstrongswan \
diff --git a/src/libstrongswan/tests/suites/test_array.c b/src/libstrongswan/tests/suites/test_array.c
new file mode 100644 (file)
index 0000000..2220d5a
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <collections/array.h>
+
+START_TEST(test_append_ptr)
+{
+       array_t *array;
+       uintptr_t x;
+       int i;
+
+       array = array_create(0, 0);
+
+       for (i = 0; i < 4; i++)
+       {
+               ck_assert_int_eq(array_count(array), 0);
+
+               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)3);
+               array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)4);
+               ck_assert_int_eq(array_count(array), 2);
+
+               /* 3, 4 */
+
+               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)1);
+               array_insert(array, 1, (void*)(uintptr_t)2);
+               ck_assert_int_eq(array_count(array), 4);
+
+               /* 1, 2, 3, 4 */
+
+               array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)5);
+               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)0);
+               ck_assert_int_eq(array_count(array), 6);
+
+               /* 0, 1, 2, 3, 4, 5 */
+
+               ck_assert(array_remove(array, ARRAY_TAIL, &x));
+               ck_assert_int_eq(x, 5);
+               ck_assert(array_remove(array, 4, &x));
+               ck_assert_int_eq(x, 4);
+
+               if (i < 3)
+               {
+                       array_compress(array);
+               }
+
+               /* 0, 1, 2, 3 */
+
+               ck_assert(array_remove(array, 1, &x));
+               ck_assert_int_eq(x, 1);
+               ck_assert(array_remove(array, ARRAY_HEAD, &x));
+               ck_assert_int_eq(x, 0);
+
+               if (i < 2)
+               {
+                       array_compress(array);
+               }
+
+               /* 2, 3 */
+
+               ck_assert(array_remove(array, ARRAY_TAIL, &x));
+               ck_assert_int_eq(x, 3);
+               ck_assert(array_remove(array, ARRAY_TAIL, &x));
+               ck_assert_int_eq(x, 2);
+
+               if (i < 1)
+               {
+                       array_compress(array);
+               }
+
+               ck_assert_int_eq(array_count(array), 0);
+
+               ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
+               ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
+       }
+
+       array_destroy(array);
+}
+END_TEST
+
+START_TEST(test_append_obj)
+{
+       array_t *array;
+       int i, x, y[6] = {0, 1, 2, 3, 4, 5};
+
+       array = array_create(sizeof(y[0]), 0);
+
+       for (i = 0; i < 4; i++)
+       {
+               ck_assert_int_eq(array_count(array), 0);
+
+               array_insert(array, ARRAY_HEAD, &y[3]);
+               array_insert(array, ARRAY_TAIL, &y[4]);
+               ck_assert_int_eq(array_count(array), 2);;
+
+               /* 3, 4 */
+
+               array_insert(array, ARRAY_HEAD, &y[1]);
+               array_insert(array, 1, &y[2]);
+               ck_assert_int_eq(array_count(array), 4);
+
+               /* 1, 2, 3, 4 */
+
+               array_insert(array, ARRAY_TAIL, &y[5]);
+               array_insert(array, ARRAY_HEAD, &y[0]);
+               ck_assert_int_eq(array_count(array), 6);
+
+               /* 0, 1, 2, 3, 4, 5 */
+
+               ck_assert(array_remove(array, ARRAY_TAIL, &x));
+               ck_assert_int_eq(x, 5);
+               ck_assert(array_remove(array, 4, &x));
+               ck_assert_int_eq(x, 4);
+
+               if (i < 3)
+               {
+                       array_compress(array);
+               }
+
+               /* 0, 1, 2, 3 */
+
+               ck_assert(array_remove(array, ARRAY_HEAD, &x));
+               ck_assert_int_eq(x, 0);
+               ck_assert(array_remove(array, ARRAY_HEAD, &x));
+               ck_assert_int_eq(x, 1);
+
+               if (i < 2)
+               {
+                       array_compress(array);
+               }
+
+               /* 2, 3 */
+
+               ck_assert(array_remove(array, ARRAY_TAIL, &x));
+               ck_assert_int_eq(x, 3);
+               ck_assert(array_remove(array, ARRAY_HEAD, &x));
+               ck_assert_int_eq(x, 2);
+
+               if (i < 1)
+               {
+                       array_compress(array);
+               }
+
+               ck_assert_int_eq(array_count(array), 0);
+
+               ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
+               ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
+       }
+
+       array_destroy(array);
+}
+END_TEST
+
+START_TEST(test_enumerate)
+{
+       array_t *array;
+       int i, *x, y[6] = {0, 1, 2, 3, 4, 5};
+       enumerator_t *enumerator;
+
+       array = array_create(sizeof(y[0]), 0);
+
+       array_insert(array, ARRAY_TAIL, &y[0]);
+       array_insert(array, ARRAY_TAIL, &y[1]);
+       array_insert(array, ARRAY_TAIL, &y[2]);
+       array_insert(array, ARRAY_TAIL, &y[3]);
+       array_insert(array, ARRAY_TAIL, &y[4]);
+       array_insert(array, ARRAY_TAIL, &y[5]);
+
+       ck_assert_int_eq(array_count(array), 6);
+
+       /* 0, 1, 2, 3, 4, 5 */
+
+       i = 0;
+       enumerator = array_create_enumerator(array);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(*x, y[i]);
+               i++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(i, 6);
+
+       i = 0;
+       enumerator = array_create_enumerator(array);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(*x, y[i]);
+               if (i == 0 || i == 3 || i == 5)
+               {
+                       array_remove_at(array, enumerator);
+               }
+               i++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(i, 6);
+       ck_assert_int_eq(array_count(array), 3);
+
+       /* 1, 2, 4 */
+
+       i = 0;
+       enumerator = array_create_enumerator(array);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               switch (i++)
+               {
+                       case 0:
+                               ck_assert_int_eq(*x, y[1]);
+                               break;
+                       case 1:
+                               ck_assert_int_eq(*x, y[2]);
+                               break;
+                       case 2:
+                               ck_assert_int_eq(*x, y[4]);
+                               break;
+                       default:
+                               ck_assert(0);
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       array_compress(array);
+
+       i = 0;
+       enumerator = array_create_enumerator(array);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               switch (i++)
+               {
+                       case 0:
+                               ck_assert_int_eq(*x, y[1]);
+                               break;
+                       case 1:
+                               ck_assert_int_eq(*x, y[2]);
+                               break;
+                       case 2:
+                               ck_assert_int_eq(*x, y[4]);
+                               break;
+                       default:
+                               ck_assert(0);
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       array_destroy(array);
+}
+END_TEST
+
+static void invoke(void *data, int idx, void *user)
+{
+       int *y = user, *x = data;
+
+       ck_assert(idx < 3);
+
+       ck_assert_int_eq(y[idx], *x);
+       y[idx] = 0;
+}
+
+START_TEST(test_invoke)
+{
+       array_t *array;
+       int y[] = {1, 2, 3};
+
+       array = array_create(sizeof(y[0]), 0);
+
+       array_insert(array, ARRAY_TAIL, &y[0]);
+       array_insert(array, ARRAY_TAIL, &y[1]);
+       array_insert(array, ARRAY_TAIL, &y[2]);
+
+       array_invoke(array, invoke, y);
+
+       ck_assert_int_eq(y[0], 0);
+       ck_assert_int_eq(y[0], 0);
+       ck_assert_int_eq(y[0], 0);
+
+       array_destroy(array);
+}
+END_TEST
+
+typedef struct obj_t obj_t;
+
+struct obj_t {
+       void (*fun)(obj_t *obj);
+       int x;
+       int *counter;
+};
+
+static void fun(obj_t *obj)
+{
+       ck_assert(obj->x == (*obj->counter)++);
+}
+
+START_TEST(test_invoke_offset)
+{
+       array_t *array;
+       obj_t objs[5];
+       int i, counter = 0;
+
+       array = array_create(0, 0);
+
+       for (i = 0; i < countof(objs); i++)
+       {
+               objs[i].x = i;
+               objs[i].counter = &counter;
+               objs[i].fun = fun;
+
+               array_insert(array, ARRAY_TAIL, &objs[i]);
+       }
+
+       ck_assert_int_eq(countof(objs), array_count(array));
+
+       array_invoke_offset(array, offsetof(obj_t, fun));
+
+       ck_assert_int_eq(counter, countof(objs));
+
+       array_destroy(array);
+}
+END_TEST
+
+Suite *array_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("array");
+
+       tc = tcase_create("add/remove ptr");
+       tcase_add_test(tc, test_append_ptr);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("add/remove obj");
+       tcase_add_test(tc, test_append_obj);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("enumerate");
+       tcase_add_test(tc, test_enumerate);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("invoke");
+       tcase_add_test(tc, test_invoke);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("invoke offset");
+       tcase_add_test(tc, test_invoke_offset);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_asn1.c b/src/libstrongswan/tests/suites/test_asn1.c
new file mode 100644 (file)
index 0000000..5ac4a94
--- /dev/null
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "test_suite.h"
+
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
+#include <utils/chunk.h>
+
+/*******************************************************************************
+ * algorithm_identifier
+ */
+
+START_TEST(test_asn1_algorithmIdentifier)
+{
+       typedef struct {
+               int n;
+               chunk_t algid;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { OID_ECDSA_WITH_SHA1, chunk_from_chars(0x30, 0x09, 0x06, 0x07,
+                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
+               { OID_SHA1_WITH_RSA,   chunk_from_chars(0x30, 0x0d, 0x06, 0x09,
+                       0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00) },
+       };
+
+       chunk_t algid;
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               algid = asn1_algorithmIdentifier(test[i].n);
+               ck_assert(chunk_equals(algid, test[i].algid));
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * parse_algorithm_identifier
+ */
+
+START_TEST(test_asn1_parse_algorithmIdentifier)
+{
+       typedef struct {
+               int alg;
+               bool empty;
+               chunk_t parameters;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { OID_ECDSA_WITH_SHA1, TRUE,  chunk_empty },
+               { OID_SHA1_WITH_RSA,   TRUE,  chunk_from_chars(0x05, 0x00) },
+               { OID_3DES_EDE_CBC,    FALSE, chunk_from_chars(0x04, 0x01, 0xaa) },
+               { OID_PBKDF2,          FALSE, chunk_from_chars(0x30, 0x01, 0xaa) }
+       };
+
+       chunk_t algid, parameters;
+       int i, alg;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               algid = asn1_wrap(ASN1_SEQUENCE, "mc",
+                                        asn1_build_known_oid(test[i].alg), test[i].parameters);
+               parameters = chunk_empty;
+               if (i == 2)
+               {
+                       alg = asn1_parse_algorithmIdentifier(algid, 0, NULL);
+               }
+               else
+               {
+                       alg = asn1_parse_algorithmIdentifier(algid, 0, &parameters);
+                       if (test[i].empty)
+                       {
+                               ck_assert(parameters.len == 0 && parameters.ptr == NULL);
+                       }
+                               else
+                       {
+                               ck_assert(chunk_equals(parameters, test[i].parameters));
+                       }
+               }
+               ck_assert(alg == test[i].alg);
+               chunk_free(&algid);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * known_oid
+ */
+
+START_TEST(test_asn1_known_oid)
+{
+       typedef struct {
+               int n;
+               chunk_t oid;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { OID_UNKNOWN,    chunk_empty },
+               { OID_UNKNOWN,    chunk_from_chars(0x55, 0x04, 0x02) },
+               { OID_COUNTRY,    chunk_from_chars(0x55, 0x04, 0x06) },
+               { OID_STRONGSWAN, chunk_from_chars(0x2b, 0x06, 0x01, 0x04, 0x01,
+                                                                                  0x82, 0xa0, 0x2a, 0x01) }
+       };
+
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               ck_assert(asn1_known_oid(test[i].oid) == test[i].n);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * build_known_oid
+ */
+
+START_TEST(test_asn1_build_known_oid)
+{
+       typedef struct {
+               int n;
+               chunk_t oid;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { OID_UNKNOWN,    chunk_empty },
+               { OID_MAX,        chunk_empty },
+               { OID_COUNTRY,    chunk_from_chars(0x06, 0x03, 0x55, 0x04, 0x06) },
+               { OID_STRONGSWAN, chunk_from_chars(0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
+                                                                                  0x01, 0x82, 0xa0, 0x2a, 0x01) }
+       };
+
+       int i;
+       chunk_t oid = chunk_empty;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               oid = asn1_build_known_oid(test[i].n);
+               if (test[i].oid.len == 0)
+               {
+                       ck_assert(oid.len == 0 && oid.ptr == NULL);
+               }
+               else
+               {
+                       ck_assert(chunk_equals(oid, test[i].oid));
+                       chunk_free(&oid);
+               }
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * oid_from_string
+ */
+
+START_TEST(test_asn1_oid_from_string)
+{
+       typedef struct {
+               char *string;
+               chunk_t oid;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { "",  chunk_empty },
+               { " ", chunk_empty },
+               { "0.2.262.1", chunk_from_chars(
+                       0x02, 0x82, 0x06, 0x01) },
+               { "1.2.840.10045.4.1", chunk_from_chars(
+                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
+               { "1.3.6.1.4.1.36906.1", chunk_from_chars(
+                       0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) },
+               { "2.16.840.1.101.3.4.2.1", chunk_from_chars(
+                       0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01) },
+               { "0.10.100.1000.10000.100000.1000000.10000000.100000000.268435455",
+                       chunk_from_chars(0x0a,0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d,
+                       0x20, 0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00,
+                       0xaf, 0xd7, 0xc2, 0x00, 0xff, 0xff, 0xff, 0x7f) },
+               { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137."
+                 "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388."
+                 "2097153", chunk_from_chars(
+                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+                       0x81, 0x00, 0x81, 0x01, 0x81, 0x02, 0x81, 0x03, 0x81, 0x04,
+                       0x81, 0x05, 0x81, 0x06, 0x81, 0x07, 0x81, 0x08, 0x81, 0x09,
+                       0x82, 0x00, 0x82, 0x01, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04,
+                       0x82, 0x05, 0x82, 0x06, 0x82, 0x07, 0x82, 0x08, 0x82, 0x09,
+                       0x83, 0x00, 0x83, 0x01, 0x83, 0x02, 0x83, 0x03, 0x83, 0x04,
+                       0x81, 0x80, 0x80, 0x01) },
+               { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137."
+                 "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388."
+                 "1.2097153", chunk_empty },
+               { "1.a.2.b.3", chunk_empty }
+       };
+
+       int i;
+       chunk_t oid = chunk_empty;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               oid = asn1_oid_from_string(test[i].string);
+               if (test[i].oid.len == 0)
+               {
+                       ck_assert(oid.len == 0 && oid.ptr == NULL);
+               }
+               else
+               {
+                       ck_assert(chunk_equals(oid, test[i].oid));
+                       chunk_free(&oid);
+               }
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * oid_to_string
+ */
+
+START_TEST(test_asn1_oid_to_string)
+{
+       typedef struct {
+               char *string;
+               chunk_t oid;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {  NULL,  chunk_empty },
+               { "0.2.262.1", chunk_from_chars(
+                       0x02, 0x82, 0x06, 0x01) },
+               { "1.2.840.10045.4.1", chunk_from_chars(
+                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
+               { "1.3.6.1.4.1.36906.1", chunk_from_chars(
+                       0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) },
+               { "2.16.840.1.101.3.4.2.1", chunk_from_chars(
+                       0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01) },
+               { "0.10.100.1000.10000.100000.1000000.10000000.100000000.268435455",
+                       chunk_from_chars( 0x0a, 0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d,
+                       0x20, 0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00,
+                       0xaf, 0xd7, 0xc2, 0x00, 0xff, 0xff, 0xff, 0x7f) },
+               { NULL, chunk_from_chars(
+                       0x0a, 0x02, 0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d, 0x20,
+                       0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00, 0xaf, 0xd7, 0xc2, 0x00,
+                   0xff, 0xff, 0xff, 0x7f) },
+               { NULL, chunk_from_chars(0x0a, 0x87) }
+       };
+
+       int i;
+       char *string = NULL;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               string = asn1_oid_to_string(test[i].oid);
+               if (test[i].string == NULL)
+               {
+                       ck_assert(string == NULL);
+               }
+               else
+               {
+                       ck_assert(streq(string, test[i].string));
+                       free(string);
+               }
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * length
+ */
+
+START_TEST(test_asn1_length)
+{
+       chunk_t a;
+
+       a = chunk_empty;
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04);
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04, 0x00);
+       ck_assert(asn1_length(&a) == 0);
+
+       a = chunk_from_chars(0x04, 0x01);
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04, 0x01, 0xaa);
+       ck_assert(asn1_length(&a) == 1);
+
+       a = chunk_from_chars(0x04, 0x7f, 0xaa);
+       a.len = 2 + 127;
+       ck_assert(asn1_length(&a) == 127);
+
+       a = chunk_from_chars(0x04, 0x80, 0xaa);
+       a.len = 2 + 128;
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04, 0x81);
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04, 0x81, 0x80, 0xaa);
+       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
+
+       a = chunk_from_chars(0x04, 0x81, 0x80, 0xaa);
+       a.len = 3 + 128;
+       ck_assert(asn1_length(&a) == 128);
+
+       a = chunk_from_chars(0x04, 0x82, 0x01, 0x02, 0xaa);
+       a.len = 4 + 258;
+       ck_assert(asn1_length(&a) == 258);
+
+       a = chunk_from_chars(0x04, 0x83, 0x01, 0x02, 0x03, 0xaa);
+       a.len = 5 + 66051;
+       ck_assert(asn1_length(&a) == 66051);
+}
+END_TEST
+
+/*******************************************************************************
+ * unwrap
+ */
+
+START_TEST(test_asn1_unwrap)
+{
+       chunk_t c0 = chunk_from_chars(0x30);
+       chunk_t c1 = chunk_from_chars(0x30, 0x01, 0xaa);
+       chunk_t c2 = chunk_from_chars(0x30, 0x80);
+       chunk_t c3 = chunk_from_chars(0x30, 0x81);
+       chunk_t c4 = chunk_from_chars(0x30, 0x81, 0x01, 0xaa);
+       chunk_t c5 = chunk_from_chars(0x30, 0x81, 0x02, 0xaa);
+
+       chunk_t inner;
+       chunk_t inner_ref = chunk_from_chars(0xaa);
+
+       ck_assert(asn1_unwrap(&c0, &inner) == ASN1_INVALID);
+
+       ck_assert(asn1_unwrap(&c1, &inner) == ASN1_SEQUENCE);
+
+       ck_assert(chunk_equals(inner, inner_ref));
+
+       ck_assert(asn1_unwrap(&c2, &inner) == ASN1_INVALID);
+
+       ck_assert(asn1_unwrap(&c3, &inner) == ASN1_INVALID);
+
+       ck_assert(asn1_unwrap(&c4, &inner) == ASN1_SEQUENCE);
+
+       ck_assert(chunk_equals(inner, inner_ref));
+
+       ck_assert(asn1_unwrap(&c5, &inner) == ASN1_INVALID);
+}
+END_TEST
+
+/*******************************************************************************
+ * is_asn1
+ */
+
+START_TEST(test_is_asn1)
+{
+       typedef struct {
+               bool asn1;
+               chunk_t chunk;
+       } testdata_t;
+
+       u_char buf[8];
+       chunk_t chunk_zero = { buf, 0 };
+       chunk_t chunk_mean = {   0, 1 };
+
+       testdata_t test[] = {
+               { FALSE, chunk_zero },
+               { FALSE, chunk_empty },
+               { FALSE, chunk_mean },
+               { TRUE,  chunk_from_chars(0x30, 0x00) },
+               { TRUE,  chunk_from_chars(0x31, 0x00) },
+               { TRUE,  chunk_from_chars(0x04, 0x00) },
+               { FALSE, chunk_from_chars(0x02, 0x00) },
+               { FALSE, chunk_from_chars(0x30, 0x01) },
+               { FALSE, chunk_from_chars(0x30, 0x80) },
+               { TRUE,  chunk_from_chars(0x30, 0x01, 0xa1) },
+               { FALSE, chunk_from_chars(0x30, 0x01, 0xa1, 0xa2) },
+               { TRUE,  chunk_from_chars(0x30, 0x01, 0xa1, 0x0a) },
+               { FALSE, chunk_from_chars(0x30, 0x01, 0xa1, 0xa2, 0x0a) },
+       };
+
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               ck_assert(is_asn1(test[i].chunk) == test[i].asn1);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * is_printablestring
+ */
+
+START_TEST(test_asn1_is_printablestring)
+{
+       typedef struct {
+               bool printable;
+               char *string;
+       } testdata_t;
+
+
+       testdata_t test[] = {
+               { TRUE,  "" },
+               { TRUE,  "Z" },
+               { FALSE, "Z#" },
+               { FALSE, "&Z" },
+               { FALSE, "Z@z" },
+               { FALSE, "!" },  { FALSE, "*" },  { FALSE, "$" },  { FALSE, "%" },
+               { FALSE, "[" },  { FALSE, "]" },  { FALSE, "{" },  { FALSE, "}" },
+               { FALSE, "|" },  { FALSE, "~" },  { FALSE, "^" },  { FALSE, "_" },
+               { FALSE, "\"" }, { FALSE, "\\" }, { FALSE, "ä" },  { FALSE, "à" },
+               { TRUE,  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+                                "0123456789 '()+,-./:=?" },
+       };
+
+       chunk_t chunk;
+       int i;
+
+       ck_assert(asn1_is_printablestring(chunk_empty));
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk = chunk_from_str(test[i].string);
+               ck_assert(asn1_is_printablestring(chunk) == test[i].printable);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * to_time
+ */
+
+START_TEST(test_asn1_to_time)
+{
+       typedef struct {
+               time_t time;
+               u_int8_t type;
+               char *string;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {     352980, 0x18, "197001050203Z" },
+               {     352984, 0x18, "19700105020304Z" },
+               {     352980, 0x17, "7001050203Z" },
+               {     347580, 0x17, "7001050203+0130" },
+               {     358380, 0x17, "7001050203-0130" },
+               {     352984, 0x17, "700105020304Z" },
+               {     347584, 0x17, "700105020304+0130" },
+               {     358384, 0x17, "700105020304-0130" },
+               {          0, 0x17, "700105020304+01" },
+               {          0, 0x17, "700105020304-01" },
+               {          0, 0x17, "700105020304" },
+               {          0, 0x17, "70010502Z" },
+               {          0, 0x17, "7001050203xxZ" },
+               {          0, 0x17, "7000050203Z" },
+               {          0, 0x17, "7013050203Z" },
+               {    5097600, 0x17, "7003010000Z" },
+               {   68256000, 0x17, "7203010000Z" },
+               {  951868800, 0x17, "0003010000Z" },
+               { 4107542400, 0x18, "210003010000Z" }
+       };
+
+       int i;
+       chunk_t chunk;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               if (test[i].time > TIME_32_BIT_SIGNED_MAX && sizeof(time_t) == 4)
+               {
+                       continue;
+               }
+               chunk = chunk_from_str(test[i].string);
+               ck_assert(asn1_to_time(&chunk, test[i].type) == test[i].time);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * from_time
+ */
+
+START_TEST(test_asn1_from_time)
+{
+       typedef struct {
+               time_t time;
+               u_int8_t type;
+               chunk_t chunk;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {     352984, 0x18, chunk_from_chars(
+                                         0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
+                                         0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
+               {     352984, 0x17, chunk_from_chars(
+                                         0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
+                                         0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
+               { 1078099200, 0x17, chunk_from_chars(
+                                         0x17, 0x0d, 0x30, 0x34, 0x30, 0x33, 0x30, 0x31,
+                                         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) },
+        { 4107542400, 0x18, chunk_from_chars( 
+                                         0x18, 0x0f, 0x32, 0x31, 0x30, 0x30, 0x30, 0x33, 0x30, 0x31,
+                                         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) }
+       };
+
+       int i;
+       chunk_t chunk;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               if (test[i].time > TIME_32_BIT_SIGNED_MAX && sizeof(time_t) == 4)
+        {
+                       continue;
+        }
+               chunk = asn1_from_time(&test[i].time, test[i].type);
+               ck_assert(chunk_equals(chunk, test[i].chunk));
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * parse_time
+ */
+
+START_TEST(test_asn1_parse_time)
+{
+       typedef struct {
+               time_t time;
+               chunk_t chunk;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { 352984, chunk_from_chars(
+                                       0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
+                                       0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
+               { 352984, chunk_from_chars(
+                                       0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
+                                       0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
+               {      0, chunk_from_chars(0x05, 0x00) }
+       };
+
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               ck_assert(asn1_parse_time(test[i].chunk, 0) == test[i].time);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * build_object
+ */
+
+START_TEST(test_asn1_build_object)
+{
+       typedef struct {
+               size_t len;
+               size_t size;
+               u_char *b;
+       } testdata_t;
+
+       u_char b0[] = { 0x05, 0x00 };
+       u_char b1[] = { 0x04, 0x7f };
+       u_char b2[] = { 0x04, 0x81, 0x80 };
+       u_char b3[] = { 0x04, 0x81, 0xff };
+       u_char b4[] = { 0x04, 0x82, 0x01, 0x00 };
+       u_char b5[] = { 0x04, 0x82, 0xff, 0xff };
+       u_char b6[] = { 0x04, 0x83, 0x01, 0x00, 0x00 };
+
+       testdata_t test[] = {
+               {     0, sizeof(b0), b0 },
+               {   127, sizeof(b1), b1 },
+               {   128, sizeof(b2), b2 },
+               {   255, sizeof(b3), b3 },
+               {   256, sizeof(b4), b4 },
+               { 65535, sizeof(b5), b5 },
+               { 65536, sizeof(b6), b6 }
+       };
+
+       chunk_t a = chunk_empty;
+       u_char *pos;
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               pos = asn1_build_object(&a, test[i].b[0], test[i].len);
+               ck_assert(pos == (a.ptr + test[i].size));
+               ck_assert(a.len == test[i].size + test[i].len);
+               ck_assert(memeq(a.ptr, test[i].b, test[i].size)); 
+               chunk_free(&a);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * simple_object
+ */
+
+START_TEST(test_asn1_simple_object)
+{
+       chunk_t a = chunk_empty;
+       chunk_t b = chunk_from_chars(0x04, 0x05, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5);
+       chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4, 0xa5);
+
+       a = asn1_simple_object(0x04, c);
+       ck_assert(chunk_equals(a, b));
+       chunk_free(&a);
+}
+END_TEST
+
+/*******************************************************************************
+ * parse_simple_object
+ */
+
+START_TEST(test_asn1_parse_simple_object)
+{
+       typedef struct {
+               bool res;
+               int type;
+               chunk_t chunk;
+       } testdata_t;
+
+       testdata_t test[] = {
+               { FALSE, 0x04, chunk_from_chars(0x04) },
+               { FALSE, 0x04, chunk_from_chars(0x02, 0x01, 0x55) },
+               { FALSE, 0x04, chunk_from_chars(0x04, 0x01) },
+               { TRUE,  0x04, chunk_from_chars(0x04, 0x01, 0x55) },
+               { TRUE,  0x06, chunk_from_chars(0x06, 0x02, 0x55, 0x03) },
+               { TRUE,  0x06, chunk_from_chars(0x06, 0x00) },
+               { TRUE,  0x13, chunk_from_chars(0x13, 0x01, 0x55), }
+       };
+
+       int i;
+       bool res;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               res = asn1_parse_simple_object(&test[i].chunk, test[i].type, 0, "test");
+               ck_assert(res == test[i].res);
+               if (res && test[i].chunk.len)
+               {
+                       ck_assert(*test[i].chunk.ptr == 0x55);
+               }
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * bitstring
+ */
+
+START_TEST(test_asn1_bitstring)
+{
+       chunk_t a = chunk_empty;
+       chunk_t b = chunk_from_chars(0x03, 0x05, 0x00, 0xa1, 0xa2, 0xa3, 0xa4);
+       chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4);
+       chunk_t d = chunk_clone(c);
+
+       a = asn1_bitstring("c", c);
+       ck_assert(chunk_equals(a, b));
+       chunk_free(&a);
+
+       a = asn1_bitstring("m", d);
+       ck_assert(chunk_equals(a, b));
+       chunk_free(&a);
+}
+END_TEST
+
+/*******************************************************************************
+ * integer
+ */
+
+START_TEST(test_asn1_integer)
+{
+       typedef struct {
+               chunk_t b;
+               chunk_t c;
+       } testdata_t;
+
+       chunk_t b0 = chunk_from_chars(0x02, 0x01, 0x00);
+       chunk_t b1 = chunk_from_chars(0x02, 0x01, 0x7f);
+       chunk_t b2 = chunk_from_chars(0x02, 0x02, 0x00, 0x80);
+
+       chunk_t c0 = chunk_empty;
+       chunk_t c1 = chunk_from_chars(0x7f);
+       chunk_t c2 = chunk_from_chars(0x80);
+       chunk_t c3 = chunk_from_chars(0x00, 0x80);
+
+       testdata_t test[] = {
+               { b0, c0 },
+               { b1, c1 },
+               { b2, c2 },
+               { b2, c3 }
+       };
+
+       chunk_t a = chunk_empty;
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               a = asn1_integer("c", test[i].c);
+               ck_assert(chunk_equals(a, test[i].b));
+               chunk_free(&a);
+
+               a = asn1_integer("m", chunk_clone(test[i].c));
+               ck_assert(chunk_equals(a, test[i].b));
+               chunk_free(&a);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * parse_integer_uint64
+ */
+
+START_TEST(test_asn1_parse_integer_uint64)
+{
+       typedef struct {
+               u_int64_t n;
+               chunk_t chunk;
+       } testdata_t;
+
+
+       testdata_t test[] = {
+               {             67305985ULL, chunk_from_chars(
+                                               0x04, 0x03, 0x02, 0x01) },
+               {   578437695752307201ULL, chunk_from_chars(
+                                               0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01) },
+               { 18446744073709551615ULL, chunk_from_chars(
+                                               0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff) }
+       };
+
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               ck_assert(asn1_parse_integer_uint64(test[i].chunk) == test[i].n);
+       }
+}
+END_TEST
+
+Suite *asn1_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("asn1");
+
+       tc = tcase_create("algorithmIdentifier");
+       tcase_add_test(tc, test_asn1_algorithmIdentifier);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("parse_algorithmIdentifier");
+       tcase_add_test(tc, test_asn1_parse_algorithmIdentifier);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("known_oid");
+       tcase_add_test(tc, test_asn1_known_oid);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("build_known_oid");
+       tcase_add_test(tc, test_asn1_build_known_oid);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("oid_from_string");
+       tcase_add_test(tc, test_asn1_oid_from_string);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("oid_to_string");
+       tcase_add_test(tc, test_asn1_oid_to_string);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("length");
+       tcase_add_test(tc, test_asn1_length);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("unwrap");
+       tcase_add_test(tc, test_asn1_unwrap);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("is_asn1");
+       tcase_add_test(tc, test_is_asn1);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("is_printablestring");
+       tcase_add_test(tc, test_asn1_is_printablestring);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("to_time");
+       tcase_add_test(tc, test_asn1_to_time);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("from_time");
+       tcase_add_test(tc, test_asn1_from_time);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("parse_time");
+       tcase_add_test(tc, test_asn1_parse_time);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("build_object");
+       tcase_add_test(tc, test_asn1_build_object);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("simple_object");
+       tcase_add_test(tc, test_asn1_simple_object);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("parse_simple_object");
+       tcase_add_test(tc, test_asn1_parse_simple_object);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("bitstring");
+       tcase_add_test(tc, test_asn1_bitstring);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("integer");
+       tcase_add_test(tc, test_asn1_integer);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("parse_integer_uint64");
+       tcase_add_test(tc, test_asn1_parse_integer_uint64);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_bio_reader.c b/src/libstrongswan/tests/suites/test_bio_reader.c
new file mode 100644 (file)
index 0000000..6a9743d
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <bio/bio_reader.h>
+
+/*******************************************************************************
+ * different integer reads
+ */
+
+#define assert_integer_read(data, bits, val) ({ \
+       bio_reader_t *reader = bio_reader_create(data); \
+       typeof(val) i; \
+       for (i = 0; reader->remaining(reader) >= (bits / 8); i++) \
+       { \
+               ck_assert(reader->read_uint##bits(reader, &val)); \
+               ck_assert_int_eq(i, val); \
+       } \
+       ck_assert_int_eq(i, data.len / (bits / 8)); \
+       ck_assert_int_eq(reader->remaining(reader), data.len % (bits / 8)); \
+       ck_assert(!reader->read_uint##bits(reader, &val)); \
+       reader->destroy(reader); \
+})
+
+#define assert_integer_read_uneven(data, bits, val) ({ \
+       int i; \
+       for (i = 0; i <= bits / 8; i++, data.len++) \
+       { \
+               assert_integer_read(data, bits, val); \
+       } \
+})
+
+#define assert_basic_read(bits, val) ({ \
+       chunk_t data; \
+       data = chunk_empty; \
+       assert_integer_read(data, bits, val); \
+       data = chunk_alloca(bits / 8); \
+       memset(data.ptr, 0, data.len); \
+       data.len = 0; \
+       assert_integer_read_uneven(data, bits, val); \
+})
+
+#define assert_extended_read(data, bits, val) ({ \
+       chunk_t extended = chunk_alloca(data.len + bits / 8); \
+       memset(extended.ptr, 0, extended.len); \
+       extended.ptr[extended.len - 1] = data.len / (bits / 8); \
+       memcpy(extended.ptr, data.ptr, data.len); \
+       extended.len = data.len; \
+       assert_integer_read_uneven(extended, bits, val); \
+})
+
+START_TEST(test_read_uint8)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07);
+       u_int8_t val;
+
+       assert_integer_read(data, 8, val);
+       assert_basic_read(8, val);
+       assert_extended_read(data, 8, val);
+}
+END_TEST
+
+START_TEST(test_read_uint16)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03);
+       u_int16_t val;
+
+       assert_integer_read(data, 16, val);
+       assert_basic_read(16, val);
+       assert_extended_read(data, 16, val);
+}
+END_TEST
+
+START_TEST(test_read_uint24)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03);
+       u_int32_t val;
+
+       assert_integer_read(data, 24, val);
+       assert_basic_read(24, val);
+       assert_extended_read(data, 24, val);
+}
+END_TEST
+
+START_TEST(test_read_uint32)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                                                                       0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03);
+       u_int32_t val;
+
+       assert_integer_read(data, 32, val);
+       assert_basic_read(32, val);
+       assert_extended_read(data, 32, val);
+}
+END_TEST
+
+START_TEST(test_read_uint64)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03);
+       u_int64_t val;
+
+       assert_integer_read(data, 64, val);
+       assert_basic_read(64, val);
+       assert_extended_read(data, 64, val);
+}
+END_TEST
+
+/*******************************************************************************
+ * different integer reads from the end of a buffer
+ */
+
+#define assert_integer_read_end(data, bits, val) ({ \
+       bio_reader_t *reader = bio_reader_create(data); \
+       typeof(val) i; \
+       for (i = 0; reader->remaining(reader) >= (bits / 8); i++) \
+       { \
+               ck_assert(reader->read_uint##bits##_end(reader, &val)); \
+               ck_assert_int_eq(i, val); \
+       } \
+       ck_assert_int_eq(i, data.len / (bits / 8)); \
+       ck_assert_int_eq(reader->remaining(reader), data.len % (bits / 8)); \
+       ck_assert(!reader->read_uint##bits##_end(reader, &val)); \
+       reader->destroy(reader); \
+})
+
+#define assert_integer_read_end_uneven(data, bits, val) ({ \
+       int i; \
+       data.ptr += bits / 8; \
+       for (i = 0; i <= bits / 8; i++, data.ptr--, data.len++) \
+       { \
+               assert_integer_read_end(data, bits, val); \
+       } \
+})
+
+#define assert_basic_read_end(bits, val) ({ \
+       chunk_t data; \
+       data = chunk_empty; \
+       assert_integer_read_end(data, bits, val); \
+       data = chunk_alloca(bits / 8); \
+       memset(data.ptr, 0, data.len); \
+       data.len = 0; \
+       assert_integer_read_end_uneven(data, bits, val); \
+})
+
+#define assert_extended_read_end(data, bits, val) ({ \
+       chunk_t extended = chunk_alloca(data.len + bits / 8); \
+       memset(extended.ptr, 0, extended.len); \
+       extended.ptr[bits / 8 - 1] = data.len / (bits / 8); \
+       memcpy(extended.ptr + bits / 8, data.ptr, data.len); \
+       extended.len = data.len; \
+       assert_integer_read_end_uneven(extended, bits, val); \
+})
+
+START_TEST(test_read_uint8_end)
+{
+       chunk_t data = chunk_from_chars(0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00);
+       u_int8_t val;
+
+       assert_integer_read_end(data, 8, val);
+       assert_basic_read_end(8, val);
+       assert_extended_read_end(data, 8, val);
+}
+END_TEST
+
+START_TEST(test_read_uint16_end)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00);
+       u_int16_t val;
+
+       assert_integer_read_end(data, 16, val);
+       assert_basic_read_end(16, val);
+       assert_extended_read_end(data, 16, val);
+}
+END_TEST
+
+START_TEST(test_read_uint24_end)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00);
+       u_int32_t val;
+
+       assert_integer_read_end(data, 24, val);
+       assert_basic_read_end(24, val);
+       assert_extended_read_end(data, 24, val);
+}
+END_TEST
+
+START_TEST(test_read_uint32_end)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02,
+                                                                       0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00);
+       u_int32_t val;
+
+       assert_integer_read_end(data, 32, val);
+       assert_basic_read_end(32, val);
+       assert_extended_read_end(data, 32, val);
+}
+END_TEST
+
+START_TEST(test_read_uint64_end)
+{
+       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+       u_int64_t val;
+
+       assert_integer_read_end(data, 64, val);
+       assert_basic_read_end(64, val);
+       assert_extended_read_end(data, 64, val);
+}
+END_TEST
+
+/*******************************************************************************
+ * read data
+ */
+
+static inline void assert_reader_after_read(bio_reader_t *reader, chunk_t data)
+{
+       chunk_t peek;
+
+       ck_assert_int_eq(reader->remaining(reader), data.len);
+       peek = reader->peek(reader);
+       ck_assert_int_eq(reader->remaining(reader), data.len);
+       ck_assert(peek.ptr == data.ptr);
+       data.ptr != NULL ? ck_assert(chunk_equals(peek, data))
+                                        : ck_assert(peek.ptr == NULL);
+}
+
+START_TEST(test_read_data)
+{
+       chunk_t read, data = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
+       bio_reader_t *reader;
+
+       reader = bio_reader_create(chunk_empty);
+       ck_assert_int_eq(reader->remaining(reader), 0);
+       ck_assert(reader->read_data(reader, 0, &read));
+       ck_assert(!reader->read_data(reader, 1, &read));
+       reader->destroy(reader);
+
+       reader = bio_reader_create(data);
+       ck_assert(reader->read_data(reader, 0, &read));
+       ck_assert_int_eq(read.len, 0);
+       ck_assert(read.ptr == data.ptr);
+       assert_reader_after_read(reader, data);
+
+       ck_assert(reader->read_data(reader, 1, &read));
+       ck_assert_int_eq(read.len, 1);
+       ck_assert(read.ptr == data.ptr);
+       assert_reader_after_read(reader, chunk_skip(data, 1));
+
+       ck_assert(reader->read_data(reader, 2, &read));
+       ck_assert_int_eq(read.len, 2);
+       ck_assert(read.ptr == data.ptr + 1);
+       assert_reader_after_read(reader, chunk_skip(data, 3));
+
+       ck_assert(!reader->read_data(reader, 2, &read));
+       ck_assert(reader->read_data(reader, 1, &read));
+       ck_assert_int_eq(read.len, 1);
+       ck_assert(read.ptr == data.ptr + 3);
+       assert_reader_after_read(reader, chunk_skip(data, 4));
+
+       ck_assert_int_eq(reader->remaining(reader), 0);
+       ck_assert(reader->read_data(reader, 0, &read));
+       ck_assert(!reader->read_data(reader, 1, &read));
+       reader->destroy(reader);
+}
+END_TEST
+
+START_TEST(test_read_data_end)
+{
+       chunk_t read, data = chunk_from_chars(0x00, 0x00, 0x00, 0x00);
+       bio_reader_t *reader;
+
+       reader = bio_reader_create(chunk_empty);
+       ck_assert_int_eq(reader->remaining(reader), 0);
+       ck_assert(reader->read_data_end(reader, 0, &read));
+       ck_assert(!reader->read_data_end(reader, 1, &read));
+       reader->destroy(reader);
+
+       reader = bio_reader_create(data);
+       ck_assert(reader->read_data_end(reader, 0, &read));
+       ck_assert_int_eq(read.len, 0);
+       ck_assert(read.ptr == data.ptr + data.len);
+       assert_reader_after_read(reader, data);
+
+       ck_assert(reader->read_data_end(reader, 1, &read));
+       ck_assert_int_eq(read.len, 1);
+       data.len--;
+       ck_assert(read.ptr == data.ptr + data.len);
+       assert_reader_after_read(reader, data);
+
+       ck_assert(reader->read_data_end(reader, 2, &read));
+       ck_assert_int_eq(read.len, 2);
+       data.len -= 2;
+       ck_assert(read.ptr == data.ptr + data.len);
+       assert_reader_after_read(reader, data);
+
+       ck_assert(!reader->read_data(reader, 2, &read));
+       ck_assert(reader->read_data(reader, 1, &read));
+       ck_assert_int_eq(read.len, 1);
+       ck_assert(read.ptr == data.ptr);
+       assert_reader_after_read(reader, chunk_empty);
+
+       ck_assert_int_eq(reader->remaining(reader), 0);
+       ck_assert(reader->read_data(reader, 0, &read));
+       ck_assert(!reader->read_data(reader, 1, &read));
+       reader->destroy(reader);
+}
+END_TEST
+
+/*******************************************************************************
+ * read length followed by data
+ */
+
+#define assert_read_data_len(bits) ({ \
+       bio_reader_t *reader; \
+       chunk_t read, data; \
+       int i, len = bits / 8; \
+       data = chunk_empty; \
+       reader = bio_reader_create(data); \
+       ck_assert(!reader->read_data##bits(reader, &read)); \
+       reader->destroy(reader); \
+       data = chunk_alloca(len + 8); \
+       memset(data.ptr, 0, data.len); \
+       for (i = 0; i <= 8; i++) \
+       { \
+               data.ptr[len - 1] = i; \
+               data.len = len + i; \
+               reader = bio_reader_create(data); \
+               ck_assert(reader->read_data##bits(reader, &read)); \
+               ck_assert_int_eq(reader->remaining(reader), 0); \
+               ck_assert_int_eq(read.len, i); \
+               ck_assert((!read.ptr && !read.len) || (read.ptr == data.ptr + len)); \
+               reader->destroy(reader); \
+       } \
+       data.ptr[len - 1] = i; \
+       reader = bio_reader_create(data); \
+       ck_assert(!reader->read_data##bits(reader, &read)); \
+       reader->destroy(reader); \
+})
+
+START_TEST(test_read_data8)
+{
+       assert_read_data_len(8);
+}
+END_TEST
+
+START_TEST(test_read_data16)
+{
+       assert_read_data_len(16);
+}
+END_TEST
+
+START_TEST(test_read_data24)
+{
+       assert_read_data_len(24);
+}
+END_TEST
+
+START_TEST(test_read_data32)
+{
+       assert_read_data_len(32);
+}
+END_TEST
+
+/*******************************************************************************
+ * test constructors
+ */
+
+START_TEST(test_create)
+{
+       chunk_t data = chunk_from_str("foobar");
+       bio_reader_t *reader;
+
+       data = chunk_clone(data);
+       reader = bio_reader_create(data);
+       reader->destroy(reader);
+       chunk_free(&data);
+}
+END_TEST
+
+START_TEST(test_create_own)
+{
+       chunk_t data = chunk_from_str("foobar");
+       bio_reader_t *reader;
+
+       data = chunk_clone(data);
+       reader = bio_reader_create_own(data);
+       reader->destroy(reader);
+}
+END_TEST
+
+Suite *bio_reader_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("bio_reader");
+
+       tc = tcase_create("integer reads");
+       tcase_add_test(tc, test_read_uint8);
+       tcase_add_test(tc, test_read_uint16);
+       tcase_add_test(tc, test_read_uint24);
+       tcase_add_test(tc, test_read_uint32);
+       tcase_add_test(tc, test_read_uint64);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("integer reads from end");
+       tcase_add_test(tc, test_read_uint8_end);
+       tcase_add_test(tc, test_read_uint16_end);
+       tcase_add_test(tc, test_read_uint24_end);
+       tcase_add_test(tc, test_read_uint32_end);
+       tcase_add_test(tc, test_read_uint64_end);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("data reads and peek");
+       tcase_add_test(tc, test_read_data);
+       tcase_add_test(tc, test_read_data_end);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("data length reads");
+       tcase_add_test(tc, test_read_data8);
+       tcase_add_test(tc, test_read_data16);
+       tcase_add_test(tc, test_read_data24);
+       tcase_add_test(tc, test_read_data32);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("constructors");
+       tcase_add_test(tc, test_create);
+       tcase_add_test(tc, test_create_own);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_bio_writer.c b/src/libstrongswan/tests/suites/test_bio_writer.c
new file mode 100644 (file)
index 0000000..e74288e
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <bio/bio_writer.h>
+
+/*******************************************************************************
+ * different integer writes
+ */
+
+static inline void verify_int_buffer(chunk_t data, int bits, int val)
+{
+       size_t i;
+       int len = bits / 8;
+
+       ck_assert_int_eq(data.len, (val + 1) * len);
+       for (i = 0; i < data.len; i++)
+       {
+               if ((i + 1) % len)
+               {
+                       ck_assert_int_eq(data.ptr[i], 0);
+               }
+               else
+               {
+                       ck_assert_int_eq(data.ptr[i], i / len);
+               }
+       }
+}
+
+#define assert_integer_write(init, bits) ({ \
+       int i; \
+       bio_writer_t *writer = bio_writer_create(init); \
+       for (i = 0; i < 16; i++) \
+       { \
+               writer->write_uint##bits(writer, i); \
+               verify_int_buffer(writer->get_buf(writer), bits, i); \
+       } \
+       writer->destroy(writer); \
+})
+
+START_TEST(test_write_uint8)
+{
+       /* use default buffer (and increase) size */
+       assert_integer_write(0, 8);
+       /* force a resize by the given size */
+       assert_integer_write(1, 8);
+}
+END_TEST
+
+START_TEST(test_write_uint16)
+{
+       assert_integer_write(0, 16);
+       assert_integer_write(1, 16);
+}
+END_TEST
+
+START_TEST(test_write_uint24)
+{
+       assert_integer_write(0, 24);
+       assert_integer_write(1, 24);
+}
+END_TEST
+
+START_TEST(test_write_uint32)
+{
+       assert_integer_write(0, 32);
+       assert_integer_write(1, 32);
+}
+END_TEST
+
+START_TEST(test_write_uint64)
+{
+       assert_integer_write(0, 64);
+       assert_integer_write(1, 64);
+}
+END_TEST
+
+/*******************************************************************************
+ * write data / skip
+ */
+
+static inline void assert_writer_after_write(bio_writer_t *writer, int count)
+{
+       chunk_t buf;
+       size_t i;
+
+       buf = writer->get_buf(writer);
+       ck_assert_int_eq(buf.len, count * 3);
+       for (i = 0; i < buf.len; i++)
+       {
+               ck_assert(buf.ptr[i] == i % 3);
+       }
+}
+
+START_TEST(test_write_data)
+{
+       chunk_t buf, data = chunk_from_chars(0x00, 0x01, 0x02);
+       bio_writer_t *writer;
+
+       /* no allocation, but default buffer size */
+       writer = bio_writer_create(0);
+       buf = writer->get_buf(writer);
+       ck_assert_int_eq(buf.len, 0);
+       ck_assert(buf.ptr == NULL);
+
+       writer->write_data(writer, chunk_empty);
+       buf = writer->get_buf(writer);
+       ck_assert_int_eq(buf.len, 0);
+       ck_assert(buf.ptr == NULL);
+       writer->destroy(writer);
+
+       /* custom buffer size, initial buffer allocated */
+       writer = bio_writer_create(1);
+       buf = writer->get_buf(writer);
+       ck_assert_int_eq(buf.len, 0);
+       ck_assert(buf.ptr != NULL);
+
+       writer->write_data(writer, chunk_empty);
+       buf = writer->get_buf(writer);
+       ck_assert_int_eq(buf.len, 0);
+       ck_assert(buf.ptr != NULL);
+       writer->destroy(writer);
+
+       writer = bio_writer_create(0);
+
+       writer->write_data(writer, data);
+       assert_writer_after_write(writer, 1);
+
+       writer->write_data(writer, data);
+       assert_writer_after_write(writer, 2);
+
+       writer->write_data(writer, data);
+       assert_writer_after_write(writer, 3);
+
+       writer->destroy(writer);
+}
+END_TEST
+
+START_TEST(test_skip)
+{
+       chunk_t skipped, buf, data = chunk_from_chars(0x00, 0x01, 0x02);
+       bio_writer_t *writer;
+
+       writer = bio_writer_create(4);
+       skipped = writer->skip(writer, 3);
+       ck_assert_int_eq(skipped.len, 3);
+       buf = writer->get_buf(writer);
+       ck_assert(skipped.ptr == buf.ptr);
+       memset(skipped.ptr, 0, skipped.len);
+
+       writer->write_data(writer, data);
+       buf = writer->get_buf(writer);
+       ck_assert(chunk_equals(buf, chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x01, 0x02)));
+       writer->destroy(writer);
+
+       writer = bio_writer_create(1);
+       skipped = writer->skip(writer, 3);
+       memcpy(skipped.ptr, data.ptr, data.len);
+
+       writer->write_data(writer, data);
+       assert_writer_after_write(writer, 2);
+       writer->destroy(writer);
+}
+END_TEST
+
+/*******************************************************************************
+ * write length followed by data
+ */
+
+#define assert_write_data_len(init, bits) ({ \
+       bio_writer_t *writer; \
+       chunk_t buf, data; \
+       int i, len = bits / 8; \
+       writer = bio_writer_create(init); \
+       writer->write_data##bits(writer, chunk_empty); \
+       buf = writer->get_buf(writer); \
+       ck_assert_int_eq(buf.len, len); \
+       ck_assert_int_eq(buf.ptr[len - 1], 0); \
+       writer->destroy(writer); \
+       data = chunk_alloca(32); \
+       memset(data.ptr, 0, data.len); \
+       for (i = 0; i < 32; i++) \
+       { \
+               data.ptr[i] = i; \
+               data.len = i; \
+               writer = bio_writer_create(init); \
+               writer->write_data##bits(writer, data); \
+               buf = writer->get_buf(writer); \
+               ck_assert_int_eq(buf.len, len + i); \
+               ck_assert_int_eq(buf.ptr[len - 1], i); \
+               ck_assert(chunk_equals(chunk_create(buf.ptr + len, buf.len - len), data)); \
+               writer->destroy(writer); \
+       } \
+})
+
+START_TEST(test_write_data8)
+{
+       assert_write_data_len(0, 8);
+       assert_write_data_len(1, 8);
+}
+END_TEST
+
+START_TEST(test_write_data16)
+{
+       assert_write_data_len(0, 16);
+       assert_write_data_len(1, 16);
+}
+END_TEST
+
+START_TEST(test_write_data24)
+{
+       assert_write_data_len(0, 24);
+       assert_write_data_len(1, 24);
+}
+END_TEST
+
+START_TEST(test_write_data32)
+{
+       assert_write_data_len(0, 32);
+       assert_write_data_len(1, 32);
+}
+END_TEST
+
+
+/*******************************************************************************
+ * add length header before current data
+ */
+
+#define assert_wrap_data(init, bits) ({ \
+       bio_writer_t *writer; \
+       chunk_t buf, data; \
+       int i, len = bits / 8; \
+       writer = bio_writer_create(init); \
+       writer->wrap##bits(writer); \
+       buf = writer->get_buf(writer); \
+       ck_assert_int_eq(buf.len, len); \
+       ck_assert_int_eq(buf.ptr[len - 1], 0); \
+       writer->destroy(writer); \
+       data = chunk_alloca(32); \
+       memset(data.ptr, 0, data.len); \
+       for (i = 0; i < 32; i++) \
+       { \
+               data.ptr[i] = i; \
+               data.len = i; \
+               writer = bio_writer_create(init); \
+               writer->write_data(writer, data); \
+               writer->wrap##bits(writer); \
+               buf = writer->get_buf(writer); \
+               ck_assert_int_eq(buf.len, len + i); \
+               ck_assert_int_eq(buf.ptr[len - 1], i); \
+               ck_assert(chunk_equals(chunk_create(buf.ptr + len, buf.len - len), data)); \
+               writer->wrap##bits(writer); \
+               buf = writer->get_buf(writer); \
+               ck_assert_int_eq(buf.len, 2 * len + i); \
+               ck_assert_int_eq(buf.ptr[len - 1], len + i); \
+               ck_assert(chunk_equals(chunk_create(buf.ptr + 2 * len, buf.len - 2 * len), data)); \
+               writer->destroy(writer); \
+       } \
+})
+
+START_TEST(test_wrap8)
+{
+       assert_wrap_data(0, 8);
+       assert_wrap_data(1, 8);
+}
+END_TEST
+
+START_TEST(test_wrap16)
+{
+       assert_wrap_data(0, 16);
+       assert_wrap_data(1, 16);
+}
+END_TEST
+
+START_TEST(test_wrap24)
+{
+       assert_wrap_data(0, 24);
+       assert_wrap_data(1, 24);
+}
+END_TEST
+
+START_TEST(test_wrap32)
+{
+       assert_wrap_data(0, 32);
+       assert_wrap_data(1, 32);
+}
+END_TEST
+
+/*******************************************************************************
+ * test data extraction
+ */
+
+START_TEST(test_get_buf)
+{
+       bio_writer_t *writer;
+       chunk_t data1, data2;
+
+       writer = bio_writer_create(0);
+       writer->write_uint8(writer, 1);
+       data1 = writer->get_buf(writer);
+       ck_assert_int_eq(data1.len, 1);
+       ck_assert(data1.ptr[0] == 1);
+
+       data2 = writer->get_buf(writer);
+       ck_assert(chunk_equals(data1, data2));
+       ck_assert(data1.ptr == data2.ptr);
+       writer->destroy(writer);
+}
+END_TEST
+
+START_TEST(test_extract_buf)
+{
+       bio_writer_t *writer;
+       chunk_t data1, data2;
+
+       writer = bio_writer_create(0);
+       writer->write_uint8(writer, 1);
+       data1 = writer->extract_buf(writer);
+       ck_assert_int_eq(data1.len, 1);
+       ck_assert(data1.ptr[0] == 1);
+
+       data2 = writer->get_buf(writer);
+       ck_assert_int_eq(data2.len, 0);
+       ck_assert(data2.ptr == NULL);
+       data2 = writer->extract_buf(writer);
+       ck_assert_int_eq(data2.len, 0);
+       ck_assert(data2.ptr == NULL);
+
+       writer->write_uint8(writer, 1);
+       data2 = writer->get_buf(writer);
+       ck_assert(chunk_equals(data1, data2));
+       ck_assert(data1.ptr != data2.ptr);
+
+       writer->destroy(writer);
+       chunk_free(&data1);
+}
+END_TEST
+
+Suite *bio_writer_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("bio_writer");
+
+       tc = tcase_create("integer writes");
+       tcase_add_test(tc, test_write_uint8);
+       tcase_add_test(tc, test_write_uint16);
+       tcase_add_test(tc, test_write_uint24);
+       tcase_add_test(tc, test_write_uint32);
+       tcase_add_test(tc, test_write_uint64);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("data writes/skip");
+       tcase_add_test(tc, test_write_data);
+       tcase_add_test(tc, test_skip);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("data length writes");
+       tcase_add_test(tc, test_write_data8);
+       tcase_add_test(tc, test_write_data16);
+       tcase_add_test(tc, test_write_data24);
+       tcase_add_test(tc, test_write_data32);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("wrap writes");
+       tcase_add_test(tc, test_wrap8);
+       tcase_add_test(tc, test_wrap16);
+       tcase_add_test(tc, test_wrap24);
+       tcase_add_test(tc, test_wrap32);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("get/extract");
+       tcase_add_test(tc, test_get_buf);
+       tcase_add_test(tc, test_extract_buf);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c
new file mode 100644 (file)
index 0000000..8e29971
--- /dev/null
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "test_suite.h"
+
+#include <utils/chunk.h>
+
+/*******************************************************************************
+ * utilities
+ */
+
+static void assert_chunk_empty(chunk_t chunk)
+{
+       ck_assert(chunk.len == 0 && chunk.ptr == NULL);
+}
+
+/*******************************************************************************
+ * equals
+ */
+
+START_TEST(test_chunk_equals)
+{
+       chunk_t chunk = chunk_from_str("chunk");
+       chunk_t chunk_a, chunk_b;
+
+       chunk_a = chunk_empty;
+       chunk_b = chunk_empty;
+       ck_assert(!chunk_equals(chunk_a, chunk_b));
+
+       chunk_a = chunk;
+       ck_assert(!chunk_equals(chunk_a, chunk_b));
+       chunk_b = chunk;
+       ck_assert(chunk_equals(chunk_a, chunk_b));
+
+       chunk_b = chunk_from_str("asdf");
+       ck_assert(!chunk_equals(chunk_a, chunk_b));
+
+       chunk_b = chunk_from_str("chunk");
+       ck_assert(chunk_equals(chunk_a, chunk_b));
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_compare test
+ */
+
+static struct {
+       int result;
+       chunk_t a;
+       chunk_t b;
+} compare_data[] = {
+       { 0, { NULL, 0 }, { NULL, 0 }},
+       { 0, chunk_from_chars(0x00), chunk_from_chars(0x00)},
+       {-1, chunk_from_chars(0x00), chunk_from_chars(0x01)},
+       { 1, chunk_from_chars(0x01), chunk_from_chars(0x00)},
+       { 0, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x00)},
+       {-1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x01)},
+       { 1, chunk_from_chars(0x00, 0x01), chunk_from_chars(0x00, 0x00)},
+       {-1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x01, 0x00)},
+       { 1, chunk_from_chars(0x01, 0x00), chunk_from_chars(0x00, 0x00)},
+       {-1, chunk_from_chars(0xff), chunk_from_chars(0x00, 0x00)},
+       { 1, chunk_from_chars(0x00, 0x00), chunk_from_chars(0xff)},
+};
+
+START_TEST(test_compare)
+{
+       int result, expected;
+
+       result = chunk_compare(compare_data[_i].a, compare_data[_i].b);
+       expected = compare_data[_i].result;
+       ck_assert((result == 0 && expected == 0) ||
+                         (result < 0 && expected < 0) ||
+                         (result > 0 && expected > 0));
+}
+END_TEST
+
+/*******************************************************************************
+ * clear
+ */
+
+START_TEST(test_chunk_clear)
+{
+       chunk_t chunk;
+       u_char *ptr;
+       int i;
+       bool cleared = TRUE;
+
+       chunk = chunk_empty;
+       chunk_clear(&chunk);
+       chunk_free(&chunk);
+
+       chunk = chunk_alloc(64);
+       ptr = chunk.ptr;
+       for (i = 0; i < 64; i++)
+       {
+               chunk.ptr[i] = i;
+       }
+       chunk_clear(&chunk);
+       /* check memory area of freed chunk. We can't use ck_assert() for this
+        * test directly, as it might allocate data at the freed area. */
+       for (i = 0; i < 64; i++)
+       {
+               if (ptr[i] != 0 && ptr[i] == i)
+               {
+                       cleared = FALSE;
+                       break;
+               }
+       }
+       assert_chunk_empty(chunk);
+       ck_assert(cleared);
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_length
+ */
+
+START_TEST(test_chunk_length)
+{
+       chunk_t a, b, c;
+       size_t len;
+
+       a = chunk_empty;
+       b = chunk_empty;
+       c = chunk_empty;
+       len = chunk_length("ccc", a, b, c);
+       ck_assert_int_eq(len, 0);
+
+       a = chunk_from_str("foo");
+       b = chunk_from_str("bar");
+       len = chunk_length("ccc", a, b, c);
+       ck_assert_int_eq(len, 6);
+
+       len = chunk_length("zcc", a, b, c);
+       ck_assert_int_eq(len, 0);
+
+       len = chunk_length("czc", a, b, c);
+       ck_assert_int_eq(len, 3);
+
+       a = chunk_from_str("foo");
+       b = chunk_from_str("bar");
+       c = chunk_from_str("baz");
+       len = chunk_length("ccc", a, b, c);
+       ck_assert_int_eq(len, 9);
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_create_cat
+ */
+
+START_TEST(test_chunk_create_cat)
+{
+       chunk_t foo, bar;
+       chunk_t a, b, c;
+       u_char *ptra, *ptrb;
+
+       foo = chunk_from_str("foo");
+       bar = chunk_from_str("bar");
+
+       /* to simplify things we use the chunk_cata macro */
+
+       a = chunk_empty;
+       b = chunk_empty;
+       c = chunk_cata("cc", a, b);
+       ck_assert_int_eq(c.len, 0);
+       ck_assert(c.ptr != NULL);
+
+       a = foo;
+       b = bar;
+       c = chunk_cata("cc", a, b);
+       ck_assert_int_eq(c.len, 6);
+       ck_assert(chunk_equals(c, chunk_from_str("foobar")));
+
+       a = chunk_clone(foo);
+       b = chunk_clone(bar);
+       c = chunk_cata("mm", a, b);
+       ck_assert_int_eq(c.len, 6);
+       ck_assert(chunk_equals(c, chunk_from_str("foobar")));
+
+       a = chunk_clone(foo);
+       b = chunk_clone(bar);
+       ptra = a.ptr;
+       ptrb = b.ptr;
+       c = chunk_cata("ss", a, b);
+       ck_assert_int_eq(c.len, 6);
+       ck_assert(chunk_equals(c, chunk_from_str("foobar")));
+       /* check memory area of cleared chunk */
+       ck_assert(!chunk_equals(foo, chunk_create(ptra, 3)));
+       ck_assert(!chunk_equals(bar, chunk_create(ptrb, 3)));
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_split
+ */
+
+static bool mem_in_chunk(u_char *ptr, chunk_t chunk)
+{
+       return ptr >= chunk.ptr && ptr < (chunk.ptr + chunk.len);
+}
+
+START_TEST(test_chunk_split)
+{
+       chunk_t foo, bar, foobar;
+       chunk_t a, b, c;
+       u_char *ptra, *ptrb;
+
+       foo = chunk_from_str("foo");
+       bar = chunk_from_str("bar");
+       foobar = chunk_from_str("foobar");
+
+       chunk_split(foobar, "aa", 3, &a, 3, &b);
+       ck_assert(chunk_equals(a, foo));
+       ck_assert(chunk_equals(b, bar));
+       ck_assert(!mem_in_chunk(a.ptr, foobar));
+       ck_assert(!mem_in_chunk(b.ptr, foobar));
+       chunk_free(&a);
+       chunk_free(&b);
+
+       chunk_split(foobar, "mm", 3, &a, 3, &b);
+       ck_assert(chunk_equals(a, foo));
+       ck_assert(chunk_equals(b, bar));
+       ck_assert(mem_in_chunk(a.ptr, foobar));
+       ck_assert(mem_in_chunk(b.ptr, foobar));
+
+       chunk_split(foobar, "am", 3, &a, 3, &b);
+       ck_assert(chunk_equals(a, foo));
+       ck_assert(chunk_equals(b, bar));
+       ck_assert(!mem_in_chunk(a.ptr, foobar));
+       ck_assert(mem_in_chunk(b.ptr, foobar));
+       chunk_free(&a);
+
+       a = chunk_alloca(3);
+       ptra = a.ptr;
+       b = chunk_alloca(3);
+       ptrb = b.ptr;
+       chunk_split(foobar, "cc", 3, &a, 3, &b);
+       ck_assert(chunk_equals(a, foo));
+       ck_assert(chunk_equals(b, bar));
+       ck_assert(a.ptr == ptra);
+       ck_assert(b.ptr == ptrb);
+
+       chunk_split(foobar, "mm", 1, NULL, 2, &a, 2, NULL, 1, &b);
+       ck_assert(chunk_equals(a, chunk_from_str("oo")));
+       ck_assert(chunk_equals(b, chunk_from_str("r")));
+
+       chunk_split(foobar, "mm", 6, &a, 6, &b);
+       ck_assert(chunk_equals(a, foobar));
+       assert_chunk_empty(b);
+
+       chunk_split(foobar, "mac", 12, &a, 12, &b, 12, &c);
+       ck_assert(chunk_equals(a, foobar));
+       assert_chunk_empty(b);
+       assert_chunk_empty(c);
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_skip[_zero]
+ */
+
+START_TEST(test_chunk_skip)
+{
+       chunk_t foobar, a;
+
+       foobar = chunk_from_str("foobar");
+       a = foobar;
+       a = chunk_skip(a, 0);
+       ck_assert(chunk_equals(a, foobar));
+       a = chunk_skip(a, 1);
+       ck_assert(chunk_equals(a, chunk_from_str("oobar")));
+       a = chunk_skip(a, 2);
+       ck_assert(chunk_equals(a, chunk_from_str("bar")));
+       a = chunk_skip(a, 3);
+       assert_chunk_empty(a);
+
+       a = foobar;
+       a = chunk_skip(a, 6);
+       assert_chunk_empty(a);
+
+       a = foobar;
+       a = chunk_skip(a, 10);
+       assert_chunk_empty(a);
+}
+END_TEST
+
+START_TEST(test_chunk_skip_zero)
+{
+       chunk_t foobar, a;
+
+       a = chunk_empty;
+       a = chunk_skip_zero(a);
+       assert_chunk_empty(a);
+
+       foobar = chunk_from_str("foobar");
+       a = foobar;
+       a = chunk_skip_zero(a);
+       ck_assert(chunk_equals(a, foobar));
+
+       a = chunk_from_chars(0x00, 0xaa, 0xbb, 0xcc);
+       a = chunk_skip_zero(a);
+       ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc)));
+       a = chunk_skip_zero(a);
+       ck_assert(chunk_equals(a, chunk_from_chars(0xaa, 0xbb, 0xcc)));
+}
+END_TEST
+
+/*******************************************************************************
+ * BASE16 encoding test
+ */
+
+START_TEST(test_base16)
+{
+       /* test vectors from RFC 4648:
+        *
+        * BASE16("") = ""
+        * BASE16("f") = "66"
+        * BASE16("fo") = "666F"
+        * BASE16("foo") = "666F6F"
+        * BASE16("foob") = "666F6F62"
+        * BASE16("fooba") = "666F6F6261"
+        * BASE16("foobar") = "666F6F626172"
+        */
+       typedef struct {
+               bool upper;
+               char *in;
+               char *out;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {TRUE,  "", ""},
+               {TRUE,  "f", "66"},
+               {TRUE,  "fo", "666F"},
+               {TRUE,  "foo", "666F6F"},
+               {TRUE,  "foob", "666F6F62"},
+               {TRUE,  "fooba", "666F6F6261"},
+               {TRUE,  "foobar", "666F6F626172"},
+               {FALSE, "", ""},
+               {FALSE, "f", "66"},
+               {FALSE, "fo", "666f"},
+               {FALSE, "foo", "666f6f"},
+               {FALSE, "foob", "666f6f62"},
+               {FALSE, "fooba", "666f6f6261"},
+               {FALSE, "foobar", "666f6f626172"},
+       };
+       testdata_t test_colon[] = {
+               {TRUE,  "", ""},
+               {TRUE,  "f", "66"},
+               {TRUE,  "fo", "66:6F"},
+               {TRUE,  "foo", "66:6F:6F"},
+               {FALSE, "foob", "66:6f:6f:62"},
+               {FALSE, "fooba", "66:6f:6f:62:61"},
+               {FALSE, "foobar", "66:6f:6f:62:61:72"},
+               {FALSE, "foobar", "66:6f6f:6261:72"},
+       };
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk_t out;
+
+               out = chunk_to_hex(chunk_create(test[i].in, strlen(test[i].in)), NULL,
+                                                  test[i].upper);
+               ck_assert_str_eq(out.ptr, test[i].out);
+               free(out.ptr);
+       }
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk_t out;
+
+               out = chunk_from_hex(chunk_create(test[i].out, strlen(test[i].out)), NULL);
+               fail_unless(strneq(out.ptr, test[i].in, out.len),
+                                       "base16 conversion error - should '%s', is %#B",
+                                       test[i].in, &out);
+               free(out.ptr);
+       }
+
+       for (i = 0; i < countof(test_colon); i++)
+       {
+               chunk_t out;
+
+               out = chunk_from_hex(chunk_create(test_colon[i].out, strlen(test_colon[i].out)), NULL);
+               fail_unless(strneq(out.ptr, test_colon[i].in, out.len),
+                                       "base16 conversion error - should '%s', is %#B",
+                                       test_colon[i].in, &out);
+               free(out.ptr);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * BASE64 encoding test
+ */
+
+START_TEST(test_base64)
+{
+       /* test vectors from RFC 4648:
+        *
+        * BASE64("") = ""
+        * BASE64("f") = "Zg=="
+        * BASE64("fo") = "Zm8="
+        * BASE64("foo") = "Zm9v"
+        * BASE64("foob") = "Zm9vYg=="
+        * BASE64("fooba") = "Zm9vYmE="
+        * BASE64("foobar") = "Zm9vYmFy"
+        */
+       typedef struct {
+               char *in;
+               char *out;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {"", ""},
+               {"f", "Zg=="},
+               {"fo", "Zm8="},
+               {"foo", "Zm9v"},
+               {"foob", "Zm9vYg=="},
+               {"fooba", "Zm9vYmE="},
+               {"foobar", "Zm9vYmFy"},
+       };
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk_t out;
+
+               out = chunk_to_base64(chunk_create(test[i].in, strlen(test[i].in)), NULL);
+               ck_assert_str_eq(out.ptr, test[i].out);
+               free(out.ptr);
+       }
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk_t out;
+
+               out = chunk_from_base64(chunk_create(test[i].out, strlen(test[i].out)), NULL);
+               fail_unless(strneq(out.ptr, test[i].in, out.len),
+                                       "base64 conversion error - should '%s', is %#B",
+                                       test[i].in, &out);
+               free(out.ptr);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * BASE32 encoding test
+ */
+
+START_TEST(test_base32)
+{
+       /* test vectors from RFC 4648:
+        *
+        * BASE32("") = ""
+        * BASE32("f") = "MY======"
+        * BASE32("fo") = "MZXQ===="
+        * BASE32("foo") = "MZXW6==="
+        * BASE32("foob") = "MZXW6YQ="
+        * BASE32("fooba") = "MZXW6YTB"
+        * BASE32("foobar") = "MZXW6YTBOI======"
+        */
+       typedef struct {
+               char *in;
+               char *out;
+       } testdata_t;
+
+       testdata_t test[] = {
+               {"", ""},
+               {"f", "MY======"},
+               {"fo", "MZXQ===="},
+               {"foo", "MZXW6==="},
+               {"foob", "MZXW6YQ="},
+               {"fooba", "MZXW6YTB"},
+               {"foobar", "MZXW6YTBOI======"},
+       };
+       int i;
+
+       for (i = 0; i < countof(test); i++)
+       {
+               chunk_t out;
+
+               out = chunk_to_base32(chunk_create(test[i].in, strlen(test[i].in)), NULL);
+               ck_assert_str_eq(out.ptr, test[i].out);
+               free(out.ptr);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_increment test
+ */
+
+static struct {
+       bool overflow;
+       chunk_t in;
+       chunk_t out;
+} increment_data[] = {
+       {TRUE,  { NULL, 0 }, { NULL, 0 }},
+       {FALSE, chunk_from_chars(0x00), chunk_from_chars(0x01)},
+       {FALSE, chunk_from_chars(0xfe), chunk_from_chars(0xff)},
+       {TRUE,  chunk_from_chars(0xff), chunk_from_chars(0x00)},
+       {FALSE, chunk_from_chars(0x00, 0x00), chunk_from_chars(0x00, 0x01)},
+       {FALSE, chunk_from_chars(0x00, 0xff), chunk_from_chars(0x01, 0x00)},
+       {FALSE, chunk_from_chars(0xfe, 0xff), chunk_from_chars(0xff, 0x00)},
+       {TRUE,  chunk_from_chars(0xff, 0xff), chunk_from_chars(0x00, 0x00)},
+};
+
+START_TEST(test_increment)
+{
+       chunk_t chunk;
+       bool overflow;
+
+       chunk = chunk_clonea(increment_data[_i].in);
+       overflow = chunk_increment(chunk);
+       ck_assert(overflow == increment_data[_i].overflow);
+       ck_assert(!increment_data[_i].out.ptr ||
+                         chunk_equals(chunk, increment_data[_i].out));
+}
+END_TEST
+
+/*******************************************************************************
+ * chunk_printable tests
+ */
+
+static struct {
+       bool printable;
+       chunk_t in;
+       char *out;
+} printable_data[] = {
+       {TRUE,  chunk_from_chars(0x31), "1"},
+       {FALSE, chunk_from_chars(0x00), "?"},
+       {FALSE, chunk_from_chars(0x31, 0x00), "1?"},
+       {FALSE, chunk_from_chars(0x00, 0x31), "?1"},
+       {TRUE,  chunk_from_chars(0x3f, 0x31), "?1"},
+       {FALSE, chunk_from_chars(0x00, 0x31, 0x00), "?1?"},
+       {FALSE, chunk_from_chars(0x00, 0x31, 0x00, 0x32), "?1?2"},
+};
+
+START_TEST(test_printable)
+{
+       bool printable;
+
+       printable = chunk_printable(printable_data[_i].in, NULL, ' ');
+       ck_assert(printable == printable_data[_i].printable);
+}
+END_TEST
+
+START_TEST(test_printable_sanitize)
+{
+       chunk_t sane, expected;
+       bool printable;
+
+       printable = chunk_printable(printable_data[_i].in, &sane, '?');
+       ck_assert(printable == printable_data[_i].printable);
+       expected = chunk_from_str(printable_data[_i].out);
+       ck_assert(chunk_equals(sane, expected));
+       chunk_free(&sane);
+}
+END_TEST
+
+START_TEST(test_printable_empty)
+{
+       chunk_t sane;
+       bool printable;
+
+       printable = chunk_printable(chunk_empty, NULL, ' ');
+       ck_assert(printable);
+
+       sane.ptr = (void*)1;
+       sane.len = 1;
+       printable = chunk_printable(chunk_empty, &sane, ' ');
+       ck_assert(printable);
+       assert_chunk_empty(sane);
+}
+END_TEST
+
+/*******************************************************************************
+ * test for chunk_mac(), i.e. SipHash-2-4
+ */
+
+/**
+ * SipHash-2-4 output with
+ * k = 00 01 02 ...
+ * and
+ * in = (empty string)
+ * in = 00 (1 byte)
+ * in = 00 01 (2 bytes)
+ * in = 00 01 02 (3 bytes)
+ * ...
+ * in = 00 01 02 ... 3e (63 bytes)
+ */
+static const u_char sip_vectors[64][8] =
+{
+       { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+       { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+       { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+       { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+       { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+       { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+       { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+       { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+       { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+       { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+       { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+       { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+       { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+       { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+       { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+       { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+       { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+       { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+       { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+       { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+       { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+       { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+       { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+       { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+       { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+       { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+       { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+       { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+       { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+       { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+       { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+       { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+       { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+       { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+       { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+       { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+       { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+       { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+       { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+       { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+       { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+       { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+       { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+       { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+       { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+       { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+       { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+       { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+       { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+       { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+       { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+       { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+       { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+       { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+       { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+       { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+       { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+       { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+       { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+       { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+       { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+       { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+       { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+       { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+};
+
+START_TEST(test_chunk_mac)
+{
+       chunk_t in;
+       u_char key[16];
+       u_int64_t out;
+       int i, count;
+
+       count = countof(sip_vectors);
+       in = chunk_alloca(count);
+
+       for (i = 0; i < 16; ++i)
+       {
+               key[i] = i;
+       }
+
+       for (i = 0; i < count; ++i)
+       {
+               in.ptr[i] = i;
+               in.len = i;
+               out = chunk_mac(in, key);
+               fail_unless(memeq(&out, sip_vectors[i], 8),
+                                       "test vector failed for %d bytes", i);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * test for chunk_hash[_inc]()
+ */
+
+START_TEST(test_chunk_hash)
+{
+       chunk_t chunk;
+       u_int32_t hash_a, hash_b, hash_c;
+
+       chunk = chunk_from_str("asdf");
+
+       /* output is randomized, so there are no test-vectors we could use */
+       hash_a = chunk_hash(chunk);
+       hash_b = chunk_hash(chunk);
+       ck_assert(hash_a == hash_b);
+       hash_b = chunk_hash_inc(chunk, hash_a);
+       ck_assert(hash_a != hash_b);
+       hash_c = chunk_hash_inc(chunk, hash_a);
+       ck_assert(hash_b == hash_c);
+}
+END_TEST
+
+/*******************************************************************************
+ * test for chunk_hash_static[_inc]()
+ */
+
+START_TEST(test_chunk_hash_static)
+{
+       chunk_t in;
+       u_int32_t out, hash_a, hash_b, hash_inc = 0x7b891a95;
+       int i, count;
+
+       count = countof(sip_vectors);
+       in = chunk_alloca(count);
+
+       for (i = 0; i < count; ++i)
+       {
+               in.ptr[i] = i;
+               in.len = i;
+               /* compared to chunk_mac() we only get half the value back */
+               out = chunk_hash_static(in);
+               fail_unless(memeq(&out, sip_vectors[i], 4),
+                                       "test vector failed for %d bytes", i);
+       }
+       hash_a = chunk_hash_static_inc(in, out);
+       ck_assert_int_eq(hash_a, hash_inc);
+       hash_b = chunk_hash_static_inc(in, out);
+       ck_assert_int_eq(hash_a, hash_b);
+}
+END_TEST
+
+/*******************************************************************************
+ * printf_hook tests
+ */
+
+static struct {
+       chunk_t in;
+       char *out;
+       char *out_plus;
+} printf_hook_data[] = {
+       {chunk_from_chars(), "", ""},
+       {chunk_from_chars(0x00), "00", "00"},
+       {chunk_from_chars(0x00, 0x01), "00:01", "0001"},
+       {chunk_from_chars(0x00, 0x01, 0x02), "00:01:02", "000102"},
+};
+
+START_TEST(test_printf_hook_hash)
+{
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%#B", &printf_hook_data[_i].in);
+       ck_assert(len >= 0 && len < sizeof(buf));
+       ck_assert_str_eq(buf, printf_hook_data[_i].out);
+}
+END_TEST
+
+START_TEST(test_printf_hook_plus)
+{
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%+B", &printf_hook_data[_i].in);
+       ck_assert(len >= 0 && len < sizeof(buf));
+       ck_assert_str_eq(buf, printf_hook_data[_i].out_plus);
+}
+END_TEST
+
+START_TEST(test_printf_hook)
+{
+       char buf[128], mem[128];
+       int len;
+
+       /* %B should be the same as %b, which is what we check, comparing the
+        * acutal result could be tricky as %b prints the chunk's memory address */
+       len = snprintf(buf, sizeof(buf), "%B", &printf_hook_data[_i].in);
+       ck_assert(len >= 0 && len < sizeof(buf));
+       len = snprintf(mem, sizeof(mem), "%b", printf_hook_data[_i].in.ptr,
+                                 (u_int)printf_hook_data[_i].in.len);
+       ck_assert(len >= 0 && len < sizeof(mem));
+       ck_assert_str_eq(buf, mem);
+}
+END_TEST
+
+Suite *chunk_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("chunk");
+
+       tc = tcase_create("equals");
+       tcase_add_test(tc, test_chunk_equals);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_compare");
+       tcase_add_loop_test(tc, test_compare, 0, countof(compare_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("clear");
+       tcase_add_test(tc, test_chunk_clear);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_length");
+       tcase_add_test(tc, test_chunk_length);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_create_cat");
+       tcase_add_test(tc, test_chunk_create_cat);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_split");
+       tcase_add_test(tc, test_chunk_split);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_skip");
+       tcase_add_test(tc, test_chunk_skip);
+       tcase_add_test(tc, test_chunk_skip_zero);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_increment");
+       tcase_add_loop_test(tc, test_increment, 0, countof(increment_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_printable");
+       tcase_add_loop_test(tc, test_printable, 0, countof(printable_data));
+       tcase_add_loop_test(tc, test_printable_sanitize, 0, countof(printable_data));
+       tcase_add_test(tc, test_printable_empty);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("baseXX");
+       tcase_add_test(tc, test_base64);
+       tcase_add_test(tc, test_base32);
+       tcase_add_test(tc, test_base16);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_mac");
+       tcase_add_test(tc, test_chunk_mac);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_hash");
+       tcase_add_test(tc, test_chunk_hash);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("chunk_hash_static");
+       tcase_add_test(tc, test_chunk_hash_static);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("printf_hook");
+       tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data));
+       tcase_add_loop_test(tc, test_printf_hook_plus, 0, countof(printf_hook_data));
+       tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_hook_data));
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_ecdsa.c b/src/libstrongswan/tests/suites/test_ecdsa.c
new file mode 100644 (file)
index 0000000..2955bae
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <plugins/plugin_feature.h>
+
+/**
+ * Signature schemes to test
+ */
+static struct {
+       /* key size for scheme, 0 for any */
+       int key_size;
+       signature_scheme_t scheme;
+} schemes[] = {
+       { 0, SIGN_ECDSA_WITH_SHA1_DER },
+       { 0, SIGN_ECDSA_WITH_SHA256_DER },
+       { 0, SIGN_ECDSA_WITH_SHA384_DER },
+       { 0, SIGN_ECDSA_WITH_SHA512_DER },
+       { 0, SIGN_ECDSA_WITH_NULL },
+       { 256, SIGN_ECDSA_256 },
+       { 384, SIGN_ECDSA_384 },
+       { 521, SIGN_ECDSA_521 },
+};
+
+/**
+ * Perform a signature verification "good" test having a keypair
+ */
+static void test_good_sig(private_key_t *privkey, public_key_t *pubkey)
+{
+       chunk_t sig, data = chunk_from_chars(0x01,0x02,0x03,0xFD,0xFE,0xFF);
+       int i;
+
+       for (i = 0; i < countof(schemes); i++)
+       {
+               if (!lib->plugins->has_feature(lib->plugins,
+                                               PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].scheme)) ||
+                       !lib->plugins->has_feature(lib->plugins,
+                                               PLUGIN_PROVIDE(PRIVKEY_SIGN, schemes[i].scheme)))
+               {
+                       continue;
+               }
+               if (schemes[i].key_size != 0 &&
+                       schemes[i].scheme != privkey->get_keysize(privkey))
+               {
+                       continue;
+               }
+               fail_unless(privkey->sign(privkey, schemes[i].scheme, data, &sig),
+                                       "sign %N", signature_scheme_names, schemes[i].scheme);
+               fail_unless(pubkey->verify(pubkey, schemes[i].scheme, data, sig),
+                                       "verify %N", signature_scheme_names, schemes[i].scheme);
+               free(sig.ptr);
+       }
+}
+
+/**
+ * Some special signatures that should never validate successfully
+ */
+static chunk_t invalid_sigs[] = {
+       chunk_from_chars(),
+       chunk_from_chars(0x00),
+       chunk_from_chars(0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+};
+
+/**
+ * Check public key that it properly fails against some crafted sigs
+ */
+static void test_bad_sigs(public_key_t *pubkey)
+{
+       chunk_t data = chunk_from_chars(0x01,0x02,0x03,0xFD,0xFE,0xFF);
+       int s, i;
+
+       for (s = 0; s < countof(schemes); s++)
+       {
+               if (schemes[s].key_size != 0 &&
+                       schemes[s].scheme != pubkey->get_keysize(pubkey))
+               {
+                       continue;
+               }
+               if (!lib->plugins->has_feature(lib->plugins,
+                                               PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[s].scheme)))
+               {
+                       continue;
+               }
+               for (i = 0; i < countof(invalid_sigs); i++)
+               {
+                       fail_if(
+                               pubkey->verify(pubkey, schemes[s].scheme, data, invalid_sigs[i]),
+                               "bad %N sig accepted %B",
+                               signature_scheme_names, schemes[s].scheme,
+                               &invalid_sigs[i]);
+               }
+       }
+}
+
+/**
+ * ECDSA key sizes to test
+ */
+static int key_sizes[] = {
+       256, 384, 521,
+};
+
+START_TEST(test_gen)
+{
+       private_key_t *privkey;
+       public_key_t *pubkey;
+
+       privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
+                                                                BUILD_KEY_SIZE, key_sizes[_i], BUILD_END);
+       ck_assert(privkey != NULL);
+       pubkey = privkey->get_public_key(privkey);
+       ck_assert(pubkey != NULL);
+
+       test_good_sig(privkey, pubkey);
+
+       test_bad_sigs(pubkey);
+
+       pubkey->destroy(pubkey);
+       privkey->destroy(privkey);
+}
+END_TEST
+
+/**
+ * Private keys to load
+ */
+static chunk_t keys[] = {
+       chunk_from_chars( /* ECDSA-256 */
+               0x30,0x77,0x02,0x01,0x01,0x04,0x20,0x42,0xc6,0x8c,0xff,0x2b,0x8b,0x87,0xa1,0xfb,
+               0x50,0xf6,0xfe,0xd6,0x88,0xb3,0x0a,0x48,0xb2,0xc5,0x8f,0x50,0xe0,0xcf,0x40,0xfa,
+               0x57,0xd1,0xc6,0x6c,0x20,0x64,0xc5,0xa0,0x0a,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,
+               0x03,0x01,0x07,0xa1,0x44,0x03,0x42,0x00,0x04,0x9c,0xb2,0x52,0xcb,0xc0,0x5c,0xcf,
+               0x97,0xdd,0xd6,0xe7,0x49,0x32,0x47,0x0c,0x8e,0xdb,0x6d,0xbf,0xc8,0x1a,0x0a,0x01,
+               0xe8,0x5e,0x3f,0x8e,0x64,0x33,0xb4,0x15,0xbb,0x1b,0xa5,0xed,0xf9,0x4b,0xa7,0xe8,
+               0x5e,0x6f,0x49,0x24,0xf7,0x32,0xf4,0x9b,0x4c,0x47,0xdc,0xf1,0x28,0x44,0x1c,0x37,
+               0xdb,0xee,0xfb,0xd8,0xbd,0x4e,0x5c,0xeb,0x07),
+       chunk_from_chars( /* ECDSA-384 */
+               0x30,0x81,0xa4,0x02,0x01,0x01,0x04,0x30,0x4b,0xbf,0x6c,0xf5,0x24,0x78,0x53,0x4b,
+               0x1a,0x91,0x23,0xae,0x30,0xc8,0xb3,0xc9,0xc2,0x9b,0x23,0x07,0x10,0x6f,0x1b,0x47,
+               0x7c,0xa0,0xd4,0x79,0x3c,0xc4,0x83,0x10,0xd1,0x44,0x07,0xc2,0x1b,0x66,0xff,0xae,
+               0x76,0x57,0x72,0x90,0x53,0xc2,0xf5,0x29,0xa0,0x07,0x06,0x05,0x2b,0x81,0x04,0x00,
+               0x22,0xa1,0x64,0x03,0x62,0x00,0x04,0x1e,0xcf,0x1c,0x85,0x9d,0x06,0xa0,0x54,0xa2,
+               0x24,0x2f,0xd8,0x63,0x56,0x7b,0x70,0x0b,0x7f,0x81,0x96,0xce,0xb9,0x2e,0x35,0x03,
+               0x9c,0xf9,0x0a,0x5d,0x3b,0x10,0xf7,0x13,0x7a,0x0d,0xca,0x56,0xda,0x1d,0x44,0x84,
+               0x07,0x6f,0x58,0xdc,0x34,0x7b,0x1d,0x4c,0xdd,0x28,0x10,0xc0,0xe2,0xae,0xf4,0xd6,
+               0xda,0xea,0xaf,0xfc,0x7a,0xaf,0x59,0x5f,0xbc,0x91,0x65,0xd3,0x21,0x19,0x61,0xbb,
+               0xfe,0x3c,0xdb,0x47,0xcb,0x7a,0xe7,0x5d,0xbd,0x28,0xde,0x25,0x64,0x9e,0x3a,0xa9,
+               0x18,0xed,0x24,0xe1,0x1f,0x73,0xcc),
+       chunk_from_chars( /* ECDSA-521 */
+               0x30,0x81,0xdc,0x02,0x01,0x01,0x04,0x42,0x01,0xcf,0x38,0xaa,0xa7,0x7a,0x79,0x48,
+               0xa9,0x60,0x55,0x24,0xa8,0x7e,0xe1,0xbc,0x45,0x35,0x16,0xff,0x18,0xce,0x44,0xa2,
+               0x0b,0x72,0x6b,0xca,0x0a,0x40,0xb4,0x97,0x13,0x17,0x90,0x50,0x15,0xb9,0xba,0xfc,
+               0x08,0x0e,0xdb,0xf8,0xfc,0x06,0x35,0x37,0xbf,0xfb,0x25,0x74,0xfe,0x0f,0xe1,0x3c,
+               0x3a,0xf0,0x0d,0xe0,0x52,0x15,0xa8,0x07,0x6f,0x3e,0xa0,0x07,0x06,0x05,0x2b,0x81,
+               0x04,0x00,0x23,0xa1,0x81,0x89,0x03,0x81,0x86,0x00,0x04,0x00,0x56,0x81,0x28,0xd6,
+               0xac,0xe9,0xc8,0x82,0x2c,0xac,0x61,0x6d,0xdd,0x88,0x79,0x00,0xe3,0x7a,0x4d,0x25,
+               0xc4,0xea,0x05,0x80,0x75,0x48,0xbc,0x75,0x73,0xc4,0xe9,0x76,0x68,0xba,0x51,0xc3,
+               0x29,0xce,0x7d,0x1b,0xb0,0x8b,0xac,0xc1,0xcc,0x23,0xa7,0x2d,0xa7,0x2c,0x95,0xf6,
+               0x01,0x40,0x26,0x01,0x1c,0x1c,0x9c,0xe7,0xa7,0xb4,0x0f,0x8e,0xba,0x01,0x07,0xb3,
+               0xf7,0xbe,0x45,0x20,0xa9,0x9e,0x70,0xf0,0xcf,0x9b,0xa0,0x91,0xe3,0x88,0x8f,0x04,
+               0x69,0x3d,0x0f,0x2b,0xf3,0xb4,0x03,0x19,0x89,0xcf,0xfa,0x77,0x04,0x15,0xaf,0xdd,
+               0xf7,0x32,0x76,0x25,0x25,0x05,0x8d,0xfd,0x18,0x8a,0xda,0xd6,0xbc,0x71,0xb8,0x9f,
+               0x39,0xb0,0xaf,0xcc,0x54,0xb0,0x9c,0x4d,0x54,0xfb,0x46,0x53,0x5f,0xf8,0x45),
+};
+
+START_TEST(test_load)
+{
+       private_key_t *privkey;
+       public_key_t *pubkey;
+
+       privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
+                                                                BUILD_BLOB_ASN1_DER, keys[_i], BUILD_END);
+       ck_assert(privkey != NULL);
+       pubkey = privkey->get_public_key(privkey);
+       ck_assert(pubkey != NULL);
+
+       test_good_sig(privkey, pubkey);
+
+       test_bad_sigs(pubkey);
+
+       pubkey->destroy(pubkey);
+       privkey->destroy(privkey);
+}
+END_TEST
+
+Suite *ecdsa_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("ecdsa");
+
+       tc = tcase_create("generate");
+       tcase_add_loop_test(tc, test_gen, 0, countof(key_sizes));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("load");
+       tcase_add_loop_test(tc, test_load, 0, countof(keys));
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_enum.c b/src/libstrongswan/tests/suites/test_enum.c
new file mode 100644 (file)
index 0000000..990d9cf
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <utils/enum.h>
+#include <utils/utils.h>
+
+/*******************************************************************************
+ * continuous enum
+ */
+enum {
+       CONT1,
+       CONT2,
+       CONT3,
+       CONT4,
+       CONT5,
+} test_enum_cont;
+
+/* can't be static */
+enum_name_t *test_enum_cont_names;
+
+ENUM_BEGIN(test_enum_cont_names, CONT1, CONT5,
+       "CONT1", "CONT2", "CONT3", "CONT4", "CONT5");
+ENUM_END(test_enum_cont_names, CONT5);
+
+/*******************************************************************************
+ * split enum
+ */
+enum {
+       SPLIT1 = 1,
+       SPLIT2,
+       SPLIT3 = 5,
+       SPLIT4,
+       SPLIT5 = 255,
+} test_enum_split;
+
+/* can't be static */
+enum_name_t *test_enum_split_names;
+
+ENUM_BEGIN(test_enum_split_names, SPLIT1, SPLIT2,
+       "SPLIT1", "SPLIT2");
+ENUM_NEXT(test_enum_split_names, SPLIT3, SPLIT4, SPLIT2,
+       "SPLIT3", "SPLIT4");
+ENUM_NEXT(test_enum_split_names, SPLIT5, SPLIT5, SPLIT4,
+       "SPLIT5");
+ENUM_END(test_enum_split_names, SPLIT5);
+
+/*******************************************************************************
+ * enum_to_name
+ */
+
+static struct {
+       int val;
+       char *str;
+} name_tests_cont[] = {
+       {-1, NULL},
+       {CONT1, "CONT1"},
+       {CONT2, "CONT2"},
+       {CONT3, "CONT3"},
+       {CONT4, "CONT4"},
+       {CONT5, "CONT5"},
+       {5, NULL},
+}, name_tests_split[] = {
+       {-1, NULL},
+       {0, NULL},
+       {SPLIT1, "SPLIT1"},
+       {SPLIT2, "SPLIT2"},
+       {3, NULL},
+       {4, NULL},
+       {SPLIT3, "SPLIT3"},
+       {SPLIT4, "SPLIT4"},
+       {7, NULL},
+       {254, NULL},
+       {SPLIT5, "SPLIT5"},
+       {256, NULL},
+};
+
+START_TEST(test_enum_to_name_cont)
+{
+       char *str = enum_to_name(test_enum_cont_names, name_tests_cont[_i].val);
+       if (str)
+       {
+               ck_assert_str_eq(str, name_tests_cont[_i].str);
+       }
+       else
+       {
+               ck_assert(str == name_tests_cont[_i].str);
+       }
+}
+END_TEST
+
+START_TEST(test_enum_to_name_split)
+{
+       char *str = enum_to_name(test_enum_split_names, name_tests_split[_i].val);
+       if (str)
+       {
+               ck_assert_str_eq(str, name_tests_split[_i].str);
+       }
+       else
+       {
+               ck_assert(str == name_tests_split[_i].str);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * enum_from_name
+ */
+
+static struct {
+       int val;
+       char *str;
+} enum_tests_cont[] = {
+       {CONT1, "CONT1"},
+       {CONT2, "CONT2"},
+       {CONT2, "CoNt2"},
+       {CONT3, "CONT3"},
+       {CONT4, "CONT4"},
+       {CONT5, "CONT5"},
+       {-1, "asdf"},
+       {-1, ""},
+       {-1, NULL},
+}, enum_tests_split[] = {
+       {SPLIT1, "SPLIT1"},
+       {SPLIT1, "split1"},
+       {SPLIT2, "SPLIT2"},
+       {SPLIT2, "SpLiT2"},
+       {SPLIT3, "SPLIT3"},
+       {SPLIT4, "SPLIT4"},
+       {SPLIT5, "SPLIT5"},
+       {-1, "asdf"},
+       {-1, ""},
+       {-1, NULL},
+};
+
+START_TEST(test_enum_from_name_cont)
+{
+       int val = enum_from_name(test_enum_cont_names, enum_tests_cont[_i].str);
+       ck_assert_int_eq(val, enum_tests_cont[_i].val);
+}
+END_TEST
+
+START_TEST(test_enum_from_name_split)
+{
+       int val = enum_from_name(test_enum_split_names, enum_tests_split[_i].str);
+       ck_assert_int_eq(val, enum_tests_split[_i].val);
+}
+END_TEST
+
+/*******************************************************************************
+ * enum_printf_hook
+ */
+
+static struct {
+       int val;
+       char *str;
+} printf_tests_cont[] = {
+       {-1, "(-1)"},
+       {CONT1, "CONT1"},
+       {CONT2, "CONT2"},
+       {CONT3, "CONT3"},
+       {CONT4, "CONT4"},
+       {CONT5, "CONT5"},
+       {5, "(5)"},
+}, printf_tests_split[] = {
+       {-1, "(-1)"},
+       {0, "(0)"},
+       {SPLIT1, "SPLIT1"},
+       {SPLIT2, "SPLIT2"},
+       {3, "(3)"},
+       {4, "(4)"},
+       {SPLIT3, "SPLIT3"},
+       {SPLIT4, "SPLIT4"},
+       {7, "(7)"},
+       {254, "(254)"},
+       {SPLIT5, "SPLIT5"},
+       {256, "(256)"},
+};
+
+START_TEST(test_enum_printf_hook_cont)
+{
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%N", test_enum_cont_names, printf_tests_cont[_i].val);
+       ck_assert_str_eq(printf_tests_cont[_i].str, buf);
+}
+END_TEST
+
+START_TEST(test_enum_printf_hook_split)
+{
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%N", test_enum_split_names, printf_tests_split[_i].val);
+       ck_assert_str_eq(printf_tests_split[_i].str, buf);
+}
+END_TEST
+
+START_TEST(test_enum_printf_hook_width)
+{
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%10N", test_enum_cont_names, CONT1);
+       ck_assert_str_eq("     CONT1", buf);
+       snprintf(buf, sizeof(buf), "%-*N", 10, test_enum_cont_names, CONT2);
+       ck_assert_str_eq("CONT2     ", buf);
+       snprintf(buf, sizeof(buf), "%3N", test_enum_cont_names, CONT3);
+       ck_assert_str_eq("CONT3", buf);
+}
+END_TEST
+
+Suite *enum_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("enum");
+
+       tc = tcase_create("enum_to_name");
+       tcase_add_loop_test(tc, test_enum_to_name_cont, 0, countof(name_tests_cont));
+       tcase_add_loop_test(tc, test_enum_to_name_split, 0, countof(name_tests_split));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("enum_from_name");
+       tcase_add_loop_test(tc, test_enum_from_name_cont, 0, countof(enum_tests_cont));
+       tcase_add_loop_test(tc, test_enum_from_name_split, 0, countof(enum_tests_split));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("enum_printf_hook");
+       tcase_add_loop_test(tc, test_enum_printf_hook_cont, 0, countof(printf_tests_cont));
+       tcase_add_loop_test(tc, test_enum_printf_hook_split, 0, countof(printf_tests_split));
+       tcase_add_test(tc, test_enum_printf_hook_width);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_enumerator.c b/src/libstrongswan/tests/suites/test_enumerator.c
new file mode 100644 (file)
index 0000000..b5dde46
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <collections/enumerator.h>
+#include <collections/linked_list.h>
+
+/*******************************************************************************
+ * token test
+ */
+
+static const char *token_results1[] = { "abc", "cde", "efg" };
+static const char *token_results2[] = { "a", "b", "c" };
+
+static struct {
+       char *string;
+       char *sep;
+       char *trim;
+       const char **results;
+} token_tests[] = {
+       {"abc, cde, efg", ",", " ", token_results1},
+       {" abc 1:2 cde;3  4efg5.  ", ":;.,", " 12345", token_results1},
+       {"abc.cde,efg", ",.", "", token_results1},
+       {"  abc   cde  efg  ", " ", " ", token_results1},
+       {"a'abc' c 'cde' cefg", " ", " abcd", token_results1},
+       {"'abc' abc 'cde'd 'efg'", " ", " abcd", token_results1},
+
+       {"a, b, c", ",", " ", token_results2},
+       {"a,b,c", ",", " ", token_results2},
+       {" a 1:2 b;3  4c5.  ", ":;.,", " 12345", token_results2},
+       {"a.b,c", ",.", "", token_results2},
+       {"  a   b  c  ", " ", " ", token_results2},
+};
+
+START_TEST(test_token)
+{
+       enumerator_t *enumerator;
+       const char **results;
+       char *token;
+       int tok = 0;
+
+       enumerator = enumerator_create_token(token_tests[_i].string,
+                                                                       token_tests[_i].sep, token_tests[_i].trim);
+       results = token_tests[_i].results;
+       while (enumerator->enumerate(enumerator, &token))
+       {
+               switch (tok)
+               {
+                       case 0:
+                       case 1:
+                       case 2:
+                               ck_assert_str_eq(token, results[tok]);
+                               break;
+                       default:
+                               fail("unexpected token '%s'", token);
+               }
+               tok++;
+       }
+       fail_if(tok != 3, "not enough tokens (%d) extracted from '%s'",
+                       tok, token_tests[_i].string);
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+/*******************************************************************************
+ * utilities for filtered, nested and cleaner tests
+ */
+
+static int destroy_data_called;
+
+START_SETUP(setup_destroy_data)
+{
+       destroy_data_called = 0;
+}
+END_SETUP
+
+START_TEARDOWN(teardown_destroy_data)
+{
+       ck_assert_int_eq(destroy_data_called, 1);
+}
+END_TEARDOWN
+
+static void destroy_data(void *data)
+{
+       fail_if(data != (void*)101, "data does not match '101' in destructor");
+       destroy_data_called++;
+}
+
+/*******************************************************************************
+ * filtered test
+ */
+
+static bool filter(void *data, int *v, int *vo, int *w, int *wo,
+                                  int *x, int *xo, int *y, int *yo, int *z, int *zo)
+{
+       int val = *v;
+
+       *vo = val++;
+       *wo = val++;
+       *xo = val++;
+       *yo = val++;
+       *zo = val++;
+       fail_if(data != (void*)101, "data does not match '101' in filter function");
+       return TRUE;
+}
+
+static bool filter_odd(void *data, int *item, int *out)
+{
+       fail_if(data != (void*)101, "data does not match '101' in filter function");
+       *out = *item;
+       return *item % 2 == 0;
+}
+
+START_TEST(test_filtered)
+{
+       int round, v, w, x, y, z;
+       linked_list_t *list;
+       enumerator_t *enumerator;
+
+       list = linked_list_create_with_items((void*)1, (void*)2, (void*)3, (void*)4,
+                                                                                (void*)5, NULL);
+
+       round = 1;
+       enumerator = enumerator_create_filter(list->create_enumerator(list),
+                                                                       (void*)filter, (void*)101, destroy_data);
+       while (enumerator->enumerate(enumerator, &v, &w, &x, &y, &z))
+       {
+               ck_assert_int_eq(v, round);
+               ck_assert_int_eq(w, round + 1);
+               ck_assert_int_eq(x, round + 2);
+               ck_assert_int_eq(y, round + 3);
+               ck_assert_int_eq(z, round + 4);
+               round++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(round, 6);
+
+       list->destroy(list);
+}
+END_TEST
+
+START_TEST(test_filtered_filter)
+{
+       int count, x;
+       linked_list_t *list;
+       enumerator_t *enumerator;
+
+       list = linked_list_create_with_items((void*)1, (void*)2, (void*)3, (void*)4,
+                                                                                (void*)5, NULL);
+
+       count = 0;
+       /* should also work without destructor, so set this manually */
+       destroy_data_called = 1;
+       enumerator = enumerator_create_filter(list->create_enumerator(list),
+                                                                                (void*)filter_odd, (void*)101, NULL);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert(x % 2 == 0);
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 2);
+
+       list->destroy(list);
+}
+END_TEST
+
+/*******************************************************************************
+ * nested test
+ */
+
+static enumerator_t* create_inner(linked_list_t *outer, void *data)
+{
+       fail_if(data != (void*)101, "data does not match '101' in nested constr.");
+       return outer->create_enumerator(outer);
+}
+
+static enumerator_t* create_inner_null(void *outer, void *data)
+{
+       ck_assert(outer == (void*)1);
+       fail_if(data != (void*)101, "data does not match '101' in nested constr.");
+       return NULL;
+}
+
+START_TEST(test_nested)
+{
+       linked_list_t *list, *l1, *l2, *l3;
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       l1 = linked_list_create_with_items((void*)1, (void*)2, NULL);
+       l2 = linked_list_create();
+       l3 = linked_list_create_with_items((void*)3, (void*)4, (void*)5, NULL);
+       list = linked_list_create_with_items(l1, l2, l3, NULL);
+
+       round = 1;
+       enumerator = enumerator_create_nested(list->create_enumerator(list),
+                                                               (void*)create_inner, (void*)101, destroy_data);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(round, 6);
+
+       list->destroy(list);
+       l1->destroy(l1);
+       l2->destroy(l2);
+       l3->destroy(l3);
+}
+END_TEST
+
+START_TEST(test_nested_reset)
+{
+       linked_list_t *list, *l1, *l2, *l3;
+       enumerator_t *outer, *enumerator;
+       intptr_t x;
+       int count = 0;
+
+       l1 = linked_list_create_with_items((void*)1, (void*)2, NULL);
+       l2 = linked_list_create();
+       l3 = linked_list_create_with_items((void*)3, (void*)4, (void*)5, NULL);
+       list = linked_list_create_with_items(l1, l2, l3, NULL);
+
+       outer = list->create_enumerator(list);
+       enumerator = enumerator_create_nested(outer, (void*)create_inner,
+                                                                                (void*)101, destroy_data);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               count++;
+       }
+       ck_assert_int_eq(count, 5);
+
+       list->reset_enumerator(list, outer);
+       ck_assert(enumerator->enumerate(enumerator, &x));
+       ck_assert_int_eq(x, 1);
+       enumerator->destroy(enumerator);
+
+       list->destroy(list);
+       l1->destroy(l1);
+       l2->destroy(l2);
+       l3->destroy(l3);
+}
+END_TEST
+
+START_TEST(test_nested_empty)
+{
+       linked_list_t *list;
+       enumerator_t *enumerator;
+       intptr_t x;
+       int count;
+
+       list = linked_list_create();
+       count = 0;
+       enumerator = enumerator_create_nested(list->create_enumerator(list),
+                                                               (void*)create_inner, (void*)101, destroy_data);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 0);
+
+       list->destroy(list);
+}
+END_TEST
+
+START_TEST(test_nested_null)
+{
+       linked_list_t *list;
+       enumerator_t *enumerator;
+       intptr_t x;
+       int count;
+
+       list = linked_list_create_with_items((void*)1, NULL);
+
+       count = 0;
+       /* should also work without destructor, so set this manually */
+       destroy_data_called = 1;
+       enumerator = enumerator_create_nested(list->create_enumerator(list),
+                                                                       (void*)create_inner_null, (void*)101, NULL);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 0);
+
+       list->destroy(list);
+}
+END_TEST
+
+/*******************************************************************************
+ * cleaner test
+ */
+
+START_TEST(test_cleaner)
+{
+       enumerator_t *enumerator;
+       linked_list_t *list;
+       intptr_t x;
+       int round;
+
+       list = linked_list_create_with_items((void*)1, (void*)2, NULL);
+
+       round = 1;
+       enumerator = enumerator_create_cleaner(list->create_enumerator(list),
+                                                                                  destroy_data, (void*)101);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       ck_assert_int_eq(round, 3);
+       enumerator->destroy(enumerator);
+       list->destroy(list);
+}
+END_TEST
+
+/*******************************************************************************
+ * single test
+ */
+
+static void single_cleanup(void *data)
+{
+       ck_assert_int_eq((intptr_t)data, 1);
+}
+
+static void do_test_single(enumerator_t *enumerator)
+{
+       intptr_t x;
+
+       ck_assert(enumerator->enumerate(enumerator, &x));
+       ck_assert_int_eq(x, 1);
+       ck_assert(!enumerator->enumerate(enumerator, &x));
+       enumerator->destroy(enumerator);
+}
+
+START_TEST(test_single)
+{
+       enumerator_t *enumerator;
+
+       enumerator = enumerator_create_single((void*)1, NULL);
+       do_test_single(enumerator);
+}
+END_TEST
+
+START_TEST(test_single_cleanup)
+{
+       enumerator_t *enumerator;
+
+       enumerator = enumerator_create_single((void*)1, single_cleanup);
+       do_test_single(enumerator);
+}
+END_TEST
+
+Suite *enumerator_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("enumerator");
+
+       tc = tcase_create("tokens");
+       tcase_add_loop_test(tc, test_token, 0, countof(token_tests));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("filtered");
+       tcase_add_checked_fixture(tc, setup_destroy_data, teardown_destroy_data);
+       tcase_add_test(tc, test_filtered);
+       tcase_add_test(tc, test_filtered_filter);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("nested");
+       tcase_add_checked_fixture(tc, setup_destroy_data, teardown_destroy_data);
+       tcase_add_test(tc, test_nested);
+       tcase_add_test(tc, test_nested_reset);
+       tcase_add_test(tc, test_nested_empty);
+       tcase_add_test(tc, test_nested_null);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("cleaner");
+       tcase_add_checked_fixture(tc, setup_destroy_data, teardown_destroy_data);
+       tcase_add_test(tc, test_cleaner);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("single");
+       tcase_add_test(tc, test_single);
+       tcase_add_test(tc, test_single_cleanup);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_hashtable.c b/src/libstrongswan/tests/suites/test_hashtable.c
new file mode 100644 (file)
index 0000000..8cc7bfe
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2010-2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <collections/hashtable.h>
+#include <utils/chunk.h>
+
+/*******************************************************************************
+ * string hash table functions
+ */
+
+static u_int hash(char *key)
+{
+       return chunk_hash(chunk_from_str(key));
+}
+
+static bool equals(char *key1, char *key2)
+{
+       return streq(key1, key2);
+}
+
+/*******************************************************************************
+ * test fixture
+ */
+
+static hashtable_t *ht;
+
+START_SETUP(setup_ht)
+{
+       ht = hashtable_create((hashtable_hash_t)hash,
+                                                 (hashtable_equals_t)equals, 0);
+       ck_assert_int_eq(ht->get_count(ht), 0);
+}
+END_SETUP
+
+START_TEARDOWN(teardown_ht)
+{
+       ht->destroy(ht);
+}
+END_TEARDOWN
+
+/*******************************************************************************
+ * put/get
+ */
+
+START_TEST(test_put_get)
+{
+       char *k1 = "key1", *k2 = "key2", *k3 = "key3";
+       char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value;
+
+       value = ht->put(ht, k1, v1);
+       ck_assert_int_eq(ht->get_count(ht), 1);
+       ck_assert(streq(ht->get(ht, k1), v1));
+       ck_assert(ht->get(ht, k2) == NULL);
+       ck_assert(ht->get(ht, k3) == NULL);
+       ck_assert(value == NULL);
+
+       ht->put(ht, k2, v2);
+       ht->put(ht, k3, v3);
+       ck_assert_int_eq(ht->get_count(ht), 3);
+       ck_assert(streq(ht->get(ht, k1), v1));
+       ck_assert(streq(ht->get(ht, k2), v2));
+       ck_assert(streq(ht->get(ht, k3), v3));
+
+       value = ht->put(ht, k2, v1);
+       ck_assert_int_eq(ht->get_count(ht), 3);
+       ck_assert(streq(value, v2));
+       ck_assert(streq(ht->get(ht, k2), v1));
+}
+END_TEST
+
+/*******************************************************************************
+ * get_match
+ */
+
+static u_int hash_match(char *key)
+{
+       return chunk_hash(chunk_create(key, 4));
+}
+
+static bool equal_match(char *key1, char *key2)
+{
+       if (!strneq(key1, key2, 4))
+       {
+               return FALSE;
+       }
+       /* look for an item with a key < than what we look for */
+       return strcmp(key1, key2) >= 0;
+}
+
+START_TEST(test_get_match)
+{
+       char *k1 = "key1_a", *k2 = "key2", *k3 = "key1_b", *k4 = "key1_c";
+       char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value;
+
+       ht = hashtable_create((hashtable_hash_t)hash_match,
+                                                 (hashtable_equals_t)equals, 0);
+
+       ht->put(ht, k1, v1);
+       ht->put(ht, k2, v2);
+       value = ht->put(ht, k3, v3);
+       ck_assert_int_eq(ht->get_count(ht), 3);
+       ck_assert(streq(ht->get(ht, k1), v1));
+       ck_assert(streq(ht->get(ht, k2), v2));
+       ck_assert(streq(ht->get(ht, k3), v3));
+       ck_assert(value == NULL);
+
+       value = ht->get_match(ht, k1, (hashtable_equals_t)equal_match);
+       ck_assert(value != NULL);
+       ck_assert(streq(value, v1));
+       value = ht->get_match(ht, k2, (hashtable_equals_t)equal_match);
+       ck_assert(value != NULL);
+       ck_assert(streq(value, v2));
+       value = ht->get_match(ht, k3, (hashtable_equals_t)equal_match);
+       ck_assert(value != NULL);
+       ck_assert(streq(value, v1));
+       value = ht->get_match(ht, k4, (hashtable_equals_t)equal_match);
+       ck_assert(value != NULL);
+       ck_assert(streq(value, v1));
+
+       ht->destroy(ht);
+}
+END_TEST
+
+/*******************************************************************************
+ * remove
+ */
+
+static void do_remove(char *k1, char *k2, char *k3)
+{
+       char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value;
+
+       ht->put(ht, k1, v1);
+       ht->put(ht, k2, v2);
+       ht->put(ht, k3, v3);
+
+       value = ht->remove(ht, k2);
+       ck_assert_int_eq(ht->get_count(ht), 2);
+       ck_assert(streq(ht->get(ht, k1), v1));
+       ck_assert(streq(ht->get(ht, k3), v3));
+       ck_assert(streq(value, v2));
+       ck_assert(ht->get(ht, k2) == NULL);
+
+       value = ht->remove(ht, k2);
+       ck_assert_int_eq(ht->get_count(ht), 2);
+       ck_assert(value == NULL);
+
+       value = ht->remove(ht, k1);
+       value = ht->remove(ht, k3);
+       ck_assert_int_eq(ht->get_count(ht), 0);
+       ck_assert(ht->get(ht, k1) == NULL);
+       ck_assert(ht->get(ht, k2) == NULL);
+       ck_assert(ht->get(ht, k3) == NULL);
+}
+
+START_TEST(test_remove)
+{
+       char *k1 = "key1", *k2 = "key2", *k3 = "key3";
+
+       do_remove(k1, k2, k3);
+}
+END_TEST
+
+START_TEST(test_remove_one_bucket)
+{
+       char *k1 = "key1_a", *k2 = "key1_b", *k3 = "key1_c";
+
+       ht->destroy(ht);
+       /* set a capacity to avoid rehashing, which would change the items' order */
+       ht = hashtable_create((hashtable_hash_t)hash_match,
+                                                 (hashtable_equals_t)equals, 8);
+
+       do_remove(k1, k2, k3);
+}
+END_TEST
+
+/*******************************************************************************
+ * enumerator
+ */
+
+START_TEST(test_enumerator)
+{
+       char *k1 = "key1", *k2 = "key2", *k3 = "key3", *key;
+       char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value;
+       enumerator_t *enumerator;
+       int count;
+
+       ht->put(ht, k1, v1);
+       ht->put(ht, k2, v2);
+       ht->put(ht, k3, v3);
+
+       count = 0;
+       enumerator = ht->create_enumerator(ht);
+       while (enumerator->enumerate(enumerator, &key, &value))
+       {
+               ck_assert(streq(key, k1) || streq(key, k2) || streq(key, k3));
+               ck_assert(streq(value, v1) || streq(value, v2) || streq(value, v3));
+               ck_assert(!streq(key, k1) || streq(value, v1));
+               ck_assert(!streq(key, k2) || streq(value, v2));
+               ck_assert(!streq(key, k3) || streq(value, v3));
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 3);
+
+       count = 0;
+       enumerator = ht->create_enumerator(ht);
+       while (enumerator->enumerate(enumerator, NULL, NULL))
+       {
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 3);
+
+       value = ht->remove(ht, k1);
+       value = ht->remove(ht, k2);
+       value = ht->remove(ht, k3);
+
+       count = 0;
+       enumerator = ht->create_enumerator(ht);
+       while (enumerator->enumerate(enumerator, &key, &value))
+       {
+               count++;
+       }
+       enumerator->destroy(enumerator);
+       ck_assert_int_eq(count, 0);
+}
+END_TEST
+
+/*******************************************************************************
+ * remove_at
+ */
+
+static void do_remove_at(char *k1, char *k2, char *k3)
+{
+       char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value, *key;
+       enumerator_t *enumerator;
+
+       ht->put(ht, k1, v1);
+       ht->put(ht, k2, v2);
+       ht->put(ht, k3, v3);
+
+       enumerator = ht->create_enumerator(ht);
+       ht->remove_at(ht, enumerator);
+       while (enumerator->enumerate(enumerator, &key, &value))
+       {
+               if (streq(key, k2))
+               {
+                       ht->remove_at(ht, enumerator);
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       ck_assert_int_eq(ht->get_count(ht), 2);
+       ck_assert(ht->get(ht, k1) != NULL);
+       ck_assert(ht->get(ht, k3) != NULL);
+       ck_assert(ht->get(ht, k2) == NULL);
+
+       ht->put(ht, k2, v2);
+
+       ck_assert_int_eq(ht->get_count(ht), 3);
+       ck_assert(ht->get(ht, k1) != NULL);
+       ck_assert(ht->get(ht, k2) != NULL);
+       ck_assert(ht->get(ht, k3) != NULL);
+
+       enumerator = ht->create_enumerator(ht);
+       while (enumerator->enumerate(enumerator, &key, &value))
+       {
+               ht->remove_at(ht, enumerator);
+       }
+       enumerator->destroy(enumerator);
+
+       ck_assert_int_eq(ht->get_count(ht), 0);
+       ck_assert(ht->get(ht, k1) == NULL);
+       ck_assert(ht->get(ht, k2) == NULL);
+       ck_assert(ht->get(ht, k3) == NULL);
+}
+
+START_TEST(test_remove_at)
+{
+       char *k1 = "key1", *k2 = "key2", *k3 = "key3";
+
+       do_remove_at(k1, k2, k3);
+}
+END_TEST
+
+START_TEST(test_remove_at_one_bucket)
+{
+       char *k1 = "key1_a", *k2 = "key1_b", *k3 = "key1_c";
+
+       ht->destroy(ht);
+       /* set a capacity to avoid rehashing, which would change the items' order */
+       ht = hashtable_create((hashtable_hash_t)hash_match,
+                                                 (hashtable_equals_t)equals, 8);
+       do_remove_at(k1, k2, k3);
+}
+END_TEST
+
+Suite *hashtable_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("hashtable");
+
+       tc = tcase_create("put/get");
+       tcase_add_checked_fixture(tc, setup_ht, teardown_ht);
+       tcase_add_test(tc, test_put_get);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("get_match");
+       tcase_add_test(tc, test_get_match);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("remove");
+       tcase_add_checked_fixture(tc, setup_ht, teardown_ht);
+       tcase_add_test(tc, test_remove);
+       tcase_add_test(tc, test_remove_one_bucket);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("enumerator");
+       tcase_add_checked_fixture(tc, setup_ht, teardown_ht);
+       tcase_add_test(tc, test_enumerator);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("remove_at");
+       tcase_add_checked_fixture(tc, setup_ht, teardown_ht);
+       tcase_add_test(tc, test_remove_at);
+       tcase_add_test(tc, test_remove_at_one_bucket);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_host.c b/src/libstrongswan/tests/suites/test_host.c
new file mode 100644 (file)
index 0000000..30b9eb9
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <networking/host.h>
+
+/**
+ * Verify a netmask (a number of set bits starting at byte 0)
+ * Can also be used to check for %any (mask == 0)
+ */
+static void verify_netmask(chunk_t addr, int mask)
+{
+       int byte, bit;
+
+       for (byte = 0; byte < addr.len; byte++)
+       {
+               for (bit = 7; bit >= 0; bit--)
+               {
+                       int val = (addr.ptr[byte] >> bit) & 0x01;
+                       if (mask-- > 0)
+                       {
+                               ck_assert_int_eq(val, 1);
+                       }
+                       else
+                       {
+                               ck_assert_int_eq(val, 0);
+                       }
+               }
+       }
+}
+
+/*******************************************************************************
+ * host_create_any
+ */
+
+static void verify_any(host_t *host, int family, u_int16_t port)
+{
+       verify_netmask(host->get_address(host), 0);
+       ck_assert(host->is_anyaddr(host));
+       ck_assert_int_eq(host->get_port(host), port);
+       ck_assert_int_eq(host->get_family(host), family);
+}
+
+static void test_create_any(int family)
+{
+       host_t *host;
+
+       host = host_create_any(family);
+       verify_any(host, family, 0);
+       host->destroy(host);
+}
+
+START_TEST(test_create_any_v4)
+{
+       test_create_any(AF_INET);
+}
+END_TEST
+
+START_TEST(test_create_any_v6)
+{
+       test_create_any(AF_INET6);
+}
+END_TEST
+
+START_TEST(test_create_any_other)
+{
+       host_t *host;
+
+       host = host_create_any(AF_UNSPEC);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_from_string
+ */
+
+static void verify_address(host_t *host, chunk_t addr, int family, u_int16_t port)
+{
+       ck_assert(chunk_equals(host->get_address(host), addr));
+       ck_assert(!host->is_anyaddr(host));
+       ck_assert_int_eq(host->get_port(host), port);
+       ck_assert_int_eq(host->get_family(host), family);
+}
+
+static const chunk_t addr_v4 = chunk_from_chars(0xc0, 0xa8, 0x00, 0x01);
+static const chunk_t addr_v6 = chunk_from_chars(0xfe, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
+
+START_TEST(test_create_from_string_v4)
+{
+       host_t *host;
+
+       host = host_create_from_string("%any", 500);
+       verify_any(host, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("%any4", 500);
+       verify_any(host, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("0.0.0.0", 500);
+       verify_any(host, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("192.168.0.1", 500);
+       verify_address(host, addr_v4, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("192.168.0.1::500", 500);
+       ck_assert(host == NULL);
+       host = host_create_from_string("123.456.789.012", 500);
+       ck_assert(host == NULL);
+       host = host_create_from_string("1.1.1.1.1.1.1.1", 500);
+       ck_assert(host == NULL);
+       host = host_create_from_string("foo.b.a.r", 500);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+START_TEST(test_create_from_string_any_v6)
+{
+       host_t *host;
+
+       host = host_create_from_string("%any6", 500);
+       verify_any(host, AF_INET6, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("::", 500);
+       verify_any(host, AF_INET6, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("fec1::1", 500);
+       verify_address(host, addr_v6, AF_INET6, 500);
+       host->destroy(host);
+
+       host = host_create_from_string("fec1::1.500", 500);
+       ck_assert(host == NULL);
+       host = host_create_from_string("f::e::c::1::1", 500);
+       ck_assert(host == NULL);
+       host = host_create_from_string("foo::bar", 500);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_from_string_and_family
+ */
+
+static void test_create_from_string_and_family_any(char *string, int family,
+                                                                                                  int expected)
+{
+       host_t *host;
+
+       host = host_create_from_string_and_family(string, family, 500);
+       if (expected == AF_UNSPEC)
+       {
+               ck_assert(host == NULL);
+       }
+       else
+       {
+               verify_any(host, expected, 500);
+               host->destroy(host);
+       }
+}
+
+static void test_create_from_string_and_family_addr(char *string, chunk_t addr,
+                                                                                                       int family, int expected)
+{
+       host_t *host;
+
+       host = host_create_from_string_and_family(string, family, 500);
+       if (expected == AF_UNSPEC)
+       {
+               ck_assert(host == NULL);
+       }
+       else
+       {
+               verify_address(host, addr, expected, 500);
+               host->destroy(host);
+       }
+}
+
+START_TEST(test_create_from_string_and_family_v4)
+{
+       test_create_from_string_and_family_any("%any", AF_INET, AF_INET);
+       test_create_from_string_and_family_any("%any4", AF_INET, AF_INET);
+       test_create_from_string_and_family_any("0.0.0.0", AF_INET, AF_INET);
+
+       test_create_from_string_and_family_any("%any4", AF_INET6, AF_UNSPEC);
+       test_create_from_string_and_family_any("0.0.0.0", AF_INET6, AF_UNSPEC);
+
+       test_create_from_string_and_family_addr("192.168.0.1", addr_v4, AF_INET, AF_INET);
+       test_create_from_string_and_family_addr("192.168.0.1", addr_v4, AF_INET6, AF_UNSPEC);
+}
+END_TEST
+
+START_TEST(test_create_from_string_and_family_v6)
+{
+       test_create_from_string_and_family_any("%any", AF_INET6, AF_INET6);
+       test_create_from_string_and_family_any("%any6", AF_INET6, AF_INET6);
+       test_create_from_string_and_family_any("::", AF_INET6, AF_INET6);
+
+       test_create_from_string_and_family_any("%any6", AF_INET, AF_UNSPEC);
+       test_create_from_string_and_family_any("::", AF_INET, AF_UNSPEC);
+
+       test_create_from_string_and_family_addr("fec1::1", addr_v6, AF_INET6, AF_INET6);
+       test_create_from_string_and_family_addr("fec1::1", addr_v6, AF_INET, AF_UNSPEC);
+}
+END_TEST
+
+START_TEST(test_create_from_string_and_family_other)
+{
+       test_create_from_string_and_family_any("%any", AF_UNSPEC, AF_INET);
+       test_create_from_string_and_family_any("%any4", AF_UNSPEC, AF_INET);
+       test_create_from_string_and_family_any("0.0.0.0", AF_UNSPEC, AF_INET);
+
+       test_create_from_string_and_family_any("%any6", AF_UNSPEC, AF_INET6);
+       test_create_from_string_and_family_any("::", AF_UNSPEC, AF_INET6);
+
+       test_create_from_string_and_family_addr("192.168.0.1", addr_v4, AF_UNSPEC, AF_INET);
+       test_create_from_string_and_family_addr("fec1::1", addr_v6, AF_UNSPEC, AF_INET6);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_from_sockaddr
+ */
+
+START_TEST(test_create_from_sockaddr_v4)
+{
+       struct sockaddr_in addr = {
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               .sin_len = sizeof(struct sockaddr_in),
+#endif
+               .sin_family = AF_INET,
+               .sin_port = htons(500),
+       }, *val;
+       socklen_t *socklen;
+       host_t *host;
+
+       host = host_create_from_sockaddr((sockaddr_t*)&addr);
+       verify_any(host, AF_INET, 500);
+       val = (struct sockaddr_in*)host->get_sockaddr(host);
+       ck_assert(memeq(&addr, val, sizeof(addr)));
+       socklen = host->get_sockaddr_len(host);
+       ck_assert(*socklen == sizeof(addr));
+       host->destroy(host);
+}
+END_TEST
+
+START_TEST(test_create_from_sockaddr_v6)
+{
+       struct sockaddr_in6 addr = {
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               .sin6_len = sizeof(struct sockaddr_in6),
+#endif
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(500),
+       }, *val;
+       socklen_t *socklen;
+       host_t *host;
+
+       host = host_create_from_sockaddr((sockaddr_t*)&addr);
+       verify_any(host, AF_INET6, 500);
+       val = (struct sockaddr_in6*)host->get_sockaddr(host);
+       ck_assert(memeq(&addr, val, sizeof(addr)));
+       socklen = host->get_sockaddr_len(host);
+       ck_assert(*socklen == sizeof(addr));
+       host->destroy(host);
+}
+END_TEST
+
+START_TEST(test_create_from_sockaddr_other)
+{
+       struct sockaddr_un addr = {
+               .sun_family = AF_UNIX,
+       };
+       host_t *host;
+
+       host = host_create_from_sockaddr((sockaddr_t*)&addr);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_from_chunk
+ */
+
+START_TEST(test_create_from_chunk_v4)
+{
+       host_t *host;
+
+       host = host_create_from_chunk(AF_INET, addr_v4, 500);
+       verify_address(host, addr_v4, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_chunk(AF_UNSPEC, addr_v4, 500);
+       verify_address(host, addr_v4, AF_INET, 500);
+       host->destroy(host);
+
+       host = host_create_from_chunk(AF_INET, chunk_empty, 500);
+       ck_assert(host == NULL);
+       host = host_create_from_chunk(AF_UNSPEC, chunk_empty, 500);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+START_TEST(test_create_from_chunk_v6)
+{
+       host_t *host;
+
+       host = host_create_from_chunk(AF_INET6, addr_v6, 500);
+       verify_address(host, addr_v6, AF_INET6, 500);
+       host->destroy(host);
+
+       host = host_create_from_chunk(AF_UNSPEC, addr_v6, 500);
+       verify_address(host, addr_v6, AF_INET6, 500);
+       host->destroy(host);
+
+       host = host_create_from_chunk(AF_INET6, chunk_empty, 500);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+START_TEST(test_create_from_chunk_other)
+{
+       host_t *host;
+
+       host = host_create_from_chunk(AF_UNIX, addr_v6, 500);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_from_subnet
+ */
+
+START_TEST(test_create_from_subnet_v4)
+{
+       host_t *host;
+       int bits = -1;
+
+       host = host_create_from_subnet("0.0.0.0/0", &bits);
+       verify_any(host, AF_INET, 0);
+       ck_assert_int_eq(bits, 0);
+       host->destroy(host);
+
+       host = host_create_from_subnet("192.168.0.1", &bits);
+       verify_address(host, addr_v4, AF_INET, 0);
+       ck_assert_int_eq(bits, 32);
+       host->destroy(host);
+
+       host = host_create_from_subnet("192.168.0.1/24", &bits);
+       verify_address(host, addr_v4, AF_INET, 0);
+       ck_assert_int_eq(bits, 24);
+       host->destroy(host);
+
+       host = host_create_from_subnet("foo.b.a.r", &bits);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+START_TEST(test_create_from_subnet_v6)
+{
+       host_t *host;
+       int bits = -1;
+
+       host = host_create_from_subnet("::/0", &bits);
+       verify_any(host, AF_INET6, 0);
+       ck_assert_int_eq(bits, 0);
+       host->destroy(host);
+
+       host = host_create_from_subnet("fec1::1", &bits);
+       verify_address(host, addr_v6, AF_INET6, 0);
+       ck_assert_int_eq(bits, 128);
+       host->destroy(host);
+
+       host = host_create_from_subnet("fec1::1/64", &bits);
+       verify_address(host, addr_v6, AF_INET6, 0);
+       ck_assert_int_eq(bits, 64);
+       host->destroy(host);
+
+       host = host_create_from_subnet("foo::bar", &bits);
+       ck_assert(host == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * host_create_netmask
+ */
+
+static void test_create_netmask(int family)
+{
+       host_t *netmask;
+       int i, len = (family == AF_INET) ? 32 : 128;
+
+       netmask = host_create_netmask(family, -1);
+       ck_assert(netmask == NULL);
+       for (i = 0; i <= len; i++)
+       {
+               netmask = host_create_netmask(family, i);
+               verify_netmask(netmask->get_address(netmask), i);
+               netmask->destroy(netmask);
+       }
+       netmask = host_create_netmask(family, len + 1);
+       ck_assert(netmask == NULL);
+}
+
+START_TEST(test_create_netmask_v4)
+{
+       test_create_netmask(AF_INET);
+}
+END_TEST
+
+START_TEST(test_create_netmask_v6)
+{
+       test_create_netmask(AF_INET6);
+}
+END_TEST
+
+START_TEST(test_create_netmask_other)
+{
+       host_t *netmask;
+
+       netmask = host_create_netmask(AF_UNSPEC, 0);
+       ck_assert(netmask == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * equals, ip_equals
+ */
+
+START_TEST(test_equals)
+{
+       host_t *a, *b;
+
+       a = host_create_from_string("192.168.0.1", 500);
+       b = host_create_from_string("192.168.0.1", 0);
+       ck_assert(!a->equals(a, b));
+       ck_assert(!b->equals(b, a));
+       ck_assert(a->ip_equals(a, b));
+       ck_assert(b->ip_equals(b, a));
+       b->set_port(b, 500);
+       ck_assert(a->equals(a, b));
+       ck_assert(b->equals(b, a));
+       ck_assert(a->ip_equals(a, b));
+       ck_assert(b->ip_equals(b, a));
+       b->destroy(b);
+       b = host_create_from_string("192.168.0.2", 500);
+       ck_assert(!a->ip_equals(a, b));
+       ck_assert(!a->equals(a, b));
+       b->destroy(b);
+
+       b = host_create_from_string("fec1::1", 500);
+       ck_assert(!a->ip_equals(a, b));
+       ck_assert(!a->equals(a, b));
+       a->destroy(a);
+       a = host_create_from_string("fec1::1", 500);
+       ck_assert(a->equals(a, b));
+       ck_assert(a->ip_equals(a, b));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_equals_any)
+{
+       host_t *a, *b;
+
+       a = host_create_from_string("%any", 500);
+       b = host_create_from_string("%any", 0);
+       ck_assert(!a->equals(a, b));
+       ck_assert(a->ip_equals(a, b));
+       b->set_port(b, 500);
+       ck_assert(a->equals(a, b));
+       ck_assert(a->ip_equals(a, b));
+       b->destroy(b);
+       b = host_create_from_string("%any6", 0);
+       ck_assert(a->ip_equals(a, b));
+       ck_assert(!a->equals(a, b));
+       b->set_port(b, 500);
+       ck_assert(a->ip_equals(a, b));
+       ck_assert(a->equals(a, b));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+/*******************************************************************************
+ * clone
+ */
+
+START_TEST(test_clone)
+{
+       host_t *a, *b;
+
+       a = host_create_from_string("192.168.0.1", 500);
+       b = a->clone(a);
+       ck_assert(a != b);
+       ck_assert(a->equals(a, b));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+/*******************************************************************************
+ * printf hook
+ */
+
+static struct {
+       char *addr;
+       u_int16_t port;
+       /* results for %H, %+H, %#H (falls back to [0]) */
+       char *result[3];
+} printf_data[] = {
+       {NULL,          0, { "(null)" }},
+       {NULL,        500, { "(null)" }},
+       {"%any",        0, { "%any", "0.0.0.0", "0.0.0.0[0]" }},
+       {"%any",      500, { "%any", "0.0.0.0", "0.0.0.0[500]" }},
+       {"%any6",       0, { "%any6", "::", "::[0]" }},
+       {"%any6",     500, { "%any6", "::", "::[500]" }},
+       {"192.168.0.1",   0, { "192.168.0.1", "192.168.0.1", "192.168.0.1[0]" }},
+       {"192.168.0.1", 500, { "192.168.0.1", "192.168.0.1", "192.168.0.1[500]" }},
+       {"fec1::1",     0, { "fec1::1", "fec1::1", "fec1::1[0]" }},
+       {"fec1::1",   500, { "fec1::1", "fec1::1", "fec1::1[500]" }},
+};
+
+static void verify_printf(host_t *host, const char *format, char *expected)
+{
+       char buf[64];
+
+       snprintf(buf, sizeof(buf), format, host);
+       ck_assert_str_eq(expected, buf);
+}
+
+START_TEST(test_printf_hook)
+{
+       static const char *formats[] = { "%H", "%+H", "%#H" };
+       host_t *host = NULL;
+       char *expected;
+       int i;
+
+       if (printf_data[_i].addr)
+       {
+               host = host_create_from_string(printf_data[_i].addr,
+                                                                          printf_data[_i].port);
+       }
+       for (i = 0; i < countof(formats); i++)
+       {
+               expected = printf_data[_i].result[i];
+               expected = expected ?: printf_data[_i].result[0];
+               verify_printf(host, formats[i], expected);
+       }
+       DESTROY_IF(host);
+}
+END_TEST
+
+START_TEST(test_printf_hook_align)
+{
+       host_t *host;
+
+       verify_printf(NULL, "%14H", "        (null)");
+       verify_printf(NULL, "%-14H", "(null)        ");
+
+       host = host_create_from_string("192.168.0.1", 0);
+       verify_printf(host, "%14H", "   192.168.0.1");
+       verify_printf(host, "%-14H", "192.168.0.1   ");
+       verify_printf(host, "%4H", "192.168.0.1");
+       verify_printf(host, "%-4H", "192.168.0.1");
+       host->destroy(host);
+}
+END_TEST
+
+Suite *host_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("host");
+
+       tc = tcase_create("host_create_any");
+       tcase_add_test(tc, test_create_any_v4);
+       tcase_add_test(tc, test_create_any_v6);
+       tcase_add_test(tc, test_create_any_other);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_from_string");
+       tcase_add_test(tc, test_create_from_string_v4);
+       tcase_add_test(tc, test_create_from_string_any_v6);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_from_string_and_family");
+       tcase_add_test(tc, test_create_from_string_and_family_v4);
+       tcase_add_test(tc, test_create_from_string_and_family_v6);
+       tcase_add_test(tc, test_create_from_string_and_family_other);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_from_sockaddr");
+       tcase_add_test(tc, test_create_from_sockaddr_v4);
+       tcase_add_test(tc, test_create_from_sockaddr_v6);
+       tcase_add_test(tc, test_create_from_sockaddr_other);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_from_chunk");
+       tcase_add_test(tc, test_create_from_chunk_v4);
+       tcase_add_test(tc, test_create_from_chunk_v6);
+       tcase_add_test(tc, test_create_from_chunk_other);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_from_subnet");
+       tcase_add_test(tc, test_create_from_subnet_v4);
+       tcase_add_test(tc, test_create_from_subnet_v6);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("host_create_netmask");
+       tcase_add_test(tc, test_create_netmask_v4);
+       tcase_add_test(tc, test_create_netmask_v6);
+       tcase_add_test(tc, test_create_netmask_other);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("equals, ip_equals");
+       tcase_add_test(tc, test_equals);
+       tcase_add_test(tc, test_equals_any);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("clone");
+       tcase_add_test(tc, test_clone);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("printf hook");
+       tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_data));
+       tcase_add_test(tc, test_printf_hook_align);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_identification.c b/src/libstrongswan/tests/suites/test_identification.c
new file mode 100644 (file)
index 0000000..1dc6776
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <utils/identification.h>
+
+/*******************************************************************************
+ * create (_from_encoding, _from_data, _from_string, _from_sockaddr)
+ */
+
+START_TEST(test_from_encoding)
+{
+       identification_t *a;
+       chunk_t expected, encoding;
+
+       /* only ID_ANY is handled differently, for all other types the following
+        * applies.  should we perhaps test that this is in fact the case? */
+       expected = chunk_from_str("moon@strongswan.org");
+       a = identification_create_from_encoding(ID_RFC822_ADDR, expected);
+       ck_assert(ID_RFC822_ADDR == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(expected.ptr != encoding.ptr);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+
+       a = identification_create_from_encoding(ID_ANY, expected);
+       ck_assert(ID_ANY == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(encoding.ptr == NULL);
+       ck_assert(encoding.len == 0);
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_from_data)
+{
+       identification_t *a;
+       chunk_t expected, encoding;
+
+       /* this uses the DN parser (C=CH) */
+       expected = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
+                                                               0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48);
+       a = identification_create_from_data(expected);
+       ck_assert(ID_DER_ASN1_DN == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(expected.ptr != encoding.ptr);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+
+       /* everything else is handled by the string parser */
+       expected = chunk_from_str("moon@strongswan.org");
+       a = identification_create_from_data(expected);
+       ck_assert(ID_RFC822_ADDR == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(expected.ptr != encoding.ptr);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_from_sockaddr)
+{
+       identification_t *a;
+       chunk_t expected, encoding;
+       struct sockaddr_in in = {
+               .sin_family = AF_INET,
+       };
+       struct sockaddr_in6 in6 = {
+               .sin6_family = AF_INET6,
+       };
+
+       expected = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01);
+       memcpy(&in.sin_addr, expected.ptr, sizeof(in.sin_addr));
+       a = identification_create_from_sockaddr((sockaddr_t*)&in);
+       ck_assert(ID_IPV4_ADDR == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+
+       expected = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
+       memcpy(&in6.sin6_addr, expected.ptr, sizeof(in6.sin6_addr));
+       a = identification_create_from_sockaddr((sockaddr_t*)&in6);
+       ck_assert(ID_IPV6_ADDR == a->get_type(a));
+       encoding = a->get_encoding(a);
+       ck_assert(chunk_equals(expected, encoding));
+       a->destroy(a);
+
+       in6.sin6_family = AF_UNSPEC;
+       a = identification_create_from_sockaddr((sockaddr_t*)&in6);
+       ck_assert(ID_ANY == a->get_type(a));
+       a->destroy(a);
+}
+END_TEST
+
+static struct {
+       char *id;
+       id_type_t type;
+       struct {
+               enum {
+                       ENC_CHUNK,
+                       ENC_STRING,
+                       ENC_SIMPLE,
+               } type;
+               union {
+                       chunk_t c;
+                       char *s;
+               } data;
+       } result;
+} string_data[] = {
+       {NULL,      ID_ANY,  { .type = ENC_CHUNK }},
+       {"",        ID_ANY,  { .type = ENC_CHUNK }},
+       {"%any",    ID_ANY,  { .type = ENC_CHUNK }},
+       {"%any6",   ID_ANY,  { .type = ENC_CHUNK }},
+       {"0.0.0.0", ID_ANY,  { .type = ENC_CHUNK }},
+       {"0::0",    ID_ANY,  { .type = ENC_CHUNK }},
+       {"::",      ID_ANY,  { .type = ENC_CHUNK }},
+       {"*",       ID_ANY,  { .type = ENC_CHUNK }},
+       {"any",     ID_FQDN, { .type = ENC_SIMPLE }},
+       {"any6",    ID_FQDN, { .type = ENC_SIMPLE }},
+       {"0",       ID_FQDN, { .type = ENC_SIMPLE }},
+       {"**",      ID_FQDN, { .type = ENC_SIMPLE }},
+       {"192.168.1.1", ID_IPV4_ADDR, { .type = ENC_CHUNK,
+                                                                       .data.c = chunk_from_chars(0xc0, 0xa8, 0x01, 0x01) }},
+       {"192.168.",ID_FQDN, { .type = ENC_SIMPLE }},
+       {".",       ID_FQDN, { .type = ENC_SIMPLE }},
+       {"fec0::1", ID_IPV6_ADDR, { .type = ENC_CHUNK,
+                                                               .data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01) }},
+       {"fec0::",  ID_IPV6_ADDR, { .type = ENC_CHUNK,
+                                                               .data.c = chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                                                                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) }},
+       {"fec0:",   ID_KEY_ID,    { .type = ENC_SIMPLE }},
+       {":",       ID_KEY_ID,    { .type = ENC_SIMPLE }},
+       {"alice@strongswan.org", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
+       {"alice@strongswan", ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
+       {"alice@",  ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
+       {"alice",   ID_FQDN, { .type = ENC_SIMPLE }},
+       {"@",       ID_FQDN, { .type = ENC_CHUNK }},
+       {" @",      ID_RFC822_ADDR, { .type = ENC_SIMPLE }},
+       {"@strongswan.org",  ID_FQDN, { .type = ENC_STRING,
+                                                                       .data.s = "strongswan.org" }},
+       {"@#deadbeef", ID_KEY_ID, { .type = ENC_CHUNK,
+                                                               .data.c = chunk_from_chars(0xde, 0xad, 0xbe, 0xef) }},
+       {"@#deadbee",  ID_KEY_ID, { .type = ENC_CHUNK,
+                                                               .data.c = chunk_from_chars(0x0d, 0xea, 0xdb, 0xee) }},
+       {"foo=bar",    ID_KEY_ID, { .type = ENC_SIMPLE }},
+       {"foo=",           ID_KEY_ID, { .type = ENC_SIMPLE }},
+       {"=bar",           ID_KEY_ID, { .type = ENC_SIMPLE }},
+       {"C=",             ID_DER_ASN1_DN, { .type = ENC_CHUNK,
+                                                                        .data.c = chunk_from_chars(0x30, 0x0b, 0x31, 0x09, 0x30, 0x07, 0x06,
+                                                                                                                               0x03, 0x55, 0x04, 0x06, 0x13, 0x00)}},
+       {"C=CH",           ID_DER_ASN1_DN, { .type = ENC_CHUNK,
+                                                                        .data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
+                                                                                                                               0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
+       {"C=CH,",          ID_DER_ASN1_DN, { .type = ENC_CHUNK,
+                                                                        .data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
+                                                                                                                               0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
+       {"C=CH, ",         ID_DER_ASN1_DN, { .type = ENC_CHUNK,
+                                                                        .data.c = chunk_from_chars(0x30, 0x0d, 0x31, 0x0b, 0x30, 0x09, 0x06,
+                                                                                                                               0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48)}},
+       {"C=CH, O",        ID_KEY_ID, { .type = ENC_SIMPLE }},
+};
+
+START_TEST(test_from_string)
+{
+       identification_t *a;
+       chunk_t encoding, expected;
+       char *id;
+
+       id = string_data[_i].id;
+       a = identification_create_from_string(id);
+       fail_unless(a->get_type(a) == string_data[_i].type,
+                               "type of id '%s' is %N, %N expected", id,
+                               id_type_names, a->get_type(a),
+                               id_type_names, string_data[_i].type);
+
+       encoding = a->get_encoding(a);
+       switch (string_data[_i].result.type)
+       {
+               case ENC_SIMPLE:
+                       expected = chunk_from_str(string_data[_i].id);
+                       break;
+               case ENC_STRING:
+                       expected = chunk_from_str(string_data[_i].result.data.s);
+                       break;
+               case ENC_CHUNK:
+                       expected = string_data[_i].result.data.c;
+                       break;
+               default:
+                       fail("unexpected result type");
+       }
+
+       ck_assert(!id || (char*)encoding.ptr != id);
+       if (expected.ptr)
+       {
+               fail_unless(chunk_equals(encoding, expected),
+                                       "parsing '%s' failed\nencoding %B\nexpected %B\n",
+                                       id, &encoding, &expected);
+       }
+       else
+       {
+               ck_assert(encoding.ptr == NULL);
+               ck_assert(encoding.len == 0);
+       }
+       a->destroy(a);
+}
+END_TEST
+
+/*******************************************************************************
+ * printf_hook
+ */
+
+static void string_equals(char *a_str, char *b_str)
+{
+       identification_t *b;
+       char buf[128];
+
+       b = b_str ? identification_create_from_string(b_str) : NULL;
+       snprintf(buf, sizeof(buf), "%Y", b);
+       DESTROY_IF(b);
+       ck_assert_str_eq(a_str, buf);
+}
+
+static void string_equals_id(char *a_str, identification_t *b)
+{
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%Y", b);
+       DESTROY_IF(b);
+       ck_assert_str_eq(a_str, buf);
+}
+
+START_TEST(test_printf_hook)
+{
+       string_equals("(null)", NULL);
+       string_equals("%any", "");
+       string_equals("%any", "%any");
+       string_equals("%any", "*");
+
+       string_equals("192.168.1.1", "192.168.1.1");
+       string_equals_id("(invalid ID_IPV4_ADDR)",
+                               identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
+       string_equals("fec0::1", "fec0::1");
+       string_equals("fec0::1", "fec0:0:0::1");
+       string_equals_id("(invalid ID_IPV6_ADDR)",
+                               identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
+
+       string_equals_id("(unknown ID type: 255)",
+                               identification_create_from_encoding(255, chunk_empty));
+
+       string_equals("moon@strongswan.org", "moon@strongswan.org");
+       string_equals("MOON@STRONGSWAN.ORG", "MOON@STRONGSWAN.ORG");
+       /* non-printable characters */
+       string_equals_id("????@strongswan.org", identification_create_from_encoding(ID_RFC822_ADDR,
+                       chunk_from_chars(0xfa, 0xfb, 0xfc, 0xfd, 0x40, 0x73, 0x74, 0x72,
+                                                        0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
+                                                        0x6f, 0x72, 0x67)));
+
+       /* not a DN => ID_KEY_ID => no normalization */
+       string_equals("C=CH, AsdF=asdf", "C=CH, AsdF=asdf");
+       string_equals_id("moon@strongswan.org", identification_create_from_encoding(ID_KEY_ID,
+                       chunk_from_str("moon@strongswan.org")));
+       /* non-printable characters */
+       string_equals_id("de:ad:be:ef", identification_create_from_encoding(ID_KEY_ID,
+                       chunk_from_chars(0xde, 0xad, 0xbe, 0xef)));
+       /* printable characters */
+       string_equals_id("ABCDEFGHIJKLMNOPQRS",
+               identification_create_from_encoding(ID_KEY_ID,
+                       chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+                                                        0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+                                                        0x51, 0x52, 0x53)));
+       /* ABCDEFGHIJKLMNOPQRST is printable but has the length of a SHA1 hash */
+       string_equals_id("41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54",
+               identification_create_from_encoding(ID_KEY_ID,
+                       chunk_from_chars(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+                                                        0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+                                                        0x51, 0x52, 0x53, 0x54)));
+
+       string_equals_id("", identification_create_from_encoding(ID_DER_ASN1_DN, chunk_empty));
+       string_equals("C=", "C=");
+       string_equals("C=", "C=,");
+       string_equals("C=", "C=, ");
+       string_equals("C=", "C= , ");
+       string_equals("C=, O=strongSwan", "C=, O=strongSwan");
+       string_equals("C=CH, O=", "C=CH, O=");
+       string_equals("C=CH, O=strongSwan, CN=strongswan.org",
+                                 "C=CH, O=strongSwan, CN=strongswan.org");
+       string_equals("CN=strongswan.org, O=strongSwan, C=CH",
+                                 "cn=strongswan.org, o=strongSwan, c=CH");
+       string_equals("C=CH, O=strongSwan, CN=strongswan.org",
+                                 "C=CH,O=strongSwan,CN=strongswan.org");
+       string_equals("C=CH, O=strongSwan, CN=strongswan.org",
+                                 "/C=CH/O=strongSwan/CN=strongswan.org");
+       string_equals("CN=strongswan.org, O=strongSwan, C=CH",
+                                 "CN=strongswan.org,O=strongSwan,C=CH");
+
+       string_equals("C=CH, E=moon@strongswan.org, CN=moon",
+                                 "C=CH, email=moon@strongswan.org, CN=moon");
+       string_equals("C=CH, E=moon@strongswan.org, CN=moon",
+                                 "C=CH, emailAddress=moon@strongswan.org, CN=moon");
+
+       /* C=CH, pseudonym=ANO (pseudonym is currently not recognized) */
+       string_equals_id("C=CH, 55:04:41=ANO", identification_create_from_encoding(ID_DER_ASN1_DN,
+               chunk_from_chars(0x30, 0x19, 0x31, 0x17, 0x30, 0x09, 0x06, 0x03, 0x55,
+                                                0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x0a, 0x06,
+                                                0x03, 0x55, 0x04, 0x41, 0x13, 0x03, 0x41, 0x4e, 0x4f)));
+       /* C=CH, O=strongSwan (but instead of a 2nd OID -0x06- we got NULL -0x05) */
+       string_equals_id("C=CH, (invalid ID_DER_ASN1_DN)", identification_create_from_encoding(ID_DER_ASN1_DN,
+               chunk_from_chars(0x30, 0x20, 0x31, 0x1e, 0x30, 0x09, 0x06, 0x03, 0x55,
+                                                0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x11, 0x05,
+                                                0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x73, 0x74, 0x72,
+                                                0x6f, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x6e)));
+       /* moon@strongswan.org as GN */
+       string_equals_id("(ASN.1 general name)", identification_create_from_encoding(ID_DER_ASN1_GN,
+               chunk_from_chars(0x81, 0x14, 0x6d, 0x6f, 0x6f, 0x6e, 0x40, 0x73, 0x74,
+                                                0x72, 0x6f, 0x6e, 0x67, 0x73, 0x77, 0x61, 0x6e, 0x2e,
+                                                0x6f, 0x72, 0x67)));
+}
+END_TEST
+
+START_TEST(test_printf_hook_width)
+{
+       identification_t *a;
+       char buf[128];
+
+       a = identification_create_from_string("moon@strongswan.org");
+       snprintf(buf, sizeof(buf), "%25Y", a);
+       ck_assert_str_eq("      moon@strongswan.org", buf);
+       snprintf(buf, sizeof(buf), "%-*Y", 25, a);
+       ck_assert_str_eq("moon@strongswan.org      ", buf);
+       snprintf(buf, sizeof(buf), "%5Y", a);
+       ck_assert_str_eq("moon@strongswan.org", buf);
+       DESTROY_IF(a);
+}
+END_TEST
+
+/*******************************************************************************
+ * equals
+ */
+
+static bool id_equals(identification_t *a, char *b_str)
+{
+       identification_t *b;
+       bool equals;
+
+       b = identification_create_from_string(b_str);
+       equals = a->equals(a, b);
+       ck_assert_int_eq(equals, b->equals(b, a));
+       b->destroy(b);
+       return equals;
+}
+
+START_TEST(test_equals)
+{
+       identification_t *a;
+       chunk_t encoding, fuzzed;
+       int i;
+
+       /* this test also tests identification_create_from_string with DNs */
+       a = identification_create_from_string(
+                                                        "C=CH, E=moon@strongswan.org, CN=moon");
+
+       ck_assert(id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
+       ck_assert(id_equals(a, "C==CH, E==moon@strongswan.org,,, CN==moon"));
+       ck_assert(id_equals(a, "  C=CH, E=moon@strongswan.org, CN=moon  "));
+       ck_assert(id_equals(a, "C=ch, E=moon@STRONGSWAN.ORG, CN=Moon"));
+       ck_assert(id_equals(a, "/C=CH/E=moon@strongswan.org/CN=moon"));
+       ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org/CN=moon"));
+       ck_assert(id_equals(a, "C=CH/E=moon@strongswan.org,CN=moon"));
+       ck_assert(id_equals(a, "C=CH / E=moon@strongswan.org , CN=moon"));
+
+       ck_assert(!id_equals(a, "C=CH E=moon@strongswan.org CN=moon"));
+       ck_assert(!id_equals(a, "C=CN, E=moon@strongswan.org, CN=moon"));
+       ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
+       ck_assert(!id_equals(a, "E=moon@strongswan.org, C=CH, CN=moon"));
+
+       encoding = chunk_clone(a->get_encoding(a));
+       a->destroy(a);
+
+       /* simple fuzzing, increment each byte of encoding */
+       for (i = 0; i < encoding.len; i++)
+       {
+               if (i == 11 || i == 30 || i == 60)
+               {       /* skip ASN.1 type fields, as equals() handles them graceful */
+                       continue;
+               }
+               fuzzed = chunk_clone(encoding);
+               fuzzed.ptr[i]++;
+               a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
+               if (id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"))
+               {
+                       printf("%d %B\n%B\n", i, &fuzzed, &encoding);
+               }
+               ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
+               a->destroy(a);
+               free(fuzzed.ptr);
+       }
+
+       /* and decrement each byte of encoding */
+       for (i = 0; i < encoding.len; i++)
+       {
+               if (i == 11 || i == 30 || i == 60)
+               {
+                       continue;
+               }
+               fuzzed = chunk_clone(encoding);
+               fuzzed.ptr[i]--;
+               a = identification_create_from_encoding(ID_DER_ASN1_DN, fuzzed);
+               ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
+               a->destroy(a);
+               free(fuzzed.ptr);
+       }
+       free(encoding.ptr);
+}
+END_TEST
+
+START_TEST(test_equals_any)
+{
+       identification_t *a, *b;
+
+       a = identification_create_from_string("%any");
+       b = identification_create_from_encoding(ID_ANY, chunk_empty);
+       ck_assert(a->equals(a, b));
+       ck_assert(b->equals(b, a));
+       b->destroy(b);
+
+       b = identification_create_from_string("C=CH, O=strongSwan, CN=strongswan.org");
+       ck_assert(!a->equals(a, b));
+       ck_assert(!b->equals(b, a));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_equals_binary)
+{
+       identification_t *a, *b;
+       chunk_t encoding;
+
+       encoding = chunk_from_str("foobar=");
+       /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
+       a = identification_create_from_string("foobar=");
+       ck_assert(a->get_type(a) == ID_KEY_ID);
+       b = identification_create_from_encoding(ID_KEY_ID, encoding);
+       ck_assert(a->equals(a, b));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_equals_fqdn)
+{
+       identification_t *a;
+
+       a = identification_create_from_string("ipsec.strongswan.org");
+       ck_assert(id_equals(a, "IPSEC.strongswan.org"));
+       ck_assert(id_equals(a, "ipsec.strongSwan.org"));
+       ck_assert(id_equals(a, "ipsec.strongSwan.ORG"));
+       ck_assert(!id_equals(a, "strongswan.org"));
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_equals_empty)
+{
+       identification_t *a;
+
+       a = identification_create_from_encoding(_i, chunk_empty);
+
+       switch (_i)
+       {
+               case ID_ANY:
+                       ck_assert(id_equals(a, "%any"));
+                       break;
+               case ID_IPV4_ADDR:
+                       ck_assert(!id_equals(a, "192.168.1.1"));
+                       break;
+               case ID_FQDN:
+                       ck_assert(!id_equals(a, "moon.strongswan.org"));
+                       break;
+               case ID_USER_FQDN:
+                       ck_assert(!id_equals(a, "moon@strongswan.org"));
+                       break;
+               case ID_IPV6_ADDR:
+                       ck_assert(!id_equals(a, "fec0::1"));
+                       break;
+               case ID_DER_ASN1_DN:
+                       ck_assert(!id_equals(a, "C=CH, E=moon@strongswan.org, CN=moon"));
+                       break;
+               case ID_KEY_ID:
+                       ck_assert(!id_equals(a, "@#12345678"));
+                       break;
+               case ID_DER_ASN1_GN:
+               case ID_IPV4_ADDR_SUBNET:
+               case ID_IPV6_ADDR_SUBNET:
+               case ID_IPV4_ADDR_RANGE:
+               case ID_IPV6_ADDR_RANGE:
+                       /* currently not tested */
+                       break;
+       }
+
+       a->destroy(a);
+}
+END_TEST
+
+/*******************************************************************************
+ * matches
+ */
+
+static bool id_matches(identification_t *a, char *b_str, id_match_t expected)
+{
+       identification_t *b;
+       id_match_t match;
+
+       b = identification_create_from_string(b_str);
+       match = a->matches(a, b);
+       b->destroy(b);
+       return match == expected;
+}
+
+START_TEST(test_matches)
+{
+       identification_t *a;
+
+       a = identification_create_from_string("C=CH, E=moon@strongswan.org, CN=moon");
+
+       ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon", ID_MATCH_PERFECT));
+       ck_assert(id_matches(a, "C=CH, E=*, CN=moon", ID_MATCH_ONE_WILDCARD));
+       ck_assert(id_matches(a, "C=CH, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 1));
+       ck_assert(id_matches(a, "C=*, E=*, CN=*", ID_MATCH_ONE_WILDCARD - 2));
+       ck_assert(id_matches(a, "C=*, E=*, CN=*, O=BADInc", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "C=*, E=*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "C=*, E=a@b.c, CN=*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_matches_any)
+{
+       identification_t *a;
+
+       a = identification_create_from_string("%any");
+
+       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "*", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_NONE));
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_matches_binary)
+{
+       identification_t *a;
+
+       /* strings containing = are parsed as KEY_ID if they aren't valid ASN.1 DNs */
+       a = identification_create_from_string("foo=bar");
+       ck_assert(a->get_type(a) == ID_KEY_ID);
+       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "foo=bar", ID_MATCH_PERFECT));
+       ck_assert(id_matches(a, "bar=foo", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*=bar", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "foo=*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "foo@bar", ID_MATCH_NONE));
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_matches_string)
+{
+       identification_t *a;
+
+       a = identification_create_from_string("moon@strongswan.org");
+
+       ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_PERFECT));
+       ck_assert(id_matches(a, "*@strongswan.org", ID_MATCH_ONE_WILDCARD));
+       ck_assert(id_matches(a, "*@*.org", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*@*", ID_MATCH_NONE));
+       /* the following two are parsed as ID_FQDN, so no match */
+       ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*.org", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "moon@*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "**", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+       a->destroy(a);
+
+       a = identification_create_from_string("vpn.strongswan.org");
+
+       ck_assert(id_matches(a, "vpn.strongswan.org", ID_MATCH_PERFECT));
+       ck_assert(id_matches(a, "*.strongswan.org", ID_MATCH_ONE_WILDCARD));
+       ck_assert(id_matches(a, "*strongswan.org", ID_MATCH_ONE_WILDCARD));
+       ck_assert(id_matches(a, "*.org", ID_MATCH_ONE_WILDCARD));
+       ck_assert(id_matches(a, "*.strongswan.*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*vpn.strongswan.org", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "vpn.strongswan.*", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "**", ID_MATCH_NONE));
+       ck_assert(id_matches(a, "*", ID_MATCH_ANY));
+       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+       a->destroy(a);
+}
+END_TEST
+
+START_TEST(test_matches_empty)
+{
+       identification_t *a;
+
+       a = identification_create_from_encoding(_i, chunk_empty);
+
+       switch (_i)
+       {
+               case ID_ANY:
+                       ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+                       break;
+               case ID_IPV4_ADDR:
+                       ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_NONE));
+                       break;
+               case ID_FQDN:
+                       ck_assert(id_matches(a, "moon.strongswan.org", ID_MATCH_NONE));
+                       break;
+               case ID_USER_FQDN:
+                       ck_assert(id_matches(a, "moon@strongswan.org", ID_MATCH_NONE));
+                       break;
+               case ID_IPV6_ADDR:
+                       ck_assert(id_matches(a, "fec0::1", ID_MATCH_NONE));
+                       break;
+               case ID_DER_ASN1_DN:
+                       ck_assert(id_matches(a, "C=CH, E=moon@strongswan.org, CN=moon",
+                                                                ID_MATCH_NONE));
+                       break;
+               case ID_KEY_ID:
+                       ck_assert(id_matches(a, "@#12345678", ID_MATCH_NONE));
+                       break;
+               case ID_DER_ASN1_GN:
+               case ID_IPV4_ADDR_SUBNET:
+               case ID_IPV6_ADDR_SUBNET:
+               case ID_IPV4_ADDR_RANGE:
+               case ID_IPV6_ADDR_RANGE:
+                       /* currently not tested */
+                       break;
+       }
+
+       a->destroy(a);
+}
+END_TEST
+
+static bool id_matches_rev(identification_t *a, char *b_str, id_match_t expected)
+{
+       identification_t *b;
+       id_match_t match;
+
+       b = identification_create_from_string(b_str);
+       match = b->matches(b, a);
+       b->destroy(b);
+       return match == expected;
+}
+
+START_TEST(test_matches_empty_reverse)
+{
+       identification_t *a;
+
+       a = identification_create_from_encoding(_i, chunk_empty);
+
+       switch (_i)
+       {
+               case ID_ANY:
+                       ck_assert(id_matches_rev(a, "%any", ID_MATCH_ANY));
+                       break;
+               case ID_IPV4_ADDR:
+                       ck_assert(id_matches_rev(a, "192.168.1.1", ID_MATCH_NONE));
+                       break;
+               case ID_FQDN:
+                       ck_assert(id_matches_rev(a, "moon.strongswan.org", ID_MATCH_NONE));
+                       break;
+               case ID_USER_FQDN:
+                       ck_assert(id_matches_rev(a, "moon@strongswan.org", ID_MATCH_NONE));
+                       break;
+               case ID_IPV6_ADDR:
+                       ck_assert(id_matches_rev(a, "fec0::1", ID_MATCH_NONE));
+                       break;
+               case ID_DER_ASN1_DN:
+                       ck_assert(id_matches_rev(a, "C=CH, E=moon@strongswan.org, CN=moon",
+                                                                        ID_MATCH_NONE));
+                       break;
+               case ID_KEY_ID:
+                       ck_assert(id_matches_rev(a, "@#12345678", ID_MATCH_NONE));
+                       break;
+               case ID_DER_ASN1_GN:
+               case ID_IPV4_ADDR_SUBNET:
+               case ID_IPV6_ADDR_SUBNET:
+               case ID_IPV4_ADDR_RANGE:
+               case ID_IPV6_ADDR_RANGE:
+                       /* currently not tested */
+                       break;
+       }
+
+       a->destroy(a);
+}
+END_TEST
+
+/*******************************************************************************
+ * identification part enumeration
+ */
+
+START_TEST(test_parts)
+{
+       identification_t *id;
+       enumerator_t *enumerator;
+       id_part_t part;
+       chunk_t data;
+       int i = 0;
+
+       id = identification_create_from_string("C=CH, O=strongSwan, CN=tester");
+
+       enumerator = id->create_part_enumerator(id);
+       while (enumerator->enumerate(enumerator, &part, &data))
+       {
+               switch (i++)
+               {
+                       case 0:
+                               ck_assert(part == ID_PART_RDN_C &&
+                                                 chunk_equals(data, chunk_create("CH", 2)));
+                               break;
+                       case 1:
+                               ck_assert(part == ID_PART_RDN_O &&
+                                                 chunk_equals(data, chunk_from_str("strongSwan")));
+                               break;
+                       case 2:
+                               ck_assert(part == ID_PART_RDN_CN &&
+                                                 chunk_equals(data, chunk_from_str("tester")));
+                               break;
+                       default:
+                               fail("unexpected identification part %d", part);
+               }
+       }
+       ck_assert_int_eq(i, 3);
+       enumerator->destroy(enumerator);
+       id->destroy(id);
+}
+END_TEST
+
+/*******************************************************************************
+ * wildcards
+ */
+
+static bool id_contains_wildcards(char *string)
+{
+       identification_t *id;
+       bool contains;
+
+       id = identification_create_from_string(string);
+       contains = id->contains_wildcards(id);
+       id->destroy(id);
+       return contains;
+}
+
+START_TEST(test_contains_wildcards)
+{
+       ck_assert(id_contains_wildcards("%any"));
+       ck_assert(id_contains_wildcards("C=*, O=strongSwan, CN=gw"));
+       ck_assert(id_contains_wildcards("C=CH, O=strongSwan, CN=*"));
+       ck_assert(id_contains_wildcards("*@strongswan.org"));
+       ck_assert(id_contains_wildcards("*.strongswan.org"));
+       ck_assert(!id_contains_wildcards("C=**, O=a*, CN=*a"));
+}
+END_TEST
+
+/*******************************************************************************
+ * clone
+ */
+
+START_TEST(test_clone)
+{
+       identification_t *a, *b;
+       chunk_t a_enc, b_enc;
+
+       a = identification_create_from_string("moon@strongswan.org");
+       a_enc = a->get_encoding(a);
+       b = a->clone(a);
+       ck_assert(b != NULL);
+       ck_assert(a != b);
+       b_enc = b->get_encoding(b);
+       ck_assert(a_enc.ptr != b_enc.ptr);
+       ck_assert(chunk_equals(a_enc, b_enc));
+       a->destroy(a);
+       b->destroy(b);
+}
+END_TEST
+
+Suite *identification_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("identification");
+
+       tc = tcase_create("create");
+       tcase_add_test(tc, test_from_encoding);
+       tcase_add_test(tc, test_from_data);
+       tcase_add_test(tc, test_from_sockaddr);
+       tcase_add_loop_test(tc, test_from_string, 0, countof(string_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("printf_hook");
+       tcase_add_test(tc, test_printf_hook);
+       tcase_add_test(tc, test_printf_hook_width);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("equals");
+       tcase_add_test(tc, test_equals);
+       tcase_add_test(tc, test_equals_any);
+       tcase_add_test(tc, test_equals_binary);
+       tcase_add_test(tc, test_equals_fqdn);
+       tcase_add_loop_test(tc, test_equals_empty, ID_ANY, ID_KEY_ID + 1);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("matches");
+       tcase_add_test(tc, test_matches);
+       tcase_add_test(tc, test_matches_any);
+       tcase_add_test(tc, test_matches_binary);
+       tcase_add_test(tc, test_matches_string);
+       tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
+       tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("part enumeration");
+       tcase_add_test(tc, test_parts);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("wildcards");
+       tcase_add_test(tc, test_contains_wildcards);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("clone");
+       tcase_add_test(tc, test_clone);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_linked_list.c b/src/libstrongswan/tests/suites/test_linked_list.c
new file mode 100644 (file)
index 0000000..9e85c58
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <collections/linked_list.h>
+
+/*******************************************************************************
+ * test fixture
+ */
+
+static linked_list_t *list;
+
+START_SETUP(setup_list)
+{
+       void *x = NULL;
+
+       list = linked_list_create();
+       ck_assert_int_eq(list->get_count(list), 0);
+       ck_assert(list->get_first(list, &x) == NOT_FOUND);
+       ck_assert(list->get_last(list, &x) == NOT_FOUND);
+}
+END_SETUP
+
+START_TEARDOWN(teardown_list)
+{
+       list->destroy(list);
+}
+END_TEARDOWN
+
+/*******************************************************************************
+ * insert first/last
+ */
+
+START_TEST(test_insert_first)
+{
+       void *a = (void*)1, *b = (void*)2, *x = NULL;
+
+       list->insert_first(list, a);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(list->get_first(list, &x) == SUCCESS);
+       ck_assert(x == a);
+       ck_assert(list->get_last(list, &x) == SUCCESS);
+       ck_assert(x == a);
+
+       list->insert_first(list, b);
+       ck_assert_int_eq(list->get_count(list), 2);
+       ck_assert(list->get_first(list, &x) == SUCCESS);
+       ck_assert(x == b);
+       ck_assert(list->get_last(list, &x) == SUCCESS);
+       ck_assert(x == a);
+}
+END_TEST
+
+START_TEST(test_insert_last)
+{
+       void *a = (void*)1, *b = (void*)2, *x = NULL;
+
+       list->insert_last(list, a);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(list->get_first(list, &x) == SUCCESS);
+       ck_assert(x == a);
+       ck_assert(list->get_last(list, &x) == SUCCESS);
+       ck_assert(x == a);
+
+       list->insert_last(list, b);
+       ck_assert_int_eq(list->get_count(list), 2);
+       ck_assert(list->get_first(list, &x) == SUCCESS);
+       ck_assert(x == a);
+       ck_assert(list->get_last(list, &x) == SUCCESS);
+       ck_assert(x == b);
+}
+END_TEST
+
+/*******************************************************************************
+ * remove first/last
+ */
+
+START_TEST(test_remove_first)
+{
+       void *a = (void*)1, *b = (void*)2, *x = NULL;
+
+       list->insert_first(list, a);
+       list->insert_first(list, b);
+       ck_assert(list->remove_first(list, &x) == SUCCESS);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(x == b);
+       ck_assert(list->remove_first(list, &x) == SUCCESS);
+       ck_assert_int_eq(list->get_count(list), 0);
+       ck_assert(x == a);
+       ck_assert(list->remove_first(list, &x) == NOT_FOUND);
+       ck_assert(list->remove_last(list, &x) == NOT_FOUND);
+}
+END_TEST
+
+START_TEST(test_remove_last)
+{
+       void *a = (void*)1, *b = (void*)2, *x = NULL;
+
+       list->insert_first(list, a);
+       list->insert_first(list, b);
+       ck_assert(list->remove_last(list, &x) == SUCCESS);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(x == a);
+       ck_assert(list->remove_last(list, &x) == SUCCESS);
+       ck_assert_int_eq(list->get_count(list), 0);
+       ck_assert(x == b);
+       ck_assert(list->remove_first(list, &x) == NOT_FOUND);
+       ck_assert(list->remove_last(list, &x) == NOT_FOUND);
+}
+END_TEST
+
+/*******************************************************************************
+ * helper function for remove and find tests
+ */
+
+static bool match_a(void *item, void *a)
+{
+       ck_assert(a == (void*)1);
+       return item == a;
+}
+
+static bool match_b(void *item, void *b)
+{
+       ck_assert(b == (void*)2);
+       return item == b;
+}
+
+/*******************************************************************************
+ * remove
+ */
+
+START_TEST(test_remove)
+{
+       void *a = (void*)1, *b = (void*)2;
+
+       list->insert_first(list, a);
+       ck_assert(list->remove(list, a, NULL) == 1);
+       ck_assert_int_eq(list->get_count(list), 0);
+
+       list->insert_last(list, a);
+       list->insert_last(list, a);
+       list->insert_last(list, a);
+       list->insert_last(list, b);
+       ck_assert(list->remove(list, a, NULL) == 3);
+       ck_assert(list->remove(list, a, NULL) == 0);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(list->remove(list, b, NULL) == 1);
+       ck_assert(list->remove(list, b, NULL) == 0);
+}
+END_TEST
+
+START_TEST(test_remove_callback)
+{
+       void *a = (void*)1, *b = (void*)2;
+
+       list->insert_last(list, a);
+       list->insert_last(list, b);
+       list->insert_last(list, a);
+       list->insert_last(list, b);
+       ck_assert(list->remove(list, a, match_a) == 2);
+       ck_assert(list->remove(list, a, match_a) == 0);
+       ck_assert_int_eq(list->get_count(list), 2);
+       ck_assert(list->remove(list, b, match_b) == 2);
+       ck_assert(list->remove(list, b, match_b) == 0);
+       ck_assert_int_eq(list->get_count(list), 0);
+}
+END_TEST
+
+/*******************************************************************************
+ * find
+ */
+
+static bool match_a_b(void *item, void *a, void *b)
+{
+       ck_assert(a == (void*)1);
+       ck_assert(b == (void*)2);
+       return item == a || item == b;
+}
+
+START_TEST(test_find)
+{
+       void *a = (void*)1, *b = (void*)2;
+
+       ck_assert(list->find_first(list, NULL, &a) == NOT_FOUND);
+       list->insert_last(list, a);
+       ck_assert(list->find_first(list, NULL, &a) == SUCCESS);
+       ck_assert(list->find_first(list, NULL, &b) == NOT_FOUND);
+       list->insert_last(list, b);
+       ck_assert(list->find_first(list, NULL, &a) == SUCCESS);
+       ck_assert(list->find_first(list, NULL, &b) == SUCCESS);
+
+       ck_assert(list->find_first(list, NULL, NULL) == NOT_FOUND);
+}
+END_TEST
+
+START_TEST(test_find_callback)
+{
+       void *a = (void*)1, *b = (void*)2, *x = NULL;
+
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == NOT_FOUND);
+       list->insert_last(list, a);
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a, NULL, a) == SUCCESS);
+       x = NULL;
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a, &x, a) == SUCCESS);
+       ck_assert(a == x);
+       ck_assert(list->find_first(list, (linked_list_match_t)match_b, &x, b) == NOT_FOUND);
+       ck_assert(a == x);
+       x = NULL;
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == SUCCESS);
+       ck_assert(a == x);
+
+       list->insert_last(list, b);
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a, &x, a) == SUCCESS);
+       ck_assert(a == x);
+       ck_assert(list->find_first(list, (linked_list_match_t)match_b, &x, b) == SUCCESS);
+       ck_assert(b == x);
+       x = NULL;
+       ck_assert(list->find_first(list, (linked_list_match_t)match_a_b, &x, a, b) == SUCCESS);
+       ck_assert(a == x);
+}
+END_TEST
+
+/*******************************************************************************
+ * invoke
+ */
+
+typedef struct invoke_t invoke_t;
+
+struct invoke_t {
+       int val;
+       void (*invoke)(invoke_t *item, void *a, void *b, void *c, void *d, int *sum);
+};
+
+static void invoke(intptr_t item, void *a, void *b, void *c, void *d, int *sum)
+{
+       ck_assert(a == (void*)1);
+       ck_assert(b == (void*)2);
+       ck_assert(c == (void*)3);
+       ck_assert(d == (void*)4);
+       *sum += item;
+}
+
+static void invoke_offset(invoke_t *item, void *a, void *b, void *c, void *d, int *sum)
+{
+       invoke(item->val, a, b, c, d, sum);
+}
+
+START_TEST(test_invoke_function)
+{
+       int sum = 0;
+
+       list->insert_last(list, (void*)1);
+       list->insert_last(list, (void*)2);
+       list->insert_last(list, (void*)3);
+       list->insert_last(list, (void*)4);
+       list->insert_last(list, (void*)5);
+       list->invoke_function(list, (linked_list_invoke_t)invoke, 1, 2, 3, 4, &sum);
+       ck_assert_int_eq(sum, 15);
+}
+END_TEST
+
+START_TEST(test_invoke_offset)
+{
+       invoke_t items[] = {
+               { .val = 1, .invoke = invoke_offset, },
+               { .val = 2, .invoke = invoke_offset, },
+               { .val = 3, .invoke = invoke_offset, },
+               { .val = 4, .invoke = invoke_offset, },
+               { .val = 5, .invoke = invoke_offset, },
+       };
+       int i, sum = 0;
+
+       for (i = 0; i < countof(items); i++)
+       {
+               list->insert_last(list, &items[i]);
+       }
+       list->invoke_offset(list, offsetof(invoke_t, invoke), 1, 2, 3, 4, &sum);
+       ck_assert_int_eq(sum, 15);
+}
+END_TEST
+
+/*******************************************************************************
+ * clone
+ */
+
+typedef struct clone_t clone_t;
+
+struct clone_t {
+       void *val;
+       void *(*clone)(clone_t *item);
+};
+
+static void *clone(clone_t *item)
+{
+       return item->val;
+}
+
+static void test_clone(linked_list_t *list)
+{
+       intptr_t x;
+       int round = 1;
+
+       ck_assert_int_eq(list->get_count(list), 5);
+       while (list->remove_first(list, (void*)&x) == SUCCESS)
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       ck_assert_int_eq(round, 6);
+}
+
+START_TEST(test_clone_offset)
+{
+       linked_list_t *other;
+       clone_t items[] = {
+               { .val = (void*)1, .clone = clone, },
+               { .val = (void*)2, .clone = clone, },
+               { .val = (void*)3, .clone = clone, },
+               { .val = (void*)4, .clone = clone, },
+               { .val = (void*)5, .clone = clone, },
+       };
+       int i;
+
+       for (i = 0; i < countof(items); i++)
+       {
+               list->insert_last(list, &items[i]);
+       }
+       other = list->clone_offset(list, offsetof(clone_t, clone));
+       test_clone(other);
+       other->destroy(other);
+}
+END_TEST
+
+Suite *linked_list_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("linked list");
+
+       tc = tcase_create("insert/get");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_insert_first);
+       tcase_add_test(tc, test_insert_last);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("remove");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_remove_first);
+       tcase_add_test(tc, test_remove_last);
+       tcase_add_test(tc, test_remove);
+       tcase_add_test(tc, test_remove_callback);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("find");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_find);
+       tcase_add_test(tc, test_find_callback);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("invoke");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_invoke_function);
+       tcase_add_test(tc, test_invoke_offset);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("clone");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_clone_offset);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_linked_list_enumerator.c b/src/libstrongswan/tests/suites/test_linked_list_enumerator.c
new file mode 100644 (file)
index 0000000..48d6f40
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <collections/linked_list.h>
+
+/*******************************************************************************
+ * test fixture
+ */
+
+static linked_list_t *list;
+
+START_SETUP(setup_list)
+{
+       list = linked_list_create_with_items((void*)1, (void*)2, (void*)3, (void*)4,
+                                                                        (void*)5, NULL);
+       ck_assert_int_eq(list->get_count(list), 5);
+}
+END_SETUP
+
+START_TEARDOWN(teardown_list)
+{
+       list->destroy(list);
+}
+END_TEARDOWN
+
+/*******************************************************************************
+ * enumeration
+ */
+
+START_TEST(test_enumerate)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       round = 1;
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       ck_assert_int_eq(round, 6);
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_enumerate_null)
+{
+       enumerator_t *enumerator;
+       int round;
+
+       round = 1;
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, NULL))
+       {
+               round++;
+       }
+       ck_assert_int_eq(round, 6);
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_reset_enumerator)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+       }
+       list->reset_enumerator(list, enumerator);
+       round = 1;
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       ck_assert_int_eq(round, 6);
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+/*******************************************************************************
+ * insert before
+ */
+
+START_TEST(test_insert_before)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       round = 1;
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+               if (x == _i)
+               {
+                       list->insert_before(list, enumerator, (void*)6);
+               }
+       }
+       ck_assert_int_eq(list->get_count(list), 6);
+       list->reset_enumerator(list, enumerator);
+       round = 1;
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               if (round == _i && x != _i)
+               {
+                       ck_assert_int_eq(6, x);
+               }
+               else
+               {
+                       ck_assert_int_eq(round, x);
+                       round++;
+               }
+       }
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_insert_before_ends)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       enumerator = list->create_enumerator(list);
+       list->insert_before(list, enumerator, (void*)0);
+       ck_assert_int_eq(list->get_count(list), 6);
+       ck_assert(list->get_first(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 0);
+       round = 0;
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       list->insert_before(list, enumerator, (void*)6);
+       ck_assert_int_eq(list->get_count(list), 7);
+       ck_assert(list->get_last(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 6);
+       ck_assert(!enumerator->enumerate(enumerator, &x));
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_insert_before_empty)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+
+       list->destroy(list);
+       list = linked_list_create();
+       enumerator = list->create_enumerator(list);
+       list->insert_before(list, enumerator, (void*)1);
+       ck_assert_int_eq(list->get_count(list), 1);
+       ck_assert(list->get_first(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 1);
+       ck_assert(list->get_last(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 1);
+       ck_assert(enumerator->enumerate(enumerator, &x));
+       ck_assert_int_eq(x, 1);
+       ck_assert(!enumerator->enumerate(enumerator, NULL));
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+/*******************************************************************************
+ * remove_at
+ */
+
+START_TEST(test_remove_at)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       round = 1;
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               if (round == 2)
+               {
+                       list->remove_at(list, enumerator);
+               }
+               round++;
+       }
+       ck_assert_int_eq(list->get_count(list), 4);
+       list->reset_enumerator(list, enumerator);
+       round = 1;
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               if (round == 2)
+               {       /* skip removed item */
+                       round++;
+               }
+               ck_assert_int_eq(round, x);
+               round++;
+       }
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_remove_at_ends)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+
+       enumerator = list->create_enumerator(list);
+       list->remove_at(list, enumerator);
+       ck_assert_int_eq(list->get_count(list), 5);
+       ck_assert(list->get_first(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 1);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+       }
+       list->remove_at(list, enumerator);
+       ck_assert_int_eq(list->get_count(list), 5);
+       ck_assert(list->get_last(list, (void*)&x) == SUCCESS);
+       ck_assert_int_eq(x, 5);
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_insert_before_remove_at)
+{
+       enumerator_t *enumerator;
+       intptr_t x;
+       int round;
+
+       round = 1;
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               ck_assert_int_eq(round, x);
+               if (round == 2)
+               {       /* this replaces the current item, as insert_before does not change
+                        * the enumerator position */
+                       list->insert_before(list, enumerator, (void*)42);
+                       list->remove_at(list, enumerator);
+               }
+               else if (round == 4)
+               {       /* this does not replace the item, as remove_at moves the enumerator
+                        * position to the previous item */
+                       list->remove_at(list, enumerator);
+                       list->insert_before(list, enumerator, (void*)21);
+               }
+               round++;
+       }
+       ck_assert_int_eq(list->get_count(list), 5);
+       list->reset_enumerator(list, enumerator);
+       round = 1;
+       while (enumerator->enumerate(enumerator, &x))
+       {
+               if (round == 2)
+               {       /* check replaced item */
+                       ck_assert_int_eq(42, x);
+               }
+               else if (round == 3)
+               {       /* check misplaced item */
+                       ck_assert_int_eq(21, x);
+               }
+               else if (round == 4)
+               {       /* check misplaced item */
+                       ck_assert_int_eq(3, x);
+               }
+               else
+               {
+                       ck_assert_int_eq(round, x);
+               }
+               round++;
+       }
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
+/*******************************************************************************
+ * create list from enumerator
+ */
+
+START_TEST(test_create_from_enumerator)
+{
+       enumerator_t *enumerator, *enumerator_other;
+       linked_list_t *other;
+       intptr_t x, y;
+       int count = 0;
+
+       enumerator = list->create_enumerator(list);
+       other = linked_list_create_from_enumerator(enumerator);
+       ck_assert_int_eq(other->get_count(list), 5);
+
+       enumerator = list->create_enumerator(list);
+       enumerator_other = other->create_enumerator(other);
+       while (enumerator->enumerate(enumerator, &x) &&
+                  enumerator_other->enumerate(enumerator_other, &y))
+       {
+               ck_assert_int_eq(x, y);
+               count++;
+       }
+       ck_assert_int_eq(count, 5);
+       enumerator_other->destroy(enumerator_other);
+       enumerator->destroy(enumerator);
+       other->destroy(other);
+}
+END_TEST
+
+Suite *linked_list_enumerator_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("linked list and enumerators");
+
+       tc = tcase_create("enumerate");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_enumerate);
+       tcase_add_test(tc, test_enumerate_null);
+       tcase_add_test(tc, test_reset_enumerator);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("insert_before()");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_loop_test(tc, test_insert_before, 1, 5);
+       tcase_add_test(tc, test_insert_before_ends);
+       tcase_add_test(tc, test_insert_before_empty);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("modify");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_remove_at);
+       tcase_add_test(tc, test_remove_at_ends);
+       tcase_add_test(tc, test_insert_before_remove_at);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("create_from_enumerator");
+       tcase_add_checked_fixture(tc, setup_list, teardown_list);
+       tcase_add_test(tc, test_create_from_enumerator);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_pen.c b/src/libstrongswan/tests/suites/test_pen.c
new file mode 100644 (file)
index 0000000..a6cbc9a
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+
+#include "test_suite.h"
+
+#include <pen/pen.h>
+
+/*******************************************************************************
+ * create
+ */
+
+START_TEST(test_pen_type_create)
+{
+       pen_type_t ita_1 = pen_type_create(PEN_ITA, 100);
+
+       ck_assert(ita_1.vendor_id == PEN_ITA);
+       ck_assert(ita_1.type == 100);
+}
+END_TEST
+
+/*******************************************************************************
+ * equals
+ */
+
+START_TEST(test_pen_type_equals)
+{
+       pen_type_t ita_1 = pen_type_create(PEN_ITA, 100);
+       pen_type_t ita_2 = pen_type_create(PEN_ITA, 200);
+       pen_type_t fhh_1 = pen_type_create(PEN_FHH, 100);
+       pen_type_t fhh_2 = pen_type_create(PEN_FHH, 200);
+
+       ck_assert( pen_type_equals(ita_1, ita_1));
+       ck_assert(!pen_type_equals(ita_1, ita_2));
+       ck_assert(!pen_type_equals(ita_1, fhh_1));
+       ck_assert(!pen_type_equals(ita_1, fhh_2));
+}
+END_TEST
+
+/*******************************************************************************
+ * is
+ */
+
+START_TEST(test_pen_type_is)
+{
+       pen_type_t ita_1 = pen_type_create(PEN_ITA, 100);
+
+       ck_assert( pen_type_is(ita_1, PEN_ITA, 100));
+       ck_assert(!pen_type_is(ita_1, PEN_ITA, 200));
+       ck_assert(!pen_type_is(ita_1, PEN_FHH, 100));
+       ck_assert(!pen_type_is(ita_1, PEN_FHH, 200));
+}
+END_TEST
+
+Suite *pen_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("pen");
+
+       tc = tcase_create("create");
+       tcase_add_test(tc, test_pen_type_create);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("equals");
+       tcase_add_test(tc, test_pen_type_equals);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("is");
+       tcase_add_test(tc, test_pen_type_is);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_printf.c b/src/libstrongswan/tests/suites/test_printf.c
new file mode 100644 (file)
index 0000000..6c15fbe
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <errno.h>
+#include <math.h>
+
+static void verify(char *expected, char *format, ...)
+{
+       FILE *mem;
+       char buf[128];
+       va_list args;
+
+       va_start(args, format);
+       vsnprintf(buf, sizeof(buf), format, args);
+       ck_assert_str_eq(expected, buf);
+       va_end(args);
+
+       mem = fmemopen(buf, sizeof(buf), "w");
+       va_start(args, format);
+       vfprintf(mem, format, args);
+       va_end(args);
+       fclose(mem);
+       ck_assert_str_eq(expected, buf);
+}
+
+START_TEST(test_printf_strings)
+{
+       verify("a bc def", "%s %s %s", "a", "bc", "def");
+       verify("asd", "%.3s", "asdfg");
+       verify("asdf", "%.*s", (int)4, "asdfg");
+       verify("  asdf", "%6s", "asdf");
+       verify("  asdf", "%+6s", "asdf");
+       verify("asdf  ", "%-6s", "asdf");
+}
+END_TEST
+
+START_TEST(test_printf_err)
+{
+       errno = EINVAL;
+       verify((char*)strerror(errno), "%m");
+}
+END_TEST
+
+START_TEST(test_printf_unsigned)
+{
+       verify("1 23 456", "%u %lu %llu", 1, (u_long)23, (u_int64_t)456);
+       verify("65535 255", "%hu %hhu", 0x1ffff, 0x1ff);
+       verify("123456789", "%zu", (size_t)123456789);
+       verify("   12", "%5u", 12);
+       verify("12   ", "%-5u", 12);
+       verify("0012", "%04u", 12);
+       verify("0012", "%.4u", 12);
+}
+END_TEST
+
+START_TEST(test_printf_signed)
+{
+       verify("-1 -23 -456", "%d %ld %lld", -1, (long)-23, (int64_t)-456);
+       verify("-1 -1", "%hd %hhd", 0x1ffff, 0x1ff);
+       verify("123456789", "%zd", (ssize_t)123456789);
+       verify("  -12", "%5d", -12);
+       verify("-12  ", "%-5d", -12);
+       verify("-012", "%04d", -12);
+       verify("-0012", "%.4d", -12);
+}
+END_TEST
+
+START_TEST(test_printf_hex)
+{
+       verify("1 23 456", "%x %lx %llx", 1, (u_long)0x23, (u_int64_t)0x456);
+       verify("12abcdef 12ABCDEF", "%x %X", 0x12ABCDEF, 0x12ABCDEF);
+       verify("ffff ff", "%hx %hhx", 0x1ffff, 0x1ff);
+       verify("23456789", "%zx", (size_t)0x23456789);
+       verify("   ab", "%5x", 0xab);
+       verify("ab   ", "%-5x", 0xab);
+       verify("00ab", "%04x", 0xab);
+       verify("00ab", "%.4x", 0xab);
+}
+END_TEST
+
+START_TEST(test_printf_float)
+{
+       verify("0.000000", "%f", 0.0);
+       verify("1.000000", "%f", 1.0);
+       verify("12345.1", "%.1f", 12345.123);
+       verify("1", "%.0f", 1.0);
+       verify("1.3", "%.1f", 1.346789);
+       verify("1.23", "%.2f", 1.23456789);
+       verify("1.123", "%.3f", 1.123456789);
+       verify("1.0123", "%.4f", 1.0123456789);
+
+       verify("-1.000000", "%f", -1.0);
+       verify("-12345.1", "%.1f", -12345.123);
+       verify("-1", "%.0f", -1.0);
+       verify("-1.3", "%.1f", -1.3456789);
+       verify("-1.23", "%.2f", -1.23456789);
+       verify("-1.123", "%.3f", -1.123456789);
+       verify("-1.0123", "%.4f", -1.0123456789);
+
+       verify("  1.2", "%5.1f", 1.234);
+       verify("001.2", "%05.1f", 1.234);
+       verify("1.2  ", "%-5.1f", 1.234);
+
+       verify("12346", "%.0f", 12345.6789);
+       verify("2", "%.0f", 1.5);
+       verify("1", "%.0f", 1.49);
+       verify("1.2", "%.1f", 1.151);
+       verify("1.1", "%.1f", 1.149);
+       verify("1.13", "%.2f", 1.1251);
+       verify("1.12", "%.2f", 1.1249);
+       verify("1.124", "%.3f", 1.12351);
+       verify("1.123", "%.3f", 1.12349);
+
+       verify("-12346", "%.0f", -12345.6789);
+       verify("-2", "%.0f", -1.51);
+       verify("-1", "%.0f", -1.49);
+       verify("-1.2", "%.1f", -1.151);
+       verify("-1.1", "%.1f", -1.149);
+       verify("-1.13", "%.2f", -1.1251);
+       verify("-1.12", "%.2f", -1.1249);
+       verify("-1.124", "%.3f", -1.12351);
+       verify("-1.123", "%.3f", -1.12349);
+
+#ifdef NAN
+       verify("nan", "%.3f", NAN);
+       verify("  nan", "%5.3f", NAN);
+       verify("NAN", "%.3F", NAN);
+       verify("NAN  ", "%-5.3F", NAN);
+#endif
+#ifdef INFINITY
+       verify("inf", "%.3f", INFINITY);
+       verify("-inf", "%.4f", -INFINITY);
+       verify("INF", "%.3F", INFINITY);
+       verify("-INF", "%.4F", -INFINITY);
+#endif
+}
+END_TEST
+
+Suite *printf_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("printf");
+
+       tc = tcase_create("strings");
+       tcase_add_test(tc, test_printf_strings);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("err");
+       tcase_add_test(tc, test_printf_err);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("unsiged");
+       tcase_add_test(tc, test_printf_unsigned);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("siged");
+       tcase_add_test(tc, test_printf_signed);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("hex");
+       tcase_add_test(tc, test_printf_hex);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("float");
+       tcase_add_test(tc, test_printf_float);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_rsa.c b/src/libstrongswan/tests/suites/test_rsa.c
new file mode 100644 (file)
index 0000000..4c75c34
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <plugins/plugin_feature.h>
+
+/**
+ * Signature schemes to test
+ */
+static signature_scheme_t schemes[] = {
+       SIGN_RSA_EMSA_PKCS1_NULL,
+       SIGN_RSA_EMSA_PKCS1_MD5,
+       SIGN_RSA_EMSA_PKCS1_SHA1,
+       SIGN_RSA_EMSA_PKCS1_SHA224,
+       SIGN_RSA_EMSA_PKCS1_SHA256,
+       SIGN_RSA_EMSA_PKCS1_SHA384,
+       SIGN_RSA_EMSA_PKCS1_SHA512,
+};
+
+/**
+ * Perform a signature verification "good" test having a keypair
+ */
+static void test_good_sig(private_key_t *privkey, public_key_t *pubkey)
+{
+       chunk_t sig, data = chunk_from_chars(0x01,0x02,0x03,0xFD,0xFE,0xFF);
+       int i;
+
+       for (i = 0; i < countof(schemes); i++)
+       {
+               if (!lib->plugins->has_feature(lib->plugins,
+                                               PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i])) ||
+                       !lib->plugins->has_feature(lib->plugins,
+                                               PLUGIN_PROVIDE(PRIVKEY_SIGN, schemes[i])))
+               {
+                       continue;
+               }
+               fail_unless(privkey->sign(privkey, schemes[i], data, &sig),
+                                       "sign %N", signature_scheme_names, schemes[i]);
+               fail_unless(pubkey->verify(pubkey, schemes[i], data, sig),
+                                       "verify %N", signature_scheme_names, schemes[i]);
+               free(sig.ptr);
+       }
+}
+
+/**
+ * Some special signatures that should never validate successfully
+ */
+static chunk_t invalid_sigs[] = {
+       chunk_from_chars(),
+       chunk_from_chars(0x00),
+       chunk_from_chars(0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+       chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+};
+
+/**
+ * Check public key that it properly fails against some crafted sigs
+ */
+static void test_bad_sigs(public_key_t *pubkey)
+{
+       chunk_t data = chunk_from_chars(0x01,0x02,0x03,0xFD,0xFE,0xFF);
+       int s, i;
+
+       for (s = 0; s < countof(schemes); s++)
+       {
+                       if (!lib->plugins->has_feature(lib->plugins,
+                                                       PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[s])))
+                       {
+                               continue;
+                       }
+               for (i = 0; i < countof(invalid_sigs); i++)
+               {
+                       fail_if(
+                               pubkey->verify(pubkey, schemes[s], data, invalid_sigs[i]),
+                               "bad %N sig accepted %B", signature_scheme_names, schemes[s],
+                               &invalid_sigs[i]);
+               }
+       }
+}
+
+/**
+ * RSA key sizes to test
+ */
+static int key_sizes[] = {
+       786, 1024, 1536, 2048, 3072, 4096,
+};
+
+START_TEST(test_gen)
+{
+       private_key_t *privkey;
+       public_key_t *pubkey;
+
+       privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+                                                                BUILD_KEY_SIZE, key_sizes[_i], BUILD_END);
+       ck_assert(privkey != NULL);
+       pubkey = privkey->get_public_key(privkey);
+       ck_assert(pubkey != NULL);
+
+       test_good_sig(privkey, pubkey);
+
+       test_bad_sigs(pubkey);
+
+       pubkey->destroy(pubkey);
+       privkey->destroy(privkey);
+}
+END_TEST
+
+/**
+ * Private keys to load
+ */
+static chunk_t keys[] = {
+       chunk_from_chars( /* RSA-768 */
+               0x30,0x82,0x01,0xcb,0x02,0x01,0x00,0x02,0x61,0x00,0xd1,0x5d,0x98,0x97,0x95,0x98,
+               0x19,0x87,0x20,0x3f,0x10,0xb0,0x05,0x36,0x1e,0x1b,0xcd,0xc8,0x93,0x66,0xd7,0x43,
+               0xed,0x84,0xb0,0x3e,0x96,0xd3,0xe7,0x27,0x0e,0xc0,0xba,0xdf,0x7e,0x32,0x05,0xd3,
+               0x08,0xd6,0x44,0xd5,0x01,0x2b,0x3e,0x5d,0xc0,0x37,0xae,0x4f,0xe0,0xea,0x8d,0x2c,
+               0x42,0x4c,0xa9,0xa2,0x42,0xbe,0xdd,0xdb,0xf7,0xd3,0x28,0x07,0x10,0x88,0x53,0x15,
+               0xb2,0x4f,0xb5,0x9d,0x47,0x9b,0xd6,0xc8,0xfe,0x5b,0xa2,0xd7,0xe1,0x13,0xca,0x0b,
+               0xce,0x7a,0xed,0xa2,0x3e,0xd5,0x9b,0xb8,0x8b,0x4f,0x02,0x03,0x01,0x00,0x01,0x02,
+               0x60,0x2d,0x83,0x82,0x53,0x99,0xb2,0xaa,0x02,0x05,0x11,0x90,0xa8,0x23,0x49,0xe3,
+               0x7b,0xb9,0xdd,0x9b,0xa5,0xa4,0xb0,0x60,0xa7,0x12,0xc5,0x58,0x76,0x92,0x6e,0x9c,
+               0x37,0x6b,0xa8,0x80,0x3f,0x91,0xa2,0x91,0xee,0x3a,0xa2,0x6f,0x91,0x9e,0x0a,0x35,
+               0x69,0xc0,0xa7,0xdc,0xd8,0x46,0xe4,0x29,0x1c,0x3d,0x34,0x30,0xa2,0xb9,0x0d,0x34,
+               0x94,0xa1,0x12,0xa7,0x85,0xd3,0x2c,0x47,0x1b,0xf0,0x78,0xd5,0x22,0xfc,0xa5,0xe0,
+               0x75,0xac,0x71,0x21,0xe8,0xe8,0x19,0x9f,0xbb,0x98,0x5c,0xa6,0x9d,0x42,0xd7,0x9c,
+               0x89,0x02,0x31,0x00,0xee,0xaa,0x9e,0x82,0xe1,0xb2,0xdd,0x05,0xbc,0x2e,0x53,0xe9,
+               0x64,0x4b,0x48,0x06,0x3a,0xfd,0x9e,0x91,0xce,0x1b,0x7f,0x66,0xbc,0xd2,0xc4,0xab,
+               0xbf,0xc5,0x5d,0x1a,0xbd,0xd6,0xb5,0x9c,0x5c,0x18,0x01,0xe6,0x79,0x19,0xf2,0xc3,
+               0x1d,0x66,0x88,0x2d,0x02,0x31,0x00,0xe0,0x92,0x34,0x1e,0x09,0xf2,0x1b,0xf9,0xbf,
+               0x11,0x65,0x3f,0xc8,0x85,0x5a,0xe6,0xc0,0xcf,0x93,0x44,0xb0,0x50,0xe4,0x8b,0x6f,
+               0x30,0xde,0x42,0x0c,0x8a,0x77,0x0d,0x98,0x7f,0x52,0x59,0x9e,0x87,0xb8,0x6e,0xdc,
+               0xed,0x15,0x80,0xbd,0xbb,0xf2,0xeb,0x02,0x31,0x00,0xb0,0x6b,0x36,0x98,0x90,0xb5,
+               0x62,0x63,0xa6,0xe2,0xa7,0xec,0x51,0xd2,0xc3,0xfe,0xb7,0x04,0x5a,0x7e,0x74,0xd8,
+               0x26,0xa8,0x8e,0xd3,0x4d,0xc5,0x97,0x10,0x10,0xee,0x7f,0x7d,0x82,0xe9,0x7d,0xb9,
+               0xd1,0x4d,0xc8,0x1e,0xc2,0x30,0x30,0x3f,0x66,0x51,0x02,0x31,0x00,0xaa,0x75,0x2f,
+               0x4c,0x11,0xbe,0x8d,0x0f,0x8f,0xc1,0x13,0x7a,0x4b,0xa9,0x35,0x6b,0x6b,0xb4,0xe3,
+               0x92,0xc2,0xc6,0x54,0x03,0xa6,0x5d,0x90,0x86,0xcf,0xe0,0x16,0x27,0xe2,0xb5,0xd9,
+               0xfb,0x1e,0x82,0xe4,0x32,0x7a,0x4d,0x17,0x02,0x46,0x82,0x30,0x0b,0x02,0x30,0x09,
+               0xf3,0xce,0x9b,0x02,0xc5,0x53,0xe9,0xa2,0x89,0xe2,0x3b,0x8c,0x8b,0xe9,0xc2,0xba,
+               0x94,0x76,0x60,0x27,0x2b,0xe9,0x92,0xc1,0x5e,0x3c,0xc3,0x77,0x9b,0xc7,0xce,0xc6,
+               0x67,0xd5,0x20,0x2c,0x54,0xa1,0x5d,0x2a,0x17,0x16,0x66,0xdf,0x5a,0xe9,0x87,
+       ),
+       chunk_from_chars( /* RSA-1024 */
+               0x30,0x82,0x02,0x5c,0x02,0x01,0x00,0x02,0x81,0x81,0x00,0xc0,0xbd,0x48,0x83,0xbc,
+               0xea,0x0b,0x32,0x06,0x4b,0xf5,0x10,0x54,0x1b,0xba,0x88,0xc4,0x10,0x7e,0x47,0xec,
+               0x0e,0xf9,0xb4,0xcf,0x9a,0x02,0xc6,0xb3,0xaf,0x35,0xc8,0xaf,0x78,0x1a,0xbc,0x37,
+               0x1a,0x25,0x7a,0x37,0x24,0x73,0x53,0x9a,0xf0,0x44,0x64,0x5b,0x6b,0x64,0x4c,0xfa,
+               0x83,0x3a,0x0f,0x77,0x5d,0x7b,0x21,0xa2,0x25,0x00,0x11,0xae,0x72,0x36,0x35,0xd9,
+               0x0d,0xef,0x5a,0xdd,0x98,0x35,0x49,0xaf,0x44,0xa0,0x33,0x29,0xc0,0xca,0xf5,0x6f,
+               0xfe,0xc1,0x06,0x4c,0x80,0x9a,0x54,0xbe,0x46,0x1a,0x96,0xb1,0xf3,0x29,0xb8,0x9d,
+               0x07,0x84,0x03,0x68,0x6b,0x9f,0xbf,0xe5,0xd8,0x14,0x2a,0xe0,0xef,0xbd,0x1a,0x61,
+               0x0d,0x3a,0xc8,0x67,0xcd,0x99,0x90,0xe3,0xe6,0x52,0x83,0x02,0x03,0x01,0x00,0x01,
+               0x02,0x81,0x80,0x13,0xd2,0xa3,0xe5,0xa0,0xb0,0x0a,0xe2,0x0f,0x3c,0x65,0x57,0xa8,
+               0xe9,0x87,0xd5,0x79,0xcc,0xc9,0xca,0xc8,0x8a,0xd5,0xc0,0x74,0x90,0x3e,0x1e,0xda,
+               0x40,0xcd,0x42,0xf7,0x01,0x09,0x9c,0x37,0xfd,0x41,0x6e,0x2b,0x6e,0x5d,0x4a,0x1e,
+               0x52,0x53,0x1b,0xbb,0x3c,0x9f,0xfe,0x91,0x79,0x48,0xfc,0x69,0x90,0xbc,0xbc,0x3d,
+               0xcf,0xee,0x62,0x0a,0xbd,0x57,0x6b,0xa9,0x51,0x3e,0xc2,0x7f,0x26,0xb1,0xaa,0x38,
+               0xeb,0x40,0x91,0x3a,0x3c,0x80,0x1e,0x4e,0xe2,0xff,0xa2,0x8e,0x56,0xbb,0xb3,0xeb,
+               0x24,0x81,0x4c,0x19,0x2c,0x8f,0x51,0x4c,0x04,0x81,0xaf,0x5e,0xc2,0xa6,0xf9,0xd3,
+               0x48,0xee,0xe9,0x6d,0x9b,0xe1,0xe5,0x17,0x4f,0x07,0x18,0xea,0x96,0xd3,0x2c,0xce,
+               0x44,0x71,0x51,0x02,0x41,0x00,0xe9,0xe9,0x46,0x7e,0xe1,0xc2,0x86,0x94,0x65,0x77,
+               0x9c,0xc7,0x76,0x5d,0xa0,0xd3,0xcc,0x1f,0xa3,0xc7,0xfe,0xbb,0x4e,0x27,0xd6,0x43,
+               0x6b,0xbd,0x0d,0x05,0x7a,0x10,0xe8,0x48,0x97,0x30,0xaa,0x53,0x61,0x57,0x1f,0x8a,
+               0xf7,0x39,0x5e,0xa6,0xfe,0xe9,0x2c,0x19,0x5e,0x53,0xea,0xc2,0xb2,0xc2,0x11,0x3c,
+               0x18,0xab,0xcf,0xc4,0x91,0x1b,0x02,0x41,0x00,0xd2,0xf0,0xb1,0x49,0xa1,0x6f,0xf1,
+               0x83,0xa3,0xd2,0xa1,0x0e,0xb3,0xb3,0x33,0x01,0xed,0xd0,0x28,0xc1,0x2f,0x88,0x80,
+               0x9f,0x43,0x7c,0x7e,0x5d,0x4c,0x15,0x05,0x86,0xff,0x75,0x9b,0xf1,0x64,0xde,0x06,
+               0xbf,0xdd,0x98,0x50,0xd9,0x4a,0x3a,0xd6,0x25,0x1c,0xdd,0xc8,0x56,0x12,0x11,0xb9,
+               0x02,0x42,0xc7,0x1d,0x86,0xeb,0xd9,0xc2,0xb9,0x02,0x41,0x00,0x80,0x25,0x8c,0xb9,
+               0x76,0x75,0x5b,0xc5,0x70,0xd1,0x56,0xd2,0xef,0xc5,0xdb,0x96,0x2c,0xfe,0x28,0x7c,
+               0x28,0xd1,0xf4,0xbf,0x5e,0x63,0x11,0x63,0x40,0xfe,0xff,0x20,0xc4,0x21,0x00,0xb3,
+               0x68,0x9c,0xc5,0x77,0x35,0x90,0xac,0x60,0x81,0xba,0x7b,0x6c,0xc2,0xfc,0x22,0xf1,
+               0x56,0x6b,0xd4,0x02,0xfd,0xee,0x2e,0x95,0xf1,0xfd,0x7e,0x81,0x02,0x40,0x47,0xaf,
+               0x84,0x90,0x81,0x4c,0x89,0xc7,0x32,0xe5,0x61,0xd6,0x9d,0x3b,0x49,0x1a,0x5e,0xb7,
+               0x5f,0x22,0x48,0x05,0x1b,0xb1,0x04,0x3e,0x4a,0xb3,0x6a,0x27,0xba,0xb9,0x26,0x17,
+               0xd1,0xe7,0x37,0x60,0x3c,0xea,0xf7,0x63,0xcc,0x16,0x0c,0x23,0xf2,0xa2,0xaa,0x2c,
+               0xb4,0xe8,0x8b,0x3b,0x7a,0xa4,0x4a,0x0d,0x60,0xfb,0x79,0x2b,0x88,0x01,0x02,0x40,
+               0x42,0xee,0x12,0x91,0xf9,0x80,0x1e,0x60,0x0b,0xaa,0xbe,0xfd,0x09,0x84,0x93,0x0d,
+               0x09,0xd3,0x1e,0x37,0x52,0xb0,0xe8,0x51,0x4f,0xd3,0x9e,0xda,0x32,0x38,0x22,0x35,
+               0xdb,0x25,0x8b,0x9f,0x1a,0xb5,0xf1,0x75,0xfa,0x4d,0x09,0x42,0x01,0x64,0xe6,0xc4,
+               0x6e,0xba,0x2d,0x88,0x92,0xbe,0xa9,0x1f,0x85,0x38,0x10,0xa3,0x0e,0x1a,0x92,0x54,
+       ),
+       chunk_from_chars( /* RSA-1536 */
+               0x30,0x82,0x03,0x7d,0x02,0x01,0x00,0x02,0x81,0xc1,0x00,0xba,0xe3,0x37,0x93,0x7e,
+               0x42,0x13,0x3c,0xba,0x41,0xc1,0x7b,0xf0,0xcc,0x7a,0x44,0xc6,0x54,0xc8,0x77,0x01,
+               0x70,0x2f,0x6e,0x4a,0xcf,0x2d,0x07,0xab,0x01,0xc0,0x43,0xab,0x8d,0x33,0xb3,0xd4,
+               0xeb,0xe3,0x90,0xf6,0x01,0x03,0x75,0x03,0x1d,0xe8,0x06,0x40,0x15,0xfa,0x96,0x0b,
+               0xd5,0x26,0x64,0xea,0x55,0x82,0x16,0x7b,0xd5,0x1e,0xaa,0x08,0xc7,0x30,0x1a,0x59,
+               0xf8,0xd9,0xe3,0x9e,0x89,0xd9,0x92,0x2c,0x32,0x79,0x0e,0xb3,0x25,0xbc,0x1d,0x7c,
+               0x59,0xde,0x05,0x47,0x8f,0x61,0x77,0xf5,0x4f,0xed,0x82,0x2c,0xf8,0x2a,0x3e,0x02,
+               0xf3,0xc0,0x15,0x51,0xde,0x05,0xc4,0xfc,0x80,0x91,0xae,0x06,0x1b,0xd7,0x39,0x8e,
+               0x9a,0x6d,0xb3,0x2f,0xb0,0xd0,0xc8,0x96,0xa6,0x88,0xb3,0x17,0xca,0x58,0xbe,0x38,
+               0x2c,0x64,0x35,0x5a,0x29,0xb7,0xf8,0x74,0x3d,0xbb,0xec,0x90,0x01,0x04,0x64,0x3d,
+               0x38,0x0f,0x87,0xce,0xd7,0xfc,0xd2,0x96,0x93,0x31,0x85,0x0d,0x2d,0xa5,0x91,0xe2,
+               0xfc,0x7b,0xea,0xb0,0x89,0x24,0xaa,0x00,0x29,0x8c,0x26,0x7c,0x94,0x54,0x74,0xe4,
+               0x11,0xa8,0x04,0x6f,0x40,0xeb,0xaf,0xed,0xac,0x75,0x33,0x02,0x03,0x01,0x00,0x01,
+               0x02,0x81,0xc0,0x0a,0x96,0xec,0x63,0xc1,0xa0,0x39,0xd9,0xd3,0x8d,0xfd,0x4a,0x2a,
+               0x13,0x54,0x0c,0x48,0x96,0xae,0x43,0x3c,0x04,0x20,0xd3,0xe5,0x8e,0x46,0xb5,0x6c,
+               0x05,0xad,0xe0,0xc7,0xbc,0x39,0x05,0x44,0x17,0xd7,0xad,0xb3,0x9a,0xcc,0x18,0xd9,
+               0xc3,0xdc,0x8d,0x5a,0x1d,0x44,0xb5,0x32,0xd7,0x71,0x94,0xff,0x48,0x38,0x16,0x51,
+               0x0e,0xfa,0xed,0x54,0x91,0x00,0xd3,0x45,0x6c,0xd9,0xdf,0xd1,0x70,0x6b,0x31,0x22,
+               0xaa,0xfb,0x7c,0x0f,0x3f,0xa0,0xa0,0xa5,0x16,0xac,0x83,0x6d,0x12,0x1d,0x4a,0x40,
+               0x4e,0xb6,0x9c,0xf4,0x67,0xaa,0xa9,0xb0,0xc8,0xb4,0x0a,0xd5,0x3b,0x5c,0x19,0xed,
+               0x86,0x83,0x5a,0x75,0xbc,0xeb,0x17,0xc8,0x16,0xa0,0x60,0x2e,0xb6,0x25,0xc5,0x4d,
+               0x59,0xba,0x62,0xcb,0x3d,0x91,0x7c,0x79,0x6a,0x4b,0x4a,0x54,0xbd,0xb7,0xa3,0x89,
+               0x7f,0xbf,0x0e,0x77,0xe1,0x54,0x29,0x0d,0x45,0x6d,0xa8,0x15,0xa5,0x17,0x8c,0xcf,
+               0x27,0x9e,0x47,0x4e,0x2a,0x91,0x7e,0x4e,0x14,0x59,0x8c,0x62,0x91,0xa3,0x40,0xa5,
+               0x9e,0x67,0xbb,0x02,0x97,0xb4,0xe7,0x06,0x04,0xbc,0x16,0x24,0x3d,0x49,0xb1,0xf0,
+               0xae,0xfc,0x1d,0x02,0x61,0x00,0xde,0x86,0x5d,0x49,0x88,0xeb,0x5c,0xd3,0xe5,0x11,
+               0x48,0x0b,0x1e,0x52,0x95,0xa9,0x65,0x99,0x89,0xcf,0x51,0xb0,0x08,0xdd,0xb5,0x5b,
+               0x64,0x1a,0x34,0xd2,0xee,0x4b,0x2d,0x8b,0xc1,0xd5,0xd6,0x1d,0x6c,0x0c,0x7e,0xa5,
+               0x66,0x12,0xec,0xaf,0x5d,0xe9,0x33,0xd4,0xba,0x18,0x71,0x84,0x97,0xbe,0xc0,0x75,
+               0x63,0x19,0xae,0xc6,0xc7,0x65,0xf3,0xf6,0xda,0x3f,0x91,0xfa,0x5e,0x87,0xf3,0xbc,
+               0xd2,0x64,0x8d,0xcf,0xfb,0xdd,0x7f,0x9b,0x6c,0x81,0xba,0x9b,0x4e,0x94,0x5e,0x83,
+               0xd1,0xcb,0xb9,0xf4,0x39,0x7f,0x02,0x61,0x00,0xd7,0x00,0x6d,0x8e,0x1b,0xa1,0x44,
+               0xd9,0xff,0xe6,0x42,0x72,0x18,0x55,0x26,0x3e,0x87,0x40,0x71,0xb2,0x67,0x37,0x16,
+               0xe9,0xbd,0x51,0x7f,0x0e,0x79,0x0e,0x75,0xa9,0x1f,0x0f,0x6b,0xa5,0x7c,0x5f,0xc8,
+               0xdc,0x17,0xde,0x53,0x88,0x97,0x90,0x88,0xf2,0x4d,0x66,0x5e,0x0e,0x11,0x16,0x92,
+               0x1e,0x61,0x56,0xe6,0xf0,0x74,0x81,0x58,0x95,0x05,0x29,0x71,0x9b,0xa0,0x69,0xed,
+               0x14,0x23,0xf6,0x36,0x9b,0x8f,0x06,0x3a,0x76,0xab,0xeb,0xce,0xe8,0xdc,0x79,0xc1,
+               0x29,0xb9,0xfc,0x49,0x7a,0x26,0x59,0xd6,0x4d,0x02,0x61,0x00,0xaf,0x3c,0xac,0xd6,
+               0x2d,0xe6,0xfb,0x91,0x3a,0xc1,0x23,0x34,0xee,0x4a,0x26,0xe5,0xe1,0xc6,0xc9,0xc9,
+               0xe4,0x10,0x76,0xca,0xf1,0xf8,0xe8,0x99,0xe2,0xa3,0x81,0x58,0xde,0xa3,0x42,0xa0,
+               0x3d,0x1f,0xaa,0x69,0x24,0x8a,0xe8,0x19,0x5b,0x1e,0xb7,0x1b,0xe0,0xdf,0x53,0x35,
+               0xd0,0x9f,0x94,0x48,0x79,0x93,0x77,0xd9,0x4f,0xd3,0xe6,0x4f,0x19,0x92,0x7a,0x48,
+               0xb9,0x92,0xab,0x42,0xf0,0xe4,0xef,0xe2,0x93,0xf3,0x07,0xeb,0x64,0x84,0x67,0x2c,
+               0xba,0x61,0x77,0xbe,0x4b,0xb8,0x0f,0x4d,0x1a,0x41,0x83,0xcd,0x02,0x60,0x56,0xec,
+               0x55,0x5e,0x9e,0xcd,0x14,0x89,0x0e,0x6c,0x89,0x70,0x97,0x65,0xd5,0x90,0x72,0x1e,
+               0x1b,0xd9,0x84,0xe1,0x40,0xe2,0x3f,0x28,0x33,0xb6,0x26,0x3b,0x32,0x56,0xad,0xb8,
+               0x0e,0x4d,0x59,0x7b,0x60,0x39,0x9b,0x6c,0xc7,0x58,0xf1,0xed,0xfd,0x6f,0xf8,0xda,
+               0xea,0x2b,0xc5,0xbc,0xda,0x56,0x6e,0x04,0x34,0x5a,0x02,0xc0,0x48,0x8f,0xf7,0x06,
+               0x4a,0x68,0x20,0xf2,0xb2,0x66,0xf2,0x23,0x18,0xf0,0xcb,0x62,0x39,0x40,0xc1,0x41,
+               0x14,0xe6,0x10,0x3d,0x29,0x5b,0x35,0x56,0x4a,0x5e,0x98,0x22,0xba,0x01,0x02,0x61,
+               0x00,0xcc,0x80,0xb7,0xb9,0xb9,0x4a,0xaf,0x47,0x00,0x3e,0x21,0x0f,0xb8,0x4e,0x7c,
+               0xb1,0xe4,0x25,0xd6,0x19,0x26,0x54,0xc6,0x8c,0x30,0x88,0x54,0x70,0xcf,0x1f,0x62,
+               0x75,0xcb,0x18,0x58,0x6c,0x14,0xb0,0x9b,0x13,0x90,0xa2,0x1a,0x5a,0x79,0xa3,0x82,
+               0xf0,0x9b,0xba,0xf0,0x90,0xaf,0xa1,0xe8,0xa8,0x70,0xef,0x60,0x6a,0x68,0xed,0x5a,
+               0x21,0x77,0x69,0x7a,0xf2,0xee,0x3e,0xe5,0x90,0xd2,0x33,0x71,0x3b,0x82,0x88,0x75,
+               0xdd,0x8e,0x6e,0xbc,0x17,0x83,0xef,0x37,0x82,0x4e,0x83,0x30,0xcb,0x8a,0xbc,0x6c,
+               0x41,
+       ),
+       chunk_from_chars( /* RSA-2048 */
+               0x30,0x82,0x04,0xa2,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00,0xba,0xbf,0x27,0x0b,
+               0x22,0x59,0xd8,0x6f,0xff,0x26,0x5d,0x41,0x3d,0xb0,0x94,0x58,0x5d,0xc0,0x46,0xb6,
+               0x77,0xa9,0x78,0x10,0x6d,0xe9,0xbf,0xca,0x6f,0x04,0xe1,0xda,0x85,0x12,0x1e,0xe0,
+               0xa6,0xc7,0xa2,0x71,0x04,0x8b,0x6e,0x84,0xf9,0x86,0x2b,0xeb,0x72,0x01,0x72,0xc8,
+               0x0a,0x83,0xa6,0xf7,0xc0,0xd6,0x76,0x1d,0x28,0x38,0xb5,0x7e,0x6c,0x8c,0x6a,0x13,
+               0xf4,0xf1,0x7f,0xf2,0x79,0xae,0x73,0xba,0x1a,0x3f,0x30,0x65,0xb6,0x23,0xa7,0x94,
+               0x34,0x29,0x87,0xce,0x06,0x99,0xee,0x85,0x10,0xce,0x08,0xe2,0x8d,0xd5,0x47,0xf3,
+               0xc8,0xf0,0x18,0x41,0xc0,0x59,0x66,0x06,0xda,0xb6,0x18,0xd2,0xa3,0xa0,0xbd,0x3a,
+               0x90,0x7f,0x37,0x39,0xdf,0x98,0x55,0xa2,0x19,0x5e,0x37,0xbc,0x86,0xf3,0x02,0xf8,
+               0x68,0x49,0x53,0xf2,0x4b,0x3d,0x7a,0xe3,0x1d,0xa4,0x15,0x10,0xa6,0xce,0x8c,0xb8,
+               0xfd,0x95,0x54,0xa2,0x50,0xa2,0xd9,0x35,0x12,0x56,0xae,0xbc,0x51,0x33,0x6d,0xb8,
+               0x63,0x7c,0x26,0xab,0x19,0x01,0xa5,0xda,0xfa,0x4b,0xb6,0x57,0xd3,0x4b,0xdd,0xc0,
+               0x62,0xc5,0x05,0xb7,0xc3,0x2e,0x1f,0x17,0xc8,0x09,0x87,0x12,0x37,0x21,0xd7,0x7a,
+               0x53,0xb0,0x47,0x60,0xa2,0xb5,0x23,0x3b,0x99,0xdf,0xea,0x8b,0x94,0xea,0x9d,0x53,
+               0x5d,0x02,0x52,0xf7,0x29,0xfb,0x63,0xb0,0xff,0x27,0x5e,0xde,0x54,0x7d,0x95,0xd6,
+               0x4e,0x58,0x12,0x06,0x60,0x22,0x33,0xf2,0x19,0x67,0x65,0xdd,0xf3,0x42,0xb5,0x00,
+               0x51,0x35,0xe5,0x62,0x4d,0x90,0x44,0xfb,0x7f,0x5b,0xb5,0xe5,0x02,0x03,0x01,0x00,
+               0x01,0x02,0x82,0x01,0x00,0x1c,0xf5,0x66,0xf5,0xce,0x4c,0x1d,0xe8,0xd2,0x29,0x6e,
+               0x15,0x1f,0x9e,0x9a,0x06,0x70,0xf5,0x4f,0xd1,0xdc,0x51,0x02,0x8e,0x13,0xa9,0x47,
+               0x85,0x39,0xfd,0x89,0x13,0x74,0x86,0xb8,0x94,0x90,0x30,0x4d,0x73,0x96,0xa7,0x93,
+               0x8a,0x19,0xd2,0x91,0x4d,0x77,0xb6,0x9b,0x48,0xc3,0x7e,0xa2,0x5d,0xf1,0x80,0xa0,
+               0x3c,0xc9,0xbf,0xaf,0x7f,0x4d,0x10,0x62,0x23,0xb9,0x9c,0x58,0x81,0xae,0x96,0x5b,
+               0x9a,0x4c,0x97,0x27,0x67,0x62,0x5c,0xf9,0x8f,0xdd,0x1d,0xe2,0x92,0x13,0x8a,0x7b,
+               0xc7,0x15,0x31,0xca,0x05,0x6d,0xc6,0x98,0xdb,0x88,0x39,0x99,0x1d,0x5b,0x19,0x51,
+               0xdd,0xb6,0xbd,0x3d,0xb0,0xae,0x50,0x8e,0xff,0x7d,0xa8,0x48,0x95,0x58,0x23,0xbc,
+               0x85,0xc0,0x46,0xd0,0xc0,0x0e,0xda,0xdd,0xa4,0x8e,0x8d,0x31,0x8b,0x89,0x0f,0x8b,
+               0x76,0x9a,0xb5,0x99,0x56,0x5e,0xd3,0x0c,0x88,0x0b,0x03,0xf1,0xc9,0xe3,0x05,0x05,
+               0x08,0x75,0xce,0x35,0x52,0xa0,0xc0,0xf2,0xf4,0xb9,0x87,0x22,0x21,0x3f,0x61,0xd6,
+               0x99,0xae,0x0e,0x76,0x5d,0x9c,0x16,0xa3,0xe9,0xde,0x2d,0x2a,0x46,0xf7,0x89,0xbf,
+               0x0d,0xb1,0x60,0xad,0xbc,0x24,0xe2,0xe5,0xb1,0xc1,0x1c,0x00,0x40,0x1c,0xbd,0xfa,
+               0x6e,0xc7,0x0d,0xc1,0xda,0x4d,0x54,0x45,0x96,0xac,0xf7,0xfe,0x1b,0xf2,0x47,0x1e,
+               0xf7,0x8b,0xcf,0x27,0xcc,0xe7,0x08,0xd6,0x43,0x60,0xea,0xda,0x19,0xd7,0x98,0x17,
+               0x7c,0xab,0x0c,0x90,0x60,0x75,0x9f,0x8b,0xaa,0x13,0x63,0x98,0x9e,0xc6,0x41,0x9f,
+               0xd4,0x85,0xa3,0xb2,0xb9,0x02,0x81,0x81,0x00,0xe1,0x20,0xf6,0xac,0xa9,0x01,0xbd,
+               0x31,0xe6,0xb2,0x4e,0xcf,0x66,0xc3,0x11,0x0e,0x5b,0xfe,0x58,0x6b,0xc6,0x2d,0x7a,
+               0x05,0x30,0x9a,0x6f,0xcc,0xcc,0xdf,0xd2,0x2c,0xe1,0x47,0x39,0x9e,0xf3,0x0c,0x81,
+               0xd9,0x76,0x00,0xe2,0xb1,0x08,0x91,0xfb,0x12,0x04,0xf6,0x1f,0xea,0xff,0x82,0xe5,
+               0x64,0x64,0x6f,0x14,0xbe,0x33,0x5f,0x41,0x5f,0x73,0x1f,0xa2,0x32,0xec,0x75,0xb3,
+               0x98,0x4b,0x88,0x4d,0x1e,0xec,0x78,0xda,0x4c,0x2d,0xf8,0xbb,0xcf,0x0e,0x8f,0x2f,
+               0x23,0xae,0xcd,0xe0,0x4c,0x13,0x1c,0x1c,0x16,0x8e,0xb9,0x9f,0x02,0x12,0x12,0xa5,
+               0xf4,0x21,0xfe,0x57,0x08,0x7a,0xe8,0xbe,0x15,0xe9,0xdd,0x2a,0xd1,0x7b,0x39,0xd6,
+               0x4f,0x70,0x74,0x7d,0xfd,0x39,0x97,0x80,0x8d,0x02,0x81,0x81,0x00,0xd4,0x5a,0xce,
+               0x05,0x93,0x51,0x15,0x44,0xdd,0x4d,0x79,0x92,0x04,0xe6,0x64,0x7e,0x6c,0xb5,0x61,
+               0x6b,0xc3,0xb3,0xae,0x4f,0x0a,0x75,0xbf,0x6c,0xec,0x47,0xf2,0xbc,0xea,0x76,0xc4,
+               0xc2,0xe7,0xd2,0x50,0xc4,0xe0,0xaf,0x56,0x05,0x72,0x3c,0x34,0x8c,0x5b,0xae,0xb8,
+               0x0e,0xfb,0x83,0x27,0xcf,0x61,0x05,0x44,0x97,0x3f,0x66,0x6d,0x26,0x7d,0xed,0xcd,
+               0x5a,0x87,0x04,0xbc,0xb3,0x70,0x75,0x15,0x51,0xe9,0x18,0x85,0xf7,0x2a,0x45,0xd5,
+               0xc7,0x93,0x32,0x07,0x2e,0x26,0x34,0x2d,0x18,0x63,0x45,0x06,0x6f,0xa9,0x75,0x5d,
+               0x20,0x6b,0x0b,0x13,0x45,0x81,0x7e,0x5c,0xc5,0x48,0x16,0x4b,0x82,0x7c,0xad,0xbe,
+               0xfd,0xa5,0x0a,0xd6,0xc2,0x21,0xfc,0xa5,0x84,0xaf,0xf3,0x10,0xb9,0x02,0x81,0x80,
+               0x29,0x20,0x20,0x6f,0xc2,0x1f,0xf3,0x33,0xde,0x74,0xcc,0x38,0xcf,0x08,0xeb,0x60,
+               0xb8,0x25,0x6a,0x79,0xa5,0xa6,0x41,0x18,0x19,0x9c,0xdc,0xb7,0x88,0xe5,0x8a,0x3b,
+               0x70,0x9b,0xd6,0x46,0xd7,0x17,0x7d,0xd0,0xff,0xe1,0x81,0x87,0xdd,0x8c,0xed,0x54,
+               0x89,0x5b,0x7c,0xd1,0x2d,0x03,0xf8,0x6b,0xb2,0x7d,0x28,0x48,0xe6,0x91,0x8c,0x1b,
+               0xa7,0xa8,0x2b,0xb5,0x29,0xc5,0x06,0x9d,0xd7,0x8e,0x7a,0xa8,0x1f,0x82,0xa4,0x3e,
+               0x2e,0x57,0xb5,0xd7,0x49,0x4d,0x96,0xca,0xe9,0xef,0xe9,0xfd,0x7b,0xb0,0x32,0xe1,
+               0x5c,0x09,0x44,0xa6,0xd8,0x2e,0x57,0xea,0x95,0x1b,0x25,0x43,0x03,0x50,0xe9,0x08,
+               0x8f,0xc4,0x3b,0x42,0x31,0x44,0x8b,0x85,0xcf,0x81,0x38,0x52,0xbd,0xe6,0x93,0x31,
+               0x02,0x81,0x80,0x18,0x3d,0x79,0x51,0x07,0x9c,0xf4,0xd9,0x94,0x8d,0x78,0x78,0x23,
+               0x99,0x0d,0x15,0xa5,0x61,0x1b,0x0a,0xcb,0x1f,0x22,0xa1,0xa1,0x27,0x09,0xbf,0xec,
+               0x44,0xd6,0x3f,0x9c,0x60,0x0c,0x5b,0xd7,0x4c,0x99,0xad,0xaf,0x9c,0x34,0x2c,0x90,
+               0xfa,0xb0,0x60,0xe9,0x42,0x4b,0x7e,0x62,0x55,0x79,0x60,0xe1,0xc9,0x51,0x28,0x16,
+               0xb3,0xa1,0x78,0x08,0x5d,0xf1,0xd8,0x08,0x9b,0x90,0xd2,0xc6,0xde,0x86,0x9d,0x80,
+               0x07,0x2d,0x9b,0xa6,0x36,0xac,0x8d,0x88,0x8e,0xe8,0x64,0xeb,0x35,0x7f,0x84,0x4e,
+               0x28,0x9d,0xf0,0x77,0x1e,0x8f,0x8f,0xd8,0xc8,0x3d,0xdd,0xec,0x47,0x39,0x5d,0xc7,
+               0xb9,0xcb,0xca,0xcc,0x62,0xa4,0xef,0x9d,0x3c,0x5c,0x81,0x72,0x91,0xbd,0x6f,0x25,
+               0x0a,0x90,0xf9,0x02,0x81,0x80,0x51,0x42,0x23,0x64,0x3d,0xbc,0xcb,0xcb,0x77,0xd4,
+               0x5c,0x6b,0xf4,0x16,0x3a,0x6b,0x05,0x5f,0xd4,0xf8,0x59,0xe6,0x98,0x0c,0x43,0x7e,
+               0x6b,0x17,0x0d,0x01,0x23,0x6e,0x4c,0xff,0x35,0xe4,0xc5,0xba,0xe8,0x9e,0x12,0x94,
+               0x34,0x78,0xe4,0x3d,0x35,0xa1,0xd4,0xa9,0xa3,0x7e,0xe4,0x57,0xef,0xa4,0x9a,0x6a,
+               0x32,0xb3,0x9f,0xf8,0x3a,0xcf,0xea,0xf4,0xc7,0x59,0x92,0xd4,0x2a,0x5b,0x26,0x83,
+               0x78,0x30,0x5f,0xdf,0x46,0xa6,0xb0,0x28,0x37,0x2b,0x55,0x08,0x4c,0xb6,0x6b,0xb8,
+               0xa9,0x11,0x7d,0x0b,0xab,0x97,0x4d,0x8c,0xc3,0xbf,0x3b,0xcd,0x3e,0xad,0x80,0xce,
+               0xe8,0xc6,0x01,0x35,0xd2,0x3e,0x31,0xdc,0x96,0xd7,0xc3,0xab,0x65,0xd1,0xc4,0xa3,
+               0x47,0x14,0xa9,0xba,0xd0,0x30,
+       ),
+};
+
+START_TEST(test_load)
+{
+       private_key_t *privkey;
+       public_key_t *pubkey;
+
+       privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+                                                                BUILD_BLOB_ASN1_DER, keys[_i], BUILD_END);
+       ck_assert(privkey != NULL);
+       pubkey = privkey->get_public_key(privkey);
+       ck_assert(pubkey != NULL);
+
+       test_good_sig(privkey, pubkey);
+
+       test_bad_sigs(pubkey);
+
+       pubkey->destroy(pubkey);
+       privkey->destroy(privkey);
+}
+END_TEST
+
+Suite *rsa_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("rsa");
+
+       tc = tcase_create("generate");
+       tcase_add_loop_test(tc, test_gen, 0, countof(key_sizes));
+       tcase_set_timeout(tc, 8);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("load");
+       tcase_add_loop_test(tc, test_load, 0, countof(keys));
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_threading.c b/src/libstrongswan/tests/suites/test_threading.c
new file mode 100644 (file)
index 0000000..0c768b3
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <sched.h>
+#include <pthread.h>
+
+#include "test_suite.h"
+
+#include <threading/mutex.h>
+
+/*******************************************************************************
+ * recursive mutex test
+ */
+
+#define THREADS 20
+
+static mutex_t *mutex;
+
+static pthread_barrier_t mutex_barrier;
+
+static int mutex_locked = 0;
+
+static void *mutex_run(void *data)
+{
+       int i;
+
+       /* wait for all threads before getting in action */
+       pthread_barrier_wait(&mutex_barrier);
+
+       for (i = 0; i < 100; i++)
+       {
+               mutex->lock(mutex);
+               mutex->lock(mutex);
+               mutex->lock(mutex);
+               mutex_locked++;
+               sched_yield();
+               if (mutex_locked > 1)
+               {
+                       fail("two threads locked the mutex concurrently");
+               }
+               mutex_locked--;
+               mutex->unlock(mutex);
+               mutex->unlock(mutex);
+               mutex->unlock(mutex);
+       }
+       return NULL;
+}
+
+START_TEST(test_mutex)
+{
+       pthread_t threads[THREADS];
+       int i;
+
+       mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+
+       for (i = 0; i < 10; i++)
+       {
+               mutex->lock(mutex);
+               mutex->unlock(mutex);
+       }
+       for (i = 0; i < 10; i++)
+       {
+               mutex->lock(mutex);
+       }
+       for (i = 0; i < 10; i++)
+       {
+               mutex->unlock(mutex);
+       }
+
+       pthread_barrier_init(&mutex_barrier, NULL, THREADS);
+       for (i = 0; i < THREADS; i++)
+       {
+               pthread_create(&threads[i], NULL, mutex_run, NULL);
+       }
+       for (i = 0; i < THREADS; i++)
+       {
+               pthread_join(threads[i], NULL);
+       }
+       pthread_barrier_destroy(&mutex_barrier);
+
+       mutex->destroy(mutex);
+}
+END_TEST
+
+Suite *threading_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("threading");
+
+       tc = tcase_create("recursive mutex");
+       tcase_add_test(tc, test_mutex);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_utils.c b/src/libstrongswan/tests/suites/test_utils.c
new file mode 100644 (file)
index 0000000..3ca0412
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <library.h>
+#include <utils/utils.h>
+#include <ipsec/ipsec_types.h>
+
+#include <time.h>
+
+/*******************************************************************************
+ * object storage on lib
+ */
+
+START_TEST(test_objects)
+{
+       char *k1 = "key1", *k2 = "key2";
+       char *v1 = "val1", *val;
+
+       ck_assert(lib->get(lib, k1) == NULL);
+
+       ck_assert(lib->set(lib, k1, v1));
+       ck_assert(!lib->set(lib, k1, v1));
+
+       val = lib->get(lib, k1);
+       ck_assert(val != NULL);
+       ck_assert(streq(val, v1));
+
+       ck_assert(lib->set(lib, k1, NULL));
+       ck_assert(!lib->set(lib, k2, NULL));
+
+       ck_assert(lib->get(lib, k1) == NULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * test return_... functions
+ */
+
+START_TEST(test_return_functions)
+{
+       ck_assert(return_null() == NULL);
+       ck_assert(return_null("asdf", 5, NULL, 1, "qwer") == NULL);
+
+       ck_assert(return_true() == TRUE);
+       ck_assert(return_true("asdf", 5, NULL, 1, "qwer") == TRUE);
+
+       ck_assert(return_false() == FALSE);
+       ck_assert(return_false("asdf", 5, NULL, 1, "qwer") == FALSE);
+
+       ck_assert(return_failed() == FAILED);
+       ck_assert(return_failed("asdf", 5, NULL, 1, "qwer") == FAILED);
+
+       ck_assert(return_success() == SUCCESS);
+       ck_assert(return_success("asdf", 5, NULL, 1, "qwer") == SUCCESS);
+
+       /* just make sure this works */
+       nop();
+       nop("asdf", 5, NULL, 1, "qwer");
+}
+END_TEST
+
+/*******************************************************************************
+ * timeval_add_ms
+ */
+
+START_TEST(test_timeval_add_ms)
+{
+       timeval_t tv;
+
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+       timeval_add_ms(&tv, 0);
+       ck_assert_int_eq(tv.tv_sec, 0);
+       ck_assert_int_eq(tv.tv_usec, 0);
+
+       timeval_add_ms(&tv, 1);
+       ck_assert_int_eq(tv.tv_sec, 0);
+       ck_assert_int_eq(tv.tv_usec, 1000);
+
+       timeval_add_ms(&tv, 0);
+       ck_assert_int_eq(tv.tv_sec, 0);
+       ck_assert_int_eq(tv.tv_usec, 1000);
+
+       timeval_add_ms(&tv, 999);
+       ck_assert_int_eq(tv.tv_sec, 1);
+       ck_assert_int_eq(tv.tv_usec, 0);
+
+       timeval_add_ms(&tv, 0);
+       ck_assert_int_eq(tv.tv_sec, 1);
+       ck_assert_int_eq(tv.tv_usec, 0);
+
+       timeval_add_ms(&tv, 1000);
+       ck_assert_int_eq(tv.tv_sec, 2);
+       ck_assert_int_eq(tv.tv_usec, 0);
+
+       timeval_add_ms(&tv, 1500);
+       ck_assert_int_eq(tv.tv_sec, 3);
+       ck_assert_int_eq(tv.tv_usec, 500000);
+}
+END_TEST
+
+/*******************************************************************************
+ * htoun/untoh
+ */
+
+START_TEST(test_htoun)
+{
+       chunk_t net64, expected;
+       u_int16_t host16 = 513;
+       u_int32_t net16 = 0, host32 = 67305985;
+       u_int64_t net32 = 0, host64 = 578437695752307201ULL;
+
+       net64 = chunk_alloca(16);
+       memset(net64.ptr, 0, net64.len);
+
+       expected = chunk_from_chars(0x00, 0x02, 0x01, 0x00);
+       htoun16((char*)&net16 + 1, host16);
+       ck_assert(chunk_equals(expected, chunk_from_thing(net16)));
+
+       expected = chunk_from_chars(0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00);
+       htoun32((u_int16_t*)&net32 + 1, host32);
+       ck_assert(chunk_equals(expected, chunk_from_thing(net32)));
+
+       expected = chunk_from_chars(0x00, 0x00, 0x00, 0x00,
+                                                               0x08, 0x07, 0x06, 0x05,
+                                                               0x04, 0x03, 0x02, 0x01,
+                                                               0x00, 0x00, 0x00, 0x00);
+       htoun64((u_int32_t*)net64.ptr + 1, host64);
+       ck_assert(chunk_equals(expected, net64));
+}
+END_TEST
+
+START_TEST(test_untoh)
+{
+       chunk_t net;
+       u_int16_t host16;
+       u_int32_t host32;
+       u_int64_t host64;
+
+       net = chunk_from_chars(0x00, 0x02, 0x01, 0x00);
+       host16 = untoh16(net.ptr + 1);
+       ck_assert(host16 == 513);
+
+       net = chunk_from_chars(0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00);
+       host32 = untoh32(net.ptr + 2);
+       ck_assert(host32 == 67305985);
+
+       net = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x05,
+                                                  0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00);
+       host64 = untoh64(net.ptr + 4);
+       ck_assert(host64 == 578437695752307201ULL);
+}
+END_TEST
+
+/*******************************************************************************
+ * pad_len/round_up/down
+ */
+
+START_TEST(test_round)
+{
+       ck_assert_int_eq(pad_len(0, 4), 0);
+       ck_assert_int_eq(pad_len(1, 4), 3);
+       ck_assert_int_eq(pad_len(2, 4), 2);
+       ck_assert_int_eq(pad_len(3, 4), 1);
+       ck_assert_int_eq(pad_len(4, 4), 0);
+       ck_assert_int_eq(pad_len(5, 4), 3);
+
+       ck_assert_int_eq(round_up(0, 4), 0);
+       ck_assert_int_eq(round_up(1, 4), 4);
+       ck_assert_int_eq(round_up(2, 4), 4);
+       ck_assert_int_eq(round_up(3, 4), 4);
+       ck_assert_int_eq(round_up(4, 4), 4);
+       ck_assert_int_eq(round_up(5, 4), 8);
+
+       ck_assert_int_eq(round_down(0, 4), 0);
+       ck_assert_int_eq(round_down(1, 4), 0);
+       ck_assert_int_eq(round_down(2, 4), 0);
+       ck_assert_int_eq(round_down(3, 4), 0);
+       ck_assert_int_eq(round_down(4, 4), 4);
+       ck_assert_int_eq(round_down(5, 4), 4);
+}
+END_TEST
+
+/*******************************************************************************
+ * strpfx
+ */
+
+static struct {
+       char *str;
+       char *pfx;
+       bool prefix;
+       bool case_prefix;
+} strpfx_data[] = {
+       {"", "", TRUE, TRUE},
+       {"abc", "", TRUE, TRUE},
+       {"abc", "a", TRUE, TRUE},
+       {"abc", "ab", TRUE, TRUE},
+       {"abc", "abc", TRUE, TRUE},
+       {"abc", "abcd", FALSE, FALSE},
+       {"abc", "AB", FALSE, TRUE},
+       {"ABC", "ab", FALSE, TRUE},
+       {" abc", "abc", FALSE, FALSE},
+};
+
+START_TEST(test_strpfx)
+{
+       bool prefix;
+
+       prefix = strpfx(strpfx_data[_i].str, strpfx_data[_i].pfx);
+       ck_assert(prefix == strpfx_data[_i].prefix);
+       prefix = strcasepfx(strpfx_data[_i].str, strpfx_data[_i].pfx);
+       ck_assert(prefix == strpfx_data[_i].case_prefix);
+}
+END_TEST
+
+/*******************************************************************************
+ * memxor
+ */
+
+static void do_memxor(chunk_t a, chunk_t b, chunk_t exp)
+{
+       chunk_t dst;
+
+       dst = chunk_clonea(a);
+       dst.len = b.len;
+       memxor(dst.ptr, b.ptr, b.len);
+       ck_assert(chunk_equals(dst, exp));
+}
+
+START_TEST(test_memxor)
+{
+       chunk_t a, b, dst;
+       int i;
+
+       a = chunk_alloca(64);
+       memset(a.ptr, 0, a.len);
+       b = chunk_alloca(64);
+       for (i = 0; i < 64; i++)
+       {
+               b.ptr[i] = i;
+               b.len = i;
+               do_memxor(a, b, b);
+       }
+       b.len = 64;
+       do_memxor(a, b, b);
+
+       dst = chunk_clonea(a);
+       memxor(dst.ptr, b.ptr, b.len);
+       ck_assert(chunk_equals(dst, b));
+
+       memxor(dst.ptr, b.ptr, 0);
+       memxor(dst.ptr, b.ptr, 1);
+       memxor(dst.ptr + 1, b.ptr + 1, 1);
+       memxor(dst.ptr + 2, b.ptr + 2, b.len - 2);
+       ck_assert(chunk_equals(dst, a));
+}
+END_TEST
+
+START_TEST(test_memxor_aligned)
+{
+       u_int64_t a = 0, b = 0;
+       chunk_t ca, cb;
+       int i;
+
+       ca = chunk_from_thing(a);
+       cb = chunk_from_thing(b);
+
+       for (i = 0; i < 8; i++)
+       {
+               cb.ptr[i] = i + 1;
+       }
+
+       /* 64-bit aligned */
+       memxor(ca.ptr, cb.ptr, 8);
+       ck_assert(a == b);
+       /* 32-bit aligned source */
+       a = 0;
+       memxor(ca.ptr, cb.ptr + 4, 4);
+       ck_assert(chunk_equals(ca, chunk_from_chars(0x05, 0x06, 0x07, 0x08,
+                                                                                               0x00, 0x00, 0x00, 0x00)));
+       /* 16-bit aligned source */
+       a = 0;
+       memxor(ca.ptr, cb.ptr + 2, 6);
+       ck_assert(chunk_equals(ca, chunk_from_chars(0x03, 0x04, 0x05, 0x06,
+                                                                                               0x07, 0x08, 0x00, 0x00)));
+       /* 8-bit aligned source */
+       a = 0;
+       memxor(ca.ptr, cb.ptr + 1, 7);
+       ck_assert(chunk_equals(ca, chunk_from_chars(0x02, 0x03, 0x04, 0x05,
+                                                                                               0x06, 0x07, 0x08, 0x00)));
+}
+END_TEST
+
+/*******************************************************************************
+ * memstr
+ */
+
+static struct {
+       char *haystack;
+       char *needle;
+       size_t n;
+       int offset;
+} memstr_data[] = {
+       {NULL, NULL, 0, -1},
+       {NULL, NULL, 3, -1},
+       {NULL, "abc", 0, -1},
+       {NULL, "abc", 3, -1},
+       {"", "", 0, -1},
+       {"abc", NULL, 3, -1},
+       {"abc", "", 3, -1},
+       {"abc", "abc", 3, 0},
+       {" abc", "abc", 4, 1},
+       {" abc", "abc", 3, -1},
+       {"abcabc", "abc", 6, 0},
+       {" abc ", "abc", 5, 1},
+};
+
+START_TEST(test_memstr)
+{
+       char *ret;
+
+       ret = memstr(memstr_data[_i].haystack, memstr_data[_i].needle, memstr_data[_i].n);
+       if (memstr_data[_i].offset >= 0)
+       {
+               ck_assert(ret == memstr_data[_i].haystack + memstr_data[_i].offset);
+       }
+       else
+       {
+               ck_assert(ret == NULL);
+       }
+}
+END_TEST
+
+/*******************************************************************************
+ * translate
+ */
+
+static struct {
+       char *in;
+       char *from;
+       char *to;
+       char *out;
+} translate_data[] = {
+       {NULL, "", "", NULL},
+       {"abc", "", "", "abc"},
+       {"abc", "", "x", "abc"},
+       {"abc", "x", "", "abc"},
+       {"abc", "abc", "xyz", "xyz"},
+       {"aabbcc", "abc", "xyz", "xxyyzz"},
+       {"abbaccb", "abc", "xyz", "xyyxzzy"},
+       {"abxyzc", "abc", "xyz", "xyxyzz"},
+       {"abcdef", "abc", "xyz", "xyzdef"},
+       {"aaa", "abc", "xyz", "xxx"},
+       {"abc", "aaa", "xyz", "xbc"},
+       {"abc", "abc", "xxx", "xxx"},
+};
+
+START_TEST(test_translate)
+{
+       char *str, *ret;
+
+       str = strdupnull(translate_data[_i].in);
+       ret = translate(str, translate_data[_i].from, translate_data[_i].to);
+       ck_assert(ret == str);
+       if (ret != translate_data[_i].out)
+       {
+               ck_assert_str_eq(str, translate_data[_i].out);
+       }
+       free(str);
+}
+END_TEST
+
+/*******************************************************************************
+ * time_printf_hook
+ */
+
+static struct {
+       time_t in;
+       bool utc;
+       char *out;
+} time_data[] = {
+       {UNDEFINED_TIME, FALSE, "--- -- --:--:-- ----"},
+       {UNDEFINED_TIME, TRUE , "--- -- --:--:-- UTC ----"},
+       {1, FALSE, "Jan 01 01:00:01 1970"},
+       {1, TRUE , "Jan 01 00:00:01 UTC 1970"},
+       {1341150196, FALSE, "Jul 01 15:43:16 2012"},
+       {1341150196, TRUE , "Jul 01 13:43:16 UTC 2012"},
+};
+
+START_TEST(test_time_printf_hook)
+{
+       char buf[32];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%T", &time_data[_i].in, time_data[_i].utc);
+       ck_assert(len >= 0 && len < sizeof(buf));
+       ck_assert_str_eq(buf, time_data[_i].out);
+}
+END_TEST
+
+/*******************************************************************************
+ * time_delta_printf_hook
+ */
+
+static struct {
+       time_t a;
+       time_t b;
+       char *out;
+} time_delta_data[] = {
+       {0, 0, "0 seconds"},
+       {0, 1, "1 second"},
+       {0, -1, "1 second"},
+       {1, 0, "1 second"},
+       {0, 2, "2 seconds"},
+       {2, 0, "2 seconds"},
+       {0, 60, "60 seconds"},
+       {0, 120, "120 seconds"},
+       {0, 121, "2 minutes"},
+       {0, 3600, "60 minutes"},
+       {0, 7200, "120 minutes"},
+       {0, 7201, "2 hours"},
+       {0, 86400, "24 hours"},
+       {0, 172800, "48 hours"},
+       {0, 172801, "2 days"},
+       {172801, 86400, "24 hours"},
+};
+
+START_TEST(test_time_delta_printf_hook)
+{
+       char buf[16];
+       int len;
+
+       len = snprintf(buf, sizeof(buf), "%V", &time_delta_data[_i].a, &time_delta_data[_i].b);
+       ck_assert(len >= 0 && len < sizeof(buf));
+       ck_assert_str_eq(buf, time_delta_data[_i].out);
+}
+END_TEST
+
+/*******************************************************************************
+ * mark_from_string
+ */
+
+static struct {
+       char *s;
+       bool ok;
+       mark_t m;
+} mark_data[] = {
+       {NULL,                  FALSE, { 0 }},
+       {"",                    TRUE,  { 0, 0xffffffff }},
+       {"/",                   TRUE,  { 0, 0 }},
+       {"42",                  TRUE,  { 42, 0xffffffff }},
+       {"0x42",                TRUE,  { 0x42, 0xffffffff }},
+       {"x",                   FALSE, { 0 }},
+       {"42/",                 TRUE,  { 0, 0 }},
+       {"42/0",                TRUE,  { 0, 0 }},
+       {"42/x",                FALSE, { 0 }},
+       {"42/42",               TRUE,  { 42, 42 }},
+       {"42/0xff",             TRUE,  { 42, 0xff }},
+       {"0x42/0xff",   TRUE,  { 0x42, 0xff }},
+       {"/0xff",               TRUE,  { 0, 0xff }},
+       {"/x",                  FALSE, { 0 }},
+       {"x/x",                 FALSE, { 0 }},
+       {"0xffffffff/0x0000ffff",       TRUE, { 0x0000ffff, 0x0000ffff }},
+       {"0xffffffff/0xffffffff",       TRUE, { 0xffffffff, 0xffffffff }},
+};
+
+START_TEST(test_mark_from_string)
+{
+       mark_t mark;
+
+       if (mark_from_string(mark_data[_i].s, &mark))
+       {
+               ck_assert_int_eq(mark.value, mark_data[_i].m.value);
+               ck_assert_int_eq(mark.mask, mark_data[_i].m.mask);
+       }
+       else
+       {
+               ck_assert(!mark_data[_i].ok);
+       }
+}
+END_TEST
+
+Suite *utils_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       /* force a timezone to match non-UTC conversions */
+       setenv("TZ", "Europe/Zurich", 1);
+       tzset();
+
+       s = suite_create("utils");
+
+       tc = tcase_create("objects");
+       tcase_add_test(tc, test_objects);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("return functions");
+       tcase_add_test(tc, test_return_functions);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("timeval_add_ms");
+       tcase_add_test(tc, test_timeval_add_ms);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("htoun,untoh");
+       tcase_add_test(tc, test_htoun);
+       tcase_add_test(tc, test_untoh);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("round");
+       tcase_add_test(tc, test_round);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("string helper");
+       tcase_add_loop_test(tc, test_strpfx, 0, countof(strpfx_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("memxor");
+       tcase_add_test(tc, test_memxor);
+       tcase_add_test(tc, test_memxor_aligned);
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("memstr");
+       tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("translate");
+       tcase_add_loop_test(tc, test_translate, 0, countof(translate_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("printf_hooks");
+       tcase_add_loop_test(tc, test_time_printf_hook, 0, countof(time_data));
+       tcase_add_loop_test(tc, test_time_delta_printf_hook, 0, countof(time_delta_data));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("mark_from_string");
+       tcase_add_loop_test(tc, test_mark_from_string, 0, countof(mark_data));
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_vectors.c b/src/libstrongswan/tests/suites/test_vectors.c
new file mode 100644 (file)
index 0000000..f2817d3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+/*******************************************************************************
+ * Check if test vectors have been successful during transform registration
+ */
+
+START_TEST(test_vectors)
+{
+       fail_if(lib->crypto->get_test_vector_failures(lib->crypto));
+}
+END_TEST
+
+
+Suite *vectors_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("vectors");
+
+       tc = tcase_create("failures");
+       tcase_add_test(tc, test_vectors);
+       suite_add_tcase(s, tc);
+
+       return s;
+}
diff --git a/src/libstrongswan/tests/test_array.c b/src/libstrongswan/tests/test_array.c
deleted file mode 100644 (file)
index 2220d5a..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2013 Martin Willi
- * Copyright (C) 2013 revosec AG
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "test_suite.h"
-
-#include <collections/array.h>
-
-START_TEST(test_append_ptr)
-{
-       array_t *array;
-       uintptr_t x;
-       int i;
-
-       array = array_create(0, 0);
-
-       for (i = 0; i < 4; i++)
-       {
-               ck_assert_int_eq(array_count(array), 0);
-
-               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)3);
-               array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)4);
-               ck_assert_int_eq(array_count(array), 2);
-
-               /* 3, 4 */
-
-               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)1);
-               array_insert(array, 1, (void*)(uintptr_t)2);
-               ck_assert_int_eq(array_count(array), 4);
-
-               /* 1, 2, 3, 4 */
-
-               array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)5);
-               array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)0);
-               ck_assert_int_eq(array_count(array), 6);
-
-               /* 0, 1, 2, 3, 4, 5 */
-
-               ck_assert(array_remove(array, ARRAY_TAIL, &x));
-               ck_assert_int_eq(x, 5);
-               ck_assert(array_remove(array, 4, &x));
-               ck_assert_int_eq(x, 4);
-
-               if (i < 3)
-               {
-                       array_compress(array);
-               }
-
-               /* 0, 1, 2, 3 */
-
-               ck_assert(array_remove(array, 1, &x));
-               ck_assert_int_eq(x, 1);
-               ck_assert(array_remove(array, ARRAY_HEAD, &x));
-               ck_assert_int_eq(x, 0);
-
-               if (i < 2)
-               {
-                       array_compress(array);
-               }
-
-               /* 2, 3 */
-
-               ck_assert(array_remove(array, ARRAY_TAIL, &x));
-               ck_assert_int_eq(x, 3);
-               ck_assert(array_remove(array, ARRAY_TAIL, &x));
-               ck_assert_int_eq(x, 2);
-
-               if (i < 1)
-               {
-                       array_compress(array);
-               }
-
-               ck_assert_int_eq(array_count(array), 0);
-
-               ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
-               ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
-       }
-
-       array_destroy(array);
-}
-END_TEST
-
-START_TEST(test_append_obj)
-{
-       array_t *array;
-       int i, x, y[6] = {0, 1, 2, 3, 4, 5};
-
-       array = array_create(sizeof(y[0]), 0);
-
-       for (i = 0; i < 4; i++)
-       {
-               ck_assert_int_eq(array_count(array), 0);
-
-               array_insert(array, ARRAY_HEAD, &y[3]);
-               array_insert(array, ARRAY_TAIL, &y[4]);
-               ck_assert_int_eq(array_count(array), 2);;
-
-               /* 3, 4 */
-
-               array_insert(array, ARRAY_HEAD, &y[1]);
-               array_insert(array, 1, &y[2]);
-               ck_assert_int_eq(array_count(array), 4);
-
-               /* 1, 2, 3, 4 */
-
-               array_insert(array, ARRAY_TAIL, &y[5]);
-               array_insert(array, ARRAY_HEAD, &y[0]);
-               ck_assert_int_eq(array_count(array), 6);
-
-               /* 0, 1, 2, 3, 4, 5 */
-
-               ck_assert(array_remove(array, ARRAY_TAIL, &x));
-               ck_assert_int_eq(x, 5);
-               ck_assert(array_remove(array, 4, &x));
-               ck_assert_int_eq(x, 4);
-
-               if (i < 3)
-               {
-                       array_compress(array);
-               }
-
-               /* 0, 1, 2, 3 */
-
-               ck_assert(array_remove(array, ARRAY_HEAD, &x));
-               ck_assert_int_eq(x, 0);
-               ck_assert(array_remove(array, ARRAY_HEAD, &x));
-               ck_assert_int_eq(x, 1);
-
-               if (i < 2)
-               {
-                       array_compress(array);
-               }
-
-               /* 2, 3 */
-
-               ck_assert(array_remove(array, ARRAY_TAIL, &x));
-               ck_assert_int_eq(x, 3);
-               ck_assert(array_remove(array, ARRAY_HEAD, &x));
-               ck_assert_int_eq(x, 2);
-
-               if (i < 1)
-               {
-                       array_compress(array);
-               }
-
-               ck_assert_int_eq(array_count(array), 0);
-
-               ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
-               ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
-       }
-
-       array_destroy(array);
-}
-END_TEST
-
-START_TEST(test_enumerate)
-{
-       array_t *array;
-       int i, *x, y[6] = {0, 1, 2, 3, 4, 5};
-       enumerator_t *enumerator;
-
-       array = array_create(sizeof(y[0]), 0);
-
-       array_insert(array, ARRAY_TAIL, &y[0]);
-       array_insert(array, ARRAY_TAIL, &y[1]);
-       array_insert(array, ARRAY_TAIL, &y[2]);
-       array_insert(array, ARRAY_TAIL, &y[3]);
-       array_insert(array, ARRAY_TAIL, &y[4]);
-       array_insert(array, ARRAY_TAIL, &y[5]);
-
-       ck_assert_int_eq(array_count(array), 6);
-
-       /* 0, 1, 2, 3, 4, 5 */
-
-       i = 0;
-       enumerator = array_create_enumerator(array);
-       while (enumerator->enumerate(enumerator, &x))
-       {
-               ck_assert_int_eq(*x, y[i]);
-               i++;
-       }
-       enumerator->destroy(enumerator);
-       ck_assert_int_eq(i, 6);
-
-       i = 0;
-       enumerator = array_create_enumerator(array);
-       while (enumerator->enumerate(enumerator, &x))
-       {
-               ck_assert_int_eq(*x, y[i]);
-               if (i == 0 || i == 3 || i == 5)
-               {
-                       array_remove_at(array, enumerator);
-               }
-               i++;
-       }
-       enumerator->destroy(enumerator);
-       ck_assert_int_eq(i, 6);
-       ck_assert_int_eq(array_count(array), 3);
-
-       /* 1, 2, 4 */
-
-       i = 0;
-       enumerator = array_create_enumerator(array);
-       while (enumerator->enumerate(enumerator, &x))
-       {
-               switch (i++)
-               {
-                       case 0:
-                               ck_assert_int_eq(*x, y[1]);
-                               break;
-                       case 1:
-                               ck_assert_int_eq(*x, y[2]);
-                               break;
-                       case 2:
-                               ck_assert_int_eq(*x, y[4]);
-                               break;
-                       default:
-                               ck_assert(0);
-               }
-       }
-       enumerator->destroy(enumerator);
-
-       array_compress(array);
-
-       i = 0;
-       enumerator = array_create_enumerator(array);
-       while (enumerator->enumerate(enumerator, &x))
-       {
-               switch (i++)
-               {
-                       case 0:
-                               ck_assert_int_eq(*x, y[1]);
-                               break;
-                       case 1:
-                               ck_assert_int_eq(*x, y[2]);
-                               break;
-                       case 2:
-                               ck_assert_int_eq(*x, y[4]);
-                               break;
-                       default:
-                               ck_assert(0);
-               }
-       }
-       enumerator->destroy(enumerator);
-
-       array_destroy(array);
-}
-END_TEST
-
-static void invoke(void *data, int idx, void *user)
-{
-       int *y = user, *x = data;
-
-       ck_assert(idx < 3);
-
-       ck_assert_int_eq(y[idx], *x);
-       y[idx] = 0;
-}
-
-START_TEST(test_invoke)
-{
-       array_t *array;
-       int y[] = {1, 2, 3};
-
-       array = array_create(sizeof(y[0]), 0);
-
-       array_insert(array, ARRAY_TAIL, &y[0]);
-       array_insert(array, ARRAY_TAIL, &y[1]);
-       array_insert(array, ARRAY_TAIL, &y[2]);
-
-       array_invoke(array, invoke, y);
-
-       ck_assert_int_eq(y[0], 0);
-       ck_assert_int_eq(y[0], 0);
-       ck_assert_int_eq(y[0], 0);
-
-       array_destroy(array);
-}
-END_TEST
-
-typedef struct obj_t obj_t;
-
-struct obj_t {
-       void (*fun)(obj_t *obj);
-       int x;
-       int *counter;
-};
-
-static void fun(obj_t *obj)
-{
-       ck_assert(obj->x == (*obj->counter)++);
-}
-
-START_TEST(test_invoke_offset)
-{
-       array_t *array;
-       obj_t objs[5];
-       int i, counter = 0;
-
-       array = array_create(0, 0);
-
-       for (i = 0; i < countof(objs); i++)
-       {
-               objs[i].x = i;
-               objs[i].counter = &counter;
-               objs[i].fun = fun;
-
-               array_insert(array, ARRAY_TAIL, &objs[i]);
-       }
-
-       ck_assert_int_eq(countof(objs), array_count(array));
-
-       array_invoke_offset(array, offsetof(obj_t, fun));
-
-       ck_assert_int_eq(counter, countof(objs));
-
-       array_destroy(array);
-}
-END_TEST
-
-Suite *array_suite_create()
-{
-       Suite *s;
-       TCase *tc;
-
-       s = suite_create("array");
-
-       tc = tcase_create("add/remove ptr");
-       tcase_add_test(tc, test_append_ptr);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("add/remove obj");
-       tcase_add_test(tc, test_append_obj);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("enumerate");
-       tcase_add_test(tc, test_enumerate);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("invoke");
-       tcase_add_test(tc, test_invoke);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("invoke offset");
-       tcase_add_test(tc, test_invoke_offset);
-       suite_add_tcase(s, tc);
-
-       return s;
-}
diff --git a/src/libstrongswan/tests/test_asn1.c b/src/libstrongswan/tests/test_asn1.c
deleted file mode 100644 (file)
index 5ac4a94..0000000
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-
-#include "test_suite.h"
-
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
-#include <utils/chunk.h>
-
-/*******************************************************************************
- * algorithm_identifier
- */
-
-START_TEST(test_asn1_algorithmIdentifier)
-{
-       typedef struct {
-               int n;
-               chunk_t algid;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { OID_ECDSA_WITH_SHA1, chunk_from_chars(0x30, 0x09, 0x06, 0x07,
-                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
-               { OID_SHA1_WITH_RSA,   chunk_from_chars(0x30, 0x0d, 0x06, 0x09,
-                       0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00) },
-       };
-
-       chunk_t algid;
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               algid = asn1_algorithmIdentifier(test[i].n);
-               ck_assert(chunk_equals(algid, test[i].algid));
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * parse_algorithm_identifier
- */
-
-START_TEST(test_asn1_parse_algorithmIdentifier)
-{
-       typedef struct {
-               int alg;
-               bool empty;
-               chunk_t parameters;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { OID_ECDSA_WITH_SHA1, TRUE,  chunk_empty },
-               { OID_SHA1_WITH_RSA,   TRUE,  chunk_from_chars(0x05, 0x00) },
-               { OID_3DES_EDE_CBC,    FALSE, chunk_from_chars(0x04, 0x01, 0xaa) },
-               { OID_PBKDF2,          FALSE, chunk_from_chars(0x30, 0x01, 0xaa) }
-       };
-
-       chunk_t algid, parameters;
-       int i, alg;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               algid = asn1_wrap(ASN1_SEQUENCE, "mc",
-                                        asn1_build_known_oid(test[i].alg), test[i].parameters);
-               parameters = chunk_empty;
-               if (i == 2)
-               {
-                       alg = asn1_parse_algorithmIdentifier(algid, 0, NULL);
-               }
-               else
-               {
-                       alg = asn1_parse_algorithmIdentifier(algid, 0, &parameters);
-                       if (test[i].empty)
-                       {
-                               ck_assert(parameters.len == 0 && parameters.ptr == NULL);
-                       }
-                               else
-                       {
-                               ck_assert(chunk_equals(parameters, test[i].parameters));
-                       }
-               }
-               ck_assert(alg == test[i].alg);
-               chunk_free(&algid);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * known_oid
- */
-
-START_TEST(test_asn1_known_oid)
-{
-       typedef struct {
-               int n;
-               chunk_t oid;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { OID_UNKNOWN,    chunk_empty },
-               { OID_UNKNOWN,    chunk_from_chars(0x55, 0x04, 0x02) },
-               { OID_COUNTRY,    chunk_from_chars(0x55, 0x04, 0x06) },
-               { OID_STRONGSWAN, chunk_from_chars(0x2b, 0x06, 0x01, 0x04, 0x01,
-                                                                                  0x82, 0xa0, 0x2a, 0x01) }
-       };
-
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               ck_assert(asn1_known_oid(test[i].oid) == test[i].n);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * build_known_oid
- */
-
-START_TEST(test_asn1_build_known_oid)
-{
-       typedef struct {
-               int n;
-               chunk_t oid;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { OID_UNKNOWN,    chunk_empty },
-               { OID_MAX,        chunk_empty },
-               { OID_COUNTRY,    chunk_from_chars(0x06, 0x03, 0x55, 0x04, 0x06) },
-               { OID_STRONGSWAN, chunk_from_chars(0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
-                                                                                  0x01, 0x82, 0xa0, 0x2a, 0x01) }
-       };
-
-       int i;
-       chunk_t oid = chunk_empty;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               oid = asn1_build_known_oid(test[i].n);
-               if (test[i].oid.len == 0)
-               {
-                       ck_assert(oid.len == 0 && oid.ptr == NULL);
-               }
-               else
-               {
-                       ck_assert(chunk_equals(oid, test[i].oid));
-                       chunk_free(&oid);
-               }
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * oid_from_string
- */
-
-START_TEST(test_asn1_oid_from_string)
-{
-       typedef struct {
-               char *string;
-               chunk_t oid;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { "",  chunk_empty },
-               { " ", chunk_empty },
-               { "0.2.262.1", chunk_from_chars(
-                       0x02, 0x82, 0x06, 0x01) },
-               { "1.2.840.10045.4.1", chunk_from_chars(
-                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
-               { "1.3.6.1.4.1.36906.1", chunk_from_chars(
-                       0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) },
-               { "2.16.840.1.101.3.4.2.1", chunk_from_chars(
-                       0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01) },
-               { "0.10.100.1000.10000.100000.1000000.10000000.100000000.268435455",
-                       chunk_from_chars(0x0a,0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d,
-                       0x20, 0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00,
-                       0xaf, 0xd7, 0xc2, 0x00, 0xff, 0xff, 0xff, 0x7f) },
-               { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137."
-                 "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388."
-                 "2097153", chunk_from_chars(
-                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
-                       0x81, 0x00, 0x81, 0x01, 0x81, 0x02, 0x81, 0x03, 0x81, 0x04,
-                       0x81, 0x05, 0x81, 0x06, 0x81, 0x07, 0x81, 0x08, 0x81, 0x09,
-                       0x82, 0x00, 0x82, 0x01, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04,
-                       0x82, 0x05, 0x82, 0x06, 0x82, 0x07, 0x82, 0x08, 0x82, 0x09,
-                       0x83, 0x00, 0x83, 0x01, 0x83, 0x02, 0x83, 0x03, 0x83, 0x04,
-                       0x81, 0x80, 0x80, 0x01) },
-               { "0.1.2.3.4.5.6.7.8.9.10.128.129.130.131.132.133.134.135.136.137."
-                 "256.257.258.259.260.261.262.263.264.265.384.385.386.387.388."
-                 "1.2097153", chunk_empty },
-               { "1.a.2.b.3", chunk_empty }
-       };
-
-       int i;
-       chunk_t oid = chunk_empty;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               oid = asn1_oid_from_string(test[i].string);
-               if (test[i].oid.len == 0)
-               {
-                       ck_assert(oid.len == 0 && oid.ptr == NULL);
-               }
-               else
-               {
-                       ck_assert(chunk_equals(oid, test[i].oid));
-                       chunk_free(&oid);
-               }
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * oid_to_string
- */
-
-START_TEST(test_asn1_oid_to_string)
-{
-       typedef struct {
-               char *string;
-               chunk_t oid;
-       } testdata_t;
-
-       testdata_t test[] = {
-               {  NULL,  chunk_empty },
-               { "0.2.262.1", chunk_from_chars(
-                       0x02, 0x82, 0x06, 0x01) },
-               { "1.2.840.10045.4.1", chunk_from_chars(
-                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01) },
-               { "1.3.6.1.4.1.36906.1", chunk_from_chars(
-                       0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa0, 0x2a, 0x01) },
-               { "2.16.840.1.101.3.4.2.1", chunk_from_chars(
-                       0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01) },
-               { "0.10.100.1000.10000.100000.1000000.10000000.100000000.268435455",
-                       chunk_from_chars( 0x0a, 0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d,
-                       0x20, 0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00,
-                       0xaf, 0xd7, 0xc2, 0x00, 0xff, 0xff, 0xff, 0x7f) },
-               { NULL, chunk_from_chars(
-                       0x0a, 0x02, 0x64, 0x87, 0x68, 0xce, 0x10, 0x86, 0x8d, 0x20,
-                       0xbd, 0x84, 0x40, 0x84, 0xe2, 0xad, 0x00, 0xaf, 0xd7, 0xc2, 0x00,
-                   0xff, 0xff, 0xff, 0x7f) },
-               { NULL, chunk_from_chars(0x0a, 0x87) }
-       };
-
-       int i;
-       char *string = NULL;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               string = asn1_oid_to_string(test[i].oid);
-               if (test[i].string == NULL)
-               {
-                       ck_assert(string == NULL);
-               }
-               else
-               {
-                       ck_assert(streq(string, test[i].string));
-                       free(string);
-               }
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * length
- */
-
-START_TEST(test_asn1_length)
-{
-       chunk_t a;
-
-       a = chunk_empty;
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04);
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04, 0x00);
-       ck_assert(asn1_length(&a) == 0);
-
-       a = chunk_from_chars(0x04, 0x01);
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04, 0x01, 0xaa);
-       ck_assert(asn1_length(&a) == 1);
-
-       a = chunk_from_chars(0x04, 0x7f, 0xaa);
-       a.len = 2 + 127;
-       ck_assert(asn1_length(&a) == 127);
-
-       a = chunk_from_chars(0x04, 0x80, 0xaa);
-       a.len = 2 + 128;
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04, 0x81);
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04, 0x81, 0x80, 0xaa);
-       ck_assert(asn1_length(&a) == ASN1_INVALID_LENGTH);
-
-       a = chunk_from_chars(0x04, 0x81, 0x80, 0xaa);
-       a.len = 3 + 128;
-       ck_assert(asn1_length(&a) == 128);
-
-       a = chunk_from_chars(0x04, 0x82, 0x01, 0x02, 0xaa);
-       a.len = 4 + 258;
-       ck_assert(asn1_length(&a) == 258);
-
-       a = chunk_from_chars(0x04, 0x83, 0x01, 0x02, 0x03, 0xaa);
-       a.len = 5 + 66051;
-       ck_assert(asn1_length(&a) == 66051);
-}
-END_TEST
-
-/*******************************************************************************
- * unwrap
- */
-
-START_TEST(test_asn1_unwrap)
-{
-       chunk_t c0 = chunk_from_chars(0x30);
-       chunk_t c1 = chunk_from_chars(0x30, 0x01, 0xaa);
-       chunk_t c2 = chunk_from_chars(0x30, 0x80);
-       chunk_t c3 = chunk_from_chars(0x30, 0x81);
-       chunk_t c4 = chunk_from_chars(0x30, 0x81, 0x01, 0xaa);
-       chunk_t c5 = chunk_from_chars(0x30, 0x81, 0x02, 0xaa);
-
-       chunk_t inner;
-       chunk_t inner_ref = chunk_from_chars(0xaa);
-
-       ck_assert(asn1_unwrap(&c0, &inner) == ASN1_INVALID);
-
-       ck_assert(asn1_unwrap(&c1, &inner) == ASN1_SEQUENCE);
-
-       ck_assert(chunk_equals(inner, inner_ref));
-
-       ck_assert(asn1_unwrap(&c2, &inner) == ASN1_INVALID);
-
-       ck_assert(asn1_unwrap(&c3, &inner) == ASN1_INVALID);
-
-       ck_assert(asn1_unwrap(&c4, &inner) == ASN1_SEQUENCE);
-
-       ck_assert(chunk_equals(inner, inner_ref));
-
-       ck_assert(asn1_unwrap(&c5, &inner) == ASN1_INVALID);
-}
-END_TEST
-
-/*******************************************************************************
- * is_asn1
- */
-
-START_TEST(test_is_asn1)
-{
-       typedef struct {
-               bool asn1;
-               chunk_t chunk;
-       } testdata_t;
-
-       u_char buf[8];
-       chunk_t chunk_zero = { buf, 0 };
-       chunk_t chunk_mean = {   0, 1 };
-
-       testdata_t test[] = {
-               { FALSE, chunk_zero },
-               { FALSE, chunk_empty },
-               { FALSE, chunk_mean },
-               { TRUE,  chunk_from_chars(0x30, 0x00) },
-               { TRUE,  chunk_from_chars(0x31, 0x00) },
-               { TRUE,  chunk_from_chars(0x04, 0x00) },
-               { FALSE, chunk_from_chars(0x02, 0x00) },
-               { FALSE, chunk_from_chars(0x30, 0x01) },
-               { FALSE, chunk_from_chars(0x30, 0x80) },
-               { TRUE,  chunk_from_chars(0x30, 0x01, 0xa1) },
-               { FALSE, chunk_from_chars(0x30, 0x01, 0xa1, 0xa2) },
-               { TRUE,  chunk_from_chars(0x30, 0x01, 0xa1, 0x0a) },
-               { FALSE, chunk_from_chars(0x30, 0x01, 0xa1, 0xa2, 0x0a) },
-       };
-
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               ck_assert(is_asn1(test[i].chunk) == test[i].asn1);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * is_printablestring
- */
-
-START_TEST(test_asn1_is_printablestring)
-{
-       typedef struct {
-               bool printable;
-               char *string;
-       } testdata_t;
-
-
-       testdata_t test[] = {
-               { TRUE,  "" },
-               { TRUE,  "Z" },
-               { FALSE, "Z#" },
-               { FALSE, "&Z" },
-               { FALSE, "Z@z" },
-               { FALSE, "!" },  { FALSE, "*" },  { FALSE, "$" },  { FALSE, "%" },
-               { FALSE, "[" },  { FALSE, "]" },  { FALSE, "{" },  { FALSE, "}" },
-               { FALSE, "|" },  { FALSE, "~" },  { FALSE, "^" },  { FALSE, "_" },
-               { FALSE, "\"" }, { FALSE, "\\" }, { FALSE, "ä" },  { FALSE, "à" },
-               { TRUE,  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-                                "0123456789 '()+,-./:=?" },
-       };
-
-       chunk_t chunk;
-       int i;
-
-       ck_assert(asn1_is_printablestring(chunk_empty));
-
-       for (i = 0; i < countof(test); i++)
-       {
-               chunk = chunk_from_str(test[i].string);
-               ck_assert(asn1_is_printablestring(chunk) == test[i].printable);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * to_time
- */
-
-START_TEST(test_asn1_to_time)
-{
-       typedef struct {
-               time_t time;
-               u_int8_t type;
-               char *string;
-       } testdata_t;
-
-       testdata_t test[] = {
-               {     352980, 0x18, "197001050203Z" },
-               {     352984, 0x18, "19700105020304Z" },
-               {     352980, 0x17, "7001050203Z" },
-               {     347580, 0x17, "7001050203+0130" },
-               {     358380, 0x17, "7001050203-0130" },
-               {     352984, 0x17, "700105020304Z" },
-               {     347584, 0x17, "700105020304+0130" },
-               {     358384, 0x17, "700105020304-0130" },
-               {          0, 0x17, "700105020304+01" },
-               {          0, 0x17, "700105020304-01" },
-               {          0, 0x17, "700105020304" },
-               {          0, 0x17, "70010502Z" },
-               {          0, 0x17, "7001050203xxZ" },
-               {          0, 0x17, "7000050203Z" },
-               {          0, 0x17, "7013050203Z" },
-               {    5097600, 0x17, "7003010000Z" },
-               {   68256000, 0x17, "7203010000Z" },
-               {  951868800, 0x17, "0003010000Z" },
-               { 4107542400, 0x18, "210003010000Z" }
-       };
-
-       int i;
-       chunk_t chunk;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               if (test[i].time > TIME_32_BIT_SIGNED_MAX && sizeof(time_t) == 4)
-               {
-                       continue;
-               }
-               chunk = chunk_from_str(test[i].string);
-               ck_assert(asn1_to_time(&chunk, test[i].type) == test[i].time);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * from_time
- */
-
-START_TEST(test_asn1_from_time)
-{
-       typedef struct {
-               time_t time;
-               u_int8_t type;
-               chunk_t chunk;
-       } testdata_t;
-
-       testdata_t test[] = {
-               {     352984, 0x18, chunk_from_chars(
-                                         0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
-                                         0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
-               {     352984, 0x17, chunk_from_chars(
-                                         0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
-                                         0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
-               { 1078099200, 0x17, chunk_from_chars(
-                                         0x17, 0x0d, 0x30, 0x34, 0x30, 0x33, 0x30, 0x31,
-                                         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) },
-        { 4107542400, 0x18, chunk_from_chars( 
-                                         0x18, 0x0f, 0x32, 0x31, 0x30, 0x30, 0x30, 0x33, 0x30, 0x31,
-                                         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a) }
-       };
-
-       int i;
-       chunk_t chunk;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               if (test[i].time > TIME_32_BIT_SIGNED_MAX && sizeof(time_t) == 4)
-        {
-                       continue;
-        }
-               chunk = asn1_from_time(&test[i].time, test[i].type);
-               ck_assert(chunk_equals(chunk, test[i].chunk));
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * parse_time
- */
-
-START_TEST(test_asn1_parse_time)
-{
-       typedef struct {
-               time_t time;
-               chunk_t chunk;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { 352984, chunk_from_chars(
-                                       0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
-                                       0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
-               { 352984, chunk_from_chars(
-                                       0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x35,
-                                       0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x5a) },
-               {      0, chunk_from_chars(0x05, 0x00) }
-       };
-
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               ck_assert(asn1_parse_time(test[i].chunk, 0) == test[i].time);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * build_object
- */
-
-START_TEST(test_asn1_build_object)
-{
-       typedef struct {
-               size_t len;
-               size_t size;
-               u_char *b;
-       } testdata_t;
-
-       u_char b0[] = { 0x05, 0x00 };
-       u_char b1[] = { 0x04, 0x7f };
-       u_char b2[] = { 0x04, 0x81, 0x80 };
-       u_char b3[] = { 0x04, 0x81, 0xff };
-       u_char b4[] = { 0x04, 0x82, 0x01, 0x00 };
-       u_char b5[] = { 0x04, 0x82, 0xff, 0xff };
-       u_char b6[] = { 0x04, 0x83, 0x01, 0x00, 0x00 };
-
-       testdata_t test[] = {
-               {     0, sizeof(b0), b0 },
-               {   127, sizeof(b1), b1 },
-               {   128, sizeof(b2), b2 },
-               {   255, sizeof(b3), b3 },
-               {   256, sizeof(b4), b4 },
-               { 65535, sizeof(b5), b5 },
-               { 65536, sizeof(b6), b6 }
-       };
-
-       chunk_t a = chunk_empty;
-       u_char *pos;
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               pos = asn1_build_object(&a, test[i].b[0], test[i].len);
-               ck_assert(pos == (a.ptr + test[i].size));
-               ck_assert(a.len == test[i].size + test[i].len);
-               ck_assert(memeq(a.ptr, test[i].b, test[i].size)); 
-               chunk_free(&a);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * simple_object
- */
-
-START_TEST(test_asn1_simple_object)
-{
-       chunk_t a = chunk_empty;
-       chunk_t b = chunk_from_chars(0x04, 0x05, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5);
-       chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4, 0xa5);
-
-       a = asn1_simple_object(0x04, c);
-       ck_assert(chunk_equals(a, b));
-       chunk_free(&a);
-}
-END_TEST
-
-/*******************************************************************************
- * parse_simple_object
- */
-
-START_TEST(test_asn1_parse_simple_object)
-{
-       typedef struct {
-               bool res;
-               int type;
-               chunk_t chunk;
-       } testdata_t;
-
-       testdata_t test[] = {
-               { FALSE, 0x04, chunk_from_chars(0x04) },
-               { FALSE, 0x04, chunk_from_chars(0x02, 0x01, 0x55) },
-               { FALSE, 0x04, chunk_from_chars(0x04, 0x01) },
-               { TRUE,  0x04, chunk_from_chars(0x04, 0x01, 0x55) },
-               { TRUE,  0x06, chunk_from_chars(0x06, 0x02, 0x55, 0x03) },
-               { TRUE,  0x06, chunk_from_chars(0x06, 0x00) },
-               { TRUE,  0x13, chunk_from_chars(0x13, 0x01, 0x55), }
-       };
-
-       int i;
-       bool res;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               res = asn1_parse_simple_object(&test[i].chunk, test[i].type, 0, "test");
-               ck_assert(res == test[i].res);
-               if (res && test[i].chunk.len)
-               {
-                       ck_assert(*test[i].chunk.ptr == 0x55);
-               }
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * bitstring
- */
-
-START_TEST(test_asn1_bitstring)
-{
-       chunk_t a = chunk_empty;
-       chunk_t b = chunk_from_chars(0x03, 0x05, 0x00, 0xa1, 0xa2, 0xa3, 0xa4);
-       chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4);
-       chunk_t d = chunk_clone(c);
-
-       a = asn1_bitstring("c", c);
-       ck_assert(chunk_equals(a, b));
-       chunk_free(&a);
-
-       a = asn1_bitstring("m", d);
-       ck_assert(chunk_equals(a, b));
-       chunk_free(&a);
-}
-END_TEST
-
-/*******************************************************************************
- * integer
- */
-
-START_TEST(test_asn1_integer)
-{
-       typedef struct {
-               chunk_t b;
-               chunk_t c;
-       } testdata_t;
-
-       chunk_t b0 = chunk_from_chars(0x02, 0x01, 0x00);
-       chunk_t b1 = chunk_from_chars(0x02, 0x01, 0x7f);
-       chunk_t b2 = chunk_from_chars(0x02, 0x02, 0x00, 0x80);
-
-       chunk_t c0 = chunk_empty;
-       chunk_t c1 = chunk_from_chars(0x7f);
-       chunk_t c2 = chunk_from_chars(0x80);
-       chunk_t c3 = chunk_from_chars(0x00, 0x80);
-
-       testdata_t test[] = {
-               { b0, c0 },
-               { b1, c1 },
-               { b2, c2 },
-               { b2, c3 }
-       };
-
-       chunk_t a = chunk_empty;
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               a = asn1_integer("c", test[i].c);
-               ck_assert(chunk_equals(a, test[i].b));
-               chunk_free(&a);
-
-               a = asn1_integer("m", chunk_clone(test[i].c));
-               ck_assert(chunk_equals(a, test[i].b));
-               chunk_free(&a);
-       }
-}
-END_TEST
-
-/*******************************************************************************
- * parse_integer_uint64
- */
-
-START_TEST(test_asn1_parse_integer_uint64)
-{
-       typedef struct {
-               u_int64_t n;
-               chunk_t chunk;
-       } testdata_t;
-
-
-       testdata_t test[] = {
-               {             67305985ULL, chunk_from_chars(
-                                               0x04, 0x03, 0x02, 0x01) },
-               {   578437695752307201ULL, chunk_from_chars(
-                                               0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01) },
-               { 18446744073709551615ULL, chunk_from_chars(
-                                               0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff) }
-       };
-
-       int i;
-
-       for (i = 0; i < countof(test); i++)
-       {
-               ck_assert(asn1_parse_integer_uint64(test[i].chunk) == test[i].n);
-       }
-}
-END_TEST
-
-Suite *asn1_suite_create()
-{
-       Suite *s;
-       TCase *tc;
-
-       s = suite_create("asn1");
-
-       tc = tcase_create("algorithmIdentifier");
-       tcase_add_test(tc, test_asn1_algorithmIdentifier);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("parse_algorithmIdentifier");
-       tcase_add_test(tc, test_asn1_parse_algorithmIdentifier);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("known_oid");
-       tcase_add_test(tc, test_asn1_known_oid);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("build_known_oid");
-       tcase_add_test(tc, test_asn1_build_known_oid);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("oid_from_string");
-       tcase_add_test(tc, test_asn1_oid_from_string);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("oid_to_string");
-       tcase_add_test(tc, test_asn1_oid_to_string);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("length");
-       tcase_add_test(tc, test_asn1_length);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("unwrap");
-       tcase_add_test(tc, test_asn1_unwrap);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("is_asn1");
-       tcase_add_test(tc, test_is_asn1);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("is_printablestring");
-       tcase_add_test(tc, test_asn1_is_printablestring);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("to_time");
-       tcase_add_test(tc, test_asn1_to_time);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("from_time");
-       tcase_add_test(tc, test_asn1_from_time);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("parse_time");
-       tcase_add_test(tc, test_asn1_parse_time);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("build_object");
-       tcase_add_test(tc, test_asn1_build_object);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("simple_object");
-       tcase_add_test(tc, test_asn1_simple_object);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("parse_simple_object");
-       tcase_add_test(tc, test_asn1_parse_simple_object);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("bitstring");
-       tcase_add_test(tc, test_asn1_bitstring);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("integer");
-       tcase_add_test(tc, test_asn1_integer);
-       suite_add_tcase(s, tc);
-
-       tc = tcase_create("parse_integer_uint64");
-       tcase_add_test(tc, test_asn1_parse_integer_uint64);
-       suite_add_tcase(s, tc);
-
-       return s;
-}
diff --git a/src/libstrongswan/tests/test_bio_reader.c b/src/libstrongswan/tests/test_bio_reader.c
deleted file mode 100644 (file)
index 45b20db..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (C) 2013 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "test_suite.h"
-
-#include <bio/bio_reader.h>
-
-/*******************************************************************************
- * different integer reads
- */
-
-#define assert_integer_read(data, bits, val) ({ \
-       bio_reader_t *reader = bio_reader_create(data); \
-       typeof(val) i; \
-       for (i = 0; reader->remaining(reader) >= (bits / 8); i++) \
-       { \
-               ck_assert(reader->read_uint##bits(reader, &val)); \
-               ck_assert_int_eq(i, val); \
-       } \
-       ck_assert_int_eq(i, data.len / (bits / 8)); \
-       ck_assert_int_eq(reader->remaining(reader), data.len % (bits / 8)); \
-       ck_assert(!reader->read_uint##bits(reader, &val)); \
-       reader->destroy(reader); \
-})
-
-#define assert_integer_read_uneven(data, bits, val) ({ \
-       int i; \
-       for (i = 0; i <= bits / 8; i++, data.len++) \
-       { \
-               assert_integer_read(data, bits, val); \
-       } \
-})
-
-#define assert_basic_read(bits, val) ({ \
-       chunk_t data; \
-       data = chunk_empty; \
-       assert_integer_read(data, bits, val); \
-       data = chunk_alloca(bits / 8); \
-       memset(data.ptr, 0, data.len); \
-       data.len = 0; \
-       assert_integer_read_uneven(data, bits, val); \
-})
-
-#define assert_extended_read(data, bits, val) ({ \
-       chunk_t extended = chunk_alloca(data.len + bits / 8); \
-       memset(extended.ptr, 0, extended.len); \
-       extended.ptr[extended.len - 1] = data.len / (bits / 8); \
-       memcpy(extended.ptr, data.ptr, data.len); \
-       extended.len = data.len; \
-       assert_integer_read_uneven(extended, bits, val); \
-})
-
-START_TEST(test_read_uint8)
-{
-       chunk_t data = chunk_from_chars(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07);
-       u_int8_t val;
-
-       assert_integer_read(data, 8, val);
-       assert_basic_read(8, val);
-       assert_extended_read(data, 8, val);
-}
-END_TEST
-
-START_TEST(test_read_uint16)
-{
-       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03);
-       u_int16_t val;
-
-       assert_integer_read(data, 16, val);
-       assert_basic_read(16, val);
-       assert_extended_read(data, 16, val);
-}
-END_TEST
-
-START_TEST(test_read_uint24)
-{
-       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03);
-       u_int32_t val;
-
-       assert_integer_read(data, 24, val);
-       assert_basic_read(24, val);
-       assert_extended_read(data, 24, val);
-}
-END_TEST
-
-START_TEST(test_read_uint32)
-{
-       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                                                                       0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03);
-       u_int32_t val;
-
-       assert_integer_read(data, 32, val);
-       assert_basic_read(32, val);
-       assert_extended_read(data, 32, val);
-}
-END_TEST
-
-START_TEST(test_read_uint64)
-{
-       chunk_t data = chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-                                                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03);
-       u_int64_t val;
-
-       assert_integer_read(data, 64, val);
-       assert_basic_read(64, val);
-       assert_extended_read(data, 64, val);
-}
-END_TEST
-
-/*******************************************************************************
- * different integer reads from the end of a buffer
- */
-
-#define assert_integer_read_end(data, bits, val) ({ \
-       bio_reader_t *reader = bio_reader_create(data); \
-       typeof(val) i; \
-       for (i = 0; reader->remaining(reader) >= (bits / 8); i++) \
-       { \
-               ck_assert(reader->read_uint##bits##_end(reader, &val)); \
-               ck_assert_int_eq(i, val); \
-       } \
-       ck_assert_int_eq(i, data.len / (bits / 8)); \
-       ck_assert_int_eq(reader->remaining(reader), data.len % (bits / 8)); \
-       ck_assert(!reader->read_uint##bits##_end(reader, &val)); \
-       reader->destroy(reader); \
-})
-
-#define assert_integer_read_end_uneven(data, bits, val) ({ \
-       int i; \
-       data.ptr += bits / 8; \
-       for (i = 0; i <= bits / 8; i++, data.ptr--, data.len++) \
-       { \
-               assert_integer_read_end(data, bits, val); \
-       } \
-})
-
-#define assert_basic_read_end(bits, val) ({ \