Skip to main content

Headlock - Python/C Bridge for Unittesting

buildstate docstate

About

This is an adapter for testing C code via tests written in python. When being combined i.e. with pytest it provides a very powerful and convinient way of writing (unit-/integration-) tests for C code.

In contrary to other C/Python bridges (like ctypes, cffi, swing, ...) the goals of this projects are:

  • Run (and Compile) a piece of C code (Module Under Test) out of the box with as less lines of Python code as possible. No need to create Makefile, no need to run extra build steps.
  • Provide a simple, intuitive API for accessing C objects
  • Allow to quickly:
    • mock the underlying C modules in Python
    • work with different binaries of a Module Under Test at the same time.
    • testing a Module Under Test with binaries compiled with different preprocessor defines
  • Run the C code in a separate Address Space to avoid that a crashing Module Under Test crashes also the testing python code (Not implemented yet!).
  • Especially make it work with embedded systems, so that
    • C code can be run on real hardware while python tests run on PC. (Mainly useful for integration tests) This is not implemented yet!
    • C code can be run on PC instead of embedded environment. (Mainly useful for unittests)

Explicitly Non-Goals Are:

  • Supporting C++ is not planned
  • Performance has a very low priority. This does not mean that it is slow. But if speed conflicts with one of the goals of this project, there will be no compromises in favour of speed.
  • Being self-contained is not planned. A C-compiler is required to be installed for building C code.
  • Python < 3.9 is not supported

Sample

This piece of C-code contains a macros, a struct a function implementation and a function that is relying on (which should be mocked):

#include "underlying_module.h"

struct ops_t
{
    int a, b;
} ;

#define MACRO_2   (MACRO_1 + 1)

int func(struct ops_t * p)
{
    return underlying_func(p->a + p->b + MACRO_1);
}

You can access it from python through headlock like:

from headlock.testsetup import TestSetup, CModule

@CModule('dummy.c', MACRO_1=1)
class TSSample(TestSetup):
    def underlying_func_mock(self, param):
        return param.val + 4000

with TSSample() as ts:
    ops = ts.struct.ops_t(a=ts.MACRO_2, b=20)
    assert ts.func(ops.ptr).val == 4021

This demonstrates how:

  • You can handle different binaries of the same C-source per .py file (as each one is a TestSetup derived class instead of a module)
  • Every binary can be compiled with other parameters (PY_MACRO can be set differently per testsetup)
  • structures/unions/enums/typedefs can be accessed from Python without extra declarations (struct ops_t in this case).
  • You can access C-functions from Python without extra declarations (func in this case)
  • You can access C-macros from Python without extra declarations (C_MACRO in this case)
  • You can call python-methods from C (=mocking C functions that are not part of the Module Under Test; underlying_func in this case). It is even possible to dynamicially replace mocks (i.e. by unittest.mock.Mock())

Status

Currently this is beta.

For a list of planned but not yet implemented features please refer to Development Status

Metadata

Release files for headlock 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for headlock 0.6.0
File Size Uploaded
headlock-0.6.0.tar.gz 53.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for headlock 0.6.0
File Interpreter ABI Platform
headlock-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 103.9 kB

Release files / headlock-0.6.0.tar.gz

Download URL headlock-0.6.0.tar.gz
Size 53.3 kB
Tags Source
SHA-256 checksum
How to use checksums
79ef6913ae7a7a7dd282e3c40643c4571905b8d96f7c36da4a46a9e549151c33
BLAKE2b-256 checksum
How to use checksums
c51d609be7610b93d97a1387ab70376cbb55ac675e08bf9a7d2840d3315dc7d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release files / headlock-0.6.0-py3-none-any.whl

Download URL headlock-0.6.0-py3-none-any.whl
Size 50.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe81a38c044b03183af8912572f01651e248997b74efaf8fb47cc491d5cbc76b
BLAKE2b-256 checksum
How to use checksums
3277255437abe549acce6ec51ebb0e1809cefa9080394d94c44a6586b5bf41d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.5

1 release file

0.5.3

1 release file

0.5.2

1 release file

0.5.1

1 release file

0.5.0

1 release file

0.4.1

2 release files

0.4.0

2 release files

0.3.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page