1 /*******************************************************************************
2 
3     Unit tests for SelectListener.
4 
5     Copyright:
6         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
7         All rights reserved.
8 
9     License:
10         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
11         Alternatively, this file may be distributed under the terms of the Tango
12         3-Clause BSD License (see LICENSE_BSD.txt for details).
13 
14 *******************************************************************************/
15 
16 module ocean.net.server.SelectListener_slowtest;
17 
18 
19 import ocean.meta.types.Qualifiers;
20 
21 import ocean.net.server.SelectListener;
22 import ocean.net.server.connection.IConnectionHandler;
23 import ocean.io.select.protocol.generic.ErrnoIOException: SocketError;
24 import ocean.util.log.Logger;
25 
26 import ocean.core.Test;
27 import ocean.sys.socket.AddressIPSocket;
28 import ocean.sys.socket.UnixSocket;
29 import ocean.sys.socket.InetAddress;
30 import core.sys.posix.unistd: unlink;
31 import ocean.stdc.posix.sys.un;
32 import core.sys.posix.sys.socket;
33 
34 
35 /*******************************************************************************
36 
37     Static module logger
38 
39 *******************************************************************************/
40 
41 static private Logger log;
42 static this ( )
43 {
44     log = Log.lookup("ocean.net.server.SelectListener_slowtest");
45 }
46 
47 /*******************************************************************************
48 
49     IP unit tests
50 
51 *******************************************************************************/
52 
53 class DummyConHandler : IConnectionHandler
54 {
55     this ( scope void delegate ( IConnectionHandler instance ) )
56     {
57         super(new AddressIPSocket!(), null, null);
58     }
59     override protected bool io_error() { return true; }
60     override public void handleConnection () {}
61     override public void unregisterSocket() {}
62 }
63 
64 ushort testPort ( ushort port )
65 {
66     InetAddress!(false) addr;
67 
68     auto socket = new AddressIPSocket!();
69 
70     auto listener = new SelectListener!(DummyConHandler)(
71         addr(port), socket);
72 
73     scope (exit) listener.shutdown();
74 
75     test(!socket.updateAddress(), "socket.updateAddress() failed.");
76 
77     test(socket.port() != 0, "Did not correctly query bounded port from OS");
78 
79     test(port == 0 || socket.port() == port,
80          "Didn't bind to expected port!");
81 
82     return socket.port();
83 }
84 
85 unittest
86 {
87     auto port = testPort(0);
88 
89     port++;
90 
91     // If the port we're testing happens to be taken, try the next one
92     // give up after 10 tries
93     for ( size_t i = 0; i < 10; ++i ) try
94     {
95         port = testPort(port);
96         return;
97     }
98     catch ( SocketError e )
99     {
100         port += i;
101     }
102 
103     log.warn("FLAKEY: Failed to perform test of binding to a "
104         ~ "specific port after 10 tries");
105 }
106 
107 /*******************************************************************************
108 
109     UNIX socket unit tests
110 
111 *******************************************************************************/
112 
113 class DummyConHandlerUnix : IConnectionHandler
114 {
115     this ( scope void delegate ( IConnectionHandler instance ) )
116     {
117         super(new UnixSocket, null, null);
118     }
119     override protected bool io_error() { return true; }
120     override public void handleConnection () {}
121     override public void unregisterSocket() {}
122 }
123 
124 void test_unix (istring path)
125 {
126     // The following test will fail:
127     // 1) during the socket creation if the socket file can not be created.
128     // 2) during the socket termination, if the socket file can not be deleted.
129 
130     auto local_address = sockaddr_un.create(path);
131     auto unix_socket = new UnixSocket;
132 
133     auto listener = new SelectListener!(DummyConHandlerUnix)(
134         cast(sockaddr*)&local_address, unix_socket);
135 
136     test(unix_socket.error ==0, "Something wrong happened");
137 
138     scope (exit)
139     {
140         listener.shutdown();
141 
142         if ( (local_address.sun_path[0] != '\0')
143             && unlink(local_address.sun_path.ptr) == -1 )
144         {
145             test(false, "Socket file '" ~ local_address.sun_path ~
146                 "' could not be unlinked (it may not exist or "
147               ~ "the executable lacks permissions).");
148         }
149     }
150 }
151 
152 unittest
153 {
154     test_unix("\0ocean-unixsocket-test");
155     test_unix("/tmp/ocean-unixsocket-test");
156 }