blob: 64536ad71655f9dce7b984b2e488c83a2f867536 [file] [log] [blame]
{{#chip_tests tests useSynthesizeWaitForReport=true}}
class {{filename}}: public TestCommandBridge
{
public:
// NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
{{#if ../credsIssuerConfigArg}}
{{filename}}(CredentialIssuerCommands * credsIssuerConfig): TestCommand("{{filename}}", credsIssuerConfig), mTestIndex(0)
{{else}}
{{filename}}(): TestCommandBridge("{{filename}}"), mTestIndex(0)
{{/if}}
{
{{#chip_tests_config}}
{{#if (isString type)}}
AddArgument("{{name}}", &m{{asUpperCamelCase name}});
{{else}}
AddArgument("{{name}}", {{as_type_min_value type language='c++'}}, {{as_type_max_value type language='c++'}}, &m{{asUpperCamelCase name}});
{{/if}}
{{/chip_tests_config}}
}
// NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull)
~{{filename}}()
{
}
/////////// TestCommand Interface /////////
void NextTest() override
{
CHIP_ERROR err = CHIP_NO_ERROR;
if (0 == mTestIndex)
{
ChipLogProgress(chipTool, " **** Test Start: {{filename}}\n");
}
if (mTestCount == mTestIndex)
{
ChipLogProgress(chipTool, " **** Test Complete: {{filename}}\n");
SetCommandExitStatus(CHIP_NO_ERROR);
return;
}
Wait();
// Ensure we increment mTestIndex before we start running the relevant
// command. That way if we lose the timeslice after we send the message
// but before our function call returns, we won't end up with an
// incorrect mTestIndex value observed when we get the response.
switch (mTestIndex++)
{
{{#chip_tests_items}}
case {{index}}:
ChipLogProgress(chipTool, " ***** Test Step {{index}} : {{label}}\n");
{{#if PICS}}
if (ShouldSkip("{{PICS}}"))
{
NextTest();
return;
}
{{/if}}
err = Test{{asUpperCamelCase label}}_{{index}}();
break;
{{/chip_tests_items}}
}
if (CHIP_NO_ERROR != err)
{
ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err));
SetCommandExitStatus(err);
}
}
void OnStatusUpdate(const chip::app::StatusIB & status) override
{
switch (mTestIndex - 1)
{
{{#chip_tests_items}}
case {{index}}:
{{! No support for expectMultipleResponses yet }}
{{#chip_tests_item_responses}}
VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), {{error}}));
{{#if error}}
{{#if clusterError}}
VerifyOrReturn(CheckValue("clusterStatus present", status.mClusterStatus.HasValue(), true));
VerifyOrReturn(CheckValue("clusterStatus value", status.mClusterStatus.Value(), {{clusterError}}));
{{/if}}
{{/if}}
{{/chip_tests_item_responses}}
break;
{{/chip_tests_items}}
}
// Go on to the next test.
ContinueOnChipMainThread(CHIP_NO_ERROR);
}
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(mTimeout.ValueOr({{chip_tests_config_get_default_value "timeout"}})); }
private:
std::atomic_uint16_t mTestIndex;
const uint16_t mTestCount = {{totalTests}};
{{#chip_tests_config}}
chip::Optional<{{chipType}}> m{{asUpperCamelCase name}};
{{/chip_tests_config}}
{{#chip_tests_items}}
{{#if async}}
bool testSendCluster{{parent.filename}}_{{index}}_{{asUpperCamelCase command}}_Fulfilled = false;
{{/if}}
{{#chip_tests_item_responses}}
{{#chip_tests_item_response_parameters}}
{{#if saveAs}}
{{asObjectiveCType type ../cluster}} {{saveAs}};
{{/if}}
{{/chip_tests_item_response_parameters}}
{{/chip_tests_item_responses}}
{{~#*inline "subscribeDataCallback"}}
test_{{parent.filename}}_{{attribute}}_Reported
{{/inline}}
{{#if allocateSubscribeDataCallback}}
ResponseHandler _Nullable {{> subscribeDataCallback}} = nil;
{{/if~}}
{{#*inline "testCommand"}}Test{{asUpperCamelCase label}}_{{index}}{{/inline}}
CHIP_ERROR {{>testCommand}}()
{
{{#*inline "cluster"}}{{asUpperCamelCase cluster preserveAcronyms=true}}{{/inline}}
{{#*inline "attribute"}}{{asUpperCamelCase attribute preserveAcronyms=true}}{{/inline}}
{{#if (isTestOnlyCluster cluster)}}
{{asEncodableType}} value;
{{#chip_tests_item_parameters}}
{{>commandValue ns=parent.cluster container=(asPropertyValue dontUnwrapValue=true) definedValue=definedValue depth=0}}
{{/chip_tests_item_parameters}}
return {{command}}("{{identity}}", value);
{{else}}
MTRBaseDevice * device = GetDevice("{{identity}}");
__auto_type * cluster = [[MTRBaseCluster{{>cluster}} alloc] initWithDevice:device endpointID:@({{endpoint}}) queue:mCallbackQueue];
VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
{{#if isCommand}}
{{#if commandObject.arguments.length}}
__auto_type * params = [[MTR{{>cluster}}Cluster{{asUpperCamelCase command preserveAcronyms=true}}Params alloc] init];
{{/if}}
{{#chip_tests_item_parameters}}
{{>test_value target=(concat "params." (asStructPropertyName label)) definedValue=definedValue cluster=parent.cluster depth=0}}
{{/chip_tests_item_parameters}}
[cluster {{asLowerCamelCase command}}With{{#if commandObject.arguments.length}}Params:params completion{{else}}Completion{{/if}}:
{{#if commandObject.hasSpecificResponse}}
^(MTR{{>cluster}}Cluster{{asUpperCamelCase commandObject.responseName}}Params * _Nullable values, NSError * _Nullable err) {
{{else}}
^(NSError * _Nullable err) {
{{/if}}
{{else if isSubscribeAttribute}}
{{#chip_tests_item_parameters}}
{{asObjectiveCBasicType type}} {{asLowerCamelCase name}}Argument = {{asTypedLiteral definedValue type}};
{{/chip_tests_item_parameters}}
__auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(minIntervalArgument) maxInterval:@(maxIntervalArgument)];
params.filterByFabric = {{#if fabricFiltered}}true{{else}}false{{/if}};
params.replaceExistingSubscriptions = {{#if keepSubscriptions}}false{{else}}true{{/if}};
[cluster subscribeAttribute{{>attribute}}WithParams:params
subscriptionEstablished:^{
VerifyOrReturn(testSendCluster{{parent.filename}}_{{waitForReport.index}}_{{asUpperCamelCase waitForReport.command}}_Fulfilled, SetCommandExitStatus(CHIP_ERROR_INCORRECT_STATE));
NextTest();
}
reportHandler:^({{asObjectiveCClass attributeObject.type cluster forceList=attributeObject.isArray}} * _Nullable value, NSError * _Nullable err) {
{{else if isWaitForReport}}
{{> subscribeDataCallback }} = ^({{asObjectiveCClass attributeObject.type cluster forceList=attributeObject.isArray}} * _Nullable value, NSError * _Nullable err) {
{{else if isReadAttribute}}
{{#if_is_fabric_scoped_struct attributeObject.type}}
__auto_type * params = [[MTRReadParams alloc] init];
params.filterByFabric = {{fabricFiltered}};
{{/if_is_fabric_scoped_struct}}
[cluster readAttribute{{>attribute}}With
{{~#if_is_fabric_scoped_struct attributeObject.type~}}
Params:params completion:
{{~else~}}
Completion:
{{~/if_is_fabric_scoped_struct~}}
^({{asObjectiveCClass attributeObject.type cluster forceList=attributeObject.isArray}} * _Nullable value, NSError * _Nullable err) {
{{else if isWriteAttribute}}
{{#chip_tests_item_parameters}}
id {{asLowerCamelCase name}}Argument;
{{>test_value target=(concat (asLowerCamelCase name) "Argument") definedValue=definedValue cluster=parent.cluster depth=0}}
{{/chip_tests_item_parameters}}
[cluster writeAttribute{{>attribute}}WithValue:{{#chip_tests_item_parameters}}{{asLowerCamelCase name}}Argument{{/chip_tests_item_parameters}} completion:^(NSError * _Nullable err) {
{{/if}}
NSLog(@"{{label}} Error: %@", err);
{{#if optional}}
if (err.code == MTRInteractionErrorCodeUnsupportedAttribute) {
NextTest();
return;
}
{{/if}}
{{#chip_tests_item_responses}}
{{#if error}}
VerifyOrReturn(CheckValue("status", err ? ([err.domain isEqualToString:MTRInteractionErrorDomain] ? err.code : EMBER_ZCL_STATUS_FAILURE) : 0, {{error}}));
NextTest();
{{else}}
VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
{{#unless isSubscribeAttribute}}
{{#chip_tests_item_response_parameters}}
{{#*inline "actualValue"}}value{{#unless parent.isAttribute}}s.{{asStructPropertyName name}}{{/unless}}{{/inline}}
{{#if hasExpectedValue}}
{
id actualValue = {{> actualValue}};
{{>check_test_value actual="actualValue" expected=expectedValue cluster=../cluster}}
}
{{/if}}
{{>maybeCheckExpectedConstraints}}
{{#if saveAs}}
{
{{saveAs}} = {{>actualValue}};
}
{{/if}}
{{/chip_tests_item_response_parameters}}
{{#unless async}}
NextTest();
{{else}}
testSendCluster{{parent.filename}}_{{../index}}_{{asUpperCamelCase command}}_Fulfilled = true;
{{/unless}}
{{else}}
{{! We're a subscription }}
if ({{> subscribeDataCallback}} != nil) {
ResponseHandler callback = {{> subscribeDataCallback}};
{{> subscribeDataCallback}} = nil;
callback(value, err);
}
{{/unless}}
{{/if}}
{{/chip_tests_item_responses}}
}{{#unless isWaitForReport}}]{{/unless}};
{{#if async}}
NextTest();
{{/if}}
return CHIP_NO_ERROR;
{{/if}}
}
{{/chip_tests_items}}
};
{{/chip_tests}}