- changes
[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            neg_cont (self)
56         elif ((False == res) and (execs < timeout)):
57             if (None != neg_cont):
58                 neg_cont (self)
59         else:
60             if (None != pos_cont):
61                 pos_cont (self)
62         return res     
63     def run_once (self, pos_cont, neg_cont):
64         execs = 0;
65         res = False
66         res = self.run()
67         if ((res == False) and (neg_cont != None)):
68             neg_cont (self)
69         if ((res == True) and (pos_cont != None)):
70             pos_cont (self)            
71         return res
72     def evaluate (self, failed_only):
73         pos = 0
74         neg = 0
75         for c in self.conditions:
76             if (False == c.evaluate (failed_only)):
77                 neg += 1
78             else:
79                 pos += 1
80         print (str(pos) +' out of '+ str (pos+neg) + ' conditions fulfilled')
81         return self.fulfilled
82     def reset (self):
83                 self.fulfilled = False     
84                 for c in self.conditions:
85                         c.fulfilled = False
86         
87 class Condition:
88     def __init__(self):
89         self.fulfilled = False
90         self.type = 'generic'
91     def __init__(self, type):
92         self.fulfilled = False
93         self.type = type
94     def check(self):
95         return False;
96     def evaluate (self, failed_only):
97         if ((self.fulfilled == False) and (failed_only == True)):
98             print str(self.type) + 'condition for was ' + str(self.fulfilled)
99         elif (failed_only == False): 
100             print str(self.type) + 'condition for was ' + str(self.fulfilled)
101         return self.fulfilled            
102
103 class FileExistCondition (Condition):
104     def __init__(self, file):
105         self.fulfilled = False
106         self.type = 'file'
107         self.file = file
108     def check(self):
109         if (self.fulfilled == False):
110             res = os.path.isfile(self.file)
111             if (res == True):
112                 self.fulfilled = True
113                 return True
114             else:
115                 return False
116         else:
117             return True
118     def evaluate (self, failed_only):
119         if ((self.fulfilled == False) and (failed_only == True)):
120             print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled)
121         elif (failed_only == False): 
122             print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled)
123         return self.fulfilled
124
125 class StatisticsCondition (Condition):
126     def __init__(self, peer, subsystem, name, value):
127         self.fulfilled = False
128         self.type = 'statistics'
129         self.peer = peer;
130         self.subsystem = subsystem;
131         self.name = name;
132         self.value = value;
133         self.result = -1;
134     def check(self):
135         if (self.fulfilled == False):
136             self.result = self.peer.get_statistics_value (self.subsystem, self.name)
137             if (str(self.result) == str(self.value)):
138                 self.fulfilled = True
139                 return True
140             else:
141                 return False
142         else:
143             return True
144     def evaluate (self, failed_only):
145         if (self.result == -1):
146             res = 'NaN'
147         else:
148             res = str(self.result)
149         if (self.fulfilled == False):
150             fail = " FAIL!" 
151             op = " != "
152         else: 
153             fail = ""
154             op = " == "
155         if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
156             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
157         return self.fulfilled    
158
159 # Specify two statistic values and check if they are equal  
160 class EqualStatisticsCondition (Condition):
161     def __init__(self, peer, subsystem, name, peer2, subsystem2, name2):
162         self.fulfilled = False
163         self.type = 'equalstatistics'
164         self.peer = peer;
165         self.subsystem = subsystem;
166         self.name = name;
167         self.result = -1;
168         self.peer2 = peer2;
169         self.subsystem2 = subsystem2;
170         self.name2 = name2;
171         self.result2 = -1;
172     def check(self):
173         if (self.fulfilled == False):
174             self.result = self.peer.get_statistics_value (self.subsystem, self.name);
175             self.result2 = self.peer2.get_statistics_value (self.subsystem2, self.name2);
176             if (str(self.result) == str(self.result2)):
177                 self.fulfilled = True
178                 return True
179             else:
180                 return False
181         else:
182             return True
183     def evaluate (self, failed_only):
184         if (self.result == -1):
185             res = 'NaN'
186         else:
187             res = str(self.result)
188         if (self.result2 == -1):
189             res2 = 'NaN'
190         else:
191             res2 = str(self.result2)            
192         if (self.fulfilled == False):
193             fail = " FAIL!" 
194             op = " != "
195         else: 
196             fail = ""
197             op = " == "
198         if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)):
199             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) 
200         return self.fulfilled                    
201         
202 class Test:
203     def __init__(self, testname, verbose):
204         self.peers = list()
205         self.verbose = verbose;
206         self.name = testname;
207         srcdir = "../.."
208         gnunet_pyexpect_dir = os.path.join (srcdir, "contrib")
209         if gnunet_pyexpect_dir not in sys.path:
210             sys.path.append (gnunet_pyexpect_dir)
211         self.gnunetarm = ''        
212         self.gnunetstatistics = ''
213         if os.name == 'posix':
214             self.gnunetarm = 'gnunet-arm'
215             self.gnunetstatistics = 'gnunet-statistics'
216             self.gnunetpeerinfo = 'gnunet-peerinfo'
217         elif os.name == 'nt':
218             self.gnunetarm = 'gnunet-arm.exe'
219             self.gnunetstatistics = 'gnunet-statistics.exe'
220             self.gnunetpeerinfo = 'gnunet-peerinfo.exe'    
221         if os.name == "nt":
222             shutil.rmtree (os.path.join (os.getenv ("TEMP"), testname), True)
223         else:
224             shutil.rmtree ("/tmp/" + testname, True)
225     def add_peer (self, peer):
226         self.peers.append(peer)
227     def p (self, msg):
228         if (self.verbose == True):
229             print msg    
230
231 class Peer:
232     def __init__(self, test, cfg_file):
233         if (False == os.path.isfile(cfg_file)):
234             print ("Peer cfg " + cfg_file + ": FILE NOT FOUND")
235         self.id = "<NaN>"
236         self.test = test
237         self.started = False
238         self.cfg = cfg_file 
239     def __del__(self):
240         if (self.started == True): 
241             print 'ERROR! Peer using cfg ' + self.cfg + ' was not stopped'
242             ret = self.stop ()
243             if (False == ret):
244                 print 'ERROR! Peer using cfg ' + self.cfg + ' could not be stopped'
245                 self.started = False
246             return ret
247         else:
248             return False
249     def start (self):
250         self.test.p ("Starting peer using cfg " + self.cfg)
251         try:
252             server = subprocess.Popen ([self.test.gnunetarm, '-sq', '-c', self.cfg])
253             server.communicate ()    
254         except OSError:
255             print "Can not start peer"
256             self.started = False
257             return False
258         self.started = True;
259         test = ''
260         try:
261             server = pexpect ()
262             server.spawn (None, [self.test.gnunetpeerinfo, '-c', self.cfg ,'-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
263             test = server.read("stdout", 1024)
264         except OSError:
265             print "Can not get peer identity"
266         test = (test.split('`')[1])
267         self.id = test.split('\'')[0]
268         return True 
269     def stop (self):
270         if (self.started == False):
271             return False
272         self.test.p ("Stopping peer using cfg " + self.cfg)
273         try:
274             server = subprocess.Popen ([self.test.gnunetarm, '-eq', '-c', self.cfg])
275             server.communicate ()    
276         except OSError:
277             print "Can not stop peer"
278             return False
279         self.started = False
280         return True;
281     def get_statistics_value (self, subsystem, name):
282         server = pexpect ()
283         server.spawn (None, [self.test.gnunetstatistics, '-c', self.cfg ,'-q','-n', name, '-s', subsystem ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
284         #server.expect ("stdout", re.compile (r""))
285         test = server.read("stdout", 10240)
286         tests = test.partition('\n')
287         # On W32 GNUnet outputs with \r\n, rather than \n
288         if os.name == 'nt' and tests[1] == '\n' and tests[0][-1] == '\r':
289             tests = (tests[0][:-1], tests[1], tests[2])
290         tests = tests[0]
291         if (tests.isdigit() == True):
292             return tests
293         else:
294             return -1
295