Guarantee single argument evaluation for test macros.
authorPauli <paul.dale@oracle.com>
Wed, 12 Apr 2017 22:51:28 +0000 (08:51 +1000)
committerRich Salz <rsalz@openssl.org>
Thu, 13 Apr 2017 12:33:12 +0000 (08:33 -0400)
Add test case that checks some of them.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3208)

test/README
test/test_test.c
test/testutil.h

index cf7e4d4..7831c86 100644 (file)
@@ -134,4 +134,16 @@ conditions.  These macros produce an error message in a standard format if the
 condition is not met (and nothing if the condition is met).  Additional
 information can be presented with the TEST_info macro that takes a printf
 format string and arguments.  TEST_error is useful for complicated conditions,
-it also takes a printf format string and argument.
+it also takes a printf format string and argument.  In all cases the TEST_xxx
+macros are guaranteed to evaluate their arguments exactly once.  This means
+that expressions with side effects are allowed as parameters.  Thus,
+
+    if (!TEST_ptr(ptr = OPENSSL_malloc(..)))
+
+works fine and can be used in place of:
+
+    ptr = OPENSSL_malloc(..);
+    if (!TEST_ptr(ptr))
+
+The former produces a more meaningful message on failure than the latter.
+
index df4725a..a154289 100644 (file)
@@ -259,6 +259,61 @@ static int test_messages(void)
     return 1;
 }
 
+static int test_single_eval(void)
+{
+    int i = 4;
+    long l = -9000;
+    char c = 'd';
+    unsigned char uc = 22;
+    unsigned long ul = 500;
+    size_t st = 1234;
+    char buf[4] = { 0 }, *p = buf;
+
+           /* int */
+    return TEST_int_eq(i++, 4)
+           && TEST_int_eq(i, 5)
+           && TEST_int_gt(++i, 5)
+           && TEST_int_le(5, i++)
+           && TEST_int_ne(--i, 5)
+           && TEST_int_eq(12, i *= 2)
+           /* Long */
+           && TEST_long_eq(l--, -9000L)
+           && TEST_long_eq(++l, -9000L)
+           && TEST_long_ne(-9000L, l /= 2)
+           && TEST_long_lt(--l, -4500L)
+           /* char */
+           && TEST_char_eq(++c, 'e')
+           && TEST_char_eq('e', c--)
+           && TEST_char_ne('d', --c)
+           && TEST_char_le('b', --c)
+           && TEST_char_lt(c++, 'c')
+           /* unsigned char */
+           && TEST_uchar_eq(22, uc++)
+           && TEST_uchar_eq(uc /= 2, 11)
+           && TEST_ulong_eq(ul ^= 1, 501)
+           && TEST_ulong_eq(502, ul ^= 3)
+           && TEST_ulong_eq(ul = ul * 3 - 6, 1500)
+           /* size_t */
+           && TEST_size_t_eq((--i, st++), 1234)
+           && TEST_size_t_eq(st, 1235)
+           && TEST_int_eq(11, i)
+           /* pointers */
+           && TEST_ptr_eq(p++, buf)
+           && TEST_ptr_eq(buf + 2, ++p)
+           && TEST_ptr_eq(buf, p -= 2)
+           && TEST_ptr(++p)
+           && TEST_ptr_eq(p, buf + 1)
+           && TEST_ptr_null(p = NULL)
+           /* strings */
+           && TEST_str_eq(p = "123456" + 1, "23456")
+           && TEST_str_eq("3456", ++p)
+           && TEST_str_ne(p++, "456")
+           /* memory */
+           && TEST_mem_eq(--p, sizeof("3456"), "3456", sizeof("3456"))
+           && TEST_mem_ne(p++, sizeof("456"), "456", sizeof("456"))
+           && TEST_mem_eq(p--, sizeof("456"), "456", sizeof("456"));
+}
+
 void register_tests(void)
 {
     ADD_TEST(test_int);
@@ -273,4 +328,5 @@ void register_tests(void)
     ADD_TEST(test_string);
     ADD_TEST(test_memory);
     ADD_TEST(test_messages);
+    ADD_TEST(test_single_eval);
 }
index a83323b..0631a8b 100644 (file)
@@ -191,7 +191,7 @@ DECLARE_COMPARISON(char *, str, ne)
 
 /*
  * Equality test for memory blocks where NULL is a legitimate value.
-* These calls return 1 if the two memory blocks compare true.
+ * These calls return 1 if the two memory blocks compare true.
  * Otherwise, they return 0 and pretty-print diagnostics.
  * These should not be called directly, use the TEST_xxx macros below instead.
  */
@@ -223,6 +223,12 @@ void test_info_c90(const char *desc, ...) PRINTF_FORMAT(1, 2);
 /*
  * The following macros provide wrapper calls to the test functions with
  * a default description that indicates the file and line number of the error.
+ *
+ * The following macros guarantee to evaluate each argument exactly once.
+ * This allows constructs such as: if(!TEST_ptr(ptr = OPENSSL_malloc(..)))
+ * to produce better contextual output than:
+ *      ptr = OPENSSL_malloc(..);
+ *      if (!TEST_ptr(ptr))
  */
 # define TEST_int_eq(a, b)    test_int_eq(__FILE__, __LINE__, #a, #b, a, b)
 # define TEST_int_ne(a, b)    test_int_ne(__FILE__, __LINE__, #a, #b, a, b)
@@ -238,47 +244,47 @@ void test_info_c90(const char *desc, ...) PRINTF_FORMAT(1, 2);
 # define TEST_int_gt(a, b)    test_int_gt(__FILE__, __LINE__, #a, #b, a, b)
 # define TEST_int_ge(a, b)    test_int_ge(__FILE__, __LINE__, #a, #b, a, b)
 
-# define TEST_uint_eq(a, b)    test_uint_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uint_ne(a, b)    test_uint_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uint_lt(a, b)    test_uint_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uint_le(a, b)    test_uint_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uint_gt(a, b)    test_uint_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uint_ge(a, b)    test_uint_ge(__FILE__, __LINE__, #a, #b, a, b)
-
-# define TEST_char_eq(a, b)    test_char_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_char_ne(a, b)    test_char_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_char_lt(a, b)    test_char_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_char_le(a, b)    test_char_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_char_gt(a, b)    test_char_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_char_ge(a, b)    test_char_ge(__FILE__, __LINE__, #a, #b, a, b)
-
-# define TEST_uchar_eq(a, b)    test_uchar_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uchar_ne(a, b)    test_uchar_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uchar_lt(a, b)    test_uchar_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uchar_le(a, b)    test_uchar_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uchar_gt(a, b)    test_uchar_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_uchar_ge(a, b)    test_uchar_ge(__FILE__, __LINE__, #a, #b, a, b)
-
-# define TEST_long_eq(a, b)    test_long_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_long_ne(a, b)    test_long_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_long_lt(a, b)    test_long_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_long_le(a, b)    test_long_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_long_gt(a, b)    test_long_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_long_ge(a, b)    test_long_ge(__FILE__, __LINE__, #a, #b, a, b)
-
-# define TEST_ulong_eq(a, b)    test_ulong_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_ulong_ne(a, b)    test_ulong_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_ulong_lt(a, b)    test_ulong_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_ulong_le(a, b)    test_ulong_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_ulong_gt(a, b)    test_ulong_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_ulong_ge(a, b)    test_ulong_ge(__FILE__, __LINE__, #a, #b, a, b)
-
-# define TEST_size_t_eq(a, b)    test_size_t_eq(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_size_t_ne(a, b)    test_size_t_ne(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_size_t_lt(a, b)    test_size_t_lt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_size_t_le(a, b)    test_size_t_le(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_size_t_gt(a, b)    test_size_t_gt(__FILE__, __LINE__, #a, #b, a, b)
-# define TEST_size_t_ge(a, b)    test_size_t_ge(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_eq(a, b)   test_uint_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_ne(a, b)   test_uint_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_lt(a, b)   test_uint_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_le(a, b)   test_uint_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_gt(a, b)   test_uint_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uint_ge(a, b)   test_uint_ge(__FILE__, __LINE__, #a, #b, a, b)
+
+# define TEST_char_eq(a, b)   test_char_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_char_ne(a, b)   test_char_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_char_lt(a, b)   test_char_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_char_le(a, b)   test_char_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_char_gt(a, b)   test_char_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_char_ge(a, b)   test_char_ge(__FILE__, __LINE__, #a, #b, a, b)
+
+# define TEST_uchar_eq(a, b)  test_uchar_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uchar_ne(a, b)  test_uchar_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uchar_lt(a, b)  test_uchar_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uchar_le(a, b)  test_uchar_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uchar_gt(a, b)  test_uchar_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_uchar_ge(a, b)  test_uchar_ge(__FILE__, __LINE__, #a, #b, a, b)
+
+# define TEST_long_eq(a, b)   test_long_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_long_ne(a, b)   test_long_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_long_lt(a, b)   test_long_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_long_le(a, b)   test_long_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_long_gt(a, b)   test_long_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_long_ge(a, b)   test_long_ge(__FILE__, __LINE__, #a, #b, a, b)
+
+# define TEST_ulong_eq(a, b)  test_ulong_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_ulong_ne(a, b)  test_ulong_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_ulong_lt(a, b)  test_ulong_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_ulong_le(a, b)  test_ulong_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_ulong_gt(a, b)  test_ulong_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_ulong_ge(a, b)  test_ulong_ge(__FILE__, __LINE__, #a, #b, a, b)
+
+# define TEST_size_t_eq(a, b) test_size_t_eq(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_size_t_ne(a, b) test_size_t_ne(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_size_t_lt(a, b) test_size_t_lt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_size_t_le(a, b) test_size_t_le(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_size_t_gt(a, b) test_size_t_gt(__FILE__, __LINE__, #a, #b, a, b)
+# define TEST_size_t_ge(a, b) test_size_t_ge(__FILE__, __LINE__, #a, #b, a, b)
 
 # define TEST_ptr_eq(a, b)    test_ptr_eq(__FILE__, __LINE__, #a, #b, a, b)
 # define TEST_ptr_ne(a, b)    test_ptr_ne(__FILE__, __LINE__, #a, #b, a, b)