| #include "Cancellation.h" |
| #include "Context.h" |
| #include "Threading.h" |
| #include "llvm/Support/Error.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include <atomic> |
| #include <memory> |
| #include <thread> |
| |
| namespace clang { |
| namespace clangd { |
| namespace { |
| |
| TEST(CancellationTest, CancellationTest) { |
| auto Task = cancelableTask(); |
| WithContext ContextWithCancellation(std::move(Task.first)); |
| EXPECT_FALSE(isCancelled()); |
| Task.second(); |
| EXPECT_TRUE(isCancelled()); |
| } |
| |
| TEST(CancellationTest, CancelerDiesContextLives) { |
| llvm::Optional<WithContext> ContextWithCancellation; |
| { |
| auto Task = cancelableTask(); |
| ContextWithCancellation.emplace(std::move(Task.first)); |
| EXPECT_FALSE(isCancelled()); |
| Task.second(); |
| EXPECT_TRUE(isCancelled()); |
| } |
| EXPECT_TRUE(isCancelled()); |
| } |
| |
| TEST(CancellationTest, TaskContextDiesHandleLives) { |
| auto Task = cancelableTask(); |
| { |
| WithContext ContextWithCancellation(std::move(Task.first)); |
| EXPECT_FALSE(isCancelled()); |
| Task.second(); |
| EXPECT_TRUE(isCancelled()); |
| } |
| // Still should be able to cancel without any problems. |
| Task.second(); |
| } |
| |
| TEST(CancellationTest, AsynCancellationTest) { |
| std::atomic<bool> HasCancelled(false); |
| Notification Cancelled; |
| auto TaskToBeCancelled = [&](Context Ctx) { |
| WithContext ContextGuard(std::move(Ctx)); |
| Cancelled.wait(); |
| HasCancelled = isCancelled(); |
| }; |
| auto Task = cancelableTask(); |
| std::thread AsyncTask(TaskToBeCancelled, std::move(Task.first)); |
| Task.second(); |
| Cancelled.notify(); |
| AsyncTask.join(); |
| |
| EXPECT_TRUE(HasCancelled); |
| } |
| } // namespace |
| } // namespace clangd |
| } // namespace clang |