• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / test-run / 9780659958

03 Jul 2024 03:20PM UTC coverage: 62.565% (-0.04%) from 62.605%
9780659958

push

github

drewdzzz
ignore local lsn in wait_cluster_vclock

760 of 1566 branches covered (48.53%)

Branch coverage included in aggregate %.

2952 of 4367 relevant lines covered (67.6%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.53
/lib/utils.py
1
import errno
1✔
2
import os
1✔
3
import sys
1✔
4
import collections
1✔
5
import signal
1✔
6
import fcntl
1✔
7
import difflib
1✔
8
import time
1✔
9
import json
1✔
10
import subprocess
1✔
11
from lib.colorer import color_stdout
1✔
12

13
try:
1✔
14
    # Python3.5 or above
15
    from signal import Signals
1✔
16
except ImportError:
×
17
    # Python2
18
    Signals = None
×
19

20
try:
1✔
21
    # Python 3.3+.
22
    from shlex import quote as _shlex_quote
1✔
23
except ImportError:
×
24
    # Python 2.7.
25
    from pipes import quote as _shlex_quote
×
26

27
try:
1✔
28
    # Python 3.3+.
29
    from shutil import get_terminal_size
1✔
30
except ImportError:
×
31
    # Python 2.7.
32
    get_terminal_size = None
×
33

34
UNIX_SOCKET_LEN_LIMIT = 107
1✔
35

36
# Useful for very coarse version differentiation.
37
PY3 = sys.version_info[0] == 3
1✔
38
PY2 = sys.version_info[0] == 2
1✔
39

40
if PY2:
1!
41
    FileNotFoundError = IOError
×
42

43
if PY3:
1!
44
    string_types = str,
1✔
45
    integer_types = int,
1✔
46
else:
47
    string_types = basestring,      # noqa: F821
×
48
    integer_types = (int, long)     # noqa: F821
×
49

50

51
def check_libs():
1✔
52
    deps = [
1✔
53
        ('msgpack', 'msgpack-python'),
54
        ('tarantool', 'tarantool-python')
55
    ]
56
    base_path = os.path.dirname(os.path.abspath(__file__))
1✔
57

58
    for (mod_name, mod_dir) in deps:
1✔
59
        mod_path = os.path.join(base_path, mod_dir)
1✔
60
        if mod_path not in sys.path:
1!
61
            sys.path = [mod_path] + sys.path
1✔
62

63
    for (mod_name, _mod_dir) in deps:
1✔
64
        try:
1✔
65
            __import__(mod_name)
1✔
66
        except ImportError as e:
×
67
            color_stdout("\n\nNo %s library found\n" % mod_name,
×
68
                         schema='error')
69
            print(e)
×
70
            sys.exit(1)
×
71

72

73
def non_empty_valgrind_logs(paths_to_log):
1✔
74
    """ Check that there were no warnings in the log."""
75
    non_empty_logs = []
×
76
    for path_to_log in paths_to_log:
×
77
        if os.path.exists(path_to_log) and os.path.getsize(path_to_log) != 0:
×
78
            non_empty_logs.append(path_to_log)
×
79
    return non_empty_logs
×
80

81

82
def print_tail_n(filename, num_lines=None):
1✔
83
    """ Print N last lines of a file. If num_lines is not set,
84
    prints the whole file.
85
    """
86
    with open(filename, "r") as logfile:
×
87
        tail_n = collections.deque(logfile, num_lines)
×
88
        for line in tail_n:
×
89
            color_stdout(line, schema='tail')
×
90

91

92
def find_in_path(name):
1✔
93
    path = os.curdir + os.pathsep + os.environ["PATH"]
×
94
    for _dir in path.split(os.pathsep):
×
95
        exe = os.path.join(_dir, name)
×
96
        if os.access(exe, os.X_OK):
×
97
            return exe
×
98
    return ''
×
99

100

101
# http://stackoverflow.com/a/2549950
102
SIGNAMES = dict((int(v), k) for k, v in reversed(sorted(
1✔
103
    signal.__dict__.items())) if k.startswith('SIG') and
104
    not k.startswith('SIG_'))
105
SIGNUMS = dict((k, int(v)) for k, v in reversed(sorted(
1✔
106
    signal.__dict__.items())) if k.startswith('SIG') and
107
    not k.startswith('SIG_'))
108

109

110
def signame(signal):
1✔
111
    if isinstance(signal, integer_types):
1!
112
        return SIGNAMES[signal]
1✔
113
    if Signals and isinstance(signal, Signals):
×
114
        return SIGNAMES[int(signal)]
×
115
    if isinstance(signal, string_types):
×
116
        return signal
×
117
    raise TypeError('signame(): signal argument of unexpected type: {}'.format(
×
118
                    str(type(signal))))
119

120

121
def signum(signal):
1✔
122
    if isinstance(signal, integer_types):
×
123
        return signal
×
124
    if Signals and isinstance(signal, Signals):
×
125
        return int(signal)
×
126
    if isinstance(signal, string_types):
×
127
        if not signal.startswith('SIG'):
×
128
            signal = 'SIG' + signal
×
129
        return SIGNUMS[signal]
×
130
    raise TypeError('signum(): signal argument of unexpected type: {}'.format(
×
131
                    str(type(signal))))
132

133

134
def warn_unix_sockets_at_start(vardir):
1✔
135
    max_unix_socket_rel = '???_replication/autobootstrap_guest3.control'
1✔
136
    real_vardir = os.path.realpath(vardir)
1✔
137
    max_unix_socket_abs = os.path.join(real_vardir, max_unix_socket_rel)
1✔
138
    max_unix_socket_real = os.path.realpath(max_unix_socket_abs)
1✔
139
    if len(max_unix_socket_real) > UNIX_SOCKET_LEN_LIMIT:
1!
140
        color_stdout(
×
141
            'WARGING: unix sockets can become longer than %d symbols:\n'
142
            % UNIX_SOCKET_LEN_LIMIT,
143
            schema='error')
144
        color_stdout('WARNING: for example: "%s" has length %d\n' %
×
145
                     (max_unix_socket_real, len(max_unix_socket_real)),
146
                     schema='error')
147

148

149
def warn_unix_socket(path):
1✔
150
    real_path = os.path.realpath(path)
1✔
151
    if len(real_path) <= UNIX_SOCKET_LEN_LIMIT or \
1!
152
            real_path in warn_unix_socket.warned:
153
        return
1✔
154
    color_stdout(
×
155
        '\nWARGING: unix socket\'s "%s" path has length %d symbols that is '
156
        'longer than %d. That likely will cause failing of tests.\n' %
157
        (real_path, len(real_path), UNIX_SOCKET_LEN_LIMIT), schema='error')
158
    warn_unix_socket.warned.add(real_path)
×
159

160

161
warn_unix_socket.warned = set()
1✔
162

163

164
def safe_makedirs(directory):
1✔
165
    if os.path.isdir(directory):
1✔
166
        return
1✔
167
    # try-except to prevent races btw processes
168
    try:
1✔
169
        os.makedirs(directory)
1✔
170
    except OSError:
×
171
        pass
×
172

173

174
def format_process(pid):
1✔
175
    cmdline = 'unknown'
1✔
176
    try:
1✔
177
        with open('/proc/%d/cmdline' % pid, 'r') as f:
1✔
178
            cmdline = ' '.join(f.read().split('\0')).strip() or cmdline
1✔
179
    except (OSError, IOError):
1✔
180
        pass
1✔
181
    status = 'unknown'
1✔
182
    try:
1✔
183
        with open('/proc/%d/status' % pid, 'r') as f:
1✔
184
            for line in f:
1✔
185
                if ':' not in line:
1!
186
                    continue
×
187
                key, value = line.split(':', 1)
1✔
188
                if key == 'State':
1✔
189
                    status = value.strip()
1✔
190
    except (OSError, IOError):
1✔
191
        pass
1✔
192
    return 'process %d [%s; %s]' % (pid, status, cmdline)
1✔
193

194

195
def proc_stat_rss_supported():
1✔
196
    return os.path.isfile('/proc/%d/status' % os.getpid())
1✔
197

198

199
def get_proc_stat_rss(pid):
1✔
200
    rss = 0
1✔
201
    try:
1✔
202
        with open('/proc/%d/status' % pid, 'r') as f:
1✔
203
            for line in f:
1✔
204
                if ':' not in line:
1!
205
                    continue
×
206
                key, value = line.split(':', 1)
1✔
207
                if key == 'VmRSS':
1✔
208
                    rss = int(value.strip().split()[0])
1✔
209
    except (OSError, IOError):
×
210
        pass
×
211
    return rss
1✔
212

213

214
def set_fd_cloexec(socket):
1✔
215
    flags = fcntl.fcntl(socket, fcntl.F_GETFD)
1✔
216
    fcntl.fcntl(socket, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
1✔
217

218

219
def print_unidiff(filepath_a, filepath_b):
1✔
220
    def process_file(filepath):
×
221
        fh = None
×
222
        try:
×
223
            fh = open(filepath, 'r')
×
224
            lines = fh.readlines()
×
225
            ctime = time.ctime(os.stat(filepath).st_mtime)
×
226
        except Exception:
×
227
            if not os.path.exists(filepath):
×
228
                color_stdout('[File does not exist: {}]\n'.format(filepath),
×
229
                             schema='error')
230
            lines = []
×
231
            ctime = time.ctime()
×
232
        if fh:
×
233
            fh.close()
×
234
        return lines, ctime
×
235

236
    lines_a, time_a = process_file(filepath_a)
×
237
    lines_b, time_b = process_file(filepath_b)
×
238
    diff = difflib.unified_diff(lines_a,
×
239
                                lines_b,
240
                                filepath_a,
241
                                filepath_b,
242
                                time_a,
243
                                time_b)
244
    color_stdout.writeout_unidiff(diff)
×
245

246

247
def prefix_each_line(prefix, data):
1✔
248
    data = data.rstrip('\n')
1✔
249
    lines = [(line + '\n') for line in data.split('\n')]
1✔
250
    return prefix + prefix.join(lines)
1✔
251

252

253
def just_and_trim(src, width):
1✔
254
    if len(src) > width:
1✔
255
        return src[:width - 1] + '>'
1✔
256
    return src.ljust(width)
1✔
257

258

259
def xlog_rows(xlog_path):
1✔
260
    """ Parse xlog / snapshot file.
261

262
        Assume tarantool and tarantoolctl is in PATH.
263
    """
264
    if not os.path.exists(xlog_path):
1!
265
        raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), xlog_path)
×
266
    cmd = ['tarantoolctl', 'cat', xlog_path, '--format=json', '--show-system']
1✔
267
    with open(os.devnull, 'w') as devnull:
1✔
268
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=devnull)
1✔
269
    for line in process.stdout.readlines():
1!
270
        yield json.loads(bytes_to_str(line))
1✔
271

272

273
def extract_schema_from_snapshot(snapshot_path):
1✔
274
    """
275
    Extract schema version from snapshot.
276

277
    Assume tarantool and tarantoolctl is in PATH.
278

279
    Example of record:
280

281
     {
282
       "HEADER": {"lsn":2, "type": "INSERT", "timestamp": 1584694286.0031},
283
       "BODY": {"space_id": 272, "tuple": ["version", 2, 3, 1]}
284
     }
285

286
    :returns: (2, 3, 1)
287
    """
288
    BOX_SCHEMA_ID = 272
1✔
289
    for row in xlog_rows(snapshot_path):
1!
290
        if row['HEADER']['type'] == 'INSERT' and \
1!
291
           row['BODY']['space_id'] == BOX_SCHEMA_ID:
292
            res = row['BODY']['tuple']
1✔
293
            if res[0] == 'version':
1✔
294
                return tuple(res[1:])
1✔
295
    return None
×
296

297

298
def assert_bytes(b):
1✔
299
    """ Ensure given value is <bytes>.
300
    """
301
    if type(b) is not bytes:
1!
302
        raise ValueError('Internal error: expected {}, got {}: {}'.format(
×
303
            str(bytes), str(type(b)), repr(b)))
304

305

306
def assert_str(s):
1✔
307
    """ Ensure given value is <str>.
308
    """
309
    if type(s) is not str:
1!
310
        raise ValueError('Internal error: expected {}, got {}: {}'.format(
×
311
            str(str), str(type(s)), repr(s)))
312

313

314
def bytes_to_str(b):
1✔
315
    """ Convert <bytes> to <str>.
316

317
        No-op on Python 2.
318
    """
319
    assert_bytes(b)
1✔
320
    if PY2:
1!
321
        return b
×
322
    return b.decode('utf-8')
1✔
323

324

325
def str_to_bytes(s):
1✔
326
    """ Convert <str> to <bytes>.
327

328
        No-op on Python 2.
329
    """
330
    assert_str(s)
1✔
331
    if PY2:
1!
332
        return s
×
333
    return s.encode('utf-8')
1✔
334

335

336
def parse_tag_line(line):
1✔
337
    tags_str = line.split(':', 1)[1].strip()
×
338
    return [tag.strip() for tag in tags_str.split(',')]
×
339

340

341
def find_tags(filename):
1✔
342
    """ Extract tags from a first comment in the file.
343
    """
344
    # TODO: Support multiline comments. See exclude_tests() in
345
    # lib/server.py.
346
    if filename.endswith('.lua') or filename.endswith('.sql'):
×
347
        singleline_comment = '--'
×
348
    elif filename.endswith('.py'):
×
349
        singleline_comment = '#'
×
350
    else:
351
        return []
×
352

353
    tags = []
×
354
    with open(filename, 'r') as f:
×
355
        for line in f:
×
356
            line = line.rstrip('\n')
×
357
            if line.startswith('#!'):
×
358
                pass
×
359
            elif line == '':
×
360
                pass
×
361
            elif line.startswith(singleline_comment + ' tags:'):
×
362
                tags.extend(parse_tag_line(line))
×
363
            elif line.startswith(singleline_comment):
×
364
                pass
×
365
            else:
366
                break
×
367
    return tags
×
368

369

370
def prepend_path(p):
1✔
371
    """ Add an absolute path into PATH (at start) if it is not already there.
372
    """
373
    p = os.path.abspath(p)
1✔
374
    if p in os.environ['PATH'].split(os.pathsep):
1✔
375
        return
1✔
376
    os.environ['PATH'] = os.pathsep.join((p, os.environ['PATH']))
1✔
377

378

379
def shlex_quote(s):
1✔
380
    return _shlex_quote(s)
×
381

382

383
def terminal_columns():
1✔
384
    if get_terminal_size:
1!
385
        return get_terminal_size().columns
1✔
386
    return 80
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc