1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sal.hxx"
26 
27 /**  test coder preface:
28 	1. the BSD socket function will meet "unresolved external symbol error" on Windows platform
29 	if you are not including ws2_32.lib in makefile.mk,  the including format will be like this:
30 
31 	.IF "$(GUI)" == "WNT"
32 	SHL1STDLIBS +=	$(SOLARLIBDIR)$/cppunit.lib
33 	SHL1STDLIBS +=  ws2_32.lib
34 	.ENDIF
35 
36 	likewise on Solaris platform.
37 	.IF "$(GUI)" == "UNX"
38 	SHL1STDLIBS+=$(SOLARLIBDIR)$/libcppunit$(DLLPOSTFIX).a
39 	SHL1STDLIBS += -lsocket -ldl -lnsl
40 	.ENDIF
41 
42 	2. since the Socket implementation of osl is only IPv4 oriented, our test are mainly focus on IPv4
43 	category.
44 
45 	3. some fragment of Socket source implementation are lack of comment so it is hard for testers
46 	guess what the exact functionality or usage of a member.  Hope the Socket section's comment
47 	will be added.
48 
49 	4. following functions are declared but not implemented:
50 	inline sal_Bool SAL_CALL operator== (const SocketAddr & Addr) const;
51  */
52 
53 //------------------------------------------------------------------------
54 // include files
55 //------------------------------------------------------------------------
56 
57 #include <testshl/simpleheader.hxx>
58 
59 #include "osl_Socket_Const.h"
60 #include "sockethelper.hxx"
61 
62 using namespace osl;
63 using namespace rtl;
64 
65 #define IP_PORT_MYPORT2 8883
66 #define IP_PORT_FTP     21
67 #define IP_PORT_MYPORT3 8884
68 
69 //------------------------------------------------------------------------
70 // helper functions
71 //------------------------------------------------------------------------
72 
73 class CloseSocketThread : public Thread
74 {
75 	::osl::Socket &m_sSocket;
76 protected:
77 	void SAL_CALL run( )
78 	{
79 		thread_sleep( 1 );
80 		m_sSocket.close( );
81 	}
82 public:
83 	CloseSocketThread(::osl::Socket & sSocket )
84 		: m_sSocket( sSocket )
85 	{
86 	}
87 
88 	~CloseSocketThread( )
89 	{
90 		if ( isRunning( ) )
91 		{
92 			t_print("# error: CloseSocketThread not terminated.\n" );
93 		}
94 	}
95 };
96 
97 namespace osl_ConnectorSocket
98 {
99 
100 	/** testing the method:
101 		ConnectorSocket(oslAddrFamily Family = osl_Socket_FamilyInet,
102 						oslProtocol	Protocol = osl_Socket_ProtocolIp,
103 						oslSocketType	Type = osl_Socket_TypeStream);
104 	*/
105 
106 	class ctors : public CppUnit::TestFixture
107 	{
108 	public:
109 		void ctors_001()
110 		{
111 			/// Socket constructor.
112 			::osl::ConnectorSocket csSocket( osl_Socket_FamilyInet, osl_Socket_ProtocolIp, osl_Socket_TypeStream );
113 
114 			CPPUNIT_ASSERT_MESSAGE( "test for ctors_001 constructor function: check if the connector socket was created successfully.",
115 									osl_Socket_TypeStream ==  csSocket.getType( ) );
116 		}
117 
118 		CPPUNIT_TEST_SUITE( ctors );
119 		CPPUNIT_TEST( ctors_001 );
120 		CPPUNIT_TEST_SUITE_END();
121 
122 	}; // class ctors
123 
124 	/** testing the method:
125 		oslSocketResult SAL_CALL connect(const SocketAddr& TargetHost, const TimeValue* pTimeout = 0);
126 	*/
127 
128 	class connect : public CppUnit::TestFixture
129 	{
130 	public:
131 		TimeValue *pTimeout;
132 		::osl::AcceptorSocket asAcceptorSocket;
133 		::osl::ConnectorSocket csConnectorSocket;
134 
135 
136 		// initialization
137 		void setUp( )
138 		{
139 			pTimeout  = ( TimeValue* )malloc( sizeof( TimeValue ) );
140 			pTimeout->Seconds = 3;
141 			pTimeout->Nanosec = 0;
142 		//	sHandle = osl_createSocket( osl_Socket_FamilyInet, osl_Socket_TypeStream, osl_Socket_ProtocolIp );
143 		}
144 
145 		void tearDown( )
146 		{
147 			free( pTimeout );
148 		//	sHandle = NULL;
149 			asAcceptorSocket.close( );
150 			csConnectorSocket.close( );
151 		}
152 
153 
154 		void connect_001()
155 		{
156 			::osl::SocketAddr saLocalSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT2 );
157 			::osl::SocketAddr saTargetSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT2 );
158 			::osl::SocketAddr saPeerSocketAddr( rtl::OUString::createFromAscii("129.158.217.202"), IP_PORT_FTP );
159 			::osl::StreamSocket ssConnection;
160 
161 			/// launch server socket
162 			asAcceptorSocket.setOption( osl_Socket_OptionReuseAddr, 1 ); //sal_True);
163 			sal_Bool bOK1 = asAcceptorSocket.bind( saLocalSocketAddr );
164 			CPPUNIT_ASSERT_MESSAGE( "AcceptorSocket bind address failed.", sal_True == bOK1 );
165 			sal_Bool bOK2 = asAcceptorSocket.listen( 1 );
166 			CPPUNIT_ASSERT_MESSAGE( "AcceptorSocket listen failed.",  sal_True == bOK2 );
167 
168 			//asAcceptorSocket.enableNonBlockingMode( sal_True );
169 			//oslSocketResult eResultAccept = asAcceptorSocket.acceptConnection(ssConnection); /// waiting for incoming connection...
170 			//CPPUNIT_ASSERT_MESSAGE( "accept failed.",  osl_Socket_Ok == eResultAccept );
171 			/// launch client socket
172 			oslSocketResult eResult = csConnectorSocket.connect( saTargetSocketAddr, pTimeout );   /// connecting to server...
173 			CPPUNIT_ASSERT_MESSAGE( "connect failed.",  osl_Socket_Ok == eResult );
174 
175 			/// get peer information
176 			csConnectorSocket.getPeerAddr( saPeerSocketAddr );/// connected.
177 
178 			CPPUNIT_ASSERT_MESSAGE( "test for connect function: try to create a connection with remote host. and check the setup address.",
179 									( sal_True == compareSocketAddr( saPeerSocketAddr, saLocalSocketAddr ) ) &&
180 									( osl_Socket_Ok == eResult ));
181 		}
182 		//non-blocking mode connect?
183 		void connect_002()
184 		{
185 			::osl::SocketAddr saLocalSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT3 );
186 			::osl::SocketAddr saTargetSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT3 );
187 			::osl::SocketAddr saPeerSocketAddr( rtl::OUString::createFromAscii("129.158.217.202"), IP_PORT_FTP );
188 
189 			asAcceptorSocket.setOption( osl_Socket_OptionReuseAddr, 1 ); //sal_True);
190 			asAcceptorSocket.enableNonBlockingMode( sal_True );
191 			sal_Bool bOK1 = asAcceptorSocket.bind( saLocalSocketAddr );
192 			CPPUNIT_ASSERT_MESSAGE( "AcceptorSocket bind address failed.", sal_True == bOK1 );
193 			sal_Bool bOK2 = asAcceptorSocket.listen( 1 );
194 			CPPUNIT_ASSERT_MESSAGE( "AcceptorSocket listen failed.",  sal_True == bOK2 );
195 
196 			csConnectorSocket.enableNonBlockingMode( sal_True );
197 
198 			oslSocketResult eResult = csConnectorSocket.connect( saTargetSocketAddr, pTimeout );   /// connecting to server...
199 			CPPUNIT_ASSERT_MESSAGE( "connect failed.",  osl_Socket_InProgress == eResult ||  osl_Socket_Ok == eResult );
200 
201 			/// get peer information
202 			csConnectorSocket.getPeerAddr( saPeerSocketAddr );
203 
204 			CPPUNIT_ASSERT_MESSAGE( "test for connect function: try to create a connection with remote host. and check the setup address.",
205 				sal_True == compareSocketAddr( saPeerSocketAddr, saLocalSocketAddr  )  ) ;
206 		}
207 		// really an error or just delayed
208 		// how to design scenarios that will return osl_Socket_Interrupted, osl_Socket_TimedOut
209 		void connect_003()
210 		{
211 			::osl::SocketAddr saTargetSocketAddr1( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT3 );
212 			::osl::SocketAddr saTargetSocketAddr2( rtl::OUString::createFromAscii("123.345.67.89"), IP_PORT_MYPORT3 );
213 
214 			csConnectorSocket.enableNonBlockingMode( sal_False );
215 
216 			oslSocketResult eResult1 = csConnectorSocket.connect( saTargetSocketAddr1, pTimeout );
217 			oslSocketResult eResult2 = csConnectorSocket.connect( saTargetSocketAddr2, pTimeout );
218 			CloseSocketThread myCloseThread( csConnectorSocket );
219 			oslSocketResult eResult3 = csConnectorSocket.connect( saTargetSocketAddr2, pTimeout );
220 			myCloseThread.join();
221 			CPPUNIT_ASSERT_MESSAGE( "connect should failed.",  osl_Socket_Error == eResult1 &&
222 				osl_Socket_Error == eResult2 &&  osl_Socket_Error == eResult3 );
223 
224 		}
225 
226 		// really an error in non-blocking mode
227 		void connect_004()
228 		{
229 			::osl::SocketAddr saTargetSocketAddr( rtl::OUString::createFromAscii("123.345.67.89"), IP_PORT_MYPORT3 );
230 
231 			csConnectorSocket.enableNonBlockingMode( sal_True );
232 
233 			oslSocketResult eResult = csConnectorSocket.connect( saTargetSocketAddr, pTimeout );   /// connecting to server...
234 			CPPUNIT_ASSERT_MESSAGE( "connect should failed.",  osl_Socket_Error == eResult );
235 		}
236 		/** here need a case: immediate connection, say in non-blocking mode connect return osl_Socket_Ok
237 		*/
238 
239 		CPPUNIT_TEST_SUITE( connect );
240 		CPPUNIT_TEST( connect_001 );
241 		CPPUNIT_TEST( connect_002 );
242 		CPPUNIT_TEST( connect_003 );
243 		CPPUNIT_TEST( connect_004 );
244 		CPPUNIT_TEST_SUITE_END();
245 
246 	}; // class connect
247 
248 
249 // -----------------------------------------------------------------------------
250 
251 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_ConnectorSocket::ctors, "osl_ConnectorSocket");
252 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_ConnectorSocket::connect, "osl_ConnectorSocket");
253 
254 } // namespace osl_ConnectorSocket
255 
256 // -----------------------------------------------------------------------------
257 
258 // this macro creates an empty function, which will called by the RegisterAllFunctions()
259 // to let the user the possibility to also register some functions by hand.
260 NOADDITIONAL;
261