From adcefe6f175f850d59a8ae935093e515c049bd79 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Tue, 11 Jan 2022 16:05:18 +0100 Subject: [PATCH] [YAML] Add isLowerCase/isUpperCase/isHexString constraints --- .../templates/partials/test_cluster.zapt | 3 + src/app/tests/suites/TestConstraints.yaml | 71 ++++ .../tests/suites/include/ConstraintsChecker.h | 99 ++++++ .../chip-tool/zap-generated/test/Commands.h | 326 +++++++++++++++++- 4 files changed, 494 insertions(+), 5 deletions(-) diff --git a/examples/chip-tool/templates/partials/test_cluster.zapt b/examples/chip-tool/templates/partials/test_cluster.zapt index 311b21326b4a2d..f3f6050c45c768 100644 --- a/examples/chip-tool/templates/partials/test_cluster.zapt +++ b/examples/chip-tool/templates/partials/test_cluster.zapt @@ -336,6 +336,9 @@ class {{filename}}: public TestCommand {{~#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.isUpperCase}}VerifyOrReturn(CheckConstraintIsUpperCase("{{>item}}", {{>item}}, {{expectedConstraints.isUpperCase}}));{{/if}} + {{~#if expectedConstraints.isLowerCase}}VerifyOrReturn(CheckConstraintIsLowerCase("{{>item}}", {{>item}}, {{expectedConstraints.isLowerCase}}));{{/if}} + {{~#if expectedConstraints.isHexString}}VerifyOrReturn(CheckConstraintIsHexString("{{>item}}", {{>item}}, {{expectedConstraints.isHexString}}));{{/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}} diff --git a/src/app/tests/suites/TestConstraints.yaml b/src/app/tests/suites/TestConstraints.yaml index 017d41a3b79b6c..30c5bc19ceb8a8 100644 --- a/src/app/tests/suites/TestConstraints.yaml +++ b/src/app/tests/suites/TestConstraints.yaml @@ -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" diff --git a/src/app/tests/suites/include/ConstraintsChecker.h b/src/app/tests/suites/include/ConstraintsChecker.h index 0c44c8b3bbe5d9..43d14134c64c07 100644 --- a/src/app/tests/suites/include/ConstraintsChecker.h +++ b/src/app/tests/suites/include/ConstraintsChecker.h @@ -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 bool CheckConstraintMinValue(const char * itemName, T current, T expected) { diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 8169cedb2573b5..f2a2221dc54dbe 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -55871,8 +55871,51 @@ class TestConstraints : public TestCommand err = TestReadAttributeCharStringValueEndsWithConstraints_10(); break; case 11: - ChipLogProgress(chipTool, " ***** Test Step 11 : Write attribute CHAR_STRING Value Back to Default Value\n"); - err = TestWriteAttributeCharStringValueBackToDefaultValue_11(); + ChipLogProgress(chipTool, " ***** Test Step 11 : Write attribute CHAR_STRING Value\n"); + err = TestWriteAttributeCharStringValue_11(); + break; + case 12: + ChipLogProgress(chipTool, + " ***** Test Step 12 : Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints\n"); + err = TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_12(); + break; + case 13: + ChipLogProgress(chipTool, " ***** Test Step 13 : Write attribute CHAR_STRING Value\n"); + err = TestWriteAttributeCharStringValue_13(); + break; + case 14: + ChipLogProgress(chipTool, + " ***** Test Step 14 : Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints\n"); + err = TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_14(); + break; + case 15: + ChipLogProgress(chipTool, " ***** Test Step 15 : Write attribute CHAR_STRING Value\n"); + err = TestWriteAttributeCharStringValue_15(); + break; + case 16: + ChipLogProgress(chipTool, + " ***** Test Step 16 : Read attribute CHAR_STRING Value isLowerCase/isUpperCase Constraints\n"); + err = TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_16(); + break; + case 17: + ChipLogProgress(chipTool, " ***** Test Step 17 : Write attribute CHAR_STRING Value\n"); + err = TestWriteAttributeCharStringValue_17(); + break; + case 18: + ChipLogProgress(chipTool, " ***** Test Step 18 : Read attribute CHAR_STRING Value isHexString Constraints\n"); + err = TestReadAttributeCharStringValueIsHexStringConstraints_18(); + break; + case 19: + ChipLogProgress(chipTool, " ***** Test Step 19 : Write attribute CHAR_STRING Value\n"); + err = TestWriteAttributeCharStringValue_19(); + break; + case 20: + ChipLogProgress(chipTool, " ***** Test Step 20 : Read attribute CHAR_STRING Value isHexString Constraints\n"); + err = TestReadAttributeCharStringValueIsHexStringConstraints_20(); + break; + case 21: + ChipLogProgress(chipTool, " ***** Test Step 21 : Write attribute CHAR_STRING Value Back to Default Value\n"); + err = TestWriteAttributeCharStringValueBackToDefaultValue_21(); break; } @@ -55885,7 +55928,7 @@ class TestConstraints : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 12; + const uint16_t mTestCount = 22; chip::Optional mCluster; chip::Optional mEndpoint; @@ -55988,6 +56031,91 @@ class TestConstraints : public TestCommand static void OnSuccessCallback_11(void * context) { (static_cast(context))->OnSuccessResponse_11(); } + static void OnFailureCallback_12(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_12(status); + } + + static void OnSuccessCallback_12(void * context, chip::CharSpan charString) + { + (static_cast(context))->OnSuccessResponse_12(charString); + } + + static void OnFailureCallback_13(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_13(status); + } + + static void OnSuccessCallback_13(void * context) { (static_cast(context))->OnSuccessResponse_13(); } + + static void OnFailureCallback_14(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_14(status); + } + + static void OnSuccessCallback_14(void * context, chip::CharSpan charString) + { + (static_cast(context))->OnSuccessResponse_14(charString); + } + + static void OnFailureCallback_15(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_15(status); + } + + static void OnSuccessCallback_15(void * context) { (static_cast(context))->OnSuccessResponse_15(); } + + static void OnFailureCallback_16(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_16(status); + } + + static void OnSuccessCallback_16(void * context, chip::CharSpan charString) + { + (static_cast(context))->OnSuccessResponse_16(charString); + } + + static void OnFailureCallback_17(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_17(status); + } + + static void OnSuccessCallback_17(void * context) { (static_cast(context))->OnSuccessResponse_17(); } + + static void OnFailureCallback_18(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_18(status); + } + + static void OnSuccessCallback_18(void * context, chip::CharSpan charString) + { + (static_cast(context))->OnSuccessResponse_18(charString); + } + + static void OnFailureCallback_19(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_19(status); + } + + static void OnSuccessCallback_19(void * context) { (static_cast(context))->OnSuccessResponse_19(); } + + static void OnFailureCallback_20(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_20(status); + } + + static void OnSuccessCallback_20(void * context, chip::CharSpan charString) + { + (static_cast(context))->OnSuccessResponse_20(charString); + } + + static void OnFailureCallback_21(void * context, EmberAfStatus status) + { + (static_cast(context))->OnFailureResponse_21(status); + } + + static void OnSuccessCallback_21(void * context) { (static_cast(context))->OnSuccessResponse_21(); } + // // Tests methods // @@ -56186,14 +56314,14 @@ class TestConstraints : public TestCommand NextTest(); } - CHIP_ERROR TestWriteAttributeCharStringValueBackToDefaultValue_11() + CHIP_ERROR TestWriteAttributeCharStringValue_11() { const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; chip::Controller::TestClusterClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); chip::CharSpan charStringArgument; - charStringArgument = chip::Span("garbage: not in length on purpose", 0); + charStringArgument = chip::Span("lowercasegarbage: not in length on purpose", 9); ReturnErrorOnFailure(cluster.WriteAttribute( charStringArgument, this, OnSuccessCallback_11, OnFailureCallback_11)); @@ -56203,6 +56331,194 @@ class TestConstraints : public TestCommand void OnFailureResponse_11(EmberAfStatus status) { ThrowFailureResponse(); } void OnSuccessResponse_11() { NextTest(); } + + CHIP_ERROR TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_12() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_12, OnFailureCallback_12)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_12(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_12(chip::CharSpan charString) + { + VerifyOrReturn(CheckConstraintIsUpperCase("charString", charString, false)); + VerifyOrReturn(CheckConstraintIsLowerCase("charString", charString, true)); + NextTest(); + } + + CHIP_ERROR TestWriteAttributeCharStringValue_13() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + chip::CharSpan charStringArgument; + charStringArgument = chip::Span("UPPERCASEgarbage: not in length on purpose", 9); + + ReturnErrorOnFailure(cluster.WriteAttribute( + charStringArgument, this, OnSuccessCallback_13, OnFailureCallback_13)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_13(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_13() { NextTest(); } + + CHIP_ERROR TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_14() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_14, OnFailureCallback_14)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_14(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_14(chip::CharSpan charString) + { + VerifyOrReturn(CheckConstraintIsUpperCase("charString", charString, true)); + VerifyOrReturn(CheckConstraintIsLowerCase("charString", charString, false)); + NextTest(); + } + + CHIP_ERROR TestWriteAttributeCharStringValue_15() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + chip::CharSpan charStringArgument; + charStringArgument = chip::Span("lowUPPERgarbage: not in length on purpose", 8); + + ReturnErrorOnFailure(cluster.WriteAttribute( + charStringArgument, this, OnSuccessCallback_15, OnFailureCallback_15)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_15(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_15() { NextTest(); } + + CHIP_ERROR TestReadAttributeCharStringValueIsLowerCaseIsUpperCaseConstraints_16() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_16, OnFailureCallback_16)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_16(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_16(chip::CharSpan charString) + { + VerifyOrReturn(CheckConstraintIsUpperCase("charString", charString, false)); + VerifyOrReturn(CheckConstraintIsLowerCase("charString", charString, false)); + NextTest(); + } + + CHIP_ERROR TestWriteAttributeCharStringValue_17() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + chip::CharSpan charStringArgument; + charStringArgument = chip::Span("ABCDEF012Vgarbage: not in length on purpose", 10); + + ReturnErrorOnFailure(cluster.WriteAttribute( + charStringArgument, this, OnSuccessCallback_17, OnFailureCallback_17)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_17(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_17() { NextTest(); } + + CHIP_ERROR TestReadAttributeCharStringValueIsHexStringConstraints_18() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_18, OnFailureCallback_18)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_18(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_18(chip::CharSpan charString) + { + VerifyOrReturn(CheckConstraintIsHexString("charString", charString, false)); + NextTest(); + } + + CHIP_ERROR TestWriteAttributeCharStringValue_19() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + chip::CharSpan charStringArgument; + charStringArgument = chip::Span("ABCDEF0123garbage: not in length on purpose", 10); + + ReturnErrorOnFailure(cluster.WriteAttribute( + charStringArgument, this, OnSuccessCallback_19, OnFailureCallback_19)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_19(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_19() { NextTest(); } + + CHIP_ERROR TestReadAttributeCharStringValueIsHexStringConstraints_20() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_20, OnFailureCallback_20)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_20(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_20(chip::CharSpan charString) + { + VerifyOrReturn(CheckConstraintIsHexString("charString", charString, true)); + NextTest(); + } + + CHIP_ERROR TestWriteAttributeCharStringValueBackToDefaultValue_21() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + chip::CharSpan charStringArgument; + charStringArgument = chip::Span("garbage: not in length on purpose", 0); + + ReturnErrorOnFailure(cluster.WriteAttribute( + charStringArgument, this, OnSuccessCallback_21, OnFailureCallback_21)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_21(EmberAfStatus status) { ThrowFailureResponse(); } + + void OnSuccessResponse_21() { NextTest(); } }; class TestDelayCommands : public TestCommand