---
# System prepended metadata

title: Unit test framework for kernel (ktfff)

---

# Unit test framework for kernel (ktfff)
-----------------------------

## Introduction
This framework is a unit test runner which integrates the following open source:
1. [ktf (kernel test framework)](https://github.com/oracle/ktf)
2. [fff (fake function framework)](https://github.com/meekrosoft/fff)

A first open source is a kernel unit test framework, but it hasn't covered the mock feature, that will cause some unit test case could not reproduce easy.
So, we join the fff framework with ktf, then we could use mock function and could run the unit test in linux kernel.

## Options
Usage:  ./ktfff.sh [argument...]

#### Argument:
* ```install```:
    * install the ktfff required pakage (gtest, ktf).
* ```run```:
    * build all kernel module and run all unittest case.

    ```--test=<test case>```
    * build the specific kernel module and run the specific unit test case.
    
    ```--suite=<test file>``` 
    * build the specific kernel module and run the specific unit test file.
        
* ```clean```:
    * remove all file generated by ktfff.

* ```uninstall```:
    * uninstall ktfff framework.
 
* ```-h, --help```: 
    * display this help text and exit.

## Usage
**ktfff setup**  
ktfff install will build the gtest and ktf in ~/ktfff.
```
./ktfff.sh install
```

**Run all unit test**  
```
./ktfff.sh run
```

**Run specific unit test case**  
```
./ktfff.sh run --test=hello_ok --test=hello_fail
```

**Run specific unit test file**  
```
./ktfff.sh run --suite=test_hello.c
```

**Run with other ktfrun options** (Hasn't implement)  
```
```

**Clean env**  
```
./ktfff.sh clean
```

**ktfff uninstall**
```
./ktfff.sh uninstall
```

## Unit test example
#### Coding rule
```
KTF_INIT();

TEST(unit_name, test_name)
{
	EXPECT_TRUE(true);
}
ADD_TEST(test_name);
``` 

```
Prep:
   KTF_INIT();
   DECLARE_F(fixture_name)
         <attributes>
   };
   INIT_F(fixture_name,setup,teardown);

Usage:
   SETUP_F(fixture_name,setup)
   {
          <setup code, set ctx->ok to true to have the test executed>
   }
   TEARDOWN_F(fixture_name,teardown)
   {
          <teardown code>
   }
   TEST_F(fixture_name,unit_name,test_name)
   {
          <test code>
   }
```
example: [link](https://github.com/oracle/ktf/blob/master/examples/h3.c)
#### Assersion
[ktfff Assertion docs](https://github.com/oracle/ktf/blob/master/kernel/ktf.h#L213)


## Mock function
#### How to Mock
If you want to mock the function in ktfff, could reference the following template, you should add the comment that `// MOCK_FILE: <mock_filename>` in your test file, the `./ktfff.sh` will through this comment to exclude the mock file in makefile.

Due to `fff.h` will reference `FAKE_VOID_FUNC` or `FAKE_VALUE_FUNC` to redefine the function which you want to mock, so we couldn't include this file to compile together.  

**Step**:
1. Include the fff header `#include "fff.h"`
2. Init fff `DEFINE_FFF_GLOBALS;`
3. Comment your mock function `// MOCK_FILE: mock filename`
4. Using fff macro to mock your function `FAKE_VOID_FUNC(void function);` or `FAKE_VALUE_FUNC(return type, function);`

*Example in ktfff_unittest/unittest/test_hello.c*
```
#include "../lib/fff.h"
DEFINE_FFF_GLOBALS;

// MOCK_FILE: drv_main.c
FAKE_VALUE_FUNC(int32_t, init_drv_component);
FAKE_VALUE_FUNC(int32_t, rel_drv_component);

RESET_FAKE(init_drv_component);
RESET_FAKE(rel_drv_component);
```
##### fff Macro Table:
| Macro | Description | Example |
|-------|-------------|---------|
| `FAKE_VOID_FUNC(fn [,arg_types*]);` |Define a fake function named fn returning void with n arguments | `FAKE_VOID_FUNC(DISPLAY_output_message, const char*);` |
| `FAKE_VALUE_FUNC(return_type, fn [,arg_types*]);` | Define a fake function returning a value with type return_type taking n arguments | `FAKE_VALUE_FUNC(int, DISPLAY_get_line_insert_index);` |
| `RESET_FAKE(fn);` | Reset the state of fake function called fn | `RESET_FAKE(DISPLAY_init);` |

#### Mock function structure
fff will also defines a struct `"function_name"_fake` which contains all the information about the fake, and support some method for test.

For instance:
 |Usage|Description|Referencee|
 |-----|-----------|----------|
|`"function_name"_fake.call_count`| will incremented every time the faked function is called |[more..](https://github.com/meekrosoft/fff/blob/master/README.md#hello-fake-world)
|`"function_name"_fake.return_val`| define a mock function that returns a value|[more..](https://github.com/meekrosoft/fff/blob/master/README.md#return-values)|

More mock function information: [fff docs](https://github.com/meekrosoft/fff/blob/master/README.md)

---
## ktfff implemention
![](https://i.imgur.com/RmIpEre.png)
## ktfff file structure
```
.
├── ...
├── unittest-mk-temp		# Each unit test makefiles folder
├── unittest-module-temp	# Each test case kernel module temporary folder
├── unittest-output			# Unit test result temporary folder
├── unittest				# Unit test files
├── lib						# Library for ktfff
│   ├── config.sh           # Define all global variable
│   ├── fff.h				# fff header file
│   ├── install.sh			# Install function of ktfff
│   ├── kerN_ver_patch.sh   # Patch dms_kernel_version.h with different linux kernel version
│   ├── makefile.sh			# Generate && build Makefile function
│   ├── message.sh          # Message information ouput for ktfff runner
│   └── unittest.sh			# About unit test trigger function and info message function
├──	gtest2html				# A template which transfer xml to html
├── ktfff.sh				# ktfff runner main script file
└── Makefile_ktfff			# Template Makefile for ktfff 
```

## Run unit test 
#### ktfrun
**Step**:
1. Insert kernel module - ktf.ko 
```
sudo insmod ktfff/build/4.4.0-134-generic/ktf/kernel/ktf.ko
```
2. Insert unit test kernel modlue - test_hello.ko
```
sudo insmod unittest-module-temp/4.4.0-134-generic/test_hello.ko
```
3. Run ktfrun
```
ktfrun
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from examples
[ RUN      ] examples./hello_fail
[       OK ] examples./hello_fail (1 ms)
[ RUN      ] examples./hello_ok
[       OK ] examples./hello_ok (0 ms)
[----------] 2 tests from examples (1 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 2 tests.

```

#### ktfff Runner
```
./ktfff.sh run
[INFO] BUILDING KERNEL MODULE 
...
...
[INFO] UNNITEST START 
======================================================================================
ktfff_unittest :: kernel version - 4.4.0-134-generic Test
======================================================================================

[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from examples
[ RUN      ] examples./hello_fail
[       OK ] examples./hello_fail (0 ms)
[ RUN      ] examples./hello_ok
[       OK ] examples./hello_ok (0 ms)
[----------] 2 tests from examples (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 2 tests.

--------------------------------------------------------------------------------------
Output:	/home/louis/clientnode-uf/BlockDeviceDriver2/ktfff_unittest/unittest-output/4.4.0-134-generic/output.xml
Report:	/home/louis/clientnode-uf/BlockDeviceDriver2/ktfff_unittest/unittest-output/4.4.0-134-generic/report.html
```
#### ktfff result
![](https://i.imgur.com/GJmk2SS.png)

## Resources
ktf: [link](https://github.com/oracle/ktf/)  
fff: [link](https://github.com/meekrosoft/fff)  
