|
10 | 10 | #include "TestingSupport/SubsystemRAII.h" |
11 | 11 | #include "lldb/Host/FileSystem.h" |
12 | 12 | #include "lldb/Host/HostInfo.h" |
| 13 | +#include "llvm/Testing/Support/Error.h" |
13 | 14 | #include "gtest/gtest.h" |
| 15 | +#include <chrono> |
14 | 16 | #include <fcntl.h> |
15 | 17 | #include <numeric> |
| 18 | +#include <thread> |
16 | 19 | #include <vector> |
| 20 | +#include <future> |
17 | 21 |
|
18 | 22 | using namespace lldb_private; |
19 | 23 |
|
@@ -144,3 +148,52 @@ TEST_F(PipeTest, WriteWithTimeout) { |
144 | 148 | pipe.Write(write_ptr, write_chunk_size, std::chrono::milliseconds(10)), |
145 | 149 | llvm::Succeeded()); |
146 | 150 | } |
| 151 | + |
| 152 | +TEST_F(PipeTest, ReadWithTimeout) { |
| 153 | + Pipe pipe; |
| 154 | + ASSERT_THAT_ERROR(pipe.CreateNew(false).ToError(), llvm::Succeeded()); |
| 155 | + |
| 156 | + char buf[100]; |
| 157 | + // The pipe is initially empty. A polling read returns immediately. |
| 158 | + ASSERT_THAT_EXPECTED(pipe.Read(buf, sizeof(buf), std::chrono::seconds(0)), |
| 159 | + llvm::Failed()); |
| 160 | + |
| 161 | + // With a timeout, we should wait for at least this amount of time (but not |
| 162 | + // too much). |
| 163 | + auto start = std::chrono::steady_clock::now(); |
| 164 | + ASSERT_THAT_EXPECTED( |
| 165 | + pipe.Read(buf, sizeof(buf), std::chrono::milliseconds(200)), |
| 166 | + llvm::Failed()); |
| 167 | + auto dur = std::chrono::steady_clock::now() - start; |
| 168 | + EXPECT_GT(dur, std::chrono::milliseconds(200)); |
| 169 | + EXPECT_LT(dur, std::chrono::seconds(2)); |
| 170 | + |
| 171 | + // Write something into the pipe, and read it back. The blocking read call |
| 172 | + // should return even though it hasn't filled the buffer. |
| 173 | + llvm::StringRef hello_world("Hello world!"); |
| 174 | + ASSERT_THAT_EXPECTED(pipe.Write(hello_world.data(), hello_world.size()), |
| 175 | + llvm::HasValue(hello_world.size())); |
| 176 | + ASSERT_THAT_EXPECTED(pipe.Read(buf, sizeof(buf)), |
| 177 | + llvm::HasValue(hello_world.size())); |
| 178 | + EXPECT_EQ(llvm::StringRef(buf, hello_world.size()), hello_world); |
| 179 | + |
| 180 | + // Now write something and try to read it in chunks. |
| 181 | + memset(buf, 0, sizeof(buf)); |
| 182 | + ASSERT_THAT_EXPECTED(pipe.Write(hello_world.data(), hello_world.size()), |
| 183 | + llvm::HasValue(hello_world.size())); |
| 184 | + ASSERT_THAT_EXPECTED(pipe.Read(buf, 4), llvm::HasValue(4)); |
| 185 | + ASSERT_THAT_EXPECTED(pipe.Read(buf + 4, sizeof(buf) - 4), |
| 186 | + llvm::HasValue(hello_world.size() - 4)); |
| 187 | + EXPECT_EQ(llvm::StringRef(buf, hello_world.size()), hello_world); |
| 188 | + |
| 189 | + // A blocking read should wait until the data arrives. |
| 190 | + memset(buf, 0, sizeof(buf)); |
| 191 | + std::future<llvm::Expected<size_t>> future_num_bytes = std::async( |
| 192 | + std::launch::async, [&] { return pipe.Read(buf, sizeof(buf)); }); |
| 193 | + std::this_thread::sleep_for(std::chrono::seconds(1)); |
| 194 | + ASSERT_THAT_EXPECTED(pipe.Write(hello_world.data(), hello_world.size()), |
| 195 | + llvm::HasValue(hello_world.size())); |
| 196 | + ASSERT_THAT_EXPECTED(future_num_bytes.get(), |
| 197 | + llvm::HasValue(hello_world.size())); |
| 198 | + EXPECT_EQ(llvm::StringRef(buf, hello_world.size()), hello_world); |
| 199 | +} |
0 commit comments