Kernel TDD

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Kernel TDD

Post by Candy »

Hi all,

As TDD proponent and as osdever, I wanted to see if I could combine the two to a method of making a kernel, TDD style. I've tried (for about 30 minutes during my lunch break today) and came up with this. The difference between this and basic typical TDD frameworks is that this one assumes that you have only run the .ctors section, and that you have a non-crashing kerror function (that you can change in the header if you'd like). It does not use malloc, it does not use anything that a simple ELF loader wouldn't have put there already. You should be able to use this to unit-test your paging code.

Of course, if stuff crashes or triple-faults all bets are off.

Header:

Code: Select all

#ifndef TEST_H
#define TEST_H

#include <cstddef>
#include <kerror.h>

struct test_entry;

void register_test(test_entry *entry);

struct test_entry {
  test_entry(const char *testname, const char *filename, size_t lineno, bool (*test)()) 
  : testname(testname)
  , filename(filename)
  , lineno(lineno)
  , test(test)
  {
    register_test(this);
  }
  test_entry *next;
  const char *testname;
  const char *filename;
  size_t lineno;
  bool (*test)();
};

#define TEST(x) bool testf_##x(); static struct test_entry test##x(#x, __FILE__, __LINE__, &testf_##x); bool testf_##x()
#define ASSERT(x, y) if ((x) != (y)) { kerror(0, "%s:%d: ASSERT: %d was not equal to %d\n", __FILE__, __LINE__, x, y); return false; } (void)0
#define ASSERT_THAT(x) if (!(x)) { kerror(0, "%s:%d: ASSERT: %s was not true\n", __FILE__, __LINE__, #x); return false; } (void)0

void test_run();

#endif


Code

Code: Select all

#include "test.h"

struct test_entry *tests = 0;

void register_test(test_entry *entry) {
  entry->next = tests;
  tests = entry;
}

void test_run() {
  test_entry *entry = tests;
  size_t testcount = 0, failures = 0;
  while (entry) {
    testcount++;
    kerror(0, ".");
    if (!entry->test()) {
      kerror(0, "\n%s:%d: Failed test %s\n", entry->filename, entry->lineno, entry->testname);
      failures++;
    }
    entry = entry->next;
  }
  kerror(0, "\n%d / %d tests failed\n", failures, testcount);
}
To use, make a test like

Code: Select all

TEST(vector_simple_use) {
  std::vector<int> numbers;
  ASSERT(numbers.size(), 0);
  ASSERT(numbers.capacity(), 0);
}
and during startup run test_run() at some point where you do have text output of some sort.

Hope you enjoy it! :-)
Post Reply