clang-tools  14.0.0git
CancellationTests.cpp
Go to the documentation of this file.
1 #include "support/Cancellation.h"
2 #include "support/Context.h"
3 #include "support/Threading.h"
4 #include "llvm/Support/Error.h"
5 #include "gmock/gmock.h"
6 #include "gtest/gtest.h"
7 #include <atomic>
8 #include <memory>
9 #include <thread>
10 
11 namespace clang {
12 namespace clangd {
13 namespace {
14 
15 TEST(CancellationTest, CancellationTest) {
16  auto Task = cancelableTask();
17  WithContext ContextWithCancellation(std::move(Task.first));
18  EXPECT_FALSE(isCancelled());
19  Task.second();
20  EXPECT_TRUE(isCancelled());
21 }
22 
23 TEST(CancellationTest, CancelerDiesContextLives) {
24  llvm::Optional<WithContext> ContextWithCancellation;
25  {
26  auto Task = cancelableTask();
27  ContextWithCancellation.emplace(std::move(Task.first));
28  EXPECT_FALSE(isCancelled());
29  Task.second();
30  EXPECT_TRUE(isCancelled());
31  }
32  EXPECT_TRUE(isCancelled());
33 }
34 
35 TEST(CancellationTest, TaskContextDiesHandleLives) {
36  auto Task = cancelableTask();
37  {
38  WithContext ContextWithCancellation(std::move(Task.first));
39  EXPECT_FALSE(isCancelled());
40  Task.second();
41  EXPECT_TRUE(isCancelled());
42  }
43  // Still should be able to cancel without any problems.
44  Task.second();
45 }
46 
47 struct NestedTasks {
48  enum { OuterReason = 1, InnerReason = 2 };
49  std::pair<Context, Canceler> Outer, Inner;
50  NestedTasks() {
51  Outer = cancelableTask(OuterReason);
52  {
53  WithContext WithOuter(Outer.first.clone());
54  Inner = cancelableTask(InnerReason);
55  }
56  }
57 };
58 
59 TEST(CancellationTest, Nested) {
60  // Cancelling inner task works but leaves outer task unaffected.
61  NestedTasks CancelInner;
62  CancelInner.Inner.second();
63  EXPECT_EQ(NestedTasks::InnerReason, isCancelled(CancelInner.Inner.first));
64  EXPECT_FALSE(isCancelled(CancelInner.Outer.first));
65  // Cancellation of outer task is inherited by inner task.
66  NestedTasks CancelOuter;
67  CancelOuter.Outer.second();
68  EXPECT_EQ(NestedTasks::OuterReason, isCancelled(CancelOuter.Inner.first));
69  EXPECT_EQ(NestedTasks::OuterReason, isCancelled(CancelOuter.Outer.first));
70 }
71 
72 TEST(CancellationTest, AsynCancellationTest) {
73  std::atomic<bool> HasCancelled(false);
74  Notification Cancelled;
75  auto TaskToBeCancelled = [&](Context Ctx) {
76  WithContext ContextGuard(std::move(Ctx));
77  Cancelled.wait();
78  HasCancelled = isCancelled();
79  };
80  auto Task = cancelableTask();
81  std::thread AsyncTask(TaskToBeCancelled, std::move(Task.first));
82  Task.second();
83  Cancelled.notify();
84  AsyncTask.join();
85 
86  EXPECT_TRUE(HasCancelled);
87 }
88 } // namespace
89 } // namespace clangd
90 } // namespace clang
clang::clangd::cancelableTask
std::pair< Context, Canceler > cancelableTask(int Reason)
Defines a new task whose cancellation may be requested.
Definition: Cancellation.cpp:24
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:752
Ctx
Context Ctx
Definition: TUScheduler.cpp:460
Outer
std::pair< Context, Canceler > Outer
Definition: CancellationTests.cpp:49
Cancellation.h
clang::clangd::isCancelled
int isCancelled(const Context &Ctx)
If the current context is within a cancelled task, returns the reason.
Definition: Cancellation.cpp:35
Inner
std::pair< Context, Canceler > Inner
Definition: CancellationTests.cpp:49
Threading.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
Context.h