blob: ce6d5c16d45b170415b6a5009b28f74e57a4cc49 [file] [log] [blame]
Bram Moolenaard7ece102016-02-02 23:23:02 +01001#!/usr/bin/python
2#
3# Server that will accept connections from a Vim channel.
Bram Moolenaar77073442016-02-13 23:23:53 +01004# Used by test_channel.vim.
Bram Moolenaard7ece102016-02-02 23:23:02 +01005#
6# This requires Python 2.6 or later.
7
8from __future__ import print_function
9import json
10import socket
11import sys
12import threading
13
14try:
15 # Python 3
16 import socketserver
17except ImportError:
18 # Python 2
19 import SocketServer as socketserver
20
Bram Moolenaard7ece102016-02-02 23:23:02 +010021class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
22
23 def handle(self):
24 print("=== socket opened ===")
Bram Moolenaard7ece102016-02-02 23:23:02 +010025 while True:
26 try:
Bram Moolenaar608a8912016-02-03 22:39:51 +010027 received = self.request.recv(4096).decode('utf-8')
Bram Moolenaard7ece102016-02-02 23:23:02 +010028 except socket.error:
29 print("=== socket error ===")
30 break
31 except IOError:
32 print("=== socket closed ===")
33 break
Bram Moolenaar608a8912016-02-03 22:39:51 +010034 if received == '':
Bram Moolenaard7ece102016-02-02 23:23:02 +010035 print("=== socket closed ===")
36 break
Bram Moolenaar608a8912016-02-03 22:39:51 +010037 print("received: {}".format(received))
Bram Moolenaard7ece102016-02-02 23:23:02 +010038
Bram Moolenaare7bed622016-02-03 22:20:29 +010039 # We may receive two messages at once. Take the part up to the
40 # matching "]" (recognized by finding "][").
Bram Moolenaar608a8912016-02-03 22:39:51 +010041 todo = received
42 while todo != '':
43 splitidx = todo.find('][')
Bram Moolenaare7bed622016-02-03 22:20:29 +010044 if splitidx < 0:
Bram Moolenaar608a8912016-02-03 22:39:51 +010045 used = todo
46 todo = ''
Bram Moolenaard7ece102016-02-02 23:23:02 +010047 else:
Bram Moolenaar608a8912016-02-03 22:39:51 +010048 used = todo[:splitidx + 1]
49 todo = todo[splitidx + 1:]
50 if used != received:
51 print("using: {}".format(used))
Bram Moolenaard7ece102016-02-02 23:23:02 +010052
Bram Moolenaare7bed622016-02-03 22:20:29 +010053 try:
Bram Moolenaar608a8912016-02-03 22:39:51 +010054 decoded = json.loads(used)
Bram Moolenaare7bed622016-02-03 22:20:29 +010055 except ValueError:
56 print("json decoding failed")
57 decoded = [-1, '']
Bram Moolenaard7ece102016-02-02 23:23:02 +010058
Bram Moolenaare7bed622016-02-03 22:20:29 +010059 # Send a response if the sequence number is positive.
60 if decoded[0] >= 0:
61 if decoded[1] == 'hello!':
62 # simply send back a string
63 response = "got it"
64 elif decoded[1] == 'make change':
Bram Moolenaar66624ff2016-02-03 23:59:43 +010065 # Send two ex commands at the same time, before
66 # replying to the request.
Bram Moolenaare7bed622016-02-03 22:20:29 +010067 cmd = '["ex","call append(\\"$\\",\\"added1\\")"]'
68 cmd += '["ex","call append(\\"$\\",\\"added2\\")"]'
69 print("sending: {}".format(cmd))
Bram Moolenaar3b05b132016-02-03 23:25:07 +010070 self.request.sendall(cmd.encode('utf-8'))
Bram Moolenaare7bed622016-02-03 22:20:29 +010071 response = "ok"
Bram Moolenaarf4160862016-02-05 23:09:12 +010072 elif decoded[1] == 'do normal':
73 # Send a normal command.
74 cmd = '["normal","G$s more\u001b"]'
75 print("sending: {}".format(cmd))
76 self.request.sendall(cmd.encode('utf-8'))
77 response = "ok"
Bram Moolenaare7bed622016-02-03 22:20:29 +010078 elif decoded[1] == 'eval-works':
79 # Send an eval request. We ignore the response.
80 cmd = '["eval","\\"foo\\" . 123", -1]'
81 print("sending: {}".format(cmd))
Bram Moolenaar3b05b132016-02-03 23:25:07 +010082 self.request.sendall(cmd.encode('utf-8'))
Bram Moolenaare7bed622016-02-03 22:20:29 +010083 response = "ok"
84 elif decoded[1] == 'eval-fails':
85 # Send an eval request that will fail.
86 cmd = '["eval","xxx", -2]'
87 print("sending: {}".format(cmd))
Bram Moolenaar3b05b132016-02-03 23:25:07 +010088 self.request.sendall(cmd.encode('utf-8'))
Bram Moolenaare7bed622016-02-03 22:20:29 +010089 response = "ok"
Bram Moolenaar55fab432016-02-07 16:53:13 +010090 elif decoded[1] == 'eval-error':
91 # Send an eval request that works but the result can't
92 # be encoded.
93 cmd = '["eval","function(\\"tr\\")", -3]'
94 print("sending: {}".format(cmd))
95 self.request.sendall(cmd.encode('utf-8'))
96 response = "ok"
Bram Moolenaar66624ff2016-02-03 23:59:43 +010097 elif decoded[1] == 'eval-bad':
98 # Send an eval request missing the third argument.
99 cmd = '["eval","xxx"]'
100 print("sending: {}".format(cmd))
101 self.request.sendall(cmd.encode('utf-8'))
102 response = "ok"
Bram Moolenaarf4160862016-02-05 23:09:12 +0100103 elif decoded[1] == 'an expr':
104 # Send an expr request.
105 cmd = '["expr","setline(\\"$\\", [\\"one\\",\\"two\\",\\"three\\"])"]'
106 print("sending: {}".format(cmd))
107 self.request.sendall(cmd.encode('utf-8'))
108 response = "ok"
109 elif decoded[1] == 'redraw':
110 cmd = '["redraw",""]'
111 print("sending: {}".format(cmd))
112 self.request.sendall(cmd.encode('utf-8'))
113 response = "ok"
114 elif decoded[1] == 'redraw!':
115 cmd = '["redraw","force"]'
116 print("sending: {}".format(cmd))
117 self.request.sendall(cmd.encode('utf-8'))
118 response = "ok"
Bram Moolenaar6076fe12016-02-05 22:49:56 +0100119 elif decoded[1] == 'empty-request':
120 cmd = '[]'
121 print("sending: {}".format(cmd))
122 self.request.sendall(cmd.encode('utf-8'))
123 response = "ok"
Bram Moolenaare7bed622016-02-03 22:20:29 +0100124 elif decoded[1] == 'eval-result':
125 # Send back the last received eval result.
126 response = last_eval
Bram Moolenaarf6157282016-02-10 21:07:14 +0100127 elif decoded[1] == 'call me':
128 cmd = '[0,"we called you"]'
129 print("sending: {}".format(cmd))
130 self.request.sendall(cmd.encode('utf-8'))
131 response = "ok"
132 elif decoded[1] == 'call me again':
133 cmd = '[0,"we did call you"]'
134 print("sending: {}".format(cmd))
135 self.request.sendall(cmd.encode('utf-8'))
136 response = ""
Bram Moolenaare7bed622016-02-03 22:20:29 +0100137 elif decoded[1] == '!quit!':
138 # we're done
Bram Moolenaarb3e2f002016-02-04 00:11:37 +0100139 self.server.shutdown()
Bram Moolenaarb92abad2016-02-08 22:37:24 +0100140 return
Bram Moolenaare7bed622016-02-03 22:20:29 +0100141 elif decoded[1] == '!crash!':
142 # Crash!
143 42 / 0
144 else:
145 response = "what?"
146
Bram Moolenaarf6157282016-02-10 21:07:14 +0100147 if response == "":
148 print("no response")
149 else:
150 encoded = json.dumps([decoded[0], response])
151 print("sending: {}".format(encoded))
152 self.request.sendall(encoded.encode('utf-8'))
Bram Moolenaare7bed622016-02-03 22:20:29 +0100153
154 # Negative numbers are used for "eval" responses.
155 elif decoded[0] < 0:
156 last_eval = decoded
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100157
Bram Moolenaard7ece102016-02-02 23:23:02 +0100158class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
159 pass
160
161if __name__ == "__main__":
162 HOST, PORT = "localhost", 0
163
164 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
165 ip, port = server.server_address
166
Bram Moolenaar6076fe12016-02-05 22:49:56 +0100167 # Start a thread with the server. That thread will then start a new thread
168 # for each connection.
Bram Moolenaard7ece102016-02-02 23:23:02 +0100169 server_thread = threading.Thread(target=server.serve_forever)
Bram Moolenaard7ece102016-02-02 23:23:02 +0100170 server_thread.start()
171
172 # Write the port number in Xportnr, so that the test knows it.
173 f = open("Xportnr", "w")
174 f.write("{}".format(port))
175 f.close()
176
Bram Moolenaard7ece102016-02-02 23:23:02 +0100177 print("Listening on port {}".format(port))
Bram Moolenaarb3e2f002016-02-04 00:11:37 +0100178
179 # Main thread terminates, but the server continues running
180 # until server.shutdown() is called.