diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -27,6 +27,8 @@ #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include +#include namespace clang { namespace clangd { @@ -1112,8 +1114,10 @@ bool fuzzyFind(const FuzzyFindRequest &Req, llvm::function_ref Callback) const override { - std::lock_guard Lock(Mut); + std::unique_lock Lock(Mut); Requests.push_back(Req); + ++NumRequestsReceived; + ReceivedRequestCV.notify_one(); return true; } @@ -1131,8 +1135,11 @@ // isn't used in production code. size_t estimateMemoryUsage() const override { return 0; } - const std::vector consumeRequests() const { - std::lock_guard Lock(Mut); + const std::vector consumeRequests(size_t Num) const { + std::unique_lock Lock(Mut); + ReceivedRequestCV.wait(Lock, + [this, Num] { return NumRequestsReceived == Num; }); + NumRequestsReceived = 0; auto Reqs = std::move(Requests); Requests = {}; return Reqs; @@ -1140,16 +1147,19 @@ private: // We need a mutex to handle async fuzzy find requests. + mutable std::condition_variable ReceivedRequestCV; mutable std::mutex Mut; + mutable size_t NumRequestsReceived = 0; mutable std::vector Requests; }; -std::vector captureIndexRequests(llvm::StringRef Code) { +std::vector captureIndexRequests(llvm::StringRef Code, + size_t Num = 1) { clangd::CodeCompleteOptions Opts; IndexRequestCollector Requests; Opts.Index = &Requests; completions(Code, {}, Opts); - return Requests.consumeRequests(); + return Requests.consumeRequests(Num); } TEST(CompletionTest, UnqualifiedIdQuery) { @@ -2098,18 +2108,15 @@ auto CompleteAtPoint = [&](StringRef P) { cantFail(runCodeComplete(Server, File, Test.point(P), Opts)); - // Sleep for a while to make sure asynchronous call (if applicable) is also - // triggered before callback is invoked. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); }; CompleteAtPoint("1"); - auto Reqs1 = Requests.consumeRequests(); + auto Reqs1 = Requests.consumeRequests(1); ASSERT_EQ(Reqs1.size(), 1u); EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::")); CompleteAtPoint("2"); - auto Reqs2 = Requests.consumeRequests(); + auto Reqs2 = Requests.consumeRequests(1); // Speculation succeeded. Used speculative index result. ASSERT_EQ(Reqs2.size(), 1u); EXPECT_EQ(Reqs2[0], Reqs1[0]); @@ -2117,7 +2124,7 @@ CompleteAtPoint("3"); // Speculation failed. Sent speculative index request and the new index // request after sema. - auto Reqs3 = Requests.consumeRequests(); + auto Reqs3 = Requests.consumeRequests(2); ASSERT_EQ(Reqs3.size(), 2u); }