Skip to content

Commit 039535f

Browse files
vivien-applepull[bot]
authored andcommitted
[YAML] Add isLowerCase/isUpperCase/isHexString constraints (#13479)
1 parent f7459a8 commit 039535f

File tree

7 files changed

+1358
-28
lines changed

7 files changed

+1358
-28
lines changed

examples/chip-tool/templates/partials/test_cluster.zapt

+16-11
Original file line numberDiff line numberDiff line change
@@ -332,18 +332,23 @@ class {{filename}}: public TestCommand
332332
{{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}}
333333
VerifyOrReturn(CheckValuePresent("{{> item}}", {{> item}}));
334334
{{/if}}
335-
{{#if expectedConstraints.type}}VerifyOrReturn(CheckConstraintType("{{>item}}", "", "{{expectedConstraints.type}}"));{{/if}}
336-
{{~#if expectedConstraints.format}}VerifyOrReturn(CheckConstraintFormat("{{>item}}", "", "{{expectedConstraints.format}}"));{{/if}}
337-
{{~#if expectedConstraints.startsWith}}VerifyOrReturn(CheckConstraintStartsWith("{{>item}}", {{>item}}, "{{expectedConstraints.startsWith}}"));{{/if}}
338-
{{~#if expectedConstraints.endsWith}}VerifyOrReturn(CheckConstraintEndsWith("{{>item}}", {{>item}}, "{{expectedConstraints.endsWith}}"));{{/if}}
339-
{{~#if expectedConstraints.minLength}}VerifyOrReturn(CheckConstraintMinLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.minLength}}));{{/if}}
340-
{{~#if expectedConstraints.maxLength}}VerifyOrReturn(CheckConstraintMaxLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.maxLength}}));{{/if}}
341-
{{~#if expectedConstraints.minValue}}VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.minValue type}}));{{/if}}
342-
{{~#if expectedConstraints.maxValue}}VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.maxValue type}}));{{/if}}
343-
{{~#if expectedConstraints.notValue}}
344-
VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.notValue type}}));
345-
{{else if (isLiteralNull expectedConstraints.notValue)}}
335+
{{#if (hasProperty expectedConstraints "type")}}VerifyOrReturn(CheckConstraintType("{{>item}}", "", "{{expectedConstraints.type}}"));{{/if}}
336+
{{~#if (hasProperty expectedConstraints "format")}}VerifyOrReturn(CheckConstraintFormat("{{>item}}", "", "{{expectedConstraints.format}}"));{{/if}}
337+
{{~#if (hasProperty expectedConstraints "startsWith")}}VerifyOrReturn(CheckConstraintStartsWith("{{>item}}", {{>item}}, "{{expectedConstraints.startsWith}}"));{{/if}}
338+
{{~#if (hasProperty expectedConstraints "endsWith")}}VerifyOrReturn(CheckConstraintEndsWith("{{>item}}", {{>item}}, "{{expectedConstraints.endsWith}}"));{{/if}}
339+
{{~#if (hasProperty expectedConstraints "isUpperCase")}}VerifyOrReturn(CheckConstraintIsUpperCase("{{>item}}", {{>item}}, {{expectedConstraints.isUpperCase}}));{{/if}}
340+
{{~#if (hasProperty expectedConstraints "isLowerCase")}}VerifyOrReturn(CheckConstraintIsLowerCase("{{>item}}", {{>item}}, {{expectedConstraints.isLowerCase}}));{{/if}}
341+
{{~#if (hasProperty expectedConstraints "isHexString")}}VerifyOrReturn(CheckConstraintIsHexString("{{>item}}", {{>item}}, {{expectedConstraints.isHexString}}));{{/if}}
342+
{{~#if (hasProperty expectedConstraints "minLength")}}VerifyOrReturn(CheckConstraintMinLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.minLength}}));{{/if}}
343+
{{~#if (hasProperty expectedConstraints "maxLength")}}VerifyOrReturn(CheckConstraintMaxLength("{{>item}}", {{>item}}.size(), {{expectedConstraints.maxLength}}));{{/if}}
344+
{{~#if (hasProperty expectedConstraints "minValue")}}VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.minValue type}}));{{/if}}
345+
{{~#if (hasProperty expectedConstraints "maxValue")}}VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.maxValue type}}));{{/if}}
346+
{{~#if (hasProperty expectedConstraints "notValue")}}
347+
{{#if (isLiteralNull expectedConstraints.notValue)}}
346348
VerifyOrReturn(CheckValueNonNull("{{>item}}", {{>item}}));
349+
{{else}}
350+
VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>item}}, {{asTypedLiteral expectedConstraints.notValue type}}));
351+
{{/if}}
347352
{{/if}}
348353
{{/if}}
349354

src/app/tests/suites/TestConstraints.yaml

+71
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,77 @@ tests:
9494
constraints:
9595
endsWith: "**"
9696

97+
- label: "Write attribute CHAR_STRING Value"
98+
command: "writeAttribute"
99+
attribute: "char_string"
100+
arguments:
101+
value: "lowercase"
102+
103+
- label:
104+
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
105+
command: "readAttribute"
106+
attribute: "char_string"
107+
response:
108+
constraints:
109+
isLowerCase: true
110+
isUpperCase: false
111+
112+
- label: "Write attribute CHAR_STRING Value"
113+
command: "writeAttribute"
114+
attribute: "char_string"
115+
arguments:
116+
value: "UPPERCASE"
117+
118+
- label:
119+
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
120+
command: "readAttribute"
121+
attribute: "char_string"
122+
response:
123+
constraints:
124+
isUpperCase: true
125+
isLowerCase: false
126+
127+
- label: "Write attribute CHAR_STRING Value"
128+
command: "writeAttribute"
129+
attribute: "char_string"
130+
arguments:
131+
value: "lowUPPER"
132+
133+
- label:
134+
"Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints"
135+
command: "readAttribute"
136+
attribute: "char_string"
137+
response:
138+
constraints:
139+
isUpperCase: false
140+
isLowerCase: false
141+
142+
- label: "Write attribute CHAR_STRING Value"
143+
command: "writeAttribute"
144+
attribute: "char_string"
145+
arguments:
146+
value: "ABCDEF012V"
147+
148+
- label: "Read attribute CHAR_STRING Value isHexString Constraints"
149+
command: "readAttribute"
150+
attribute: "char_string"
151+
response:
152+
constraints:
153+
isHexString: false
154+
155+
- label: "Write attribute CHAR_STRING Value"
156+
command: "writeAttribute"
157+
attribute: "char_string"
158+
arguments:
159+
value: "ABCDEF0123"
160+
161+
- label: "Read attribute CHAR_STRING Value isHexString Constraints"
162+
command: "readAttribute"
163+
attribute: "char_string"
164+
response:
165+
constraints:
166+
isHexString: true
167+
97168
- label: "Write attribute CHAR_STRING Value Back to Default Value"
98169
command: "writeAttribute"
99170
attribute: "char_string"

src/app/tests/suites/include/ConstraintsChecker.h

+99
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,105 @@ class ConstraintsChecker
9090
return true;
9191
}
9292

93+
bool CheckConstraintIsUpperCase(const char * itemName, const chip::CharSpan current, bool expectUpperCase)
94+
{
95+
std::string value(current.data(), current.size());
96+
return CheckConstraintIsUpperCase(itemName, value.c_str(), expectUpperCase);
97+
}
98+
99+
bool CheckConstraintIsUpperCase(const char * itemName, const char * current, bool expectUpperCase)
100+
{
101+
bool isUpperCase = true;
102+
for (size_t i = 0; i < strlen(current); i++)
103+
{
104+
if (!isupper(current[i]))
105+
{
106+
isUpperCase = false;
107+
break;
108+
}
109+
}
110+
111+
if (expectUpperCase && !isUpperCase)
112+
{
113+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not an upppercase string");
114+
return false;
115+
}
116+
117+
if (!expectUpperCase && isUpperCase)
118+
{
119+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is an upppercase string");
120+
return false;
121+
}
122+
123+
return true;
124+
}
125+
126+
bool CheckConstraintIsLowerCase(const char * itemName, const chip::CharSpan current, bool expectLowerCase)
127+
{
128+
std::string value(current.data(), current.size());
129+
return CheckConstraintIsLowerCase(itemName, value.c_str(), expectLowerCase);
130+
}
131+
132+
bool CheckConstraintIsLowerCase(const char * itemName, const char * current, bool expectLowerCase)
133+
{
134+
bool isLowerCase = true;
135+
for (size_t i = 0; i < strlen(current); i++)
136+
{
137+
if (isupper(current[i]))
138+
{
139+
isLowerCase = false;
140+
break;
141+
}
142+
}
143+
144+
if (expectLowerCase && !isLowerCase)
145+
{
146+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not a lowercase string");
147+
return false;
148+
}
149+
150+
if (!expectLowerCase && isLowerCase)
151+
{
152+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is a lowercase string");
153+
return false;
154+
}
155+
156+
return true;
157+
}
158+
159+
bool CheckConstraintIsHexString(const char * itemName, const chip::CharSpan current, bool expectHexString)
160+
{
161+
std::string value(current.data(), current.size());
162+
return CheckConstraintIsHexString(itemName, value.c_str(), expectHexString);
163+
}
164+
165+
bool CheckConstraintIsHexString(const char * itemName, const char * current, bool expectHexString)
166+
{
167+
bool isHexString = true;
168+
for (size_t i = 0; i < strlen(current); i++)
169+
{
170+
if (!isxdigit(current[i]))
171+
{
172+
isHexString = false;
173+
break;
174+
}
175+
}
176+
177+
if (expectHexString && !isHexString)
178+
{
179+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is not a hexadecimal string");
180+
return false;
181+
}
182+
183+
if (!expectHexString && isHexString)
184+
{
185+
Exit(std::string(itemName) + " (\"" + std::string(current) + "\") is a hexadecimal string");
186+
return false;
187+
}
188+
189+
return true;
190+
}
191+
93192
template <typename T>
94193
bool CheckConstraintMinValue(const char * itemName, T current, T expected)
95194
{

src/app/zap-templates/templates/app/helper.js

+6
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,11 @@ function incrementDepth(depth)
685685
return depth + 1;
686686
}
687687

688+
function hasProperty(obj, prop)
689+
{
690+
return prop in obj;
691+
}
692+
688693
//
689694
// Module exports
690695
//
@@ -695,6 +700,7 @@ exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list
695700
exports.asTypedLiteral = asTypedLiteral;
696701
exports.asLowerCamelCase = asLowerCamelCase;
697702
exports.asUpperCamelCase = asUpperCamelCase;
703+
exports.hasProperty = hasProperty;
698704
exports.hasSpecificAttributes = hasSpecificAttributes;
699705
exports.asMEI = asMEI;
700706
exports.zapTypeToEncodableClusterObjectType = zapTypeToEncodableClusterObjectType;

src/darwin/Framework/CHIP/templates/partials/test_cluster.zapt

+33-12
Original file line numberDiff line numberDiff line change
@@ -108,57 +108,78 @@ ResponseHandler {{> subscribeDataCallback}} = nil;
108108
}
109109
{{/if}}
110110
{{#if hasExpectedConstraints}}
111-
{{#if expectedConstraints.minLength}}
111+
{{#if (hasProperty expectedConstraints "minLength")}}
112112
{
113113
{{> actualValue}}
114114
XCTAssertGreaterThanOrEqual([actualValue length], {{expectedConstraints.minLength}});
115115
}
116116
{{/if}}
117-
{{#if expectedConstraints.startsWith}}
117+
{{#if (hasProperty expectedConstraints "startsWith")}}
118118
{
119119
{{> actualValue}}
120120
XCTAssertTrue([actualValue hasPrefix:@"{{expectedConstraints.startsWith}}"]);
121121
}
122122
{{/if}}
123-
{{#if expectedConstraints.endsWith}}
123+
{{#if (hasProperty expectedConstraints "endsWith")}}
124124
{
125125
{{> actualValue}}
126126
XCTAssertTrue([actualValue hasSuffix:@"{{expectedConstraints.endsWith}}"]);
127127
}
128128
{{/if}}
129-
{{#if expectedConstraints.maxLength}}
129+
{{#if (hasProperty expectedConstraints "isLowerCase")}}
130+
{
131+
{{> actualValue}}
132+
BOOL isLowerCase = [actualValue isEqualToString:[actualValue lowercaseString]];
133+
XCTAssert{{#if expectedConstraints.isLowerCase}}True{{else}}False{{/if}}(isLowerCase);
134+
}
135+
{{/if}}
136+
{{#if (hasProperty expectedConstraints "isUpperCase")}}
137+
{
138+
{{> actualValue}}
139+
BOOL isUpperCase = [actualValue isEqualToString:[actualValue uppercaseString]];
140+
XCTAssert{{#if expectedConstraints.isUpperCase}}True{{else}}False{{/if}}(isUpperCase);
141+
}
142+
{{/if}}
143+
{{#if (hasProperty expectedConstraints "isHexString")}}
144+
{
145+
{{> actualValue}}
146+
NSCharacterSet *chars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"] invertedSet];
147+
BOOL isHexString = (NSNotFound == [actualValue rangeOfCharacterFromSet:chars].location);
148+
XCTAssert{{#if expectedConstraints.isHexString}}True{{else}}False{{/if}}(isHexString);
149+
}
150+
{{/if}}
151+
{{#if (hasProperty expectedConstraints "maxLength")}}
130152
{
131153
{{> actualValue}}
132154
XCTAssertLessThanOrEqual([actualValue length], {{expectedConstraints.maxLength}});
133155
}
134156
{{/if}}
135-
{{#if expectedConstraints.minValue}}
157+
{{#if (hasProperty expectedConstraints "minValue")}}
136158
{
137159
{{> actualValue}}
138160
if (actualValue != nil) {
139161
XCTAssertGreaterThanOrEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.minValue type}});
140162
}
141163
}
142164
{{/if}}
143-
{{#if expectedConstraints.maxValue}}
165+
{{#if (hasProperty expectedConstraints "maxValue")}}
144166
{
145167
{{> actualValue}}
146168
if (actualValue != nil) {
147169
XCTAssertLessThanOrEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.maxValue type}});
148170
}
149171
}
150172
{{/if}}
151-
{{#if expectedConstraints.notValue}}
173+
{{#if (hasProperty expectedConstraints "notValue")}}
152174
{
153175
{{> actualValue}}
176+
{{#if (isLiteralNull expectedConstraints.notValue)}}
177+
XCTAssertFalse(actualValue == nil);
178+
{{else}}
154179
if (actualValue != nil) {
155180
XCTAssertNotEqual([actualValue {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.notValue type}});
156181
}
157-
}
158-
{{else if (isLiteralNull expectedConstraints.notValue)}}
159-
{
160-
{{> actualValue}}
161-
XCTAssertFalse(actualValue == nil);
182+
{{/if}}
162183
}
163184
{{/if}}
164185
{{/if}}

0 commit comments

Comments
 (0)