Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .claude/commands/write-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Write Tests for libqcperf

You are writing Unity-based C unit tests for the **libqcperf** (Qualcomm Performance Profiler Library).

Before writing any tests, read the relevant source and header files to confirm actual API behaviour. Use the project structure below to locate them.

## Project structure

```
qcperf/
core/inc/
qcperf.h ← core API
qcperf_common.h ← return codes, structs, typedefs
backends/inc/
qcperf_backend_enum.h ← QcPerfBackendId enum
qcperf_backends.h ← backend init registry
backends/dummy/inc/
dummy.h
third-party/Unity/src/
unity.h ← test framework
test_app/
src/ ← test source files go here
CMakeLists.txt ← register new test executables here
```

## Backends

```c
enum QcPerfBackendId {
QC_PERF_BACKEND_DUMMY = 0, // safe on any machine
QC_PERF_BACKEND_POWER = 1, // requires WoS ARM64 hardware
QC_PERF_BACKEND_THERMAL = 2, // requires WoS ARM64 hardware
QC_PERF_BACKEND_MAX,
};
```

## Core API

```c
enum QcPerfReturnCode qcperf_init(void);
enum QcPerfReturnCode qcperf_deinit(void);
enum QcPerfReturnCode qcperf_version(struct QcPerfVersionInfo *version_info);
enum QcPerfReturnCode qcperf_connect_backend(enum QcPerfBackendId id, QcPerfMessageCallback cb);
enum QcPerfReturnCode qcperf_disconnect_backend(enum QcPerfBackendId id);
enum QcPerfReturnCode qcperf_get_capabilities_info(enum QcPerfBackendId id, struct QcPerfBackendInfo *info);
enum QcPerfReturnCode qcperf_set_data_callback(enum QcPerfBackendId id, QcPerfDataCallback cb);
enum QcPerfReturnCode qcperf_start(enum QcPerfBackendId id, struct QcPerfRequest *req);
enum QcPerfReturnCode qcperf_stop(enum QcPerfBackendId id, struct QcPerfRequest *req);
enum QcPerfReturnCode qcperf_get_error_info(enum QcPerfReturnCode code, struct QcPerfReturnCodeInfo *info);
```

## Unity patterns

**Test function:**
```c
void test_<api>_<scenario>(void)
{
enum QcPerfReturnCode ret = ...;
TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret);
}
```

**Test runner (`main`):**
```c
void setUp(void) { }
void tearDown(void) { }

int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
UNITY_BEGIN();
RUN_TEST(test_foo);
return UNITY_END();
}
```

**Common assertions:**
```c
TEST_ASSERT_EQUAL(expected, actual)
TEST_ASSERT_NOT_EQUAL(not_expected, actual)
TEST_ASSERT_NULL(ptr)
TEST_ASSERT_NOT_NULL(ptr)
TEST_ASSERT_TRUE(condition)
TEST_ASSERT_GREATER_THAN(threshold, actual)
TEST_ASSERT_EQUAL_STRING(expected, actual)
```

## CMakeLists.txt pattern for a new test executable

```cmake
add_executable(test_<name>
src/test_runner_<name>.c
src/test_<name>.c
)
target_include_directories(test_<name> PRIVATE
${CMAKE_SOURCE_DIR}/third-party/Unity/src
${CMAKE_SOURCE_DIR}/core/inc
${CMAKE_SOURCE_DIR}/backends/inc
${CMAKE_SOURCE_DIR}/backends/dummy/inc
)
target_link_libraries(test_<name> PRIVATE unity QcPerfCore)
add_test(NAME <name>_tests COMMAND test_<name>)
```

## Existing tests (do not duplicate)

| File | What is already tested |
|------|------------------------|
| `test_qcperf_unit.c` | init, deinit, connect dummy, disconnect dummy, get_capabilities_info dummy |
| `test_backends.c` | dummy init, dummy info (backend_id + capabilities_list_length), dummy deinit |

## Rules

1. Each test calls `qcperf_init()` at the start and `qcperf_deinit()` at the end — the library does not persist state across cycles.
2. One logical condition per test function.
3. Name tests `test_<api_function>_<scenario>`, e.g. `test_connect_backend_invalid_id_returns_error`.
4. Cover both happy paths and error paths (null pointers, bad IDs, wrong call order, double init, etc.).
5. Use `QC_PERF_BACKEND_DUMMY` unless the user explicitly asks for hardware-specific tests.
6. New source files go in `qcperf/test_app/src/`. Update `CMakeLists.txt` if adding a new executable.

---

User request: **$ARGUMENTS**
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build*
.vscode
qcperf/third-party/*
!qcperf/third-party/Unity/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "qcperf/third-party/krabs"]
path = qcperf/third-party/krabs
url = https://github.com/microsoft/krabsetw.git
[submodule "qcperf/third-party/Unity"]
path = qcperf/third-party/Unity
url = https://github.com/ThrowTheSwitch/Unity.git
6 changes: 5 additions & 1 deletion qcperf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ project(QcPerf
# This centralizes platform detection, compiler flags, and other build settings
include(cmake/BuildConfig.cmake)

# Enable testing
enable_testing()

# ============================================================================
# Component subdirectories
# ============================================================================
# Add each component in dependency order:
# - third-party: Third-party libraries (Unity testing framework)
# - core: Main library functionality
# - backends: Performance monitoring backend implementations
# - utils: Utility libraries used by core and backends
# - core-test: Test application for the core library
# - test-app: Test application for the core library
add_subdirectory(third-party)
add_subdirectory(core)
add_subdirectory(backends)
add_subdirectory(utils)
Expand Down
Loading