48 changes: 45 additions & 3 deletions libc/test/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ add_libc_unittest(
libc.src.stdio.snprintf
)

list(APPEND fprintf_test_deps
libc.src.stdio.fprintf
)
if(LLVM_LIBC_FULL_BUILD)
# In fullbuild mode, fprintf's tests use the internal FILE for other functions.
list(APPEND fprintf_test_deps
Expand All @@ -158,6 +155,7 @@ add_libc_unittest(
SRCS
fprintf_test.cpp
DEPENDS
libc.src.stdio.fprintf
${fprintf_test_deps}
COMPILE_OPTIONS
${fprintf_test_copts}
Expand All @@ -173,6 +171,50 @@ add_libc_unittest(
libc.src.stdio.printf
)

add_fp_unittest(
vsprintf_test
UNIT_TEST_ONLY
SUITE
libc_stdio_unittests
SRCS
vsprintf_test.cpp
DEPENDS
libc.src.stdio.vsprintf
)

add_libc_unittest(
vsnprintf_test
SUITE
libc_stdio_unittests
SRCS
vsnprintf_test.cpp
DEPENDS
libc.src.stdio.vsnprintf
)

add_libc_unittest(
vfprintf_test
SUITE
libc_stdio_unittests
SRCS
vfprintf_test.cpp
DEPENDS
libc.src.stdio.vfprintf
${fprintf_test_deps}
COMPILE_OPTIONS
${fprintf_test_copts}
)

add_libc_unittest(
vprintf_test
SUITE
libc_stdio_unittests
SRCS
vprintf_test.cpp
DEPENDS
libc.src.stdio.vprintf
)

add_libc_unittest(
fscanf_test
SUITE
Expand Down
97 changes: 97 additions & 0 deletions libc/test/src/stdio/vfprintf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===-- Unittests for vfprintf --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// These tests are copies of the non-v variants of the printf functions. This is
// because these functions are identical in every way except for how the varargs
// are passed.

#ifndef LIBC_COPT_PRINTF_USE_SYSTEM_FILE
#include "src/stdio/fclose.h"
#include "src/stdio/ferror.h"
#include "src/stdio/fopen.h"
#include "src/stdio/fread.h"
#endif // LIBC_COPT_PRINTF_USE_SYSTEM_FILE

#include "src/stdio/vfprintf.h"

#include "test/UnitTest/Test.h"

#include <stdio.h>

namespace printf_test {
#ifndef LIBC_COPT_PRINTF_USE_SYSTEM_FILE
using __llvm_libc::fclose;
using __llvm_libc::ferror;
using __llvm_libc::fopen;
using __llvm_libc::fread;
#else // defined(LIBC_COPT_PRINTF_USE_SYSTEM_FILE)
using ::fclose;
using ::ferror;
using ::fopen;
using ::fread;
#endif // LIBC_COPT_PRINTF_USE_SYSTEM_FILE
} // namespace printf_test

int call_vfprintf(::FILE *__restrict stream, const char *__restrict format,
...) {
va_list vlist;
va_start(vlist, format);
int ret = __llvm_libc::vfprintf(stream, format, vlist);
va_end(vlist);
return ret;
}

TEST(LlvmLibcVFPrintfTest, WriteToFile) {
const char *FILENAME = "fprintf_output.test";
auto FILE_PATH = libc_make_test_file_path(FILENAME);

::FILE *file = printf_test::fopen(FILE_PATH, "w");
ASSERT_FALSE(file == nullptr);

int written;

constexpr char simple[] = "A simple string with no conversions.\n";
written = call_vfprintf(file, simple);
EXPECT_EQ(written, 37);

constexpr char numbers[] = "1234567890\n";
written = call_vfprintf(file, "%s", numbers);
EXPECT_EQ(written, 11);

constexpr char format_more[] = "%s and more\n";
constexpr char short_numbers[] = "1234";
written = call_vfprintf(file, format_more, short_numbers);
EXPECT_EQ(written, 14);

ASSERT_EQ(0, printf_test::fclose(file));

file = printf_test::fopen(FILE_PATH, "r");
ASSERT_FALSE(file == nullptr);

char data[50];
ASSERT_EQ(printf_test::fread(data, 1, sizeof(simple) - 1, file),
sizeof(simple) - 1);
data[sizeof(simple) - 1] = '\0';
ASSERT_STREQ(data, simple);
ASSERT_EQ(printf_test::fread(data, 1, sizeof(numbers) - 1, file),
sizeof(numbers) - 1);
data[sizeof(numbers) - 1] = '\0';
ASSERT_STREQ(data, numbers);
ASSERT_EQ(printf_test::fread(
data, 1, sizeof(format_more) + sizeof(short_numbers) - 4, file),
sizeof(format_more) + sizeof(short_numbers) - 4);
data[sizeof(format_more) + sizeof(short_numbers) - 4] = '\0';
ASSERT_STREQ(data, "1234 and more\n");

ASSERT_EQ(printf_test::ferror(file), 0);

written = call_vfprintf(file, "Writing to a read only file should fail.");
EXPECT_LT(written, 0);

ASSERT_EQ(printf_test::fclose(file), 0);
}
41 changes: 41 additions & 0 deletions libc/test/src/stdio/vprintf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===-- Unittests for vprintf --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// These tests are copies of the non-v variants of the printf functions. This is
// because these functions are identical in every way except for how the varargs
// are passed.

#include "src/stdio/vprintf.h"

#include "test/UnitTest/Test.h"

int call_vprintf(const char *__restrict format, ...) {
va_list vlist;
va_start(vlist, format);
int ret = __llvm_libc::vprintf(format, vlist);
va_end(vlist);
return ret;
}

TEST(LlvmLibcVPrintfTest, PrintOut) {
int written;

constexpr char simple[] = "A simple string with no conversions.\n";
written = call_vprintf(simple);
EXPECT_EQ(written, static_cast<int>(sizeof(simple) - 1));

constexpr char numbers[] = "1234567890\n";
written = call_vprintf("%s", numbers);
EXPECT_EQ(written, static_cast<int>(sizeof(numbers) - 1));

constexpr char format_more[] = "%s and more\n";
constexpr char short_numbers[] = "1234";
written = call_vprintf(format_more, short_numbers);
EXPECT_EQ(written,
static_cast<int>(sizeof(format_more) + sizeof(short_numbers) - 4));
}
69 changes: 69 additions & 0 deletions libc/test/src/stdio/vsnprintf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//===-- Unittests for snprintf --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// These tests are copies of the non-v variants of the printf functions. This is
// because these functions are identical in every way except for how the varargs
// are passed.

#include "src/stdio/vsnprintf.h"

#include "test/UnitTest/Test.h"

int call_vsnprintf(char *__restrict buffer, size_t buffsz,
const char *__restrict format, ...) {
va_list vlist;
va_start(vlist, format);
int ret = __llvm_libc::vsnprintf(buffer, buffsz, format, vlist);
va_end(vlist);
return ret;
}

// The sprintf test cases cover testing the shared printf functionality, so
// these tests will focus on snprintf exclusive features.

TEST(LlvmLibcVSNPrintfTest, CutOff) {
char buff[100];
int written;

written = call_vsnprintf(buff, 16, "A simple string with no conversions.");
EXPECT_EQ(written, 36);
ASSERT_STREQ(buff, "A simple string");

written = call_vsnprintf(buff, 5, "%s", "1234567890");
EXPECT_EQ(written, 10);
ASSERT_STREQ(buff, "1234");

written = call_vsnprintf(buff, 67, "%-101c", 'a');
EXPECT_EQ(written, 101);
ASSERT_STREQ(buff, "a "
" " // Each of these is 8 spaces, and there are 8.
" " // In total there are 65 spaces
" " // 'a' + 65 spaces + '\0' = 67
" "
" "
" "
" "
" ");

// passing null as the output pointer is allowed as long as buffsz is 0.
written = call_vsnprintf(nullptr, 0, "%s and more", "1234567890");
EXPECT_EQ(written, 19);
}

TEST(LlvmLibcVSNPrintfTest, NoCutOff) {
char buff[64];
int written;

written = call_vsnprintf(buff, 37, "A simple string with no conversions.");
EXPECT_EQ(written, 36);
ASSERT_STREQ(buff, "A simple string with no conversions.");

written = call_vsnprintf(buff, 20, "%s", "1234567890");
EXPECT_EQ(written, 10);
ASSERT_STREQ(buff, "1234567890");
}
66 changes: 66 additions & 0 deletions libc/test/src/stdio/vsprintf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===-- Unittests for vsprintf --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// These tests are shortened copies of the non-v variants of the printf
// functions. This is because these functions are identical in every way except
// for how the varargs are passed.

#include "src/stdio/vsprintf.h"

#include "test/UnitTest/Test.h"

int call_vsprintf(char *__restrict buffer, const char *__restrict format, ...) {
va_list vlist;
va_start(vlist, format);
int ret = __llvm_libc::vsprintf(buffer, format, vlist);
va_end(vlist);
return ret;
}

TEST(LlvmLibcVSPrintfTest, SimpleNoConv) {
char buff[64];
int written;

written = call_vsprintf(buff, "A simple string with no conversions.");
EXPECT_EQ(written, 36);
ASSERT_STREQ(buff, "A simple string with no conversions.");
}

TEST(LlvmLibcVSPrintfTest, PercentConv) {
char buff[64];
int written;

written = call_vsprintf(buff, "%%");
EXPECT_EQ(written, 1);
ASSERT_STREQ(buff, "%");

written = call_vsprintf(buff, "abc %% def");
EXPECT_EQ(written, 9);
ASSERT_STREQ(buff, "abc % def");

written = call_vsprintf(buff, "%%%%%%");
EXPECT_EQ(written, 3);
ASSERT_STREQ(buff, "%%%");
}

TEST(LlvmLibcVSPrintfTest, CharConv) {
char buff[64];
int written;

written = call_vsprintf(buff, "%c", 'a');
EXPECT_EQ(written, 1);
ASSERT_STREQ(buff, "a");

written = call_vsprintf(buff, "%3c %-3c", '1', '2');
EXPECT_EQ(written, 7);
ASSERT_STREQ(buff, " 1 2 ");

written = call_vsprintf(buff, "%*c", 2, '3');
EXPECT_EQ(written, 2);
ASSERT_STREQ(buff, " 3");
}
73 changes: 63 additions & 10 deletions utils/bazel/llvm-project-overlay/libc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2642,6 +2642,19 @@ libc_support_library(
],
)

libc_support_library(
name = "vfprintf_internal",
hdrs = ["src/stdio/printf_core/vfprintf_internal.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":__support_file_file",
":__support_macros_attributes",
":printf_main",
":printf_writer",
],
)

libc_function(
name = "sprintf",
srcs = ["src/stdio/sprintf.cpp"],
Expand Down Expand Up @@ -2669,23 +2682,63 @@ libc_function(
],
)

libc_support_library(
name = "vfprintf_internal",
hdrs = ["src/stdio/printf_core/vfprintf_internal.h"],
libc_function(
name = "printf",
srcs = ["src/stdio/printf.cpp"],
hdrs = ["src/stdio/printf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":__support_file_file",
":__support_macros_attributes",
":errno",
":vfprintf_internal",
],
)

libc_function(
name = "fprintf",
srcs = ["src/stdio/fprintf.cpp"],
hdrs = ["src/stdio/fprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":__support_file_file",
":errno",
":vfprintf_internal",
],
)

libc_function(
name = "vsprintf",
srcs = ["src/stdio/vsprintf.cpp"],
hdrs = ["src/stdio/vsprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":__support_cpp_limits",
":errno",
":printf_main",
":printf_writer",
],
)

libc_function(
name = "printf",
srcs = ["src/stdio/printf.cpp"],
hdrs = ["src/stdio/printf.h"],
name = "vsnprintf",
srcs = ["src/stdio/vsnprintf.cpp"],
hdrs = ["src/stdio/vsnprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
":errno",
":printf_main",
":printf_writer",
],
)

libc_function(
name = "vprintf",
srcs = ["src/stdio/vprintf.cpp"],
hdrs = ["src/stdio/vprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
Expand All @@ -2696,9 +2749,9 @@ libc_function(
)

libc_function(
name = "fprintf",
srcs = ["src/stdio/fprintf.cpp"],
hdrs = ["src/stdio/fprintf.h"],
name = "vfprintf",
srcs = ["src/stdio/vfprintf.cpp"],
hdrs = ["src/stdio/vfprintf.h"],
defines = PRINTF_COPTS,
deps = [
":__support_arg_list",
Expand Down
32 changes: 32 additions & 0 deletions utils/bazel/llvm-project-overlay/libc/test/src/stdio/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,35 @@ libc_test(
"//libc:fprintf",
],
)

libc_test(
name = "vsprintf_test",
srcs = ["vsprintf_test.cpp"],
libc_function_deps = [
"//libc:vsprintf",
],
)

libc_test(
name = "vsnprintf_test",
srcs = ["vsnprintf_test.cpp"],
libc_function_deps = [
"//libc:vsnprintf",
],
)

libc_test(
name = "vprintf_test",
srcs = ["vprintf_test.cpp"],
libc_function_deps = [
"//libc:vprintf",
],
)

libc_test(
name = "vfprintf_test",
srcs = ["vfprintf_test.cpp"],
libc_function_deps = [
"//libc:vfprintf",
],
)