random: Use a different RNG for testing

This RNG is more predictable, which makes it great for testing.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2014-05-18 10:10:04 -04:00
parent 7aa5f22777
commit 6dc8bf7329
6 changed files with 115 additions and 0 deletions

20
DESIGN
View File

@ -828,6 +828,26 @@ Track Tag:
Random:
The random number generator is used by the Queue to pick a song as
randomly as possible. I use two different RNG implementations,
depending on if Ocarina is compiled with CONFIG_TEST or not.
When CONFIG_TEST is enabled, the RNG is a simple counter. Every time
_pick_random() is called, the counter is incremented and returned.
When compiled without CONFIG_TEST we will return values using the
rand() function from stdlib.h.
- API:
void random_seed(unsigned int n);
Seed the random number generator based on n.
void random(unsigned int min, unsigned int max);
Return a random number between min and max, inclusive.
If min >= max: return min.
Queue:
Queues are lists of songs that the user has requested to play. They
are the main interface for all music played by Ocarina.

36
include/random.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright 2014 (c) Anna Schumaker
*/
#ifndef OCARINA_RANDOM_H
#define OCARINA_RANDOM_H
#ifndef CONFIG_TEST
#include <stdlib.h>
static inline void _seed_random(unsigned int n) { srand(time(NULL) + n); }
static inline unsigned int _pick_random() { return rand(); }
#else /* CONFIG_TEST */
void _seed_random(unsigned int);
unsigned int _pick_random();
#endif /* CONFIG_TEST */
static inline void random_seed(unsigned int n)
{
_seed_random(n);
}
static inline unsigned int random(unsigned int min, unsigned int max)
{
if (min >= max)
return min;
return min + (_pick_random() % (max - min));
}
#endif /* OCARINA_RANDOM_H */

21
lib/random.cpp Normal file
View File

@ -0,0 +1,21 @@
/*
* Copyright 2014 (c) Anna Schumaker
*/
#ifdef CONFIG_TEST
#include <random.h>
static unsigned int _random_value = 0;
void _seed_random(unsigned int n)
{
_random_value = n;
}
unsigned int _pick_random()
{
return ++_random_value;
}
#endif /* CONFIG_TEST */

1
tests/.gitignore vendored
View File

@ -5,4 +5,5 @@ index
filter
idle
tags
random
queue

View File

@ -16,6 +16,7 @@ tests = [
("filter.cpp", True, [], []),
("idle.cpp", False, [ "idle.cpp" ], []),
("tags.cpp", True, [], [ "taglib" ]),
("random.cpp", False, [ "random.cpp" ], []),
("queue.cpp", True, [ "callback.cpp" ], []),
]

36
tests/random.cpp Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <random.h>
#include "test.h"
#include <sstream>
static void do_test_rng(unsigned int seed)
{
random_seed(seed);
for (unsigned int i = 0; i <= 10; i++) {
if (i <= seed)
test_equal(random(seed, i), seed);
else
test_equal(random(seed, i), seed + (i % (i - seed)));
}
}
static void test_rng(unsigned int seed)
{
std::stringstream ss;
ss << " (seed = " << seed << ")";
std::string seed_str = ss.str();
run_test("Random Number Generator Test" + seed_str, do_test_rng, seed);
}
int main(int argc, char **argv)
{
for (unsigned int i = 0; i < 10; i++)
test_rng(i);
return 0;
}