| {{#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}}() |
| { |
| {{#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}}"); |
| MTRBaseCluster{{asUpperCamelCase cluster}} * cluster = [[MTRBaseCluster{{asUpperCamelCase 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{{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase command}}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{{asUpperCamelCase 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}} |
| MTRSubscribeParams * 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{{asUpperCamelCase 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}} |
| MTRReadParams * params = [[MTRReadParams alloc] init]; |
| params.filterByFabric = {{fabricFiltered}}; |
| {{/if_is_fabric_scoped_struct}} |
| [cluster readAttribute{{asUpperCamelCase 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{{asUpperCamelCase 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}} |