Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
testpolling.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 John Selbie
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 #include "commonincludes.hpp"
18 #include "unittest.h"
19 
20 #include "polling.h"
21 
22 #include "testpolling.h"
23 
25 {
26  ;
27 }
28 
30 {
31  TestUnInit();
32 }
33 
35 {
36  HRESULT hr = S_OK;
37 
38 #ifdef HAS_EPOLL
40  ChkA(Test1());
41  ChkA(Test2());
42 #endif
43 
45  ChkA(Test1());
46  ChkA(Test2());
47  ChkA(Test3());
48 Cleanup:
49  return hr;
50 }
51 
53 {
54  size_t size = _pipes.size();
56 
57  for (size_t index = 0; index < size; index++)
58  {
59  close(_pipes[index].readpipe);
60  close(_pipes[index].writepipe);
61  }
62 
63  _pipes.clear();
64 
65 }
66 
68 {
69  HRESULT hr = S_OK;
70  int result;
71  int flags;
72 
73  flags = ::fcntl(fd, F_GETFL, 0);
74 
75  ChkIfA(flags == -1, ERRNOHR);
76 
77  flags |= O_NONBLOCK;
78 
79  result = fcntl(fd , F_SETFL , flags);
80 
81  ChkIfA(result == -1, ERRNOHR);
82 
83 Cleanup:
84  return hr;
85 
86 }
87 
89 {
90  HRESULT hr = S_OK;
91  PipePair pp = {};
92  int ret = -1;
93  int fds[2];
94  ret = ::pipe(fds);
95 
96  ChkIfA(ret == -1, ERRNOHR);
97 
98  pp.readpipe = fds[0];
99  pp.writepipe = fds[1];
100  pp.fDataPending = false;
101 
104 
105  _pipes.push_back(pp);
106 
107  ChkA(_spPolling->Add(fds[0], IPOLLING_READ));
108 
109 Cleanup:
110  return hr;
111 }
112 
113 HRESULT CTestPolling::TestInit(size_t sizePolling, size_t sizePipeArray)
114 {
115  HRESULT hr = S_OK;
116 
117  TestUnInit();
118 
120 
121  for (size_t index = 0; index < sizePipeArray; index++)
122  {
124  }
125 
126 Cleanup:
127  return hr;
128 }
129 
131 {
132  HRESULT hr = S_OK;
133  char ch = 'x';
134  int ret = -1;
135 
136  ret = write(pPair->writepipe, &ch, 1);
137  ChkIfA(ret < 0, ERRNOHR);
138  ChkIfA(ret == 0, E_UNEXPECTED);
139  pPair->fDataPending = true;
140 
141 Cleanup:
142  return hr;
143 }
144 
145 HRESULT CTestPolling::ConsumeEvent(int* pFD, int* pCount)
146 {
147  HRESULT hr = S_OK;
148  HRESULT hrResult = S_OK;
149  PollEvent event;
150  char ch;
151  int result;
152  int count = 0;
153  int fd = -1;
154  int pipesindex = -1;
155 
156  hrResult = _spPolling->WaitForNextEvent(&event, 0);
157  ChkA(hrResult);
158 
159  ChkIfA(hrResult == S_FALSE, S_FALSE);
160 
161  fd = event.fd;
162 
163  while (true)
164  {
165  result = ::read(fd, &ch, 1);
166  if (result <= 0)
167  {
168  break;
169  }
170  count++;
171  }
172 
173  pipesindex = FindPipePairIndex(fd);
174  ChkIfA(pipesindex == -1, E_UNEXPECTED);
175 
176  ChkIfA(count == 0, E_UNEXPECTED);
177 
178  ChkIfA(_pipes[pipesindex].fDataPending == false, E_UNEXPECTED);
179  _pipes[pipesindex].fDataPending = false;
180 
181 Cleanup:
182  if (pFD)
183  {
184  *pFD = fd;
185  }
186  if (pCount)
187  {
188  *pCount = count;
189  }
190  return hr;
191 }
192 
194 {
195  size_t size = _pipes.size();
196 
197  for (size_t index = 0; index < size; index++)
198  {
199  if ((_pipes[index].readpipe == fd) || (_pipes[index].writepipe == fd))
200  {
201  return index;
202  }
203  }
204 
205  return -1;
206 }
207 
209 {
210  size_t size = _pipes.size();
211  size_t count = 0;
212 
213  for (size_t index = 0; index < size; index++)
214  {
215  if (_pipes[index].fDataPending)
216  {
217  count++;
218  }
219  }
220 
221  return count;
222 }
223 
225 {
226  HRESULT hr = S_OK;
227 
228  size_t size = _pipes.size();
229 
230  ChkIfA(pipeindex < 0, E_FAIL);
231  ChkIfA(pipeindex >= (int)size, E_FAIL);
232 
233  ChkA(_spPolling->Remove(_pipes[pipeindex].readpipe));
234 
235  close(_pipes[pipeindex].readpipe);
236  _pipes[pipeindex].readpipe = -1;
237 
238  close(_pipes[pipeindex].writepipe);
239  _pipes[pipeindex].writepipe = -1;
240 
241  _pipes.erase(_pipes.begin()+pipeindex);
242 
243 Cleanup:
244  return hr;
245 }
246 
247 
248 
249 // simplest of all tests. Just set a file descriptor and see that it's available
250 // repeat many times
252 {
253  HRESULT hr = S_OK;
254  HRESULT hrResult;
255  size_t size;
256  PollEvent event;
257  int fd;
258  int count = 0;
259 
260  srand(100);
261 
262  ChkA(TestInit(10, 10));
263 
264  size = _pipes.size();
265 
266  hrResult = _spPolling->WaitForNextEvent(&event, 0);
267  ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
268 
269  // one event at a time model
270  for (int index = 0; index < 100; index++)
271  {
272 
273  size_t item = rand() % size;
274 
275  ChkA(WritePipe(&_pipes[item]));
276 
277  ConsumeEvent(&fd, &count);
278 
279  ChkIfA(fd != _pipes[item].readpipe, E_UNEXPECTED);
280  ChkIfA(count != 1, E_UNEXPECTED);
281  }
282 
283  hrResult = _spPolling->WaitForNextEvent(&event, 0);
284  ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
285 
286 Cleanup:
287  return hr;
288 }
289 
290 
291 
292 // create a polling set
294 {
295  // simulate the following events in random order:
296  // socket added (did it succeed as expected)
297  // incoming data (write to a random pipe)
298  // WaitForNextEvent called (did it return an expected result/socket)
299  // Remove socket last notified about
300 
301  HRESULT hr = S_OK;
302  HRESULT hrResult;
303  PollEvent event;
304  const size_t c_maxSockets = 10;
305 
306  srand(100);
307 
308  ChkA(TestInit(c_maxSockets, 0));
309 
310 
311  hrResult = _spPolling->WaitForNextEvent(&event, 0);
312  ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
313 
314 
315  for (size_t index = 0; index < 1000; index++)
316  {
317  int randresult = ::rand() % 4;
318 
319  switch (randresult)
320  {
321  case 0:
322  {
323  // simulate a new socket being added
324  if (_pipes.size() >= c_maxSockets)
325  {
326  continue;
327  }
328 
330 
331  break;
332  }
333 
334  case 1:
335  {
336  // simulate incoming data
337  size_t size = _pipes.size();
338  size_t itemindex;
339 
340  if (size == 0)
341  {
342  continue;
343  }
344 
345  itemindex = rand() % size;
346  ChkA(WritePipe(&_pipes[itemindex]));
347 
348  break;
349  }
350 
351  case 2:
352  case 3:
353  {
354  int fd;
355  size_t pending = GetPendingCount();
356  if (pending == 0)
357  {
358  continue;
359  }
360 
361  ChkA(ConsumeEvent(&fd, NULL));
362 
363  if (randresult == 3)
364  {
365  // simulate removing this pipe from the set
367  }
368  break;
369  } // case
370  } // switch
371  } // for
372 
373 Cleanup:
374  return hr;
375 }
376 
378 {
379  HRESULT hr = S_OK;
380 
381  const size_t c_maxSockets = 10;
382 
383  ChkA(TestInit(c_maxSockets, 0));
384 
386  ChkA(_spPolling->Remove(3));
390  ChkA(_spPolling->Remove(5));
393  ChkA(_spPolling->Remove(7));
397  ChkA(_spPolling->Remove(11));
402  ChkA(_spPolling->Remove(13));
403 
404 Cleanup:
405  return hr;
406 
407 }
408 
409 
#define S_OK
Definition: hresult.h:46
const uint32_t IPOLLING_TYPE_EPOLL
Definition: polling.h:51
HRESULT RemovePipe(int pipeindex)
virtual HRESULT WaitForNextEvent(PollEvent *pPollEvent, int timeoutMilliseconds)=0
void TestUnInit()
Definition: testpolling.cpp:52
HRESULT CreatePollingInstance(uint32_t type, size_t maxSockets, IPolling **ppPolling)
Definition: polling.cpp:519
HRESULT Run()
Definition: testpolling.cpp:34
const uint32_t IPOLLING_TYPE_POLL
Definition: polling.h:52
HRESULT CreateAndAddPipe()
Definition: testpolling.cpp:88
#define S_FALSE
Definition: hresult.h:47
CRefCountedPtr< IPolling > _spPolling
Definition: testpolling.h:32
#define E_UNEXPECTED
Definition: hresult.h:48
HRESULT Test2()
int readpipe
Definition: testpolling.h:22
bool fDataPending
Definition: testpolling.h:24
virtual HRESULT Add(int fd, uint32_t eventflags)=0
std::vector< PipePair > _pipes
Definition: testpolling.h:33
const uint32_t IPOLLING_READ
Definition: polling.h:29
int writepipe
Definition: testpolling.h:23
HRESULT TestInit(size_t sizePolling, size_t sizePipeArray)
virtual HRESULT Remove(int fd)=0
T ** GetPointerPointer()
uint32_t _polltype
Definition: testpolling.h:35
void ReleaseAndClear()
int32_t HRESULT
Definition: hresult.h:22
HRESULT Test3()
HRESULT ConsumeEvent(int *pFD, int *pCount)
int FindPipePairIndex(int fd)
HRESULT WritePipe(PipePair *pPipePair)
size_t GetPendingCount()
HRESULT Test1()
#define E_FAIL
Definition: hresult.h:56
#define ChkA(expr)
Definition: chkmacros.h:73
HRESULT SetNonBlocking(int fd)
Definition: testpolling.cpp:67
#define ChkIfA(expr, hrerror)
Definition: chkmacros.h:84
#define ERRNOHR
Definition: hresult.h:42