Skip to content
Open
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
899 changes: 899 additions & 0 deletions .github/workflows/sample_unit_test copy.yaml

Large diffs are not rendered by default.

109 changes: 63 additions & 46 deletions .github/workflows/sample_unit_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,49 @@ jobs:
echo "files-with-tests=0" >> $GITHUB_OUTPUT
echo "test-files=" >> $GITHUB_OUTPUT
fi
- name: "Validate Existing GTest Unit Tests"
if: steps.mapping.outputs.has-mappings == 'true'
env:
LITELLM_TOKEN: ${{ secrets.LITELLM_TOKEN }}
TEST_FILES: ${{ steps.mapping.outputs.test-files }}
run: |
set -euo pipefail
echo "=== Validating Existing GTest Unit Tests ==="

# ------------------------------------------------------------
# AI-powered validation is intentionally kept commented out.
# Ensure validate_tests.py and ValidationTemplate.md are present
# at the repo root before enabling.
#
# - name: "Run Unit Test Validator with AI"
# if: steps.mapping.outputs.test-files != ''
# env:
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# run: |
# set -euo pipefail
# echo "=== Running AI-Powered Unit Test Validation ==="
# echo "${{ steps.mapping.outputs.test-files }}" | tr ',' '\n' > test_files_list.txt
# python validate_tests.py --test-files test_files_list.txt --output validation_report.md
# echo "=== VALIDATION COMPLETE ==="
# echo "=== VALIDATION SUMMARY ==="
# awk '/^## Summary/{flag=1;print;next}/^$/{if(flag){exit}}flag' validation_report.md || true
# ------------------------------------------------------------
if [ -z "$TEST_FILES" ]; then
echo "No test files to validate"
exit 0
fi

# Convert comma-separated test files to array
IFS=',' read -ra test_files <<< "$TEST_FILES"

# Initialize validation results file
echo "=== Unit Test Validation Results ===" > validation_results.txt
echo "" >> validation_results.txt

# Validate each test file
for test_file in "${test_files[@]}"; do
[ -z "$test_file" ] && continue

echo "Validating: $test_file"

# Run validation and capture result
if python3 internal/silabs/ai_unit_test/validate_with_litellm.py "$test_file" >> validation_results.txt 2>&1; then
echo "✅ Validation completed for: $test_file"
else
echo "⚠️ Validation had issues for: $test_file"
fi

echo "" >> validation_results.txt
echo "---" >> validation_results.txt
echo "" >> validation_results.txt
done

# Display all validation results
echo ""
echo "=== COMPLETE VALIDATION RESULTS ==="
cat validation_results.txt

code-coverage-analysis:
name: "Code Coverage Analysis"
Expand Down Expand Up @@ -379,34 +403,27 @@ jobs:
test_name=$(basename "$tf")
exe_name="${test_name%.*}"

# Smart source file detection based on test file name and includes
# Generic source file detection based on includes in the test file
srcs=""

# Method 1: If test file is TestCalculator.cpp, look for calculator.c
if [[ "$test_name" == "TestCalculator.cpp" ]]; then
if [ -f "../calculator.c" ]; then
srcs="../calculator.c"
echo "Found specific source for $test_name: $srcs"
echo "Looking for includes in $tf..."
includes=$(grep -oE '#include *["<][^">]+\.h' "../$tf" | sed 's/#include *["<]//' | sed 's/"//' || true)
echo "Found includes: $includes"
for inc in $includes; do
[ -z "$inc" ] && continue
base=$(basename "$inc" .h)
echo "Looking for ${base}.c or ${base}.cpp..."
# Look for corresponding .c or .cpp file
c_file=$(find .. -name "${base}.c" -type f | head -n1 || true)
cpp_file=$(find .. -name "${base}.cpp" -type f | head -n1 || true)

if [ -n "$c_file" ] && [ -f "$c_file" ]; then
srcs="$srcs $c_file"
echo "Found C source: $c_file"
elif [ -n "$cpp_file" ] && [ -f "$cpp_file" ]; then
srcs="$srcs $cpp_file"
echo "Found C++ source: $cpp_file"
fi
fi

# Method 2: Generic approach - look for includes in the test file
if [ -z "$srcs" ]; then
echo "Looking for includes in $tf..."
includes=$(grep -oE '#include *["<][^">]+\.h' "../$tf" | sed 's/#include *["<]//' | sed 's/"//' || true)
echo "Found includes: $includes"
for inc in $includes; do
[ -z "$inc" ] && continue
base=$(basename "$inc" .h)
echo "Looking for ${base}.c..."
# Look for corresponding .c file
c_file=$(find .. -name "${base}.c" -type f | head -n1 || true)
if [ -n "$c_file" ] && [ -f "$c_file" ]; then
srcs="$srcs $c_file"
echo "Found source: $c_file"
fi
done
fi
done

echo "Source files to link: $srcs"

Expand Down Expand Up @@ -542,7 +559,7 @@ jobs:
const filesWithTests = '${{ needs.find-and-validate-tests.outputs.files-with-tests }}';

const coverageStatus = parseFloat(actualCoverage) >= parseFloat(requiredCoverage) ? '✅' : '❌';
const coverageEmoji = parseFloat(actualCoverage) >= parseFloat(requiredCoverage) ? '🎯' : '⚠️';
// const coverageEmoji = parseFloat(actualCoverage) >= parseFloat(requiredCoverage) ? '🎯' : '⚠️';

const changedFilesList = cppFiles ? cppFiles.split(',').map(f => `- \`${f.trim()}\``).join('\n') : '- None';
const testFilesList = testFiles ? testFiles.split(',').map(f => `- \`${f.trim()}\``).join('\n') : '- None found';
Expand All @@ -552,7 +569,7 @@ jobs:
const finalMessage = parseFloat(actualCoverage) >= parseFloat(requiredCoverage) ? passedMessage : failedMessage;

const commentBody = [
`## ${coverageEmoji} Code Coverage Report`,
`## Code Coverage Report`,
'',
'### Coverage Summary',
`- **Required Coverage**: ${requiredCoverage}%`,
Expand Down
15 changes: 15 additions & 0 deletions ClosureManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "ClosureManager.h"

void ClosureManager::open() {
open_state = true;
std::cout << "Opening closure" << std::endl;
}

void ClosureManager::close() {
open_state = false;
std::cout << "Closing closure" << std::endl;
}

bool ClosureManager::isOpen() const {
return open_state;
}
16 changes: 16 additions & 0 deletions ClosureManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef CLOSURE_MANAGER_H
#define CLOSURE_MANAGER_H

#include <iostream>

class ClosureManager {
public:
void open();
void close();
bool isOpen() const;

private:
bool open_state = false;
};

#endif // CLOSURE_MANAGER_H
7 changes: 7 additions & 0 deletions calculator.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ int is_even(int n) {
int max(int a, int b) {
return (a > b) ? a : b;
}

/**
* @brief Find minimum of two integers
*/
int min(int a, int b) {
return (a < b) ? a : b;
}
8 changes: 8 additions & 0 deletions calculator.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ int is_even(int n);
*/
int max(int a, int b);

/**
* @brief Find minimum of two integers
* @param a First integer
* @param b Second integer
* @return Minimum of a and b
*/
int min(int a, int b);

#ifdef __cplusplus
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@
```cpp
// filepath: src/app/tests/Test{YourComponent}.cpp

#include <lib/core/StringBuilderAdapters.h>
#include <pw_unit_test/framework.h>
#include <app/data-model/Nullable.h>
// #include <lib/core/StringBuilderAdapters.h>
// #include <pw_unit_test/framework.h>
// #include <app/data-model/Nullable.h>

// Include your component's header file
#include <app/clusters/{your-cluster}/{your-component}.h>
// #include <app/clusters/{your-cluster}/{your-component}.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::DataModel;
using namespace chip::app::Clusters::{YourCluster};
#include <gtest/gtest.h>
#include "../../../<YourComponent>.h"

// using namespace chip;
// using namespace chip::app;
// using namespace chip::app::DataModel;
// using namespace chip::app::Clusters::{YourCluster};

// Note: These are sample tests for the {YourComponent} component. Only add them if they are relevant to your implementation.
// Test Suite: {YourComponent}Validation
TEST({YourComponent}Validation, InitialStateIsCorrect)
{
Expand Down Expand Up @@ -102,22 +106,24 @@ TEST({YourComponent}Validation, ErrorHandlingIsRobust)

#### 1. **Standard Headers**
```cpp
#include <lib/core/StringBuilderAdapters.h>
#include <pw_unit_test/framework.h>
#include <app/data-model/Nullable.h>
// #include <lib/core/StringBuilderAdapters.h>
// #include <pw_unit_test/framework.h>
// #include <app/data-model/Nullable.h>
#include <gtest/gtest.h>
#include "../../../ClosureManager.h"
```
- Essential Matter framework headers for testing
<!-- - Essential Matter framework headers for testing
- `pw_unit_test` provides the testing framework
- `StringBuilderAdapters` for string handling utilities
- `StringBuilderAdapters` for string handling utilities -->

#### 2. **Namespace Usage**
<!-- #### 2. **Namespace Usage**
```cpp
using namespace chip;
using namespace chip::app;
using namespace chip::app::DataModel;
```
- Simplifies code by avoiding repetitive namespace prefixes
- Standard pattern across Matter codebase
- Standard pattern across Matter codebase -->

#### 3. **Test Structure Pattern**
```cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ You are a basic code validator for Matter unit tests. Your task is to check only

### 1. **Component Header Inclusion**
- [ ] Check if the component's .cpp file is included
- Look for `#include` statements that reference the .cpp file being tested
- Look for `#include` statements that reference the .cpp or .h file being tested
- Example: `#include "../../../ClosureManager.cpp"` or `#include <app/clusters/door-lock/DoorLockManager.cpp>`
- Note: .h file inclusion is optional, .cpp file inclusion is required

### 2. **Test Function Naming**
- [ ] Verify all test functions start with "TEST"
Expand Down Expand Up @@ -40,10 +39,10 @@ When evaluating a unit test file, provide feedback in this simple format:
### ❌ Failed Checks
- [List what failed]

### 📋 Simple Recommendations
### Simple Recommendations
- [Brief suggestions to fix issues]

### 🎯 Status: [PASS/FAIL]
### Status: [PASS/FAIL]
```

## Examples
Expand Down
Loading