1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "googletest.h"
27 
28 #include <clangfixitoperation.h>
29 #include <fixitcontainer.h>
30 
31 #include <utils/changeset.h>
32 
33 #include <QFile>
34 #include <QVector>
35 
36 using ClangBackEnd::FixItContainer;
37 using ClangCodeModel::Internal::ClangFixItOperation;
38 
39 using ::testing::PrintToString;
40 
41 namespace {
42 
unsavedFileContent(const QString & unsavedFilePath)43 QString unsavedFileContent(const QString &unsavedFilePath)
44 {
45     QFile unsavedFileContentFile(unsavedFilePath);
46     const bool isOpen = unsavedFileContentFile.open(QFile::ReadOnly | QFile::Text);
47     if (!isOpen)
48         ADD_FAILURE() << "File with the unsaved content cannot be opened!";
49 
50     return QString::fromUtf8(unsavedFileContentFile.readAll());
51 }
52 
53 MATCHER_P(MatchText, expectedText,
54           std::string(negation ? "hasn't" : "has")
55           + " expected text:\n" + PrintToString(expectedText))
56 {
57     const ::ClangFixItOperation &operation = arg;
58     QString resultText = operation.firstRefactoringFileContent_forTestOnly();
59 
60     if (resultText != expectedText) {
61         *result_listener << "\n" << resultText.toUtf8().constData();
62         return false;
63     }
64 
65     return true;
66 }
67 
68 class ClangFixItOperation : public ::testing::Test
69 {
70 protected:
71     Utf8String semicolonFilePath{TESTDATA_DIR"/diagnostic_semicolon_fixit.cpp", -1};
72     Utf8String compareFilePath{TESTDATA_DIR"/diagnostic_comparison_fixit.cpp", -1};
73     Utf8String diagnosticText{Utf8StringLiteral("expected ';' at end of declaration")};
74     FixItContainer semicolonFixItContainer{Utf8StringLiteral(";"),
75                                   {{semicolonFilePath, 3u, 13u},
76                                    {semicolonFilePath, 3u, 13u}}};
77     QString semicolonErrorFile{semicolonFilePath.toString()};
78     QString semicolonExpectedFile{QString::fromUtf8(TESTDATA_DIR"/diagnostic_semicolon_fixit_expected.cpp")};
79     QString compareWarningFile{compareFilePath.toString()};
80     QString compareExpected1File{QString::fromUtf8(TESTDATA_DIR"/diagnostic_comparison_fixit_expected1.cpp")};
81     QString compareExpected2File{QString::fromUtf8(TESTDATA_DIR"/diagnostic_comparison_fixit_expected2.cpp")};
82     FixItContainer compareFixItContainer{Utf8StringLiteral("=="),
83                                   {{compareFilePath, 4u, 11u},
84                                    {compareFilePath, 4u, 12u}}};
85     FixItContainer assignmentFixItContainerParenLeft{Utf8StringLiteral("("),
86                                   {{compareFilePath, 4u, 9u},
87                                    {compareFilePath, 4u, 9u}}};
88     FixItContainer assignmentFixItContainerParenRight{Utf8StringLiteral(")"),
89                                   {{compareFilePath, 4u, 14u},
90                                    {compareFilePath, 4u, 14u}}};
91 };
92 
TEST_F(ClangFixItOperation,Description)93 TEST_F(ClangFixItOperation, Description)
94 {
95     ::ClangFixItOperation operation(diagnosticText, {semicolonFixItContainer});
96 
97     ASSERT_THAT(operation.description(),
98                 QStringLiteral("Apply Fix: expected ';' at end of declaration"));
99 }
100 
TEST_F(ClangFixItOperation,AppendSemicolon)101 TEST_F(ClangFixItOperation, AppendSemicolon)
102 {
103     ::ClangFixItOperation operation(diagnosticText, {semicolonFixItContainer});
104 
105     operation.perform();
106 
107     ASSERT_THAT(operation, MatchText(unsavedFileContent(semicolonExpectedFile)));
108 }
109 
TEST_F(ClangFixItOperation,ComparisonVersusAssignmentChooseComparison)110 TEST_F(ClangFixItOperation, ComparisonVersusAssignmentChooseComparison)
111 {
112     ::ClangFixItOperation operation(diagnosticText, {compareFixItContainer});
113 
114     operation.perform();
115 
116     ASSERT_THAT(operation, MatchText(unsavedFileContent(compareExpected1File)));
117 }
118 
TEST_F(ClangFixItOperation,ComparisonVersusAssignmentChooseParentheses)119 TEST_F(ClangFixItOperation, ComparisonVersusAssignmentChooseParentheses)
120 {
121     ::ClangFixItOperation operation(diagnosticText,
122                                     {assignmentFixItContainerParenLeft,
123                                      assignmentFixItContainerParenRight});
124 
125     operation.perform();
126 
127     ASSERT_THAT(operation, MatchText(unsavedFileContent(compareExpected2File)));
128 }
129 
130 }
131