Tests: Convert remaining LibC tests to LibTest

Convert them to using outln instead of printf at the same time.
This commit is contained in:
Andrew Kaster 2021-09-01 04:40:46 -06:00 committed by Andreas Kling
parent 1d253880e6
commit b3e3e4d45d
Notes: sideshowbarker 2024-07-18 04:58:27 +09:00
9 changed files with 135 additions and 178 deletions

View file

@ -1,28 +1,24 @@
set(TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/snprintf-correctness.cpp
${CMAKE_CURRENT_SOURCE_DIR}/strlcpy-correctness.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCTime.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCMkTemp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCExec.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCDirEnt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCInodeWatcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCSetjmp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCString.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestStackSmash.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestIo.cpp
TestIo.cpp
TestLibCExec.cpp
TestLibCDirEnt.cpp
TestLibCInodeWatcher.cpp
TestLibCMkTemp.cpp
TestLibCSetjmp.cpp
TestLibCString.cpp
TestLibCTime.cpp
TestMemmem.cpp
TestQsort.cpp
TestRealpath.cpp
TestScanf.cpp
TestSnprintf.cpp
TestStackSmash.cpp
TestStrlcpy.cpp
TestStrtodAccuracy.cpp
)
file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
list(REMOVE_ITEM CMD_SOURCES ${TEST_SOURCES})
set_source_files_properties(TestStrtodAccuracy.cpp PROPERTIES COMPILE_FLAGS "-fno-builtin-strtod")
# 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)
install(TARGETS ${CMD_NAME} RUNTIME DESTINATION usr/Tests/LibC)
endforeach()
foreach(source ${TEST_SOURCES})
serenity_test(${source} LibC)
foreach(source IN LISTS TEST_SOURCES)
serenity_test("${source}" LibC)
endforeach()

View file

@ -4,12 +4,10 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/Types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct TestCase {
const u8* haystack;
@ -32,20 +30,15 @@ const static TestCase g_test_cases[] = {
{ (const u8[64]) { 0, 1, 1, 2 }, 64u, (const u8[33]) { 1, 1 }, 2u, 1 },
};
int main()
TEST_CASE(memmem_search)
{
bool failed = false;
size_t i = 0;
for (const auto& test_case : g_test_cases) {
auto expected = test_case.matching_offset >= 0 ? test_case.haystack + test_case.matching_offset : nullptr;
auto result = memmem(test_case.haystack, test_case.haystack_length, test_case.needle, test_case.needle_length);
if (result != expected) {
failed = true;
fprintf(stderr, "Test %zu FAILED! expected %p, got %p\n", i, expected, result);
FAIL(String::formatted("Test {} FAILED! expected {:p}, got {:p}", i, expected, result));
}
++i;
}
printf(failed ? "FAIL\n" : "PASS\n");
return failed ? 1 : 0;
}

View file

@ -4,10 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/QuickSort.h>
#include <AK/Random.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <stdio.h>
#include <stdlib.h>
const size_t NUM_RUNS = 100;
@ -39,13 +41,13 @@ static int calc_payload_for_pos(size_t pos)
static void shuffle_vec(Vector<SortableObject>& test_objects)
{
for (size_t i = 0; i < test_objects.size() * 3; ++i) {
auto i1 = rand() % test_objects.size();
auto i2 = rand() % test_objects.size();
auto i1 = get_random_uniform(test_objects.size());
auto i2 = get_random_uniform(test_objects.size());
swap(test_objects[i1], test_objects[i2]);
}
}
int main()
TEST_CASE(quick_sort)
{
// Generate vector of SortableObjects in sorted order, with payloads determined by their sorted positions
Vector<SortableObject> test_objects;
@ -61,8 +63,7 @@ int main()
const auto& key1 = test_objects[i].m_key;
const auto& key2 = test_objects[i + 1].m_key;
if (key1 > key2) {
printf("\x1b[01;35mTests failed: saw key %d before key %d\n", key1, key2);
return 1;
FAIL(String::formatted("saw key {} before key {}\n", key1, key2));
}
}
// Check that the object's payloads have not been corrupted
@ -70,11 +71,8 @@ int main()
const auto expected = calc_payload_for_pos(i);
const auto payload = test_objects[i].m_payload;
if (payload != expected) {
printf("\x1b[01;35mTests failed: expected payload %d for pos %u, got payload %d\n", expected, i, payload);
return 1;
FAIL(String::formatted("Expected payload {} for pos {}, got payload {}", expected, i, payload));
}
}
}
printf("PASS\n");
return 0;
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2021, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static constexpr char TMPDIR_PATTERN[] = "/tmp/overlong_realpath_XXXXXX";
static constexpr char PATH_LOREM_250[] = "This-is-an-annoyingly-long-name-that-should-take-up-exactly-two-hundred-and-fifty-characters-and-is-surprisingly-difficult-to-fill-with-reasonably-meaningful-text-which-is-necessary-because-that-makes-it-easier-for-my-eyes-to-spot-any-corruption-fast";
static constexpr size_t ITERATION_DEPTH = 17;
static void check_result(const char* what, const String& expected, const char* actual)
{
if (expected != actual)
FAIL(String::formatted("Expected {} to be \"{}\" ({} characters)", what, actual, actual ? strlen(actual) : 0));
}
TEST_CASE(overlong_realpath)
{
// We want to construct a path that is over PATH_MAX characters long.
// This cannot be done in a single step.
// First, switch to a known environment:
char tmp_dir[] = "/tmp/overlong_realpath_XXXXXX";
errno = 0;
auto* new_dir = mkdtemp(tmp_dir);
VERIFY(new_dir != nullptr);
VERIFY(errno == 0);
errno = 0;
auto ret = chdir(tmp_dir);
VERIFY(ret >= 0);
VERIFY(errno == 0);
// Then, create a long path.
StringBuilder expected;
expected.append(tmp_dir);
// But first, demonstrate the functionality at a reasonable depth:
auto expected_str = expected.build();
check_result("getwd", expected_str, getwd(static_cast<char*>(calloc(1, PATH_MAX))));
check_result("getcwd", expected_str, getcwd(nullptr, 0));
check_result("realpath", expected_str, realpath(".", nullptr));
for (size_t i = 0; i < ITERATION_DEPTH; ++i) {
ret = mkdir(PATH_LOREM_250, S_IRWXU);
if (ret < 0) {
perror("mkdir iter");
FAIL(String::formatted("Unable to mkdir the overlong path fragment in iteration {}", i));
return;
}
expected.append('/');
expected.append(PATH_LOREM_250);
ret = chdir(PATH_LOREM_250);
if (ret < 0) {
perror("chdir iter");
FAIL(String::formatted("Unable to chdir to the overlong path fragment in iteration {}", i));
return;
}
}
outln("cwd should now be ridiculously large");
// Evaluate
expected_str = expected.build();
check_result("getwd", {}, getwd(static_cast<char*>(calloc(1, PATH_MAX))));
check_result("getcwd", expected_str, getcwd(nullptr, 0));
check_result("realpath", expected_str, realpath(".", nullptr));
VERIFY(strlen(PATH_LOREM_250) == 250);
VERIFY(strlen(TMPDIR_PATTERN) + ITERATION_DEPTH * (1 + strlen(PATH_LOREM_250)) == expected_str.length());
VERIFY(expected_str.length() > PATH_MAX);
}

View file

@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/Array.h>
#include <stdio.h>
#include <stdlib.h>
@ -233,13 +235,11 @@ static void do_one_test(const TestSuite& test)
else
printf(" overall FAIL\n");
g_any_failed = g_any_failed || !overall;
VERIFY(overall);
}
int main()
TEST_CASE(scanf)
{
for (auto& test : test_suites)
do_one_test(test);
return g_any_failed ? 1 : 0;
}

View file

@ -107,23 +107,6 @@ static bool test_single(const Testcase& testcase)
// Drop the NUL terminator added by the C++ compiler.
#define LITERAL(x) x, (sizeof(x) - 1)
//static Testcase TESTCASES[] = {
// // Golden path:
// // Hitting the border:
// // Too long:
// { LITERAL("Hello World!\0"), LITERAL("Hello Friend!"), LITERAL("Hello Friend\0") },
// { LITERAL("Hello World!\0"), LITERAL("This source is just *way* too long!"), LITERAL("This source \0") },
// { LITERAL("x"), LITERAL("This source is just *way* too long!"), LITERAL("\0") },
// // Other special cases:
// { LITERAL(""), LITERAL(""), LITERAL("") },
// { LITERAL(""), LITERAL("Empty test"), LITERAL("") },
// { LITERAL("x"), LITERAL(""), LITERAL("\0") },
// { LITERAL("xx"), LITERAL(""), LITERAL("\0x") },
// { LITERAL("xxx"), LITERAL(""), LITERAL("\0xx") },
//};
TEST_CASE(golden_path)
{
EXPECT(test_single({ LITERAL("Hello World!\0\0\0"), LITERAL("Hello Friend!"), LITERAL("Hello Friend!\0\0") }));

View file

@ -4,13 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <LibTest/TestCase.h>
#include <AK/Format.h>
#include <AK/String.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static constexpr char TEXT_ERROR[] = "\x1b[01;35m";
static constexpr char TEXT_WRONG[] = "\x1b[01;31m";
@ -291,7 +290,7 @@ static bool is_strtod_close(strtod_fn_t strtod_fn, const char* test_string, cons
bool error_cns = !actual_consume_possible;
bool wrong_cns = !error_cns && (actual_consume != expect_consume);
printf(" %s%s%s(%s%2u%s)",
out(" {}{}{}({}{:2}{})",
ofby1_hex ? TEXT_OFBY1 : wrong_hex ? TEXT_WRONG
: "",
actual_hex,
@ -315,8 +314,8 @@ static long long hex_to_ll(const char* hex)
} else if ('a' <= ch && ch <= 'f') {
digit = ch - 'a' + 10;
} else {
printf("\n!!! Encountered char %02x at %d.\n", ch, i);
assert(false);
FAIL(String::formatted("\n!!! Encountered char {:02x} at {}", ch, i));
return result;
}
result <<= 4;
result += digit;
@ -324,10 +323,10 @@ static long long hex_to_ll(const char* hex)
return result;
}
int main()
TEST_CASE(strtod_accuracy)
{
printf("Running %zu testcases...\n", NUM_TESTCASES);
printf("%3s(%-5s): %16s(%2s) %16s(%2s) %16s(%2s) %16s(%2s) %s\n", "num", "name", "correct", "cs", "builtin", "cs", "old_strtod", "cs", "new_strtod", "cs", "teststring");
outln("Running {} testcases...", NUM_TESTCASES);
outln("{:3}({:-5}): {:16}({:2}) {:16}({:2}) - {}", "num", "name", "correct", "cs", "strtod", "cs", "teststring");
int successes = 0;
int fails = 0;
@ -336,13 +335,12 @@ int main()
if (tc.should_consume == -1) {
tc.should_consume = strlen(tc.test_string);
}
printf("%3zu(%-5s):", i, tc.test_name);
printf(" %s(%2d)", tc.hex, tc.should_consume);
out("{:3}({:-5}): {}({:2})", i, tc.test_name, tc.hex, tc.should_consume);
long long expect_ll = hex_to_ll(tc.hex);
bool success = false;
success = is_strtod_close(strtod, tc.test_string, tc.hex, tc.should_consume, expect_ll);
printf(" from %s\n", tc.test_string);
outln(" from {}", tc.test_string);
if (success) {
successes += 1;
@ -350,12 +348,10 @@ int main()
fails += 1;
}
}
printf("Out of %zu tests, saw %d successes and %d fails.\n", NUM_TESTCASES, successes, fails);
outln("Out of {} tests, saw {} successes and {} fails.", NUM_TESTCASES, successes, fails);
if (fails != 0) {
printf("FAIL\n");
return 1;
FAIL(String::formatted("{} strtod tests failed", fails));
}
printf("PASS (with leniency up to %lld ULP from the exact solution.\n", LENIENCY);
return 0;
outln("PASS (with leniency up to {} ULP from the exact solution)", LENIENCY);
}

View file

@ -1,94 +0,0 @@
/*
* Copyright (c) 2021, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
// FIXME
static constexpr char TEXT_FAIL[] = "\x1b[01;31m";
static constexpr char TEXT_PASS[] = "\x1b[01;32m";
static constexpr char TEXT_RESET[] = "\x1b[0m";
static constexpr char TMPDIR_PATTERN[] = "/tmp/overlong_realpath_XXXXXX";
static constexpr char PATH_LOREM_250[] = "This-is-an-annoyingly-long-name-that-should-take-up-exactly-two-hundred-and-fifty-characters-and-is-surprisingly-difficult-to-fill-with-reasonably-meaningful-text-which-is-necessary-because-that-makes-it-easier-for-my-eyes-to-spot-any-corruption-fast";
static constexpr size_t ITERATION_DEPTH = 17;
static bool check_result(const char* what, const String& expected, const char* actual)
{
bool good = expected == actual;
printf("%s%s%s: %s = \"%s\" (%zu characters)\n", good ? TEXT_PASS : TEXT_FAIL, good ? "GOOD" : "FAIL", TEXT_RESET, what, actual, actual ? strlen(actual) : 0);
return good;
}
int main()
{
// We want to construct a path that is over PATH_MAX characters long.
// This cannot be done in a single step.
// First, switch to a known environment:
char* tmp_dir = strdup("/tmp/overlong_realpath_XXXXXX");
if (!mkdtemp(tmp_dir)) {
perror("mkdtmp");
return 1;
}
if (chdir(tmp_dir) < 0) {
perror("chdir tmpdir");
return 1;
}
// Then, create a long path.
StringBuilder expected;
expected.append(tmp_dir);
// But first, demonstrate the functionality at a reasonable depth:
bool all_good = true;
auto expected_str = expected.build();
all_good &= check_result("getwd", expected_str, getwd(static_cast<char*>(calloc(1, PATH_MAX))));
all_good &= check_result("getcwd", expected_str, getcwd(nullptr, 0));
all_good &= check_result("realpath", expected_str, realpath(".", nullptr));
for (size_t i = 0; i < ITERATION_DEPTH; ++i) {
if (mkdir(PATH_LOREM_250, 0700) < 0) {
perror("mkdir iter");
printf("%sFAILED%s in iteration %zu.\n", TEXT_FAIL, TEXT_RESET, i);
return 1;
}
expected.append('/');
expected.append(PATH_LOREM_250);
if (chdir(PATH_LOREM_250) < 0) {
perror("chdir iter");
printf("%sFAILED%s in iteration %zu.\n", TEXT_FAIL, TEXT_RESET, i);
return 1;
}
}
printf("cwd should now be ridiculously large.\n");
// Evaluate
expected_str = expected.build();
all_good &= check_result("getwd", {}, getwd(static_cast<char*>(calloc(1, PATH_MAX))));
all_good &= check_result("getcwd", expected_str, getcwd(nullptr, 0));
all_good &= check_result("realpath", expected_str, realpath(".", nullptr));
VERIFY(strlen(PATH_LOREM_250) == 250);
VERIFY(strlen(TMPDIR_PATTERN) + ITERATION_DEPTH * (1 + strlen(PATH_LOREM_250)) == expected_str.length());
VERIFY(expected_str.length() > PATH_MAX);
if (all_good) {
printf("Overall: %sPASS%s\n", TEXT_PASS, TEXT_RESET);
return 0;
} else {
printf("Overall: %sFAIL%s\n", TEXT_FAIL, TEXT_RESET);
return 2;
}
}