mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
[test_runner] Add test_runner program
This change introduces test_runner, which runs unit or integration tests
and then tells the kernel to exit QEMU with a status code indicating the
number of failed tests.
The test_runner program is not loaded by default. Use the test manifest
to enable it:
./configure --manifest=assets/manifests/test.yml
A number of tests from the old src/tests have moved over. More to come,
as well as moving code from testapp before getting rid of it.
The test.sh script has been repurposed to be a "headless" version of
qemu.sh for running tests, and it exits with the appropriate exit code.
(Though ./qemu.sh gained the ability to exit with the correct exit code
as well.) Exit codes from kernel panics have been updated so that the
bash scripts should exit with code 127.
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
#include "kutil/constexpr_hash.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
using namespace kutil;
|
||||
|
||||
TEST_CASE( "constexpr hash", "[hash]" )
|
||||
{
|
||||
const unsigned hash1 = static_cast<unsigned>("hash1!"_h);
|
||||
CHECK(hash1 == 210);
|
||||
|
||||
const unsigned hash2 = static_cast<unsigned>("hash1!"_h);
|
||||
CHECK(hash1 == hash2);
|
||||
|
||||
const unsigned hash3 = static_cast<unsigned>("not hash1!"_h);
|
||||
CHECK(hash1 != hash3);
|
||||
CHECK(hash3 == 37);
|
||||
|
||||
const unsigned hash4 = static_cast<unsigned>("another thing that's longer"_h);
|
||||
CHECK(hash1 != hash4);
|
||||
CHECK(hash4 == 212);
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include "kutil/linked_list.h"
|
||||
#include "catch.hpp"
|
||||
#include "container_helpers.h"
|
||||
|
||||
using namespace kutil;
|
||||
|
||||
const int test_list_size = 100;
|
||||
|
||||
template <typename T>
|
||||
class ListVectorCompare :
|
||||
public Catch::MatcherBase<std::vector<list_node<T>>>
|
||||
{
|
||||
public:
|
||||
using item = list_node<T>;
|
||||
using vector = std::vector<item>;
|
||||
|
||||
ListVectorCompare(const linked_list<T> &list, bool reversed) :
|
||||
m_list(list), m_reverse(reversed) {}
|
||||
|
||||
virtual bool match (vector const& vec) const override
|
||||
{
|
||||
size_t index = m_reverse ? vec.size() - 1 : 0;
|
||||
for (const T *i : m_list) {
|
||||
if (i != &vec[index]) return false;
|
||||
index += m_reverse ? -1 : 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual std::string describe() const override
|
||||
{
|
||||
return "is the same as the given linked list";
|
||||
}
|
||||
|
||||
private:
|
||||
const linked_list<T> &m_list;
|
||||
bool m_reverse;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IsSorted :
|
||||
public Catch::MatcherBase<linked_list<T>>
|
||||
{
|
||||
public:
|
||||
using item = list_node<T>;
|
||||
using list = linked_list<T>;
|
||||
|
||||
IsSorted() {}
|
||||
|
||||
virtual bool match (list const& l) const override
|
||||
{
|
||||
int big = std::numeric_limits<int>::min();
|
||||
for (const T *i : l) {
|
||||
if (i->value < big) return false;
|
||||
big = i->value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual std::string describe() const override
|
||||
{
|
||||
return "is sorted";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ListContainsMatcher :
|
||||
public Catch::MatcherBase<linked_list<T>>
|
||||
{
|
||||
public:
|
||||
using item = list_node<T>;
|
||||
using list = linked_list<T>;
|
||||
|
||||
ListContainsMatcher(const item &needle) : m_needle(needle) {}
|
||||
|
||||
virtual bool match (list const& l) const override
|
||||
{
|
||||
for (const T *i : l)
|
||||
if (i == &m_needle) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::string describe() const override
|
||||
{
|
||||
return "contains the given item";
|
||||
}
|
||||
|
||||
const item &m_needle;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ListVectorCompare<T> IsSameAsList(const linked_list<T> &list, bool reversed = false)
|
||||
{
|
||||
return ListVectorCompare<T>(list, reversed);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ListContainsMatcher<T> ListContains(const list_node<T> &item)
|
||||
{
|
||||
return ListContainsMatcher<T>(item);
|
||||
}
|
||||
|
||||
TEST_CASE( "Linked list tests", "[containers] [list]" )
|
||||
{
|
||||
linked_list<unsortableT> ulist;
|
||||
|
||||
int value = 0;
|
||||
std::vector<list_node<unsortableT>> unsortables(test_list_size);
|
||||
for (auto &i : unsortables) {
|
||||
i.value = value++;
|
||||
ulist.push_back(&i);
|
||||
}
|
||||
CHECK( ulist.length() == test_list_size );
|
||||
CHECK_THAT( unsortables, IsSameAsList(ulist) );
|
||||
|
||||
linked_list<unsortableT> ulist_reversed;
|
||||
|
||||
for (auto &i : unsortables) {
|
||||
ulist.remove(&i);
|
||||
ulist_reversed.push_front(&i);
|
||||
}
|
||||
|
||||
CHECK( ulist_reversed.length() == test_list_size );
|
||||
CHECK_THAT( unsortables, IsSameAsList(ulist_reversed, true) );
|
||||
|
||||
auto &removed = unsortables[test_list_size / 2];
|
||||
ulist_reversed.remove(&removed);
|
||||
CHECK( ulist_reversed.length() == test_list_size - 1 );
|
||||
CHECK_THAT( ulist_reversed, !ListContains(removed) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Sorted list tests", "[containers] [list]" )
|
||||
{
|
||||
using clock = std::chrono::system_clock;
|
||||
unsigned seed = clock::now().time_since_epoch().count();
|
||||
std::default_random_engine rng(seed);
|
||||
std::uniform_int_distribution<int> gen(1, 1000);
|
||||
|
||||
linked_list<sortableT> slist;
|
||||
CHECK( slist.length() == 0 );
|
||||
|
||||
std::vector<list_node<sortableT>> sortables(test_list_size);
|
||||
for (auto &i : sortables) {
|
||||
i.value = gen(rng);
|
||||
slist.sorted_insert(&i);
|
||||
}
|
||||
CHECK( slist.length() == test_list_size );
|
||||
CHECK_THAT( slist, IsSorted<sortableT>() );
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
#include "kutil/map.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
using Catch::rng;
|
||||
std::uniform_int_distribution<int> distrib {0, 10000};
|
||||
|
||||
TEST_CASE( "map insertion", "[containers] [map]" )
|
||||
{
|
||||
std::vector<int> ints;
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
ints.push_back(i);
|
||||
|
||||
size_t sizes[] = {1, 2, 3, 5, 100};
|
||||
for (size_t s : sizes) {
|
||||
kutil::map<int, int> v;
|
||||
std::shuffle(ints.begin(), ints.end(), rng());
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
v.insert(ints[i], ints[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
int *p = v.find(ints[i]);
|
||||
CAPTURE( s );
|
||||
CAPTURE( i );
|
||||
CAPTURE( ints[i] );
|
||||
CAPTURE( kutil::hash(ints[i]) );
|
||||
CHECK( p );
|
||||
CHECK( *p == ints[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "map deletion", "[containers] [map]" )
|
||||
{
|
||||
std::vector<int> ints;
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
ints.push_back(i);
|
||||
|
||||
size_t sizes[] = {1, 2, 3, 5, 100};
|
||||
for (size_t s : sizes) {
|
||||
kutil::map<int, int> v;
|
||||
std::shuffle(ints.begin(), ints.end(), rng());
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
v.insert(ints[i], ints[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < s; i += 2) {
|
||||
v.erase(ints[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < s; ++i) {
|
||||
int *p = v.find(ints[i]);
|
||||
CAPTURE( s );
|
||||
CAPTURE( i );
|
||||
CAPTURE( ints[i] );
|
||||
CAPTURE( kutil::hash(ints[i]) );
|
||||
if ( i%2 )
|
||||
CHECK( p );
|
||||
else
|
||||
CHECK( !p );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "map with pointer vals", "[containers] [map]" )
|
||||
{
|
||||
kutil::map<int, int*> v;
|
||||
int is[4] = { 0, 0, 0, 0 };
|
||||
for (int i = 0; i < 4; ++i)
|
||||
v.insert(i*7, &is[i]);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int *p = v.find(i*7);
|
||||
CHECK( p == &is[i] );
|
||||
}
|
||||
|
||||
CHECK( v.find(3) == nullptr );
|
||||
}
|
||||
|
||||
TEST_CASE( "map with uint64_t keys", "[containers] [map]" )
|
||||
{
|
||||
kutil::map<uint64_t, int> v;
|
||||
int is[4] = { 2, 3, 5, 7 };
|
||||
for (uint64_t i = 0; i < 4; ++i)
|
||||
v.insert(i+1, is[i]);
|
||||
|
||||
for (uint64_t i = 0; i < 4; ++i) {
|
||||
int *p = v.find(i+1);
|
||||
CHECK( *p == is[i] );
|
||||
}
|
||||
|
||||
CHECK( v.find(30) == nullptr );
|
||||
}
|
||||
Reference in New Issue
Block a user