18
18
#include " TestFS.h"
19
19
#include " TestIndex.h"
20
20
#include " TestTU.h"
21
+ #include " Threading.h"
21
22
#include " index/Index.h"
22
23
#include " index/MemIndex.h"
23
24
#include " clang/Sema/CodeCompleteConsumer.h"
27
28
#include " llvm/Testing/Support/Error.h"
28
29
#include " gmock/gmock.h"
29
30
#include " gtest/gtest.h"
31
+ #include < condition_variable>
32
+ #include < mutex>
30
33
31
34
namespace clang {
32
35
namespace clangd {
@@ -1112,8 +1115,9 @@ class IndexRequestCollector : public SymbolIndex {
1112
1115
bool
1113
1116
fuzzyFind (const FuzzyFindRequest &Req,
1114
1117
llvm::function_ref<void (const Symbol &)> Callback) const override {
1115
- std::lock_guard <std::mutex> Lock (Mut);
1118
+ std::unique_lock <std::mutex> Lock (Mut);
1116
1119
Requests.push_back (Req);
1120
+ ReceivedRequestCV.notify_one ();
1117
1121
return true ;
1118
1122
}
1119
1123
@@ -1131,25 +1135,32 @@ class IndexRequestCollector : public SymbolIndex {
1131
1135
// isn't used in production code.
1132
1136
size_t estimateMemoryUsage () const override { return 0 ; }
1133
1137
1134
- const std::vector<FuzzyFindRequest> consumeRequests () const {
1135
- std::lock_guard<std::mutex> Lock (Mut);
1138
+ const std::vector<FuzzyFindRequest> consumeRequests (size_t Num) const {
1139
+ std::unique_lock<std::mutex> Lock (Mut);
1140
+ EXPECT_TRUE (wait (Lock, ReceivedRequestCV, timeoutSeconds (10 ),
1141
+ [this , Num] { return Requests.size () == Num; }));
1136
1142
auto Reqs = std::move (Requests);
1137
1143
Requests = {};
1138
1144
return Reqs;
1139
1145
}
1140
1146
1141
1147
private:
1142
1148
// We need a mutex to handle async fuzzy find requests.
1149
+ mutable std::condition_variable ReceivedRequestCV;
1143
1150
mutable std::mutex Mut;
1144
1151
mutable std::vector<FuzzyFindRequest> Requests;
1145
1152
};
1146
1153
1147
- std::vector<FuzzyFindRequest> captureIndexRequests (llvm::StringRef Code) {
1154
+ // Clients have to consume exactly Num requests.
1155
+ std::vector<FuzzyFindRequest> captureIndexRequests (llvm::StringRef Code,
1156
+ size_t Num = 1 ) {
1148
1157
clangd::CodeCompleteOptions Opts;
1149
1158
IndexRequestCollector Requests;
1150
1159
Opts.Index = &Requests;
1151
1160
completions (Code, {}, Opts);
1152
- return Requests.consumeRequests ();
1161
+ const auto Reqs = Requests.consumeRequests (Num);
1162
+ EXPECT_EQ (Reqs.size (), Num);
1163
+ return Reqs;
1153
1164
}
1154
1165
1155
1166
TEST (CompletionTest, UnqualifiedIdQuery) {
@@ -2098,26 +2109,23 @@ TEST(CompletionTest, EnableSpeculativeIndexRequest) {
2098
2109
2099
2110
auto CompleteAtPoint = [&](StringRef P) {
2100
2111
cantFail (runCodeComplete (Server, File, Test.point (P), Opts));
2101
- // Sleep for a while to make sure asynchronous call (if applicable) is also
2102
- // triggered before callback is invoked.
2103
- std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
2104
2112
};
2105
2113
2106
2114
CompleteAtPoint (" 1" );
2107
- auto Reqs1 = Requests.consumeRequests ();
2115
+ auto Reqs1 = Requests.consumeRequests (1 );
2108
2116
ASSERT_EQ (Reqs1.size (), 1u );
2109
2117
EXPECT_THAT (Reqs1[0 ].Scopes , UnorderedElementsAre (" ns1::" ));
2110
2118
2111
2119
CompleteAtPoint (" 2" );
2112
- auto Reqs2 = Requests.consumeRequests ();
2120
+ auto Reqs2 = Requests.consumeRequests (1 );
2113
2121
// Speculation succeeded. Used speculative index result.
2114
2122
ASSERT_EQ (Reqs2.size (), 1u );
2115
2123
EXPECT_EQ (Reqs2[0 ], Reqs1[0 ]);
2116
2124
2117
2125
CompleteAtPoint (" 3" );
2118
2126
// Speculation failed. Sent speculative index request and the new index
2119
2127
// request after sema.
2120
- auto Reqs3 = Requests.consumeRequests ();
2128
+ auto Reqs3 = Requests.consumeRequests (2 );
2121
2129
ASSERT_EQ (Reqs3.size (), 2u );
2122
2130
}
2123
2131
0 commit comments