Skip to content

Commit dc8079f

Browse files
authoredJan 21, 2023
Merge pull request #48 from luavela/imun/gh-41-fix-test-lua-iprof
Fix flaky tests for instrumenting profiler
2 parents cf775b3 + 92918af commit dc8079f

File tree

1 file changed

+80
-4
lines changed

1 file changed

+80
-4
lines changed
 

Diff for: ‎tests/impl/uJIT-tests-C/suite/test_lua_iprof.c

+80-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,80 @@
44
* Copyright (C) 2015-2020 IPONWEB Ltd. See Copyright Notice in COPYRIGHT
55
*/
66

7+
#include <time.h>
78
#include <unistd.h>
89
#include "test_common_lua.h"
910

10-
#define EPSILON 1e-1
11+
#define EPSILON 1e-6
12+
13+
/* Clock emulation {{{ */
14+
15+
/*
16+
* We try to make the test less fragile by removing its dependence on the system
17+
* time by overriding <clock_gettime(3)> function. For this reason, clock mock
18+
* static counter is introduced and <clock_gettime> simply adds a jiffy to this
19+
* counter, normalizes .nsec and .sec fields of the mock and respectively sets
20+
* the value to the given struct timespec argument.
21+
*
22+
* According to jargon file (http://www.catb.org/~esr/jargon/html/J/jiffy.html):
23+
* | 1. The duration of one tick of the system clock on your computer. Often one
24+
* | AC cycle time (1/60 second in the U.S. and Canada, 1/50 most other
25+
* | places), but more recently 1/100 sec has become common. "The swapper
26+
* | runs every 6 jiffies" means that the virtual memory management routine
27+
* | is executed once for every 6 ticks of the clock, or about ten times a
28+
* | second.
29+
* | 2. Confusingly, the term is sometimes also used for a 1-millisecond wall
30+
* | time interval.
31+
* | 3. Even more confusingly, physicists semi-jokingly use 'jiffy' to mean the
32+
* | time required for light to travel one foot in a vacuum, which turns out
33+
* | to be close to one nanosecond. Other physicists use the term for the
34+
* | quantum-mechanical lower bound on meaningful time lengths.
35+
* | 4. Indeterminate time from a few seconds to forever. "I'll do it in a
36+
* | jiffy" means certainly not now and possibly never. This is a bit
37+
* | contrary to the more widespread use of the word. Oppose nano.
38+
*
39+
* Besides, there are several <sleep(3)> calls required in the test cases to
40+
* check whether "lua" and "wall" counters are calculated right. This function
41+
* is also overridden, considering how time is counted within this test: since
42+
* <sleep> receives the seconds as an argument, simply add the given amount of
43+
* seconds to the clock mock.
44+
*
45+
* Unfortunately, there is one flaw in such time mocking: these are not real
46+
* nanoseconds and seconds used in the clock mock, but just two types of
47+
* counters: short (for consecutive actions) and long (for interrupted actions).
48+
* Hence, we can't use some real jiffy value (i.e. the first one from the jargon
49+
* file), considering the cumulative discrepancy between linear mocked clock
50+
* behaviour and non-linear real clock behaviour.
51+
*
52+
* Considering everything above "physicists semi-joking" constant (i.e. 1 ns)
53+
* looks fine to be a jiffy in for a clock mock.
54+
*/
55+
#define JIFFY (1L)
56+
#define NSECNORM ((long)1e9)
57+
58+
static struct timespec clock_mock = {
59+
.tv_sec = 0,
60+
.tv_nsec = 0,
61+
};
62+
63+
extern int clock_gettime(clockid_t clockid, struct timespec *tp)
64+
{
65+
UNUSED(clockid);
66+
clock_mock.tv_nsec += JIFFY;
67+
clock_mock.tv_sec += clock_mock.tv_nsec / NSECNORM;
68+
clock_mock.tv_nsec = clock_mock.tv_nsec % NSECNORM;
69+
tp->tv_sec = clock_mock.tv_sec;
70+
tp->tv_nsec = clock_mock.tv_nsec;
71+
return 0;
72+
}
73+
74+
extern unsigned int sleep(unsigned int seconds)
75+
{
76+
clock_mock.tv_sec += seconds;
77+
return 0;
78+
}
79+
80+
/* }}} */
1181

1282
const char *ujit_iprof_profile =
1383
" return function (pfn, pcb, name, mode, level) "
@@ -298,12 +368,10 @@ unsigned int parent_iter = 5, parent_timeout = 1;
298368
const char *parent_name = "PARENT";
299369
const char *parent_chunk =
300370
" jit.off() "
301-
" local ffi = require 'ffi' "
302-
" ffi.cdef('unsigned int sleep(unsigned int seconds);') "
303371
" local parent = ujit.iprof.profile(function(iter, timeout) "
304372
" local coro = coroutine.create(function(n, t) "
305373
" for _ = 1, n do "
306-
" ffi.C.sleep(t) "
374+
" sleep(t) "
307375
" coroutine.yield() "
308376
" end "
309377
" end) "
@@ -314,6 +382,12 @@ const char *parent_chunk =
314382
" end, parent_cb, parent_name, ujit.iprof.PLAIN) "
315383
" parent(parent_iter, parent_timeout) ";
316384

385+
static int sleep_lua(lua_State *L)
386+
{
387+
sleep(luaL_checkint(L, 1));
388+
return 0;
389+
}
390+
317391
static int parent_cb(lua_State *L)
318392
{
319393
assert_report_table(L, parent_name);
@@ -340,6 +414,8 @@ static void test_parent(void **state)
340414
/* Check whether ujit.iprof.profile was not defined by luaL_openlibs */
341415
assert_ujit_iprof_profile(L);
342416

417+
/* Register function Lua C wrapper for sleep(3) function */
418+
lua_register(L, "sleep", sleep_lua);
343419
/* Register callback for reporting and entity name */
344420
lua_register(L, "parent_cb", parent_cb);
345421
lua_export(L, string, parent_name);

0 commit comments

Comments
 (0)
Please sign in to comment.