{"id":17129419,"url":"https://github.com/sergiusthebest/kmtest","last_synced_at":"2025-04-13T06:32:03.799Z","repository":{"id":51237142,"uuid":"73013838","full_name":"SergiusTheBest/kmtest","owner":"SergiusTheBest","description":"Kernel-mode C++ unit testing framework in BDD-style","archived":false,"fork":false,"pushed_at":"2023-08-31T15:57:20.000Z","size":39,"stargazers_count":50,"open_issues_count":0,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-26T23:11:17.935Z","etag":null,"topics":["bdd","driver","header-only","kernel-mode","test-framework","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SergiusTheBest.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-11-06T19:31:08.000Z","updated_at":"2025-03-06T19:59:14.000Z","dependencies_parsed_at":"2023-02-17T22:00:32.871Z","dependency_job_id":null,"html_url":"https://github.com/SergiusTheBest/kmtest","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergiusTheBest%2Fkmtest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergiusTheBest%2Fkmtest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergiusTheBest%2Fkmtest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SergiusTheBest%2Fkmtest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SergiusTheBest","download_url":"https://codeload.github.com/SergiusTheBest/kmtest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248674659,"owners_count":21143760,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bdd","driver","header-only","kernel-mode","test-framework","unit-testing"],"created_at":"2024-10-14T19:09:37.320Z","updated_at":"2025-04-13T06:32:03.481Z","avatar_url":"https://github.com/SergiusTheBest.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KmTest\nKernel-mode C++ unit testing framework in BDD-style [![Build status](https://ci.appveyor.com/api/projects/status/oh90njhd50dfwco0/branch/master?svg=true)](https://ci.appveyor.com/project/SergiusTheBest/kmtest/branch/master)\n\n- [Introduction](#introduction)\n  - [Features](#features)\n  - [Requirements](#requirements)\n- [Usage](#usage)\n  - [Creating a test project](#creating-a-test-project)\n  - [Main function](#main-function)\n  - [Writing tests](#writing-tests)\n    - [BDD-style test](#bdd-style-test)\n    - [Traditional test](#traditional-test)\n    - [Require clauses](#require-clauses)\n  - [Running tests](#running-tests)\n    - [Test output](#test-output)\n- [Samples](#samples)\n- [License](#license)\n- [Acknowledgment](#acknowledgment)\n- [Version history](#version-history)\n\n# Introduction\nThere is a lack of unit testing frameworks that work in OS kernel. This library closes that gap and is targeted for Windows driver developers.\n\n## Features\n- designed for testing kernel-mode code\n- can run in user mode (for testing mode-independent code)\n- header-only\n- easy to use\n- BDD-style approach for writing unit tests (as well as a traditional one)\n- code sharing between steps in scenario\n\n## Requirements\n- Windows XP and higher\n- Visual Studio 2010 and higher\n\n# Usage\n\n## Creating a test project\nCreate an empty driver project and do the following:\n- add a path to `kmtest/inlcude` into the project include paths\n- add `#include \u003ckmtest/kmtest.h\u003e` into your new cpp/h files (if you have precompiled headers it is a good place to add this include there)\n\nThis is a sample precompiled header:\n```cpp\n#pragma once\n#include \u003cntddk.h\u003e\n#include \u003ckmtest/kmtest.h\u003e\n```\n\n## Main function\n`DriverEntry` or `main` is automatically created by the library, so you don't need to write it. \n\nA driver object and a registry path can be accessed via `kmtest::g_driverObject` and `kmtest::g_registryPath`.\n\n\n## Writing tests\nYou can write tests cases in 2 styles:\n- BDD-style (using GIVEN-WHEN-THEN clauses)\n- traditional\n\n### BDD-style test\nBDD-style tests requires more efforts in writing but they are superior in maintaining than traditional tests. The basic test structure is shown below (for more advanced usage read about [code sharing](#code-sharing)):\n```cpp\nSCENARIO(\"Addition operation\")\n{\n    GIVEN(\"x = 2\")\n    {\n        int x = 2;\n\n        WHEN(\"y = 3\")\n        {\n            int y = 3;\n\n            THEN(\"the sum will be 5\")\n            {\n                REQUIRE(Calculator::add(x, y) == 5);\n            }\n        }\n    }\n}\n```\nWhere:\n- `SCENARIO`,`GIVEN`,`WHEN`,`THEN` are used to describe the test\n- `REQUIRE` is used for assertions (can be placed in any block)\n\n#### Code sharing\nA great feature of BDD-style tests is that a `SCENARIO` can have several `GIVEN` clauses, a `GIVEN` can have several `WHEN` clauses, a `WHEN` can have several `THEN` clauses. KmTest framework will run all combinations as independed test cases. The sample below will produce 2 test cases (`2+3=5` and `2+0=2`):\n```cpp\nSCENARIO(\"Addition operation\")\n{\n    GIVEN(\"x = 2\")\n    {\n        int x = 2;\n\n        WHEN(\"y = 3\")\n        {\n            int y = 3;\n\n            THEN(\"the sum will be 5\")\n            {\n                REQUIRE(Calculator::add(x, y) == 5);\n            }\n        }\n\n        WHEN(\"y = 0\")\n        {\n            int y = 0;\n\n            THEN(\"the sum will be 2\")\n            {\n                REQUIRE(Calculator::add(x, y) == 2);\n            }\n        }\n    }\n}    \n```\nThat's not all. Setup/cleanup code can be shared as well. It is demonstrated by the following example:\n```cpp\nSCENARIO(\"Addition operation\")\n{\n    // \u003c== Here you can write a shared setup code for SCENARIO.\n\n    GIVEN(\"x = 2\")\n    {\n        int x = 2; // \u003c== Here you can write a shared setup code for GIVEN.\n\n        WHEN(\"y = 3\")\n        {\n            int y = 3; // \u003c== Here you can write a shared setup code for WHEN.\n\n            THEN(\"the sum will be 5\")\n            {\n                REQUIRE(Calculator::add(x, y) == 5);\n            }\n\n            // \u003c== Here you can write a shared cleanup code for WHEN.\n        }\n\n        // \u003c== Here you can write a shared cleanup code for GIVEN.\n    }\n\n    // \u003c== Here you can write a shared cleanup code for SCENARIO.\n}\n```\n\n### Traditional test\nA traditional test is shown below and is represented by a BDD-style test without GIVEN-WHEN-THEN clauses:\n```cpp\n// A minimal scenario for those who do not want to write GIVEN-WHEN-THEN clauses.\nSCENARIO(\"Multiplication operation\")\n{\n    REQUIRE(6 == Calculator::mul(2, 3));\n    REQUIRE(-30 == Calculator::mul(-10, 3));\n    REQUIRE(6 == Calculator::mul(-2, -3));\n    REQUIRE(0 == Calculator::mul(0, 3));\n}\n```\nWhere:\n- `SCENARIO` is used to describe the test\n- `REQUIRE` is used for assertions\n\n### Require clauses\nRequires clauses are used for assertions. There are several of them:\n|Clause|Expression return type|Expression expected value|\n|--|--|--|\n|REQUIRE(expression)|bool|true|\n|REQUIRE_NT_SUCCESS(expression)|NTSTATUS|NT_SUCCESS(status)|\n|REQUIRE_NT_FAILURE(expression)|NTSTATUS|!NT_SUCCESS(status)|\n\n## Running tests\nRunning KmTest based tests means starting a driver. It is highly recommended to do this inside a virtual machine. Any assertion failure will trigger a kernel debugger breakpoint or a BSOD if there is no debugger.\n\n*Refer to [samples/CalcTest/CalcTest.cmd](samples/CalcTest/CalcTest.cmd) for how to start a driver from the command line.*\n\n### Test output\nKmTest writes messages to the debug output. It can be viewed by WinDbg, DbgView or similar tools. A sample test output is demonstrated below:\n\n```\n**************************************************\n* KMTEST BEGIN\n**************************************************\n--------------------------------------------------\nSCENARIO: Addition operation\n--------------------------------------------------\nGIVEN: x = 2\n  WHEN: y = 3\n    THEN: the sum will be 5\nGIVEN: x = 2\n  WHEN: y = 0\n    THEN: the sum will be 2\nGIVEN: x = 2\n  WHEN: y = -2\n    THEN: the sum will be 0\nGIVEN: x = -2\n  WHEN: y = 3\n    THEN: the sum will be 1\nGIVEN: x = -2\n  WHEN: y = -1\n    THEN: the sum will be -3\n \nASSERTIONS PASSED: 5\n \n--------------------------------------------------\nSCENARIO: Multiplication operation\n--------------------------------------------------\n \nASSERTIONS PASSED: 4\n \n--------------------------------------------------\nSCENARIO: Subtraction operation\n--------------------------------------------------\nGIVEN: x = 8\n  WHEN: y = 3\n    THEN: the difference will be 5\nGIVEN: x = 8\n  WHEN: y = 0\n    THEN: the difference will be 8\nGIVEN: x = 8\n  WHEN: y = -2\n    THEN: the difference will be 10\nGIVEN: x = -3\n  WHEN: y = 2\n    THEN: the difference will be -5\nGIVEN: x = -3\n  WHEN: y = -1\n    THEN: the difference will be -2\n \nASSERTIONS PASSED: 5\n \n**************************************************\n* KMTEST END (scenarios: 3, assertions: 14)\n**************************************************\n```\n\n# Samples\nThere is a [samples](samples) folder that demonstrates usage of KmTest unit testing framework. To compile it you need Visual Studio 2015 and WDK10.\n\n# License\nKmTest is licensed under the [MPL version 2.0](http://mozilla.org/MPL/2.0/). You can freely use it in your commercial or opensource software.\n\n# Acknowledgment\nThanks to Phil Nash and his [Catch C++ test framework](https://github.com/philsquared/Catch) for BDD-style inspiration.\n\n# Version history\n\n## Version 0.9.1 (26 May 2022)\n- New: Add ability to run in user space #2\n- New: Save `DriverEntry` arguments #4\n- New: Add macro REQUIRE_SUCCESS and REQUIRE_FAILURE #5\n- Fix: Cannot convert `const char []` to `PVOID` #6\n\n## Version 0.9.0 (18 Jan 2017)\n- Initial public release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergiusthebest%2Fkmtest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsergiusthebest%2Fkmtest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergiusthebest%2Fkmtest/lists"}