This is still flaky on our Windows on Arm bot: ******************** TEST 'lldb-unit :: Host/./HostTests.exe/8/10' FAILED ******************** Script(shard): -- GTEST_OUTPUT=json:C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Host\.\HostTests.exe-lldb-unit-3616-8-10.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=10 GTEST_SHARD_INDEX=8 C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Host\.\HostTests.exe -- Script: -- C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Host\.\HostTests.exe --gtest_filter=PipeTest.WriteWithTimeout -- C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Host\PipeTest.cpp(110): error: Expected: (dur) >= (std::chrono::seconds(2)), actual: 8-byte object <1C-A6 34-77 00-00 00-00> vs 8-byte object <02-00 00-00 00-00 00-00> C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Host\PipeTest.cpp:110 Expected: (dur) >= (std::chrono::seconds(2)), actual: 8-byte object <1C-A6 34-77 00-00 00-00> vs 8-byte object <02-00 00-00 00-00 00-00>
156 lines
5.6 KiB
C++
156 lines
5.6 KiB
C++
//===-- PipeTest.cpp ------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Host/Pipe.h"
|
|
#include "TestingSupport/SubsystemRAII.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "gtest/gtest.h"
|
|
#include <fcntl.h>
|
|
#include <numeric>
|
|
#include <vector>
|
|
|
|
using namespace lldb_private;
|
|
|
|
class PipeTest : public testing::Test {
|
|
public:
|
|
SubsystemRAII<FileSystem, HostInfo> subsystems;
|
|
};
|
|
|
|
TEST_F(PipeTest, CreateWithUniqueName) {
|
|
Pipe pipe;
|
|
llvm::SmallString<0> name;
|
|
ASSERT_THAT_ERROR(pipe.CreateWithUniqueName("PipeTest-CreateWithUniqueName",
|
|
/*child_process_inherit=*/false,
|
|
name)
|
|
.ToError(),
|
|
llvm::Succeeded());
|
|
}
|
|
|
|
// Test broken
|
|
#ifndef _WIN32
|
|
TEST_F(PipeTest, OpenAsReader) {
|
|
Pipe pipe;
|
|
llvm::SmallString<0> name;
|
|
ASSERT_THAT_ERROR(pipe.CreateWithUniqueName("PipeTest-OpenAsReader",
|
|
/*child_process_inherit=*/false,
|
|
name)
|
|
.ToError(),
|
|
llvm::Succeeded());
|
|
|
|
// Ensure name is not null-terminated
|
|
size_t name_len = name.size();
|
|
name += "foobar";
|
|
llvm::StringRef name_ref(name.data(), name_len);
|
|
ASSERT_THAT_ERROR(
|
|
pipe.OpenAsReader(name_ref, /*child_process_inherit=*/false).ToError(),
|
|
llvm::Succeeded());
|
|
|
|
ASSERT_TRUE(pipe.CanRead());
|
|
}
|
|
#endif
|
|
|
|
// This test is flaky on Windows on Arm.
|
|
#ifndef _WIN32
|
|
TEST_F(PipeTest, WriteWithTimeout) {
|
|
Pipe pipe;
|
|
ASSERT_THAT_ERROR(pipe.CreateNew(false).ToError(), llvm::Succeeded());
|
|
|
|
// The pipe buffer is 1024 for PipeWindows and at least 512 on Darwin.
|
|
// In Linux versions before 2.6.11, the capacity of a pipe was the same as the
|
|
// system page size (e.g., 4096 bytes on i386).
|
|
// Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes in a
|
|
// system with a page size of 4096 bytes).
|
|
// Since Linux 2.6.35, the default pipe capacity is 16 pages, but the capacity
|
|
// can be queried and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ
|
|
// operations:
|
|
|
|
#if !defined(_WIN32) && defined(F_SETPIPE_SZ)
|
|
::fcntl(pipe.GetWriteFileDescriptor(), F_SETPIPE_SZ, 4096);
|
|
#endif
|
|
|
|
const size_t buf_size = 66000;
|
|
|
|
// Note write_chunk_size must be less than the pipe buffer.
|
|
const size_t write_chunk_size = 234;
|
|
|
|
std::vector<int32_t> write_buf(buf_size / sizeof(int32_t));
|
|
std::iota(write_buf.begin(), write_buf.end(), 0);
|
|
std::vector<int32_t> read_buf(write_buf.size() + 100, -1);
|
|
|
|
char *write_ptr = reinterpret_cast<char *>(write_buf.data());
|
|
char *read_ptr = reinterpret_cast<char *>(read_buf.data());
|
|
size_t write_bytes = 0;
|
|
size_t read_bytes = 0;
|
|
size_t num_bytes = 0;
|
|
|
|
// Write to the pipe until it is full.
|
|
while (write_bytes + write_chunk_size <= buf_size) {
|
|
Status error =
|
|
pipe.WriteWithTimeout(write_ptr + write_bytes, write_chunk_size,
|
|
std::chrono::milliseconds(10), num_bytes);
|
|
if (error.Fail())
|
|
break; // The write buffer is full.
|
|
write_bytes += num_bytes;
|
|
}
|
|
ASSERT_LE(write_bytes + write_chunk_size, buf_size)
|
|
<< "Pipe buffer larger than expected";
|
|
|
|
// Attempt a write with a long timeout.
|
|
auto start_time = std::chrono::steady_clock::now();
|
|
ASSERT_THAT_ERROR(pipe.WriteWithTimeout(write_ptr + write_bytes,
|
|
write_chunk_size,
|
|
std::chrono::seconds(2), num_bytes)
|
|
.ToError(),
|
|
llvm::Failed());
|
|
auto dur = std::chrono::steady_clock::now() - start_time;
|
|
ASSERT_GE(dur, std::chrono::seconds(2));
|
|
|
|
// Attempt a write with a short timeout.
|
|
start_time = std::chrono::steady_clock::now();
|
|
ASSERT_THAT_ERROR(
|
|
pipe.WriteWithTimeout(write_ptr + write_bytes, write_chunk_size,
|
|
std::chrono::milliseconds(200), num_bytes)
|
|
.ToError(),
|
|
llvm::Failed());
|
|
dur = std::chrono::steady_clock::now() - start_time;
|
|
ASSERT_GE(dur, std::chrono::milliseconds(200));
|
|
ASSERT_LT(dur, std::chrono::seconds(2));
|
|
|
|
// Drain the pipe.
|
|
while (read_bytes < write_bytes) {
|
|
ASSERT_THAT_ERROR(
|
|
pipe.ReadWithTimeout(read_ptr + read_bytes, write_bytes - read_bytes,
|
|
std::chrono::milliseconds(10), num_bytes)
|
|
.ToError(),
|
|
llvm::Succeeded());
|
|
read_bytes += num_bytes;
|
|
}
|
|
|
|
// Be sure the pipe is empty.
|
|
ASSERT_THAT_ERROR(pipe.ReadWithTimeout(read_ptr + read_bytes, 100,
|
|
std::chrono::milliseconds(10),
|
|
num_bytes)
|
|
.ToError(),
|
|
llvm::Failed());
|
|
|
|
// Check that we got what we wrote.
|
|
ASSERT_EQ(write_bytes, read_bytes);
|
|
ASSERT_TRUE(std::equal(write_buf.begin(),
|
|
write_buf.begin() + write_bytes / sizeof(uint32_t),
|
|
read_buf.begin()));
|
|
|
|
// Write to the pipe again and check that it succeeds.
|
|
ASSERT_THAT_ERROR(pipe.WriteWithTimeout(write_ptr, write_chunk_size,
|
|
std::chrono::milliseconds(10),
|
|
num_bytes)
|
|
.ToError(),
|
|
llvm::Succeeded());
|
|
}
|
|
#endif /*ifndef _WIN32*/
|