Skip to content

Commit

Permalink
Add function to fill a buffer with random bytes (open-telemetry#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
Johannes Tax authored Jun 5, 2020
1 parent 599bddb commit 273a0ae
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 18 deletions.
28 changes: 27 additions & 1 deletion sdk/src/common/random.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "src/common/random.h"
#include "src/common/platform/fork.h"

#include <cstring>
#include <random>

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
Expand Down Expand Up @@ -40,11 +43,34 @@ class TlsRandomNumberGenerator
thread_local FastRandomNumberGenerator TlsRandomNumberGenerator::engine_{};
} // namespace

FastRandomNumberGenerator &GetRandomNumberGenerator() noexcept
FastRandomNumberGenerator &Random::GetRandomNumberGenerator() noexcept
{
static thread_local TlsRandomNumberGenerator random_number_generator{};
return TlsRandomNumberGenerator::engine();
}

uint64_t Random::GenerateRandom64() noexcept
{
return GetRandomNumberGenerator()();
}

void Random::GenerateRandomBuffer(opentelemetry::nostd::span<uint8_t> buffer) noexcept
{
auto buf_size = buffer.size();

for (size_t i = 0; i < buf_size; i += sizeof(uint64_t))
{
uint64_t value = GenerateRandom64();
if (i + sizeof(uint64_t) <= buf_size)
{
memcpy(&buffer[i], &value, sizeof(uint64_t));
}
else
{
memcpy(&buffer[i], &value, buf_size - i);
}
}
}
} // namespace common
} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
27 changes: 23 additions & 4 deletions sdk/src/common/random.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <random>

#include "opentelemetry/nostd/span.h"
#include "opentelemetry/version.h"
#include "src/common/fast_random_number_generator.h"

Expand All @@ -11,9 +10,29 @@ namespace sdk
namespace common
{
/**
* @return a seeded thread-local random number generator.
* Utility methods for creating random data, based on a seeded thread-local
* number generator.
*/
FastRandomNumberGenerator &GetRandomNumberGenerator() noexcept;
class Random
{
public:
/**
* @return an unsigned 64 bit random number
*/
static uint64_t GenerateRandom64() noexcept;
/**
* Fill the passed span with random bytes.
*
* @param buffer A span of bytes.
*/
static void GenerateRandomBuffer(opentelemetry::nostd::span<uint8_t> buffer) noexcept;

private:
/**
* @return a seeded thread-local random number generator.
*/
static FastRandomNumberGenerator &GetRandomNumberGenerator() noexcept;
};
} // namespace common
} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
3 changes: 3 additions & 0 deletions sdk/test/common/fast_random_number_generator_test.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "src/common/random.h"

#include <random>

#include <gtest/gtest.h>

using opentelemetry::sdk::common::FastRandomNumberGenerator;

TEST(FastRandomNumberGeneratorTest, GenerateUniqueNumbers)
Expand Down
9 changes: 5 additions & 4 deletions sdk/test/common/random_benchmark.cc
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
#include "src/common/random.h"

#include <benchmark/benchmark.h>
#include <cstdint>
#include <random>

#include <benchmark/benchmark.h>

namespace
{
using opentelemetry::sdk::common::GetRandomNumberGenerator;
using opentelemetry::sdk::common::Random;

void BM_RandomIdGeneration(benchmark::State &state)
{
auto &generator = GetRandomNumberGenerator();
while (state.KeepRunning())
{
benchmark::DoNotOptimize(generator());
benchmark::DoNotOptimize(Random::GenerateRandom64());
}
}
BENCHMARK(BM_RandomIdGeneration);
Expand Down
8 changes: 3 additions & 5 deletions sdk/test/common/random_fork_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@
# include <cstdio>
# include <cstdlib>
# include <iostream>
using opentelemetry::sdk::common::GetRandomNumberGenerator;
using opentelemetry::sdk::common::Random;

static uint64_t *child_id;

int main()
{
auto &random_number_generator = GetRandomNumberGenerator();

// Set up shared memory to communicate between parent and child processes.
//
// See https://stackoverflow.com/a/13274800/4447365
Expand All @@ -27,13 +25,13 @@ int main()
*child_id = 0;
if (fork() == 0)
{
*child_id = random_number_generator();
*child_id = Random::GenerateRandom64();
exit(EXIT_SUCCESS);
}
else
{
wait(nullptr);
auto parent_id = random_number_generator();
auto parent_id = Random::GenerateRandom64();
auto child_id_copy = *child_id;
munmap(static_cast<void *>(child_id), sizeof(*child_id));
if (parent_id == child_id_copy)
Expand Down
30 changes: 26 additions & 4 deletions sdk/test/common/random_test.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
#include "src/common/random.h"

#include <algorithm>
#include <iterator>

#include <gtest/gtest.h>
using opentelemetry::sdk::common::GetRandomNumberGenerator;
using opentelemetry::sdk::common::Random;

TEST(RandomTest, GenerateRandom64)
{
EXPECT_NE(Random::GenerateRandom64(), Random::GenerateRandom64());
}

TEST(RandomTest, GenerateRandomNumbers)
TEST(RandomTest, GenerateRandomBuffer)
{
auto &random_number_generator = GetRandomNumberGenerator();
EXPECT_NE(random_number_generator(), random_number_generator());
uint8_t buf1[8] = {0};
uint8_t buf2[8] = {0};
Random::GenerateRandomBuffer(buf1);
Random::GenerateRandomBuffer(buf2);
EXPECT_FALSE(std::equal(std::begin(buf1), std::end(buf1), std::begin(buf2)));

// Edge cases.
for (auto size : {1, 7, 8, 9, 16, 17})
{
std::vector<uint8_t> buf1(size);
std::vector<uint8_t> buf2(size);

Random::GenerateRandomBuffer(buf1);
Random::GenerateRandomBuffer(buf2);
EXPECT_FALSE(std::equal(std::begin(buf1), std::end(buf1), std::begin(buf2)));
}
}

0 comments on commit 273a0ae

Please sign in to comment.