• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 //       Some ideas of improvements:
12 //       Break out common init and maybe terminate to separate function(s).
13 //       How much trace should we have enabled?
14 //       API error counter, to print info and return -1 if any error.
15 
16 #include <assert.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #if defined(_WIN32)
22 #include <conio.h>
23 #endif
24 
25 #include "webrtc/voice_engine/test/auto_test/voe_stress_test.h"
26 
27 #include "webrtc/base/scoped_ptr.h"
28 #include "webrtc/system_wrappers/include/sleep.h"
29 #include "webrtc/test/channel_transport/channel_transport.h"
30 #include "webrtc/voice_engine/test/auto_test/voe_standard_test.h"
31 #include "webrtc/voice_engine/test/auto_test/voe_test_defines.h"
32 #include "webrtc/voice_engine/voice_engine_defines.h"  // defines build macros
33 
34 using namespace webrtc;
35 using namespace test;
36 
37 namespace voetest {
38 
39 #define VALIDATE_STRESS(expr)                                   \
40     if (expr)                                                   \
41     {                                                           \
42         printf("Error at line: %i, %s \n", __LINE__, #expr);    \
43         printf("Error code: %i \n", base->LastError());  \
44     }
45 
46 #ifdef _WIN32
47 // Pause if supported
48 #define PAUSE_OR_SLEEP(x) PAUSE;
49 #else
50 // Sleep a bit instead if pause not supported
51 #define PAUSE_OR_SLEEP(x) SleepMs(x);
52 #endif
53 
DoTest()54 int VoEStressTest::DoTest() {
55   int test(-1);
56   while (test != 0) {
57     test = MenuSelection();
58     switch (test) {
59       case 0:
60         // Quit stress test
61         break;
62       case 1:
63         // All tests
64         StartStopTest();
65         CreateDeleteChannelsTest();
66         MultipleThreadsTest();
67         break;
68       case 2:
69         StartStopTest();
70         break;
71       case 3:
72         CreateDeleteChannelsTest();
73         break;
74       case 4:
75         MultipleThreadsTest();
76         break;
77       default:
78         // Should not be possible
79         printf("Invalid selection! (Test code error)\n");
80         assert(false);
81     }  // switch
82   }  // while
83 
84   return 0;
85 }
86 
MenuSelection()87 int VoEStressTest::MenuSelection() {
88   printf("------------------------------------------------\n");
89   printf("Select stress test\n\n");
90   printf(" (0)  Quit\n");
91   printf(" (1)  All\n");
92   printf("- - - - - - - - - - - - - - - - - - - - - - - - \n");
93   printf(" (2)  Start/stop\n");
94   printf(" (3)  Create/delete channels\n");
95   printf(" (4)  Multiple threads\n");
96 
97   const int maxMenuSelection = 4;
98   int selection(-1);
99 
100   while ((selection < 0) || (selection > maxMenuSelection)) {
101     printf("\n: ");
102     int retval = scanf("%d", &selection);
103     if ((retval != 1) || (selection < 0) || (selection > maxMenuSelection)) {
104       printf("Invalid selection!\n");
105     }
106   }
107 
108   return selection;
109 }
110 
StartStopTest()111 int VoEStressTest::StartStopTest() {
112   printf("------------------------------------------------\n");
113   printf("Running start/stop test\n");
114   printf("------------------------------------------------\n");
115 
116   printf("\nNOTE: this thest will fail after a while if Core audio is used\n");
117   printf("because MS returns AUDCLNT_E_CPUUSAGE_EXCEEDED (VoE Error 10013).\n");
118 
119   // Get sub-API pointers
120   VoEBase* base = _mgr.BasePtr();
121   VoENetwork* voe_network = _mgr.NetworkPtr();
122 
123   // Set trace
124   //     VALIDATE_STRESS(base->SetTraceFileName(
125   //         GetFilename("VoEStressTest_StartStop_trace.txt")));
126   //     VALIDATE_STRESS(base->SetDebugTraceFileName(
127   //         GetFilename("VoEStressTest_StartStop_trace_debug.txt")));
128   //     VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
129   //         kTraceWarning | kTraceError |
130   //         kTraceCritical | kTraceApiCall |
131   //         kTraceMemory | kTraceInfo));
132   VALIDATE_STRESS(base->Init());
133   VALIDATE_STRESS(base->CreateChannel());
134 
135   ///////////// Start test /////////////
136 
137   int numberOfLoops(2000);
138   int loopSleep(200);
139   int i(0);
140   int markInterval(20);
141 
142   printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
143          numberOfLoops, loopSleep, markInterval);
144   printf("Test will take approximately %d minutes. \n",
145          numberOfLoops * loopSleep / 1000 / 60 + 1);
146 
147   rtc::scoped_ptr<VoiceChannelTransport> voice_channel_transport(
148       new VoiceChannelTransport(voe_network, 0));
149 
150   for (i = 0; i < numberOfLoops; ++i) {
151     voice_channel_transport->SetSendDestination("127.0.0.1", 4800);
152     voice_channel_transport->SetLocalReceiver(4800);
153     VALIDATE_STRESS(base->StartReceive(0));
154     VALIDATE_STRESS(base->StartPlayout(0));
155     VALIDATE_STRESS(base->StartSend(0));
156     if (!(i % markInterval))
157       MARK();
158     SleepMs(loopSleep);
159     VALIDATE_STRESS(base->StopSend(0));
160     VALIDATE_STRESS(base->StopPlayout(0));
161     VALIDATE_STRESS(base->StopReceive(0));
162   }
163   ANL();
164 
165   VALIDATE_STRESS(voice_channel_transport->SetSendDestination("127.0.0.1",
166                                                               4800));
167   VALIDATE_STRESS(voice_channel_transport->SetLocalReceiver(4800));
168   VALIDATE_STRESS(base->StartReceive(0));
169   VALIDATE_STRESS(base->StartPlayout(0));
170   VALIDATE_STRESS(base->StartSend(0));
171   printf("Verify that audio is good. \n");
172   PAUSE_OR_SLEEP(20000);
173   VALIDATE_STRESS(base->StopSend(0));
174   VALIDATE_STRESS(base->StopPlayout(0));
175   VALIDATE_STRESS(base->StopReceive(0));
176 
177   ///////////// End test /////////////
178 
179 
180   // Terminate
181   VALIDATE_STRESS(base->DeleteChannel(0));
182   VALIDATE_STRESS(base->Terminate());
183 
184   printf("Test finished \n");
185 
186   return 0;
187 }
188 
CreateDeleteChannelsTest()189 int VoEStressTest::CreateDeleteChannelsTest() {
190   printf("------------------------------------------------\n");
191   printf("Running create/delete channels test\n");
192   printf("------------------------------------------------\n");
193 
194   // Get sub-API pointers
195   VoEBase* base = _mgr.BasePtr();
196 
197   // Set trace
198   //     VALIDATE_STRESS(base->SetTraceFileName(
199   //          GetFilename("VoEStressTest_CreateChannels_trace.txt")));
200   //     VALIDATE_STRESS(base->SetDebugTraceFileName(
201   //          GetFilename("VoEStressTest_CreateChannels_trace_debug.txt")));
202   //     VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
203   //         kTraceWarning | kTraceError |
204   //         kTraceCritical | kTraceApiCall |
205   //         kTraceMemory | kTraceInfo));
206   VALIDATE_STRESS(base->Init());
207 
208   ///////////// Start test /////////////
209 
210   int numberOfLoops(10000);
211   int loopSleep(10);
212   int i(0);
213   int markInterval(200);
214 
215   printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
216          numberOfLoops, loopSleep, markInterval);
217   printf("Test will take approximately %d minutes. \n",
218          numberOfLoops * loopSleep / 1000 / 60 + 1);
219 
220   //       Some possible extensions include:
221   //       Different sleep times (fixed or random) or zero.
222   //       Start call on all or some channels.
223   //       Two parts: first have a slight overweight to creating channels,
224   //       then to deleting. (To ensure we hit max channels and go to zero.)
225   //       Make sure audio is OK after test has finished.
226 
227   // Set up, start with maxChannels/2 channels
228   const int maxChannels = 100;
229   VALIDATE_STRESS(maxChannels < 1); // Should always have at least one channel
230   bool* channelState = new bool[maxChannels];
231   memset(channelState, 0, maxChannels * sizeof(bool));
232   int channel(0);
233   int noOfActiveChannels(0);
234   for (i = 0; i < (maxChannels / 2); ++i) {
235     channel = base->CreateChannel();
236     VALIDATE_STRESS(channel < 0);
237     if (channel >= 0) {
238       channelState[channel] = true;
239       ++noOfActiveChannels;
240     }
241   }
242   srand((unsigned int) time(NULL));
243   bool action(false);
244   double rnd(0.0);
245   int res(0);
246 
247   // Create/delete channels with slight
248   for (i = 0; i < numberOfLoops; ++i) {
249     // Randomize action (create or delete channel)
250     action = rand() <= (RAND_MAX / 2);
251     if (action) {
252       if (noOfActiveChannels < maxChannels) {
253         // Create new channel
254         channel = base->CreateChannel();
255         VALIDATE_STRESS(channel < 0);
256         if (channel >= 0) {
257           channelState[channel] = true;
258           ++noOfActiveChannels;
259         }
260       }
261     } else {
262       if (noOfActiveChannels > 0) {
263         // Delete random channel that's created [0, maxChannels - 1]
264         do {
265           rnd = static_cast<double> (rand());
266           channel = static_cast<int> (rnd /
267                                       (static_cast<double> (RAND_MAX) + 1.0f) *
268                                       maxChannels);
269         } while (!channelState[channel]); // Must find a created channel
270 
271         res = base->DeleteChannel(channel);
272         VALIDATE_STRESS(0 != res);
273         if (0 == res) {
274           channelState[channel] = false;
275           --noOfActiveChannels;
276         }
277       }
278     }
279 
280     if (!(i % markInterval))
281       MARK();
282     SleepMs(loopSleep);
283   }
284   ANL();
285 
286   delete[] channelState;
287 
288   ///////////// End test /////////////
289 
290 
291   // Terminate
292   VALIDATE_STRESS(base->Terminate()); // Deletes all channels
293 
294   printf("Test finished \n");
295 
296   return 0;
297 }
298 
MultipleThreadsTest()299 int VoEStressTest::MultipleThreadsTest() {
300   printf("------------------------------------------------\n");
301   printf("Running multiple threads test\n");
302   printf("------------------------------------------------\n");
303 
304   // Get sub-API pointers
305   VoEBase* base = _mgr.BasePtr();
306 
307   // Set trace
308   //     VALIDATE_STRESS(base->SetTraceFileName(
309   //        GetFilename("VoEStressTest_MultipleThreads_trace.txt")));
310   //     VALIDATE_STRESS(base->SetDebugTraceFileName(
311   //        GetFilename("VoEStressTest_MultipleThreads_trace_debug.txt")));
312   //     VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
313   //        kTraceWarning | kTraceError |
314   //        kTraceCritical | kTraceApiCall |
315   //        kTraceMemory | kTraceInfo));
316 
317   // Init
318   VALIDATE_STRESS(base->Init());
319   VALIDATE_STRESS(base->CreateChannel());
320 
321   ///////////// Start test /////////////
322 
323   int numberOfLoops(10000);
324   int loopSleep(0);
325   int i(0);
326   int markInterval(1000);
327 
328   printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
329          numberOfLoops, loopSleep, markInterval);
330   printf("Test will take approximately %d minutes. \n",
331          numberOfLoops * loopSleep / 1000 / 60 + 1);
332 
333   srand((unsigned int) time(NULL));
334   int rnd(0);
335 
336   // Start extra thread
337   _ptrExtraApiThread.reset(
338       new rtc::PlatformThread(RunExtraApi, this, "StressTestExtraApiThread"));
339   _ptrExtraApiThread->Start();
340 
341   //       Some possible extensions include:
342   //       Add more API calls to randomize
343   //       More threads
344   //       Different sleep times (fixed or random).
345   //       Make sure audio is OK after test has finished.
346 
347   // Call random API functions here and in extra thread, ignore any error
348   for (i = 0; i < numberOfLoops; ++i) {
349     // This part should be equal to the marked part in the extra thread
350     // --- BEGIN ---
351     rnd = rand();
352     if (rnd < (RAND_MAX / 2)) {
353       // Start playout
354       base->StartPlayout(0);
355     } else {
356       // Stop playout
357       base->StopPlayout(0);
358     }
359     // --- END ---
360 
361     if (!(i % markInterval))
362       MARK();
363     SleepMs(loopSleep);
364   }
365   ANL();
366 
367   // Stop extra thread
368   _ptrExtraApiThread->Stop();
369 
370   ///////////// End test /////////////
371 
372   // Terminate
373   VALIDATE_STRESS(base->Terminate()); // Deletes all channels
374 
375   printf("Test finished \n");
376 
377   return 0;
378 }
379 
380 // Thread functions
381 
RunExtraApi(void * ptr)382 bool VoEStressTest::RunExtraApi(void* ptr) {
383   return static_cast<VoEStressTest*> (ptr)->ProcessExtraApi();
384 }
385 
ProcessExtraApi()386 bool VoEStressTest::ProcessExtraApi() {
387   // Prepare
388   VoEBase* base = _mgr.BasePtr();
389   int rnd(0);
390 
391   // Call random API function, ignore any error
392 
393   // This part should be equal to the marked part in the main thread
394   // --- BEGIN ---
395   rnd = rand();
396   if (rnd < (RAND_MAX / 2)) {
397     // Start playout
398     base->StartPlayout(0);
399   } else {
400     // Stop playout
401     base->StopPlayout(0);
402   }
403   // --- END ---
404 
405   return true;
406 }
407 
408 }  // namespace voetest
409