libuv-svace-build

Форк
0
/
test-stdio-over-pipes.c 
299 строк · 7.8 Кб
1
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
 *
3
 * Permission is hereby granted, free of charge, to any person obtaining a copy
4
 * of this software and associated documentation files (the "Software"), to
5
 * deal in the Software without restriction, including without limitation the
6
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
 * sell copies of the Software, and to permit persons to whom the Software is
8
 * furnished to do so, subject to the following conditions:
9
 *
10
 * The above copyright notice and this permission notice shall be included in
11
 * all copies or substantial portions of the Software.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
 * IN THE SOFTWARE.
20
 */
21

22
#include "uv.h"
23
#include "task.h"
24

25
#include <stdlib.h>
26
#include <string.h>
27

28

29
static char exepath[1024];
30
static size_t exepath_size = 1024;
31
static char* args[3];
32
static uv_process_options_t options;
33
static int close_cb_called;
34
static int exit_cb_called;
35
static int on_read_cb_called;
36
static int after_write_cb_called;
37
static uv_pipe_t in;
38
static uv_pipe_t out;
39
static uv_loop_t* loop;
40
#define OUTPUT_SIZE 1024
41
static char output[OUTPUT_SIZE];
42
static int output_used;
43

44

45
static void close_cb(uv_handle_t* handle) {
46
  close_cb_called++;
47
}
48

49

50
static void exit_cb(uv_process_t* process,
51
                    int64_t exit_status,
52
                    int term_signal) {
53
  printf("exit_cb\n");
54
  exit_cb_called++;
55
  ASSERT_OK(exit_status);
56
  ASSERT_OK(term_signal);
57
  uv_close((uv_handle_t*)process, close_cb);
58
  uv_close((uv_handle_t*)&in, close_cb);
59
  uv_close((uv_handle_t*)&out, close_cb);
60
}
61

62

63
static void init_process_options(char* test, uv_exit_cb exit_cb) {
64
  int r = uv_exepath(exepath, &exepath_size);
65
  ASSERT_OK(r);
66
  exepath[exepath_size] = '\0';
67
  args[0] = exepath;
68
  args[1] = test;
69
  args[2] = NULL;
70
  options.file = exepath;
71
  options.args = args;
72
  options.exit_cb = exit_cb;
73
}
74

75

76
static void on_alloc(uv_handle_t* handle,
77
                     size_t suggested_size,
78
                     uv_buf_t* buf) {
79
  buf->base = output + output_used;
80
  buf->len = OUTPUT_SIZE - output_used;
81
}
82

83

84
static void after_write(uv_write_t* req, int status) {
85
  if (status) {
86
    fprintf(stderr, "uv_write error: %s\n", uv_strerror(status));
87
    ASSERT(0);
88
  }
89

90
  /* Free the read/write buffer and the request */
91
  free(req);
92

93
  after_write_cb_called++;
94
}
95

96

97
static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* rdbuf) {
98
  uv_write_t* req;
99
  uv_buf_t wrbuf;
100
  int r;
101

102
  ASSERT(nread > 0 || nread == UV_EOF);
103

104
  if (nread > 0) {
105
    output_used += nread;
106
    if (output_used % 12 == 0) {
107
      ASSERT_OK(memcmp("hello world\n", output, 12));
108
      wrbuf = uv_buf_init(output, 12);
109
      req = malloc(sizeof(*req));
110
      r = uv_write(req, (uv_stream_t*) &in, &wrbuf, 1, after_write);
111
      ASSERT_OK(r);
112
    }
113
  }
114

115
  on_read_cb_called++;
116
}
117

118

119
static void test_stdio_over_pipes(int overlapped) {
120
  int r;
121
  uv_process_t process;
122
  uv_stdio_container_t stdio[3];
123

124
  loop = uv_default_loop();
125

126
  init_process_options("stdio_over_pipes_helper", exit_cb);
127

128
  uv_pipe_init(loop, &out, 0);
129
  uv_pipe_init(loop, &in, 0);
130

131
  options.stdio = stdio;
132
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE |
133
      (overlapped ?  UV_OVERLAPPED_PIPE : 0);
134
  options.stdio[0].data.stream = (uv_stream_t*) &in;
135
  options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE |
136
      (overlapped ? UV_OVERLAPPED_PIPE : 0);
137
  options.stdio[1].data.stream = (uv_stream_t*) &out;
138
  options.stdio[2].flags = UV_INHERIT_FD;
139
  options.stdio[2].data.fd = 2;
140
  options.stdio_count = 3;
141

142
  r = uv_spawn(loop, &process, &options);
143
  ASSERT_OK(r);
144

145
  r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
146
  ASSERT_OK(r);
147

148
  r = uv_run(loop, UV_RUN_DEFAULT);
149
  ASSERT_OK(r);
150

151
  ASSERT_GT(on_read_cb_called, 1);
152
  ASSERT_EQ(2, after_write_cb_called);
153
  ASSERT_EQ(1, exit_cb_called);
154
  ASSERT_EQ(3, close_cb_called);
155
  ASSERT_OK(memcmp("hello world\nhello world\n", output, 24));
156
  ASSERT_EQ(24, output_used);
157

158
  MAKE_VALGRIND_HAPPY(loop);
159
}
160

161
TEST_IMPL(stdio_over_pipes) {
162
  test_stdio_over_pipes(0);
163
  return 0;
164
}
165

166
TEST_IMPL(stdio_emulate_iocp) {
167
  test_stdio_over_pipes(1);
168
  return 0;
169
}
170

171

172
/* Everything here runs in a child process. */
173

174
static int on_pipe_read_called;
175
static int after_write_called;
176
static uv_pipe_t stdin_pipe1;
177
static uv_pipe_t stdout_pipe1;
178
static uv_pipe_t stdin_pipe2;
179
static uv_pipe_t stdout_pipe2;
180

181
static void on_pipe_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) {
182
  ASSERT_GT(nread, 0);
183
  ASSERT_OK(memcmp("hello world\n", buf->base, nread));
184
  on_pipe_read_called++;
185

186
  free(buf->base);
187

188
  uv_read_stop(pipe);
189
}
190

191

192
static void after_pipe_write(uv_write_t* req, int status) {
193
  ASSERT_OK(status);
194
  after_write_called++;
195
}
196

197

198
static void on_read_alloc(uv_handle_t* handle,
199
                          size_t suggested_size,
200
                          uv_buf_t* buf) {
201
  buf->base = malloc(suggested_size);
202
  buf->len = suggested_size;
203
}
204

205

206
int stdio_over_pipes_helper(void) {
207
  /* Write several buffers to test that the write order is preserved. */
208
  char* buffers[] = {
209
    "he",
210
    "ll",
211
    "o ",
212
    "wo",
213
    "rl",
214
    "d",
215
    "\n"
216
  };
217

218
  uv_write_t write_req[ARRAY_SIZE(buffers)];
219
  uv_buf_t buf[ARRAY_SIZE(buffers)];
220
  unsigned int i;
221
  int j;
222
  int r;
223
  uv_loop_t* loop = uv_default_loop();
224

225
  ASSERT_EQ(UV_NAMED_PIPE, uv_guess_handle(0));
226
  ASSERT_EQ(UV_NAMED_PIPE, uv_guess_handle(1));
227

228
  r = uv_pipe_init(loop, &stdin_pipe1, 0);
229
  ASSERT_OK(r);
230
  r = uv_pipe_init(loop, &stdout_pipe1, 0);
231
  ASSERT_OK(r);
232
  r = uv_pipe_init(loop, &stdin_pipe2, 0);
233
  ASSERT_OK(r);
234
  r = uv_pipe_init(loop, &stdout_pipe2, 0);
235
  ASSERT_OK(r);
236

237
  uv_pipe_open(&stdin_pipe1, 0);
238
  uv_pipe_open(&stdout_pipe1, 1);
239
  uv_pipe_open(&stdin_pipe2, 0);
240
  uv_pipe_open(&stdout_pipe2, 1);
241

242
  for (j = 0; j < 2; j++) {
243
    /* Unref both stdio handles to make sure that all writes complete. */
244
    uv_unref((uv_handle_t*) &stdin_pipe1);
245
    uv_unref((uv_handle_t*) &stdout_pipe1);
246
    uv_unref((uv_handle_t*) &stdin_pipe2);
247
    uv_unref((uv_handle_t*) &stdout_pipe2);
248

249
    for (i = 0; i < ARRAY_SIZE(buffers); i++) {
250
      buf[i] = uv_buf_init((char*) buffers[i], strlen(buffers[i]));
251
    }
252

253
    for (i = 0; i < ARRAY_SIZE(buffers); i++) {
254
      r = uv_write(&write_req[i],
255
                   (uv_stream_t*) (j == 0 ? &stdout_pipe1 : &stdout_pipe2),
256
                   &buf[i],
257
                   1,
258
                   after_pipe_write);
259
      ASSERT_OK(r);
260
    }
261

262
    notify_parent_process();
263
    uv_run(loop, UV_RUN_DEFAULT);
264

265
    ASSERT_EQ(after_write_called, 7 * (j + 1));
266
    ASSERT_EQ(on_pipe_read_called, j);
267
    ASSERT_OK(close_cb_called);
268

269
    uv_ref((uv_handle_t*) &stdout_pipe1);
270
    uv_ref((uv_handle_t*) &stdin_pipe1);
271
    uv_ref((uv_handle_t*) &stdout_pipe2);
272
    uv_ref((uv_handle_t*) &stdin_pipe2);
273

274
    r = uv_read_start((uv_stream_t*) (j == 0 ? &stdin_pipe1 : &stdin_pipe2),
275
                      on_read_alloc,
276
                      on_pipe_read);
277
    ASSERT_OK(r);
278

279
    uv_run(loop, UV_RUN_DEFAULT);
280

281
    ASSERT_EQ(after_write_called, 7 * (j + 1));
282
    ASSERT_EQ(on_pipe_read_called, j + 1);
283
    ASSERT_OK(close_cb_called);
284
  }
285

286
  uv_close((uv_handle_t*)&stdin_pipe1, close_cb);
287
  uv_close((uv_handle_t*)&stdout_pipe1, close_cb);
288
  uv_close((uv_handle_t*)&stdin_pipe2, close_cb);
289
  uv_close((uv_handle_t*)&stdout_pipe2, close_cb);
290

291
  uv_run(loop, UV_RUN_DEFAULT);
292

293
  ASSERT_EQ(14, after_write_called);
294
  ASSERT_EQ(2, on_pipe_read_called);
295
  ASSERT_EQ(4, close_cb_called);
296

297
  MAKE_VALGRIND_HAPPY(loop);
298
  return 0;
299
}
300

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.