blob: 5ee86a8fa178ad074f7e41be2a6e57c4129b38b5 [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source 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:
// // Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// // 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS 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
// COPYRIGHT OWNER OR 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 MINITEST_MINITEST_H
#define MINITEST_MINITEST_H
// Minitest is a minimalistic unit testing framework designed specifically
// for the Android support library.
//
// - Unit tests must be written in C++, but no C++ runtime implementation
// is either required or _supported_. This is by design.
//
// _ Inspired by GoogleTest, you can use the TEST macro to define a new
// test case easily, and it can contain EXPECT_XX|ASSERT_XX statements.
//
// For example:
//
// TEST(stdio, strlen) {
// EXPECT_EQ(3, strlen("foo"));
// EXPECT_EQ(1, srlen("a"));
// }
//
// However, there are important differences / limitations:
//
// o You cannot stream strings into an except or assert statement.
// Minitest provides a TEST_TEXT macro to do that instead.
//
// In other words, replace:
//
// EXPECT_EQ(expected, expression) << "When checking 'foo'";
//
// With:
// TEST_TEXT << "When checking 'foo'";
// EXPECT_EQ(expected, expression);
//
// The context text is only printed on failure.
//
// o TEST_F() is not supported (for now).
//
// o EXPECT/ASSERT statements only work inside a TESET() function, not
// in a function called by it.
//
// o No test death detection.
//
// - You can use minitest::Format() to stream formatted output into
// a TEST_TEXT context, as in:
//
// for (size_t n = 0; n < kMaxCount; n++) {
// TEST_TEXT << "Checking string : "
// << minitest;:Format("%z/%z", n+1, kMaxCount);
// EXPECT_EQ(kExpected[n], Foo(kString[n]));
// }
//
#include <stdio.h>
#include <string.h>
namespace minitest {
namespace internal {
// AddConst<T>::type adds a 'const' qualifier to type T.
// Examples:
// int -> const int
// char* -> const char* const
// const char* -> const char* const
// char* const -> const char* const
template <typename T>
struct AddConst {
typedef const T type;
};
template <typename T>
struct AddConst<const T> {
typedef const T type;
};
template <typename T>
struct AddConst<T*> {
typedef const T* const type;
};
template <typename T>
struct AddConst<const T*> {
typedef const T* const type;
};
// String class used to accumulate error messages.
// Very similar to std::string but also supports streaming into it
// for easier formatted output, as in:
//
// String str;
// int x = 42;
// str << "x is '" << x << "'\n";
//
// You can also use minitest::Format() as in:
//
// str << minitest::Format("Hex value %08x\n", x);
//
class String {
public:
String() : str_(NULL), size_(0), capacity_(0) {}
String(const char* str, size_t len);
explicit String(const char* str) { String(str, ::strlen(str)); }
String(const String& other) { String(other.str_, other.size_); }
String& operator=(const String& other) {
(*this) += other;
return *this;
}
char& operator[](size_t index) { return str_[index]; }
~String() { Clear(); }
const char* c_str() const { return str_; }
const char* data() const { return str_; }
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
String& operator+=(const String& other);
String& operator+=(const char* str);
String& operator+=(char ch);
String operator+(const String& other) const {
String result(*this);
result += other;
return result;
}
String operator+(const char* str) const {
String result(*this);
result += str;
return result;
}
// Basic formatting operators.
String& operator<<(const String& other);
String& operator<<(const char* str);
#define MINITEST_OPERATOR_LL_(ParamType) String& operator<<(ParamType v)
MINITEST_OPERATOR_LL_(bool);
MINITEST_OPERATOR_LL_(char);
MINITEST_OPERATOR_LL_(signed char);
MINITEST_OPERATOR_LL_(short);
MINITEST_OPERATOR_LL_(int);
MINITEST_OPERATOR_LL_(long);
MINITEST_OPERATOR_LL_(long long);
MINITEST_OPERATOR_LL_(unsigned char);
MINITEST_OPERATOR_LL_(unsigned short);
MINITEST_OPERATOR_LL_(unsigned int);
MINITEST_OPERATOR_LL_(unsigned long);
MINITEST_OPERATOR_LL_(unsigned long long);
MINITEST_OPERATOR_LL_(float);
MINITEST_OPERATOR_LL_(double);
MINITEST_OPERATOR_LL_(long double);
MINITEST_OPERATOR_LL_(const void*);
#undef MINITEST_OPERATOR_LL_
void Clear();
void Resize(size_t new_size);
private:
void Reserve(size_t new_capacity);
char* str_;
size_t size_;
size_t capacity_;
};
} // namespace internal
// A helper function that can be used to generate formatted output
// as a temporary string. Use like printf(), but returns a new String
// object. Useful to stream into TEST_TEXT() objects, as in:
//
// TEST_TEXT << "Using "
// << minitest::Format("%08d", bytes)
// << " bytes";
//
internal::String Format(const char* format, ...);
class TestCase {
public:
enum Result {
PASS = 0,
FAIL,
FATAL
};
TestCase() : result_(PASS) {}
~TestCase() {}
void Failure();
void FatalFailure();
Result result() { return result_; }
internal::String& GetText();
private:
Result result_;
internal::String text_;
};
// Type of a function defined through the TEST(<test>,<case>) macro.
typedef void(TestFunction)(TestCase* testcase);
// Used internally to register new test functions.
void RegisterTest(const char* test_name,
const char* case_name,
TestFunction* test_function);
#define MINITEST_TEST_FUNCTION(testname, casename) \
MINITEST_TEST_FUNCTION_(testname, casename)
#define MINITEST_TEST_FUNCTION_(testname, casename) \
minitest_##testname##_##casename
#define TEST(testname, casename) \
static void MINITEST_TEST_FUNCTION(testname, casename)(minitest::TestCase*); \
static void \
__attribute__((constructor)) RegisterMiniTest##testname##_##casename() { \
minitest::RegisterTest( \
#testname, #casename, &MINITEST_TEST_FUNCTION(testname, casename)); \
} \
void MINITEST_TEST_FUNCTION(testname, \
casename)(minitest::TestCase* minitest_testcase)
// Use this macro to add context text before an EXPECT or ASSERT statement
// For example:
//
// for (size_t n = 0; n < MAX; ++n) {
// TEST_TEXT << "When checking " << kStrings[n];
// EXPECT_STREQ(kExpected[n], kStrings[n]);
// }
//
// The text will only be printed in case of failure in the next
// EXPECT/ASSERT statement.
//
#define TEST_TEXT minitest_testcase->GetText()
// EXPECT_TRUE() must evaluate to something that supports the << operator
// to receive debugging strings only in case of failure.
#define EXPECT_TRUE(expression) \
do { \
if (!(expression)) { \
printf( \
"EXPECT_TRUE:%s:%d: expression '%s' returned 'false', expected " \
"'true'\n", \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->Failure(); \
} \
} while (0)
#define EXPECT_FALSE(expression) \
do { \
if (!!(expression)) { \
printf( \
"EXPECT_FALSE:%s:%d: expression '%s' returned 'true', expected " \
"'false'\n", \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->Failure(); \
} \
} while (0)
#define MINITEST_DEFINE_LOCAL_EXPR_(varname, expr) \
typedef minitest::internal::AddConst<__typeof__(expr)>::type varname##Type; \
const varname##Type varname = (expr);
#define MINITEST_EXPECT_ASSERT_BINOP_( \
opname, op, expected, expression, is_assert) \
do { \
MINITEST_DEFINE_LOCAL_EXPR_(minitest_expected, expected); \
MINITEST_DEFINE_LOCAL_EXPR_(minitest_actual, expression); \
if (!(minitest_actual op minitest_expected)) { \
printf("%s" #opname ":%s:%d: with expression '%s'\n", \
is_assert ? "ASSERT_" : "EXPECT_", \
__FILE__, \
__LINE__, \
#expression); \
minitest::internal::String minitest_str; \
minitest_str << minitest_actual; \
printf("actual : %s\n", minitest_str.c_str()); \
minitest_str.Clear(); \
minitest_str << minitest_expected; \
printf("expected : %s\n", minitest_str.c_str()); \
if (is_assert) { \
minitest_testcase->FatalFailure(); \
return; \
} \
minitest_testcase->Failure(); \
} \
} while (0)
#define MINITEST_EXPECT_BINOP_(opname, op, expected, expression) \
MINITEST_EXPECT_ASSERT_BINOP_(opname, op, expected, expression, false)
#define EXPECT_EQ(expected, expression) \
MINITEST_EXPECT_BINOP_(EQ, ==, expected, expression)
#define EXPECT_NE(expected, expression) \
MINITEST_EXPECT_BINOP_(NE, !=, expected, expression)
#define EXPECT_LE(expected, expression) \
MINITEST_EXPECT_BINOP_(LE, <=, expected, expression)
#define EXPECT_LT(expected, expression) \
MINITEST_EXPECT_BINOP_(LT, <, expected, expression)
#define EXPECT_GE(expected, expression) \
MINITEST_EXPECT_BINOP_(GE, >=, expected, expression)
#define EXPECT_GT(expected, expression) \
MINITEST_EXPECT_BINOP_(GT, >, expected, expression)
#define MINITEST_EXPECT_ASSERT_STR_(expected, expression, is_eq, is_assert) \
do { \
const char* minitest_prefix = is_assert ? "ASSERT_STR" : "EXPECT_STR"; \
const char* minitest_suffix = is_eq ? "EQ" : "NEQ"; \
const char* minitest_expected = (expected); \
const char* minitest_actual = (expression); \
if (minitest_actual == NULL) { \
printf("%s%s:%s:%d: expression '%s' is NULL!\n", \
minitest_prefix, \
minitest_suffix, \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->Failure(); \
} else { \
bool minitest_eq = !strcmp(minitest_expected, minitest_actual); \
if (minitest_eq != is_eq) { \
printf("%s%s:%s:%d: with expression '%s'\n", \
minitest_prefix, \
minitest_suffix, \
__FILE__, \
__LINE__, \
#expression); \
printf("actual : %s\n", minitest_actual); \
printf("expected : %s\n", minitest_expected); \
minitest_testcase->Failure(); \
} \
} \
} while (0)
#define EXPECT_STREQ(expected, expression) \
MINITEST_EXPECT_ASSERT_STR_(expected, expression, true, false)
#define EXPECT_STRNEQ(expected, expression) \
MINITEST_EXPECT_ASSERT_STR_(expected, expression, false, false)
#define MINITEST_EXPECT_ASSERT_MEM_( \
expected, expected_len, expression, expression_len, is_eq, is_assert) \
do { \
const char* minitest_prefix = is_assert ? "ASSERT_MEM" : "EXPECT_MEM"; \
const char* minitest_suffix = is_eq ? "EQ" : "NEQ"; \
const char* minitest_expected = (expected); \
size_t minitest_expected_len = static_cast<size_t>(expected_len); \
const char* minitest_actual = (expression); \
size_t minitest_actual_len = static_cast<size_t>(expression_len); \
if (minitest_actual == NULL) { \
printf("%s%s:%s:%d: expression '%s' is NULL!\n", \
minitest_prefix, \
minitest_suffix, \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->Failure(); \
} else if (minitest_actual_len != minitest_expected_len) { \
printf("%s:%s:%s:%d: size mistmatch for expression '%s'\n", \
minitest_prefix, \
minitest_suffix, \
__FILE__, \
__LINE__, \
#expression); \
printf("actual size : %zu (0x%zx)\n", \
minitest_actual_len, \
minitest_actual_len); \
printf("expected size : %zu (0x%zx)\n", \
minitest_expected_len, \
minitest_expected_len); \
minitest_testcase->Failure(); \
} else { \
bool minitest_eq = \
!memcmp(minitest_expected, minitest_actual, minitest_expected_len); \
if (minitest_eq != is_eq) { \
printf("%s%s:%s:%d: with expression '%s' of %zu bytes\n", \
minitest_prefix, \
minitest_suffix, \
__FILE__, \
__LINE__, \
#expression, \
minitest_expected_len); \
printf("actual : '%.*s'\n", (int)minitest_expected_len, \
minitest_actual); \
printf( \
"expected : '%.*s'\n", (int)minitest_expected_len, \
minitest_expected); \
minitest_testcase->Failure(); \
} \
} \
} while (0)
#define EXPECT_MEMEQ(expected, expected_len, expression, expression_len) \
MINITEST_EXPECT_ASSERT_MEM_( \
expected, expected_len, expression, expression_len, true, false)
#define EXPECT_MEMNEQ(expected, expected_len, expression, expression_len) \
MINITEST_EXPECT_ASSERT_MEM_( \
expected, expected_len, expression, expression_len, false, false)
#define ASSERT_TRUE(expression) \
do { \
if (!(expression)) { \
printf( \
"ASSERT_TRUE:%s:%d: expression '%s' return 'false', expected " \
"'true'\n", \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->FatalFailure(); \
return; \
} \
} while (0)
#define ASSERT_FALSE(expression) \
do { \
if (!!(expression)) { \
printf( \
"ASSERT_FALSE:%s:%d: expression '%s' return 'true', expected " \
"'false'\n", \
__FILE__, \
__LINE__, \
#expression); \
minitest_testcase->FatalFailure(); \
return; \
} \
} while (0)
#define MINITEST_ASSERT_BINOP_(opname, op, expected, expression) \
MINITEST_EXPECT_ASSERT_BINOP_(opname, op, expected, expression, true)
#define ASSERT_EQ(expected, expression) \
MINITEST_ASSERT_BINOP_(EQ, ==, expected, expression)
#define ASSERT_NE(expected, expression) \
MINITEST_ASSERT_BINOP_(NE, !=, expected, expression)
#define ASSERT_LE(expected, expression) \
MINITEST_ASSERT_BINOP_(LE, <=, expected, expression)
#define ASSERT_LT(expected, expression) \
MINITEST_ASSERT_BINOP_(LT, <, expected, expression)
#define ASSERT_GE(expected, expression) \
MINITEST_ASSERT_BINOP_(GE, >=, expected, expression)
#define ASSERT_GT(expected, expression) \
MINITEST_ASSERT_BINOP_(GT, >, expected, expression)
#define ASSERT_STREQ(expected, expression) \
MINITEST_EXPECT_ASSERT_STR_(expected, expression, true, true)
#define ASSERT_STRNEQ(expected, expression) \
MINITEST_EXPECT_ASSERT_STR_(expected, expression, false, true)
#define ASSERT_MEMEQ(expected, expected_len, expression, expression_len) \
MINITEST_EXPECT_ASSERT_MEM_( \
expected, expected_len, expression, expression_len, true, true)
#define ASSERT_MEMNEQ(expected, expected_len, expression, expression_len) \
MINITEST_EXPECT_ASSERT_MEM_( \
expected, expected_len, expression, expression_len, false, true)
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
} // namespace minitest
#endif // MINITEST_MINITEST_H