Skip to content

Commit

Permalink
Add simple optional/nullable test.
Browse files Browse the repository at this point in the history
  • Loading branch information
bzbarsky-apple committed Oct 23, 2021
1 parent df20284 commit 65423ee
Show file tree
Hide file tree
Showing 33 changed files with 826 additions and 6 deletions.
16 changes: 16 additions & 0 deletions examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
Original file line number Diff line number Diff line change
Expand Up @@ -14598,6 +14598,14 @@
"source": "client",
"incoming": 1,
"outgoing": 0
},
{
"name": "TestNullableOptionalRequest",
"code": 14,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 0
}
],
"attributes": [
Expand Down Expand Up @@ -14649,6 +14657,14 @@
"source": "server",
"incoming": 0,
"outgoing": 1
},
{
"name": "TestNullableOptionalResponse",
"code": 5,
"mfgCode": null,
"source": "server",
"incoming": 0,
"outgoing": 1
}
],
"attributes": [
Expand Down
25 changes: 25 additions & 0 deletions examples/chip-tool/commands/common/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include "controller/ExampleOperationalCredentialsIssuer.h"
#include <app/data-model/Nullable.h>
#include <controller/CHIPDeviceController.h>
#include <inet/InetInterface.h>
#include <lib/core/Optional.h>
Expand Down Expand Up @@ -160,6 +161,30 @@ class Command
return AddArgument(name, &value->Value());
}

template <typename T>
size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional<T> * value)
{
// We always require our args to be provided for the moment.
value->Emplace();
return AddArgument(name, min, max, &value->Value());
}

template <typename T>
size_t AddArgument(const char * name, chip::app::DataModel::Nullable<T> * value)
{
// We always require our args to be provided for the moment.
value->Emplace();
return AddArgument(name, &value->Value());
}

template <typename T>
size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::app::DataModel::Nullable<T> * value)
{
// We always require our args to be provided for the moment.
value->Emplace();
return AddArgument(name, min, max, &value->Value());
}

virtual CHIP_ERROR Run() = 0;

private:
Expand Down
12 changes: 12 additions & 0 deletions examples/chip-tool/commands/tests/TestCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,18 @@ class TestCommand : public CHIPCommand

bool CheckValueAsString(const char * itemName, chip::CharSpan current, const char * expected);

template <typename T>
bool CheckValuePresent(const char * itemName, const chip::Optional<T> & value)
{
if (value.HasValue())
{
return true;
}

Exit(std::string(itemName) + " expected to have value but doesn't");
return false;
}

chip::Callback::Callback<chip::Controller::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::Controller::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;

Expand Down
2 changes: 2 additions & 0 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ static void On{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}Success(v
{{~#*inline "field"}}data.{{asLowerCamelCase label}}{{/inline~}}
{{#if isArray}}
ChipLogProgress(Zcl, " {{label}}: Array printing is not implemented yet.");
{{else if isOptional}}
ChipLogProgress(Zcl, " {{label}}: Optional printing is not implemented yet.");
{{else if (isOctetString type)}}
ChipLogProgress(Zcl, " {{label}}: %zu", {{>field}}.size());
{{else if (isCharString type)}}
Expand Down
10 changes: 9 additions & 1 deletion examples/chip-tool/templates/partials/test_cluster.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,12 @@ class {{filename}}: public TestCommand
VerifyOrReturn(mReceivedReport_{{waitForReport.index}}, Exit("Initial report not received!"));
{{/if}}
{{#chip_tests_item_response_parameters}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{#if isOptional}}.Value(){{/if}}{{/inline}}
{{#if hasExpectedValue}}
{{#if isOptional}}
{{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}}
VerifyOrReturn(CheckValuePresent("{{> item}}", {{> item}}));
{{/if}}
VerifyOrReturn(CheckValue
{{~#if isList}}AsListLength("{{>item}}", {{>item}}, {{expectedValue.length}})
{{else if isArray}}AsList("{{>item}}", {{>item}}, {{expectedValue}})
Expand All @@ -178,6 +182,10 @@ class {{filename}}: public TestCommand
);
{{/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}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
{{#if isArray}}
{{#if isOptional}}
{{container}}{{#unless ignore}}.{{asLowerCamelCase label}}{{/unless}}.Emplace();
{{#if ignore}}
{{>commandValue ns=ns container=(concat container ".Value()") definedValue=definedValue type=type isOptional=false ignore=true}}
{{else}}
{{>commandValue ns=ns container=(concat container "." label ".Value()") definedValue=definedValue type=type isOptional=false ignore=true}}
{{/if}}
{{else if isNullable}}
{{container}}{{#unless ignore}}.{{asLowerCamelCase label}}{{/unless}}.Emplace();
{{#if ignore}}
{{>commandValue ns=ns container=(concat container ".Value()") definedValue=definedValue type=type isNullable=false ignore=true}}
{{else}}
{{>commandValue ns=ns container=(concat container "." label ".Value()") definedValue=definedValue type=type isNullable=false ignore=true}}
{{/if}}
{{else if isArray}}

{{! forceNotList=true because we really want the type of a single item here }}
{{zapTypeToEncodableClusterObjectType type ns=ns forceNotList=true}} {{asLowerCamelCase label}}List[{{definedValue.length}}];
{{! forceNotList=true because we really want the type of a single item here.
Similarly, forceNotOptional=true and forceNotNullable=true because we
have accounted for those already. }}
{{zapTypeToEncodableClusterObjectType type ns=ns forceNotList=true forceNotNullable=true forceNotOptional=true}} {{asLowerCamelCase label}}List[{{definedValue.length}}];
{{#each definedValue}}
{{>commandValue ns=../ns container=(concat (asLowerCamelCase ../label) "List[" @index "]") definedValue=. type=../type ignore=true}}
{{/each}}
Expand Down
23 changes: 23 additions & 0 deletions src/app/clusters/test-cluster-server/test-cluster-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,29 @@ bool emberAfTestClusterClusterTestListInt8UReverseRequestCallback(
return true;
}

bool emberAfTestClusterClusterTestNullableOptionalRequestCallback(
CommandHandler * commandObj, ConcreteCommandPath const & commandPath,
Commands::TestNullableOptionalRequest::DecodableType const & commandData)
{
Commands::TestNullableOptionalResponse::Type response;
response.wasPresent = commandData.arg1.HasValue();
if (response.wasPresent)
{
bool wasNull = !commandData.arg1.Value().HasValue();
response.wasNull.SetValue(wasNull);
if (!wasNull)
{
response.value.SetValue(commandData.arg1.Value().Value());
}
}
CHIP_ERROR err = commandObj->AddResponseData(commandPath, response);
if (err != CHIP_NO_ERROR)
{
emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE);
}
return true;
}

// -----------------------------------------------------------------------------
// Plugin initialization

Expand Down
38 changes: 38 additions & 0 deletions src/app/tests/suites/TestClusterComplexTypes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,41 @@ tests:
]
response:
error: 1

# Tests for Nullables and Optionals

- label: "Send Test Command with optional arg set."
command: "testNullableOptionalRequest"
arguments:
values:
- name: "arg1"
value: 5
response:
values:
- name: "wasPresent"
value: true
- name: "wasNull"
value: false
- name: "value"
value: 5

- label: "Send Test Command without its optional arg."
command: "testNullableOptionalRequest"
response:
values:
- name: "wasPresent"
value: false

- label: "Send Test Command with optional arg set to null."
disabled: true
command: "testNullableOptionalRequest"
arguments:
values:
- name: "arg1"
value: null
response:
values:
- name: "wasPresent"
value: true
- name: "wasNull"
value: false
5 changes: 4 additions & 1 deletion src/app/zap-templates/common/ClusterTestGeneration.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ function chip_tests_item_parameters(options)

const expected = commandValues.find(value => value.name.toLowerCase() == commandArg.name.toLowerCase());
if (!expected) {
if (commandArg.isOptional) {
return undefined;
}
printErrorAndExit(this,
'Missing "' + commandArg.name + '" in arguments list: \n\t* '
+ commandValues.map(command => command.name).join('\n\t* '));
Expand Down Expand Up @@ -438,7 +441,7 @@ function chip_tests_item_parameters(options)
return commandArg;
});

return commands;
return commands.filter(item => item !== undefined);
});

return asBlocks.call(this, promise, options);
Expand Down
19 changes: 19 additions & 0 deletions src/app/zap-templates/zcl/data-model/chip/test-cluster.xml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@ limitations under the License.
<arg name="arg1" type="INT8U" array="true"/>
</command>

<command source="client" code="0x0E" name="TestNullableOptionalRequest" optional="false">
<description>
Command that takes an argument which is nullable and optional. The
response returns a boolean indicating whether the argument was present,
if that's true a boolean indicating whether the argument was null, and
if that' false the argument it received.
</description>
<arg name="arg1" type="INT8U" optional="true" isNullable="true"/>
</command>

<command source="server" code="0x00" name="TestSpecificResponse" optional="false" disableDefaultResponse="true">
<description>
Simple response for TestWithResponse with a simple return value
Expand Down Expand Up @@ -286,6 +296,15 @@ limitations under the License.
<arg name="arg1" type="INT8U" array="true"/>
</command>

<command source="server" code="0x05" name="TestNullableOptionalResponse" optional="false" disableDefaultResponse="true">
<description>
Delivers information about the argument TestNullableOptionalResponse had.
</description>
<arg name="wasPresent" type="BOOLEAN"/>
<arg name="wasNull" type="BOOLEAN" optional="true"/>
<arg name="value" type="INT8U" optional="true"/>
</command>

<event code="0x0001" name="TestEvent" priority="info" side="server">
<description>Example test event</description>
<field id="1" name="arg1" type="INT8U"/>
Expand Down
16 changes: 16 additions & 0 deletions src/controller/data_model/controller-clusters.zap
Original file line number Diff line number Diff line change
Expand Up @@ -10823,6 +10823,14 @@
"source": "client",
"incoming": 0,
"outgoing": 1
},
{
"name": "TestNullableOptionalRequest",
"code": 14,
"mfgCode": null,
"source": "client",
"incoming": 0,
"outgoing": 1
}
],
"attributes": [
Expand Down Expand Up @@ -10874,6 +10882,14 @@
"source": "server",
"incoming": 1,
"outgoing": 0
},
{
"name": "TestNullableOptionalResponse",
"code": 5,
"mfgCode": null,
"source": "server",
"incoming": 1,
"outgoing": 0
}
],
"attributes": [
Expand Down
Loading

0 comments on commit 65423ee

Please sign in to comment.