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