llvm-project/clang/unittests/Frontend/OutputStreamTest.cpp
Reid Kleckner db2315afa8
[clang] Merge gtest binaries into AllClangUnitTests (#134196)
This reduces the size of the clang/unittests build directory by 64% and
my overall build dir size by 5%. Static linking is the real driving
factor here, but even if the default build configuration used shared
libraries, I don't see why we should be building so many unit test
binaries.

To make the project more approachable for new contributors, I'm
attempting to make the build a bit less resource-intensive. Build
directory size is a common complaint, and this is low-hanging fruit.

I've noticed that incremental builds leave behind the old, stale gtest binaries, and lit will keep running them. This mostly doesn't matter unless they use shared libraries, which will eventually stop working after successive builds. You can clean up the old test binaries with this command in the build directory:
  $ find tools/clang/unittests/ -iname '*Tests' -type f | xargs rm

... or you can simply clean the build directory in a more holistic way.

---------

Co-authored-by: Petr Hosek <phosek@google.com>
2025-04-29 06:32:03 -07:00

119 lines
4.5 KiB
C++

//===- unittests/Frontend/OutputStreamTest.cpp --- FrontendAction tests --===//
//
// 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 "clang/Basic/LangStandard.h"
#include "clang/CodeGen/BackendUtil.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/FrontendTool/Utils.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
using namespace clang::frontend;
namespace {
TEST(FrontendOutputTests, TestOutputStream) {
llvm::InitializeAllTargetMCs();
auto Invocation = std::make_shared<CompilerInvocation>();
Invocation->getPreprocessorOpts().addRemappedFile(
"test.cc", MemoryBuffer::getMemBuffer("").release());
Invocation->getFrontendOpts().Inputs.push_back(
FrontendInputFile("test.cc", Language::CXX));
Invocation->getFrontendOpts().ProgramAction = EmitBC;
Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
CompilerInstance Compiler;
SmallVector<char, 256> IRBuffer;
std::unique_ptr<raw_pwrite_stream> IRStream(
new raw_svector_ostream(IRBuffer));
Compiler.setOutputStream(std::move(IRStream));
Compiler.setInvocation(std::move(Invocation));
Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem());
bool Success = ExecuteCompilerInvocation(&Compiler);
EXPECT_TRUE(Success);
EXPECT_TRUE(!IRBuffer.empty());
EXPECT_TRUE(StringRef(IRBuffer.data()).starts_with("BC"));
}
TEST(FrontendOutputTests, TestVerboseOutputStreamShared) {
llvm::InitializeAllTargetMCs();
auto Invocation = std::make_shared<CompilerInvocation>();
Invocation->getPreprocessorOpts().addRemappedFile(
"test.cc", MemoryBuffer::getMemBuffer("invalid").release());
Invocation->getFrontendOpts().Inputs.push_back(
FrontendInputFile("test.cc", Language::CXX));
Invocation->getFrontendOpts().ProgramAction = EmitBC;
Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
CompilerInstance Compiler;
std::string VerboseBuffer;
raw_string_ostream VerboseStream(VerboseBuffer);
Compiler.setOutputStream(std::make_unique<raw_null_ostream>());
Compiler.setInvocation(std::move(Invocation));
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
Compiler.createDiagnostics(
*llvm::vfs::getRealFileSystem(),
new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
Compiler.setVerboseOutputStream(VerboseStream);
bool Success = ExecuteCompilerInvocation(&Compiler);
EXPECT_FALSE(Success);
EXPECT_TRUE(!VerboseBuffer.empty());
EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
}
TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) {
std::string VerboseBuffer;
bool Success;
{
llvm::InitializeAllTargetMCs();
auto Invocation = std::make_shared<CompilerInvocation>();
Invocation->getPreprocessorOpts().addRemappedFile(
"test.cc", MemoryBuffer::getMemBuffer("invalid").release());
Invocation->getFrontendOpts().Inputs.push_back(
FrontendInputFile("test.cc", Language::CXX));
Invocation->getFrontendOpts().ProgramAction = EmitBC;
Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
CompilerInstance Compiler;
std::unique_ptr<raw_ostream> VerboseStream =
std::make_unique<raw_string_ostream>(VerboseBuffer);
Compiler.setOutputStream(std::make_unique<raw_null_ostream>());
Compiler.setInvocation(std::move(Invocation));
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
Compiler.createDiagnostics(
*llvm::vfs::getRealFileSystem(),
new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
Compiler.setVerboseOutputStream(std::move(VerboseStream));
Success = ExecuteCompilerInvocation(&Compiler);
}
EXPECT_FALSE(Success);
EXPECT_TRUE(!VerboseBuffer.empty());
EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
}
TEST(FrontendOutputTests, TestVerboseOutputStreamOwnedNotLeaked) {
CompilerInstance Compiler;
Compiler.setVerboseOutputStream(std::make_unique<raw_null_ostream>());
// Trust leak sanitizer bots to catch a leak here.
Compiler.setVerboseOutputStream(llvm::nulls());
}
} // anonymous namespace