SyntaxError: from __future__ imports must occur at the beginning of the file
[tests.git] / system / tcptest.py
1 #!/usr/bin/env python
2
3 # Thierry Parmentelat <thierry.parmentelat@inria.fr>
4 # Copyright (C) 2010 INRIA 
5 #
6
7 from __future__ import print_function
8
9 import sys
10 import time
11 import subprocess
12 import socket
13 import SocketServer
14 import threading
15 from optparse import OptionParser    
16
17 def myprint(message, id='client'):
18     now = time.strftime("%H:%M:%S", time.localtime())
19     print("* {now} ({id}) -- {message}".format(**locals()))
20     sys.stdout.flush()
21
22 def show_network_status(id):
23     myprint("ip address show", id=id)
24     subprocess.call(['ip', 'address', 'show'])
25     myprint("ip route show", id=id)
26     subprocess.call(['ip', 'route', 'show'])
27
28 class EchoRequestHandler(SocketServer.StreamRequestHandler):
29     def handle(self):
30         line = self.rfile.readline()
31         self.wfile.write(line)
32
33 class UppercaseRequestHandler(SocketServer.StreamRequestHandler):
34     def handle(self):
35         line = self.rfile.readline()
36         self.wfile.write(line.upper())
37
38 class Server:
39     """
40     A TCP server, running for some finite amount of time
41     """
42     def main(self):
43         parser = OptionParser()
44         parser.add_option("-p", "--port", action="store", dest="port", type="int",
45                           default=10000, help="port number")
46         parser.add_option("-a", "--address", action="store", dest="address", 
47                           default=socket.gethostname(), help="address")
48         parser.add_option("-t", "--timeout", action="store", dest="timeout", type="int",
49                           default="0")
50         (options, args) = parser.parse_args()
51
52         if len(args) != 0:
53             parser.print_help()
54             sys.exit(1)
55
56         myprint("==================== tcptest.py server", id='server')
57         show_network_status(id='server')
58         server = SocketServer.TCPServer((options.address, options.port),
59                                         UppercaseRequestHandler)
60         try:
61             if options.timeout:
62                 t = threading.Thread(target=server.serve_forever)
63                 t.setDaemon(True) # don't hang on exit
64                 t.start()
65                 time.sleep(options.timeout)
66                 sys.exit(0)
67             else:
68                 server.serve_forever()        
69         except KeyboardInterrupt as e:
70             print('Bailing out on keyboard interrupt')
71             sys.exit(1)
72             
73 class Ready:
74     """
75     A utility that does exit(0) iff network as perceived
76     from the sliver is ready. Designed to be run before Server,
77     so one can wait for the right conditions.
78     """
79     def main(self):
80         parser = OptionParser()
81         # by default use another port so we don't run into
82         # the SO_LINGER kind of trouble
83         parser.add_option("-p", "--port", action="store", dest="port", type="int",
84                           default=9999, help="port number")
85         parser.add_option("-a", "--address", action="store", dest="address", 
86                           default=socket.gethostname(), help="address")
87         (options, args) = parser.parse_args()
88
89         myprint("==================== tcptest.py ready", id='ready')
90         def can_bind ():
91             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
92             try:
93                 s.bind((options.address, options.port))
94                 return True
95             except Exception as e:
96                 print(e)
97                 return False
98
99         def eth0_has_ipv4():
100             command = "ip address show eth0 | grep -q ' inet '"
101             return subprocess.check_call(command, shell=True) == 0
102
103         sys.exit(0 if can_bind() and eth0_has_ipv4() else 1)
104         
105 class Client:
106     """
107     Runs a client against a Server instance
108     """
109     def main(self):
110         parser = OptionParser()
111         parser.add_option("-p","--port", action="store", dest="port", type="int",
112                           default=10000, help="port number")
113         parser.add_option("-a","--address", action="store", dest="address", 
114                           default=socket.gethostname(), help="address")
115         parser.add_option("-s","--sleep", action="store", dest="sleep", type="int",
116                           default=1, help="sleep seconds")
117         parser.add_option("-l","--loops", action="store", dest="loops", type="int",
118                           default=1, help="iteration loops")
119         
120         (options, args) = parser.parse_args()
121         if len(args) != 0:
122             parser.print_help()
123             sys.exit(1)
124
125         myprint("==================== tcptest.py client", id='client')
126         result=True
127         for i in range(1,options.loops+1):
128             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
129             s.connect((options.address, options.port))
130             mout=i*'ping ' + '\n'
131             min=mout.upper()
132             if s.send(mout) != len(mout):
133                 myprint("cannot send {}".format(mout.strip()))
134                 result=False
135                 break
136             line=s.recv(len(min))
137             if line is not line:
138                 myprint("unexpected reception\ngot:{}\nexpected: {}".format(line, min))
139                 result = False
140             else:
141                 myprint("OK:{}".format(mout.strip()))
142             # leave the connection open, but the last one (so 1 iter returns fast)
143             if i != options.loops:
144                 time.sleep(options.sleep)
145             myprint("disconnecting")
146             s.close()
147         myprint("Done")
148         exit_return=0
149         if not result:
150             exit_return=1
151         sys.exit(exit_return)
152
153 if __name__ == '__main__':
154     for arg in sys.argv[1:]:
155         if arg.find("client") >= 0:
156             sys.argv.remove(arg)
157             Client().main()
158         elif arg.find("server") >= 0:
159             sys.argv.remove(arg)
160             Server().main()
161         elif arg.find("ready") >= 0:
162             sys.argv.remove(arg)
163             Ready().main()
164     print('you must specify either --client or --server')
165     sys.exit(1)