test_generate.py 10 KB
Newer Older
1
from sbws import version
2
import sbws.core.generate
3
4
5
6
7
8
9
10
11
12
13
14
from sbws.util.config import get_config
from sbws.lib.resultdump import load_recent_results_in_datadir
from sbws.lib.resultdump import ResultSuccess
from statistics import median


def test_generate_no_dotsbws(tmpdir, parser, log):
    dotsbws = tmpdir
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws).split())
    conf = get_config(args, log.debug)
    try:
15
        sbws.core.generate.main(args, conf, log)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    except SystemExit as e:
        assert e.code == 1
    else:
        assert None, 'Should have failed'
    lines = [l for l in log.test_get_logged_lines()]
    assert 'Sbws isn\'t initialized' in lines[-1]


def test_generate_no_datadir(empty_dotsbws, parser, log):
    dotsbws = empty_dotsbws
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
    try:
30
        sbws.core.generate.main(args, conf, log)
31
32
33
34
35
    except SystemExit as e:
        assert e.code == 1
    else:
        assert None, 'Should have failed'
    lines = [l for l in log.test_get_logged_lines()]
36
    dd = conf['paths']['datadir']
37
38
39
40
41
42
43
44
45
46
    assert '{} does not exist'.format(dd) in lines[-1]


def test_generate_bad_scale_constant(empty_dotsbws_datadir, parser, log):
    dotsbws = empty_dotsbws_datadir
    args = parser.parse_args(
        '-d {} -vvvv generate --scale-constant -1'
        .format(dotsbws.name).split())
    conf = get_config(args, log.debug)
    try:
47
        sbws.core.generate.main(args, conf, log)
48
49
50
51
52
53
54
55
56
57
58
59
60
    except SystemExit as e:
        assert e.code == 1
    else:
        assert None, 'Should have failed'
    log_lines = [l for l in log.test_get_logged_lines()]
    assert '--scale-constant must be positive' == log_lines[-1]


def test_generate_empty_datadir(empty_dotsbws_datadir, parser, log):
    dotsbws = empty_dotsbws_datadir
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
61
    sbws.core.generate.main(args, conf, log)
62
63
64
65
66
67
68
69
70
    log_lines = [l for l in log.test_get_logged_lines()]
    assert 'No recent results' in log_lines[-1]


def test_generate_single_error(dotsbws_error_result, parser, log):
    dotsbws = dotsbws_error_result
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
71
    sbws.core.generate.main(args, conf, log)
72
    log_lines = [l for l in log.test_get_logged_lines()]
73
    dd = conf['paths']['datadir']
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    for line in log_lines:
        if 'Read 0 lines from {}'.format(dd) in line:
            break
    else:
        assert None, 'Unable to find log line indicating 0 success results '\
            'in data file'
    assert 'No recent results' in log_lines[-1]


def test_generate_single_success_noscale(dotsbws_success_result, parser, log,
                                         capfd):
    dotsbws = dotsbws_success_result
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
89
    sbws.core.generate.main(args, conf, log)
90
    dd = conf['paths']['datadir']
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    results = load_recent_results_in_datadir(
        1, dd, success_only=False, log_fn=log.debug)
    assert len(results) == 1, 'There should be one result in the datadir'
    result = results[0]
    assert isinstance(result, ResultSuccess), 'The one existing result '\
        'should be a success'
    captured = capfd.readouterr()
    stdout_lines = captured.out.strip().split('\n')
    assert len(stdout_lines) == 3

    # XXX: after mocking time, make sure first line is the current timestamp
    # assert stdout_lines[0] is current timestamp

    v = 'version={}'.format(version)
    assert stdout_lines[1] == v

    bw = round(median([dl['amount'] / dl['duration']
                       for dl in result.downloads]))
    rtt = median([round(r * 1000) for r in result.rtts])
110
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
111
112
113
114
115
116
117
118
119
120
        result.fingerprint, bw, result.nickname, rtt, round(result.time))
    assert stdout_lines[2] == bw_line


def test_generate_single_success_scale(dotsbws_success_result, parser, log,
                                       capfd):
    dotsbws = dotsbws_success_result
    args = parser.parse_args(
        '-d {} -vvvv generate --scale'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
121
    sbws.core.generate.main(args, conf, log)
122
    dd = conf['paths']['datadir']
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    results = load_recent_results_in_datadir(
        1, dd, success_only=False, log_fn=log.debug)
    assert len(results) == 1, 'There should be one result in the datadir'
    result = results[0]
    assert isinstance(result, ResultSuccess), 'The one existing result '\
        'should be a success'
    captured = capfd.readouterr()
    stdout_lines = captured.out.strip().split('\n')
    assert len(stdout_lines) == 3

    # XXX: after mocking time, make sure first line is the current timestamp
    # assert stdout_lines[0] is current timestamp

    v = 'version={}'.format(version)
    assert stdout_lines[1] == v

    bw = 7500
    rtt = median([round(r * 1000) for r in result.rtts])
141
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
142
143
        result.fingerprint, bw, result.nickname, rtt, round(result.time))
    assert stdout_lines[2] == bw_line
144
145
146
147
148
149
150
151


def test_generate_single_relay_success_noscale(
        dotsbws_success_result_one_relay, parser, log, capfd):
    dotsbws = dotsbws_success_result_one_relay
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
152
    sbws.core.generate.main(args, conf, log)
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    dd = conf['paths']['datadir']
    results = load_recent_results_in_datadir(
        1, dd, success_only=False, log_fn=log.debug)
    assert len(results) == 2, 'There should be two results in the datadir'
    for result in results:
        assert isinstance(result, ResultSuccess), 'All existing results '\
            'should be a success'
    captured = capfd.readouterr()
    stdout_lines = captured.out.strip().split('\n')
    assert len(stdout_lines) == 3

    # XXX: after mocking time, make sure first line is the current timestamp
    # assert stdout_lines[0] is current timestamp

    v = 'version={}'.format(version)
    assert stdout_lines[1] == v

    speeds = [dl['amount'] / dl['duration'] for r in results
              for dl in r.downloads]
    speed = round(median(speeds))
    rtt = round(median([round(r * 1000) for r in result.rtts]))
174
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
175
176
177
178
179
180
181
182
183
184
        result.fingerprint, speed, result.nickname, rtt, round(result.time))
    assert stdout_lines[2] == bw_line


def test_generate_single_relay_success_scale(
        dotsbws_success_result_one_relay, parser, log, capfd):
    dotsbws = dotsbws_success_result_one_relay
    args = parser.parse_args(
        '-d {} -vvvv generate --scale'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
185
    sbws.core.generate.main(args, conf, log)
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
    dd = conf['paths']['datadir']
    results = load_recent_results_in_datadir(
        1, dd, success_only=False, log_fn=log.debug)
    assert len(results) == 2, 'There should be two results in the datadir'
    for result in results:
        assert isinstance(result, ResultSuccess), 'All existing results '\
            'should be a success'
    captured = capfd.readouterr()
    stdout_lines = captured.out.strip().split('\n')
    assert len(stdout_lines) == 3

    # XXX: after mocking time, make sure first line is the current timestamp
    # assert stdout_lines[0] is current timestamp

    v = 'version={}'.format(version)
    assert stdout_lines[1] == v

    speed = 7500
    rtt = round(median([round(r * 1000) for r in result.rtts]))
205
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
206
207
208
209
210
211
212
213
214
215
        result.fingerprint, speed, result.nickname, rtt, round(result.time))
    assert stdout_lines[2] == bw_line


def test_generate_two_relays_success_noscale(
        dotsbws_success_result_two_relays, parser, log, capfd):
    dotsbws = dotsbws_success_result_two_relays
    args = parser.parse_args(
        '-d {} -vvvv generate'.format(dotsbws.name).split())
    conf = get_config(args, log.debug)
216
    sbws.core.generate.main(args, conf, log)
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
    dd = conf['paths']['datadir']
    results = load_recent_results_in_datadir(
        1, dd, success_only=False, log_fn=log.debug)
    assert len(results) == 4, 'There should be 4 results in the datadir'
    for result in results:
        assert isinstance(result, ResultSuccess), 'All existing results '\
            'should be a success'
    captured = capfd.readouterr()
    stdout_lines = captured.out.strip().split('\n')
    assert len(stdout_lines) == 4

    # XXX: after mocking time, make sure first line is the current timestamp
    # assert stdout_lines[0] is current timestamp

    v = 'version={}'.format(version)
    assert stdout_lines[1] == v

    r1_results = [r for r in results if r.fingerprint == 'A' * 40]
    r1_time = round(max([r.time for r in r1_results]))
    r1_name = r1_results[0].nickname
    r1_fingerprint = r1_results[0].fingerprint
    r1_speeds = [dl['amount'] / dl['duration'] for r in r1_results
                 for dl in r.downloads]
    r1_speed = round(median(r1_speeds))
    r1_rtt = round(median([round(rtt * 1000) for r in r1_results
                           for rtt in r.rtts]))
243
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
244
245
246
247
248
249
250
251
252
253
254
255
        r1_fingerprint, r1_speed, r1_name, r1_rtt, r1_time)
    assert stdout_lines[3] == bw_line

    r2_results = [r for r in results if r.fingerprint == 'B' * 40]
    r2_time = round(max([r.time for r in r2_results]))
    r2_name = r2_results[0].nickname
    r2_fingerprint = r2_results[0].fingerprint
    r2_speeds = [dl['amount'] / dl['duration'] for r in r2_results
                 for dl in r.downloads]
    r2_speed = round(median(r2_speeds))
    r2_rtt = round(median([round(rtt * 1000) for r in r2_results
                           for rtt in r.rtts]))
256
    bw_line = 'node_id=${} bw={} nick={} rtt={} time={}'.format(
257
258
        r2_fingerprint, r2_speed, r2_name, r2_rtt, r2_time)
    assert stdout_lines[2] == bw_line