libuv-svace-build

Форк
0
435 строк · 10.3 Кб
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 <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25

26
#include "runner.h"
27
#include "task.h"
28
#include "uv.h"
29

30
char executable_path[sizeof(executable_path)];
31

32

33
static int compare_task(const void* va, const void* vb) {
34
  const task_entry_t* a = va;
35
  const task_entry_t* b = vb;
36
  return strcmp(a->task_name, b->task_name);
37
}
38

39

40
char* fmt(char (*buf)[32], double d) {
41
  uint64_t v;
42
  char* p;
43

44
  p = &(*buf)[32];
45
  v = (uint64_t) d;
46

47
  *--p = '\0';
48

49
  if (v == 0)
50
    *--p = '0';
51

52
  while (v) {
53
    if (v) *--p = '0' + (v % 10), v /= 10;
54
    if (v) *--p = '0' + (v % 10), v /= 10;
55
    if (v) *--p = '0' + (v % 10), v /= 10;
56
    if (v) *--p = ',';
57
  }
58

59
  return p;
60
}
61

62

63
int run_tests(int benchmark_output) {
64
  int actual;
65
  int total;
66
  int failed;
67
  int current;
68
  int test_result;
69
  int skip;
70
  task_entry_t* task;
71

72
  /* Count the number of tests. */
73
  actual = 0;
74
  total = 0;
75
  for (task = TASKS; task->main; task++, actual++) {
76
    if (!task->is_helper) {
77
      total++;
78
    }
79
  }
80

81
  /* Keep platform_output first. */
82
  skip = (actual > 0 && 0 == strcmp(TASKS[0].task_name, "platform_output"));
83
  qsort(TASKS + skip, actual - skip, sizeof(TASKS[0]), compare_task);
84

85
  fprintf(stdout, "1..%d\n", total);
86
  fflush(stdout);
87

88
  /* Run all tests. */
89
  failed = 0;
90
  current = 1;
91
  for (task = TASKS; task->main; task++) {
92
    if (task->is_helper) {
93
      continue;
94
    }
95

96
    test_result = run_test(task->task_name, benchmark_output, current);
97
    switch (test_result) {
98
    case TEST_OK: break;
99
    case TEST_SKIP: break;
100
    default: failed++;
101
    }
102
    current++;
103
  }
104

105
  return failed;
106
}
107

108

109
void log_tap_result(int test_count,
110
                    const char* test,
111
                    int status,
112
                    process_info_t* process) {
113
  const char* result;
114
  const char* directive;
115
  char reason[1024];
116
  int reason_length;
117

118
  switch (status) {
119
  case TEST_OK:
120
    result = "ok";
121
    directive = "";
122
    break;
123
  case TEST_SKIP:
124
    result = "ok";
125
    directive = " # SKIP ";
126
    break;
127
  default:
128
    result = "not ok";
129
    directive = "";
130
  }
131

132
  if (status == TEST_SKIP && process_output_size(process) > 0) {
133
    process_read_last_line(process, reason, sizeof reason);
134
    reason_length = strlen(reason);
135
    if (reason_length > 0 && reason[reason_length - 1] == '\n')
136
      reason[reason_length - 1] = '\0';
137
  } else {
138
    reason[0] = '\0';
139
  }
140

141
  fprintf(stdout, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
142
  fflush(stdout);
143
}
144

145

146
int run_test(const char* test,
147
             int benchmark_output,
148
             int test_count) {
149
  char errmsg[1024] = "";
150
  process_info_t processes[1024];
151
  process_info_t *main_proc;
152
  task_entry_t* task;
153
  int timeout_multiplier;
154
  int process_count;
155
  int result;
156
  int status;
157
  int i;
158

159
  status = 255;
160
  main_proc = NULL;
161
  process_count = 0;
162

163
#ifndef _WIN32
164
  /* Clean up stale socket from previous run. */
165
  remove(TEST_PIPENAME);
166
  remove(TEST_PIPENAME_2);
167
  remove(TEST_PIPENAME_3);
168
#endif
169

170
  /* If it's a helper the user asks for, start it directly. */
171
  for (task = TASKS; task->main; task++) {
172
    if (task->is_helper && strcmp(test, task->process_name) == 0) {
173
      return task->main();
174
    }
175
  }
176

177
  /* Start the helpers first. */
178
  for (task = TASKS; task->main; task++) {
179
    if (strcmp(test, task->task_name) != 0) {
180
      continue;
181
    }
182

183
    /* Skip the test itself. */
184
    if (!task->is_helper) {
185
      continue;
186
    }
187

188
    if (process_start(task->task_name,
189
                      task->process_name,
190
                      &processes[process_count],
191
                      1 /* is_helper */) == -1) {
192
      snprintf(errmsg,
193
               sizeof errmsg,
194
               "Process `%s` failed to start.",
195
               task->process_name);
196
      goto out;
197
    }
198

199
    process_count++;
200
  }
201

202
  /* Now start the test itself. */
203
  for (task = TASKS; task->main; task++) {
204
    if (strcmp(test, task->task_name) != 0) {
205
      continue;
206
    }
207

208
    if (task->is_helper) {
209
      continue;
210
    }
211

212
    if (process_start(task->task_name,
213
                      task->process_name,
214
                      &processes[process_count],
215
                      0 /* !is_helper */) == -1) {
216
      snprintf(errmsg,
217
               sizeof errmsg,
218
               "Process `%s` failed to start.",
219
               task->process_name);
220
      goto out;
221
    }
222

223
    main_proc = &processes[process_count];
224
    process_count++;
225
    break;
226
  }
227

228
  if (main_proc == NULL) {
229
    snprintf(errmsg,
230
             sizeof errmsg,
231
             "No test with that name: %s",
232
             test);
233
    goto out;
234
  }
235

236
  timeout_multiplier = 1;
237
#ifndef _WIN32
238
  do {
239
    const char* var;
240

241
    var = getenv("UV_TEST_TIMEOUT_MULTIPLIER");
242
    if (var == NULL)
243
      break;
244

245
    timeout_multiplier = atoi(var);
246
    if (timeout_multiplier <= 0)
247
      timeout_multiplier = 1;
248
  } while (0);
249
#endif
250

251
  result = process_wait(main_proc, 1, task->timeout * timeout_multiplier);
252
  if (result == -1) {
253
    FATAL("process_wait failed");
254
  } else if (result == -2) {
255
    /* Don't have to clean up the process, process_wait() has killed it. */
256
    snprintf(errmsg,
257
             sizeof errmsg,
258
             "timeout");
259
    goto out;
260
  }
261

262
  status = process_reap(main_proc);
263
  if (status != TEST_OK) {
264
    snprintf(errmsg,
265
             sizeof errmsg,
266
             "exit code %d",
267
             status);
268
    goto out;
269
  }
270

271
  if (benchmark_output) {
272
    /* Give the helpers time to clean up their act. */
273
    uv_sleep(1000);
274
  }
275

276
out:
277
  /* Reap running processes except the main process, it's already dead. */
278
  for (i = 0; i < process_count - 1; i++) {
279
    process_terminate(&processes[i]);
280
  }
281

282
  if (process_count > 0 &&
283
      process_wait(processes, process_count - 1, -1) < 0) {
284
    FATAL("process_wait failed");
285
  }
286

287
  log_tap_result(test_count, test, status, &processes[i]);
288

289
  /* Show error and output from processes if the test failed. */
290
  if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) {
291
    if (strlen(errmsg) > 0)
292
      fprintf(stdout, "# %s\n", errmsg);
293
    fprintf(stdout, "# ");
294
    fflush(stdout);
295

296
    for (i = 0; i < process_count; i++) {
297
      switch (process_output_size(&processes[i])) {
298
       case -1:
299
        fprintf(stdout, "Output from process `%s`: (unavailable)\n",
300
                process_get_name(&processes[i]));
301
        fflush(stdout);
302
        break;
303

304
       case 0:
305
        fprintf(stdout, "Output from process `%s`: (no output)\n",
306
                process_get_name(&processes[i]));
307
        fflush(stdout);
308
        break;
309

310
       default:
311
        fprintf(stdout, "Output from process `%s`:\n", process_get_name(&processes[i]));
312
        fflush(stdout);
313
        process_copy_output(&processes[i], stdout);
314
        break;
315
      }
316
    }
317

318
  /* In benchmark mode show concise output from the main process. */
319
  } else if (benchmark_output) {
320
    switch (process_output_size(main_proc)) {
321
     case -1:
322
      fprintf(stdout, "%s: (unavailable)\n", test);
323
      fflush(stdout);
324
      break;
325

326
     case 0:
327
      fprintf(stdout, "%s: (no output)\n", test);
328
      fflush(stdout);
329
      break;
330

331
     default:
332
      for (i = 0; i < process_count; i++) {
333
        process_copy_output(&processes[i], stdout);
334
      }
335
      break;
336
    }
337
  }
338

339
  /* Clean up all process handles. */
340
  for (i = 0; i < process_count; i++) {
341
    process_cleanup(&processes[i]);
342
  }
343

344
  return status;
345
}
346

347

348
/* Returns the status code of the task part
349
 * or 255 if no matching task was not found.
350
 */
351
int run_test_part(const char* test, const char* part) {
352
  task_entry_t* task;
353
  int r;
354

355
  for (task = TASKS; task->main; task++) {
356
    if (strcmp(test, task->task_name) == 0 &&
357
        strcmp(part, task->process_name) == 0) {
358
      r = task->main();
359
      return r;
360
    }
361
  }
362

363
  fprintf(stdout, "No test part with that name: %s:%s\n", test, part);
364
  fflush(stdout);
365
  return 255;
366
}
367

368

369

370
static int find_helpers(const task_entry_t* task,
371
                        const task_entry_t** helpers) {
372
  const task_entry_t* helper;
373
  int n_helpers;
374

375
  for (n_helpers = 0, helper = TASKS; helper->main; helper++) {
376
    if (helper->is_helper && strcmp(helper->task_name, task->task_name) == 0) {
377
      *helpers++ = helper;
378
      n_helpers++;
379
    }
380
  }
381

382
  return n_helpers;
383
}
384

385

386
void print_tests(FILE* stream) {
387
  const task_entry_t* helpers[1024];
388
  const task_entry_t* task;
389
  int n_helpers;
390
  int n_tasks;
391
  int i;
392

393
  for (n_tasks = 0, task = TASKS; task->main; n_tasks++, task++);
394
  qsort(TASKS, n_tasks, sizeof(TASKS[0]), compare_task);
395

396
  for (task = TASKS; task->main; task++) {
397
    if (task->is_helper) {
398
      continue;
399
    }
400

401
    n_helpers = find_helpers(task, helpers);
402
    if (n_helpers) {
403
      printf("%-25s (helpers:", task->task_name);
404
      for (i = 0; i < n_helpers; i++) {
405
        printf(" %s", helpers[i]->process_name);
406
      }
407
      printf(")\n");
408
    } else {
409
      printf("%s\n", task->task_name);
410
    }
411
  }
412
}
413

414

415
void print_lines(const char* buffer, size_t size, FILE* stream) {
416
  const char* start;
417
  const char* end;
418

419
  start = buffer;
420
  while ((end = memchr(start, '\n', &buffer[size] - start))) {
421
    fputs("# ", stream);
422
    fwrite(start, 1, (int)(end - start), stream);
423
    fputs("\n", stream);
424
    fflush(stream);
425
    start = end + 1;
426
  }
427

428
  end = &buffer[size];
429
  if (start < end) {
430
    fputs("# ", stream);
431
    fwrite(start, 1, (int)(end - start), stream);
432
    fputs("\n", stream);
433
    fflush(stream);
434
  }
435
}
436

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

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

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

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