libuv-svace-build
390 строк · 10.6 Кб
1/* Copyright libuv project 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#include <string.h> /* memset */25
26#define UV_NS_TO_MS 100000027
28typedef struct {29uv_fs_t open_req;30uv_fs_t write_req;31uv_fs_t close_req;32} fs_reqs_t;33
34static uint64_t last_events_count;35static char test_buf[] = "test-buffer\n";36static fs_reqs_t fs_reqs;37static int pool_events_counter;38
39
40static void timer_spin_cb(uv_timer_t* handle) {41uint64_t t;42
43(*(int*) handle->data)++;44t = uv_hrtime();45/* Spin for 500 ms to spin loop time out of the delta check. */46while (uv_hrtime() - t < 600 * UV_NS_TO_MS) { }47}
48
49
50TEST_IMPL(metrics_idle_time) {51#if defined(__OpenBSD__)52RETURN_SKIP("Test does not currently work in OpenBSD");53#endif54const uint64_t timeout = 1000;55uv_timer_t timer;56uint64_t idle_time;57int cntr;58
59cntr = 0;60timer.data = &cntr;61
62ASSERT_OK(uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME));63ASSERT_OK(uv_timer_init(uv_default_loop(), &timer));64ASSERT_OK(uv_timer_start(&timer, timer_spin_cb, timeout, 0));65
66ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));67ASSERT_GT(cntr, 0);68
69idle_time = uv_metrics_idle_time(uv_default_loop());70
71/* Permissive check that the idle time matches within the timeout ±500 ms. */72ASSERT_LE(idle_time, (timeout + 500) * UV_NS_TO_MS);73ASSERT_GE(idle_time, (timeout - 500) * UV_NS_TO_MS);74
75MAKE_VALGRIND_HAPPY(uv_default_loop());76return 0;77}
78
79
80static void metrics_routine_cb(void* arg) {81const uint64_t timeout = 1000;82uv_loop_t loop;83uv_timer_t timer;84uint64_t idle_time;85int cntr;86
87cntr = 0;88timer.data = &cntr;89
90ASSERT_OK(uv_loop_init(&loop));91ASSERT_OK(uv_loop_configure(&loop, UV_METRICS_IDLE_TIME));92ASSERT_OK(uv_timer_init(&loop, &timer));93ASSERT_OK(uv_timer_start(&timer, timer_spin_cb, timeout, 0));94
95ASSERT_OK(uv_run(&loop, UV_RUN_DEFAULT));96ASSERT_GT(cntr, 0);97
98idle_time = uv_metrics_idle_time(&loop);99
100/* Only checking that idle time is greater than the lower bound since there101* may have been thread contention, causing the event loop to be delayed in
102* the idle phase longer than expected.
103*/
104ASSERT_GE(idle_time, (timeout - 500) * UV_NS_TO_MS);105
106close_loop(&loop);107ASSERT_OK(uv_loop_close(&loop));108}
109
110
111TEST_IMPL(metrics_idle_time_thread) {112uv_thread_t threads[5];113int i;114
115for (i = 0; i < 5; i++) {116ASSERT_OK(uv_thread_create(&threads[i], metrics_routine_cb, NULL));117}118
119for (i = 0; i < 5; i++) {120uv_thread_join(&threads[i]);121}122
123return 0;124}
125
126
127static void timer_noop_cb(uv_timer_t* handle) {128(*(int*) handle->data)++;129}
130
131
132TEST_IMPL(metrics_idle_time_zero) {133uv_metrics_t metrics;134uv_timer_t timer;135int cntr;136
137cntr = 0;138timer.data = &cntr;139ASSERT_OK(uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME));140ASSERT_OK(uv_timer_init(uv_default_loop(), &timer));141ASSERT_OK(uv_timer_start(&timer, timer_noop_cb, 0, 0));142
143ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));144
145ASSERT_GT(cntr, 0);146ASSERT_OK(uv_metrics_idle_time(uv_default_loop()));147
148ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));149ASSERT_UINT64_EQ(cntr, metrics.loop_count);150
151MAKE_VALGRIND_HAPPY(uv_default_loop());152return 0;153}
154
155
156static void close_cb(uv_fs_t* req) {157uv_metrics_t metrics;158
159ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));160ASSERT_UINT64_EQ(3, metrics.loop_count);161ASSERT_UINT64_GT(metrics.events, last_events_count);162
163uv_fs_req_cleanup(req);164last_events_count = metrics.events;165}
166
167
168static void write_cb(uv_fs_t* req) {169uv_metrics_t metrics;170
171ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));172ASSERT_UINT64_EQ(2, metrics.loop_count);173ASSERT_UINT64_GT(metrics.events, last_events_count);174ASSERT_EQ(req->result, sizeof(test_buf));175
176uv_fs_req_cleanup(req);177last_events_count = metrics.events;178
179ASSERT_OK(uv_fs_close(uv_default_loop(),180&fs_reqs.close_req,181fs_reqs.open_req.result,182close_cb));183}
184
185
186static void create_cb(uv_fs_t* req) {187uv_metrics_t metrics;188
189ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));190/* Event count here is still 0 so not going to check. */191ASSERT_UINT64_EQ(1, metrics.loop_count);192ASSERT_GE(req->result, 0);193
194uv_fs_req_cleanup(req);195last_events_count = metrics.events;196
197uv_buf_t iov = uv_buf_init(test_buf, sizeof(test_buf));198ASSERT_OK(uv_fs_write(uv_default_loop(),199&fs_reqs.write_req,200req->result,201&iov,2021,2030,204write_cb));205}
206
207
208static void prepare_cb(uv_prepare_t* handle) {209uv_metrics_t metrics;210
211uv_prepare_stop(handle);212
213ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));214ASSERT_UINT64_EQ(0, metrics.loop_count);215ASSERT_UINT64_EQ(0, metrics.events);216
217ASSERT_OK(uv_fs_open(uv_default_loop(),218&fs_reqs.open_req,219"test_file",220UV_FS_O_WRONLY | UV_FS_O_CREAT, S_IRUSR | S_IWUSR,221create_cb));222}
223
224
225TEST_IMPL(metrics_info_check) {226uv_fs_t unlink_req;227uv_prepare_t prepare;228
229uv_fs_unlink(NULL, &unlink_req, "test_file", NULL);230uv_fs_req_cleanup(&unlink_req);231
232ASSERT_OK(uv_prepare_init(uv_default_loop(), &prepare));233ASSERT_OK(uv_prepare_start(&prepare, prepare_cb));234
235ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));236
237uv_fs_unlink(NULL, &unlink_req, "test_file", NULL);238uv_fs_req_cleanup(&unlink_req);239
240MAKE_VALGRIND_HAPPY(uv_default_loop());241return 0;242}
243
244
245static void fs_prepare_cb(uv_prepare_t* handle) {246uv_metrics_t metrics;247
248ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));249
250if (pool_events_counter == 1)251ASSERT_EQ(metrics.events, metrics.events_waiting);252
253if (pool_events_counter < 7)254return;255
256uv_prepare_stop(handle);257pool_events_counter = -42;258}
259
260
261static void fs_stat_cb(uv_fs_t* req) {262uv_fs_req_cleanup(req);263pool_events_counter++;264}
265
266
267static void fs_work_cb(uv_work_t* req) {268}
269
270
271static void fs_after_work_cb(uv_work_t* req, int status) {272free(req);273pool_events_counter++;274}
275
276
277static void fs_write_cb(uv_fs_t* req) {278uv_work_t* work1 = malloc(sizeof(*work1));279uv_work_t* work2 = malloc(sizeof(*work2));280pool_events_counter++;281
282uv_fs_req_cleanup(req);283
284ASSERT_OK(uv_queue_work(uv_default_loop(),285work1,286fs_work_cb,287fs_after_work_cb));288ASSERT_OK(uv_queue_work(uv_default_loop(),289work2,290fs_work_cb,291fs_after_work_cb));292}
293
294
295static void fs_random_cb(uv_random_t* req, int status, void* buf, size_t len) {296pool_events_counter++;297}
298
299
300static void fs_addrinfo_cb(uv_getaddrinfo_t* req,301int status,302struct addrinfo* res) {303uv_freeaddrinfo(req->addrinfo);304pool_events_counter++;305}
306
307
308TEST_IMPL(metrics_pool_events) {309uv_buf_t iov;310uv_fs_t open_req;311uv_fs_t stat1_req;312uv_fs_t stat2_req;313uv_fs_t unlink_req;314uv_fs_t write_req;315uv_getaddrinfo_t addrinfo_req;316uv_metrics_t metrics;317uv_prepare_t prepare;318uv_random_t random_req;319int fd;320char rdata;321
322ASSERT_OK(uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME));323
324uv_fs_unlink(NULL, &unlink_req, "test_file", NULL);325uv_fs_req_cleanup(&unlink_req);326
327ASSERT_OK(uv_prepare_init(uv_default_loop(), &prepare));328ASSERT_OK(uv_prepare_start(&prepare, fs_prepare_cb));329
330pool_events_counter = 0;331fd = uv_fs_open(NULL,332&open_req, "test_file", UV_FS_O_WRONLY | UV_FS_O_CREAT,333S_IRUSR | S_IWUSR,334NULL);335ASSERT_GT(fd, 0);336uv_fs_req_cleanup(&open_req);337
338iov = uv_buf_init(test_buf, sizeof(test_buf));339ASSERT_OK(uv_fs_write(uv_default_loop(),340&write_req,341fd,342&iov,3431,3440,345fs_write_cb));346ASSERT_OK(uv_fs_stat(uv_default_loop(),347&stat1_req,348"test_file",349fs_stat_cb));350ASSERT_OK(uv_fs_stat(uv_default_loop(),351&stat2_req,352"test_file",353fs_stat_cb));354ASSERT_OK(uv_random(uv_default_loop(),355&random_req,356&rdata,3571,3580,359fs_random_cb));360ASSERT_OK(uv_getaddrinfo(uv_default_loop(),361&addrinfo_req,362fs_addrinfo_cb,363"example.invalid",364NULL,365NULL));366
367/* Sleep for a moment to hopefully force the events to complete before368* entering the event loop. */
369uv_sleep(100);370
371ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));372
373ASSERT_OK(uv_metrics_info(uv_default_loop(), &metrics));374/* It's possible for uv__work_done() to execute one extra time even though the375* QUEUE has already been cleared out. This has to do with the way we use an
376* uv_async to tell the event loop thread to process the worker pool QUEUE. */
377ASSERT_GE(metrics.events, 7);378/* It's possible one of the other events also got stuck in the event queue, so379* check GE instead of EQ. Reason for 4 instead of 5 is because the call to
380* uv_getaddrinfo() is racey and slow. So can't guarantee that it'll always
381* execute before sleep completes. */
382ASSERT_GE(metrics.events_waiting, 4);383ASSERT_EQ(pool_events_counter, -42);384
385uv_fs_unlink(NULL, &unlink_req, "test_file", NULL);386uv_fs_req_cleanup(&unlink_req);387
388MAKE_VALGRIND_HAPPY(uv_default_loop());389return 0;390}
391