- msg
[oweals/gnunet.git] / src / integration-tests / gnunet_testing.py.in
1 #!@PYTHON@
2 #    This file is part of GNUnet.
3 #    (C) 2010 Christian Grothoff (and other contributing authors)
4 #
5 #    GNUnet is free software; you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published
7 #    by the Free Software Foundation; either version 2, or (at your
8 #    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 #    General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with GNUnet; see the file COPYING.  If not, write to the
17 #    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 #    Boston, MA 02111-1307, USA.
19 #
20 # Functions for integration testing
21 import os
22 import subprocess
23 import sys
24 import shutil
25 import time
26 from gnunet_pyexpect import pexpect
27
28 class Check:
29     def __init__(self, test):
30         self.fulfilled = False
31         self.conditions = list()
32         self.test = test
33     def add (self, condition):
34         self.conditions.append(condition)
35     def run (self):
36         fulfilled = True
37         pos = 0
38         neg = 0
39         for c in self.conditions:
40             if (False == c.check ()):
41                 fulfilled = False
42                 neg += 1
43             else:
44                 pos += 1
45         return fulfilled
46     def run_blocking (self, timeout, pos_cont, neg_cont):
47         execs = 0;
48         res = False
49         while ((False == res) and (execs < timeout)):
50             res = self.run()
51             time.sleep(1)
52             execs += 1
53         if ((False == res) and (execs >= timeout)):
54            print ('Check had timeout after ' +str(timeout)+ 'seconds')
55         else:
56             pos_cont (self)
57         return res            
58     def run_once (self, pos_cont, neg_cont):
59         execs = 0;
60         res = False
61         res = self.run()
62         if ((res == False) and (neg_cont != None)):
63             neg_cont (self)
64         if ((res == True) and (pos_cont != None)):
65             pos_cont (self)            
66         return res
67     def evaluate (self, failed_only):
68         pos = 0
69         neg = 0
70         for c in self.conditions:
71             if (False == c.evaluate (failed_only)):
72                 neg += 1
73             else:
74                 pos += 1
75         print (str(pos) +' out of '+ str (pos+neg) + ' conditions fulfilled')
76         return self.fulfilled
77     def reset (self):
78                 self.fulfilled = False     
79                 for c in self.conditions:
80                         c.fulfilled = False
81         
82 class Condition:
83     def __init__(self):
84         self.fulfilled = False
85         self.type = 'generic'
86     def __init__(self, type):
87         self.fulfilled = False
88         self.type = type
89     def check(self):
90         return False;
91     def evaluate (self, failed_only):
92         if ((self.fulfilled == False) and (failed_only == True)):
93             print str(self.type) + 'condition for was ' + str(self.fulfilled)
94         elif (failed_only == False): 
95             print str(self.type) + 'condition for was ' + str(self.fulfilled)
96         return self.fulfilled            
97
98 class FileExistCondition (Condition):
99     def __init__(self, file):
100         self.fulfilled = False
101         self.type = 'file'
102         self.file = file
103     def check(self):
104         if (self.fulfilled == False):
105             res = os.path.isfile(self.file)
106             if (res == True):
107                 self.fulfilled = True
108                 return True
109             else:
110                 return False
111         else:
112             return True
113     def evaluate (self, failed_only):
114         if ((self.fulfilled == False) and (failed_only == True)):
115             print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled)
116         elif (failed_only == False): 
117             print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled)
118         return self.fulfilled
119
120 class StatisticsCondition (Condition):
121     def __init__(self, peer, subsystem, name, value):
122         self.fulfilled = False
123         self.type = 'statistics'
124         self.peer = peer;
125         self.subsystem = subsystem;
126         self.name = name;
127         self.value = value;
128         self.result = -1;
129     def check(self):
130         if (self.fulfilled == False):
131             self.result = self.peer.get_statistics_value (self.subsystem, self.name)
132             if (str(self.result) == str(self.value)):
133                 self.fulfilled = True
134                 return True
135             else:
136                 return False
137         else:
138             return True
139     def evaluate (self, failed_only):
140         if (self.result == -1):
141             res = 'NaN'
142         else:
143             res = str(self.result)
144         if (self.fulfilled == False):
145             fail = " FAIL!" 
146             op = " != "
147         else: 
148             fail = ""
149             op = " == "
150         if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
151             print self.peer.id[:4] + " " +self.peer.cfg + " " +  str(self.type) + ' condition in subsystem "' + self.subsystem.ljust(12) +'" : "' + self.name.ljust(30) +'" : (expected/real value) ' + str(self.value) + op + res + fail
152         return self.fulfilled    
153
154 # Specify two statistic values and check if they are equal  
155 class EqualStatisticsCondition (Condition):
156     def __init__(self, peer, subsystem, name, peer2, subsystem2, name2):
157         self.fulfilled = False
158         self.type = 'equalstatistics'
159         self.peer = peer;
160         self.subsystem = subsystem;
161         self.name = name;
162         self.result = -1;
163         self.peer2 = peer2;
164         self.subsystem2 = subsystem2;
165         self.name2 = name2;
166         self.result2 = -1;
167     def check(self):
168         if (self.fulfilled == False):
169             self.result = self.peer.get_statistics_value (self.subsystem, self.name);
170             self.result2 = self.peer2.get_statistics_value (self.subsystem2, self.name2);
171             if (str(self.result) == str(self.result2)):
172                 self.fulfilled = True
173                 return True
174             else:
175                 return False
176         else:
177             return True
178     def evaluate (self, failed_only):
179         if (self.result == -1):
180             res = 'NaN'
181         else:
182             res = str(self.result)
183         if (self.result2 == -1):
184             res2 = 'NaN'
185         else:
186             res2 = str(self.result2)            
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)) or (failed_only == False)):
194             print self.peer.id[:4] + ' "'  + self.subsystem.ljust(12) + '" "' + self.name.ljust(30) + '" == ' + str(self.result) +" " + self.peer2.id[:4] + ' "'  + self.subsystem2.ljust(12) + '" '+ self.name2.ljust(30) +  '" ' + str(self.result2) 
195         return self.fulfilled                    
196         
197 class Test:
198     def __init__(self, testname, verbose):
199         self.peers = list()
200         self.verbose = verbose;
201         self.name = testname;
202         srcdir = "../.."
203         gnunet_pyexpect_dir = os.path.join (srcdir, "contrib")
204         if gnunet_pyexpect_dir not in sys.path:
205             sys.path.append (gnunet_pyexpect_dir)
206         self.gnunetarm = ''        
207         self.gnunetstatistics = ''
208         if os.name == 'posix':
209             self.gnunetarm = 'gnunet-arm'
210             self.gnunetstatistics = 'gnunet-statistics'
211             self.gnunetpeerinfo = 'gnunet-peerinfo'
212         elif os.name == 'nt':
213             self.gnunetarm = 'gnunet-arm.exe'
214             self.gnunetstatistics = 'gnunet-statistics.exe'
215             self.gnunetpeerinfo = 'gnunet-peerinfo.exe'    
216         if os.name == "nt":
217             shutil.rmtree (os.path.join (os.getenv ("TEMP"), testname), True)
218         else:
219             shutil.rmtree ("/tmp/" + testname, True)
220     def add_peer (self, peer):
221         self.peers.append(peer)
222     def p (self, msg):
223         if (self.verbose == True):
224             print msg    
225
226 class Peer:
227     def __init__(self, test, cfg_file):
228         if (False == os.path.isfile(cfg_file)):
229             print ("Peer cfg " + cfg_file + ": FILE NOT FOUND")
230         self.id = "<NaN>"
231         self.test = test
232         self.started = False
233         self.cfg = cfg_file 
234     def __del__(self):
235         if (self.started == True): 
236             print 'ERROR! Peer using cfg ' + self.cfg + ' was not stopped'
237             ret = self.stop ()
238             if (False == ret):
239                 print 'ERROR! Peer using cfg ' + self.cfg + ' could not be stopped'
240                 self.started = False
241             return ret
242         else:
243             return False
244     def start (self):
245         self.test.p ("Starting peer using cfg " + self.cfg)
246         try:
247             server = subprocess.Popen ([self.test.gnunetarm, '-sq', '-c', self.cfg])
248             server.communicate ()    
249         except OSError:
250             print "Can not start peer"
251             self.started = False
252             return False
253         self.started = True;
254         test = ''
255         try:
256             server = pexpect ()
257             server.spawn (None, [self.test.gnunetpeerinfo, '-c', self.cfg ,'-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
258             test = server.read("stdout", 1024)
259         except OSError:
260             print "Can not get peer identity"
261         test = (test.split('`')[1])
262         self.id = test.split('\'')[0]
263         return True 
264     def stop (self):
265         if (self.started == False):
266             return False
267         self.test.p ("Stopping peer using cfg " + self.cfg)
268         try:
269             server = subprocess.Popen ([self.test.gnunetarm, '-eq', '-c', self.cfg])
270             server.communicate ()    
271         except OSError:
272             print "Can not stop peer"
273             return False
274         self.started = False
275         return True;
276     def get_statistics_value (self, subsystem, name):
277         server = pexpect ()
278         server.spawn (None, [self.test.gnunetstatistics, '-c', self.cfg ,'-q','-n', name, '-s', subsystem ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
279         #server.expect ("stdout", re.compile (r""))
280         test = server.read("stdout", 10240)
281         tests = test.partition('\n')
282         # On W32 GNUnet outputs with \r\n, rather than \n
283         if os.name == 'nt' and tests[1] == '\n' and tests[0][-1] == '\r':
284             tests = (tests[0][:-1], tests[1], tests[2])
285         tests = tests[0]
286         if (tests.isdigit() == True):
287             return tests
288         else:
289             return -1
290