mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:18:13 +00:00
LibTest: Add a suite of tests for the generators
This commit is contained in:
parent
2782334152
commit
7c2a569fca
3 changed files with 170 additions and 0 deletions
|
@ -643,6 +643,7 @@ if (BUILD_LAGOM)
|
||||||
LibMarkdown
|
LibMarkdown
|
||||||
LibPDF
|
LibPDF
|
||||||
LibSQL
|
LibSQL
|
||||||
|
LibTest
|
||||||
LibTextCodec
|
LibTextCodec
|
||||||
LibTTF
|
LibTTF
|
||||||
LibTimeZone
|
LibTimeZone
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
set(TEST_SOURCES
|
set(TEST_SOURCES
|
||||||
TestNoCrash.cpp
|
TestNoCrash.cpp
|
||||||
|
TestGenerator.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(source IN LISTS TEST_SOURCES)
|
foreach(source IN LISTS TEST_SOURCES)
|
||||||
|
|
168
Tests/LibTest/TestGenerator.cpp
Normal file
168
Tests/LibTest/TestGenerator.cpp
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Martin Janiczek <martin@janiczek.cz>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/StdLibExtras.h>
|
||||||
|
#include <LibTest/Randomized/Generator.h>
|
||||||
|
#include <LibTest/TestCase.h>
|
||||||
|
|
||||||
|
using namespace Test::Randomized;
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(unsigned_int_max_bounds)
|
||||||
|
{
|
||||||
|
GEN(n, Gen::unsigned_int(10));
|
||||||
|
EXPECT(n <= 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(unsigned_int_min_max_bounds)
|
||||||
|
{
|
||||||
|
GEN(n, Gen::unsigned_int(3, 6));
|
||||||
|
EXPECT(n >= 3 && n <= 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(assume)
|
||||||
|
{
|
||||||
|
GEN(n, Gen::unsigned_int(10));
|
||||||
|
ASSUME(n % 2 == 0); // This will try to generate until it finds an even number
|
||||||
|
EXPECT(n % 2 == 0); // This will then succeed
|
||||||
|
// It will give up if the value doesn't pass the ASSUME(...) predicate 15 times in a row.
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO find a way to test that a test "unsigned_int(3) can't reach 0" fails
|
||||||
|
// TODO find a way to test that a test "unsigned_int(3) can't reach 3" fails
|
||||||
|
// TODO find a way to test that a test "unsigned_int(3,6) can't reach 3" fails
|
||||||
|
// TODO find a way to test that a test "unsigned_int(3,6) can't reach 6" fails
|
||||||
|
// TODO find a way to test that a test "unsigned_int(10) can reach n>10" fails
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(map_like)
|
||||||
|
{
|
||||||
|
GEN(n1, Gen::unsigned_int(10));
|
||||||
|
GEN(n2, n1 * 2);
|
||||||
|
EXPECT(n2 % 2 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(bind_like)
|
||||||
|
{
|
||||||
|
GEN(n1, Gen::unsigned_int(1, 9));
|
||||||
|
GEN(n2, Gen::unsigned_int(n1 * 10, n1 * 100));
|
||||||
|
EXPECT(n2 >= 10 && n2 <= 900);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An example of an user-defined generator (for the test bind_vector_suboptimal).
|
||||||
|
//
|
||||||
|
// For why this is a suboptimal way to generate collections, see the comment in
|
||||||
|
// Shrink::shrink_delete().
|
||||||
|
//
|
||||||
|
// TL;DR: this makes the length non-local to the items we're trying to delete
|
||||||
|
// (except the first item).
|
||||||
|
//
|
||||||
|
// There's a better way: flip a (biased) coin to decide whether to generate
|
||||||
|
// a next item. That makes each item much better shrinkable, since its
|
||||||
|
// contribution to the sequence length (a boolean 0 or 1) is right next to its
|
||||||
|
// own data.
|
||||||
|
//
|
||||||
|
// Because it's a pretty natural way to do this, we take special care in the
|
||||||
|
// internal shrinker to work well on this style too.
|
||||||
|
template<typename FN>
|
||||||
|
Vector<InvokeResult<FN>> vector_suboptimal(FN item_gen)
|
||||||
|
{
|
||||||
|
u32 length = Gen::unsigned_int(5);
|
||||||
|
Vector<InvokeResult<FN>> acc;
|
||||||
|
for (u32 i = 0; i < length; ++i) {
|
||||||
|
acc.append(item_gen());
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(bind_vector_suboptimal)
|
||||||
|
{
|
||||||
|
u32 max_item = 5;
|
||||||
|
GEN(vec, vector_suboptimal([&]() { return Gen::unsigned_int(max_item); }));
|
||||||
|
u32 sum = 0;
|
||||||
|
for (u32 n : vec) {
|
||||||
|
sum += n;
|
||||||
|
}
|
||||||
|
EXPECT(sum <= vec.size() * max_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(vector)
|
||||||
|
{
|
||||||
|
u32 max_item = 5;
|
||||||
|
GEN(vec, Gen::vector([&]() { return Gen::unsigned_int(max_item); }));
|
||||||
|
EXPECT(vec.size() <= 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(vector_length)
|
||||||
|
{
|
||||||
|
u32 max_item = 5;
|
||||||
|
GEN(vec, Gen::vector(3, [&]() { return Gen::unsigned_int(max_item); }));
|
||||||
|
EXPECT(vec.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(vector_min_max)
|
||||||
|
{
|
||||||
|
u32 max_item = 5;
|
||||||
|
GEN(vec, Gen::vector(1, 4, [&]() { return Gen::unsigned_int(max_item); }));
|
||||||
|
EXPECT(vec.size() >= 1 && vec.size() <= 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_below0)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(-0.5));
|
||||||
|
EXPECT(b == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_0)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(0));
|
||||||
|
EXPECT(b == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_1)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(1));
|
||||||
|
EXPECT(b == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_above1)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(1.5));
|
||||||
|
EXPECT(b == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_fair_true)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(0.5));
|
||||||
|
ASSUME(b == true);
|
||||||
|
EXPECT(b == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(weighted_boolean_fair_false)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::weighted_boolean(0.5));
|
||||||
|
ASSUME(b == false);
|
||||||
|
EXPECT(b == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(boolean_true)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::boolean());
|
||||||
|
ASSUME(b == true);
|
||||||
|
EXPECT(b == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(boolean_false)
|
||||||
|
{
|
||||||
|
GEN(b, Gen::boolean());
|
||||||
|
ASSUME(b == false);
|
||||||
|
EXPECT(b == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
RANDOMIZED_TEST_CASE(frequency_int)
|
||||||
|
{
|
||||||
|
GEN(x, Gen::frequency(Gen::Choice { 5, 'x' }, Gen::Choice { 1, 'o' }));
|
||||||
|
ASSUME(x == 'x');
|
||||||
|
EXPECT(x == 'x');
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue