diff options
Diffstat (limited to 'src/integration-tests/gnunet_testing.py.in')
-rw-r--r-- | src/integration-tests/gnunet_testing.py.in | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/src/integration-tests/gnunet_testing.py.in b/src/integration-tests/gnunet_testing.py.in deleted file mode 100644 index 828f6ff42..000000000 --- a/src/integration-tests/gnunet_testing.py.in +++ /dev/null | |||
@@ -1,381 +0,0 @@ | |||
1 | #!@PYTHONEXE@ | ||
2 | # This file is part of GNUnet. | ||
3 | # (C) 2010, 2017, 2018 Christian Grothoff (and other contributing authors) | ||
4 | # | ||
5 | # GNUnet is free software: you can redistribute it and/or modify it | ||
6 | # under the terms of the GNU Affero General Public License as published | ||
7 | # by the Free Software Foundation, either version 3 of the License, | ||
8 | # or (at your option) any later version. | ||
9 | # | ||
10 | # GNUnet is distributed in the hope that it will be useful, but | ||
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | # Affero General Public License for more details. | ||
14 | # | ||
15 | # You should have received a copy of the GNU Affero General Public License | ||
16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | # | ||
18 | # SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | # | ||
20 | # Functions for integration testing | ||
21 | |||
22 | import os | ||
23 | import subprocess | ||
24 | import sys | ||
25 | import shutil | ||
26 | import time | ||
27 | from gnunet_pyexpect import pexpect | ||
28 | import logging | ||
29 | |||
30 | logger = logging.getLogger() | ||
31 | handler = logging.StreamHandler() | ||
32 | formatter = logging.Formatter( | ||
33 | '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' | ||
34 | ) | ||
35 | handler.setFormatter(formatter) | ||
36 | logger.addHandler(handler) | ||
37 | logger.setLevel(logging.DEBUG) | ||
38 | |||
39 | |||
40 | class Check(object): | ||
41 | def __init__(self, test): | ||
42 | self.fulfilled = False | ||
43 | self.conditions = list() | ||
44 | self.test = test | ||
45 | |||
46 | def add(self, condition): | ||
47 | self.conditions.append(condition) | ||
48 | |||
49 | def run(self): | ||
50 | fulfilled = True | ||
51 | pos = 0 | ||
52 | neg = 0 | ||
53 | for c in self.conditions: | ||
54 | if (False == c.check()): | ||
55 | fulfilled = False | ||
56 | neg += 1 | ||
57 | else: | ||
58 | pos += 1 | ||
59 | return fulfilled | ||
60 | |||
61 | def run_blocking(self, timeout, pos_cont, neg_cont): | ||
62 | execs = 0 | ||
63 | res = False | ||
64 | while ((False == res) and (execs < timeout)): | ||
65 | res = self.run() | ||
66 | time.sleep(1) | ||
67 | execs += 1 | ||
68 | if ((False == res) and (execs >= timeout)): | ||
69 | logger.debug('Check had timeout after %s seconds', str(timeout)) | ||
70 | neg_cont(self) | ||
71 | elif ((False == res) and (execs < timeout)): | ||
72 | if (None != neg_cont): | ||
73 | neg_cont(self) | ||
74 | else: | ||
75 | if (None != pos_cont): | ||
76 | pos_cont(self) | ||
77 | return res | ||
78 | |||
79 | def run_once(self, pos_cont, neg_cont): | ||
80 | execs = 0 | ||
81 | res = False | ||
82 | res = self.run() | ||
83 | if ((res == False) and (neg_cont != None)): | ||
84 | neg_cont(self) | ||
85 | if ((res == True) and (pos_cont != None)): | ||
86 | pos_cont(self) | ||
87 | return res | ||
88 | |||
89 | def evaluate(self, failed_only): | ||
90 | pos = 0 | ||
91 | neg = 0 | ||
92 | for c in self.conditions: | ||
93 | if (False == c.evaluate(failed_only)): | ||
94 | neg += 1 | ||
95 | else: | ||
96 | pos += 1 | ||
97 | logger.debug( | ||
98 | '%s out of %s conditions fulfilled', str(pos), str(pos + neg) | ||
99 | ) | ||
100 | return self.fulfilled | ||
101 | |||
102 | def reset(self): | ||
103 | self.fulfilled = False | ||
104 | for c in self.conditions: | ||
105 | c.fulfilled = False | ||
106 | |||
107 | |||
108 | class Condition(object): | ||
109 | def __init__(self): | ||
110 | self.fulfilled = False | ||
111 | self.type = 'generic' | ||
112 | |||
113 | def __init__(self, type): | ||
114 | self.fulfilled = False | ||
115 | self.type = type | ||
116 | |||
117 | def check(self): | ||
118 | return False | ||
119 | |||
120 | def evaluate(self, failed_only): | ||
121 | if ((self.fulfilled == False) and (failed_only == True)): | ||
122 | logger.debug( | ||
123 | '%s condition for was %s', str(self.type), str(self.fulfilled) | ||
124 | ) | ||
125 | elif (failed_only == False): | ||
126 | logger.debug( | ||
127 | '%s condition for was %s', str(self.type), str(self.fulfilled) | ||
128 | ) | ||
129 | return self.fulfilled | ||
130 | |||
131 | |||
132 | class FileExistCondition(Condition): | ||
133 | def __init__(self, file): | ||
134 | self.fulfilled = False | ||
135 | self.type = 'file' | ||
136 | self.file = file | ||
137 | |||
138 | def check(self): | ||
139 | if (self.fulfilled == False): | ||
140 | res = os.path.isfile(self.file) | ||
141 | if (res == True): | ||
142 | self.fulfilled = True | ||
143 | return True | ||
144 | else: | ||
145 | return False | ||
146 | else: | ||
147 | return True | ||
148 | |||
149 | def evaluate(self, failed_only): | ||
150 | if ((self.fulfilled == False) and (failed_only == True)): | ||
151 | logger.debug( | ||
152 | '%s confition for file %s was %s', str(self.type), self.file, | ||
153 | str(self.fulfilled) | ||
154 | ) | ||
155 | elif (failed_only == False): | ||
156 | logger.debug( | ||
157 | '%s confition for file %s was %s', str(self.type), self.file, | ||
158 | str(self.fulfilled) | ||
159 | ) | ||
160 | return self.fulfilled | ||
161 | |||
162 | |||
163 | class StatisticsCondition(Condition): | ||
164 | def __init__(self, peer, subsystem, name, value): | ||
165 | self.fulfilled = False | ||
166 | self.type = 'statistics' | ||
167 | self.peer = peer | ||
168 | self.subsystem = subsystem | ||
169 | self.name = name | ||
170 | self.value = str(value) | ||
171 | self.result = -1 | ||
172 | |||
173 | def check(self): | ||
174 | if (self.fulfilled == False): | ||
175 | self.result = self.peer.get_statistics_value( | ||
176 | self.subsystem, self.name | ||
177 | ) | ||
178 | if (self.result == self.value): | ||
179 | self.fulfilled = True | ||
180 | return True | ||
181 | else: | ||
182 | return False | ||
183 | else: | ||
184 | return True | ||
185 | |||
186 | def evaluate(self, failed_only): | ||
187 | if (self.fulfilled == False): | ||
188 | fail = " FAIL!" | ||
189 | op = " != " | ||
190 | else: | ||
191 | fail = "" | ||
192 | op = " == " | ||
193 | if (((self.fulfilled == False) and (failed_only == True)) | ||
194 | or (failed_only == False)): | ||
195 | logger.debug( | ||
196 | '%s %s condition in subsystem %s: %s: (expected/real value) %s %s %s %s', | ||
197 | self.peer.id[:4].decode("utf-8"), self.peer.cfg, | ||
198 | self.subsystem.ljust(12), self.name.ljust(30), self.value, op, | ||
199 | self.result, fail | ||
200 | ) | ||
201 | return self.fulfilled | ||
202 | |||
203 | |||
204 | # Specify two statistic values and check if they are equal | ||
205 | class EqualStatisticsCondition(Condition): | ||
206 | def __init__(self, peer, subsystem, name, peer2, subsystem2, name2): | ||
207 | self.fulfilled = False | ||
208 | self.type = 'equalstatistics' | ||
209 | self.peer = peer | ||
210 | self.subsystem = subsystem | ||
211 | self.name = name | ||
212 | self.result = -1 | ||
213 | self.peer2 = peer2 | ||
214 | self.subsystem2 = subsystem2 | ||
215 | self.name2 = name2 | ||
216 | self.result2 = -1 | ||
217 | |||
218 | def check(self): | ||
219 | if (self.fulfilled == False): | ||
220 | self.result = self.peer.get_statistics_value( | ||
221 | self.subsystem, self.name | ||
222 | ) | ||
223 | self.result2 = self.peer2.get_statistics_value( | ||
224 | self.subsystem2, self.name2 | ||
225 | ) | ||
226 | if (self.result == self.result2): | ||
227 | self.fulfilled = True | ||
228 | return True | ||
229 | else: | ||
230 | return False | ||
231 | else: | ||
232 | return True | ||
233 | |||
234 | def evaluate(self, failed_only): | ||
235 | if (((self.fulfilled == False) and (failed_only == True)) | ||
236 | or (failed_only == False)): | ||
237 | logger.debug( | ||
238 | '%s %s %s == %s %s %s %s %s', self.peer.id[:4], | ||
239 | self.subsystem.ljust(12), self.name.ljust(30), self.result, | ||
240 | self.peer2.id[:4], self.subsystem2.ljust(12), | ||
241 | self.name2.ljust(30), self.result2 | ||
242 | ) | ||
243 | return self.fulfilled | ||
244 | |||
245 | |||
246 | class Test(object): | ||
247 | def __init__(self, testname, verbose): | ||
248 | self.peers = list() | ||
249 | self.verbose = verbose | ||
250 | self.name = testname | ||
251 | srcdir = "../.." | ||
252 | gnunet_pyexpect_dir = os.path.join(srcdir, "contrib/scripts") | ||
253 | if gnunet_pyexpect_dir not in sys.path: | ||
254 | sys.path.append(gnunet_pyexpect_dir) | ||
255 | self.gnunetarm = '' | ||
256 | self.gnunetstatistics = '' | ||
257 | if os.name == 'posix': | ||
258 | self.gnunetarm = 'gnunet-arm' | ||
259 | self.gnunetstatistics = 'gnunet-statistics' | ||
260 | self.gnunetpeerinfo = 'gnunet-peerinfo' | ||
261 | elif os.name == 'nt': | ||
262 | self.gnunetarm = 'gnunet-arm.exe' | ||
263 | self.gnunetstatistics = 'gnunet-statistics.exe' | ||
264 | self.gnunetpeerinfo = 'gnunet-peerinfo.exe' | ||
265 | if os.name == "nt": | ||
266 | shutil.rmtree(os.path.join(os.getenv("TEMP"), testname), True) | ||
267 | else: | ||
268 | shutil.rmtree("/tmp/" + testname, True) | ||
269 | |||
270 | def add_peer(self, peer): | ||
271 | self.peers.append(peer) | ||
272 | |||
273 | def p(self, msg): | ||
274 | if (self.verbose == True): | ||
275 | print(msg) | ||
276 | |||
277 | |||
278 | class Peer(object): | ||
279 | def __init__(self, test, cfg_file): | ||
280 | if (False == os.path.isfile(cfg_file)): | ||
281 | # print(("Peer cfg " + cfg_file + ": FILE NOT FOUND")) | ||
282 | logger.debug('Peer cfg %s : FILE NOT FOUND', cfg_file) | ||
283 | self.id = "<NaN>" | ||
284 | self.test = test | ||
285 | self.started = False | ||
286 | self.cfg = cfg_file | ||
287 | |||
288 | def __del__(self): | ||
289 | if (self.started == True): | ||
290 | # print('ERROR! Peer using cfg ' + self.cfg + ' was not stopped') | ||
291 | logger.debug('ERROR! Peer using cfg %s was not stopped', self.cfg) | ||
292 | ret = self.stop() | ||
293 | if (False == ret): | ||
294 | # print('ERROR! Peer using cfg ' + | ||
295 | # self.cfg + | ||
296 | # ' could not be stopped') | ||
297 | logger.debug( | ||
298 | 'ERROR! Peer using cfg %s could not be stopped', self.cfg | ||
299 | ) | ||
300 | self.started = False | ||
301 | return ret | ||
302 | else: | ||
303 | return False | ||
304 | |||
305 | def start(self): | ||
306 | os.unsetenv("XDG_CONFIG_HOME") | ||
307 | os.unsetenv("XDG_DATA_HOME") | ||
308 | os.unsetenv("XDG_CACHE_HOME") | ||
309 | self.test.p("Starting peer using cfg " + self.cfg) | ||
310 | try: | ||
311 | server = subprocess.Popen([ | ||
312 | self.test.gnunetarm, '-sq', '-c', self.cfg | ||
313 | ]) | ||
314 | server.communicate() | ||
315 | except OSError: | ||
316 | # print("Can not start peer") | ||
317 | logger.debug('Can not start peer') | ||
318 | self.started = False | ||
319 | return False | ||
320 | self.started = True | ||
321 | test = '' | ||
322 | try: | ||
323 | server = pexpect() | ||
324 | server.spawn( | ||
325 | None, [self.test.gnunetpeerinfo, '-c', self.cfg, '-s'], | ||
326 | stdout=subprocess.PIPE, | ||
327 | stderr=subprocess.STDOUT | ||
328 | ) | ||
329 | test = server.read("stdout", 1024) | ||
330 | except OSError: | ||
331 | # print("Can not get peer identity") | ||
332 | logger.debug('Can not get peer identity') | ||
333 | test = (test.split(b'`')[1]) | ||
334 | self.id = test.split(b'\'')[0] | ||
335 | return True | ||
336 | |||
337 | def stop(self): | ||
338 | if (self.started == False): | ||
339 | return False | ||
340 | self.test.p("Stopping peer using cfg " + self.cfg) | ||
341 | try: | ||
342 | server = subprocess.Popen([ | ||
343 | self.test.gnunetarm, '-eq', '-c', self.cfg | ||
344 | ]) | ||
345 | server.communicate() | ||
346 | except OSError: | ||
347 | # print("Can not stop peer") | ||
348 | logger.debug('Can not stop peer') | ||
349 | return False | ||
350 | self.started = False | ||
351 | return True | ||
352 | |||
353 | def get_statistics_value(self, subsystem, name): | ||
354 | server = pexpect() | ||
355 | server.spawn( | ||
356 | None, [ | ||
357 | self.test.gnunetstatistics, '-c', self.cfg, '-q', '-n', name, | ||
358 | '-s', subsystem | ||
359 | ], | ||
360 | stdout=subprocess.PIPE, | ||
361 | stderr=subprocess.STDOUT | ||
362 | ) | ||
363 | # server.expect ("stdout", re.compile (r"")) | ||
364 | test = server.read("stdout", 10240) | ||
365 | tests = test.partition(b'\n') | ||
366 | # On W32 GNUnet outputs with \r\n, rather than \n | ||
367 | if os.name == 'nt' and tests[1] == b'\n' and tests[0][-1] == b'\r': | ||
368 | tests = (tests[0][:-1], tests[1], tests[2]) | ||
369 | tests = tests[0] | ||
370 | result = tests.decode("utf-8").strip() | ||
371 | logger.debug( | ||
372 | 'running gnunet-statistics %s for %s "/" %s yields %s', self.cfg, | ||
373 | name, subsystem, result | ||
374 | ) | ||
375 | if (result.isdigit() == True): | ||
376 | return result | ||
377 | else: | ||
378 | logger.debug( | ||
379 | 'Invalid statistics value: %s is not a number!', result | ||
380 | ) | ||
381 | return -1 | ||