Skip to content

Commit

Permalink
[libc] add sprintf size comparison
Browse files Browse the repository at this point in the history
To accurately measure the size of sprintf in a finished binary, the
easiest method is to simply build a binary with and without sprintf.
This patch adds an integration test that can be built with and without
sprintf, as well as targets to build it.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D131735
  • Loading branch information
michaelrj-google committed Aug 12, 2022
1 parent 76b1e83 commit 0e27dfd
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
5 changes: 3 additions & 2 deletions libc/cmake/modules/LLVMLibCTestRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ endfunction(add_libc_fuzzer)
# DEPENDS <list of entrypoint or other object targets>
# ARGS <list of command line arguments to be passed to the test>
# ENV <list of environment variables to set before running the test>
# COMPILE_OPTIONS <list of special compile options for this target>
# )
#
# The loader target should provide a property named LOADER_OBJECT which is
Expand All @@ -404,7 +405,7 @@ function(add_integration_test test_name)
"INTEGRATION_TEST"
"" # No optional arguments
"SUITE;LOADER" # Single value arguments
"SRCS;HDRS;DEPENDS;ARGS;ENV" # Multi-value arguments
"SRCS;HDRS;DEPENDS;ARGS;ENV;COMPILE_OPTIONS" # Multi-value arguments
${ARGN}
)

Expand Down Expand Up @@ -522,7 +523,7 @@ function(add_integration_test test_name)
${LIBC_BUILD_DIR}
${LIBC_BUILD_DIR}/include
)
target_compile_options(${fq_target_name} PRIVATE -ffreestanding)
target_compile_options(${fq_target_name} PRIVATE -ffreestanding ${INTEGRATION_TEST_COMPILE_OPTIONS})
# We set a number of link options to prevent picking up system libc binaries.
# Also, we restrict the integration tests to fully static executables. The
# rtlib is set to compiler-rt to make the compiler drivers pick up the compiler
Expand Down
1 change: 1 addition & 0 deletions libc/test/integration/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_subdirectory(__support)
add_subdirectory(pthread)
add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(threads)
39 changes: 39 additions & 0 deletions libc/test/integration/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
add_custom_target(stdio-integration-tests)
add_dependencies(libc-integration-tests stdio-integration-tests)

# These tests are not for correctness testing, but are instead a convenient way
# to generate hermetic binaries for comparitive binary size testing.
add_integration_test(
sprintf_size_test
SUITE
stdio-integration-tests
SRCS
sprintf_size_test.cpp
LOADER
libc.loader.linux.crt1
DEPENDS
libc.src.stdio.sprintf
ARGS
"%s %c %d"
"First arg"
"a"
"0"
)

add_integration_test(
sprintf_size_test_no_sprintf
SUITE
stdio-integration-tests
SRCS
sprintf_size_test.cpp
LOADER
libc.loader.linux.crt1
ARGS
"%s %c %d"
"First arg"
"a"
"0"
COMPILE_OPTIONS
-DINTEGRATION_DISABLE_PRINTF
)

60 changes: 60 additions & 0 deletions libc/test/integration/src/stdio/sprintf_size_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===-- Unittests for getenv ----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include <stddef.h>

#ifndef INTEGRATION_DISABLE_PRINTF
#include "src/stdio/sprintf.h"
#endif

#include "utils/IntegrationTest/test.h"

static bool my_streq(const char *lhs, const char *rhs) {
if (lhs == rhs)
return true;
if (((lhs == static_cast<char *>(nullptr)) &&
(rhs != static_cast<char *>(nullptr))) ||
((lhs != static_cast<char *>(nullptr)) &&
(rhs == static_cast<char *>(nullptr)))) {
return false;
}
const char *l, *r;
for (l = lhs, r = rhs; *l != '\0' && *r != '\0'; ++l, ++r)
if (*l != *r)
return false;

return *l == '\0' && *r == '\0';
}

static int my_strlen(const char *str) {
const char *other = str;
while (*other)
++other;
return static_cast<int>(other - str);
}

TEST_MAIN(int argc, char **argv, char **envp) {
ASSERT_EQ(argc, 5);
ASSERT_TRUE(my_streq(argv[1], "%s %c %d"));
ASSERT_EQ(my_strlen(argv[1]), 8);
ASSERT_TRUE(my_streq(argv[2], "First arg"));
ASSERT_EQ(my_strlen(argv[2]), 9);
ASSERT_TRUE(my_streq(argv[3], "a"));
ASSERT_EQ(my_strlen(argv[3]), 1);
ASSERT_TRUE(my_streq(argv[4], "0"));
ASSERT_EQ(my_strlen(argv[4]), 1);

#ifndef INTEGRATION_DISABLE_PRINTF
char buf[100];
ASSERT_EQ(__llvm_libc::sprintf(buf, argv[1], argv[2], argv[3][0], argv[4][0]),
14);
ASSERT_TRUE(my_streq(buf, "First arg a 48"));
#endif

return 0;
}

0 comments on commit 0e27dfd

Please sign in to comment.