Resurrecting the runtime unit tests, and modifying them so they compile under the latest refactoring changes.
This commit is contained in:
6
mk/rt.mk
6
mk/rt.mk
@@ -25,6 +25,9 @@ RUNTIME_CS := rt/sync/timer.cpp \
|
|||||||
rt/rust_srv.cpp \
|
rt/rust_srv.cpp \
|
||||||
rt/rust_kernel.cpp \
|
rt/rust_kernel.cpp \
|
||||||
rt/memory_region.cpp \
|
rt/memory_region.cpp \
|
||||||
|
rt/test/rust_test_harness.cpp \
|
||||||
|
rt/test/rust_test_runtime.cpp \
|
||||||
|
rt/test/rust_test_util.cpp \
|
||||||
rt/arch/i386/context.cpp \
|
rt/arch/i386/context.cpp \
|
||||||
|
|
||||||
RUNTIME_LL :=
|
RUNTIME_LL :=
|
||||||
@@ -56,6 +59,9 @@ RUNTIME_HDR := rt/globals.h \
|
|||||||
rt/rust_kernel.h \
|
rt/rust_kernel.h \
|
||||||
rt/memory_region.h \
|
rt/memory_region.h \
|
||||||
rt/memory.h \
|
rt/memory.h \
|
||||||
|
rt/test/rust_test_harness.h \
|
||||||
|
rt/test/rust_test_runtime.h \
|
||||||
|
rt/test/rust_test_util.h \
|
||||||
rt/arch/i386/context.h \
|
rt/arch/i386/context.h \
|
||||||
|
|
||||||
RUNTIME_DEF := rt/rustrt$(CFG_DEF_SUFFIX)
|
RUNTIME_DEF := rt/rustrt$(CFG_DEF_SUFFIX)
|
||||||
|
|||||||
@@ -249,6 +249,10 @@ typedef ptr_vec<rust_alarm> rust_wait_queue;
|
|||||||
#include "rust_port.h"
|
#include "rust_port.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "test/rust_test_harness.h"
|
||||||
|
#include "test/rust_test_util.h"
|
||||||
|
#include "test/rust_test_runtime.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: C++
|
// mode: C++
|
||||||
|
|||||||
@@ -68,11 +68,11 @@ class rust_kernel : public rust_thread {
|
|||||||
rust_handle<rust_scheduler> *
|
rust_handle<rust_scheduler> *
|
||||||
internal_get_sched_handle(rust_scheduler *sched);
|
internal_get_sched_handle(rust_scheduler *sched);
|
||||||
|
|
||||||
|
array_list<rust_task_thread *> threads;
|
||||||
|
|
||||||
rust_scheduler *create_scheduler(const char *name);
|
rust_scheduler *create_scheduler(const char *name);
|
||||||
void destroy_scheduler();
|
void destroy_scheduler();
|
||||||
|
|
||||||
array_list<rust_task_thread *> threads;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
rust_scheduler *sched;
|
rust_scheduler *sched;
|
||||||
lock_and_signal scheduler_lock;
|
lock_and_signal scheduler_lock;
|
||||||
|
|||||||
40
src/rt/test/rust_test_harness.cpp
Normal file
40
src/rt/test/rust_test_harness.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include "../rust_internal.h"
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_test::run() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rust_test::name() {
|
||||||
|
return "untitled";
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_test_suite::rust_test_suite() {
|
||||||
|
tests.append(new rust_domain_test());
|
||||||
|
tests.append(new rust_task_test(this));
|
||||||
|
tests.append(new rust_array_list_test());
|
||||||
|
tests.append(new rust_synchronized_indexed_list_test());
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_test_suite::~rust_test_suite() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_test_suite::run() {
|
||||||
|
bool pass = true;
|
||||||
|
for (size_t i = 0; i < tests.size(); i++) {
|
||||||
|
rust_test *test = tests[i];
|
||||||
|
printf("test: %s running ... \n", test->name());
|
||||||
|
timer timer;
|
||||||
|
bool result = tests[i]->run();
|
||||||
|
printf("test: %s %s %.2f ms\n", test->name(),
|
||||||
|
result ? "PASSED" : "FAILE", timer.get_elapsed_time_in_ms());
|
||||||
|
if (result == false) {
|
||||||
|
pass = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
22
src/rt/test/rust_test_harness.h
Normal file
22
src/rt/test/rust_test_harness.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef RUST_TEST_HARNESS_H
|
||||||
|
#define RUST_TEST_HARNESS_H
|
||||||
|
|
||||||
|
#define CHECK(x) if ((x) == false) \
|
||||||
|
{ printf("condition: %s failed at file: %s, line: %d\n", #x, \
|
||||||
|
__FILE__, __LINE__ ); return false; }
|
||||||
|
|
||||||
|
class rust_test {
|
||||||
|
public:
|
||||||
|
virtual bool run();
|
||||||
|
virtual const char *name();
|
||||||
|
};
|
||||||
|
|
||||||
|
class rust_test_suite : public rust_test {
|
||||||
|
public:
|
||||||
|
array_list<rust_test*> tests;
|
||||||
|
rust_test_suite();
|
||||||
|
virtual ~rust_test_suite();
|
||||||
|
bool run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RUST_TEST_HARNESS_H */
|
||||||
67
src/rt/test/rust_test_runtime.cpp
Normal file
67
src/rt/test/rust_test_runtime.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "rust_test_runtime.h"
|
||||||
|
|
||||||
|
rust_test_runtime::rust_test_runtime() {
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_test_runtime::~rust_test_runtime() {
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DOMAINS 32
|
||||||
|
#define TASKS 32
|
||||||
|
|
||||||
|
void
|
||||||
|
rust_domain_test::worker::run() {
|
||||||
|
rust_scheduler *handle = kernel->get_scheduler();
|
||||||
|
for (int i = 0; i < TASKS; i++) {
|
||||||
|
handle->create_task(NULL, "child");
|
||||||
|
}
|
||||||
|
sync::random_sleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_domain_test::run() {
|
||||||
|
rust_srv srv;
|
||||||
|
rust_kernel kernel(&srv);
|
||||||
|
|
||||||
|
array_list<worker *> workers;
|
||||||
|
for (int i = 0; i < DOMAINS; i++) {
|
||||||
|
worker *worker = new rust_domain_test::worker (&kernel);
|
||||||
|
workers.append(worker);
|
||||||
|
worker->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't join the worker threads here in order to simulate ad-hoc
|
||||||
|
// termination of domains. If we join_all_domains before all domains
|
||||||
|
// are actually spawned, this could crash, thus the reason for the
|
||||||
|
// sleep below.
|
||||||
|
|
||||||
|
sync::sleep(100);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_entry() {
|
||||||
|
printf("task entry\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rust_task_test::worker::run() {
|
||||||
|
rust_scheduler *scheduler = kernel->get_scheduler();
|
||||||
|
scheduler->root_task->start((uintptr_t)&task_entry, (uintptr_t)NULL);
|
||||||
|
scheduler->start_main_loop(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_task_test::run() {
|
||||||
|
rust_srv srv;
|
||||||
|
rust_kernel kernel(&srv);
|
||||||
|
|
||||||
|
array_list<worker *> workers;
|
||||||
|
for (int i = 0; i < DOMAINS; i++) {
|
||||||
|
worker *worker = new rust_task_test::worker (&kernel, this);
|
||||||
|
workers.append(worker);
|
||||||
|
worker->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
sync::random_sleep(1000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
51
src/rt/test/rust_test_runtime.h
Normal file
51
src/rt/test/rust_test_runtime.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#include "../rust_internal.h"
|
||||||
|
|
||||||
|
#ifndef RUST_TEST_RUNTIME_H
|
||||||
|
#define RUST_TEST_RUNTIME_H
|
||||||
|
|
||||||
|
class rust_test_runtime {
|
||||||
|
public:
|
||||||
|
rust_test_runtime();
|
||||||
|
virtual ~rust_test_runtime();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class rust_domain_test : public rust_test {
|
||||||
|
public:
|
||||||
|
class worker : public rust_thread {
|
||||||
|
public:
|
||||||
|
rust_kernel *kernel;
|
||||||
|
worker(rust_kernel *kernel) : kernel(kernel) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
bool run();
|
||||||
|
const char *name() {
|
||||||
|
return "rust_domain_test";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class rust_task_test : public rust_test {
|
||||||
|
public:
|
||||||
|
rust_test_suite *suite;
|
||||||
|
rust_task_test(rust_test_suite *suite) : suite(suite) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
class worker : public rust_thread {
|
||||||
|
public:
|
||||||
|
rust_kernel *kernel;
|
||||||
|
rust_task_test *parent;
|
||||||
|
worker(rust_kernel *kernel, rust_task_test *parent) :
|
||||||
|
kernel(kernel), parent(parent) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
bool run();
|
||||||
|
const char *name() {
|
||||||
|
return "rust_task_test";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RUST_TEST_RUNTIME_H */
|
||||||
78
src/rt/test/rust_test_util.cpp
Normal file
78
src/rt/test/rust_test_util.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#include "../rust_internal.h"
|
||||||
|
|
||||||
|
#define COUNT 1000
|
||||||
|
#define LARGE_COUNT 10000
|
||||||
|
#define THREADS 10
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_array_list_test::run() {
|
||||||
|
array_list<int> list;
|
||||||
|
|
||||||
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
list.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
CHECK (list[i] == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
CHECK (list.index_of(i) == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
CHECK (list.replace(i, -i));
|
||||||
|
CHECK (list.replace(-i, i));
|
||||||
|
CHECK (list.index_of(i) == i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = COUNT - 1; i >= 0; i--) {
|
||||||
|
CHECK (list.pop(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rust_synchronized_indexed_list_test::run() {
|
||||||
|
array_list<worker*> workers;
|
||||||
|
|
||||||
|
for (int i = 0; i < THREADS; i++) {
|
||||||
|
worker *worker =
|
||||||
|
new rust_synchronized_indexed_list_test::worker(this);
|
||||||
|
workers.append(worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < workers.size(); i++) {
|
||||||
|
workers[i]->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
while(workers.is_empty() == false) {
|
||||||
|
worker *worker;
|
||||||
|
workers.pop(&worker);
|
||||||
|
worker->join();
|
||||||
|
delete worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long expected_items = LARGE_COUNT * THREADS;
|
||||||
|
|
||||||
|
CHECK(list.length() == expected_items);
|
||||||
|
|
||||||
|
long long sum = 0;
|
||||||
|
for (size_t i = 0; i < list.length(); i++) {
|
||||||
|
sum += list[i]->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long expected_sum = LARGE_COUNT;
|
||||||
|
expected_sum = expected_sum * (expected_sum - 1) / 2 * THREADS;
|
||||||
|
CHECK (sum == expected_sum);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rust_synchronized_indexed_list_test::worker::run() {
|
||||||
|
for (int i = 0; i < LARGE_COUNT; i++) {
|
||||||
|
parent->list.append(new indexed_list_element<int>(i));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
41
src/rt/test/rust_test_util.h
Normal file
41
src/rt/test/rust_test_util.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef RUST_TEST_UTIL_H
|
||||||
|
#define RUST_TEST_UTIL_H
|
||||||
|
|
||||||
|
class rust_test_util : public rust_test {
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class rust_array_list_test : public rust_test {
|
||||||
|
public:
|
||||||
|
bool run();
|
||||||
|
const char *name() {
|
||||||
|
return "rust_array_list_test";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class rust_synchronized_indexed_list_test : public rust_test {
|
||||||
|
public:
|
||||||
|
rust_srv srv;
|
||||||
|
synchronized_indexed_list<indexed_list_element<int> > list;
|
||||||
|
|
||||||
|
rust_synchronized_indexed_list_test() {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
|
||||||
|
class worker : public rust_thread {
|
||||||
|
public:
|
||||||
|
rust_synchronized_indexed_list_test *parent;
|
||||||
|
worker(rust_synchronized_indexed_list_test *parent) : parent(parent) {
|
||||||
|
// Nop.
|
||||||
|
}
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
bool run();
|
||||||
|
const char *name() {
|
||||||
|
return "rust_synchronized_indexed_list_test";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RUST_TEST_UTIL_H */
|
||||||
Reference in New Issue
Block a user