1 //===- unittest/Format/FormatTestBase.h - Formatting test base classs -----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the base class for format tests.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
14 #define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
16 #include "FormatTestUtils.h"
18 #include "clang/Format/Format.h"
19 #include "llvm/Support/Debug.h"
20 #include "gtest/gtest.h"
26 #define DEBUG_TYPE "format-test-base"
28 class FormatTestBase
: public testing::Test
{
30 enum StatusCheck
{ SC_ExpectComplete
, SC_ExpectIncomplete
, SC_DoNotCheck
};
32 virtual FormatStyle
getDefaultStyle() const { return getLLVMStyle(); }
34 virtual std::string
messUp(StringRef Code
) const {
35 return test::messUp(Code
);
38 std::string
format(StringRef Code
,
39 const std::optional
<FormatStyle
> &Style
= {},
40 StatusCheck CheckComplete
= SC_ExpectComplete
,
41 const std::vector
<tooling::Range
> &Ranges
= {}) {
42 LLVM_DEBUG(llvm::errs() << "---\n");
43 LLVM_DEBUG(llvm::errs() << Code
<< "\n\n");
47 : std::vector
<tooling::Range
>{1, tooling::Range(0, Code
.size())};
48 auto UsedStyle
= Style
? Style
.value() : getDefaultStyle();
49 FormattingAttemptStatus Status
;
50 tooling::Replacements Replaces
=
51 reformat(UsedStyle
, Code
, NonEmptyRanges
, "<stdin>", &Status
);
52 if (CheckComplete
!= SC_DoNotCheck
) {
53 bool ExpectedCompleteFormat
= CheckComplete
== SC_ExpectComplete
;
54 EXPECT_EQ(ExpectedCompleteFormat
, Status
.FormatComplete
)
57 ReplacementCount
= Replaces
.size();
58 auto Result
= applyAllReplacements(Code
, Replaces
);
59 EXPECT_TRUE(static_cast<bool>(Result
));
60 LLVM_DEBUG(llvm::errs() << "\n" << *Result
<< "\n\n");
64 FormatStyle
getStyleWithColumns(FormatStyle Style
,
65 unsigned ColumnLimit
) const {
66 Style
.ColumnLimit
= ColumnLimit
;
70 FormatStyle
getLLVMStyleWithColumns(unsigned ColumnLimit
) const {
71 return getStyleWithColumns(getLLVMStyle(), ColumnLimit
);
74 FormatStyle
getGoogleStyleWithColumns(unsigned ColumnLimit
) const {
75 return getStyleWithColumns(getGoogleStyle(), ColumnLimit
);
78 FormatStyle
getTextProtoStyleWithColumns(unsigned ColumnLimit
) const {
79 return getStyleWithColumns(getGoogleStyle(FormatStyle::LK_TextProto
),
83 bool _verifyFormat(const char *File
, int Line
, StringRef Expected
,
85 const std::optional
<FormatStyle
> &Style
= {},
86 const std::vector
<tooling::Range
> &Ranges
= {}) {
87 testing::ScopedTrace
t(File
, Line
, testing::Message() << Code
.str());
88 const auto ExpectedCode
{Expected
.str()};
89 auto FormattedCode
{format(Code
, Style
, SC_ExpectComplete
, Ranges
)};
90 EXPECT_EQ(ExpectedCode
, FormattedCode
);
91 if (ExpectedCode
!= FormattedCode
)
93 if (Expected
!= Code
) {
94 FormattedCode
= format(Expected
, Style
, SC_ExpectComplete
, Ranges
);
95 EXPECT_EQ(ExpectedCode
, FormattedCode
) << "Expected code is not stable";
96 if (ExpectedCode
!= FormattedCode
)
99 auto UsedStyle
= Style
? Style
.value() : getDefaultStyle();
100 if (UsedStyle
.Language
== FormatStyle::LK_Cpp
) {
101 // Objective-C++ is a superset of C++, so everything checked for C++
102 // needs to be checked for Objective-C++ as well.
103 FormatStyle ObjCStyle
= UsedStyle
;
104 ObjCStyle
.Language
= FormatStyle::LK_ObjC
;
105 // FIXME: Additional messUp is superfluous.
106 FormattedCode
= format(Code
, ObjCStyle
, SC_ExpectComplete
, Ranges
);
107 EXPECT_EQ(ExpectedCode
, FormattedCode
);
108 if (ExpectedCode
!= FormattedCode
)
114 void _verifyFormat(const char *File
, int Line
, StringRef Code
,
115 const std::optional
<FormatStyle
> &Style
= {}) {
116 if (!_verifyFormat(File
, Line
, Code
, Code
, Style
))
118 if (const auto MessedUpCode
{messUp(Code
)}; MessedUpCode
!= Code
)
119 _verifyFormat(File
, Line
, Code
, MessedUpCode
, Style
);
122 void _verifyIncompleteFormat(const char *File
, int Line
, StringRef Code
,
123 const std::optional
<FormatStyle
> &Style
= {}) {
124 testing::ScopedTrace
t(File
, Line
, testing::Message() << Code
.str());
125 EXPECT_EQ(Code
.str(), format(messUp(Code
), Style
, SC_ExpectIncomplete
));
129 _verifyIndependentOfContext(const char *File
, int Line
, StringRef Text
,
130 const std::optional
<FormatStyle
> &Style
= {}) {
131 _verifyFormat(File
, Line
, Text
, Style
);
132 _verifyFormat(File
, Line
, Twine("void f() { " + Text
+ " }").str(), Style
);
135 void _verifyNoChange(const char *File
, int Line
, StringRef Code
,
136 const std::optional
<FormatStyle
> &Style
= {}) {
137 _verifyFormat(File
, Line
, Code
, Code
, Style
);
140 /// \brief Verify that clang-format does not crash on the given input.
141 void verifyNoCrash(StringRef Code
,
142 const std::optional
<FormatStyle
> &Style
= {}) {
143 format(Code
, Style
, SC_DoNotCheck
);
146 int ReplacementCount
;
151 #define verifyIndependentOfContext(...) \
152 _verifyIndependentOfContext(__FILE__, __LINE__, __VA_ARGS__)
153 #define verifyIncompleteFormat(...) \
154 _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__)
155 #define verifyNoChange(...) _verifyNoChange(__FILE__, __LINE__, __VA_ARGS__)
156 #define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
157 #define verifyGoogleFormat(Code) verifyFormat(Code, getGoogleStyle())
160 } // namespace format