Page 1 of 1

How to test your OS

Posted: Thu Apr 28, 2011 12:24 pm
by AlfaOmega08
In the last few months I've discovered the beauty and utility of testing. I have to admit that even though I learnt C++ more than 8-9 years ago I've never tested any of my programs until a few months ago. I learned how to use the googletest framework for c++ and get used to it. I've been frustrated however that I can't use googlecode to test my hobby operating system. I tried to build the library and plug it in the kernel, but there are tons of undefined references. Diving in the sources I found a gtest-port.h where many constants are defined to handle many operating system. However it's a pain to add a new system. So I tried to build a new framework having as model googletest. This is a LOT simpler than googletest to be ported. There are some big requirements however that, I'm sorry to say, many still haven't implemented. So it is a framework for half-mature OSs. Requirements are:
* C++ with Exceptions support
* A dynamic memory manager (new and delete)
* A method to write output (on screen, on a file, on the serial port, you decide)
* A vector/list like template class (you can use stl ones or your one, just be sure that you can add and remove elements from it)
* The ctype tolower function, or any other function which given a char returns the lowercase equivalent
So you can start testing only after memory manager has been initialized and exceptions enabled.

I'm releasing this code in the hope that it will be useful to someone but since it seems that licenses like GPL and CC are hated by some people on this forum (and that would block them from using this) I decided to release this code in the Public Domain. And to avoid problems using the "Public Domain" expression I will say that
Solar wrote:Permission is granted to use, modify, and / or redistribute at will.
This includes removing authorship notices, re-use of code parts in other software (with or without giving credit), and / or creating a commercial product based on it.
This permission is not revocable by the author.
This software is provided as-is. Use it at your own risk. There is no warranty whatsoever, neither expressed nor implied, and by using this software you accept that the author(s) shall not be held liable for any loss of data, loss of service, or other damages, be they incidental or consequential. Your only option other than accepting this is not to use the software at all.
Not every function of googletest has been implemented yet. But any example at http://code.google.com/p/googletest/wiki/V1_6_Primer will work and all the examples at http://code.google.com/p/googletest/wik ... n_Function until the paragraph "Using an Existing Boolean Function" (inclusive). I believe these are the most used ones. Death tests are not implemented nor they will (why using death tests in a kernel?), multithreading is not (maybe in the future).

It's very easy to use. Given a factorial function:

Code: Select all

int Factorial(int n)
{
   if (n < 2)
       return 1;
   return n * Factorial(n - 1);
}
you can test it like this:

Code: Select all

TEST(FactorialTest, LessThan2Returns1)
{
    EXPECT_EQ(1, Factorial(1));
    EXPECT_EQ(1, Factorial(0));
    EXPECT_EQ(1, Factorial(-100));
}

TEST(FactorialTest, GenericFactorial)
{
    EXPECT_EQ(2, Factorial(2));
    EXPECT_EQ(24, Factorial(4));
}
This creates two tests. To run them place somewhere after the needed initializations:

Code: Select all

RUN_ALL_TESTS();
This returns a value of 0 if all tests were successful, 1 otherwise.
Besides EXPECT_EQ, there are EXPECT_NE, EXPECT_LT, EXPECT_LE, EXPECT_GT, EXPECT_GE, and others. Each one of them have a ASSERT_** counterpart: ASSERT_EQ, ASSERT_NE, ASSERT_LT, ...
The difference between EXPECT_ and ASSERT_ is that ASSERT_ stops the current test on failure, EXPECT_ lets the test going on.
You can print a custom message on failure:

Code: Select all

EXPECT_EQ(24, Factorial(4)) << "4! != 24. There is a bug in Factorial!";
Those were just small example of what you can do. Check the googletest documentation for more examples.
At the moment the only serious bug found is that if you don't print anything when using ASSERT_, even though the single ASSERT_ fails, the tests keeps running like if it was an EXPECT_. So always be sure to put something near ASSERT_ (even ASSERT_EQ(2,2) << "" will work).

Since someone use std::cout and someone printf, I've made two versions so that you can just plug it in your kernel. If you use a custom function for printing output, just change all the printf (or cout) to your function. Since the output tends to be very large, it doesn't fit often in 25 rows, so (unless you have scrolling in your console), you're better redirecting output to a file, or to the 0xE9 port in bochs, or to serial, or whatever you think it's appropriate.

So this is CppOsTest 0.1-alpha. It would be great if someone tests this test framework :) Any suggestion, bug report and comment is appreciated

Re: How to test your OS

Posted: Fri Apr 29, 2011 9:38 am
by AlfaOmega08
berkus wrote:Why do you have two different implementations?
They're equal. The only difference is only that one uses printf, and the other cout. I'm planning to use a single class for all the outputs and you can specify there whether you use printf, cout or another function.

Re: How to test your OS

Posted: Sat Apr 30, 2011 6:23 pm
by xfelix
If you really want to test your OS automatically instead of manually, you could use the e9 hack for qemu. It dumps the output
from the qemu terminal to standard output.