+
+TEST(AsyncIO, Cancel) {
+ constexpr size_t kNumOps = 10;
+
+ AsyncIO aioReader(kNumOps, AsyncIO::NOT_POLLABLE);
+ int fd = ::open(tempFile.path().c_str(), O_DIRECT | O_RDONLY);
+ PCHECK(fd != -1);
+ SCOPE_EXIT {
+ ::close(fd);
+ };
+
+ std::vector<AsyncIO::Op> ops(kNumOps);
+ std::vector<ManagedBuffer> bufs;
+
+ size_t completed = 0;
+ for (auto& op : ops) {
+ const size_t size = 2 * kAlign;
+ bufs.push_back(allocateAligned(size));
+ op.setNotificationCallback([&](AsyncIOOp*) { ++completed; });
+ op.pread(fd, bufs.back().get(), size, 0);
+ aioReader.submit(&op);
+ }
+
+ EXPECT_EQ(aioReader.pending(), kNumOps);
+ EXPECT_EQ(completed, 0);
+
+ {
+ auto result = aioReader.wait(1);
+ EXPECT_EQ(result.size(), 1);
+ }
+ EXPECT_EQ(completed, 1);
+ EXPECT_EQ(aioReader.pending(), kNumOps - 1);
+
+ EXPECT_EQ(aioReader.cancel(), kNumOps - 1);
+ EXPECT_EQ(aioReader.pending(), 0);
+ EXPECT_EQ(completed, 1);
+
+ completed = 0;
+ for (auto& op : ops) {
+ if (op.state() == AsyncIOOp::State::COMPLETED) {
+ ++completed;
+ } else {
+ EXPECT_TRUE(op.state() == AsyncIOOp::State::CANCELED) << op;
+ }
+ }
+ EXPECT_EQ(completed, 1);
+}