Skip to content

Commit

Permalink
[YAML] Add isLowerCase/isUpperCase/isHexString constraints (#13479)
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple authored and pull[bot] committed Nov 15, 2023
1 parent b139d00 commit 2470065
Show file tree
Hide file tree
Showing 7 changed files with 1,358 additions and 28 deletions.
27 changes: 16 additions & 11 deletions examples/chip-tool/templates/partials/test_cluster.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -332,18 +332,23 @@ class {{filename}}: public TestCommand
{{~#*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.startsWith}}VerifyOrReturn(CheckConstraintStartsWith("{{>item}}", {{>item}}, "{{expectedConstraints.startsWith}}"));{{/if}}
{{~#if expectedConstraints.endsWith}}VerifyOrReturn(CheckConstraintEndsWith("{{>item}}", {{>item}}, "{{expectedConstraints.endsWith}}"));{{/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}}, {{asTypedLiteral expectedConstraints.minValue type}}));{{/if}}
{{~#if expectedConstraints.maxValue}}VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.maxValue type}}));{{/if}}
{{~#if expectedConstraints.notValue}}
VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.notValue type}}));
{{else if (isLiteralNull expectedConstraints.notValue)}}
{{#if (hasProperty expectedConstraints "type")}}VerifyOrReturn(CheckConstraintType("{{>item}}", "", "{{expectedConstraints.type}}"));{{/if}}
{{~#if (hasProperty expectedConstraints "format")}}VerifyOrReturn(CheckConstraintFormat("{{>item}}", "", "{{expectedConstraints.format}}"));{{/if}}
{{~#if (hasProperty expectedConstraints "startsWith")}}VerifyOrReturn(CheckConstraintStartsWith("{{>item}}", {{>item}}, "{{expectedConstraints.startsWith}}"));{{/if}}
{{~#if (hasProperty expectedConstraints "endsWith")}}VerifyOrReturn(CheckConstraintEndsWith("{{>item}}", {{>item}}, "{{expectedConstraints.endsWith}}"));{{/if}}
{{~#if (hasProperty expectedConstraints "isUpperCase")}}VerifyOrReturn(CheckConstraintIsUpperCase("{{>item}}", {{>item}}, {{expectedConstraints.isUpperCase}}));{{/if}}
{{~#if (hasProperty expectedConstraints "isLowerCase")}}VerifyOrReturn(CheckConstraintIsLowerCase("{{>item}}", {{>item}}, {{expectedConstraints.isLowerCase}}));{{/if}}
{{~#if (hasProperty expectedConstraints "isHexString")}}VerifyOrReturn(CheckConstraintIsHexString("{{>item}}", {{>item}}, {{expectedConstraints.isHexString}}));{{/if}}
{{~#if (hasProperty expectedConstraints "minLength")}}VerifyOrReturn(CheckConstraintMinLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.minLength}}));{{/if}}
{{~#if (hasProperty expectedConstraints "maxLength")}}VerifyOrReturn(CheckConstraintMaxLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.maxLength}}));{{/if}}
{{~#if (hasProperty expectedConstraints "minValue")}}VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.minValue type}}));{{/if}}
{{~#if (hasProperty expectedConstraints "maxValue")}}VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.maxValue type}}));{{/if}}
{{~#if (hasProperty expectedConstraints "notValue")}}
{{#if (isLiteralNull expectedConstraints.notValue)}}
VerifyOrReturn(CheckValueNonNull("{{>item}}", {{>item}}));
{{else}}
VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.notValue type}}));
{{/if}}
{{/if}}
{{/if}}

Expand Down
71 changes: 71 additions & 0 deletions src/app/tests/suites/TestConstraints.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,77 @@ tests:
constraints:
endsWith: "**"

- label: "Write attribute CHAR_STRING Value"
command: "writeAttribute"
attribute: "char_string"
arguments:
value: "lowercase"

- label:
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
command: "readAttribute"
attribute: "char_string"
response:
constraints:
isLowerCase: true
isUpperCase: false

- label: "Write attribute CHAR_STRING Value"
command: "writeAttribute"
attribute: "char_string"
arguments:
value: "UPPERCASE"

- label:
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
command: "readAttribute"
attribute: "char_string"
response:
constraints:
isUpperCase: true
isLowerCase: false

- label: "Write attribute CHAR_STRING Value"
command: "writeAttribute"
attribute: "char_string"
arguments:
value: "lowUPPER"

- label:
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
command: "readAttribute"
attribute: "char_string"
response:
constraints:
isUpperCase: false
isLowerCase: false

- label: "Write attribute CHAR_STRING Value"
command: "writeAttribute"
attribute: "char_string"
arguments:
value: "ABCDEF012V"

- label: "Read attribute CHAR_STRING Value isHexString Constraints"
command: "readAttribute"
attribute: "char_string"
response:
constraints:
isHexString: false

- label: "Write attribute CHAR_STRING Value"
command: "writeAttribute"
attribute: "char_string"
arguments:
value: "ABCDEF0123"

- label: "Read attribute CHAR_STRING Value isHexString Constraints"
command: "readAttribute"
attribute: "char_string"
response:
constraints:
isHexString: true

- label: "Write attribute CHAR_STRING Value Back to Default Value"
command: "writeAttribute"
attribute: "char_string"
Expand Down
99 changes: 99 additions & 0 deletions src/app/tests/suites/include/ConstraintsChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,105 @@ class ConstraintsChecker
return true;
}

bool CheckConstraintIsUpperCase(const char * itemName, const chip::CharSpan current, bool expectUpperCase)
{
std::string value(current.data(), current.size());
return CheckConstraintIsUpperCase(itemName, value.c_str(), expectUpperCase);
}

bool CheckConstraintIsUpperCase(const char * itemName, const char * current, bool expectUpperCase)
{
bool isUpperCase = true;
for (size_t i = 0; i < strlen(current); i++)
{
if (!isupper(current[i]))
{
isUpperCase = false;
break;
}
}

if (expectUpperCase && !isUpperCase)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not an upppercase string");
return false;
}

if (!expectUpperCase && isUpperCase)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is an upppercase string");
return false;
}

return true;
}

bool CheckConstraintIsLowerCase(const char * itemName, const chip::CharSpan current, bool expectLowerCase)
{
std::string value(current.data(), current.size());
return CheckConstraintIsLowerCase(itemName, value.c_str(), expectLowerCase);
}

bool CheckConstraintIsLowerCase(const char * itemName, const char * current, bool expectLowerCase)
{
bool isLowerCase = true;
for (size_t i = 0; i < strlen(current); i++)
{
if (isupper(current[i]))
{
isLowerCase = false;
break;
}
}

if (expectLowerCase && !isLowerCase)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not a lowercase string");
return false;
}

if (!expectLowerCase && isLowerCase)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is a lowercase string");
return false;
}

return true;
}

bool CheckConstraintIsHexString(const char * itemName, const chip::CharSpan current, bool expectHexString)
{
std::string value(current.data(), current.size());
return CheckConstraintIsHexString(itemName, value.c_str(), expectHexString);
}

bool CheckConstraintIsHexString(const char * itemName, const char * current, bool expectHexString)
{
bool isHexString = true;
for (size_t i = 0; i < strlen(current); i++)
{
if (!isxdigit(current[i]))
{
isHexString = false;
break;
}
}

if (expectHexString && !isHexString)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not a hexadecimal string");
return false;
}

if (!expectHexString && isHexString)
{
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is a hexadecimal string");
return false;
}

return true;
}

template <typename T>
bool CheckConstraintMinValue(const char * itemName, T current, T expected)
{
Expand Down
6 changes: 6 additions & 0 deletions src/app/zap-templates/templates/app/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,11 @@ function incrementDepth(depth)
return depth + 1;
}

function hasProperty(obj, prop)
{
return prop in obj;
}

//
// Module exports
//
Expand All @@ -695,6 +700,7 @@ exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list
exports.asTypedLiteral = asTypedLiteral;
exports.asLowerCamelCase = asLowerCamelCase;
exports.asUpperCamelCase = asUpperCamelCase;
exports.hasProperty = hasProperty;
exports.hasSpecificAttributes = hasSpecificAttributes;
exports.asMEI = asMEI;
exports.zapTypeToEncodableClusterObjectType = zapTypeToEncodableClusterObjectType;
Expand Down
45 changes: 33 additions & 12 deletions src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -108,57 +108,78 @@ ResponseHandler {{> subscribeDataCallback}} = nil;
}
{{/if}}
{{#if hasExpectedConstraints}}
{{#if expectedConstraints.minLength}}
{{#if (hasProperty expectedConstraints "minLength")}}
{
{{> actualValue}}
XCTAssertGreaterThanOrEqual([actualValue length], {{expectedConstraints.minLength}});
}
{{/if}}
{{#if expectedConstraints.startsWith}}
{{#if (hasProperty expectedConstraints "startsWith")}}
{
{{> actualValue}}
XCTAssertTrue([actualValue hasPrefix:@"{{expectedConstraints.startsWith}}"]);
}
{{/if}}
{{#if expectedConstraints.endsWith}}
{{#if (hasProperty expectedConstraints "endsWith")}}
{
{{> actualValue}}
XCTAssertTrue([actualValue hasSuffix:@"{{expectedConstraints.endsWith}}"]);
}
{{/if}}
{{#if expectedConstraints.maxLength}}
{{#if (hasProperty expectedConstraints "isLowerCase")}}
{
{{> actualValue}}
BOOL isLowerCase = [actualValue isEqualToString:[actualValue lowercaseString]];
XCTAssert{{#if expectedConstraints.isLowerCase}}True{{else}}False{{/if}}(isLowerCase);
}
{{/if}}
{{#if (hasProperty expectedConstraints "isUpperCase")}}
{
{{> actualValue}}
BOOL isUpperCase = [actualValue isEqualToString:[actualValue uppercaseString]];
XCTAssert{{#if expectedConstraints.isUpperCase}}True{{else}}False{{/if}}(isUpperCase);
}
{{/if}}
{{#if (hasProperty expectedConstraints "isHexString")}}
{
{{> actualValue}}
NSCharacterSet *chars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"] invertedSet];
BOOL isHexString = (NSNotFound == [actualValue rangeOfCharacterFromSet:chars].location);
XCTAssert{{#if expectedConstraints.isHexString}}True{{else}}False{{/if}}(isHexString);
}
{{/if}}
{{#if (hasProperty expectedConstraints "maxLength")}}
{
{{> actualValue}}
XCTAssertLessThanOrEqual([actualValue length], {{expectedConstraints.maxLength}});
}
{{/if}}
{{#if expectedConstraints.minValue}}
{{#if (hasProperty expectedConstraints "minValue")}}
{
{{> actualValue}}
if (actualValue != nil) {
XCTAssertGreaterThanOrEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.minValue type}});
}
}
{{/if}}
{{#if expectedConstraints.maxValue}}
{{#if (hasProperty expectedConstraints "maxValue")}}
{
{{> actualValue}}
if (actualValue != nil) {
XCTAssertLessThanOrEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.maxValue type}});
}
}
{{/if}}
{{#if expectedConstraints.notValue}}
{{#if (hasProperty expectedConstraints "notValue")}}
{
{{> actualValue}}
{{#if (isLiteralNull expectedConstraints.notValue)}}
XCTAssertFalse(actualValue == nil);
{{else}}
if (actualValue != nil) {
XCTAssertNotEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.notValue type}});
}
}
{{else if (isLiteralNull expectedConstraints.notValue)}}
{
{{> actualValue}}
XCTAssertFalse(actualValue == nil);
{{/if}}
}
{{/if}}
{{/if}}
Expand Down
Loading

0 comments on commit 2470065

Please sign in to comment.