diff options
Diffstat (limited to 'clang-tools-extra/unittests/clangd')
4 files changed, 82 insertions, 38 deletions
diff --git a/clang-tools-extra/unittests/clangd/CMakeLists.txt b/clang-tools-extra/unittests/clangd/CMakeLists.txt index 8f6125e192d..c0cba6c817f 100644 --- a/clang-tools-extra/unittests/clangd/CMakeLists.txt +++ b/clang-tools-extra/unittests/clangd/CMakeLists.txt @@ -21,6 +21,7 @@ add_extra_unittest(ClangdTests JSONExprTests.cpp URITests.cpp TestFS.cpp + ThreadingTests.cpp TraceTests.cpp TUSchedulerTests.cpp SourceCodeTests.cpp diff --git a/clang-tools-extra/unittests/clangd/ClangdTests.cpp b/clang-tools-extra/unittests/clangd/ClangdTests.cpp index 4d5c588609e..ac2459c7ba3 100644 --- a/clang-tools-extra/unittests/clangd/ClangdTests.cpp +++ b/clang-tools-extra/unittests/clangd/ClangdTests.cpp @@ -539,7 +539,6 @@ int d; unsigned RequestsWithErrors = 0; bool LastContentsHadErrors = false; bool FileIsRemoved = true; - std::future<void> LastRequestFuture; }; std::vector<RequestStats> ReqStats; @@ -565,8 +564,7 @@ int d; std::uniform_int_distribution<int> ColumnDist(0, MaxColumnForFileRequests); // Some helpers. - auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool HadErrors, - std::future<void> Future) { + auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool HadErrors) { auto &Stats = ReqStats[FileIndex]; if (HadErrors) @@ -575,22 +573,17 @@ int d; ++Stats.RequestsWithoutErrors; Stats.LastContentsHadErrors = HadErrors; Stats.FileIsRemoved = false; - Stats.LastRequestFuture = std::move(Future); }; - auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex, - std::future<void> Future) { + auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex) { auto &Stats = ReqStats[FileIndex]; Stats.FileIsRemoved = true; - Stats.LastRequestFuture = std::move(Future); }; - auto UpdateStatsOnForceReparse = [&](unsigned FileIndex, - std::future<void> Future) { + auto UpdateStatsOnForceReparse = [&](unsigned FileIndex) { auto &Stats = ReqStats[FileIndex]; - Stats.LastRequestFuture = std::move(Future); if (Stats.LastContentsHadErrors) ++Stats.RequestsWithErrors; else @@ -599,10 +592,10 @@ int d; auto AddDocument = [&](unsigned FileIndex) { bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen); - auto Future = Server.addDocument( - FilePaths[FileIndex], ShouldHaveErrors ? SourceContentsWithErrors - : SourceContentsWithoutErrors); - UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors, std::move(Future)); + Server.addDocument(FilePaths[FileIndex], + ShouldHaveErrors ? SourceContentsWithErrors + : SourceContentsWithoutErrors); + UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors); }; // Various requests that we would randomly run. @@ -617,8 +610,8 @@ int d; if (ReqStats[FileIndex].FileIsRemoved) AddDocument(FileIndex); - auto Future = Server.forceReparse(FilePaths[FileIndex]); - UpdateStatsOnForceReparse(FileIndex, std::move(Future)); + Server.forceReparse(FilePaths[FileIndex]); + UpdateStatsOnForceReparse(FileIndex); }; auto RemoveDocumentRequest = [&]() { @@ -627,8 +620,8 @@ int d; if (ReqStats[FileIndex].FileIsRemoved) AddDocument(FileIndex); - auto Future = Server.removeDocument(FilePaths[FileIndex]); - UpdateStatsOnRemoveDocument(FileIndex, std::move(Future)); + Server.removeDocument(FilePaths[FileIndex]); + UpdateStatsOnRemoveDocument(FileIndex); }; auto CodeCompletionRequest = [&]() { @@ -681,17 +674,6 @@ int d; BlockingRequests[RequestIndex](); } } - - // Wait for last requests to finish. - for (auto &ReqStat : ReqStats) { - if (!ReqStat.LastRequestFuture.valid()) - continue; // We never ran any requests for this file. - - // Future should be ready much earlier than in 5 seconds, the timeout is - // there to check we won't wait indefinitely. - ASSERT_EQ(ReqStat.LastRequestFuture.wait_for(std::chrono::seconds(5)), - std::future_status::ready); - } } // Wait for ClangdServer to shutdown before proceeding. // Check some invariants about the state of the program. diff --git a/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp b/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp index 34b6f25ce06..b18f04ed39c 100644 --- a/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp +++ b/clang-tools-extra/unittests/clangd/TUSchedulerTests.cpp @@ -65,10 +65,8 @@ TEST_F(TUSchedulerTests, MissingFiles) { ASSERT_FALSE(bool(Preamble)); ignoreError(Preamble.takeError()); }); - S.remove(Missing, [&](llvm::Error Err) { - EXPECT_TRUE(bool(Err)); - ignoreError(std::move(Err)); - }); + // remove() shouldn't crash on missing files. + S.remove(Missing); // Assert there aren't any errors for added file. S.runWithAST( @@ -76,7 +74,7 @@ TEST_F(TUSchedulerTests, MissingFiles) { S.runWithPreamble(Added, [&](llvm::Expected<InputsAndPreamble> Preamble) { EXPECT_TRUE(bool(Preamble)); }); - S.remove(Added, [&](llvm::Error Err) { EXPECT_FALSE(bool(Err)); }); + S.remove(Added); // Assert that all operations fail after removing the file. S.runWithAST(Added, [&](llvm::Expected<InputsAndAST> AST) { @@ -87,10 +85,8 @@ TEST_F(TUSchedulerTests, MissingFiles) { ASSERT_FALSE(bool(Preamble)); ignoreError(Preamble.takeError()); }); - S.remove(Added, [&](llvm::Error Err) { - EXPECT_TRUE(bool(Err)); - ignoreError(std::move(Err)); - }); + // remove() shouldn't crash on missing files. + S.remove(Added); } TEST_F(TUSchedulerTests, ManyUpdates) { diff --git a/clang-tools-extra/unittests/clangd/ThreadingTests.cpp b/clang-tools-extra/unittests/clangd/ThreadingTests.cpp new file mode 100644 index 00000000000..84e6512fe43 --- /dev/null +++ b/clang-tools-extra/unittests/clangd/ThreadingTests.cpp @@ -0,0 +1,65 @@ +//===-- ThreadingTests.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Threading.h" +#include "gtest/gtest.h" +#include <mutex> + +namespace clang { +namespace clangd { +class ThreadingTest : public ::testing::Test {}; + +TEST_F(ThreadingTest, TaskRunner) { + const int TasksCnt = 100; + // This should be const, but MSVC does not allow to use const vars in lambdas + // without capture. On the other hand, clang gives a warning that capture of + // const var is not required. + // Making it non-const makes both compilers happy. + int IncrementsPerTask = 1000; + + std::mutex Mutex; + int Counter(0); /* GUARDED_BY(Mutex) */ + { + AsyncTaskRunner Tasks; + auto scheduleIncrements = [&]() { + for (int TaskI = 0; TaskI < TasksCnt; ++TaskI) { + Tasks.runAsync([&Counter, &Mutex, IncrementsPerTask]() { + for (int Increment = 0; Increment < IncrementsPerTask; ++Increment) { + std::lock_guard<std::mutex> Lock(Mutex); + ++Counter; + } + }); + } + }; + + { + // Make sure runAsync is not running tasks synchronously on the same + // thread by locking the Mutex used for increments. + std::lock_guard<std::mutex> Lock(Mutex); + scheduleIncrements(); + } + + Tasks.waitForAll(); + { + std::lock_guard<std::mutex> Lock(Mutex); + ASSERT_EQ(Counter, TasksCnt * IncrementsPerTask); + } + + { + std::lock_guard<std::mutex> Lock(Mutex); + Counter = 0; + scheduleIncrements(); + } + } + // Check that destructor has waited for tasks to finish. + std::lock_guard<std::mutex> Lock(Mutex); + ASSERT_EQ(Counter, TasksCnt * IncrementsPerTask); +} +} // namespace clangd +} // namespace clang |