12
12
#include " lldb/Host/HostInfo.h"
13
13
#include " gtest/gtest.h"
14
14
15
+ #include < numeric>
16
+ #include < vector>
17
+
15
18
using namespace lldb_private ;
16
19
17
20
class PipeTest : public testing ::Test {
@@ -29,6 +32,8 @@ TEST_F(PipeTest, CreateWithUniqueName) {
29
32
llvm::Succeeded ());
30
33
}
31
34
35
+ // Test broken
36
+ #ifndef _WIN32
32
37
TEST_F (PipeTest, OpenAsReader) {
33
38
Pipe pipe;
34
39
llvm::SmallString<0 > name;
@@ -42,70 +47,95 @@ TEST_F(PipeTest, OpenAsReader) {
42
47
size_t name_len = name.size ();
43
48
name += " foobar" ;
44
49
llvm::StringRef name_ref (name.data (), name_len);
45
- // Note OpenAsReader() do nothing on Windows, the pipe is already opened for
46
- // read and write.
47
50
ASSERT_THAT_ERROR (
48
51
pipe.OpenAsReader (name_ref, /* child_process_inherit=*/ false ).ToError (),
49
52
llvm::Succeeded ());
50
53
51
54
ASSERT_TRUE (pipe.CanRead ());
52
55
}
56
+ #endif
53
57
54
58
TEST_F (PipeTest, WriteWithTimeout) {
55
59
Pipe pipe;
56
60
ASSERT_THAT_ERROR (pipe.CreateNew (false ).ToError (), llvm::Succeeded ());
57
61
// Note write_chunk_size must be less than the pipe buffer.
58
- // The pipe buffer is 1024 for PipeWindows and 4096 for PipePosix .
62
+ // The pipe buffer is 1024 for PipeWindows and at least 512 on Darwin .
59
63
const size_t buf_size = 8192 ;
60
- const size_t write_chunk_size = 256 ;
61
- const size_t read_chunk_size = 300 ;
62
- std::unique_ptr<int32_t []> write_buf_ptr (
63
- new int32_t [buf_size / sizeof (int32_t )]);
64
- int32_t *write_buf = write_buf_ptr.get ();
65
- std::unique_ptr<int32_t []> read_buf_ptr (
66
- new int32_t [(buf_size + 100 ) / sizeof (int32_t )]);
67
- int32_t *read_buf = read_buf_ptr.get ();
68
- for (int i = 0 ; i < buf_size / sizeof (int32_t ); ++i) {
69
- write_buf[i] = i;
70
- read_buf[i] = -i;
71
- }
64
+ const size_t write_chunk_size = 234 ;
72
65
73
- char *write_ptr = (char *)write_buf;
66
+ std::vector<int32_t > write_buf (buf_size / sizeof (int32_t ));
67
+ std::iota (write_buf.begin (), write_buf.end (), 0 );
68
+ std::vector<int32_t > read_buf (write_buf.size () + 100 , -1 );
69
+
70
+ char *write_ptr = (char *)&write_buf.front ();
71
+ char *read_ptr = (char *)&read_buf.front ();
74
72
size_t write_bytes = 0 ;
75
- char *read_ptr = (char *)read_buf;
76
73
size_t read_bytes = 0 ;
77
74
size_t num_bytes = 0 ;
78
- Status error;
75
+
76
+ // Write to the pipe until it is full.
79
77
while (write_bytes < buf_size) {
80
- error = pipe.WriteWithTimeout (write_ptr + write_bytes, write_chunk_size,
81
- std::chrono::milliseconds (10 ), num_bytes);
82
- if (error.Fail ()) {
83
- ASSERT_TRUE (read_bytes < buf_size);
84
- error = pipe.ReadWithTimeout (read_ptr + read_bytes, read_chunk_size,
85
- std::chrono::milliseconds (10 ), num_bytes);
86
- if (error.Fail ())
87
- FAIL ();
88
- else
89
- read_bytes += num_bytes;
90
- } else
91
- write_bytes += num_bytes;
92
- }
93
- // Read the rest data.
94
- while (read_bytes < buf_size) {
95
- error = pipe.ReadWithTimeout (read_ptr + read_bytes, buf_size - read_bytes,
96
- std::chrono::milliseconds (10 ), num_bytes);
78
+ Status error =
79
+ pipe.WriteWithTimeout (write_ptr + write_bytes, write_chunk_size,
80
+ std::chrono::milliseconds (10 ), num_bytes);
97
81
if (error.Fail ())
98
- FAIL ();
99
- else
100
- read_bytes += num_bytes;
82
+ break ; // The write buffer is full
83
+ write_bytes += num_bytes;
84
+ }
85
+ ASSERT_TRUE (write_bytes + write_chunk_size <= buf_size);
86
+
87
+ // Attempt a write with a long timeout.
88
+ auto start_time = std::chrono::steady_clock::now ();
89
+ ASSERT_THAT_ERROR (
90
+ pipe.WriteWithTimeout (write_ptr + write_bytes, write_chunk_size,
91
+ std::chrono::milliseconds (2000 ), num_bytes)
92
+ .ToError (),
93
+ llvm::Failed ());
94
+ auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(
95
+ std::chrono::steady_clock::now () - start_time)
96
+ .count ();
97
+ ASSERT_GE (dur, 2000 );
98
+
99
+ // Attempt a write with a short timeout
100
+ start_time = std::chrono::steady_clock::now ();
101
+ ASSERT_THAT_ERROR (
102
+ pipe.WriteWithTimeout (write_ptr + write_bytes, write_chunk_size,
103
+ std::chrono::milliseconds (200 ), num_bytes)
104
+ .ToError (),
105
+ llvm::Failed ());
106
+ dur = std::chrono::duration_cast<std::chrono::milliseconds>(
107
+ std::chrono::steady_clock::now () - start_time)
108
+ .count ();
109
+ ASSERT_GE (dur, 200 );
110
+ ASSERT_LT (dur, 300 );
111
+
112
+ // Drain the pipe
113
+ while (read_bytes < write_bytes) {
114
+ ASSERT_THAT_ERROR (
115
+ pipe.ReadWithTimeout (read_ptr + read_bytes, write_bytes - read_bytes,
116
+ std::chrono::milliseconds (10 ), num_bytes)
117
+ .ToError (),
118
+ llvm::Succeeded ());
119
+ read_bytes += num_bytes;
101
120
}
102
121
103
122
// Be sure the pipe is empty.
104
- error = pipe.ReadWithTimeout (read_ptr + read_bytes, 100 ,
105
- std::chrono::milliseconds (10 ), num_bytes);
106
- ASSERT_TRUE (error.Fail ());
123
+ ASSERT_THAT_ERROR (pipe.ReadWithTimeout (read_ptr + read_bytes, 100 ,
124
+ std::chrono::milliseconds (10 ),
125
+ num_bytes)
126
+ .ToError (),
127
+ llvm::Failed ());
107
128
108
- // Compare the data .
129
+ // Check that we got what we wrote .
109
130
ASSERT_EQ (write_bytes, read_bytes);
110
- ASSERT_EQ (memcmp (write_buf, read_buf, buf_size), 0 );
131
+ ASSERT_TRUE (std::equal (write_buf.begin (),
132
+ write_buf.begin () + write_bytes / sizeof (uint32_t ),
133
+ read_buf.begin ()));
134
+
135
+ // Write to the pipe again and check that it succeeds.
136
+ ASSERT_THAT_ERROR (pipe.WriteWithTimeout (write_ptr, write_chunk_size,
137
+ std::chrono::milliseconds (10 ),
138
+ num_bytes)
139
+ .ToError (),
140
+ llvm::Succeeded ());
111
141
}
0 commit comments