blob: 46a869fdfea6fc614fa32fa016ccff2fadda78be [file] [log] [blame]
{{#chip_tests tests}}
class {{filename}}: public TestCommand
{
public:
{{filename}}(): TestCommand("{{filename}}"), mTestIndex(0) {}
/////////// 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");
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);
}
}
private:
std::atomic_uint16_t mTestIndex;
const uint16_t mTestCount = {{totalTests}};
{{#*inline "failureCallback"}}mOnFailureCallback_{{index}}{{/inline}}
{{#*inline "successCallback"}}mOnSuccessCallback_{{index}}{{/inline}}
{{#*inline "failureResponse"}}OnFailureCallback_{{index}}{{/inline}}
{{#*inline "successResponse"}}OnSuccessCallback_{{index}}{{/inline}}
{{#*inline "successArguments"}}void * context{{#chip_tests_item_response_parameters}}, {{zapTypeToDecodableClusterObjectType type ns=parent.cluster isArgument=true}} {{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}}{{/inline}}
{{#*inline "failureArguments"}}void * context, uint8_t status{{/inline}}
{{#chip_tests_items}}
{{#unless (isTestOnlyCluster cluster)}}
{{#unless isWait}}
{{#unless isCommand}}
{{#unless isWriteAttribute}}
chip::Callback::Callback<void (*) ({{>failureArguments}})> {{>failureCallback}} { {{>failureResponse}}, this };
chip::Callback::Callback<void (*) ({{>successArguments}})> {{>successCallback}} { {{>successResponse}}, this };
{{/unless}}
{{/unless}}
{{/unless}}
{{/unless}}
{{/chip_tests_items}}
{{#chip_tests_items}}
{{#unless (isTestOnlyCluster cluster)}}
{{#unless isWait}}
{{#unless isCommand}}
{{#if isWriteAttribute}}
static void {{>failureResponse}}(void * context, EmberAfStatus status)
{
(static_cast<{{filename}} *>(context))->OnFailureResponse_{{index}}(chip::to_underlying(status));
}
{{else}}
static void {{>failureResponse}}({{> failureArguments}})
{
(static_cast<{{filename}} *>(context))->OnFailureResponse_{{index}}(status);
}
{{/if}}
static void {{>successResponse}}({{> successArguments}})
{
(static_cast<{{filename}} *>(context))->OnSuccessResponse_{{index}}({{#chip_tests_item_response_parameters}}{{#not_first}}, {{/not_first}}{{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}});
}
{{! "isWaitForReport" can be replaced by "async" if there is a mechanism to remove the report handler}}
{{#if isWaitForReport}}
bool mReceivedReport_{{index}} = false;
{{/if}}
{{/unless}}
{{/unless}}
{{/unless}}
{{/chip_tests_items}}
//
// Tests methods
//
{{#chip_tests_items}}
{{#*inline "testCommand"}}Test{{asUpperCamelCase label}}_{{index}}{{/inline}}
{{#if (isTestOnlyCluster cluster)}}
CHIP_ERROR {{>testCommand}}()
{
return {{command}}({{#chip_tests_item_parameters}}{{#not_first}}, {{/not_first}}{{#if (isString type)}}"{{/if}}{{definedValue}}{{#if (isString type)}}"{{/if}}{{/chip_tests_item_parameters}});
}
{{else if isWait}}
CHIP_ERROR {{>testCommand}}()
{
ChipLogError(chipTool, "[Endpoint: {{endpoint}} Cluster: {{cluster}} {{#if isAttribute}}Attribute: {{attribute}}{{else}}Command: {{wait}}{{/if}}] {{label}}");
{{#*inline "waitForTypeName"}}{{#if isAttribute}}Attribute{{else}}Command{{/if}}{{/inline}}
{{#*inline "waitForTypeId"}}chip::app::Clusters::{{asUpperCamelCase cluster}}::{{#if isAttribute}}Attributes::{{attribute}}{{else}}Commands::{{wait}}{{/if}}::Id{{/inline}}
ClearAttributeAndCommandPaths();
m{{>waitForTypeName}}Path = chip::app::Concrete{{>waitForTypeName}}Path({{endpoint}}, chip::app::Clusters::{{asUpperCamelCase cluster}}::Id, {{>waitForTypeId}});
return CHIP_NO_ERROR;
}
{{else}}
{{#*inline "failureResponse"}}OnFailureResponse_{{index}}{{/inline}}
{{#*inline "successResponse"}}OnSuccessResponse_{{index}}{{/inline}}
{{#*inline "failureArguments"}}uint8_t status{{/inline}}
{{#*inline "successArguments"}}{{#chip_tests_item_response_parameters}}{{#not_first}}, {{/not_first}}{{zapTypeToDecodableClusterObjectType type ns=parent.cluster isArgument=true}} {{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}}{{/inline}}
CHIP_ERROR {{>testCommand}}()
{
chip::Controller::{{asUpperCamelCase cluster}}ClusterTest cluster;
cluster.Associate(mDevice, {{endpoint}});
{{#if isCommand}}
using requestType = chip::app::Clusters::{{asUpperCamelCase cluster}}::Commands::{{asUpperCamelCase command}}::Type;
using responseType = chip::app::{{chip_tests_item_response_type}};
chip::app::Clusters::{{asUpperCamelCase cluster}}::Commands::{{asUpperCamelCase command}}::Type request;
{{#chip_tests_item_parameters}}
{{>commandValue ns=parent.cluster container=(concat "request." (asLowerCamelCase label)) definedValue=definedValue}}
{{/chip_tests_item_parameters}}
auto success = [](void * context, const responseType & data) {
(static_cast<{{filename}} *>(context))->OnSuccessResponse_{{index}}({{#chip_tests_item_response_parameters}}{{#not_first}}, {{/not_first}}data.{{asLowerCamelCase name}}{{/chip_tests_item_response_parameters}});
};
auto failure = [](void * context, EmberAfStatus status) {
(static_cast<{{filename}} *>(context))->OnFailureResponse_{{index}}(status);
};
{{#if async}}ReturnErrorOnFailure({{else}}return {{/if}}cluster.InvokeCommand<requestType, responseType>(request, this, success, failure){{#if async}}){{/if}};
{{else}}
{{#chip_tests_item_parameters}}
{{zapTypeToEncodableClusterObjectType type ns=parent.cluster}} {{asLowerCamelCase name}}Argument;
{{>commandValue ns=parent.cluster container=(concat (asLowerCamelCase name) "Argument") definedValue=definedValue}}
{{/chip_tests_item_parameters}}
{{#if isWriteAttribute}}
{{#*inline "failureResponse"}}OnFailureCallback_{{index}}{{/inline}}
{{#*inline "successResponse"}}OnSuccessCallback_{{index}}{{/inline}}
{{#if async}}ReturnErrorOnFailure({{else}}return {{/if}}cluster.WriteAttribute<chip::app::Clusters::{{asUpperCamelCase cluster}}::Attributes::{{asUpperCamelCase attribute}}::TypeInfo>({{#chip_tests_item_parameters}}{{asLowerCamelCase name}}Argument, {{/chip_tests_item_parameters}}this, {{>successResponse}}, {{>failureResponse}}){{#if async}}){{/if}};
{{else}}
{{~#*inline "commandName"}}{{asUpperCamelCase commandName}}{{#if isAttribute}}Attribute{{asUpperCamelCase attribute}}{{/if}}{{/inline}}
{{#if async}}ReturnErrorOnFailure({{else}}return {{/if}}cluster.{{>commandName}}({{>successCallback}}.Cancel(){{#unless isWaitForReport}}, {{>failureCallback}}.Cancel(){{/unless}}{{#chip_tests_item_parameters}}, {{asLowerCamelCase name}}Argument{{/chip_tests_item_parameters}}){{#if async}}){{/if}};
{{/if}}
{{/if}}
{{#if async}}return WaitForMs(0);{{/if}}
}
void {{>failureResponse}}({{>failureArguments}})
{
{{~#unless response.error}}
{{#if optional}}(status == EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE) ? NextTest() : {{/if}}ThrowFailureResponse();
{{else}}
{{#unless async}}NextTest();{{/unless}}
{{/unless}}
}
void {{>successResponse}}({{>successArguments}})
{
{{~#if response.error}}
ThrowSuccessResponse();
{{else}}
{{! This block can be removed if there is a mechanism to remove the report handler}}
{{#if isWaitForReport}}
VerifyOrReturn(mReceivedReport_{{index}} == false, ChipLogError(chipTool, "Not Fatal: on report called more than once."));
mReceivedReport_{{index}} = true;
{{/if}}
{{#if hasWaitForReport}}
VerifyOrReturn(mReceivedReport_{{waitForReport.index}}, Exit("Initial report not received!"));
{{/if}}
{{#chip_tests_item_response_parameters}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{#if isOptional}}.Value(){{/if}}{{/inline}}
{{~#*inline "itemValue"}}{{>item}}{{#if isNullable}}.Value(){{/if}}{{/inline}}
{{#if hasExpectedValue}}
{{#if isOptional}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}}
VerifyOrReturn(CheckValuePresent("{{> item}}", {{> item}}));
{{/if}}
{{#if (isLiteralNull expectedValue)}}
VerifyOrReturn(CheckValueNull("{{> item}}", {{> item}}));
{{else}}
{{#if isNullable}}
VerifyOrReturn(CheckValueNonNull("{{> item}}", {{> item}}));
{{/if}}
VerifyOrReturn(CheckValue
{{~#if isList}}AsListLength("{{>itemValue}}", {{>itemValue}}, {{expectedValue.length}})
{{else if isArray}}AsList("{{>itemValue}}", {{>itemValue}}{{#if expectedValue.length}}, {{expectedValue}}{{/if}})
{{else if (isString type)}}AsString("{{>itemValue}}", {{>itemValue}}, "{{expectedValue}}")
{{else}}<{{chipType}}>("{{>itemValue}}", {{>itemValue}}, {{expectedValue}}{{asTypeLiteralSuffix type}})
{{/if}}
);
{{/if}}
{{/if}}
{{#if hasExpectedConstraints}}
{{#if isOptional}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}}
VerifyOrReturn(CheckValuePresent("{{> item}}", {{> item}}));
{{/if}}
{{#if expectedConstraints.type}}VerifyOrReturn(CheckConstraintType("{{>item}}", "", "{{expectedConstraints.type}}"));{{/if}}
{{~#if expectedConstraints.format}}VerifyOrReturn(CheckConstraintFormat("{{>item}}", "", "{{expectedConstraints.format}}"));{{/if}}
{{~#if expectedConstraints.minLength}}VerifyOrReturn(CheckConstraintMinLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.minLength}}));{{/if}}
{{~#if expectedConstraints.maxLength}}VerifyOrReturn(CheckConstraintMaxLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.maxLength}}));{{/if}}
{{~#if expectedConstraints.minValue}}VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", {{>item}}, {{expectedConstraints.minValue}}));{{/if}}
{{~#if expectedConstraints.maxValue}}VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", {{>item}}, {{expectedConstraints.maxValue}}));{{/if}}
{{~#if expectedConstraints.notValue}}VerifyOrReturn(CheckConstraintNotValue<{{chipType}}>("{{>item}}", {{>item}}, {{expectedConstraints.notValue}}));{{/if}}
{{/if}}
{{/chip_tests_item_response_parameters}}
{{#unless async}}NextTest();{{/unless}}
{{/if}}
}
{{/if}}
{{/chip_tests_items}}
};
{{/chip_tests}}