diff --git a/.claude/commands/write-tests.md b/.claude/commands/write-tests.md new file mode 100644 index 0000000..69c099d --- /dev/null +++ b/.claude/commands/write-tests.md @@ -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__(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_ + src/test_runner_.c + src/test_.c +) +target_include_directories(test_ 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_ PRIVATE unity QcPerfCore) +add_test(NAME _tests COMMAND test_) +``` + +## 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__`, 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** diff --git a/.gitignore b/.gitignore index 9367dbb..693921e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build* .vscode qcperf/third-party/* +!qcperf/third-party/Unity/ diff --git a/.gitmodules b/.gitmodules index 20f5746..683682f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/qcperf/CMakeLists.txt b/qcperf/CMakeLists.txt index 0d2627c..48e2ab5 100644 --- a/qcperf/CMakeLists.txt +++ b/qcperf/CMakeLists.txt @@ -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) diff --git a/qcperf/run-tests-with-report.ps1 b/qcperf/run-tests-with-report.ps1 new file mode 100644 index 0000000..55cac93 --- /dev/null +++ b/qcperf/run-tests-with-report.ps1 @@ -0,0 +1,336 @@ +# QcPerf Testing Framework - Run Tests with Reporting (PowerShell) +# This script runs the already-built tests and generates reports +# Use build-tests.ps1 to build first, then run this to generate reports + +param( + [switch]$GenerateReport = $false, + [string]$OutputFormat = "text" +) + +# Get script directory +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$buildDir = Join-Path $scriptDir "build" +$testResultsDir = Join-Path $scriptDir "test-results" + +# Create test results directory if it doesn't exist +if (-not (Test-Path $testResultsDir)) { + New-Item -ItemType Directory -Path $testResultsDir | Out-Null +} + +# Generate timestamp for results +$timestamp = Get-Date -Format 'yyyy-MM-dd-HHmmss' +$logFile = Join-Path $testResultsDir "test-run-$timestamp.log" +$jsonFile = Join-Path $testResultsDir "test-results-$timestamp.json" + +# Initialize test results object +$testResults = @{ + timestamp = $timestamp + testStatus = "UNKNOWN" + suites = @() + totalTests = 0 + passedTests = 0 + failedTests = 0 + ignoredTests = 0 +} + +function Log-Message { + param([string]$Message, [string]$Level = "INFO") + $logEntry = "[$((Get-Date).ToString('HH:mm:ss'))] [$Level] $Message" + Write-Host $logEntry + Add-Content -Path $logFile -Value $logEntry +} + +# Runs a single Unity test executable, parses output and returns a suite result object +function Invoke-TestSuite { + param([string]$SuiteName, [string]$ExePath) + + $suite = @{ + name = $SuiteName + status = "NOT_FOUND" + total = 0 + passed = 0 + failed = 0 + ignored = 0 + testCases = @() + } + + if (-not (Test-Path $ExePath)) { + Log-Message "Executable NOT found: $ExePath" "ERROR" + Log-Message "Did you run build-tests.ps1 first?" "INFO" + return $suite + } + + Log-Message "Running suite '$SuiteName': $ExePath" "SUCCESS" + $output = & $ExePath 2>&1 + $outputStr = $output | Out-String + + Add-Content -Path $logFile -Value "`n=== $SuiteName OUTPUT ===" + Add-Content -Path $logFile -Value $outputStr + + $output | ForEach-Object { Log-Message "$_" "TEST" } + + # Parse individual test case lines + # Unity format: :::PASS or :::FAIL: + foreach ($line in $output) { + if ($line -match '^.+:\d+:(\w+):(PASS|FAIL|IGNORE)(.*)$') { + $suite.testCases += @{ + name = $Matches[1] + result = $Matches[2] + message = $Matches[3].TrimStart(':') + } + } + } + + # Parse summary line: "5 Tests 0 Failures 0 Ignored" + if ($outputStr -match '(\d+)\s+Tests\s+(\d+)\s+Failures\s+(\d+)\s+Ignored') { + $suite.total = [int]$Matches[1] + $suite.failed = [int]$Matches[2] + $suite.ignored = [int]$Matches[3] + $suite.passed = $suite.total - $suite.failed - $suite.ignored + } + + $suite.status = if ($suite.total -gt 0 -and $suite.failed -eq 0) { "PASSED" } else { "FAILED" } + return $suite +} + +# Start logging +Log-Message "========================================" "INFO" +Log-Message "QcPerf Testing Framework - Run Tests with Reporting" "INFO" +Log-Message "========================================" "INFO" +Log-Message "Log file: $logFile" "INFO" + +$suites = @() + +try { + Log-Message "" "INFO" + Log-Message "========================================" "INFO" + Log-Message "Running Unit Tests..." "INFO" + Log-Message "========================================" "INFO" + + # Run core tests + $coreExe = Join-Path $buildDir "test_app\Release\test_qcperf_core.exe" + $coreSuite = Invoke-TestSuite -SuiteName "qcperf_core" -ExePath $coreExe + $suites += $coreSuite + + Log-Message "" "INFO" + + # Run backends tests + $backendsExe = Join-Path $buildDir "test_app\Release\test_qcperf_backends.exe" + $backendsSuite = Invoke-TestSuite -SuiteName "qcperf_backends" -ExePath $backendsExe + $suites += $backendsSuite + + # Aggregate totals across all suites + foreach ($suite in $suites) { + $testResults.totalTests += $suite.total + $testResults.passedTests += $suite.passed + $testResults.failedTests += $suite.failed + $testResults.ignoredTests += $suite.ignored + } + $testResults.suites = $suites + + $anyFailed = $suites | Where-Object { $_.status -ne "PASSED" } + if ($anyFailed) { + $testResults.testStatus = "FAILED" + Log-Message "" "INFO" + Log-Message "========================================" "INFO" + Log-Message "SOME TESTS FAILED" "ERROR" + Log-Message "========================================" "INFO" + } else { + $testResults.testStatus = "PASSED" + Log-Message "" "INFO" + Log-Message "========================================" "INFO" + Log-Message "ALL TESTS PASSED" "SUCCESS" + Log-Message "========================================" "INFO" + } + +} catch { + Log-Message "Error: $_" "ERROR" + $testResults.testStatus = "ERROR" +} + +# Generate summary +Log-Message "" "INFO" +Log-Message "========================================" "INFO" +Log-Message "TEST SUMMARY" "INFO" +Log-Message "========================================" "INFO" +Log-Message "Test Status: $($testResults.testStatus)" "INFO" +Log-Message "Total Tests: $($testResults.totalTests)" "INFO" +Log-Message "Passed Tests: $($testResults.passedTests)" "INFO" +Log-Message "Failed Tests: $($testResults.failedTests)" "INFO" +Log-Message "Ignored Tests: $($testResults.ignoredTests)" "INFO" +Log-Message "========================================" "INFO" +Log-Message "Log file saved to: $logFile" "INFO" + +# Generate JSON report if requested +if ($GenerateReport -or $OutputFormat -eq "json") { + Log-Message "Generating JSON report..." "INFO" + $testResults | ConvertTo-Json -Depth 5 | Out-File $jsonFile -Encoding UTF8 + Log-Message "JSON report saved to: $jsonFile" "SUCCESS" +} + +# Always generate HTML report +$htmlFile = Join-Path $testResultsDir "test-report-$timestamp.html" +Log-Message "Generating HTML report..." "INFO" + +$overallClass = if ($testResults.testStatus -eq "PASSED") { "passed" } else { "failed" } +$overallLabel = if ($testResults.testStatus -eq "PASSED") { "ALL TESTS PASSED" } else { "SOME TESTS FAILED" } + +# Build suite summary rows +$suiteRowsHtml = "" +foreach ($suite in $suites) { + $sc = if ($suite.status -eq "PASSED") { "pass" } else { "fail" } + $suiteRowsHtml += @" + + + $($suite.name) + $($suite.total) + $($suite.passed) + $($suite.failed) + $($suite.ignored) + $($suite.status) + +"@ +} + +# Build per-suite test case detail sections +$testDetailsHtml = "" +foreach ($suite in $suites) { + $suiteStatusClass = if ($suite.status -eq "PASSED") { "pass" } else { "fail" } + + $caseRowsHtml = "" + if ($suite.testCases.Count -gt 0) { + foreach ($tc in $suite.testCases) { + $tcClass = $tc.result.ToLower() + $caseRowsHtml += @" + + + $($tc.name) + $($tc.result) + $($tc.message) + +"@ + } + } else { + $caseRowsHtml = "No test case details available (executable not found)" + } + + $testDetailsHtml += @" + +
+

$($suite.name)  $($suite.status)

+ + + $caseRowsHtml + +
Test NameResultMessage
+
+"@ +} + +$htmlContent = @" + + + + + QcPerf Test Report - $timestamp + + + +
+
+

QcPerf Test Report

+

Generated: $timestamp

+
+
+ +
+
+
Total Tests
+
$($testResults.totalTests)
+
+
+
Passed
+
$($testResults.passedTests)
+
+
+
Failed
+
$($testResults.failedTests)
+
+
+
Ignored
+
$($testResults.ignoredTests)
+
+
+ +
$overallLabel
+ +

Suite Summary

+ + + + + $suiteRowsHtml + +
SuiteTotalPassedFailedIgnoredStatus
+ +

Test Details

+$testDetailsHtml + +
+
+ + +"@ + +$htmlContent | Out-File $htmlFile -Encoding UTF8 +Log-Message "HTML report saved to: $htmlFile" "SUCCESS" + +try { + Start-Process $htmlFile + Log-Message "Opened HTML report in browser" "INFO" +} catch { + Log-Message "Could not open HTML report in browser (but file was created)" "INFO" +} + +Log-Message "" "INFO" +Log-Message "Test run completed!" "INFO" + +# Exit with appropriate code +if ($testResults.testStatus -eq "PASSED") { + exit 0 +} else { + exit 1 +} diff --git a/qcperf/test_app/CMakeLists.txt b/qcperf/test_app/CMakeLists.txt index 44d0583..8e39f56 100644 --- a/qcperf/test_app/CMakeLists.txt +++ b/qcperf/test_app/CMakeLists.txt @@ -1,36 +1,65 @@ -# Create the main QcPerfCoreTest library -add_executable(QcPerfCoreTest - src/qcperf_core_test.c +# Test application using Unity Testing Framework + +# Handle Unity library +if(NOT TARGET unity) + if(EXISTS "${CMAKE_SOURCE_DIR}/third-party/Unity/src/unity.c") + add_library(unity STATIC + ${CMAKE_SOURCE_DIR}/third-party/Unity/src/unity.c + ) + target_include_directories(unity PUBLIC + ${CMAKE_SOURCE_DIR}/third-party/Unity/src + ) + else() + message(WARNING "Unity framework not configured") + return() + endif() +endif() + +# Test executable for core functionality +add_executable(test_qcperf_core + src/test_runner.c + src/test_qcperf_unit.c ) -# Set target properties -set_target_properties(QcPerfCoreTest PROPERTIES - OUTPUT_NAME "QcPerfCoreTest" - POSITION_INDEPENDENT_CODE OFF +target_include_directories(test_qcperf_core PRIVATE + ${CMAKE_SOURCE_DIR}/third-party/Unity/src + ${CMAKE_SOURCE_DIR}/core/inc + ${CMAKE_SOURCE_DIR}/backends/inc + ${CMAKE_SOURCE_DIR}/backends/dummy/inc ) -# Include directories for the core library -target_include_directories(QcPerfCoreTest - PUBLIC - ${CMAKE_SOURCE_DIR}/core/inc +target_link_libraries(test_qcperf_core + PRIVATE + unity + QcPerfCore ) -# Link dependencies -target_link_libraries(QcPerfCoreTest - PUBLIC - QcPerfCore +add_test( + NAME qcperf_core_tests + COMMAND test_qcperf_core ) -# Compiler-specific options for the core library -if(MSVC) - target_compile_options(QcPerfCoreTest PRIVATE - /W4 - /WX- # Don't treat warnings as errors (can be changed to /WX if needed) - ) -else() - target_compile_options(QcPerfCoreTest PRIVATE - -Wall - -Wextra - -Wpedantic - ) -endif() +# Test executable for backends +add_executable(test_qcperf_backends + src/test_runner_backends.c + src/test_backends.c +) + +target_include_directories(test_qcperf_backends PRIVATE + ${CMAKE_SOURCE_DIR}/third-party/Unity/src + ${CMAKE_SOURCE_DIR}/backends/inc + ${CMAKE_SOURCE_DIR}/backends/dummy/inc + ${CMAKE_SOURCE_DIR}/core/inc +) + +target_link_libraries(test_qcperf_backends + PRIVATE + unity + QcPerfCore + QcPerfDummyBackend +) + +add_test( + NAME qcperf_backends_tests + COMMAND test_qcperf_backends +) \ No newline at end of file diff --git a/qcperf/test_app/src/test_backends.c b/qcperf/test_app/src/test_backends.c new file mode 100644 index 0000000..3825746 --- /dev/null +++ b/qcperf/test_app/src/test_backends.c @@ -0,0 +1,54 @@ +/** + * @file test_backends.c + * @brief Unit tests for qcperf backends + */ + +#include "unity.h" +#include "qcperf.h" +#include "qcperf_backends.h" +#include "qcperf_backend_enum.h" + +void test_dummy_backend_init(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_dummy_backend_info(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + struct QcPerfBackendInfo backend_info = {0}; + ret = qcperf_get_capabilities_info(QC_PERF_BACKEND_DUMMY, &backend_info); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + TEST_ASSERT_EQUAL(QC_PERF_BACKEND_DUMMY, backend_info.backend_id); + TEST_ASSERT_GREATER_THAN(0, backend_info.capabilities_list_length); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_dummy_backend_deinit(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_disconnect_backend(QC_PERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} \ No newline at end of file diff --git a/qcperf/test_app/src/test_qcperf_core.c b/qcperf/test_app/src/test_qcperf_core.c new file mode 100644 index 0000000..cc26afe --- /dev/null +++ b/qcperf/test_app/src/test_qcperf_core.c @@ -0,0 +1,87 @@ +/** + * @file test_qcperf_core.c + * @brief Unit tests for qcperf core functionality + */ + +#include "unity.h" +#include "qcperf.h" +#include "qcperf_backends.h" +#include "qcperf_backend_enum.h" + +void setUp(void) +{ + /* Called before each test */ +} + +void tearDown(void) +{ + /* Called after each test */ +} + +void test_qcperf_init_success(void) +{ + QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + /* Clean up */ + qcperf_deinit(); +} + +void test_qcperf_deinit_success(void) +{ + QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_connect_backend_dummy(void) +{ + QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QCPERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_disconnect_backend(QCPERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_disconnect_backend_dummy(void) +{ + QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QCPERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_disconnect_backend(QCPERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_get_backend_info(void) +{ + QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QCPERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + struct QcPerfBackendInfo backend_info = {0}; + ret = qcperf_get_capabilities_info(QCPERF_BACKEND_DUMMY, &backend_info); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + TEST_ASSERT_NOT_NULL(backend_info.name); + + ret = qcperf_disconnect_backend(QCPERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QCPERF_RETURN_CODE_SUCCESS, ret); +} \ No newline at end of file diff --git a/qcperf/test_app/src/test_qcperf_unit.c b/qcperf/test_app/src/test_qcperf_unit.c new file mode 100644 index 0000000..6bf53b9 --- /dev/null +++ b/qcperf/test_app/src/test_qcperf_unit.c @@ -0,0 +1,73 @@ +/** + * @file test_qcperf_unit.c + * @brief Unit tests for qcperf core functionality using Unity framework + */ + +#include "unity.h" +#include "qcperf.h" +#include "qcperf_backends.h" +#include "qcperf_backend_enum.h" + +void test_qcperf_init(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_deinit(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_acquire_handle(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_release_handle(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_disconnect_backend(QC_PERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} + +void test_qcperf_backend_selection(void) +{ + enum QcPerfReturnCode ret = qcperf_init(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_connect_backend(QC_PERF_BACKEND_DUMMY, NULL); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + struct QcPerfBackendInfo backend_info = {0}; + ret = qcperf_get_capabilities_info(QC_PERF_BACKEND_DUMMY, &backend_info); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_disconnect_backend(QC_PERF_BACKEND_DUMMY); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); + + ret = qcperf_deinit(); + TEST_ASSERT_EQUAL(QC_PERF_RETURN_CODE_SUCCESS, ret); +} \ No newline at end of file diff --git a/qcperf/test_app/src/test_runner.c b/qcperf/test_app/src/test_runner.c new file mode 100644 index 0000000..56b8079 --- /dev/null +++ b/qcperf/test_app/src/test_runner.c @@ -0,0 +1,28 @@ +/** + * @file test_runner.c + * @brief Main test runner for qcperf core tests + */ + +#include "unity.h" + +void test_qcperf_init(void); +void test_qcperf_deinit(void); +void test_qcperf_acquire_handle(void); +void test_qcperf_release_handle(void); +void test_qcperf_backend_selection(void); + +void setUp(void) { } +void tearDown(void) { } + +int main(int argc, char *argv[]) +{ + UNITY_BEGIN(); + + RUN_TEST(test_qcperf_init); + RUN_TEST(test_qcperf_deinit); + RUN_TEST(test_qcperf_acquire_handle); + RUN_TEST(test_qcperf_release_handle); + RUN_TEST(test_qcperf_backend_selection); + + return UNITY_END(); +} \ No newline at end of file diff --git a/qcperf/test_app/src/test_runner_backends.c b/qcperf/test_app/src/test_runner_backends.c new file mode 100644 index 0000000..31f7b5c --- /dev/null +++ b/qcperf/test_app/src/test_runner_backends.c @@ -0,0 +1,27 @@ +/** + * @file test_runner_backends.c + * @brief Test runner for qcperf backends tests + */ + +#include "unity.h" + +void test_dummy_backend_init(void); +void test_dummy_backend_info(void); +void test_dummy_backend_deinit(void); + +void setUp(void) { } +void tearDown(void) { } + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + UNITY_BEGIN(); + + RUN_TEST(test_dummy_backend_init); + RUN_TEST(test_dummy_backend_info); + RUN_TEST(test_dummy_backend_deinit); + + return UNITY_END(); +} \ No newline at end of file