[TargetVersion] Only enable on RISC-V and AArch64 (#115991)
[llvm-project.git] / clang-tools-extra / clangd / unittests / support / CancellationTests.cpp
blobed98d8f30748766080a26a7dacdc400fe8ea666f
1 #include "support/Cancellation.h"
2 #include "support/Context.h"
3 #include "support/Threading.h"
4 #include "gmock/gmock.h"
5 #include "gtest/gtest.h"
6 #include <atomic>
7 #include <memory>
8 #include <optional>
9 #include <thread>
11 namespace clang {
12 namespace clangd {
13 namespace {
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());
23 TEST(CancellationTest, CancelerDiesContextLives) {
24 std::optional<WithContext> ContextWithCancellation;
26 auto Task = cancelableTask();
27 ContextWithCancellation.emplace(std::move(Task.first));
28 EXPECT_FALSE(isCancelled());
29 Task.second();
30 EXPECT_TRUE(isCancelled());
32 EXPECT_TRUE(isCancelled());
35 TEST(CancellationTest, TaskContextDiesHandleLives) {
36 auto Task = cancelableTask();
38 WithContext ContextWithCancellation(std::move(Task.first));
39 EXPECT_FALSE(isCancelled());
40 Task.second();
41 EXPECT_TRUE(isCancelled());
43 // Still should be able to cancel without any problems.
44 Task.second();
47 struct NestedTasks {
48 enum { OuterReason = 1, InnerReason = 2 };
49 std::pair<Context, Canceler> Outer, Inner;
50 NestedTasks() {
51 Outer = cancelableTask(OuterReason);
53 WithContext WithOuter(Outer.first.clone());
54 Inner = cancelableTask(InnerReason);
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));
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();
80 auto Task = cancelableTask();
81 std::thread AsyncTask(TaskToBeCancelled, std::move(Task.first));
82 Task.second();
83 Cancelled.notify();
84 AsyncTask.join();
86 EXPECT_TRUE(HasCancelled);
88 } // namespace
89 } // namespace clangd
90 } // namespace clang