1f8d10d5aSManuel Klimek //===- unittest/Format/FormatTestBase.h - Formatting test base classs -----===// 2f8d10d5aSManuel Klimek // 3f8d10d5aSManuel Klimek // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f8d10d5aSManuel Klimek // See https://llvm.org/LICENSE.txt for license information. 5f8d10d5aSManuel Klimek // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f8d10d5aSManuel Klimek // 7f8d10d5aSManuel Klimek //===----------------------------------------------------------------------===// 8f8d10d5aSManuel Klimek // 9f8d10d5aSManuel Klimek // This file defines the base class for format tests. 10f8d10d5aSManuel Klimek // 11f8d10d5aSManuel Klimek //===----------------------------------------------------------------------===// 12f8d10d5aSManuel Klimek 13f8d10d5aSManuel Klimek #ifndef LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H 14f8d10d5aSManuel Klimek #define LLVM_CLANG_UNITTESTS_FORMAT_FORMATTESTBASE_H 15f8d10d5aSManuel Klimek 16f8d10d5aSManuel Klimek #include "FormatTestUtils.h" 17f8d10d5aSManuel Klimek 18f8d10d5aSManuel Klimek #include "clang/Format/Format.h" 19f8d10d5aSManuel Klimek #include "llvm/Support/Debug.h" 20f8d10d5aSManuel Klimek #include "gtest/gtest.h" 21f8d10d5aSManuel Klimek 22f8d10d5aSManuel Klimek namespace clang { 23f8d10d5aSManuel Klimek namespace format { 24f8d10d5aSManuel Klimek namespace test { 25f8d10d5aSManuel Klimek 26f8d10d5aSManuel Klimek #define DEBUG_TYPE "format-test-base" 27f8d10d5aSManuel Klimek 281c58208dSOwen Pan class FormatTestBase : public testing::Test { 29f8d10d5aSManuel Klimek protected: 30f8d10d5aSManuel Klimek enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete, SC_DoNotCheck }; 31f8d10d5aSManuel Klimek 32f8d10d5aSManuel Klimek virtual FormatStyle getDefaultStyle() const { return getLLVMStyle(); } 33f8d10d5aSManuel Klimek 341c58208dSOwen Pan virtual std::string messUp(StringRef Code) const { 356cef3254Ssstwcw return test::messUp(Code); 366cef3254Ssstwcw } 376cef3254Ssstwcw 381c58208dSOwen Pan std::string format(StringRef Code, 39f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}, 40f8d10d5aSManuel Klimek StatusCheck CheckComplete = SC_ExpectComplete, 41f8d10d5aSManuel Klimek const std::vector<tooling::Range> &Ranges = {}) { 42f8d10d5aSManuel Klimek LLVM_DEBUG(llvm::errs() << "---\n"); 43f8d10d5aSManuel Klimek LLVM_DEBUG(llvm::errs() << Code << "\n\n"); 44f8d10d5aSManuel Klimek auto NonEmptyRanges = 45f8d10d5aSManuel Klimek !Ranges.empty() 46f8d10d5aSManuel Klimek ? Ranges 47f8d10d5aSManuel Klimek : std::vector<tooling::Range>{1, tooling::Range(0, Code.size())}; 48f8d10d5aSManuel Klimek auto UsedStyle = Style ? Style.value() : getDefaultStyle(); 49f8d10d5aSManuel Klimek FormattingAttemptStatus Status; 50f8d10d5aSManuel Klimek tooling::Replacements Replaces = 51f8d10d5aSManuel Klimek reformat(UsedStyle, Code, NonEmptyRanges, "<stdin>", &Status); 52f8d10d5aSManuel Klimek if (CheckComplete != SC_DoNotCheck) { 53f8d10d5aSManuel Klimek bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete; 54f8d10d5aSManuel Klimek EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete) 55f8d10d5aSManuel Klimek << Code << "\n\n"; 56f8d10d5aSManuel Klimek } 57f8d10d5aSManuel Klimek ReplacementCount = Replaces.size(); 58f8d10d5aSManuel Klimek auto Result = applyAllReplacements(Code, Replaces); 59f8d10d5aSManuel Klimek EXPECT_TRUE(static_cast<bool>(Result)); 60f8d10d5aSManuel Klimek LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); 61f8d10d5aSManuel Klimek return *Result; 62f8d10d5aSManuel Klimek } 63f8d10d5aSManuel Klimek 64*ddbe6c41SOwen Pan FormatStyle getStyleWithColumns(FormatStyle Style, 65*ddbe6c41SOwen Pan unsigned ColumnLimit) const { 66f8d10d5aSManuel Klimek Style.ColumnLimit = ColumnLimit; 67f8d10d5aSManuel Klimek return Style; 68f8d10d5aSManuel Klimek } 69f8d10d5aSManuel Klimek 70*ddbe6c41SOwen Pan FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) const { 71f8d10d5aSManuel Klimek return getStyleWithColumns(getLLVMStyle(), ColumnLimit); 72f8d10d5aSManuel Klimek } 73f8d10d5aSManuel Klimek 74*ddbe6c41SOwen Pan FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) const { 75f8d10d5aSManuel Klimek return getStyleWithColumns(getGoogleStyle(), ColumnLimit); 76f8d10d5aSManuel Klimek } 77f8d10d5aSManuel Klimek 78*ddbe6c41SOwen Pan FormatStyle getTextProtoStyleWithColumns(unsigned ColumnLimit) const { 79*ddbe6c41SOwen Pan return getStyleWithColumns(getGoogleStyle(FormatStyle::LK_TextProto), 80*ddbe6c41SOwen Pan ColumnLimit); 81f8d10d5aSManuel Klimek } 82f8d10d5aSManuel Klimek 831c58208dSOwen Pan bool _verifyFormat(const char *File, int Line, StringRef Expected, 841c58208dSOwen Pan StringRef Code, 85f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}, 86f8d10d5aSManuel Klimek const std::vector<tooling::Range> &Ranges = {}) { 871c58208dSOwen Pan testing::ScopedTrace t(File, Line, testing::Message() << Code.str()); 887ecbf6c3SOwen const auto ExpectedCode{Expected.str()}; 897ecbf6c3SOwen auto FormattedCode{format(Code, Style, SC_ExpectComplete, Ranges)}; 907ecbf6c3SOwen EXPECT_EQ(ExpectedCode, FormattedCode); 917ecbf6c3SOwen if (ExpectedCode != FormattedCode) 927ecbf6c3SOwen return false; 93c8521451SOwen Pan if (Expected != Code) { 947ecbf6c3SOwen FormattedCode = format(Expected, Style, SC_ExpectComplete, Ranges); 957ecbf6c3SOwen EXPECT_EQ(ExpectedCode, FormattedCode) << "Expected code is not stable"; 967ecbf6c3SOwen if (ExpectedCode != FormattedCode) 977ecbf6c3SOwen return false; 98c8521451SOwen Pan } 99f8d10d5aSManuel Klimek auto UsedStyle = Style ? Style.value() : getDefaultStyle(); 100f8d10d5aSManuel Klimek if (UsedStyle.Language == FormatStyle::LK_Cpp) { 101f8d10d5aSManuel Klimek // Objective-C++ is a superset of C++, so everything checked for C++ 102f8d10d5aSManuel Klimek // needs to be checked for Objective-C++ as well. 103f8d10d5aSManuel Klimek FormatStyle ObjCStyle = UsedStyle; 104f8d10d5aSManuel Klimek ObjCStyle.Language = FormatStyle::LK_ObjC; 105f8d10d5aSManuel Klimek // FIXME: Additional messUp is superfluous. 1067ecbf6c3SOwen FormattedCode = format(Code, ObjCStyle, SC_ExpectComplete, Ranges); 1077ecbf6c3SOwen EXPECT_EQ(ExpectedCode, FormattedCode); 1087ecbf6c3SOwen if (ExpectedCode != FormattedCode) 1097ecbf6c3SOwen return false; 110f8d10d5aSManuel Klimek } 1117ecbf6c3SOwen return true; 112f8d10d5aSManuel Klimek } 113f8d10d5aSManuel Klimek 1141c58208dSOwen Pan void _verifyFormat(const char *File, int Line, StringRef Code, 115f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}) { 1167ecbf6c3SOwen if (!_verifyFormat(File, Line, Code, Code, Style)) 1177ecbf6c3SOwen return; 1186982f1fcSOwen Pan if (const auto MessedUpCode{messUp(Code)}; MessedUpCode != Code) 1196982f1fcSOwen Pan _verifyFormat(File, Line, Code, MessedUpCode, Style); 120f8d10d5aSManuel Klimek } 121f8d10d5aSManuel Klimek 1221c58208dSOwen Pan void _verifyIncompleteFormat(const char *File, int Line, StringRef Code, 123f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}) { 1241c58208dSOwen Pan testing::ScopedTrace t(File, Line, testing::Message() << Code.str()); 1256cef3254Ssstwcw EXPECT_EQ(Code.str(), format(messUp(Code), Style, SC_ExpectIncomplete)); 126f8d10d5aSManuel Klimek } 127f8d10d5aSManuel Klimek 128f8d10d5aSManuel Klimek void 1291c58208dSOwen Pan _verifyIndependentOfContext(const char *File, int Line, StringRef Text, 130f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}) { 131f8d10d5aSManuel Klimek _verifyFormat(File, Line, Text, Style); 1321c58208dSOwen Pan _verifyFormat(File, Line, Twine("void f() { " + Text + " }").str(), Style); 133f8d10d5aSManuel Klimek } 134f8d10d5aSManuel Klimek 1351c58208dSOwen Pan void _verifyNoChange(const char *File, int Line, StringRef Code, 13620b4df1eSOwen Pan const std::optional<FormatStyle> &Style = {}) { 13720b4df1eSOwen Pan _verifyFormat(File, Line, Code, Code, Style); 13820b4df1eSOwen Pan } 13920b4df1eSOwen Pan 140f8d10d5aSManuel Klimek /// \brief Verify that clang-format does not crash on the given input. 1411c58208dSOwen Pan void verifyNoCrash(StringRef Code, 142f8d10d5aSManuel Klimek const std::optional<FormatStyle> &Style = {}) { 143f8d10d5aSManuel Klimek format(Code, Style, SC_DoNotCheck); 144f8d10d5aSManuel Klimek } 145f8d10d5aSManuel Klimek 146f8d10d5aSManuel Klimek int ReplacementCount; 147f8d10d5aSManuel Klimek }; 148f8d10d5aSManuel Klimek 149f8d10d5aSManuel Klimek #undef DEBUG_TYPE 150f8d10d5aSManuel Klimek 151f8d10d5aSManuel Klimek #define verifyIndependentOfContext(...) \ 152f8d10d5aSManuel Klimek _verifyIndependentOfContext(__FILE__, __LINE__, __VA_ARGS__) 153f8d10d5aSManuel Klimek #define verifyIncompleteFormat(...) \ 154f8d10d5aSManuel Klimek _verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__) 15520b4df1eSOwen Pan #define verifyNoChange(...) _verifyNoChange(__FILE__, __LINE__, __VA_ARGS__) 156f8d10d5aSManuel Klimek #define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__) 157f8d10d5aSManuel Klimek #define verifyGoogleFormat(Code) verifyFormat(Code, getGoogleStyle()) 158f8d10d5aSManuel Klimek 159f8d10d5aSManuel Klimek } // namespace test 160f8d10d5aSManuel Klimek } // namespace format 161f8d10d5aSManuel Klimek } // namespace clang 162f8d10d5aSManuel Klimek 163f8d10d5aSManuel Klimek #endif 164