]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/d/src/thrift/internal/test/server.d
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / d / src / thrift / internal / test / server.d
CommitLineData
f67539c2
TL
1/*
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.internal.test.server;
20
21import core.sync.condition;
22import core.sync.mutex;
23import core.thread : Thread;
24import std.datetime;
25import std.exception : enforce;
26import std.typecons : WhiteHole;
27import std.variant : Variant;
28import thrift.protocol.base;
29import thrift.protocol.binary;
30import thrift.protocol.processor;
31import thrift.server.base;
32import thrift.server.transport.socket;
33import thrift.transport.base;
34import thrift.util.cancellation;
35
36version(unittest):
37
38/**
39 * Tests if serving is stopped correctly if the cancellation passed to serve()
40 * is triggered.
41 *
42 * Because the tests are run many times in a loop, this is indirectly also a
43 * test whether socket, etc. handles are cleaned up correctly, because the
44 * application will likely run out of handles otherwise.
45 */
46void testServeCancel(Server)(void delegate(Server) serverSetup = null) if (
47 is(Server : TServer)
48) {
49 auto proc = new WhiteHole!TProcessor;
50 auto tf = new TTransportFactory;
51 auto pf = new TBinaryProtocolFactory!();
52
53 // Need a special case for TNonblockingServer which doesn't use
54 // TServerTransport.
55 static if (__traits(compiles, new Server(proc, 0, tf, pf))) {
56 auto server = new Server(proc, 0, tf, pf);
57 } else {
58 auto server = new Server(proc, new TServerSocket(0), tf, pf);
59 }
60
61 // On Windows, we use TCP sockets to replace socketpair(). Since they stay
62 // in TIME_WAIT for some time even if they are properly closed, we have to use
63 // a lower number of iterations to avoid running out of ports/buffer space.
64 version (Windows) {
65 enum ITERATIONS = 100;
66 } else {
67 enum ITERATIONS = 10000;
68 }
69
70 if (serverSetup) serverSetup(server);
71
72 auto servingMutex = new Mutex;
73 auto servingCondition = new Condition(servingMutex);
74 auto doneMutex = new Mutex;
75 auto doneCondition = new Condition(doneMutex);
76
77 class CancellingHandler : TServerEventHandler {
78 void preServe() {
79 synchronized (servingMutex) {
80 servingCondition.notifyAll();
81 }
82 }
83 Variant createContext(TProtocol input, TProtocol output) { return Variant.init; }
84 void deleteContext(Variant serverContext, TProtocol input, TProtocol output) {}
85 void preProcess(Variant serverContext, TTransport transport) {}
86 }
87 server.eventHandler = new CancellingHandler;
88
89 foreach (i; 0 .. ITERATIONS) {
90 synchronized (servingMutex) {
91 auto cancel = new TCancellationOrigin;
92 synchronized (doneMutex) {
93 auto serverThread = new Thread({
94 server.serve(cancel);
95 synchronized (doneMutex) {
96 doneCondition.notifyAll();
97 }
98 });
99 serverThread.isDaemon = true;
100 serverThread.start();
101
102 servingCondition.wait();
103
104 cancel.trigger();
105 enforce(doneCondition.wait(dur!"msecs"(3*1000)));
106 serverThread.join();
107 }
108 }
109 }
110}