| name | capi-test-fixer |
| description | This skill should be used when the user asks to "C API test failures", "C API unit test issues", "modifier tests failing", "undefined symbol in C API tests", "ARKUI_CAPI_UNITTEST compilation errors", "Converter API issues in tests", "test build configuration problems", "fix C API interface test failures", "capi test fix", "modifier test fix", or mentions fixing C API unit test failures in OpenHarmony ACE Engine. Automatically diagnoses and fixes common C API unit test failures including missing static modifiers, incorrect Converter API usage, and test build configuration issues. |
| version | 1.0.0 |
C API Test Fixer Skill
This skill automatically diagnoses and fixes common C API unit test failures in OpenHarmony ACE Engine. It handles patterns like missing static modifiers in test builds, incorrect Converter API usage, and test build configuration issues.
When to Use This Skill
Use this skill when encountering C API unit test failures, particularly:
- Linker errors:
undefined symbol: OHOS::Ace::NG::GeneratedModifier::Get*StaticModifier()
- Test failures:
modifier_test_base.h:210: Expected: (modifier_) != (nullptr)
- Compilation warnings about pointer/reference mismatches
- Build failures with "undefined reference" for static modifier functions
- Test build configuration issues with missing files
Common Failure Patterns
Pattern 1: Missing Static Modifier in Test Builds
Symptoms:
- Linker error:
undefined symbol: OHOS::Ace::NG::GeneratedModifier::Get*StaticModifier()
- Test failure:
modifier_test_base.h:210: Expected: (modifier_) != (nullptr)
Root Cause: Modifier function uses DynamicModuleHelper which returns nullptr in tests.
Fix Pattern:
- Add ARKUI_CAPI_UNITTEST conditional compilation to modifier.cpp
- Include static modifier implementation in test BUILD.gn
Pattern 2: Incorrect Converter API Usage
Symptoms:
- Test failure comparing
nullopt vs nullptr
- Compilation warnings about pointer/reference mismatches
Root Cause: Using Converter::GetOptPtr(&local_var) instead of Converter::GetOpt(local_var)
Fix Pattern: Replace GetOptPtr(&var) with GetOpt(var) for local variables.
Pattern 3: Test Build Configuration Missing Files
Symptoms:
- Build fails with "undefined reference" for static modifier functions
- File not included in test build sources
Root Cause: Static modifier .cpp file not listed in test BUILD.gn sources
Fix Pattern: Add missing .cpp file to test BUILD.gn sources list.
Pattern 4: Callback Invoke vs InvokeSync Mismatch
Symptoms:
- Test callback values remain at initial value (e.g.,
g_indexValue = 0)
- Event callbacks silently don't fire
- Test error:
Expected: g_indexValue == INDEX, Actual: 0 vs 10
Root Cause: Implementation uses CallbackHelper::InvokeSync() but test callbacks
are created with Converter::ArkCallback<T>(lambda) where the lambda matches the call
signature (Ark_Int32 nodeId, ...args). InvokeSync uses callSync field which is
nullptr, so the callback silently does nothing.
The two ArkCallback overloads in reverse_converter.h select based on function signature:
call type: void (*)(Ark_Int32 resourceId, ...args) → sets .call, .callSync = nullptr
callSync type: void (*)(Ark_VMContext vmContext, Ark_Int32 resourceId, ...args) → sets .callSync, .call = nullptr
Fix Pattern: Add Ark_VMContext vmContext as the first parameter in test callback lambdas.
auto callback = [](Ark_Int32 nodeId, const Ark_Int32 index) {
g_indexValue = Converter::Convert<int32_t>(index);
};
auto callback = [](Ark_VMContext vmContext, Ark_Int32 nodeId, const Ark_Int32 index) {
g_indexValue = Converter::Convert<int32_t>(index);
};
Common affected tests: Any event callback test (onChange, onSelected, onWillShow, etc.)
where the implementation was changed from Invoke() to InvokeSync().
Pattern 5: Ark_String Dangling Pointer in Getters
Symptoms:
- Getter returns garbage/corrupted data (e.g.,
"\0x\x1D" instead of "xor")
- Use-after-free in string return values
- Only affects getters that return
Ark_String
Root Cause: Peer getter returns std::string by value. Converter::ArkValue<Ark_String>()
stores chars pointer to the temporary's data. When the temporary is destroyed, the pointer
dangles.
In reverse_converter.h, AssignArkValue(Ark_String& dst, const std::string_view& src, ConvContext *ctx):
- When
ctx != nullptr: copies data into persistent storage via ctx->Store(src)
- When
ctx == nullptr (default): stores raw pointer dst.chars = src.data() — dangles if source is temporary
Fix Pattern: Change peer getter to return const std::string& instead of std::string
(since it returns a member variable), so the Ark_String points to stable memory.
std::string GetGlobalCompositeOperation() const {
return globalCompositeOperation_;
}
const std::string& GetGlobalCompositeOperation() const {
return globalCompositeOperation_;
}
Alternative fix: Use Converter::FC (frame context) to store the string data persistently:
auto result = peerImpl->GetGlobalCompositeOperation();
return Converter::ArkValue<Ark_String>(result, Converter::FC);
Skill Implementation
The skill performs automated diagnosis through:
1. Error Analysis
- Parse build logs (
out/rk3568/build.log)
- Extract linker errors and undefined symbols
- Analyze test failure messages
2. Pattern Matching
PATTERNS = {
"static_modifier_missing": r"undefined symbol.*Get(\w+)StaticModifier",
"converter_api_misuse": r"GetOptPtr\(&",
"nullptr_modifier": r"modifier_test_base\.h.*modifier_.*!=.*nullptr",
}
3. Fix Generation
Based on detected patterns:
-
Static modifier missing:
- Check if modifier.cpp has ARKUI_CAPI_UNITTEST conditional
- Verify test BUILD.gn includes static_modifier.cpp
- Generate appropriate patches
-
Converter API misuse:
- Locate offending test file
- Suggest GetOptPtr → GetOpt replacement
-
Build configuration:
- Check test BUILD.gn source lists
- Add missing static modifier files
Usage Examples
Diagnose and Fix All Issues
claude-code skill capi-test-fixer --diagnose
Fix Specific Test Failure
claude-code skill capi-test-fixer --test SymbolGlyphModifierTest
Analyze Build Log
claude-code skill capi-test-fixer --build-log out/rk3568/build.log
Integration with Existing Skills
This skill complements:
- openharmony-build: Uses build logs for diagnosis
- build-error-analyzer: Focuses specifically on C API test patterns
- tdd: Provides test-specific fixes
File Structure
.claude/skills/capi-test-fixer/
├── SKILL.md # This file
├── README.md # Detailed documentation
├── skill.json # Skill configuration
├── test_skill.py # Test script
├── scripts/
│ ├── diagnose.py # Main diagnosis script
│ ├── fix_static_modifier.py
│ ├── fix_converter_api.py
│ └── fix_build_config.py
├── templates/
│ ├── static_modifier.patch
│ └── converter_fix.patch
└── patterns/
└── error_patterns.json # Error pattern definitions
Error Resolution Workflow
- Collect Data: Build logs, test outputs, source files
- Pattern Match: Identify failure category using error_patterns.json
- Root Cause Analysis: Determine exact issue location
- Fix Generation: Create appropriate patches using templates
- Validation: Verify fixes work by checking test compilation
Common Fix Templates
Static Modifier Fix
const GENERATED_ArkUI*Modifier* Get*Modifier()
{
auto* module = DynamicModuleHelper::GetInstance().GetDynamicModule("*");
return reinterpret_cast<const GENERATED_ArkUI*Modifier*>(module->GetStaticModifier());
}
#ifdef ARKUI_CAPI_UNITTEST
const GENERATED_ArkUI*Modifier* Get*StaticModifier();
#endif
const GENERATED_ArkUI*Modifier* Get*Modifier()
{
static const GENERATED_ArkUI*Modifier* cachedModifier = nullptr;
if (cachedModifier == nullptr) {
#ifdef ARKUI_CAPI_UNITTEST
cachedModifier = GeneratedModifier::Get*StaticModifier();
#else
auto* module = DynamicModuleHelper::GetInstance().GetDynamicModule("*");
CHECK_NULL_RETURN(module, nullptr);
cachedModifier = reinterpret_cast<const GENERATED_ArkUI*Modifier*>(module->GetStaticModifier());
#endif
}
return cachedModifier;
}
Converter API Fix
auto optValue = Converter::GetOptPtr(&ptr);
auto optValue = Converter::GetOpt(ptr);
BUILD.gn Fix
# Add to test/unittest/capi/BUILD.gn sources
sources += [
"$ace_root/frameworks/core/components_ng/pattern/*/bridge/*_static_modifier.cpp",
]
Callback InvokeSync Fix
auto callback = [](Ark_Int32 nodeId, const Ark_Int32 index) { ... };
auto callback = [](Ark_VMContext vmContext, Ark_Int32 nodeId, const Ark_Int32 index) { ... };
auto cb = [](const Ark_Int32 resourceId) { ... };
auto cb = [](Ark_VMContext vmContext, const Ark_Int32 resourceId) { ... };
Ark_String Lifetime Fix
std::string GetValue() const { return member_; }
const std::string& GetValue() const { return member_; }
Best Practices
- Always check existing patterns: Radio modifier already implements ARKUI_CAPI_UNITTEST pattern
- Verify test builds: Ensure
ARKUI_CAPI_UNITTEST is defined in test config
- Use proper Converter API:
GetOpt for values, GetOptPtr for pointers
- Maintain consistency: Follow established patterns in codebase
- Test after fixes: Always rebuild and run tests to verify fixes work
Supported Patterns
The skill supports the following error patterns (defined in patterns/error_patterns.json):
- static_modifier_missing: Detects undefined symbol errors for static modifiers
- converter_api_misuse: Detects incorrect
GetOptPtr(&var) usage
- nullptr_modifier_in_tests: Detects modifier returning nullptr in tests
- test_build_config_missing_files: Detects missing files in BUILD.gn
- arkui_capi_unittest_compilation_error: Detects ARKUI_CAPI_UNITTEST compilation errors
- dynamic_module_helper_nullptr: Detects DynamicModuleHelper returning nullptr
- callback_invoke_vs_invoke_sync: Detects test callbacks using
call signature when implementation uses InvokeSync (requires callSync signature)
- ark_string_dangling_pointer: Detects Ark_String getters returning dangling pointers from temporary std::string
Limitations
- Cannot fix complex test logic errors
- Requires clear error patterns
- May need manual review for edge cases
- Focuses on C API unit test failures only (not other test types)
Contributing
Add new patterns to patterns/error_patterns.json:
{
"pattern_name": {
"regex": "error pattern",
"category": "static_modifier|converter_api|build_config",
"fix_template": "template_name",
"severity": "high|medium|low"
}
}
Update fix templates in the templates/ directory as needed for new patterns.