mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:40:11 +01:00
171 lines
4.9 KiB
C++
171 lines
4.9 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "testing/file_test/test_file.h"
|
|
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "common/error_test_helpers.h"
|
|
#include "testing/base/file_helpers.h"
|
|
#include "testing/file_test/file_test_base.h"
|
|
|
|
// The current BUILD structure of this library means that in order to unit-test
|
|
// test_file.h, we have to pretend to be a file_test. That means there has to
|
|
// be a definition of CarbonFileTestManifest (normally generated by a file_test
|
|
// Bazel rule), and there has to be a registered FileTestFactory, so we define
|
|
// them both as dummies.
|
|
// TODO: restructure BUILD rules to avoid the need for this hack.
|
|
|
|
// Dummy empty manifest.
|
|
// NOLINTNEXTLINE(readability-identifier-naming): manifest.cpp dictates spelling
|
|
const char* CarbonFileTestManifest[] = {nullptr};
|
|
|
|
namespace Carbon::Testing {
|
|
|
|
// Dummy unusable FileTestBase.
|
|
class DummyFileTest : public FileTestBase {
|
|
public:
|
|
DummyFileTest(llvm::StringRef /*exe_path*/, llvm::StringRef test_name)
|
|
: FileTestBase(test_name) {}
|
|
|
|
auto Run(const llvm::SmallVector<llvm::StringRef>& /*test_args*/,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& /*fs*/,
|
|
FILE* /*input_stream*/, llvm::raw_pwrite_stream& /*output_stream*/,
|
|
llvm::raw_pwrite_stream& /*error_stream*/) const
|
|
-> ErrorOr<RunResult> override {
|
|
CARBON_FATAL("Called method of dummy object");
|
|
}
|
|
|
|
auto GetDefaultArgs() const -> llvm::SmallVector<std::string> override {
|
|
CARBON_FATAL("Called method of dummy object");
|
|
}
|
|
};
|
|
CARBON_FILE_TEST_FACTORY(DummyFileTest)
|
|
|
|
namespace {
|
|
|
|
using ::testing::_;
|
|
using ::testing::StrEq;
|
|
|
|
// Returns the non-check lines of test_file as a string.
|
|
auto NonCheckFileContents(const TestFile& test_file) -> std::string {
|
|
std::string buffer;
|
|
llvm::raw_string_ostream out(buffer);
|
|
for (const auto& line : test_file.non_check_lines) {
|
|
line.Print(out);
|
|
out << "\n";
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
// Returns a string consisting of 7 repetitions of `c`, for use as a simulated
|
|
// merge conflict marker. We use this in test inputs instead of writing the
|
|
// conflict markers directly in the string literals so that tools don't treat
|
|
// them as genuine merge conflicts in this file.
|
|
auto Marker(char c) -> std::string { return std::string(7, c); }
|
|
|
|
TEST(AutoupdateTest, SnapshotMergeConflict) {
|
|
std::string initial_contents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
)" + Marker('<') + R"(
|
|
// CHECK:STDOUT: side 1
|
|
)" + Marker('=') + R"(
|
|
// CHECK:STDOUT: side 2
|
|
)" + Marker('>') + R"(
|
|
More text
|
|
)";
|
|
|
|
constexpr std::string_view ExpectedContents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
More text
|
|
)";
|
|
auto file_path = *WriteTestFile("tmp", initial_contents);
|
|
auto test_file =
|
|
ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);
|
|
ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();
|
|
EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));
|
|
}
|
|
|
|
TEST(AutoupdateTest, SnapshotTheeWayMergeConflict) {
|
|
std::string initial_contents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
)" + Marker('<') + R"(
|
|
// CHECK:STDOUT: side 1
|
|
)" + Marker('|') + R"(
|
|
// CHECK:STDOUT: base
|
|
)" + Marker('=') + R"(
|
|
// CHECK:STDOUT: side 2
|
|
)" + Marker('>') + R"(
|
|
More text
|
|
)";
|
|
|
|
constexpr std::string_view ExpectedContents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
More text
|
|
)";
|
|
auto file_path = *WriteTestFile("tmp", initial_contents);
|
|
auto test_file =
|
|
ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);
|
|
ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();
|
|
EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));
|
|
}
|
|
|
|
TEST(AutoupdateTest, DiffMergeConflict) {
|
|
std::string initial_contents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
)" + Marker('<') + R"(
|
|
)" + Marker('%') + R"(
|
|
)" + Marker('\\') + R"(
|
|
// CHECK:STDOUT: unchanged
|
|
-// CHECK:STDOUT: base
|
|
+// CHECK:STDOUT: side 1
|
|
)" + Marker('+') + R"(
|
|
// CHECK:STDOUT: side 2
|
|
)" + Marker('>') + R"(
|
|
More text
|
|
)";
|
|
|
|
constexpr std::string_view ExpectedContents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
More text
|
|
)";
|
|
auto file_path = *WriteTestFile("tmp", initial_contents);
|
|
auto test_file =
|
|
ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);
|
|
ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();
|
|
EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));
|
|
}
|
|
|
|
TEST(AutoupdateTest, NonCheckInDiffRegion) {
|
|
std::string initial_contents = R"(
|
|
// AUTOUPDATE
|
|
Some text
|
|
)" + Marker('<') + R"(
|
|
)" + Marker('%') + R"(
|
|
)" + Marker('\\') + R"(
|
|
// unchanged
|
|
-// CHECK:STDOUT: base
|
|
+// CHECK:STDOUT: side 1
|
|
)" + Marker('+') + R"(
|
|
// CHECK:STDOUT: side 2
|
|
)" + Marker('>') + R"(
|
|
More text
|
|
)";
|
|
|
|
auto file_path = *WriteTestFile("tmp", initial_contents);
|
|
auto test_file =
|
|
ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);
|
|
ASSERT_THAT(test_file, IsError(_));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace Carbon::Testing
|