2 # This file is part of GNUnet.
3 # (C) 2010, 2017, 2018 Christian Grothoff (and other contributing authors)
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.
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.
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/>.
18 # SPDX-License-Identifier: AGPL3.0-or-later
20 # Functions for integration testing
21 from __future__ import unicode_literals
22 from __future__ import print_function
23 from builtins import object
24 from builtins import str
30 from gnunet_pyexpect import pexpect
33 logger = logging.getLogger()
34 handler = logging.StreamHandler()
35 formatter = logging.Formatter(
36 '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
37 handler.setFormatter(formatter)
38 logger.addHandler(handler)
39 logger.setLevel(logging.DEBUG)
42 def __init__(self, test):
43 self.fulfilled = False
44 self.conditions = list()
47 def add(self, condition):
48 self.conditions.append(condition)
54 for c in self.conditions:
55 if (False == c.check()):
62 def run_blocking(self, timeout, pos_cont, neg_cont):
65 while ((False == res) and (execs < timeout)):
69 if ((False == res) and (execs >= timeout)):
70 logger.debug('Check had timeout after %s seconds', str(timeout))
72 elif ((False == res) and (execs < timeout)):
73 if (None != neg_cont):
76 if (None != pos_cont):
80 def run_once(self, pos_cont, neg_cont):
84 if ((res == False) and (neg_cont != None)):
86 if ((res == True) and (pos_cont != None)):
90 def evaluate(self, failed_only):
93 for c in self.conditions:
94 if (False == c.evaluate(failed_only)):
98 logger.debug('%s out of %s conditions fulfilled', str(pos), str(pos+neg))
102 self.fulfilled = False
103 for c in self.conditions:
107 class Condition(object):
109 self.fulfilled = False
110 self.type = 'generic'
112 def __init__(self, type):
113 self.fulfilled = False
119 def evaluate(self, failed_only):
120 if ((self.fulfilled == False) and (failed_only == True)):
121 logger.debug('%s condition for was %s', str(self.type), str(self.fulfilled))
122 elif (failed_only == False):
123 logger.debug('%s condition for was %s', str(self.type), str(self.fulfilled))
124 return self.fulfilled
127 class FileExistCondition(Condition):
128 def __init__(self, file):
129 self.fulfilled = False
134 if (self.fulfilled == False):
135 res = os.path.isfile(self.file)
137 self.fulfilled = True
144 def evaluate(self, failed_only):
145 if ((self.fulfilled == False) and (failed_only == True)):
146 logger.debug('%s confition for file %s was %s', str(self.type), self.file, str(self.fulfilled))
147 elif (failed_only == False):
148 logger.debug('%s confition for file %s was %s', str(self.type), self.file, str(self.fulfilled))
149 return self.fulfilled
152 class StatisticsCondition(Condition):
153 def __init__(self, peer, subsystem, name, value):
154 self.fulfilled = False
155 self.type = 'statistics'
157 self.subsystem = subsystem
159 self.value = str(value)
163 if (self.fulfilled == False):
164 self.result = self.peer.get_statistics_value(self.subsystem, self.name)
165 if (self.result == self.value):
166 self.fulfilled = True
173 def evaluate(self, failed_only):
174 if (self.fulfilled == False):
180 if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
181 logger.debug('%s %s condition in subsystem %s: %s: (expected/real value) %s %s %s %s', self.peer.id[:4].decode("utf-8"), self.peer.cfg, self.subsystem.ljust(12), self.name.ljust(30), self.value, op, self.result, fail)
182 return self.fulfilled
185 # Specify two statistic values and check if they are equal
186 class EqualStatisticsCondition(Condition):
187 def __init__(self, peer, subsystem, name, peer2, subsystem2, name2):
188 self.fulfilled = False
189 self.type = 'equalstatistics'
191 self.subsystem = subsystem
195 self.subsystem2 = subsystem2
200 if (self.fulfilled == False):
201 self.result = self.peer.get_statistics_value(self.subsystem, self.name)
202 self.result2 = self.peer2.get_statistics_value(self.subsystem2, self.name2)
203 if (self.result == self.result2):
204 self.fulfilled = True
211 def evaluate(self, failed_only):
212 if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
213 logger.debug('%s %s %s == %s %s %s %s %s', self.peer.id[:4], self.subsystem.ljust(12), self.name.ljust(30), self.result, self.peer2.id[:4], self.subsystem2.ljust(12), self.name2.ljust(30), self.result2)
214 return self.fulfilled
218 def __init__(self, testname, verbose):
220 self.verbose = verbose
223 gnunet_pyexpect_dir = os.path.join(srcdir, "contrib/scripts")
224 if gnunet_pyexpect_dir not in sys.path:
225 sys.path.append(gnunet_pyexpect_dir)
227 self.gnunetstatistics = ''
228 if os.name == 'posix':
229 self.gnunetarm = 'gnunet-arm'
230 self.gnunetstatistics = 'gnunet-statistics'
231 self.gnunetpeerinfo = 'gnunet-peerinfo'
232 elif os.name == 'nt':
233 self.gnunetarm = 'gnunet-arm.exe'
234 self.gnunetstatistics = 'gnunet-statistics.exe'
235 self.gnunetpeerinfo = 'gnunet-peerinfo.exe'
237 shutil.rmtree(os.path.join(os.getenv("TEMP"), testname), True)
239 shutil.rmtree("/tmp/" + testname, True)
241 def add_peer(self, peer):
242 self.peers.append(peer)
245 if (self.verbose == True):
250 def __init__(self, test, cfg_file):
251 if (False == os.path.isfile(cfg_file)):
252 # print(("Peer cfg " + cfg_file + ": FILE NOT FOUND"))
253 logger.debug('Peer cfg %s : FILE NOT FOUND', cfg_file)
260 if (self.started == True):
261 # print('ERROR! Peer using cfg ' + self.cfg + ' was not stopped')
262 logger.debug('ERROR! Peer using cfg %s was not stopped', self.cfg)
265 # print('ERROR! Peer using cfg ' +
267 # ' could not be stopped')
268 logger.debug('ERROR! Peer using cfg %s could not be stopped', self.cfg)
275 os.unsetenv ("XDG_CONFIG_HOME")
276 os.unsetenv ("XDG_DATA_HOME")
277 os.unsetenv ("XDG_CACHE_HOME")
278 self.test.p("Starting peer using cfg " + self.cfg)
280 server = subprocess.Popen([self.test.gnunetarm, '-sq', '-c', self.cfg])
283 # print("Can not start peer")
284 logger.debug('Can not start peer')
291 server.spawn(None, [self.test.gnunetpeerinfo, '-c', self.cfg, '-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
292 test = server.read("stdout", 1024)
294 # print("Can not get peer identity")
295 logger.debug('Can not get peer identity')
296 test = (test.split(b'`')[1])
297 self.id = test.split(b'\'')[0]
301 if (self.started == False):
303 self.test.p("Stopping peer using cfg " + self.cfg)
305 server = subprocess.Popen([self.test.gnunetarm, '-eq', '-c', self.cfg])
308 # print("Can not stop peer")
309 logger.debug('Can not stop peer')
314 def get_statistics_value(self, subsystem, name):
316 server.spawn(None, [self.test.gnunetstatistics, '-c', self.cfg, '-q', '-n', name, '-s', subsystem], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
317 # server.expect ("stdout", re.compile (r""))
318 test = server.read("stdout", 10240)
319 tests = test.partition(b'\n')
320 # On W32 GNUnet outputs with \r\n, rather than \n
321 if os.name == 'nt' and tests[1] == b'\n' and tests[0][-1] == b'\r':
322 tests = (tests[0][:-1], tests[1], tests[2])
324 result = tests.decode("utf-8").strip()
325 logger.debug('running gnunet-statistics %s for %s "/" %s yields %s', self.cfg, name, subsystem, result)
326 if (result.isdigit() == True):
329 logger.debug('Invalid statistics value: %s is not a number!', result)