Create test/testutil.h for unit test helper macros
authorMike Bland <mbland@acm.org>
Sat, 7 Jun 2014 17:05:50 +0000 (13:05 -0400)
committerMatt Caswell <matt@openssl.org>
Tue, 10 Jun 2014 18:24:46 +0000 (19:24 +0100)
Defines SETUP_TEST_FIXTURE and EXECUTE_TEST, and updates ssl/heartbeat_test.c
using these macros. SETUP_TEST_FIXTURE makes use of the new TEST_CASE_NAME
macro, defined to use __func__ or __FUNCTION__ on platforms that support those
symbols, or to use the file name and line number otherwise. This should fix
several reported build problems related to lack of C99 support.

ssl/heartbeat_test.c
test/testutil.h [new file with mode: 0644]

index d8cc559981c4446bd0ca0bc11733ee521e6f0890..a0a3690096d504e74881c062852f3a6cdfa065c6 100644 (file)
@@ -38,6 +38,7 @@
  * http://mike-bland.com/tags/heartbleed.html
  */
 
+#include "../test/testutil.h"
 #include "../ssl/ssl_locl.h"
 #include <ctype.h>
 #include <stdio.h>
@@ -263,13 +264,10 @@ static int honest_payload_size(unsigned char payload_buf[])
        }
 
 #define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
-       HEARTBEAT_TEST_FIXTURE fixture = set_up_##type(__func__);\
-       int result = 0
+  SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type)
 
 #define EXECUTE_HEARTBEAT_TEST()\
-       if (execute_heartbeat(fixture) != 0) result = 1;\
-       tear_down(fixture);\
-       return result
+  EXECUTE_TEST(execute_heartbeat, tear_down)
 
 static int test_dtls1_not_bleeding()
        {
diff --git a/test/testutil.h b/test/testutil.h
new file mode 100644 (file)
index 0000000..3e9cb84
--- /dev/null
@@ -0,0 +1,116 @@
+/* test/testutil.h */
+/*
+ * Utilities for writing OpenSSL unit tests.
+ *
+ * More information:
+ * http://wiki.openssl.org/index.php/How_To_Write_Unit_Tests_For_OpenSSL
+ *
+ * Author: Mike Bland (mbland@acm.org)
+ * Date:   2014-06-07
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifndef HEADER_TESTUTIL_H
+#define HEADER_TESTUTIL_H
+
+/* SETUP_TEST_FIXTURE and EXECUTE_TEST macros for test case functions.
+ *
+ * SETUP_TEST_FIXTURE will call set_up() to create a new TEST_FIXTURE_TYPE
+ * object called "fixture". It will also allocate the "result" variable used
+ * by EXECUTE_TEST. set_up() should take a const char* specifying the test
+ * case name and return a TEST_FIXTURE_TYPE by value.
+ *
+ * EXECUTE_TEST will pass fixture to execute_func() by value, call
+ * tear_down(), and return the result of execute_func(). execute_func() should
+ * take a TEST_FIXTURE_TYPE by value and return zero on success or one on
+ * failure.
+ *
+ * Unit tests can define their own SETUP_TEST_FIXTURE and EXECUTE_TEST
+ * variations like so:
+ *
+ * #define SETUP_FOOBAR_TEST_FIXTURE()\
+ *   SETUP_TEST_FIXTURE(FOOBAR_TEST_FIXTURE, set_up_foobar)
+ *
+ * #define EXECUTE_FOOBAR_TEST()\
+ *   EXECUTE_TEST(execute_foobar, tear_down_foobar)
+ *
+ * Then test case functions can take the form:
+ *
+ * static int test_foobar_feature()
+ *     {
+ *     SETUP_FOOBAR_TEST_FIXTURE();
+ *     [...set individual members of fixture...]
+ *     EXECUTE_FOOBAR_TEST();
+ *     }
+ */
+#define SETUP_TEST_FIXTURE(TEST_FIXTURE_TYPE, set_up)\
+       TEST_FIXTURE_TYPE fixture = set_up(TEST_CASE_NAME);\
+       int result = 0
+
+#define EXECUTE_TEST(execute_func, tear_down)\
+       if (execute_func(fixture) != 0) result = 1;\
+       tear_down(fixture);\
+       return result
+
+/* TEST_CASE_NAME is defined as the name of the test case function where
+ * possible; otherwise we get by with the file name and line number.
+ */
+#if __STDC_VERSION__ < 199901L
+#if defined(_MSC_VER)
+#define TEST_CASE_NAME __FUNCTION__
+#else
+#define testutil_stringify_helper(s) #s
+#define testutil_stringify(s) testutil_stringify_helper(s)
+#define TEST_CASE_NAME __FILE__ ":" testutil_stringify(__LINE__)
+#endif /* _MSC_VER */
+#else
+#define TEST_CASE_NAME __func__
+#endif /* __STDC_VERSION__ */
+
+#endif /* HEADER_TESTUTIL_H */