36a8d233c176c6e157008151324ed8a841ed0f15
[mono.git] / mcs / class / Mono.Posix / Test / Mono.Unix.Native / SocketTest.cs
1 //
2 // socket-related test cases
3 //
4 // Authors:
5 //  Steffen Kiess (s-kiess@web.de)
6 //
7 // Copyright (C) 2015 Steffen Kiess
8 //
9
10 using System;
11 using System.IO;
12 using System.Net;
13 using System.Net.Sockets;
14 using System.Runtime.InteropServices;
15
16 using Mono.Unix;
17 using Mono.Unix.Native;
18
19 using NUnit.Framework;
20
21 namespace MonoTests.Mono.Unix.Native
22 {
23         [TestFixture, Category ("NotDotNet")]
24         public class SocketTest {
25
26                 string TempFolder;
27
28                 [SetUp]
29                 public void SetUp ()
30                 {
31                         TempFolder = Path.Combine (Path.GetTempPath (), this.GetType ().FullName);
32
33                         if (Directory.Exists (TempFolder))
34                                 Directory.Delete (TempFolder, true);
35
36                         Directory.CreateDirectory (TempFolder);
37                 }
38
39                 [TearDown]
40                 public void TearDown()
41                 {
42                         if (Directory.Exists (TempFolder))
43                                 Directory.Delete (TempFolder, true);
44                 }
45
46                 // Set a timeout on all sockets to make sure that if a test fails it
47                 // won't cause the program to hang
48                 void SetTimeout (int socket)
49                 {
50                         var timeout = new Timeval {
51                                 tv_sec = 0,
52                                 tv_usec = 500000,
53                         };
54                         if (Syscall.setsockopt (socket, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_RCVTIMEO, timeout) < 0 ||
55                                         Syscall.setsockopt (socket, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_SNDTIMEO, timeout) < 0)
56                                 UnixMarshal.ThrowExceptionForLastError ();
57                 }
58
59                 void WithSocketPair (Action<int, int> f)
60                 {
61                         int socket1, socket2;
62                         if (Syscall.socketpair (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, out socket1, out socket2) < 0)
63                                 UnixMarshal.ThrowExceptionForLastError ();
64                         try {
65                                 SetTimeout (socket1);
66                                 SetTimeout (socket2);
67
68                                 f (socket1, socket2);
69                         } finally {
70                                 int r0 = Syscall.close (socket1);
71                                 int r1 = Syscall.close (socket2);
72                                 if (r0 < 0 || r1 < 0)
73                                         UnixMarshal.ThrowExceptionForLastError ();
74                         }
75                 }
76
77                 void WithSockets (UnixAddressFamily af, UnixSocketType type, UnixSocketProtocol protocol, Action<int, int> f)
78                 {
79                         int so1, so2;
80                         if ((so1 = Syscall.socket (af, type, protocol)) < 0)
81                                 UnixMarshal.ThrowExceptionForLastError ();
82                         try {
83                                 if ((so2 = Syscall.socket (af, type, protocol)) < 0)
84                                         UnixMarshal.ThrowExceptionForLastError ();
85                                 try {
86                                         SetTimeout (so1);
87                                         SetTimeout (so2);
88
89                                         f (so1, so2);
90                                 } finally {
91                                         if (Syscall.close (so2) < 0)
92                                                 UnixMarshal.ThrowExceptionForLastError ();
93                                 }
94                         } finally {
95                                 if (Syscall.close (so1) < 0)
96                                         UnixMarshal.ThrowExceptionForLastError ();
97                         }
98                 }
99
100                 [Test]
101                 public void Socket ()
102                 {
103                         int socket;
104                         if ((socket = Syscall.socket (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0)) < 0)
105                                 UnixMarshal.ThrowExceptionForLastError ();
106
107                         if (Syscall.close (socket) < 0)
108                                 UnixMarshal.ThrowExceptionForLastError ();
109                 }
110
111                 [Test]
112                 public void SocketPair ()
113                 {
114                         int socket1, socket2;
115                         if (Syscall.socketpair (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, out socket1, out socket2) < 0)
116                                 UnixMarshal.ThrowExceptionForLastError ();
117
118                         int r0 = Syscall.close (socket1);
119                         int r1 = Syscall.close (socket2);
120                         if (r0 < 0 || r1 < 0)
121                                 UnixMarshal.ThrowExceptionForLastError ();
122                 }
123
124                 [Test]
125                 public void SendRecv ()
126                 {
127                         WithSocketPair ((so1, so2) => {
128                                 long ret;
129                                 var buffer1 = new byte[] { 42, 43, 44 };
130                                 ret = Syscall.send (so1, buffer1, (ulong) buffer1.Length, 0);
131                                 if (ret < 0)
132                                         UnixMarshal.ThrowExceptionForLastError ();
133
134                                 var buffer2 = new byte[1024];
135                                 ret = Syscall.recv (so2, buffer2, (ulong) buffer2.Length, 0);
136                                 if (ret < 0)
137                                         UnixMarshal.ThrowExceptionForLastError ();
138
139                                 Assert.AreEqual (buffer1.Length, ret);
140                                 for (int i = 0; i < buffer1.Length; i++)
141                                         Assert.AreEqual (buffer1[i], buffer2[i]);
142                         });
143                 }
144
145                 [Test]
146                 public void SockOpt ()
147                 {
148                         WithSockets (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => {
149                                 // Set SO_REUSEADDR to 1
150                                 if (Syscall.setsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, 1) < 0)
151                                         UnixMarshal.ThrowExceptionForLastError ();
152
153                                 // Get and check SO_REUSEADDR
154                                 int value;
155                                 if (Syscall.getsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, out value) < 0)
156                                         UnixMarshal.ThrowExceptionForLastError ();
157                                 Assert.AreEqual (value, 1);
158
159                                 // Set SO_REUSEADDR to 0
160                                 if (Syscall.setsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, new byte[10], 4) < 0)
161                                         UnixMarshal.ThrowExceptionForLastError ();
162
163                                 // Get and check SO_REUSEADDR
164                                 var buffer = new byte[15];
165                                 long size = 12;
166                                 if (Syscall.getsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_REUSEADDR, buffer, ref size) < 0)
167                                         UnixMarshal.ThrowExceptionForLastError ();
168                                 Assert.AreEqual (size, 4);
169                                 for (int i = 0; i < size; i++)
170                                         Assert.AreEqual (buffer[i], 0);
171                         });
172                 }
173
174                 [Test]
175                 public void SockOptLinger ()
176                 {
177                         WithSockets (UnixAddressFamily.AF_INET, UnixSocketType.SOCK_STREAM, UnixSocketProtocol.IPPROTO_TCP, (so1, so2) => {
178                                 Linger linger = new Linger {
179                                         l_onoff = 1,
180                                         l_linger = 42,
181                                 };
182                                 // Set SO_LINGER
183                                 if (Syscall.setsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_LINGER, linger) < 0)
184                                         UnixMarshal.ThrowExceptionForLastError ();
185
186                                 // Get and check SO_LINGER
187                                 Linger value;
188                                 if (Syscall.getsockopt (so1, UnixSocketProtocol.SOL_SOCKET, UnixSocketOptionName.SO_LINGER, out value) < 0)
189                                         UnixMarshal.ThrowExceptionForLastError ();
190                                 Assert.AreEqual (linger, value);
191                         });
192                 }
193
194                 [Test]
195                 public void Shutdown ()
196                 {
197                         WithSocketPair ((so1, so2) => {
198                                 if (Syscall.shutdown (so1, ShutdownOption.SHUT_WR) < 0)
199                                         UnixMarshal.ThrowExceptionForLastError ();
200
201                                 var buffer2 = new byte[1024];
202                                 long ret = Syscall.recv (so2, buffer2, (ulong) buffer2.Length, 0);
203                                 if (ret < 0)
204                                         UnixMarshal.ThrowExceptionForLastError ();
205
206                                 Assert.AreEqual (ret, 0);
207                         });
208                 }
209         }
210 }
211
212 // vim: noexpandtab
213 // Local Variables: 
214 // tab-width: 4
215 // c-basic-offset: 4
216 // indent-tabs-mode: t
217 // End: