455 lines
13 KiB
C++
455 lines
13 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
// Some ideas of improvements:
|
|
// Break out common init and maybe terminate to separate function(s).
|
|
// How much trace should we have enabled?
|
|
// API error counter, to print info and return -1 if any error.
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <cassert>
|
|
#if defined(_WIN32)
|
|
#include <conio.h>
|
|
#endif
|
|
|
|
#include "voe_stress_test.h"
|
|
#include "voe_standard_test.h"
|
|
|
|
#include "../../source/voice_engine_defines.h" // defines build macros
|
|
|
|
#include "thread_wrapper.h"
|
|
|
|
using namespace webrtc;
|
|
|
|
namespace voetest {
|
|
|
|
#define VALIDATE_STRESS(expr) \
|
|
if (expr) \
|
|
{ \
|
|
printf("Error at line: %i, %s \n", __LINE__, #expr); \
|
|
printf("Error code: %i \n", base->LastError()); \
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
// Pause if supported
|
|
#define PAUSE_OR_SLEEP(x) PAUSE;
|
|
#else
|
|
// Sleep a bit instead if pause not supported
|
|
#define PAUSE_OR_SLEEP(x) SLEEP(x);
|
|
#endif
|
|
|
|
extern char* GetFilename(char* filename);
|
|
extern const char* GetFilename(const char* filename);
|
|
extern int GetResource(char* resource, char* dest, int destLen);
|
|
extern char* GetResource(char* resource);
|
|
extern const char* GetResource(const char* resource);
|
|
|
|
|
|
const char* VoEStressTest::_key = "====YUtFWRAAAAADBtIHgAAAAAEAAAAcAAAAAQBHU0ds"
|
|
"b2JhbCBJUCBTb3VuZAAC\nAAAAIwAAAExpY2Vuc2VkIHRvIE5vcnRlbCBOZXR3cm9rcwAAAAA"
|
|
"xAAAAZxZ7/u0M\niFYyTwSwko5Uutf7mh8S0O4rYZYTFidbzQeuGonuL17F/2oD/2pfDp3jL4"
|
|
"Rf3z/A\nnlJsEJgEtASkDNFuwLILjGY0pzjjAYQp3pCl6z6k2MtE06AirdjGLYCjENpq/opX"
|
|
"\nOrs3sIuwdYK5va/aFcsjBDmlsGCUM48RDYG9s23bIHYafXUC4ofOaubbZPWiPTmL\nEVJ8WH"
|
|
"4F9pgNjALc14oJXfON7r/3\n=EsLx";
|
|
|
|
|
|
int VoEStressTest::DoTest()
|
|
{
|
|
int test(-1);
|
|
while (test != 0)
|
|
{
|
|
test = MenuSelection();
|
|
switch (test)
|
|
{
|
|
case 0:
|
|
// Quit stress test
|
|
break;
|
|
case 1:
|
|
// All tests
|
|
StartStopTest();
|
|
CreateDeleteChannelsTest();
|
|
MultipleThreadsTest();
|
|
break;
|
|
case 2:
|
|
StartStopTest();
|
|
break;
|
|
case 3:
|
|
CreateDeleteChannelsTest();
|
|
break;
|
|
case 4:
|
|
MultipleThreadsTest();
|
|
break;
|
|
default:
|
|
// Should not be possible
|
|
printf("Invalid selection! (Test code error)\n");
|
|
assert(false);
|
|
} // switch
|
|
} // while
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int VoEStressTest::MenuSelection()
|
|
{
|
|
printf("------------------------------------------------\n");
|
|
printf("Select stress test\n\n");
|
|
printf(" (0) Quit\n");
|
|
printf(" (1) All\n");
|
|
printf("- - - - - - - - - - - - - - - - - - - - - - - - \n");
|
|
printf(" (2) Start/stop\n");
|
|
printf(" (3) Create/delete channels\n");
|
|
printf(" (4) Multiple threads\n");
|
|
|
|
const int maxMenuSelection = 4;
|
|
int selection(-1);
|
|
int dummy(0);
|
|
|
|
while ((selection < 0) || (selection > maxMenuSelection))
|
|
{
|
|
printf("\n: ");
|
|
dummy = scanf("%d", &selection);
|
|
if ((selection < 0) || (selection > maxMenuSelection))
|
|
{
|
|
printf("Invalid selection!\n");
|
|
}
|
|
}
|
|
|
|
return selection;
|
|
}
|
|
|
|
|
|
int VoEStressTest::StartStopTest()
|
|
{
|
|
printf("------------------------------------------------\n");
|
|
printf("Running start/stop test\n");
|
|
printf("------------------------------------------------\n");
|
|
|
|
printf("\nNOTE: this thest will fail after a while if Core audio is used\n");
|
|
printf("because MS returns AUDCLNT_E_CPUUSAGE_EXCEEDED (VoE Error 10013).\n");
|
|
|
|
// Get sub-API pointers
|
|
VoEBase* base = _mgr.BasePtr();
|
|
|
|
// Set trace
|
|
// VALIDATE_STRESS(base->SetTraceFileName(
|
|
// GetFilename("VoEStressTest_StartStop_trace.txt")));
|
|
// VALIDATE_STRESS(base->SetDebugTraceFileName(
|
|
// GetFilename("VoEStressTest_StartStop_trace_debug.txt")));
|
|
// VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
|
|
// kTraceWarning | kTraceError |
|
|
// kTraceCritical | kTraceApiCall |
|
|
// kTraceMemory | kTraceInfo));
|
|
|
|
VALIDATE_STRESS(base->Init());
|
|
VALIDATE_STRESS(base->CreateChannel());
|
|
|
|
|
|
///////////// Start test /////////////
|
|
|
|
int numberOfLoops(2000);
|
|
int loopSleep(200);
|
|
int i(0);
|
|
int markInterval(20);
|
|
|
|
printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
|
|
numberOfLoops, loopSleep, markInterval);
|
|
printf("Test will take approximately %d minutes. \n",
|
|
numberOfLoops*loopSleep/1000/60+1);
|
|
|
|
for (i=0; i<numberOfLoops; ++i)
|
|
{
|
|
VALIDATE_STRESS(base->SetLocalReceiver(0, 4800));
|
|
VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1"));
|
|
VALIDATE_STRESS(base->StartReceive(0));
|
|
VALIDATE_STRESS(base->StartPlayout(0));
|
|
VALIDATE_STRESS(base->StartSend(0));
|
|
if (!(i % markInterval)) MARK();
|
|
SLEEP(loopSleep);
|
|
VALIDATE_STRESS(base->StopSend(0));
|
|
VALIDATE_STRESS(base->StopPlayout(0));
|
|
VALIDATE_STRESS(base->StopReceive(0));
|
|
}
|
|
ANL();
|
|
|
|
VALIDATE_STRESS(base->SetLocalReceiver(0, 4800));
|
|
VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1"));
|
|
VALIDATE_STRESS(base->StartReceive(0));
|
|
VALIDATE_STRESS(base->StartPlayout(0));
|
|
VALIDATE_STRESS(base->StartSend(0));
|
|
printf("Verify that audio is good. \n");
|
|
PAUSE_OR_SLEEP(20000);
|
|
VALIDATE_STRESS(base->StopSend(0));
|
|
VALIDATE_STRESS(base->StopPlayout(0));
|
|
VALIDATE_STRESS(base->StopReceive(0));
|
|
|
|
///////////// End test /////////////
|
|
|
|
|
|
// Terminate
|
|
VALIDATE_STRESS(base->DeleteChannel(0));
|
|
VALIDATE_STRESS(base->Terminate());
|
|
|
|
printf("Test finished \n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int VoEStressTest::CreateDeleteChannelsTest()
|
|
{
|
|
printf("------------------------------------------------\n");
|
|
printf("Running create/delete channels test\n");
|
|
printf("------------------------------------------------\n");
|
|
|
|
// Get sub-API pointers
|
|
VoEBase* base = _mgr.BasePtr();
|
|
|
|
// Set trace
|
|
// VALIDATE_STRESS(base->SetTraceFileName(
|
|
// GetFilename("VoEStressTest_CreateChannels_trace.txt")));
|
|
// VALIDATE_STRESS(base->SetDebugTraceFileName(
|
|
// GetFilename("VoEStressTest_CreateChannels_trace_debug.txt")));
|
|
// VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
|
|
// kTraceWarning | kTraceError |
|
|
// kTraceCritical | kTraceApiCall |
|
|
// kTraceMemory | kTraceInfo));
|
|
|
|
VALIDATE_STRESS(base->Init());
|
|
|
|
///////////// Start test /////////////
|
|
|
|
int numberOfLoops(10000);
|
|
int loopSleep(10);
|
|
int i(0);
|
|
int markInterval(200);
|
|
|
|
printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
|
|
numberOfLoops, loopSleep, markInterval);
|
|
printf("Test will take approximately %d minutes. \n",
|
|
numberOfLoops * loopSleep / 1000 / 60 + 1);
|
|
|
|
// Some possible extensions include:
|
|
// Different sleep times (fixed or random) or zero.
|
|
// Start call on all or some channels.
|
|
// Two parts: first have a slight overweight to creating channels,
|
|
// then to deleting. (To ensure we hit max channels and go to zero.)
|
|
// Make sure audio is OK after test has finished.
|
|
|
|
// Set up, start with maxChannels/2 channels
|
|
const int maxChannels = base->MaxNumOfChannels();
|
|
VALIDATE_STRESS(maxChannels < 1); // Should always have at least one channel
|
|
bool* channelState = new bool[maxChannels];
|
|
memset(channelState, 0, maxChannels*sizeof(bool));
|
|
int channel(0);
|
|
int noOfActiveChannels(0);
|
|
for (i=0; i<(maxChannels/2); ++i)
|
|
{
|
|
channel = base->CreateChannel();
|
|
VALIDATE_STRESS(channel < 0);
|
|
if (channel >= 0)
|
|
{
|
|
channelState[channel] = true;
|
|
++noOfActiveChannels;
|
|
}
|
|
}
|
|
srand((unsigned int)time(NULL));
|
|
bool action(false);
|
|
double rnd(0.0);
|
|
int res(0);
|
|
|
|
// Create/delete channels with slight
|
|
for (i=0; i<numberOfLoops; ++i)
|
|
{
|
|
// Randomize action (create or delete channel)
|
|
action = rand() <= (RAND_MAX / 2);
|
|
if (action)
|
|
{
|
|
if (noOfActiveChannels < maxChannels)
|
|
{
|
|
// Create new channel
|
|
channel = base->CreateChannel();
|
|
VALIDATE_STRESS(channel < 0);
|
|
if (channel >= 0)
|
|
{
|
|
channelState[channel] = true;
|
|
++noOfActiveChannels;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (noOfActiveChannels > 0)
|
|
{
|
|
// Delete random channel that's created [0, maxChannels - 1]
|
|
do
|
|
{
|
|
rnd = static_cast<double>(rand());
|
|
channel = static_cast<int>(rnd /
|
|
(static_cast<double>(RAND_MAX) + 1.0f) * maxChannels);
|
|
} while (!channelState[channel]); // Must find a created channel
|
|
|
|
res = base->DeleteChannel(channel);
|
|
VALIDATE_STRESS(0 != res);
|
|
if (0 == res)
|
|
{
|
|
channelState[channel] = false;
|
|
--noOfActiveChannels;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(i % markInterval)) MARK();
|
|
SLEEP(loopSleep);
|
|
}
|
|
ANL();
|
|
|
|
delete [] channelState;
|
|
|
|
///////////// End test /////////////
|
|
|
|
|
|
// Terminate
|
|
VALIDATE_STRESS(base->Terminate()); // Deletes all channels
|
|
|
|
printf("Test finished \n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int VoEStressTest::MultipleThreadsTest()
|
|
{
|
|
printf("------------------------------------------------\n");
|
|
printf("Running multiple threads test\n");
|
|
printf("------------------------------------------------\n");
|
|
|
|
// Get sub-API pointers
|
|
VoEBase* base = _mgr.BasePtr();
|
|
|
|
// Set trace
|
|
// VALIDATE_STRESS(base->SetTraceFileName(
|
|
// GetFilename("VoEStressTest_MultipleThreads_trace.txt")));
|
|
// VALIDATE_STRESS(base->SetDebugTraceFileName(
|
|
// GetFilename("VoEStressTest_MultipleThreads_trace_debug.txt")));
|
|
// VALIDATE_STRESS(base->SetTraceFilter(kTraceStateInfo |
|
|
// kTraceWarning | kTraceError |
|
|
// kTraceCritical | kTraceApiCall |
|
|
// kTraceMemory | kTraceInfo));
|
|
|
|
// Init
|
|
VALIDATE_STRESS(base->Init());
|
|
VALIDATE_STRESS(base->CreateChannel());
|
|
|
|
|
|
///////////// Start test /////////////
|
|
|
|
int numberOfLoops(10000);
|
|
int loopSleep(0);
|
|
int i(0);
|
|
int markInterval(1000);
|
|
|
|
printf("Running %d loops with %d ms sleep. Mark every %d loop. \n",
|
|
numberOfLoops, loopSleep, markInterval);
|
|
printf("Test will take approximately %d minutes. \n",
|
|
numberOfLoops * loopSleep / 1000 / 60 + 1);
|
|
|
|
srand((unsigned int)time(NULL));
|
|
int rnd(0);
|
|
|
|
// Start extra thread
|
|
const char* threadName = "StressTest Extra API Thread";
|
|
_ptrExtraApiThread = ThreadWrapper::CreateThread(
|
|
RunExtraApi, this, kNormalPriority, threadName);
|
|
unsigned int id(0);
|
|
VALIDATE_STRESS(!_ptrExtraApiThread->Start(id));
|
|
|
|
// Some possible extensions include:
|
|
// Add more API calls to randomize
|
|
// More threads
|
|
// Different sleep times (fixed or random).
|
|
// Make sure audio is OK after test has finished.
|
|
|
|
// Call random API functions here and in extra thread, ignore any error
|
|
for (i=0; i<numberOfLoops; ++i)
|
|
{
|
|
// This part should be equal to the marked part in the extra thread
|
|
// --- BEGIN ---
|
|
rnd = rand();
|
|
if (rnd < (RAND_MAX / 2))
|
|
{
|
|
// Start playout
|
|
base->StartPlayout(0);
|
|
}
|
|
else
|
|
{
|
|
// Stop playout
|
|
base->StopPlayout(0);
|
|
}
|
|
// --- END ---
|
|
|
|
if (!(i % markInterval)) MARK();
|
|
SLEEP(loopSleep);
|
|
}
|
|
ANL();
|
|
|
|
// Stop extra thread
|
|
VALIDATE_STRESS(!_ptrExtraApiThread->Stop());
|
|
delete _ptrExtraApiThread;
|
|
|
|
///////////// End test /////////////
|
|
|
|
// Terminate
|
|
VALIDATE_STRESS(base->Terminate()); // Deletes all channels
|
|
|
|
printf("Test finished \n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Thread functions
|
|
|
|
bool VoEStressTest::RunExtraApi(void* ptr)
|
|
{
|
|
return static_cast<VoEStressTest*>(ptr)->ProcessExtraApi();
|
|
}
|
|
|
|
bool VoEStressTest::ProcessExtraApi()
|
|
{
|
|
// Prepare
|
|
VoEBase* base = _mgr.BasePtr();
|
|
int rnd(0);
|
|
|
|
// Call random API function, ignore any error
|
|
|
|
// This part should be equal to the marked part in the main thread
|
|
// --- BEGIN ---
|
|
rnd = rand();
|
|
if (rnd < (RAND_MAX / 2))
|
|
{
|
|
// Start playout
|
|
base->StartPlayout(0);
|
|
}
|
|
else
|
|
{
|
|
// Stop playout
|
|
base->StopPlayout(0);
|
|
}
|
|
// --- END ---
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace voetest
|