12 #include "llvm/Testing/Support/Error.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
20 struct IncrementalTestStep {
25 int rangeLength(llvm::StringRef
Code,
const Range &Rng) {
34 void stepByStep(llvm::ArrayRef<IncrementalTestStep> Steps) {
36 Annotations InitialSrc(Steps.front().Src);
37 constexpr llvm::StringLiteral
Path(
"/hello.cpp");
42 for (
size_t i = 1; i < Steps.size(); i++) {
43 Annotations SrcBefore(Steps[i - 1].
Src);
44 Annotations SrcAfter(Steps[i].
Src);
45 llvm::StringRef
Contents = Steps[i - 1].Contents;
46 TextDocumentContentChangeEvent
Event{
48 rangeLength(SrcBefore.code(), SrcBefore.range()),
52 llvm::Expected<DraftStore::Draft> Result =
54 ASSERT_TRUE(!!Result);
55 EXPECT_EQ(Result->Contents, SrcAfter.code());
56 EXPECT_EQ(DS.getDraft(
Path)->Contents, SrcAfter.code());
57 EXPECT_EQ(Result->Version, static_cast<int64_t>(i));
62 void allAtOnce(llvm::ArrayRef<IncrementalTestStep> Steps) {
64 Annotations InitialSrc(Steps.front().Src);
65 Annotations FinalSrc(Steps.back().Src);
66 constexpr llvm::StringLiteral
Path(
"/hello.cpp");
67 std::vector<TextDocumentContentChangeEvent>
Changes;
69 for (
size_t i = 0; i < Steps.size() - 1; i++) {
70 Annotations
Src(Steps[i].
Src);
71 llvm::StringRef
Contents = Steps[i].Contents;
75 rangeLength(
Src.code(),
Src.range()),
83 llvm::Expected<DraftStore::Draft> Result =
87 EXPECT_EQ(Result->Contents, FinalSrc.code());
88 EXPECT_EQ(DS.getDraft(
Path)->Contents, FinalSrc.code());
89 EXPECT_EQ(Result->Version, 1);
92 TEST(DraftStoreIncrementalUpdateTest, Simple) {
94 IncrementalTestStep Steps[] =
130 TEST(DraftStoreIncrementalUpdateTest, MultiLine) {
132 IncrementalTestStep Steps[] =
150 R
"cpp(static char[[]]()
160 R"cpp(#include <stdio.h>
165 R
"cpp([[#include <stdio.h>
187 TEST(DraftStoreIncrementalUpdateTest, WrongRangeLength) {
189 Path File =
"foo.cpp";
191 DS.addDraft(File,
llvm::None,
"int main() {}\n");
193 TextDocumentContentChangeEvent Change;
194 Change.range.emplace();
195 Change.range->start.line = 0;
196 Change.range->start.character = 0;
197 Change.range->end.line = 0;
198 Change.range->end.character = 2;
199 Change.rangeLength = 10;
201 Expected<DraftStore::Draft> Result =
204 EXPECT_TRUE(!Result);
207 "Change's rangeLength (10) doesn't match the computed range length (2).");
210 TEST(DraftStoreIncrementalUpdateTest, EndBeforeStart) {
212 Path File =
"foo.cpp";
214 DS.addDraft(File,
llvm::None,
"int main() {}\n");
216 TextDocumentContentChangeEvent Change;
217 Change.range.emplace();
218 Change.range->start.line = 0;
219 Change.range->start.character = 5;
220 Change.range->end.line = 0;
221 Change.range->end.character = 3;
223 auto Result = DS.updateDraft(File,
llvm::None, {Change});
225 EXPECT_TRUE(!Result);
226 EXPECT_EQ(
toString(Result.takeError()),
227 "Range's end position (0:3) is before start position (0:5)");
230 TEST(DraftStoreIncrementalUpdateTest, StartCharOutOfRange) {
232 Path File =
"foo.cpp";
234 DS.addDraft(File,
llvm::None,
"int main() {}\n");
236 TextDocumentContentChangeEvent Change;
237 Change.range.emplace();
238 Change.range->start.line = 0;
239 Change.range->start.character = 100;
240 Change.range->end.line = 0;
241 Change.range->end.character = 100;
244 auto Result = DS.updateDraft(File,
llvm::None, {Change});
246 EXPECT_TRUE(!Result);
247 EXPECT_EQ(
toString(Result.takeError()),
248 "utf-16 offset 100 is invalid for line 0");
251 TEST(DraftStoreIncrementalUpdateTest, EndCharOutOfRange) {
253 Path File =
"foo.cpp";
255 DS.addDraft(File,
llvm::None,
"int main() {}\n");
257 TextDocumentContentChangeEvent Change;
258 Change.range.emplace();
259 Change.range->start.line = 0;
260 Change.range->start.character = 0;
261 Change.range->end.line = 0;
262 Change.range->end.character = 100;
265 auto Result = DS.updateDraft(File,
llvm::None, {Change});
267 EXPECT_TRUE(!Result);
268 EXPECT_EQ(
toString(Result.takeError()),
269 "utf-16 offset 100 is invalid for line 0");
272 TEST(DraftStoreIncrementalUpdateTest, StartLineOutOfRange) {
274 Path File =
"foo.cpp";
276 DS.addDraft(File,
llvm::None,
"int main() {}\n");
278 TextDocumentContentChangeEvent Change;
279 Change.range.emplace();
280 Change.range->start.line = 100;
281 Change.range->start.character = 0;
282 Change.range->end.line = 100;
283 Change.range->end.character = 0;
286 auto Result = DS.updateDraft(File,
llvm::None, {Change});
288 EXPECT_TRUE(!Result);
289 EXPECT_EQ(
toString(Result.takeError()),
"Line value is out of range (100)");
292 TEST(DraftStoreIncrementalUpdateTest, EndLineOutOfRange) {
294 Path File =
"foo.cpp";
296 DS.addDraft(File,
llvm::None,
"int main() {}\n");
298 TextDocumentContentChangeEvent Change;
299 Change.range.emplace();
300 Change.range->start.line = 0;
301 Change.range->start.character = 0;
302 Change.range->end.line = 100;
303 Change.range->end.character = 0;
306 auto Result = DS.updateDraft(File,
llvm::None, {Change});
308 EXPECT_TRUE(!Result);
309 EXPECT_EQ(
toString(Result.takeError()),
"Line value is out of range (100)");
314 TEST(DraftStoreIncrementalUpdateTest, InvalidRangeInASequence) {
316 Path File =
"foo.cpp";
318 StringRef OriginalContents =
"int main() {}\n";
319 EXPECT_EQ(0, DS.addDraft(File,
llvm::None, OriginalContents));
322 TextDocumentContentChangeEvent Change1;
323 Change1.range.emplace();
324 Change1.range->start.line = 0;
325 Change1.range->start.character = 0;
326 Change1.range->end.line = 0;
327 Change1.range->end.character = 0;
328 Change1.text =
"Hello ";
331 TextDocumentContentChangeEvent Change2;
332 Change2.range.emplace();
333 Change2.range->start.line = 0;
334 Change2.range->start.character = 5;
335 Change2.range->end.line = 0;
336 Change2.range->end.character = 100;
337 Change2.text =
"something";
339 auto Result = DS.updateDraft(File,
llvm::None, {Change1, Change2});
341 EXPECT_TRUE(!Result);
342 EXPECT_EQ(
toString(Result.takeError()),
343 "utf-16 offset 100 is invalid for line 0");
345 Optional<DraftStore::Draft>
Contents = DS.getDraft(File);
347 EXPECT_EQ(
Contents->Contents, OriginalContents);
351 TEST(DraftStore, Version) {
353 Path File =
"foo.cpp";
355 EXPECT_EQ(25, DS.addDraft(File, 25,
""));
356 EXPECT_EQ(25, DS.getDraft(File)->Version);
358 EXPECT_EQ(26, DS.addDraft(File,
llvm::None,
""));
359 EXPECT_EQ(26, DS.getDraft(File)->Version);
362 EXPECT_EQ(7, DS.addDraft(File, 7,
""));
363 EXPECT_EQ(7, DS.getDraft(File)->Version);
366 auto Result = DS.updateDraft(File, 10, {});
367 EXPECT_TRUE(!!Result);
368 EXPECT_EQ(10, Result->Version);
369 EXPECT_EQ(10, DS.getDraft(File)->Version);
371 Result = DS.updateDraft(File,
llvm::None, {});
372 EXPECT_TRUE(!!Result);
373 EXPECT_EQ(11, Result->Version);
374 EXPECT_EQ(11, DS.getDraft(File)->Version);
376 TextDocumentContentChangeEvent InvalidChange;
377 InvalidChange.range.emplace();
378 InvalidChange.rangeLength = 99;
380 Result = DS.updateDraft(File, 15, {InvalidChange});
381 EXPECT_FALSE(!!Result);
382 consumeError(Result.takeError());
383 EXPECT_EQ(11, DS.getDraft(File)->Version);