blob: 71ab9175d4b62fd0a4013a36b56bfb8ddb0d67ad [file] [log] [blame]
Jake Farrellb95b0ff2012-03-22 21:49:10 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19module thrift_test_server;
20
21import core.thread : dur, Thread;
22import std.algorithm;
23import std.exception : enforce;
24import std.getopt;
25import std.parallelism : totalCPUs;
26import std.string;
27import std.stdio;
28import std.typetuple : TypeTuple, staticMap;
29import thrift.base;
30import thrift.codegen.processor;
31import thrift.protocol.base;
32import thrift.protocol.binary;
33import thrift.protocol.compact;
34import thrift.protocol.json;
35import thrift.server.base;
36import thrift.server.transport.socket;
37import thrift.server.transport.ssl;
38import thrift.transport.base;
39import thrift.transport.buffered;
40import thrift.transport.framed;
41import thrift.transport.http;
42import thrift.transport.ssl;
43import thrift.util.hashset;
44import test_utils;
45
46import thrift_test_common;
47import thrift.test.ThriftTest_types;
48import thrift.test.ThriftTest;
49
50class TestHandler : ThriftTest {
51 this(bool trace) {
52 trace_ = trace;
53 }
54
55 override void testVoid() {
56 if (trace_) writeln("testVoid()");
57 }
58
59 override string testString(string thing) {
60 if (trace_) writefln("testString(\"%s\")", thing);
61 return thing;
62 }
63
64 override byte testByte(byte thing) {
65 if (trace_) writefln("testByte(%s)", thing);
66 return thing;
67 }
68
69 override int testI32(int thing) {
70 if (trace_) writefln("testI32(%s)", thing);
71 return thing;
72 }
73
74 override long testI64(long thing) {
75 if (trace_) writefln("testI64(%s)", thing);
76 return thing;
77 }
78
79 override double testDouble(double thing) {
80 if (trace_) writefln("testDouble(%s)", thing);
81 return thing;
82 }
83
Jens Geyer8bcfdd92014-12-14 03:14:26 +010084 override string testBinary(string thing) {
85 if (trace_) writefln("testBinary(\"%s\")", thing);
86 return thing;
87 }
88
Jens Geyer855cf7f2015-10-08 21:12:57 +020089 override bool testBool(bool thing) {
90 if (trace_) writefln("testBool(\"%s\")", thing);
91 return thing;
92 }
93
Jake Farrellb95b0ff2012-03-22 21:49:10 +000094 override Xtruct testStruct(ref const(Xtruct) thing) {
95 if (trace_) writefln("testStruct({\"%s\", %s, %s, %s})",
96 thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing);
97 return thing;
98 }
99
100 override Xtruct2 testNest(ref const(Xtruct2) nest) {
101 auto thing = nest.struct_thing;
102 if (trace_) writefln("testNest({%s, {\"%s\", %s, %s, %s}, %s})",
103 nest.byte_thing, thing.string_thing, thing.byte_thing, thing.i32_thing,
104 thing.i64_thing, nest.i32_thing);
105 return nest;
106 }
107
108 override int[int] testMap(int[int] thing) {
109 if (trace_) writefln("testMap({%s})", thing);
110 return thing;
111 }
112
113 override HashSet!int testSet(HashSet!int thing) {
114 if (trace_) writefln("testSet({%s})",
115 join(map!`to!string(a)`(thing[]), ", "));
116 return thing;
117 }
118
119 override int[] testList(int[] thing) {
120 if (trace_) writefln("testList(%s)", thing);
121 return thing;
122 }
123
124 override Numberz testEnum(Numberz thing) {
125 if (trace_) writefln("testEnum(%s)", thing);
126 return thing;
127 }
128
129 override UserId testTypedef(UserId thing) {
130 if (trace_) writefln("testTypedef(%s)", thing);
131 return thing;
132 }
133
134 override string[string] testStringMap(string[string] thing) {
135 if (trace_) writefln("testStringMap(%s)", thing);
136 return thing;
137 }
138
139 override int[int][int] testMapMap(int hello) {
140 if (trace_) writefln("testMapMap(%s)", hello);
141 return testMapMapReturn;
142 }
143
144 override Insanity[Numberz][UserId] testInsanity(ref const(Insanity) argument) {
145 if (trace_) writeln("testInsanity()");
Nobuaki Sukegawa8b791b22016-03-05 13:40:25 +0900146 Insanity[Numberz][UserId] ret;
147 Insanity[Numberz] m1;
148 Insanity[Numberz] m2;
149 Insanity tmp;
150 tmp = cast(Insanity)argument;
151 m1[Numberz.TWO] = tmp;
152 m1[Numberz.THREE] = tmp;
153 m2[Numberz.SIX] = Insanity();
154 ret[1] = m1;
155 ret[2] = m2;
156 return ret;
Jake Farrellb95b0ff2012-03-22 21:49:10 +0000157 }
158
159 override Xtruct testMulti(byte arg0, int arg1, long arg2, string[short] arg3,
160 Numberz arg4, UserId arg5)
161 {
162 if (trace_) writeln("testMulti()");
163 return Xtruct("Hello2", arg0, arg1, arg2);
164 }
165
166 override void testException(string arg) {
167 if (trace_) writefln("testException(%s)", arg);
168 if (arg == "Xception") {
169 auto e = new Xception();
170 e.errorCode = 1001;
171 e.message = arg;
172 throw e;
Nobuaki Sukegawa8b791b22016-03-05 13:40:25 +0900173 } else if (arg == "TException") {
174 throw new TException();
Jake Farrellb95b0ff2012-03-22 21:49:10 +0000175 } else if (arg == "ApplicationException") {
176 throw new TException();
177 }
178 }
179
180 override Xtruct testMultiException(string arg0, string arg1) {
181 if (trace_) writefln("testMultiException(%s, %s)", arg0, arg1);
182
183 if (arg0 == "Xception") {
184 auto e = new Xception();
185 e.errorCode = 1001;
186 e.message = "This is an Xception";
187 throw e;
188 } else if (arg0 == "Xception2") {
189 auto e = new Xception2();
190 e.errorCode = 2002;
191 e.struct_thing.string_thing = "This is an Xception2";
192 throw e;
193 } else {
194 return Xtruct(arg1);
195 }
196 }
197
198 override void testOneway(int sleepFor) {
199 if (trace_) writefln("testOneway(%s): Sleeping...", sleepFor);
200 Thread.sleep(dur!"seconds"(sleepFor));
201 if (trace_) writefln("testOneway(%s): done sleeping!", sleepFor);
202 }
203
204private:
205 bool trace_;
206}
207
208void main(string[] args) {
209 ushort port = 9090;
210 ServerType serverType;
211 ProtocolType protocolType;
212 size_t numIOThreads = 1;
213 TransportType transportType;
214 bool ssl;
215 bool trace;
216 size_t taskPoolSize = totalCPUs;
217
218 getopt(args, "port", &port, "protocol", &protocolType, "server-type",
219 &serverType, "ssl", &ssl, "num-io-threads", &numIOThreads,
220 "task-pool-size", &taskPoolSize, "trace", &trace,
221 "transport", &transportType);
222
223 if (serverType == ServerType.nonblocking ||
224 serverType == ServerType.pooledNonblocking
225 ) {
226 enforce(transportType == TransportType.framed,
227 "Need to use framed transport with non-blocking server.");
228 enforce(!ssl, "The non-blocking server does not support SSL yet.");
229
230 // Don't wrap the contents into another layer of framing.
231 transportType = TransportType.raw;
232 }
233
234 version (ThriftTestTemplates) {
235 // Only exercise the specialized template code paths if explicitly enabled
236 // to reduce memory consumption on regular test suite runs – there should
237 // not be much that can go wrong with that specifically anyway.
238 alias TypeTuple!(TBufferedTransport, TFramedTransport, TServerHttpTransport)
239 AvailableTransports;
240 alias TypeTuple!(
241 staticMap!(TBinaryProtocol, AvailableTransports),
242 staticMap!(TCompactProtocol, AvailableTransports)
243 ) AvailableProtocols;
244 } else {
245 alias TypeTuple!() AvailableTransports;
246 alias TypeTuple!() AvailableProtocols;
247 }
248
249 TProtocolFactory protocolFactory;
250 final switch (protocolType) {
251 case ProtocolType.binary:
252 protocolFactory = new TBinaryProtocolFactory!AvailableTransports;
253 break;
254 case ProtocolType.compact:
255 protocolFactory = new TCompactProtocolFactory!AvailableTransports;
256 break;
257 case ProtocolType.json:
258 protocolFactory = new TJsonProtocolFactory!AvailableTransports;
259 break;
260 }
261
262 auto processor = new TServiceProcessor!(ThriftTest, AvailableProtocols)(
263 new TestHandler(trace));
264
265 TServerSocket serverSocket;
266 if (ssl) {
267 auto sslContext = new TSSLContext();
268 sslContext.serverSide = true;
Nobuaki Sukegawa8b791b22016-03-05 13:40:25 +0900269 sslContext.loadCertificate("../../../test/keys/server.crt");
270 sslContext.loadPrivateKey("../../../test/keys/server.key");
Jake Farrellb95b0ff2012-03-22 21:49:10 +0000271 sslContext.ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
272 serverSocket = new TSSLServerSocket(port, sslContext);
273 } else {
274 serverSocket = new TServerSocket(port);
275 }
276
277 auto transportFactory = createTransportFactory(transportType);
278
279 auto server = createServer(serverType, numIOThreads, taskPoolSize,
280 processor, serverSocket, transportFactory, protocolFactory);
281
282 writefln("Starting %s/%s %s ThriftTest server %son port %s...", protocolType,
283 transportType, serverType, ssl ? "(using SSL) ": "", port);
284 server.serve();
285 writeln("done.");
286}