Home | History | Annotate | Download | only in auto_test
      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 
     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 
     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 
    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 
    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 
    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 
    382 bool VoEStressTest::RunExtraApi(void* ptr) {
    383   return static_cast<VoEStressTest*> (ptr)->ProcessExtraApi();
    384 }
    385 
    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