Change to use local Random object instead of global rand() in the RtcEventLog unit test.

Removed Rand(int low, int high) since that function outputs results that are non-random and/or outside the interval if low is negative.

Added new Uniform(uint32_t, uint32_t) function to replace Rand(int low, int high).

Changed various unit tests to use the new functions.
BUG=

Review URL: https://codereview.webrtc.org/1413053002

Cr-Commit-Position: refs/heads/master@{#10541}
This commit is contained in:
terelius 2015-11-06 05:13:55 -08:00 committed by Commit bot
parent 698aa8d26e
commit 56b1128c8f
5 changed files with 121 additions and 77 deletions

View File

@ -10,7 +10,6 @@
#ifdef ENABLE_RTC_EVENT_LOG
#include <stdio.h>
#include <string>
#include <vector>
@ -23,6 +22,7 @@
#include "webrtc/call/rtc_event_log.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/test/random.h"
#include "webrtc/test/test_suite.h"
#include "webrtc/test/testsupport/fileutils.h"
#include "webrtc/test/testsupport/gtest_disable.h"
@ -304,7 +304,8 @@ void VerifyLogStartEvent(const rtclog::Event& event) {
size_t GenerateRtpPacket(uint32_t extensions_bitvector,
uint32_t csrcs_count,
uint8_t* packet,
size_t packet_size) {
size_t packet_size,
test::Random* prng) {
RTC_CHECK_GE(packet_size, 16 + 4 * csrcs_count + 4 * kNumExtensions);
Clock* clock = Clock::GetRealTimeClock();
@ -321,12 +322,12 @@ size_t GenerateRtpPacket(uint32_t extensions_bitvector,
std::vector<uint32_t> csrcs;
for (unsigned i = 0; i < csrcs_count; i++) {
csrcs.push_back(rand());
csrcs.push_back(prng->Rand<uint32_t>());
}
rtp_sender.SetCsrcs(csrcs);
rtp_sender.SetSSRC(rand());
rtp_sender.SetStartTimestamp(rand(), true);
rtp_sender.SetSequenceNumber(rand());
rtp_sender.SetSSRC(prng->Rand<uint32_t>());
rtp_sender.SetStartTimestamp(prng->Rand<uint32_t>(), true);
rtp_sender.SetSequenceNumber(prng->Rand<uint16_t>());
for (unsigned i = 0; i < kNumExtensions; i++) {
if (extensions_bitvector & (1u << i)) {
@ -334,76 +335,80 @@ size_t GenerateRtpPacket(uint32_t extensions_bitvector,
}
}
int8_t payload_type = rand() % 128;
bool marker_bit = (rand() % 2 == 1);
uint32_t capture_timestamp = rand();
int64_t capture_time_ms = rand();
bool timestamp_provided = (rand() % 2 == 1);
bool inc_sequence_number = (rand() % 2 == 1);
int8_t payload_type = prng->Rand(0, 127);
bool marker_bit = prng->Rand<bool>();
uint32_t capture_timestamp = prng->Rand<uint32_t>();
int64_t capture_time_ms = prng->Rand<uint32_t>();
bool timestamp_provided = prng->Rand<bool>();
bool inc_sequence_number = prng->Rand<bool>();
size_t header_size = rtp_sender.BuildRTPheader(
packet, payload_type, marker_bit, capture_timestamp, capture_time_ms,
timestamp_provided, inc_sequence_number);
for (size_t i = header_size; i < packet_size; i++) {
packet[i] = rand();
packet[i] = prng->Rand<uint8_t>();
}
return header_size;
}
void GenerateRtcpPacket(uint8_t* packet, size_t packet_size) {
void GenerateRtcpPacket(uint8_t* packet,
size_t packet_size,
test::Random* prng) {
for (size_t i = 0; i < packet_size; i++) {
packet[i] = rand();
packet[i] = prng->Rand<uint8_t>();
}
}
void GenerateVideoReceiveConfig(uint32_t extensions_bitvector,
VideoReceiveStream::Config* config) {
VideoReceiveStream::Config* config,
test::Random* prng) {
// Create a map from a payload type to an encoder name.
VideoReceiveStream::Decoder decoder;
decoder.payload_type = rand();
decoder.payload_name = (rand() % 2 ? "VP8" : "H264");
decoder.payload_type = prng->Rand(0, 127);
decoder.payload_name = (prng->Rand<bool>() ? "VP8" : "H264");
config->decoders.push_back(decoder);
// Add SSRCs for the stream.
config->rtp.remote_ssrc = rand();
config->rtp.local_ssrc = rand();
config->rtp.remote_ssrc = prng->Rand<uint32_t>();
config->rtp.local_ssrc = prng->Rand<uint32_t>();
// Add extensions and settings for RTCP.
config->rtp.rtcp_mode =
rand() % 2 ? RtcpMode::kCompound : RtcpMode::kReducedSize;
config->rtp.rtcp_xr.receiver_reference_time_report = (rand() % 2 == 1);
config->rtp.remb = (rand() % 2 == 1);
prng->Rand<bool>() ? RtcpMode::kCompound : RtcpMode::kReducedSize;
config->rtp.rtcp_xr.receiver_reference_time_report = prng->Rand<bool>();
config->rtp.remb = prng->Rand<bool>();
// Add a map from a payload type to a new ssrc and a new payload type for RTX.
VideoReceiveStream::Config::Rtp::Rtx rtx_pair;
rtx_pair.ssrc = rand();
rtx_pair.payload_type = rand();
config->rtp.rtx.insert(std::make_pair(rand(), rtx_pair));
rtx_pair.ssrc = prng->Rand<uint32_t>();
rtx_pair.payload_type = prng->Rand(0, 127);
config->rtp.rtx.insert(std::make_pair(prng->Rand(0, 127), rtx_pair));
// Add header extensions.
for (unsigned i = 0; i < kNumExtensions; i++) {
if (extensions_bitvector & (1u << i)) {
config->rtp.extensions.push_back(
RtpExtension(kExtensionNames[i], rand()));
RtpExtension(kExtensionNames[i], prng->Rand<int>()));
}
}
}
void GenerateVideoSendConfig(uint32_t extensions_bitvector,
VideoSendStream::Config* config) {
VideoSendStream::Config* config,
test::Random* prng) {
// Create a map from a payload type to an encoder name.
config->encoder_settings.payload_type = rand();
config->encoder_settings.payload_name = (rand() % 2 ? "VP8" : "H264");
config->encoder_settings.payload_type = prng->Rand(0, 127);
config->encoder_settings.payload_name = (prng->Rand<bool>() ? "VP8" : "H264");
// Add SSRCs for the stream.
config->rtp.ssrcs.push_back(rand());
config->rtp.ssrcs.push_back(prng->Rand<uint32_t>());
// Add a map from a payload type to new ssrcs and a new payload type for RTX.
config->rtp.rtx.ssrcs.push_back(rand());
config->rtp.rtx.payload_type = rand();
config->rtp.rtx.ssrcs.push_back(prng->Rand<uint32_t>());
config->rtp.rtx.payload_type = prng->Rand(0, 127);
// Add a CNAME.
config->rtp.c_name = "some.user@some.host";
// Add header extensions.
for (unsigned i = 0; i < kNumExtensions; i++) {
if (extensions_bitvector & (1u << i)) {
config->rtp.extensions.push_back(
RtpExtension(kExtensionNames[i], rand()));
RtpExtension(kExtensionNames[i], prng->Rand<int>()));
}
}
}
@ -429,33 +434,34 @@ void LogSessionAndReadBack(size_t rtp_count,
VideoReceiveStream::Config receiver_config(nullptr);
VideoSendStream::Config sender_config(nullptr);
srand(random_seed);
test::Random prng(random_seed);
// Create rtp_count RTP packets containing random data.
for (size_t i = 0; i < rtp_count; i++) {
size_t packet_size = 1000 + rand() % 64;
size_t packet_size = prng.Rand(1000, 1100);
rtp_packets.push_back(rtc::Buffer(packet_size));
size_t header_size = GenerateRtpPacket(extensions_bitvector, csrcs_count,
rtp_packets[i].data(), packet_size);
size_t header_size =
GenerateRtpPacket(extensions_bitvector, csrcs_count,
rtp_packets[i].data(), packet_size, &prng);
rtp_header_sizes.push_back(header_size);
}
// Create rtcp_count RTCP packets containing random data.
for (size_t i = 0; i < rtcp_count; i++) {
size_t packet_size = 1000 + rand() % 64;
size_t packet_size = prng.Rand(1000, 1100);
rtcp_packets.push_back(rtc::Buffer(packet_size));
GenerateRtcpPacket(rtcp_packets[i].data(), packet_size);
GenerateRtcpPacket(rtcp_packets[i].data(), packet_size, &prng);
}
// Create playout_count random SSRCs to use when logging AudioPlayout events.
for (size_t i = 0; i < playout_count; i++) {
playout_ssrcs.push_back(static_cast<uint32_t>(rand()));
playout_ssrcs.push_back(prng.Rand<uint32_t>());
}
// Create bwe_loss_count random bitrate updates for BwePacketLoss.
for (size_t i = 0; i < bwe_loss_count; i++) {
bwe_loss_updates.push_back(std::pair<int32_t, uint8_t>(rand(), rand()));
}
// Create configurations for the video streams.
GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
GenerateVideoSendConfig(extensions_bitvector, &sender_config);
GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config, &prng);
GenerateVideoSendConfig(extensions_bitvector, &sender_config, &prng);
const int config_count = 2;
// Find the name of the current test, in order to use it as a temporary
@ -586,7 +592,7 @@ TEST(RtcEventLogTest, LogSessionAndReadBack) {
1 + csrcs_count, // Number of BWE loss events.
extensions, // Bit vector choosing extensions.
csrcs_count, // Number of contributing sources.
rand());
extensions + csrcs_count); // Random seed.
}
}
}
@ -604,29 +610,30 @@ void DropOldEvents(uint32_t extensions_bitvector,
VideoReceiveStream::Config receiver_config(nullptr);
VideoSendStream::Config sender_config(nullptr);
srand(random_seed);
test::Random prng(random_seed);
// Create two RTP packets containing random data.
size_t packet_size = 1000 + rand() % 64;
size_t packet_size = prng.Rand(1000, 1100);
old_rtp_packet.SetSize(packet_size);
GenerateRtpPacket(extensions_bitvector, csrcs_count, old_rtp_packet.data(),
packet_size);
packet_size = 1000 + rand() % 64;
packet_size, &prng);
packet_size = prng.Rand(1000, 1100);
recent_rtp_packet.SetSize(packet_size);
size_t recent_header_size = GenerateRtpPacket(
extensions_bitvector, csrcs_count, recent_rtp_packet.data(), packet_size);
size_t recent_header_size =
GenerateRtpPacket(extensions_bitvector, csrcs_count,
recent_rtp_packet.data(), packet_size, &prng);
// Create two RTCP packets containing random data.
packet_size = 1000 + rand() % 64;
packet_size = prng.Rand(1000, 1100);
old_rtcp_packet.SetSize(packet_size);
GenerateRtcpPacket(old_rtcp_packet.data(), packet_size);
packet_size = 1000 + rand() % 64;
GenerateRtcpPacket(old_rtcp_packet.data(), packet_size, &prng);
packet_size = prng.Rand(1000, 1100);
recent_rtcp_packet.SetSize(packet_size);
GenerateRtcpPacket(recent_rtcp_packet.data(), packet_size);
GenerateRtcpPacket(recent_rtcp_packet.data(), packet_size, &prng);
// Create configurations for the video streams.
GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config);
GenerateVideoSendConfig(extensions_bitvector, &sender_config);
GenerateVideoReceiveConfig(extensions_bitvector, &receiver_config, &prng);
GenerateVideoSendConfig(extensions_bitvector, &sender_config, &prng);
// Find the name of the current test, in order to use it as a temporary
// filename.

View File

@ -283,9 +283,9 @@ TEST_P(BweSimulation, PacedSelfFairness50msTest) {
const int64_t kAverageOffsetMs = 20 * 1000;
const int kNumRmcatFlows = 4;
int64_t offsets_ms[kNumRmcatFlows];
offsets_ms[0] = random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs);
for (int i = 1; i < kNumRmcatFlows; ++i) {
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs);
}
RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 1000, 3000, 50, 50, 0,
offsets_ms);
@ -295,9 +295,9 @@ TEST_P(BweSimulation, PacedSelfFairness500msTest) {
const int64_t kAverageOffsetMs = 20 * 1000;
const int kNumRmcatFlows = 4;
int64_t offsets_ms[kNumRmcatFlows];
offsets_ms[0] = random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs);
for (int i = 1; i < kNumRmcatFlows; ++i) {
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs);
}
RunFairnessTest(GetParam(), kNumRmcatFlows, 0, 1000, 3000, 500, 50, 0,
offsets_ms);
@ -307,28 +307,28 @@ TEST_P(BweSimulation, PacedSelfFairness1000msTest) {
const int64_t kAverageOffsetMs = 20 * 1000;
const int kNumRmcatFlows = 4;
int64_t offsets_ms[kNumRmcatFlows];
offsets_ms[0] = random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[0] = random_.Rand(2 * kAverageOffsetMs);
for (int i = 1; i < kNumRmcatFlows; ++i) {
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(0, 2 * kAverageOffsetMs);
offsets_ms[i] = offsets_ms[i - 1] + random_.Rand(2 * kAverageOffsetMs);
}
RunFairnessTest(GetParam(), 4, 0, 1000, 3000, 1000, 50, 0, offsets_ms);
}
TEST_P(BweSimulation, TcpFairness50msTest) {
const int64_t kAverageOffsetMs = 20 * 1000;
int64_t offset_ms[] = {random_.Rand(0, 2 * kAverageOffsetMs), 0};
int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0};
RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 50, 50, 0, offset_ms);
}
TEST_P(BweSimulation, TcpFairness500msTest) {
const int64_t kAverageOffsetMs = 20 * 1000;
int64_t offset_ms[] = {random_.Rand(0, 2 * kAverageOffsetMs), 0};
int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0};
RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 500, 50, 0, offset_ms);
}
TEST_P(BweSimulation, TcpFairness1000msTest) {
const int kAverageOffsetMs = 20 * 1000;
int64_t offset_ms[] = {random_.Rand(0, 2 * kAverageOffsetMs), 0};
int64_t offset_ms[] = {random_.Rand(2 * kAverageOffsetMs), 0};
RunFairnessTest(GetParam(), 1, 1, 1000, 2000, 1000, 50, 0, offset_ms);
}

View File

@ -323,7 +323,7 @@ void LossFilter::SetLoss(float loss_percent) {
void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
for (PacketsIt it = in_out->begin(); it != in_out->end(); ) {
if (random_.Rand() < loss_fraction_) {
if (random_.Rand<float>() < loss_fraction_) {
delete *it;
it = in_out->erase(it);
} else {
@ -459,7 +459,7 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
PacketsIt last_it = in_out->begin();
PacketsIt it = last_it;
while (++it != in_out->end()) {
if (random_.Rand() < reorder_fraction_) {
if (random_.Rand<float>() < reorder_fraction_) {
int64_t t1 = (*last_it)->send_time_us();
int64_t t2 = (*it)->send_time_us();
std::swap(*last_it, *it);

View File

@ -21,7 +21,23 @@ namespace test {
Random::Random(uint32_t seed) : a_(0x531FDB97 ^ seed), b_(0x6420ECA8 + seed) {
}
float Random::Rand() {
uint32_t Random::Rand(uint32_t t) {
// If b / 2^32 is uniform on [0,1), then b / 2^32 * (t+1) is uniform on
// the interval [0,t+1), so the integer part is uniform on [0,t].
uint64_t result = b_ * (static_cast<uint64_t>(t) + 1);
result >>= 32;
a_ ^= b_;
b_ += a_;
return result;
}
uint32_t Random::Rand(uint32_t low, uint32_t high) {
RTC_DCHECK(low <= high);
return Rand(high - low) + low;
}
template <>
float Random::Rand<float>() {
const double kScale = 1.0f / (static_cast<uint64_t>(1) << 32);
double result = kScale * b_;
a_ ^= b_;
@ -29,10 +45,9 @@ float Random::Rand() {
return static_cast<float>(result);
}
int Random::Rand(int low, int high) {
RTC_DCHECK(low <= high);
float uniform = Rand() * (high - low + 1) + low;
return static_cast<int>(uniform);
template <>
bool Random::Rand<bool>() {
return Rand(0, 1) == 1;
}
int Random::Gaussian(int mean, int standard_deviation) {
@ -50,7 +65,7 @@ int Random::Gaussian(int mean, int standard_deviation) {
}
int Random::Exponential(float lambda) {
float uniform = Rand();
float uniform = Rand<float>();
return static_cast<int>(-log(uniform) / lambda);
}
} // namespace test

View File

@ -11,6 +11,8 @@
#ifndef WEBRTC_TEST_RANDOM_H_
#define WEBRTC_TEST_RANDOM_H_
#include <limits>
#include "webrtc/typedefs.h"
#include "webrtc/base/constructormagic.h"
@ -22,11 +24,22 @@ class Random {
public:
explicit Random(uint32_t seed);
// Return pseudo-random number in the interval [0.0, 1.0).
float Rand();
// Return pseudo-random integer of the specified type.
template <typename T>
T Rand() {
static_assert(std::numeric_limits<T>::is_integer &&
std::numeric_limits<T>::radix == 2 &&
std::numeric_limits<T>::digits <= 32,
"Rand is only supported for built-in integer types that are "
"32 bits or smaller.");
return static_cast<T>(Rand(std::numeric_limits<uint32_t>::max()));
}
// Return pseudo-random number mapped to the interval [low, high].
int Rand(int low, int high);
// Uniformly distributed pseudo-random number in the interval [0, t].
uint32_t Rand(uint32_t t);
// Uniformly distributed pseudo-random number in the interval [low, high].
uint32_t Rand(uint32_t low, uint32_t high);
// Normal Distribution.
int Gaussian(int mean, int standard_deviation);
@ -43,6 +56,15 @@ class Random {
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Random);
};
// Return pseudo-random number in the interval [0.0, 1.0).
template <>
float Random::Rand<float>();
// Return pseudo-random boolean value.
template <>
bool Random::Rand<bool>();
} // namespace test
} // namespace webrtc