1//===- unittest/Format/FormatTestBase.h - Formatting test base classs -----===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the base class for format tests.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
14#define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H
15
16#include "FormatTestUtils.h"
17
18#include "clang/Format/Format.h"
19#include "llvm/Support/Debug.h"
20#include "gtest/gtest.h"
21
22namespace clang {
23namespace format {
24namespace test {
25
26#define DEBUG_TYPE "format-test-base"
27
28class FormatTestBase : public ::testing::Test {
29protected:
30 enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck };
31
32 virtual FormatStyle getDefaultStyle() const { return getLLVMStyle(); }
33
34 virtual std::string messUp(llvm::StringRef Code) const {
35 return test::messUp(Code);
36 }
37
38 std::string format(llvm::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");
44 auto NonEmptyRanges =
45 !Ranges.empty()
46 ? Ranges
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(Style: UsedStyle, Code, Ranges: NonEmptyRanges, FileName: "<stdin>", Status: &Status);
52 if (CheckComplete != SC_DoNotCheck) {
53 bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
54 EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
55 << Code << "\n\n";
56 }
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");
61 return *Result;
62 }
63
64 FormatStyle getStyleWithColumns(FormatStyle Style, unsigned ColumnLimit) {
65 Style.ColumnLimit = ColumnLimit;
66 return Style;
67 }
68
69 FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
70 return getStyleWithColumns(Style: getLLVMStyle(), ColumnLimit);
71 }
72
73 FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) {
74 return getStyleWithColumns(Style: getGoogleStyle(), ColumnLimit);
75 }
76
77 FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) {
78 FormatStyle Style = getGoogleStyle(Language: FormatStyle::FormatStyle::LK_TextProto);
79 Style.ColumnLimit = ColumnLimit;
80 return Style;
81 }
82
83 bool _verifyFormat(const char *File, int Line, llvm::StringRef Expected,
84 llvm::StringRef Code,
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, CheckComplete: SC_ExpectComplete, Ranges)};
90 EXPECT_EQ(ExpectedCode, FormattedCode);
91 if (ExpectedCode != FormattedCode)
92 return false;
93 if (Expected != Code) {
94 FormattedCode = format(Code: Expected, Style, CheckComplete: SC_ExpectComplete, Ranges);
95 EXPECT_EQ(ExpectedCode, FormattedCode) << "Expected code is not stable";
96 if (ExpectedCode != FormattedCode)
97 return false;
98 }
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, Style: ObjCStyle, CheckComplete: SC_ExpectComplete, Ranges);
107 EXPECT_EQ(ExpectedCode, FormattedCode);
108 if (ExpectedCode != FormattedCode)
109 return false;
110 }
111 return true;
112 }
113
114 void _verifyFormat(const char *File, int Line, llvm::StringRef Code,
115 const std::optional<FormatStyle> &Style = {}) {
116 if (!_verifyFormat(File, Line, Expected: Code, Code, Style))
117 return;
118 if (const auto MessedUpCode{messUp(Code)}; MessedUpCode != Code)
119 _verifyFormat(File, Line, Expected: Code, Code: MessedUpCode, Style);
120 }
121
122 void _verifyIncompleteFormat(const char *File, int Line, llvm::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));
126 }
127
128 void
129 _verifyIndependentOfContext(const char *File, int Line, llvm::StringRef Text,
130 const std::optional<FormatStyle> &Style = {}) {
131 _verifyFormat(File, Line, Code: Text, Style);
132 _verifyFormat(File, Line, Code: llvm::Twine("void f() { " + Text + " }").str(),
133 Style);
134 }
135
136 void _verifyNoChange(const char *File, int Line, llvm::StringRef Code,
137 const std::optional<FormatStyle> &Style = {}) {
138 _verifyFormat(File, Line, Expected: Code, Code, Style);
139 }
140
141 /// \brief Verify that clang-format does not crash on the given input.
142 void verifyNoCrash(llvm::StringRef Code,
143 const std::optional<FormatStyle> &Style = {}) {
144 format(Code, Style, CheckComplete: SC_DoNotCheck);
145 }
146
147 int ReplacementCount;
148};
149
150#undef DEBUG_TYPE
151
152#define verifyIndependentOfContext(...) \
153 _verifyIndependentOfContext(__FILE__, __LINE__, __VA_ARGS__)
154#define verifyIncompleteFormat(...) \
155 _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__)
156#define verifyNoChange(...) _verifyNoChange(__FILE__, __LINE__, __VA_ARGS__)
157#define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
158#define verifyGoogleFormat(Code) verifyFormat(Code, getGoogleStyle())
159
160} // namespace test
161} // namespace format
162} // namespace clang
163
164#endif
165

source code of clang/unittests/Format/FormatTestBase.h