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 "gtest/gtest.h"
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_MYPORT9  8897
66 #define IP_PORT_MYPORT10 8898
67 
68 const char * pTestString1 = "test socket";
69 const char * pTestString2 = " Passed#OK";
70 
71 //------------------------------------------------------------------------
72 // helper functions
73 //------------------------------------------------------------------------
74 
75 class CloseSocketThread : public Thread
76 {
77 	::osl::Socket m_sSocket;
78 protected:
run()79 	void SAL_CALL run( )
80 	{
81 		thread_sleep( 1 );
82 		m_sSocket.close( );
83 	}
84 public:
CloseSocketThread(::osl::Socket & sSocket)85 	CloseSocketThread(::osl::Socket & sSocket )
86 		: m_sSocket( sSocket )
87 	{
88 	}
89 
~CloseSocketThread()90 	~CloseSocketThread( )
91 	{
92 		if ( isRunning( ) )
93 		{
94 			printf("# error: CloseSocketThread not terminated.\n" );
95 		}
96 	}
97 };
98 
99 //------------------------------------------------------------------------
100 // tests cases begins here
101 //------------------------------------------------------------------------
102 
103 namespace osl_DatagramSocket
104 {
105 
106 	/** testing the methods:
107 		inline DatagramSocket(oslAddrFamily Family= osl_Socket_FamilyInet,
108 							  oslProtocol	Protocol= osl_Socket_ProtocolIp,
109 							  oslSocketType	Type= osl_Socket_TypeDgram);
110 	*/
111 
112 	class ctors : public ::testing::Test
113 	{
114 	public:
115 	}; // class ctors
116 
TEST_F(ctors,ctors_001)117     TEST_F(ctors, ctors_001)
118     {
119         /// Socket constructor.
120         ::osl::DatagramSocket dsSocket;
121 
122         ASSERT_TRUE(osl_Socket_TypeDgram ==  dsSocket.getType( ))
123             << "test for ctors_001 constructor function: check if the datagram socket was created successfully.";
124     }
125 
126 /**thread do sendTo, refer to http://www.coding-zone.co.uk/cpp/articles/140101networkprogrammingv.shtml
127 */
128 class TalkerThread : public Thread
129 {
130 protected:
131 	::osl::SocketAddr saTargetSocketAddr;
132 	::osl::DatagramSocket dsSocket;
133 
run()134 	void SAL_CALL run( )
135 	{
136 		dsSocket.sendTo( saTargetSocketAddr, pTestString1, strlen( pTestString1 ) + 1 ); // "test socket"
137 		dsSocket.shutdown();
138 	}
139 
onTerminated()140 	void SAL_CALL onTerminated( )
141 	{
142 	}
143 
144 public:
TalkerThread()145 	TalkerThread( ):
146 		saTargetSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT9 )
147 	{
148 	}
149 
~TalkerThread()150 	~TalkerThread( )
151 	{
152 		if ( isRunning( ) )
153 			printf("# error: TalkerThread not terminated normally.\n" );
154 	}
155 };
156 
157 /**thread do listen, refer to http://www.coding-zone.co.uk/cpp/articles/140101networkprogrammingv.shtml
158 */
159 class ListenerThread : public Thread
160 {
161 protected:
162 	::osl::SocketAddr saTargetSocketAddr;
163 	::osl::DatagramSocket dsSocket;
164 
run()165 	void SAL_CALL run( )
166 	{
167 		::osl::SocketAddr saLocalSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT10 );
168 		dsSocket.setOption( osl_Socket_OptionReuseAddr, 1 );
169 		if ( dsSocket.bind( saLocalSocketAddr ) == sal_False )
170 		{
171 			printf("DatagramSocket bind failed \n");
172 			return;
173 		}
174 		//blocking mode: default
175 		sal_Int32 nRecv = dsSocket.recvFrom( pRecvBuffer, 30, &saTargetSocketAddr); //strlen( pTestString2 ) + 1
176 		printf("After recvFrom, nRecv is %d\n", nRecv);
177 	}
178 
onTerminated()179 	void SAL_CALL onTerminated( )
180 	{
181 	}
182 
183 public:
184 	sal_Char pRecvBuffer[30];
ListenerThread()185 	ListenerThread( ):
186 		saTargetSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT10 )
187 	{
188 		pRecvBuffer[0] = '\0';
189 	}
190 
~ListenerThread()191 	~ListenerThread( )
192 	{
193 		if ( isRunning( ) )
194 			printf("# error: ListenerThread not terminated normally.\n" );
195 	}
196 
197 };
198 
199 	/** testing the methods:
200 		inline sal_Int32 DatagramSocket::recvFrom(void*  pBuffer, sal_uInt32 BufferSize,
201 			  SocketAddr* pSenderAddr, oslSocketMsgFlag Flag )
202 		inline sal_Int32  DatagramSocket::sendTo( const SocketAddr& ReceiverAddr,
203 			  const void* pBuffer, sal_uInt32 BufferSize, oslSocketMsgFlag Flag )
204 	*/
205 
206 	class sendTo_recvFrom : public ::testing::Test
207 	{
208 	public:
209 	}; // class sendTo_recvFrom
210 
TEST_F(sendTo_recvFrom,sr_001)211     TEST_F(sendTo_recvFrom, sr_001)
212     {
213         ::osl::SocketAddr saLocalSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT9 );
214         ::osl::DatagramSocket dsSocket;
215         dsSocket.setOption( osl_Socket_OptionReuseAddr, 1 );
216         dsSocket.bind( saLocalSocketAddr );
217 
218         sal_Char pReadBuffer[30];
219         TalkerThread myTalkThread;
220         myTalkThread.create();
221         sal_Int32 nRecv = dsSocket.recvFrom( pReadBuffer, 30, &saLocalSocketAddr);
222         myTalkThread.join();
223         //printf("#received buffer is %s# \n", pReadBuffer);
224 
225         sal_Bool bOk = ( strcmp(pReadBuffer, pTestString1) == 0 );
226 
227         ASSERT_TRUE(nRecv > 0 && bOk == sal_True )
228             << "test for sendTo/recvFrom function: create a talker thread and recvFrom in the main thread, check if the datagram socket can communicate successfully.";
229     }
230 
TEST_F(sendTo_recvFrom,sr_002)231     TEST_F(sendTo_recvFrom, sr_002)
232     {
233         ::osl::SocketAddr saListenSocketAddr( rtl::OUString::createFromAscii("127.0.0.1"), IP_PORT_MYPORT10 );
234         ::osl::DatagramSocket dsSocket;
235 
236         //listener thread construct a DatagramSocket, recvFrom waiting for data, then main thread sendto data
237         ListenerThread myListenThread;
238         myListenThread.create();
239         //to grantee the recvFrom is before sendTo
240         thread_sleep( 1 );
241 
242         sal_Int32 nSend = dsSocket.sendTo( saListenSocketAddr, pTestString2, strlen( pTestString2 ) + 1 );
243 
244         ASSERT_TRUE(nSend > 0) << "DatagramSocket sendTo failed: nSend <= 0.";
245 
246         myListenThread.join();
247         //printf("#received buffer is %s# \n", myListenThread.pRecvBuffer);
248 
249         sal_Bool bOk = ( strcmp( myListenThread.pRecvBuffer, pTestString2) == 0 );
250 
251         ASSERT_TRUE( bOk == sal_True )
252             << "test for sendTo/recvFrom function: create a listener thread and sendTo in the main thread, check if the datagram socket can communicate successfully.";
253     }
254 
255     //sendTo error, return -1; recvFrom error, return -1
TEST_F(sendTo_recvFrom,sr_003)256     TEST_F(sendTo_recvFrom, sr_003)
257     {
258         ::osl::SocketAddr saListenSocketAddr( rtl::OUString::createFromAscii("123.345.67.89"), IP_PORT_MYPORT10 );
259         ::osl::DatagramSocket dsSocket;
260         // Transport endpoint is not connected
261         sal_Int32 nSend = dsSocket.sendTo( saListenSocketAddr, pTestString2, strlen( pTestString2 ) + 1 );
262         ASSERT_TRUE(nSend == -1) << "DatagramSocket sendTo should fail: nSend <= 0.";
263     }
264 
TEST_F(sendTo_recvFrom,sr_004)265     TEST_F(sendTo_recvFrom, sr_004)
266     {
267         ::osl::SocketAddr saListenSocketAddr1( rtl::OUString::createFromAscii("123.345.67.89"), IP_PORT_MYPORT10 );
268         ::osl::SocketAddr saListenSocketAddr2( rtl::OUString::createFromAscii("129.158.217.202"), IP_PORT_MYPORT10 );
269         ::osl::DatagramSocket dsSocket;
270 
271         dsSocket.enableNonBlockingMode( sal_True );
272 
273         sal_Char pReadBuffer[30];
274         //sal_Int32 nRecv1 = dsSocket.recvFrom( pReadBuffer, 30, &saListenSocketAddr1 );
275 
276         // will block ?
277         CloseSocketThread myThread( dsSocket );
278         myThread.create();
279         sal_Int32 nRecv2 = dsSocket.recvFrom( pReadBuffer, 30, &saListenSocketAddr1 );
280         myThread.join();
281         //printf("#nRecv1 is %d nRecv2 is %d\n", nRecv1, nRecv2 );
282         ASSERT_TRUE(nRecv2 == -1) << "DatagramSocket sendTo should fail: nSend <= 0.";
283     }
284 
285 } // namespace osl_DatagramSocket
286 
main(int argc,char ** argv)287 int main(int argc, char **argv)
288 {
289     ::testing::InitGoogleTest(&argc, argv);
290     return RUN_ALL_TESTS();
291 }
292