123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #!@PYTHON@
- # This file is part of GNUnet.
- # (C) 2010, 2017, 2018 Christian Grothoff (and other contributing authors)
- #
- # GNUnet is free software: you can redistribute it and/or modify it
- # under the terms of the GNU Affero General Public License as published
- # by the Free Software Foundation, either version 3 of the License,
- # or (at your option) any later version.
- #
- # GNUnet is distributed in the hope that it will be useful, but
- # WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- # SPDX-License-Identifier: AGPL3.0-or-later
- #
- # Functions for integration testing
- import os
- import subprocess
- import sys
- import shutil
- import time
- from gnunet_pyexpect import pexpect
- import logging
- logger = logging.getLogger()
- handler = logging.StreamHandler()
- formatter = logging.Formatter(
- '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
- handler.setFormatter(formatter)
- logger.addHandler(handler)
- logger.setLevel(logging.DEBUG)
- class Check(object):
- def __init__(self, test):
- self.fulfilled = False
- self.conditions = list()
- self.test = test
- def add(self, condition):
- self.conditions.append(condition)
- def run(self):
- fulfilled = True
- pos = 0
- neg = 0
- for c in self.conditions:
- if (False == c.check()):
- fulfilled = False
- neg += 1
- else:
- pos += 1
- return fulfilled
- def run_blocking(self, timeout, pos_cont, neg_cont):
- execs = 0
- res = False
- while ((False == res) and (execs < timeout)):
- res = self.run()
- time.sleep(1)
- execs += 1
- if ((False == res) and (execs >= timeout)):
- logger.debug('Check had timeout after %s seconds', str(timeout))
- neg_cont(self)
- elif ((False == res) and (execs < timeout)):
- if (None != neg_cont):
- neg_cont(self)
- else:
- if (None != pos_cont):
- pos_cont(self)
- return res
- def run_once(self, pos_cont, neg_cont):
- execs = 0
- res = False
- res = self.run()
- if ((res == False) and (neg_cont != None)):
- neg_cont(self)
- if ((res == True) and (pos_cont != None)):
- pos_cont(self)
- return res
- def evaluate(self, failed_only):
- pos = 0
- neg = 0
- for c in self.conditions:
- if (False == c.evaluate(failed_only)):
- neg += 1
- else:
- pos += 1
- logger.debug('%s out of %s conditions fulfilled', str(pos), str(pos+neg))
- return self.fulfilled
- def reset(self):
- self.fulfilled = False
- for c in self.conditions:
- c.fulfilled = False
- class Condition(object):
- def __init__(self):
- self.fulfilled = False
- self.type = 'generic'
- def __init__(self, type):
- self.fulfilled = False
- self.type = type
- def check(self):
- return False
- def evaluate(self, failed_only):
- if ((self.fulfilled == False) and (failed_only == True)):
- logger.debug('%s condition for was %s', str(self.type), str(self.fulfilled))
- elif (failed_only == False):
- logger.debug('%s condition for was %s', str(self.type), str(self.fulfilled))
- return self.fulfilled
- class FileExistCondition(Condition):
- def __init__(self, file):
- self.fulfilled = False
- self.type = 'file'
- self.file = file
- def check(self):
- if (self.fulfilled == False):
- res = os.path.isfile(self.file)
- if (res == True):
- self.fulfilled = True
- return True
- else:
- return False
- else:
- return True
- def evaluate(self, failed_only):
- if ((self.fulfilled == False) and (failed_only == True)):
- logger.debug('%s confition for file %s was %s', str(self.type), self.file, str(self.fulfilled))
- elif (failed_only == False):
- logger.debug('%s confition for file %s was %s', str(self.type), self.file, str(self.fulfilled))
- return self.fulfilled
- class StatisticsCondition(Condition):
- def __init__(self, peer, subsystem, name, value):
- self.fulfilled = False
- self.type = 'statistics'
- self.peer = peer
- self.subsystem = subsystem
- self.name = name
- self.value = str(value)
- self.result = -1
- def check(self):
- if (self.fulfilled == False):
- self.result = self.peer.get_statistics_value(self.subsystem, self.name)
- if (self.result == self.value):
- self.fulfilled = True
- return True
- else:
- return False
- else:
- return True
- def evaluate(self, failed_only):
- if (self.fulfilled == False):
- fail = " FAIL!"
- op = " != "
- else:
- fail = ""
- op = " == "
- if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
- 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)
- return self.fulfilled
- # Specify two statistic values and check if they are equal
- class EqualStatisticsCondition(Condition):
- def __init__(self, peer, subsystem, name, peer2, subsystem2, name2):
- self.fulfilled = False
- self.type = 'equalstatistics'
- self.peer = peer
- self.subsystem = subsystem
- self.name = name
- self.result = -1
- self.peer2 = peer2
- self.subsystem2 = subsystem2
- self.name2 = name2
- self.result2 = -1
- def check(self):
- if (self.fulfilled == False):
- self.result = self.peer.get_statistics_value(self.subsystem, self.name)
- self.result2 = self.peer2.get_statistics_value(self.subsystem2, self.name2)
- if (self.result == self.result2):
- self.fulfilled = True
- return True
- else:
- return False
- else:
- return True
- def evaluate(self, failed_only):
- if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
- 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)
- return self.fulfilled
- class Test(object):
- def __init__(self, testname, verbose):
- self.peers = list()
- self.verbose = verbose
- self.name = testname
- srcdir = "../.."
- gnunet_pyexpect_dir = os.path.join(srcdir, "contrib/scripts")
- if gnunet_pyexpect_dir not in sys.path:
- sys.path.append(gnunet_pyexpect_dir)
- self.gnunetarm = ''
- self.gnunetstatistics = ''
- if os.name == 'posix':
- self.gnunetarm = 'gnunet-arm'
- self.gnunetstatistics = 'gnunet-statistics'
- self.gnunetpeerinfo = 'gnunet-peerinfo'
- elif os.name == 'nt':
- self.gnunetarm = 'gnunet-arm.exe'
- self.gnunetstatistics = 'gnunet-statistics.exe'
- self.gnunetpeerinfo = 'gnunet-peerinfo.exe'
- if os.name == "nt":
- shutil.rmtree(os.path.join(os.getenv("TEMP"), testname), True)
- else:
- shutil.rmtree("/tmp/" + testname, True)
- def add_peer(self, peer):
- self.peers.append(peer)
- def p(self, msg):
- if (self.verbose == True):
- print(msg)
- class Peer(object):
- def __init__(self, test, cfg_file):
- if (False == os.path.isfile(cfg_file)):
- # print(("Peer cfg " + cfg_file + ": FILE NOT FOUND"))
- logger.debug('Peer cfg %s : FILE NOT FOUND', cfg_file)
- self.id = "<NaN>"
- self.test = test
- self.started = False
- self.cfg = cfg_file
- def __del__(self):
- if (self.started == True):
- # print('ERROR! Peer using cfg ' + self.cfg + ' was not stopped')
- logger.debug('ERROR! Peer using cfg %s was not stopped', self.cfg)
- ret = self.stop()
- if (False == ret):
- # print('ERROR! Peer using cfg ' +
- # self.cfg +
- # ' could not be stopped')
- logger.debug('ERROR! Peer using cfg %s could not be stopped', self.cfg)
- self.started = False
- return ret
- else:
- return False
- def start(self):
- os.unsetenv ("XDG_CONFIG_HOME")
- os.unsetenv ("XDG_DATA_HOME")
- os.unsetenv ("XDG_CACHE_HOME")
- self.test.p("Starting peer using cfg " + self.cfg)
- try:
- server = subprocess.Popen([self.test.gnunetarm, '-sq', '-c', self.cfg])
- server.communicate()
- except OSError:
- # print("Can not start peer")
- logger.debug('Can not start peer')
- self.started = False
- return False
- self.started = True
- test = ''
- try:
- server = pexpect()
- server.spawn(None, [self.test.gnunetpeerinfo, '-c', self.cfg, '-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- test = server.read("stdout", 1024)
- except OSError:
- # print("Can not get peer identity")
- logger.debug('Can not get peer identity')
- test = (test.split(b'`')[1])
- self.id = test.split(b'\'')[0]
- return True
- def stop(self):
- if (self.started == False):
- return False
- self.test.p("Stopping peer using cfg " + self.cfg)
- try:
- server = subprocess.Popen([self.test.gnunetarm, '-eq', '-c', self.cfg])
- server.communicate()
- except OSError:
- # print("Can not stop peer")
- logger.debug('Can not stop peer')
- return False
- self.started = False
- return True
- def get_statistics_value(self, subsystem, name):
- server = pexpect()
- server.spawn(None, [self.test.gnunetstatistics, '-c', self.cfg, '-q', '-n', name, '-s', subsystem], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- # server.expect ("stdout", re.compile (r""))
- test = server.read("stdout", 10240)
- tests = test.partition(b'\n')
- # On W32 GNUnet outputs with \r\n, rather than \n
- if os.name == 'nt' and tests[1] == b'\n' and tests[0][-1] == b'\r':
- tests = (tests[0][:-1], tests[1], tests[2])
- tests = tests[0]
- result = tests.decode("utf-8").strip()
- logger.debug('running gnunet-statistics %s for %s "/" %s yields %s', self.cfg, name, subsystem, result)
- if (result.isdigit() == True):
- return result
- else:
- logger.debug('Invalid statistics value: %s is not a number!', result)
- return -1
|