From 35c0a6c54d4e67f0d600044ed8eae0ae5e5adfba Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Sat, 24 Apr 2021 23:53:23 -0600 Subject: [PATCH] AK+Userland: Move AK/TestSuite.h into LibTest and rework Tests' CMake As many macros as possible are moved to Macros.h, while the macros to create a test case are moved to TestCase.h. TestCase is now the only user-facing header for creating a test case. TestSuite and its helpers have moved into a .cpp file. Instead of requiring a TEST_MAIN macro to be instantiated into the test file, a TestMain.cpp file is provided instead that will be linked against each test. This has the side effect that, if we wanted to have test cases split across multiple files, it's as simple as adding them all to the same executable. The test main should be portable to kernel mode as well, so if there's a set of tests that should be run in self-test mode in kernel space, we can accomodate that. A new serenity_test CMake function streamlines adding a new test with arguments for the test source file, subdirectory under /usr/Tests to install the test application and an optional list of libraries to link against the test application. To accomodate future test where the provided TestMain.cpp is not suitable (e.g. test-js), a CUSTOM_MAIN parameter can be passed to the function to not link against the boilerplate main function. --- AK/TestSuite.h | 319 ------------------ AK/Tests/CMakeLists.txt | 5 +- AK/Tests/TestAllOf.cpp | 4 +- AK/Tests/TestAnyOf.cpp | 4 +- AK/Tests/TestArray.cpp | 4 +- AK/Tests/TestAtomic.cpp | 4 +- AK/Tests/TestBadge.cpp | 4 +- AK/Tests/TestBase64.cpp | 4 +- AK/Tests/TestBinaryHeap.cpp | 4 +- AK/Tests/TestBinarySearch.cpp | 4 +- AK/Tests/TestBitCast.cpp | 4 +- AK/Tests/TestBitmap.cpp | 4 +- AK/Tests/TestByteBuffer.cpp | 4 +- AK/Tests/TestChecked.cpp | 4 +- AK/Tests/TestCircularDeque.cpp | 4 +- AK/Tests/TestCircularDuplexStream.cpp | 4 +- AK/Tests/TestCircularQueue.cpp | 4 +- AK/Tests/TestComplex.cpp | 5 +- AK/Tests/TestDistinctNumeric.cpp | 4 +- AK/Tests/TestDoublyLinkedList.cpp | 4 +- AK/Tests/TestEndian.cpp | 4 +- AK/Tests/TestEnumBits.cpp | 5 +- AK/Tests/TestFind.cpp | 4 +- AK/Tests/TestFormat.cpp | 4 +- AK/Tests/TestGenericLexer.cpp | 4 +- AK/Tests/TestHashFunctions.cpp | 4 +- AK/Tests/TestHashMap.cpp | 4 +- AK/Tests/TestHashTable.cpp | 4 +- AK/Tests/TestHex.cpp | 4 +- AK/Tests/TestIPv4Address.cpp | 4 +- AK/Tests/TestIndexSequence.cpp | 5 +- AK/Tests/TestIntrusiveList.cpp | 5 +- AK/Tests/TestIntrusiveRedBlackTree.cpp | 4 +- AK/Tests/TestJSON.cpp | 4 +- AK/Tests/TestLexicalPath.cpp | 4 +- AK/Tests/TestMACAddress.cpp | 4 +- AK/Tests/TestMemMem.cpp | 4 +- AK/Tests/TestMemoryStream.cpp | 4 +- AK/Tests/TestNeverDestroyed.cpp | 4 +- AK/Tests/TestNonnullRefPtr.cpp | 4 +- AK/Tests/TestNumberFormat.cpp | 4 +- AK/Tests/TestOptional.cpp | 4 +- AK/Tests/TestQueue.cpp | 4 +- AK/Tests/TestQuickSort.cpp | 4 +- AK/Tests/TestRedBlackTree.cpp | 4 +- AK/Tests/TestRefPtr.cpp | 4 +- AK/Tests/TestSinglyLinkedList.cpp | 4 +- AK/Tests/TestSourceGenerator.cpp | 4 +- AK/Tests/TestSourceLocation.cpp | 5 +- AK/Tests/TestSpan.cpp | 4 +- AK/Tests/TestString.cpp | 4 +- AK/Tests/TestStringUtils.cpp | 4 +- AK/Tests/TestStringView.cpp | 4 +- AK/Tests/TestTime.cpp | 4 +- AK/Tests/TestTrie.cpp | 4 +- AK/Tests/TestTypeTraits.cpp | 5 +- AK/Tests/TestTypedTransfer.cpp | 4 +- AK/Tests/TestURL.cpp | 4 +- AK/Tests/TestUtf8.cpp | 4 +- AK/Tests/TestVector.cpp | 4 +- AK/Tests/TestWeakPtr.cpp | 4 +- Meta/CMake/utils.cmake | 16 +- Meta/Lagom/CMakeLists.txt | 22 +- .../Applications/Spreadsheet/CMakeLists.txt | 4 + .../Spreadsheet/Readers/Test/TestXSV.cpp | 4 +- .../Writers/Test/TestXSVWriter.cpp | 4 +- Userland/Libraries/LibC/Tests/CMakeLists.txt | 5 +- .../Libraries/LibC/Tests/TestLibCTime.cpp | 4 +- .../LibCompress/Tests/CMakeLists.txt | 5 +- .../LibCompress/Tests/TestDeflate.cpp | 4 +- .../Libraries/LibCompress/Tests/TestGzip.cpp | 4 +- .../Libraries/LibCompress/Tests/TestZlib.cpp | 4 +- .../Libraries/LibRegex/Tests/Benchmark.cpp | 4 +- .../Libraries/LibRegex/Tests/CMakeLists.txt | 5 +- Userland/Libraries/LibRegex/Tests/Regex.cpp | 4 +- .../Libraries/LibRegex/Tests/RegexLibC.cpp | 4 +- .../Libraries/LibSQL/Tests/CMakeLists.txt | 5 +- .../LibSQL/Tests/TestSqlExpressionParser.cpp | 4 +- .../LibSQL/Tests/TestSqlStatementParser.cpp | 4 +- Userland/Libraries/LibTest/CMakeLists.txt | 7 + Userland/Libraries/LibTest/Macros.h | 87 +++++ Userland/Libraries/LibTest/TestCase.h | 67 ++++ Userland/Libraries/LibTest/TestMain.cpp | 28 ++ Userland/Libraries/LibTest/TestSuite.cpp | 148 ++++++++ Userland/Libraries/LibTest/TestSuite.h | 55 +++ Userland/Tests/Kernel/CMakeLists.txt | 1 + Userland/Tests/LibC/CMakeLists.txt | 6 +- Userland/Tests/LibC/snprintf-correctness.cpp | 4 +- Userland/Tests/LibC/strlcpy-correctness.cpp | 4 +- Userland/Tests/LibGfx/CMakeLists.txt | 8 +- Userland/Tests/LibGfx/painter.cpp | 4 +- Userland/Tests/LibM/CMakeLists.txt | 5 +- Userland/Tests/LibM/test-math.cpp | 4 +- .../Tests/UserspaceEmulator/CMakeLists.txt | 1 + 94 files changed, 522 insertions(+), 579 deletions(-) delete mode 100644 AK/TestSuite.h create mode 100644 Userland/Libraries/LibTest/Macros.h create mode 100644 Userland/Libraries/LibTest/TestCase.h create mode 100644 Userland/Libraries/LibTest/TestMain.cpp create mode 100644 Userland/Libraries/LibTest/TestSuite.cpp create mode 100644 Userland/Libraries/LibTest/TestSuite.h diff --git a/AK/TestSuite.h b/AK/TestSuite.h deleted file mode 100644 index 0f062db9a7a..00000000000 --- a/AK/TestSuite.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace AK { - -template -void warnln(CheckedFormatString&& fmtstr, const Parameters&...); - -// Declare a helper so that we can call it from VERIFY in included headers -// before defining TestSuite -inline void current_test_case_did_fail(); - -} - -using AK::warnln; - -#undef VERIFY -#define VERIFY(x) \ - do { \ - if (!(x)) { \ - ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: VERIFY({}) failed", __FILE__, __LINE__, #x); \ - current_test_case_did_fail(); \ - } \ - } while (false) - -#undef VERIFY_NOT_REACHED -#define VERIFY_NOT_REACHED() \ - do { \ - ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: VERIFY_NOT_REACHED() called", __FILE__, __LINE__); \ - ::abort(); \ - } while (false) - -#undef TODO -#define TODO() \ - do { \ - ::AK::warnln(stderr, "\033[31;1mFAIL\033[0m: {}:{}: TODO() called", __FILE__, __LINE__); \ - ::abort(); \ - } while (false) - -#include -#include -#include -#include -#include -#include -#include - -namespace AK { - -class TestElapsedTimer { -public: - TestElapsedTimer() { restart(); } - - void restart() { gettimeofday(&m_started, nullptr); } - - u64 elapsed_milliseconds() - { - struct timeval now; - gettimeofday(&now, nullptr); - - struct timeval delta; - timersub(&now, &m_started, &delta); - - return delta.tv_sec * 1000 + delta.tv_usec / 1000; - } - -private: - struct timeval m_started; -}; - -using TestFunction = Function; - -class TestCase : public RefCounted { -public: - TestCase(const String& name, TestFunction&& fn, bool is_benchmark) - : m_name(name) - , m_function(move(fn)) - , m_is_benchmark(is_benchmark) - { - } - - bool is_benchmark() const { return m_is_benchmark; } - const String& name() const { return m_name; } - const TestFunction& func() const { return m_function; } - -private: - String m_name; - TestFunction m_function; - bool m_is_benchmark; -}; - -class TestSuite { -public: - static TestSuite& the() - { - if (s_global == nullptr) - s_global = new TestSuite(); - return *s_global; - } - - static void release() - { - if (s_global) - delete s_global; - s_global = nullptr; - } - - int run(const NonnullRefPtrVector&); - int main(const String& suite_name, int argc, char** argv); - NonnullRefPtrVector find_cases(const String& search, bool find_tests, bool find_benchmarks); - void add_case(const NonnullRefPtr& test_case) - { - m_cases.append(test_case); - } - - void current_test_case_did_fail() { m_current_test_case_passed = false; } - -private: - static TestSuite* s_global; - NonnullRefPtrVector m_cases; - u64 m_testtime = 0; - u64 m_benchtime = 0; - String m_suite_name; - bool m_current_test_case_passed = true; -}; - -inline void current_test_case_did_fail() { TestSuite::the().current_test_case_did_fail(); } - -int TestSuite::main(const String& suite_name, int argc, char** argv) -{ - m_suite_name = suite_name; - - Core::ArgsParser args_parser; - - bool do_tests_only = getenv("TESTS_ONLY") != nullptr; - bool do_benchmarks_only = false; - bool do_list_cases = false; - const char* search_string = "*"; - - args_parser.add_option(do_tests_only, "Only run tests.", "tests", 0); - args_parser.add_option(do_benchmarks_only, "Only run benchmarks.", "bench", 0); - args_parser.add_option(do_list_cases, "List available test cases.", "list", 0); - args_parser.add_positional_argument(search_string, "Only run matching cases.", "pattern", Core::ArgsParser::Required::No); - args_parser.parse(argc, argv); - - const auto& matching_tests = find_cases(search_string, !do_benchmarks_only, !do_tests_only); - - if (do_list_cases) { - outln("Available cases for {}:", suite_name); - for (const auto& test : matching_tests) { - outln(" {}", test.name()); - } - return 0; - } - - outln("Running {} cases out of {}.", matching_tests.size(), m_cases.size()); - - return run(matching_tests); -} - -NonnullRefPtrVector TestSuite::find_cases(const String& search, bool find_tests, bool find_benchmarks) -{ - NonnullRefPtrVector matches; - for (const auto& t : m_cases) { - if (!search.is_empty() && !t.name().matches(search, CaseSensitivity::CaseInsensitive)) { - continue; - } - - if (!find_tests && !t.is_benchmark()) { - continue; - } - if (!find_benchmarks && t.is_benchmark()) { - continue; - } - - matches.append(t); - } - return matches; -} - -int TestSuite::run(const NonnullRefPtrVector& tests) -{ - size_t test_count = 0; - size_t test_failed_count = 0; - size_t benchmark_count = 0; - TestElapsedTimer global_timer; - - for (const auto& t : tests) { - const auto test_type = t.is_benchmark() ? "benchmark" : "test"; - - warnln("Running {} '{}'.", test_type, t.name()); - m_current_test_case_passed = true; - - TestElapsedTimer timer; - t.func()(); - const auto time = timer.elapsed_milliseconds(); - - dbgln("{} {} '{}' in {}ms", m_current_test_case_passed ? "Completed" : "Failed", test_type, t.name(), time); - - if (t.is_benchmark()) { - m_benchtime += time; - benchmark_count++; - } else { - m_testtime += time; - test_count++; - } - - if (!m_current_test_case_passed) { - test_failed_count++; - } - } - - dbgln("Finished {} tests and {} benchmarks in {}ms ({}ms tests, {}ms benchmarks, {}ms other).", - test_count, - benchmark_count, - global_timer.elapsed_milliseconds(), - m_testtime, - m_benchtime, - global_timer.elapsed_milliseconds() - (m_testtime + m_benchtime)); - dbgln("Out of {} tests, {} passed and {} failed.", test_count, test_count - test_failed_count, test_failed_count); - - return (int)test_failed_count; -} - -} - -using AK::current_test_case_did_fail; -using AK::TestCase; -using AK::TestSuite; - -#define __TESTCASE_FUNC(x) __test_##x -#define __TESTCASE_TYPE(x) __TestCase_##x - -#define TEST_CASE(x) \ - static void __TESTCASE_FUNC(x)(); \ - struct __TESTCASE_TYPE(x) { \ - __TESTCASE_TYPE(x) \ - () { TestSuite::the().add_case(adopt_ref(*new TestCase(#x, __TESTCASE_FUNC(x), false))); } \ - }; \ - static struct __TESTCASE_TYPE(x) __TESTCASE_TYPE(x); \ - static void __TESTCASE_FUNC(x)() - -#define __BENCHMARK_FUNC(x) __benchmark_##x -#define __BENCHMARK_TYPE(x) __BenchmarkCase_##x - -#define BENCHMARK_CASE(x) \ - static void __BENCHMARK_FUNC(x)(); \ - struct __BENCHMARK_TYPE(x) { \ - __BENCHMARK_TYPE(x) \ - () { TestSuite::the().add_case(adopt_ref(*new TestCase(#x, __BENCHMARK_FUNC(x), true))); } \ - }; \ - static struct __BENCHMARK_TYPE(x) __BENCHMARK_TYPE(x); \ - static void __BENCHMARK_FUNC(x)() - -#define TEST_MAIN(x) \ - TestSuite* TestSuite::s_global = nullptr; \ - template \ - constexpr size_t compiletime_lenof(const char(&)[N]) \ - { \ - return N - 1; \ - } \ - int main(int argc, char** argv) \ - { \ - static_assert(compiletime_lenof(#x) != 0, "Set SuiteName"); \ - int ret = TestSuite::the().main(#x, argc, argv); \ - TestSuite::release(); \ - return ret; \ - } - -#define EXPECT_EQ(a, b) \ - do { \ - auto lhs = (a); \ - auto rhs = (b); \ - if (lhs != rhs) { \ - warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}", __FILE__, __LINE__, #a, #b, FormatIfSupported { lhs }, FormatIfSupported { rhs }); \ - current_test_case_did_fail(); \ - } \ - } while (false) - -// If you're stuck and `EXPECT_EQ` seems to refuse to print anything useful, -// try this: It'll spit out a nice compiler error telling you why it doesn't print. -#define EXPECT_EQ_FORCE(a, b) \ - do { \ - auto lhs = (a); \ - auto rhs = (b); \ - if (lhs != rhs) { \ - warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}", __FILE__, __LINE__, #a, #b, lhs, rhs); \ - current_test_case_did_fail(); \ - } \ - } while (false) - -#define EXPECT(x) \ - do { \ - if (!(x)) { \ - warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT({}) failed", __FILE__, __LINE__, #x); \ - current_test_case_did_fail(); \ - } \ - } while (false) - -#define EXPECT_APPROXIMATE(a, b) \ - do { \ - auto expect_close_lhs = a; \ - auto expect_close_rhs = b; \ - auto expect_close_diff = static_cast(expect_close_lhs) - static_cast(expect_close_rhs); \ - if (fabs(expect_close_diff) > 0.0000005) { \ - warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_APPROXIMATE({}, {})" \ - " failed with lhs={}, rhs={}, (lhs-rhs)={}", \ - __FILE__, __LINE__, #a, #b, expect_close_lhs, expect_close_rhs, expect_close_diff); \ - current_test_case_did_fail(); \ - } \ - } while (false) diff --git a/AK/Tests/CMakeLists.txt b/AK/Tests/CMakeLists.txt index e2de8f372df..28c7468a94e 100644 --- a/AK/Tests/CMakeLists.txt +++ b/AK/Tests/CMakeLists.txt @@ -61,10 +61,7 @@ set(AK_TEST_SOURCES ) foreach(source ${AK_TEST_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name} ${source}) - target_link_libraries(${name} LibCore) - install(TARGETS ${name} RUNTIME DESTINATION usr/Tests/AK) + serenity_test(${source} AK) endforeach() get_filename_component(TEST_FRM_RESOLVED ./test.frm REALPATH) diff --git a/AK/Tests/TestAllOf.cpp b/AK/Tests/TestAllOf.cpp index c953a14468a..48f5d0f7aa1 100644 --- a/AK/Tests/TestAllOf.cpp +++ b/AK/Tests/TestAllOf.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -19,5 +19,3 @@ TEST_CASE(should_determine_if_predicate_applies_to_all_elements_in_container) EXPECT(all_of(a.begin(), a.end(), [](auto elem) { return elem == 0; })); EXPECT(!all_of(a.begin(), a.end(), [](auto elem) { return elem == 1; })); } - -TEST_MAIN(AllOf) diff --git a/AK/Tests/TestAnyOf.cpp b/AK/Tests/TestAnyOf.cpp index e85c2fb17be..2fcfaf29e60 100644 --- a/AK/Tests/TestAnyOf.cpp +++ b/AK/Tests/TestAnyOf.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -21,5 +21,3 @@ TEST_CASE(should_determine_if_predicate_applies_to_any_element_in_container) EXPECT(any_of(a.begin(), a.end(), [](auto elem) { return elem == 1; })); EXPECT(!any_of(a.begin(), a.end(), [](auto elem) { return elem == 2; })); } - -TEST_MAIN(AllOf) diff --git a/AK/Tests/TestArray.cpp b/AK/Tests/TestArray.cpp index 901dda2ae51..440a9935ae4 100644 --- a/AK/Tests/TestArray.cpp +++ b/AK/Tests/TestArray.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -28,5 +28,3 @@ TEST_CASE(compile_time_iterable) constexpr Array array = { 0, 1, 2, 3, 4, 5, 6, 7 }; static_assert(constexpr_sum(array) == 28); } - -TEST_MAIN(Array) diff --git a/AK/Tests/TestAtomic.cpp b/AK/Tests/TestAtomic.cpp index 0b0aa23bfd0..eb7a3843ef2 100644 --- a/AK/Tests/TestAtomic.cpp +++ b/AK/Tests/TestAtomic.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -340,5 +340,3 @@ TEST_CASE(fetch_xor) a_u8 = 0xe2; EXPECT((a_u8 ^= 0xef) == 0x0d); } - -TEST_MAIN(Atomic) diff --git a/AK/Tests/TestBadge.cpp b/AK/Tests/TestBadge.cpp index cebd3fdd273..8f12b9dcb3f 100644 --- a/AK/Tests/TestBadge.cpp +++ b/AK/Tests/TestBadge.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -12,5 +12,3 @@ TEST_CASE(should_provide_underlying_type) { static_assert(IsSame::Type>); } - -TEST_MAIN(Badge) diff --git a/AK/Tests/TestBase64.cpp b/AK/Tests/TestBase64.cpp index 71a2c36588a..698a86c354f 100644 --- a/AK/Tests/TestBase64.cpp +++ b/AK/Tests/TestBase64.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -44,5 +44,3 @@ TEST_CASE(test_encode) encode_equal("fooba", "Zm9vYmE="); encode_equal("foobar", "Zm9vYmFy"); } - -TEST_MAIN(Base64) diff --git a/AK/Tests/TestBinaryHeap.cpp b/AK/Tests/TestBinaryHeap.cpp index 10865e84b03..dbd4a9a4afb 100644 --- a/AK/Tests/TestBinaryHeap.cpp +++ b/AK/Tests/TestBinaryHeap.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -65,5 +65,3 @@ TEST_CASE(large_populate_reverse) EXPECT_EQ(ints.pop_min(), i); } } - -TEST_MAIN(BinaryHeap) diff --git a/AK/Tests/TestBinarySearch.cpp b/AK/Tests/TestBinarySearch.cpp index 6a7098220d4..3e5d65c2404 100644 --- a/AK/Tests/TestBinarySearch.cpp +++ b/AK/Tests/TestBinarySearch.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -116,5 +116,3 @@ TEST_CASE(unsigned_to_signed_regression) EXPECT_EQ(binary_search(input, 1u, &nearby_index), &input[1]); EXPECT_EQ(nearby_index, 1u); } - -TEST_MAIN(BinarySearch) diff --git a/AK/Tests/TestBitCast.cpp b/AK/Tests/TestBitCast.cpp index e341e79e126..baf270f9b69 100644 --- a/AK/Tests/TestBitCast.cpp +++ b/AK/Tests/TestBitCast.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -21,5 +21,3 @@ TEST_CASE(double_int_conversion) check_cast_both_ways(static_cast(1) << 63, -0.0); check_cast_both_ways(static_cast(0x4172f58bc0000000), 19880124.0); } - -TEST_MAIN(BitCast) diff --git a/AK/Tests/TestBitmap.cpp b/AK/Tests/TestBitmap.cpp index 5271353a79a..b4326dcd544 100644 --- a/AK/Tests/TestBitmap.cpp +++ b/AK/Tests/TestBitmap.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -248,5 +248,3 @@ TEST_CASE(count_in_range) test_with_value(true); test_with_value(false); } - -TEST_MAIN(Bitmap) diff --git a/AK/Tests/TestByteBuffer.cpp b/AK/Tests/TestByteBuffer.cpp index 380022184bc..a6fabd70856 100644 --- a/AK/Tests/TestByteBuffer.cpp +++ b/AK/Tests/TestByteBuffer.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -49,5 +49,3 @@ TEST_CASE(negative_operator_lt) // error: error: use of deleted function ‘bool AK::ByteBuffer::operator<(const AK::ByteBuffer&) const’ } #endif /* COMPILE_NEGATIVE_TESTS */ - -TEST_MAIN(ByteBuffer) diff --git a/AK/Tests/TestChecked.cpp b/AK/Tests/TestChecked.cpp index ec988726295..a4c932d6969 100644 --- a/AK/Tests/TestChecked.cpp +++ b/AK/Tests/TestChecked.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -386,5 +386,3 @@ TEST_CASE(should_constexpr_make_via_factory) { [[maybe_unused]] constexpr auto value = make_checked(42); } - -TEST_MAIN(Checked) diff --git a/AK/Tests/TestCircularDeque.cpp b/AK/Tests/TestCircularDeque.cpp index 06218cb3f58..3fa5189bb84 100644 --- a/AK/Tests/TestCircularDeque.cpp +++ b/AK/Tests/TestCircularDeque.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -61,5 +61,3 @@ TEST_CASE(deque_end) EXPECT_EQ(ints.dequeue_end(), 0); EXPECT(ints.is_empty()); } - -TEST_MAIN(CircularDeque) diff --git a/AK/Tests/TestCircularDuplexStream.cpp b/AK/Tests/TestCircularDuplexStream.cpp index b2f3fa6ab2e..62b5534bfbe 100644 --- a/AK/Tests/TestCircularDuplexStream.cpp +++ b/AK/Tests/TestCircularDuplexStream.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -61,5 +61,3 @@ TEST_CASE(overwritting_is_well_defined) EXPECT(stream.eof()); } - -TEST_MAIN(CircularDuplexStream) diff --git a/AK/Tests/TestCircularQueue.cpp b/AK/Tests/TestCircularQueue.cpp index edbbd8a98d4..edc3cb5184e 100644 --- a/AK/Tests/TestCircularQueue.cpp +++ b/AK/Tests/TestCircularQueue.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -66,5 +66,3 @@ TEST_CASE(should_not_call_value_type_constructor_when_created) CircularQueue queue; EXPECT_EQ(0u, ConstructorCounter::s_num_constructor_calls); } - -TEST_MAIN(CircularQueue) diff --git a/AK/Tests/TestComplex.cpp b/AK/Tests/TestComplex.cpp index b3c9b177352..5079569d180 100644 --- a/AK/Tests/TestComplex.cpp +++ b/AK/Tests/TestComplex.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include -#include TEST_CASE(Complex) { @@ -41,5 +42,3 @@ TEST_CASE(Complex) EXPECT_APPROXIMATE(cexp(Complex(0., 1.) * M_PI).real(), -1.); #endif } - -TEST_MAIN(Complex) diff --git a/AK/Tests/TestDistinctNumeric.cpp b/AK/Tests/TestDistinctNumeric.cpp index 94638c1a230..1ecc740098f 100644 --- a/AK/Tests/TestDistinctNumeric.cpp +++ b/AK/Tests/TestDistinctNumeric.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -283,5 +283,3 @@ TEST_CASE(negative_incompatible) // | DistinctNumeric<[...],true,true,true,true,true,[...],[...],64> } #endif /* COMPILE_NEGATIVE_TESTS */ - -TEST_MAIN(DistinctNumeric) diff --git a/AK/Tests/TestDoublyLinkedList.cpp b/AK/Tests/TestDoublyLinkedList.cpp index d663efbc993..407484e4431 100644 --- a/AK/Tests/TestDoublyLinkedList.cpp +++ b/AK/Tests/TestDoublyLinkedList.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -41,5 +41,3 @@ TEST_CASE(should_find_const) EXPECT_EQ(sut.end(), sut.find(42)); } - -TEST_MAIN(DoublyLinkedList) diff --git a/AK/Tests/TestEndian.cpp b/AK/Tests/TestEndian.cpp index 104a281ad6a..7f7f1a57ffc 100644 --- a/AK/Tests/TestEndian.cpp +++ b/AK/Tests/TestEndian.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -15,5 +15,3 @@ static_assert(BigEndian { 42 } == 42, "Big endian values should be value co static_assert(LittleEndian {} == 0, "Little endian values should be default constructed in a constexpr context."); static_assert(LittleEndian { 42 } == 42, "Little endian values should be value constructed in a constexpr context."); - -TEST_MAIN(Endian); diff --git a/AK/Tests/TestEnumBits.cpp b/AK/Tests/TestEnumBits.cpp index 9a357a16677..dc9eadf32d1 100644 --- a/AK/Tests/TestEnumBits.cpp +++ b/AK/Tests/TestEnumBits.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include -#include enum class VideoIntro : u8 { None = 0x0, @@ -66,5 +67,3 @@ TEST_CASE(has_flag) EXPECT(has_flag(intro, VideoIntro::Friends)); EXPECT(!has_flag(intro, VideoIntro::Well)); } - -TEST_MAIN(EnumBits) diff --git a/AK/Tests/TestFind.cpp b/AK/Tests/TestFind.cpp index d7df2bd9c67..26d4ab11fd3 100644 --- a/AK/Tests/TestFind.cpp +++ b/AK/Tests/TestFind.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -52,5 +52,3 @@ TEST_CASE(should_return_index_to_first_predicate_matching_value_in_container) EXPECT(4 == AK::find_index(a.begin(), a.end(), 0)); } - -TEST_MAIN(Find) diff --git a/AK/Tests/TestFormat.cpp b/AK/Tests/TestFormat.cpp index cc7b2db8a4d..525082b38ff 100644 --- a/AK/Tests/TestFormat.cpp +++ b/AK/Tests/TestFormat.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -290,5 +290,3 @@ TEST_CASE(long_long_regression) EXPECT_EQ(builder.string_view(), "81985529216486895"); } - -TEST_MAIN(Format) diff --git a/AK/Tests/TestGenericLexer.cpp b/AK/Tests/TestGenericLexer.cpp index 6b5d09bef29..8b9a08cd1dc 100644 --- a/AK/Tests/TestGenericLexer.cpp +++ b/AK/Tests/TestGenericLexer.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -156,5 +156,3 @@ TEST_CASE(should_constexpr_ignore_until_pred) }(); static_assert(sut.peek() == 'c'); } - -TEST_MAIN(GenericLexer) diff --git a/AK/Tests/TestHashFunctions.cpp b/AK/Tests/TestHashFunctions.cpp index 75c284b3550..fa8eafae9e9 100644 --- a/AK/Tests/TestHashFunctions.cpp +++ b/AK/Tests/TestHashFunctions.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -59,5 +59,3 @@ TEST_CASE(constexpr_ptr_hash) // "ptr_hash" test binds the result. static_assert(ptr_hash(FlatPtr(42))); } - -TEST_MAIN(HashFunctions) diff --git a/AK/Tests/TestHashMap.cpp b/AK/Tests/TestHashMap.cpp index dac0685d36b..a0573193097 100644 --- a/AK/Tests/TestHashMap.cpp +++ b/AK/Tests/TestHashMap.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -172,5 +172,3 @@ TEST_CASE(basic_contains) EXPECT_EQ(map.remove(1), true); EXPECT_EQ(map.contains(1), false); } - -TEST_MAIN(HashMap) diff --git a/AK/Tests/TestHashTable.cpp b/AK/Tests/TestHashTable.cpp index a0cae5014ce..55c297e7741 100644 --- a/AK/Tests/TestHashTable.cpp +++ b/AK/Tests/TestHashTable.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -173,5 +173,3 @@ TEST_CASE(basic_contains) EXPECT_EQ(table.remove(1), true); EXPECT_EQ(table.contains(1), false); } - -TEST_MAIN(HashTable) diff --git a/AK/Tests/TestHex.cpp b/AK/Tests/TestHex.cpp index 7bbf0f8e2a1..0f94cc03c8d 100644 --- a/AK/Tests/TestHex.cpp +++ b/AK/Tests/TestHex.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -59,5 +59,3 @@ TEST_CASE(should_constexpr_decode_hex_digit) static_assert(14u == decode_hex_digit('E')); static_assert(15u == decode_hex_digit('F')); } - -TEST_MAIN(Hex) diff --git a/AK/Tests/TestIPv4Address.cpp b/AK/Tests/TestIPv4Address.cpp index e0a787ded3d..b8f07d1e3c5 100644 --- a/AK/Tests/TestIPv4Address.cpp +++ b/AK/Tests/TestIPv4Address.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -151,5 +151,3 @@ TEST_CASE(should_compare) EXPECT(addr_a != addr_b); EXPECT(addr_a == addr_a); } - -TEST_MAIN(IPv4Address) diff --git a/AK/Tests/TestIndexSequence.cpp b/AK/Tests/TestIndexSequence.cpp index d7943873f67..31b94016515 100644 --- a/AK/Tests/TestIndexSequence.cpp +++ b/AK/Tests/TestIndexSequence.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include -#include #include template @@ -46,5 +47,3 @@ TEST_CASE(TypeList) static_assert(IsSame, bool>, ""); static_assert(IsSame, char>, ""); } - -TEST_MAIN(IndexSequence); diff --git a/AK/Tests/TestIntrusiveList.cpp b/AK/Tests/TestIntrusiveList.cpp index 3e3012bc20f..f75db9afb7e 100644 --- a/AK/Tests/TestIntrusiveList.cpp +++ b/AK/Tests/TestIntrusiveList.cpp @@ -4,10 +4,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include #include #include -#include class IntrusiveTestItem { public: @@ -120,5 +121,3 @@ TEST_CASE(intrusive_nonnull_ref_ptr_intrusive) EXPECT(nonnull_ref_list.is_empty()); } - -TEST_MAIN(IntrusiveList) diff --git a/AK/Tests/TestIntrusiveRedBlackTree.cpp b/AK/Tests/TestIntrusiveRedBlackTree.cpp index 0271e4af11c..207b026ceca 100644 --- a/AK/Tests/TestIntrusiveRedBlackTree.cpp +++ b/AK/Tests/TestIntrusiveRedBlackTree.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -114,5 +114,3 @@ TEST_CASE(clear) test.clear(); EXPECT_EQ(test.size(), 0u); } - -TEST_MAIN(RedBlackTree) diff --git a/AK/Tests/TestJSON.cpp b/AK/Tests/TestJSON.cpp index e0c85e1e03e..d85f68c2b51 100644 --- a/AK/Tests/TestJSON.cpp +++ b/AK/Tests/TestJSON.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -121,5 +121,3 @@ TEST_CASE(json_duplicate_keys) json.set("test", "baz"); EXPECT_EQ(json.to_string(), "{\"test\":\"baz\"}"); } - -TEST_MAIN(JSON) diff --git a/AK/Tests/TestLexicalPath.cpp b/AK/Tests/TestLexicalPath.cpp index ac96bf58d69..044f5f157a3 100644 --- a/AK/Tests/TestLexicalPath.cpp +++ b/AK/Tests/TestLexicalPath.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -74,5 +74,3 @@ TEST_CASE(relative_path) EXPECT_EQ(LexicalPath::relative_path("/tmp/foo.txt", "tmp"), String {}); EXPECT_EQ(LexicalPath::relative_path("tmp/foo.txt", "/tmp"), String {}); } - -TEST_MAIN(LexicalPath) diff --git a/AK/Tests/TestMACAddress.cpp b/AK/Tests/TestMACAddress.cpp index 7f87967f879..f91ae043a2b 100644 --- a/AK/Tests/TestMACAddress.cpp +++ b/AK/Tests/TestMACAddress.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -82,5 +82,3 @@ TEST_CASE(should_string_format) MACAddress sut(1, 2, 3, 4, 5, 6); EXPECT_EQ("01:02:03:04:05:06", sut.to_string()); } - -TEST_MAIN(MACAddress) diff --git a/AK/Tests/TestMemMem.cpp b/AK/Tests/TestMemMem.cpp index 8e1266f5c7e..f4dd0a3e526 100644 --- a/AK/Tests/TestMemMem.cpp +++ b/AK/Tests/TestMemMem.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -66,5 +66,3 @@ TEST_CASE(kmp_two_chunks) EXPECT_EQ(result_2.value_or(9), 4u); EXPECT(!result_3.has_value()); } - -TEST_MAIN(MemMem) diff --git a/AK/Tests/TestMemoryStream.cpp b/AK/Tests/TestMemoryStream.cpp index 23d1dfff6da..90512fe456b 100644 --- a/AK/Tests/TestMemoryStream.cpp +++ b/AK/Tests/TestMemoryStream.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -220,5 +220,3 @@ TEST_CASE(offset_calculation_error_regression) EXPECT_EQ(input, output); } - -TEST_MAIN(MemoryStream) diff --git a/AK/Tests/TestNeverDestroyed.cpp b/AK/Tests/TestNeverDestroyed.cpp index 29931f2757a..7b72d6bae34 100644 --- a/AK/Tests/TestNeverDestroyed.cpp +++ b/AK/Tests/TestNeverDestroyed.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -71,5 +71,3 @@ TEST_CASE(should_provide_basic_getter) AK::NeverDestroyed n {}; EXPECT_EQ(0, n.get().num_destroys); } - -TEST_MAIN(NeverDestroyed) diff --git a/AK/Tests/TestNonnullRefPtr.cpp b/AK/Tests/TestNonnullRefPtr.cpp index 19d43fc2e20..c26adadacc0 100644 --- a/AK/Tests/TestNonnullRefPtr.cpp +++ b/AK/Tests/TestNonnullRefPtr.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -59,5 +59,3 @@ TEST_CASE(swap_with_self) swap(object, object); EXPECT_EQ(object->ref_count(), 1u); } - -TEST_MAIN(NonnullRefPtr) diff --git a/AK/Tests/TestNumberFormat.cpp b/AK/Tests/TestNumberFormat.cpp index f4f9d64426e..373d3bef984 100644 --- a/AK/Tests/TestNumberFormat.cpp +++ b/AK/Tests/TestNumberFormat.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -125,5 +125,3 @@ TEST_CASE(extremes_8byte) warnln("(Skipping 8-byte-size_t test on 32-bit platform)"); } } - -TEST_MAIN(NumberFormat) diff --git a/AK/Tests/TestOptional.cpp b/AK/Tests/TestOptional.cpp index e14c513d0eb..583d11f0eb9 100644 --- a/AK/Tests/TestOptional.cpp +++ b/AK/Tests/TestOptional.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -53,5 +53,3 @@ TEST_CASE(short_notation) EXPECT_EQ(value->length(), 3u); EXPECT_EQ(*value, "foo"); } - -TEST_MAIN(Optional) diff --git a/AK/Tests/TestQueue.cpp b/AK/Tests/TestQueue.cpp index 12e240c275e..6e11e6e685e 100644 --- a/AK/Tests/TestQueue.cpp +++ b/AK/Tests/TestQueue.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -57,5 +57,3 @@ TEST_CASE(order) EXPECT(strings.is_empty()); } - -TEST_MAIN(Queue) diff --git a/AK/Tests/TestQuickSort.cpp b/AK/Tests/TestQuickSort.cpp index 70c8c74edc5..23fc7692dc7 100644 --- a/AK/Tests/TestQuickSort.cpp +++ b/AK/Tests/TestQuickSort.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -98,5 +98,3 @@ TEST_CASE(maximum_stack_depth) delete[] data; } - -TEST_MAIN(QuickSort) diff --git a/AK/Tests/TestRedBlackTree.cpp b/AK/Tests/TestRedBlackTree.cpp index 9940a968c64..51f95499574 100644 --- a/AK/Tests/TestRedBlackTree.cpp +++ b/AK/Tests/TestRedBlackTree.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -86,5 +86,3 @@ TEST_CASE(clear) test.clear(); EXPECT_EQ(test.size(), 0u); } - -TEST_MAIN(RedBlackTree) diff --git a/AK/Tests/TestRefPtr.cpp b/AK/Tests/TestRefPtr.cpp index f8461183f86..8c85ace7741 100644 --- a/AK/Tests/TestRefPtr.cpp +++ b/AK/Tests/TestRefPtr.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -147,5 +147,3 @@ TEST_CASE(self_observers) object->unref(); EXPECT_EQ(SelfAwareObject::num_destroyed, 1u); } - -TEST_MAIN(RefPtr) diff --git a/AK/Tests/TestSinglyLinkedList.cpp b/AK/Tests/TestSinglyLinkedList.cpp index 9d5b51c790d..3df43d2cb5d 100644 --- a/AK/Tests/TestSinglyLinkedList.cpp +++ b/AK/Tests/TestSinglyLinkedList.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -59,5 +59,3 @@ TEST_CASE(should_find_const_with_predicate) EXPECT_EQ(sut.end(), sut.find_if([](const auto v) { return v == 42; })); } - -TEST_MAIN(SinglyLinkedList) diff --git a/AK/Tests/TestSourceGenerator.cpp b/AK/Tests/TestSourceGenerator.cpp index c6cd3fd6eaa..9b8a3b7b6c6 100644 --- a/AK/Tests/TestSourceGenerator.cpp +++ b/AK/Tests/TestSourceGenerator.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -69,5 +69,3 @@ TEST_CASE(scoped) EXPECT_EQ(global_generator.as_string_view(), "\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-2 bar-0\nfoo-2 bar-3\nfoo-0 bar-0\nfoo-2 bar-0\n"); } - -TEST_MAIN(SourceGenerator) diff --git a/AK/Tests/TestSourceLocation.cpp b/AK/Tests/TestSourceLocation.cpp index 12f2e16c171..15910062f33 100644 --- a/AK/Tests/TestSourceLocation.cpp +++ b/AK/Tests/TestSourceLocation.cpp @@ -5,9 +5,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include #include -#include TEST_CASE(basic_scenario) { @@ -29,5 +30,3 @@ TEST_CASE(default_arg_scenario) EXPECT_EQ(expected_calling_function, actual_calling_function); } - -TEST_MAIN(SourceLocation) diff --git a/AK/Tests/TestSpan.cpp b/AK/Tests/TestSpan.cpp index 1b3587d7554..2668133c4e3 100644 --- a/AK/Tests/TestSpan.cpp +++ b/AK/Tests/TestSpan.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -123,5 +123,3 @@ TEST_CASE(span_from_c_string) const char* str = "Serenity"; [[maybe_unused]] ReadonlyBytes bytes { str, strlen(str) }; } - -TEST_MAIN(Span) diff --git a/AK/Tests/TestString.cpp b/AK/Tests/TestString.cpp index ab5dde54a66..b61828199ea 100644 --- a/AK/Tests/TestString.cpp +++ b/AK/Tests/TestString.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -235,5 +235,3 @@ TEST_CASE(sprintf) EXPECT_EQ(String(buf1), String("+12")); EXPECT_EQ(String(buf2), String("-12")); } - -TEST_MAIN(String) diff --git a/AK/Tests/TestStringUtils.cpp b/AK/Tests/TestStringUtils.cpp index 1f135944686..315c14f1da9 100644 --- a/AK/Tests/TestStringUtils.cpp +++ b/AK/Tests/TestStringUtils.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -304,5 +304,3 @@ TEST_CASE(to_snakecase) EXPECT_EQ(AK::StringUtils::to_snakecase("FBar"), "f_bar"); EXPECT_EQ(AK::StringUtils::to_snakecase("FooB"), "foo_b"); } - -TEST_MAIN(StringUtils) diff --git a/AK/Tests/TestStringView.cpp b/AK/Tests/TestStringView.cpp index 28a35a301e0..2ffbdf65fdf 100644 --- a/AK/Tests/TestStringView.cpp +++ b/AK/Tests/TestStringView.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -177,5 +177,3 @@ TEST_CASE(split_view) EXPECT_EQ(test_string_view.split_view_if(predicate), Vector({ "a", "b", "c", "d" })); EXPECT_EQ(test_string_view.split_view_if(predicate, true), Vector({ "a", "", "b", "c", "d" })); } - -TEST_MAIN(StringView) diff --git a/AK/Tests/TestTime.cpp b/AK/Tests/TestTime.cpp index 732450b75d7..61319cd6053 100644 --- a/AK/Tests/TestTime.cpp +++ b/AK/Tests/TestTime.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -261,5 +261,3 @@ TEST_CASE(truncation) EXPECT_EQ(TIME(9223372036854, 775'807'000).to_truncated_microseconds(), 0x7fff'ffff'ffff'ffff); EXPECT_EQ(TIME(9223372036854, 775'808'000).to_truncated_microseconds(), 0x7fff'ffff'ffff'ffff); } - -TEST_MAIN(Time) diff --git a/AK/Tests/TestTrie.cpp b/AK/Tests/TestTrie.cpp index 83279d8a2a6..50b574cced6 100644 --- a/AK/Tests/TestTrie.cpp +++ b/AK/Tests/TestTrie.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -66,5 +66,3 @@ TEST_CASE(iterate) ++i; } } - -TEST_MAIN(Trie) diff --git a/AK/Tests/TestTypeTraits.cpp b/AK/Tests/TestTypeTraits.cpp index 810efa99b7a..ecea1bfc15f 100644 --- a/AK/Tests/TestTypeTraits.cpp +++ b/AK/Tests/TestTypeTraits.cpp @@ -4,8 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include + #include -#include #include #define STATIC_EXPECT_EQ(lhs, rhs) \ @@ -104,5 +105,3 @@ TEST_CASE(UnderlyingType) STATIC_EXPECT_EQ(Type, u8); } - -TEST_MAIN(TypeTraits) diff --git a/AK/Tests/TestTypedTransfer.cpp b/AK/Tests/TestTypedTransfer.cpp index 72380f6a7ea..5a0c347092a 100644 --- a/AK/Tests/TestTypedTransfer.cpp +++ b/AK/Tests/TestTypedTransfer.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -39,5 +39,3 @@ TEST_CASE(overlapping_source_and_destination_2) for (size_t i = 0; i < 6; ++i) EXPECT_EQ(actual[i].m_value, expected[i].m_value); } - -TEST_MAIN(TypedTransfer) diff --git a/AK/Tests/TestURL.cpp b/AK/Tests/TestURL.cpp index 104dd7c2144..c92ee4fc5b0 100644 --- a/AK/Tests/TestURL.cpp +++ b/AK/Tests/TestURL.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -200,5 +200,3 @@ TEST_CASE(port_int_overflow_wrap) EXPECT_EQ(url.port(), expected_port); EXPECT_EQ(url.is_valid(), true); } - -TEST_MAIN(URL) diff --git a/AK/Tests/TestUtf8.cpp b/AK/Tests/TestUtf8.cpp index 1336fa35373..4a3f4e80294 100644 --- a/AK/Tests/TestUtf8.cpp +++ b/AK/Tests/TestUtf8.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include @@ -67,5 +67,3 @@ TEST_CASE(validate_invalid_ut8) EXPECT(!utf8_4.validate(valid_bytes)); EXPECT(valid_bytes == 0); } - -TEST_MAIN(UTF8) diff --git a/AK/Tests/TestVector.cpp b/AK/Tests/TestVector.cpp index b81c01ac75c..0439a0605fc 100644 --- a/AK/Tests/TestVector.cpp +++ b/AK/Tests/TestVector.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -399,5 +399,3 @@ TEST_CASE(should_find_index) EXPECT_EQ(4u, v.find_first_index(0).value()); EXPECT(!v.find_first_index(42).has_value()); } - -TEST_MAIN(Vector) diff --git a/AK/Tests/TestWeakPtr.cpp b/AK/Tests/TestWeakPtr.cpp index 63651204b1b..8a573276cd6 100644 --- a/AK/Tests/TestWeakPtr.cpp +++ b/AK/Tests/TestWeakPtr.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -64,5 +64,3 @@ TEST_CASE(weakptr_move) EXPECT_EQ(weak2.is_null(), true); } - -TEST_MAIN(WeakPtr) diff --git a/Meta/CMake/utils.cmake b/Meta/CMake/utils.cmake index e3aa4e136e2..a57cee686ce 100644 --- a/Meta/CMake/utils.cmake +++ b/Meta/CMake/utils.cmake @@ -29,7 +29,6 @@ endfunction() function(serenity_lib target_name fs_name) serenity_install_headers(${target_name}) serenity_install_sources("Userland/Libraries/${target_name}") - #add_library(${target_name} SHARED ${SOURCES} ${GENERATED_SOURCES}) add_library(${target_name} SHARED ${SOURCES} ${GENERATED_SOURCES}) install(TARGETS ${target_name} DESTINATION usr/lib) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name}) @@ -74,6 +73,21 @@ function(serenity_bin target_name) serenity_generated_sources(${target_name}) endfunction() +function(serenity_test test_src sub_dir) + cmake_parse_arguments(SERENITY_TEST "CUSTOM_MAIN" "" "LIBS" ${ARGN}) + set(TEST_SOURCES ${test_src}) + if (NOT ${SERENITY_TEST_CUSTOM_MAIN}) + list(APPEND TEST_SOURCES "${CMAKE_SOURCE_DIR}/Userland/Libraries/LibTest/TestMain.cpp") + endif() + get_filename_component(test_name ${test_src} NAME_WE) + add_executable(${test_name} ${TEST_SOURCES}) + target_link_libraries(${test_name} LibTest LibCore) + foreach(lib ${SERENITY_TEST_LIBS}) + target_link_libraries(${test_name} ${lib}) + endforeach() + install(TARGETS ${test_name} RUNTIME DESTINATION usr/Tests/${sub_dir}) +endfunction() + function(serenity_app target_name) cmake_parse_arguments(SERENITY_APP "" "ICON" "" ${ARGN}) diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 556345d5ed5..ccc4a589158 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -77,9 +77,14 @@ list(FILTER SHELL_SOURCES EXCLUDE REGEX ".*main.cpp$") file(GLOB LIBSQL_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibSQL/*.cpp") file(GLOB LIBSQL_TEST_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibSQL/Tests/*.cpp") +file(GLOB LIBTEST_SOURCES CONFIGURE_DEPENDS "../../Userland/Libraries/LibTest/*.cpp") +list(FILTER LIBTEST_SOURCES EXCLUDE REGEX ".*Main.cpp$") +file(GLOB LIBTEST_MAIN CONFIGURE_DEPENDS "../../Userland/Libraries/LibTest/TestMain.cpp") + set(LAGOM_REGEX_SOURCES ${LIBREGEX_LIBC_SOURCES} ${LIBREGEX_SOURCES}) set(LAGOM_CORE_SOURCES ${AK_SOURCES} ${LIBCORE_SOURCES}) set(LAGOM_MORE_SOURCES ${LIBARCHIVE_SOURCES} ${LIBAUDIO_SOURCES} ${LIBELF_SOURCES} ${LIBIPC_SOURCES} ${LIBLINE_SOURCES} ${LIBJS_SOURCES} ${LIBJS_SUBDIR_SOURCES} ${LIBX86_SOURCES} ${LIBCRYPTO_SOURCES} ${LIBCOMPRESS_SOURCES} ${LIBCRYPTO_SUBDIR_SOURCES} ${LIBTLS_SOURCES} ${LIBTTF_SOURCES} ${LIBTEXTCODEC_SOURCES} ${LIBMARKDOWN_SOURCES} ${LIBGEMINI_SOURCES} ${LIBGFX_SOURCES} ${LIBGUI_GML_SOURCES} ${LIBHTTP_SOURCES} ${LAGOM_REGEX_SOURCES} ${SHELL_SOURCES} ${LIBSQL_SOURCES}) +set(LAGOM_TEST_SOURCES ${LIBTEST_SOURCES}) # FIXME: This is a hack, because the lagom stuff can be build individually or # in combination with the system, we generate two Debug.h files. One in @@ -98,6 +103,7 @@ if (BUILD_LAGOM) if (NOT ENABLE_OSS_FUZZ AND NOT ENABLE_FUZZER_SANITIZER) enable_testing() + add_library(LagomTest $ ${LAGOM_TEST_SOURCES}) add_executable(TestApp TestApp.cpp) target_link_libraries(TestApp Lagom) target_link_libraries(TestApp stdc++) @@ -178,8 +184,8 @@ if (BUILD_LAGOM) foreach(source ${AK_TEST_SOURCES}) get_filename_component(name ${source} NAME_WE) - add_executable(${name}_lagom ${source}) - target_link_libraries(${name}_lagom LagomCore) + add_executable(${name}_lagom ${source} ${LIBTEST_MAIN}) + target_link_libraries(${name}_lagom LagomTest) add_test( NAME ${name}_lagom COMMAND ${name}_lagom @@ -190,8 +196,8 @@ if (BUILD_LAGOM) foreach(source ${LIBREGEX_TESTS}) get_filename_component(name ${source} NAME_WE) - add_executable(${name}_lagom ${source} ${LAGOM_REGEX_SOURCES}) - target_link_libraries(${name}_lagom LagomCore) + add_executable(${name}_lagom ${source} ${LAGOM_REGEX_SOURCES} ${LIBTEST_MAIN}) + target_link_libraries(${name}_lagom LagomTest) add_test( NAME ${name}_lagom COMMAND ${name}_lagom @@ -201,8 +207,8 @@ if (BUILD_LAGOM) foreach(source ${LIBCOMPRESS_TESTS}) get_filename_component(name ${source} NAME_WE) - add_executable(${name}_lagom ${source} ${LIBCOMPRESS_SOURCES}) - target_link_libraries(${name}_lagom Lagom) + add_executable(${name}_lagom ${source} ${LIBCOMPRESS_SOURCES} ${LIBTEST_MAIN}) + target_link_libraries(${name}_lagom Lagom LagomTest) add_test( NAME ${name}_lagom COMMAND ${name}_lagom @@ -212,8 +218,8 @@ if (BUILD_LAGOM) foreach(source ${LIBSQL_TEST_SOURCES}) get_filename_component(name ${source} NAME_WE) - add_executable(${name}_lagom ${source} ${LIBSQL_SOURCES}) - target_link_libraries(${name}_lagom LagomCore) + add_executable(${name}_lagom ${source} ${LIBSQL_SOURCES} ${LIBTEST_MAIN}) + target_link_libraries(${name}_lagom LagomTest) add_test( NAME ${name}_lagom COMMAND ${name}_lagom diff --git a/Userland/Applications/Spreadsheet/CMakeLists.txt b/Userland/Applications/Spreadsheet/CMakeLists.txt index 15a9f6c020c..73945a9a5fe 100644 --- a/Userland/Applications/Spreadsheet/CMakeLists.txt +++ b/Userland/Applications/Spreadsheet/CMakeLists.txt @@ -37,3 +37,7 @@ set(GENERATED_SOURCES serenity_app(Spreadsheet ICON app-spreadsheet) target_link_libraries(Spreadsheet LibGUI LibJS LibWeb) + +# FIXME: build these tests +#serenity_test(Writers/Test/TestXSVWriter.cpp Spreadsheet) +#serenity_test(Readers/Test/TestXSV.cpp Spreadsheet) diff --git a/Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp b/Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp index 196a496c559..0155912fb2e 100644 --- a/Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp +++ b/Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include "../CSV.h" #include "../XSV.h" @@ -86,5 +86,3 @@ BENCHMARK_CASE(fairly_big_data) EXPECT(!csv.has_error()); EXPECT_EQ(csv.size(), 100000u); } - -TEST_MAIN(XSV) diff --git a/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp b/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp index 5dad1dcfdda..8f0348bf8da 100644 --- a/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp +++ b/Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include "../CSV.h" #include "../XSV.h" @@ -72,5 +72,3 @@ We"ll,"Hello,", Friends EXPECT_EQ(StringView { stream.bytes() }, expected_output); } - -TEST_MAIN(XSV) diff --git a/Userland/Libraries/LibC/Tests/CMakeLists.txt b/Userland/Libraries/LibC/Tests/CMakeLists.txt index 768d9842278..5dff11b9a33 100644 --- a/Userland/Libraries/LibC/Tests/CMakeLists.txt +++ b/Userland/Libraries/LibC/Tests/CMakeLists.txt @@ -1,8 +1,5 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "*.cpp") foreach(source ${TEST_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name} ${source}) - target_link_libraries(${name} LibC LibCore) - install(TARGETS ${name} RUNTIME DESTINATION usr/Tests/LibC) + serenity_test(${source} LibC) endforeach() diff --git a/Userland/Libraries/LibC/Tests/TestLibCTime.cpp b/Userland/Libraries/LibC/Tests/TestLibCTime.cpp index 4e4c3dd303e..fcf23276392 100644 --- a/Userland/Libraries/LibC/Tests/TestLibCTime.cpp +++ b/Userland/Libraries/LibC/Tests/TestLibCTime.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include const auto expected_epoch = "Thu Jan 1 00:00:00 1970\n"sv; @@ -41,5 +41,3 @@ TEST_CASE(ctime_r) EXPECT_EQ(expected_epoch, StringView(result)); } - -TEST_MAIN(LibCTime) diff --git a/Userland/Libraries/LibCompress/Tests/CMakeLists.txt b/Userland/Libraries/LibCompress/Tests/CMakeLists.txt index 8b157899719..bfd8880d1d3 100644 --- a/Userland/Libraries/LibCompress/Tests/CMakeLists.txt +++ b/Userland/Libraries/LibCompress/Tests/CMakeLists.txt @@ -1,8 +1,5 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "*.cpp") foreach(source ${TEST_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name} ${source}) - target_link_libraries(${name} LibCore LibCompress) - install(TARGETS ${name} RUNTIME DESTINATION usr/Tests/LibCompress) + serenity_test(${source} LibCompress LIBS LibCompress) endforeach() diff --git a/Userland/Libraries/LibCompress/Tests/TestDeflate.cpp b/Userland/Libraries/LibCompress/Tests/TestDeflate.cpp index af88c9f180d..7b992d8fee6 100644 --- a/Userland/Libraries/LibCompress/Tests/TestDeflate.cpp +++ b/Userland/Libraries/LibCompress/Tests/TestDeflate.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -155,5 +155,3 @@ TEST_CASE(deflate_compress_literals) auto compressed = Compress::DeflateCompressor::compress_all(test, Compress::DeflateCompressor::CompressionLevel::GOOD); EXPECT(compressed.has_value()); } - -TEST_MAIN(Deflate) diff --git a/Userland/Libraries/LibCompress/Tests/TestGzip.cpp b/Userland/Libraries/LibCompress/Tests/TestGzip.cpp index 8d04b238a54..189d5b52c95 100644 --- a/Userland/Libraries/LibCompress/Tests/TestGzip.cpp +++ b/Userland/Libraries/LibCompress/Tests/TestGzip.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -95,5 +95,3 @@ TEST_CASE(gzip_round_trip) EXPECT(uncompressed.has_value()); EXPECT(uncompressed.value() == original); } - -TEST_MAIN(Gzip) diff --git a/Userland/Libraries/LibCompress/Tests/TestZlib.cpp b/Userland/Libraries/LibCompress/Tests/TestZlib.cpp index 1d6b0a04086..8ab5b81a950 100644 --- a/Userland/Libraries/LibCompress/Tests/TestZlib.cpp +++ b/Userland/Libraries/LibCompress/Tests/TestZlib.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -23,5 +23,3 @@ TEST_CASE(zlib_decompress_simple) const auto decompressed = Compress::Zlib::decompress_all(compressed); EXPECT(decompressed.value().bytes() == (ReadonlyBytes { uncompressed, sizeof(uncompressed) - 1 })); } - -TEST_MAIN(Zlib) diff --git a/Userland/Libraries/LibRegex/Tests/Benchmark.cpp b/Userland/Libraries/LibRegex/Tests/Benchmark.cpp index 8e13cce111b..b51316fdb5a 100644 --- a/Userland/Libraries/LibRegex/Tests/Benchmark.cpp +++ b/Userland/Libraries/LibRegex/Tests/Benchmark.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include // import first, to prevent warning of VERIFY* redefinition +#include // import first, to prevent warning of VERIFY* redefinition #include #include @@ -967,5 +967,3 @@ BENCHMARK_CASE(simple_notbol_noteol_benchmark_reference_stdcpp) # endif #endif - -TEST_MAIN(Regex) diff --git a/Userland/Libraries/LibRegex/Tests/CMakeLists.txt b/Userland/Libraries/LibRegex/Tests/CMakeLists.txt index 66478f6ad67..a9ccade4270 100644 --- a/Userland/Libraries/LibRegex/Tests/CMakeLists.txt +++ b/Userland/Libraries/LibRegex/Tests/CMakeLists.txt @@ -2,8 +2,5 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "*.cpp") file(GLOB REGEX_SOURCES CONFIGURE_DEPENDS "../*.cpp" "../C/*.cpp") foreach(source ${TEST_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name} ${source} ${REGEX_SOURCES}) - target_link_libraries(${name} LibCore) - install(TARGETS ${name} RUNTIME DESTINATION usr/Tests/LibRegex) + serenity_test(${source} LibRegex LIBS LibRegex) endforeach() diff --git a/Userland/Libraries/LibRegex/Tests/Regex.cpp b/Userland/Libraries/LibRegex/Tests/Regex.cpp index 5aeb4ccbf8f..054c54485b2 100644 --- a/Userland/Libraries/LibRegex/Tests/Regex.cpp +++ b/Userland/Libraries/LibRegex/Tests/Regex.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include // import first, to prevent warning of VERIFY* redefinition +#include // import first, to prevent warning of VERIFY* redefinition #include #include @@ -595,5 +595,3 @@ TEST_CASE(replace) EXPECT_EQ(re.replace(test.subject, test.replacement), test.expected); } } - -TEST_MAIN(Regex) diff --git a/Userland/Libraries/LibRegex/Tests/RegexLibC.cpp b/Userland/Libraries/LibRegex/Tests/RegexLibC.cpp index 7e001f4b655..bea5e5984cd 100644 --- a/Userland/Libraries/LibRegex/Tests/RegexLibC.cpp +++ b/Userland/Libraries/LibRegex/Tests/RegexLibC.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -1116,5 +1116,3 @@ TEST_CASE(simple_notbol_noteol) regfree(®ex); } - -TEST_MAIN(Regex) diff --git a/Userland/Libraries/LibSQL/Tests/CMakeLists.txt b/Userland/Libraries/LibSQL/Tests/CMakeLists.txt index b028333c615..f002a1e864b 100644 --- a/Userland/Libraries/LibSQL/Tests/CMakeLists.txt +++ b/Userland/Libraries/LibSQL/Tests/CMakeLists.txt @@ -1,8 +1,5 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS "*.cpp") foreach(source ${TEST_SOURCES}) - get_filename_component(name ${source} NAME_WE) - add_executable(${name} ${source}) - target_link_libraries(${name} LibSQL) - install(TARGETS ${name} RUNTIME DESTINATION usr/Tests/LibSQL) + serenity_test(${source} LibSQL LIBS LibSQL) endforeach() diff --git a/Userland/Libraries/LibSQL/Tests/TestSqlExpressionParser.cpp b/Userland/Libraries/LibSQL/Tests/TestSqlExpressionParser.cpp index a3d2e6d32f9..c2a6b3bfd7d 100644 --- a/Userland/Libraries/LibSQL/Tests/TestSqlExpressionParser.cpp +++ b/Userland/Libraries/LibSQL/Tests/TestSqlExpressionParser.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -602,5 +602,3 @@ TEST_CASE(in_selection_expression) validate("15 IN (SELECT * FROM table)", false); validate("15 NOT IN (SELECT * FROM table)", true); } - -TEST_MAIN(SqlExpressionParser) diff --git a/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp b/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp index 7438311bdc0..0126a85e4e1 100644 --- a/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp +++ b/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -735,5 +735,3 @@ TEST_CASE(common_table_expression) validate("WITH table (column1, column2) AS (SELECT * FROM table) DELETE FROM table;", { false, { { "table", { "column1", "column2" } } } }); validate("WITH RECURSIVE table AS (SELECT * FROM table) DELETE FROM table;", { true, { { "table", {} } } }); } - -TEST_MAIN(SqlStatementParser) diff --git a/Userland/Libraries/LibTest/CMakeLists.txt b/Userland/Libraries/LibTest/CMakeLists.txt index a924ea3e3ff..7816fdac71c 100644 --- a/Userland/Libraries/LibTest/CMakeLists.txt +++ b/Userland/Libraries/LibTest/CMakeLists.txt @@ -1 +1,8 @@ serenity_install_sources("Userland/Libraries/LibTest") + +set(SOURCES + TestSuite.cpp +) + +serenity_lib(LibTest test) +target_link_libraries(LibTest LibC) diff --git a/Userland/Libraries/LibTest/Macros.h b/Userland/Libraries/LibTest/Macros.h new file mode 100644 index 00000000000..b4704508e27 --- /dev/null +++ b/Userland/Libraries/LibTest/Macros.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace AK { +template +void warnln(CheckedFormatString&& fmtstr, const Parameters&...); +} + +namespace Test { +// Declare a helper so that we can call it from VERIFY in included headers +void current_test_case_did_fail(); +} + +#undef VERIFY +#define VERIFY(x) \ + do { \ + if (!(x)) { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: VERIFY({}) failed", __FILE__, __LINE__, #x); \ + ::Test::current_test_case_did_fail(); \ + } \ + } while (false) + +#undef VERIFY_NOT_REACHED +#define VERIFY_NOT_REACHED() \ + do { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: VERIFY_NOT_REACHED() called", __FILE__, __LINE__); \ + ::abort(); \ + } while (false) + +#undef TODO +#define TODO() \ + do { \ + ::AK::warnln(stderr, "\033[31;1mFAIL\033[0m: {}:{}: TODO() called", __FILE__, __LINE__); \ + ::abort(); \ + } while (false) + +#define EXPECT_EQ(a, b) \ + do { \ + auto lhs = (a); \ + auto rhs = (b); \ + if (lhs != rhs) { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}", __FILE__, __LINE__, #a, #b, FormatIfSupported { lhs }, FormatIfSupported { rhs }); \ + ::Test::current_test_case_did_fail(); \ + } \ + } while (false) + +// If you're stuck and `EXPECT_EQ` seems to refuse to print anything useful, +// try this: It'll spit out a nice compiler error telling you why it doesn't print. +#define EXPECT_EQ_FORCE(a, b) \ + do { \ + auto lhs = (a); \ + auto rhs = (b); \ + if (lhs != rhs) { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_EQ({}, {}) failed with lhs={} and rhs={}", __FILE__, __LINE__, #a, #b, lhs, rhs); \ + ::Test::current_test_case_did_fail(); \ + } \ + } while (false) + +#define EXPECT(x) \ + do { \ + if (!(x)) { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT({}) failed", __FILE__, __LINE__, #x); \ + ::Test::current_test_case_did_fail(); \ + } \ + } while (false) + +#define EXPECT_APPROXIMATE(a, b) \ + do { \ + auto expect_close_lhs = a; \ + auto expect_close_rhs = b; \ + auto expect_close_diff = static_cast(expect_close_lhs) - static_cast(expect_close_rhs); \ + if (fabs(expect_close_diff) > 0.0000005) { \ + ::AK::warnln("\033[31;1mFAIL\033[0m: {}:{}: EXPECT_APPROXIMATE({}, {})" \ + " failed with lhs={}, rhs={}, (lhs-rhs)={}", \ + __FILE__, __LINE__, #a, #b, expect_close_lhs, expect_close_rhs, expect_close_diff); \ + ::Test::current_test_case_did_fail(); \ + } \ + } while (false) diff --git a/Userland/Libraries/LibTest/TestCase.h b/Userland/Libraries/LibTest/TestCase.h new file mode 100644 index 00000000000..d0fb713567f --- /dev/null +++ b/Userland/Libraries/LibTest/TestCase.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include // intentionally first -- we redefine VERIFY and friends in here + +#include +#include +#include +#include + +namespace Test { + +using TestFunction = Function; + +class TestCase : public RefCounted { +public: + TestCase(const String& name, TestFunction&& fn, bool is_benchmark) + : m_name(name) + , m_function(move(fn)) + , m_is_benchmark(is_benchmark) + { + } + + bool is_benchmark() const { return m_is_benchmark; } + const String& name() const { return m_name; } + const TestFunction& func() const { return m_function; } + +private: + String m_name; + TestFunction m_function; + bool m_is_benchmark; +}; + +// Helper to hide implementation of TestSuite from users +void add_test_case_to_suite(const NonnullRefPtr& test_case); + +} + +#define __TESTCASE_FUNC(x) __test_##x +#define __TESTCASE_TYPE(x) __TestCase_##x + +#define TEST_CASE(x) \ + static void __TESTCASE_FUNC(x)(); \ + struct __TESTCASE_TYPE(x) { \ + __TESTCASE_TYPE(x) \ + () { add_test_case_to_suite(adopt_ref(*new ::Test::TestCase(#x, __TESTCASE_FUNC(x), false))); } \ + }; \ + static struct __TESTCASE_TYPE(x) __TESTCASE_TYPE(x); \ + static void __TESTCASE_FUNC(x)() + +#define __BENCHMARK_FUNC(x) __benchmark_##x +#define __BENCHMARK_TYPE(x) __BenchmarkCase_##x + +#define BENCHMARK_CASE(x) \ + static void __BENCHMARK_FUNC(x)(); \ + struct __BENCHMARK_TYPE(x) { \ + __BENCHMARK_TYPE(x) \ + () { add_test_case_to_suite(adopt_ref(*new ::Test::TestCase(#x, __BENCHMARK_FUNC(x), true))); } \ + }; \ + static struct __BENCHMARK_TYPE(x) __BENCHMARK_TYPE(x); \ + static void __BENCHMARK_FUNC(x)() diff --git a/Userland/Libraries/LibTest/TestMain.cpp b/Userland/Libraries/LibTest/TestMain.cpp new file mode 100644 index 00000000000..6a232e16180 --- /dev/null +++ b/Userland/Libraries/LibTest/TestMain.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include + +#ifdef KERNEL +# define TEST_MAIN test_main +#else +# define TEST_MAIN main +#endif + +int TEST_MAIN(int argc, char** argv) +{ + if (argc < 1 || !argv[0] || '\0' == *argv[0]) { + warnln("Test main does not have a valid test name!"); + return 1; + } + int ret = ::Test::TestSuite::the().main(argv[0], argc, argv); + ::Test::TestSuite::release(); + return ret; +} diff --git a/Userland/Libraries/LibTest/TestSuite.cpp b/Userland/Libraries/LibTest/TestSuite.cpp new file mode 100644 index 00000000000..ac2b93b7de1 --- /dev/null +++ b/Userland/Libraries/LibTest/TestSuite.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include // intentionally first -- we redefine VERIFY and friends in here + +#include +#include +#include +#include + +namespace Test { + +TestSuite* TestSuite::s_global = nullptr; + +class TestElapsedTimer { +public: + TestElapsedTimer() { restart(); } + + void restart() { gettimeofday(&m_started, nullptr); } + + u64 elapsed_milliseconds() + { + struct timeval now = {}; + gettimeofday(&now, nullptr); + + struct timeval delta = {}; + timersub(&now, &m_started, &delta); + + return delta.tv_sec * 1000 + delta.tv_usec / 1000; + } + +private: + struct timeval m_started = {}; +}; + +// Declared in Macros.h +void current_test_case_did_fail() +{ + TestSuite::the().current_test_case_did_fail(); +} + +// Declared in TestCase.h +void add_test_case_to_suite(const NonnullRefPtr& test_case) +{ + TestSuite::the().add_case(test_case); +} + +int TestSuite::main(const String& suite_name, int argc, char** argv) +{ + m_suite_name = suite_name; + + Core::ArgsParser args_parser; + + bool do_tests_only = getenv("TESTS_ONLY") != nullptr; + bool do_benchmarks_only = false; + bool do_list_cases = false; + const char* search_string = "*"; + + args_parser.add_option(do_tests_only, "Only run tests.", "tests", 0); + args_parser.add_option(do_benchmarks_only, "Only run benchmarks.", "bench", 0); + args_parser.add_option(do_list_cases, "List available test cases.", "list", 0); + args_parser.add_positional_argument(search_string, "Only run matching cases.", "pattern", Core::ArgsParser::Required::No); + args_parser.parse(argc, argv); + + const auto& matching_tests = find_cases(search_string, !do_benchmarks_only, !do_tests_only); + + if (do_list_cases) { + outln("Available cases for {}:", suite_name); + for (const auto& test : matching_tests) { + outln(" {}", test.name()); + } + return 0; + } + + outln("Running {} cases out of {}.", matching_tests.size(), m_cases.size()); + + return run(matching_tests); +} + +NonnullRefPtrVector TestSuite::find_cases(const String& search, bool find_tests, bool find_benchmarks) +{ + NonnullRefPtrVector matches; + for (const auto& t : m_cases) { + if (!search.is_empty() && !t.name().matches(search, CaseSensitivity::CaseInsensitive)) { + continue; + } + + if (!find_tests && !t.is_benchmark()) { + continue; + } + if (!find_benchmarks && t.is_benchmark()) { + continue; + } + + matches.append(t); + } + return matches; +} + +int TestSuite::run(const NonnullRefPtrVector& tests) +{ + size_t test_count = 0; + size_t test_failed_count = 0; + size_t benchmark_count = 0; + TestElapsedTimer global_timer; + + for (const auto& t : tests) { + const auto test_type = t.is_benchmark() ? "benchmark" : "test"; + + warnln("Running {} '{}'.", test_type, t.name()); + m_current_test_case_passed = true; + + TestElapsedTimer timer; + t.func()(); + const auto time = timer.elapsed_milliseconds(); + + dbgln("{} {} '{}' in {}ms", m_current_test_case_passed ? "Completed" : "Failed", test_type, t.name(), time); + + if (t.is_benchmark()) { + m_benchtime += time; + benchmark_count++; + } else { + m_testtime += time; + test_count++; + } + + if (!m_current_test_case_passed) { + test_failed_count++; + } + } + + dbgln("Finished {} tests and {} benchmarks in {}ms ({}ms tests, {}ms benchmarks, {}ms other).", + test_count, + benchmark_count, + global_timer.elapsed_milliseconds(), + m_testtime, + m_benchtime, + global_timer.elapsed_milliseconds() - (m_testtime + m_benchtime)); + dbgln("Out of {} tests, {} passed and {} failed.", test_count, test_count - test_failed_count, test_failed_count); + + return (int)test_failed_count; +} + +} diff --git a/Userland/Libraries/LibTest/TestSuite.h b/Userland/Libraries/LibTest/TestSuite.h new file mode 100644 index 00000000000..694b6d1a696 --- /dev/null +++ b/Userland/Libraries/LibTest/TestSuite.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include // intentionally first -- we redefine VERIFY and friends in here + +#include +#include +#include +#include +#include + +namespace Test { + +class TestSuite { +public: + static TestSuite& the() + { + if (s_global == nullptr) + s_global = new TestSuite(); + return *s_global; + } + + static void release() + { + if (s_global) + delete s_global; + s_global = nullptr; + } + + int run(const NonnullRefPtrVector&); + int main(const String& suite_name, int argc, char** argv); + NonnullRefPtrVector find_cases(const String& search, bool find_tests, bool find_benchmarks); + void add_case(const NonnullRefPtr& test_case) + { + m_cases.append(test_case); + } + + void current_test_case_did_fail() { m_current_test_case_passed = false; } + +private: + static TestSuite* s_global; + NonnullRefPtrVector m_cases; + u64 m_testtime = 0; + u64 m_benchtime = 0; + String m_suite_name; + bool m_current_test_case_passed = true; +}; + +} diff --git a/Userland/Tests/Kernel/CMakeLists.txt b/Userland/Tests/Kernel/CMakeLists.txt index cd9438dc4a8..408d82163cf 100644 --- a/Userland/Tests/Kernel/CMakeLists.txt +++ b/Userland/Tests/Kernel/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") +# FIXME: These tests do not use LibTest foreach(CMD_SRC ${CMD_SOURCES}) get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE) add_executable(${CMD_NAME} ${CMD_SRC}) diff --git a/Userland/Tests/LibC/CMakeLists.txt b/Userland/Tests/LibC/CMakeLists.txt index 799dfa9ff4e..a42c42b47e7 100644 --- a/Userland/Tests/LibC/CMakeLists.txt +++ b/Userland/Tests/LibC/CMakeLists.txt @@ -1,5 +1,8 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") +list(REMOVE_ITEM CMD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/snprintf-correctness.cpp) +list(REMOVE_ITEM CMD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/strlcpy-correctness.cpp) +# FIXME: These tests do not use LibTest foreach(CMD_SRC ${CMD_SOURCES}) get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE) add_executable(${CMD_NAME} ${CMD_SRC}) @@ -7,4 +10,5 @@ foreach(CMD_SRC ${CMD_SOURCES}) install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/LibC) endforeach() -#target_link_libraries(foobar LibPthread) +serenity_test(snprintf-correctness.cpp LibC) +serenity_test(strlcpy-correctness.cpp LibC) diff --git a/Userland/Tests/LibC/snprintf-correctness.cpp b/Userland/Tests/LibC/snprintf-correctness.cpp index 5b8200db4fe..0df2a5cc309 100644 --- a/Userland/Tests/LibC/snprintf-correctness.cpp +++ b/Userland/Tests/LibC/snprintf-correctness.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -141,5 +141,3 @@ TEST_CASE(special_cases) EXPECT(test_single({ LITERAL("x"), "whf", POISON, 3, LITERAL("\0") })); EXPECT(test_single({ LITERAL("xx"), "whf", POISON, 3, LITERAL("w\0") })); } - -TEST_MAIN(Sprintf) diff --git a/Userland/Tests/LibC/strlcpy-correctness.cpp b/Userland/Tests/LibC/strlcpy-correctness.cpp index c7e4cb0401a..e23765cd29a 100644 --- a/Userland/Tests/LibC/strlcpy-correctness.cpp +++ b/Userland/Tests/LibC/strlcpy-correctness.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -162,5 +162,3 @@ TEST_CASE(to_nullptr) EXPECT(test_single({ LITERAL("Hello World!\0\0\0"), LITERAL("Hello Friend!"), LITERAL("Hello Friend!\0\0") })); EXPECT(test_single({ LITERAL("aaaaaaaaaa"), LITERAL("whf"), LITERAL("whf\0aaaaaa") })); } - -TEST_MAIN(Sprintf) diff --git a/Userland/Tests/LibGfx/CMakeLists.txt b/Userland/Tests/LibGfx/CMakeLists.txt index 1c2bc2f17e8..f0f5cecab93 100644 --- a/Userland/Tests/LibGfx/CMakeLists.txt +++ b/Userland/Tests/LibGfx/CMakeLists.txt @@ -1,12 +1,12 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") +list(REMOVE_ITEM CMD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/painter.cpp) +# FIXME These tests do not use LibTest foreach(CMD_SRC ${CMD_SOURCES}) get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE) add_executable(${CMD_NAME} ${CMD_SRC}) - target_link_libraries(${CMD_NAME} LibCore) + target_link_libraries(${CMD_NAME} LibCore LibGUI) install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/LibGfx) endforeach() -target_link_libraries(font LibGUI LibCore) -target_link_libraries(image-decoder LibGUI LibCore) -target_link_libraries(painter LibGUI LibCore) +serenity_test(painter.cpp LibGfx LIBS LibGUI) diff --git a/Userland/Tests/LibGfx/painter.cpp b/Userland/Tests/LibGfx/painter.cpp index 50210f51a75..ca4fef41cf2 100644 --- a/Userland/Tests/LibGfx/painter.cpp +++ b/Userland/Tests/LibGfx/painter.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -51,5 +51,3 @@ BENCHMARK_CASE(fill_with_gradient) painter.fill_rect_with_gradient(bitmap->rect(), Color::Blue, Color::Red); } } - -TEST_MAIN(Painter) diff --git a/Userland/Tests/LibM/CMakeLists.txt b/Userland/Tests/LibM/CMakeLists.txt index de7c217201b..bf1c0cc927a 100644 --- a/Userland/Tests/LibM/CMakeLists.txt +++ b/Userland/Tests/LibM/CMakeLists.txt @@ -1,8 +1,5 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") foreach(CMD_SRC ${CMD_SOURCES}) - get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE) - add_executable(${CMD_NAME} ${CMD_SRC}) - target_link_libraries(${CMD_NAME} LibCore) - install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/LibM) + serenity_test(${CMD_SRC} LibM) endforeach() diff --git a/Userland/Tests/LibM/test-math.cpp b/Userland/Tests/LibM/test-math.cpp index cdc5f351736..e48a5955e27 100644 --- a/Userland/Tests/LibM/test-math.cpp +++ b/Userland/Tests/LibM/test-math.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include @@ -250,5 +250,3 @@ TEST_CASE(fmax_and_fmin) EXPECT(fmin(0, NAN) == 0); EXPECT(isnan(fmin(NAN, NAN))); } - -TEST_MAIN(Math) diff --git a/Userland/Tests/UserspaceEmulator/CMakeLists.txt b/Userland/Tests/UserspaceEmulator/CMakeLists.txt index f39e141ee63..3fbbbc41202 100644 --- a/Userland/Tests/UserspaceEmulator/CMakeLists.txt +++ b/Userland/Tests/UserspaceEmulator/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp") +# FIXME: These tests do not use LibTest foreach(CMD_SRC ${CMD_SOURCES}) get_filename_component(CMD_NAME ${CMD_SRC} NAME_WE) add_executable(${CMD_NAME} ${CMD_SRC})