Skip to content

Commit

Permalink
Attribute validation defaults to minimum and maximum defined by type …
Browse files Browse the repository at this point in the history
…if not defined by attribute. (project-chip#1481)

* Attribute validation defaults to minimum and maximum defined by type if not defined by attribute.

* Added tests
  • Loading branch information
dhchandw authored Nov 13, 2024
1 parent c67f2ef commit 5289d6c
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 55 deletions.
60 changes: 32 additions & 28 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -18925,7 +18925,6 @@ things were successful or not.
* [~validateSpecificAttribute(endpointAttribute, attribute, db, zapSessionId)](#module_Validation API_ Validation APIs..validateSpecificAttribute) ⇒
* [~validateSpecificEndpoint(endpoint)](#module_Validation API_ Validation APIs..validateSpecificEndpoint) ⇒
* [~isValidNumberString(value)](#module_Validation API_ Validation APIs..isValidNumberString) ⇒
* [~isValidSignedNumberString(value)](#module_Validation API_ Validation APIs..isValidSignedNumberString) ⇒
* [~isValidHexString(value)](#module_Validation API_ Validation APIs..isValidHexString) ⇒
* [~isValidDecimalString(value)](#module_Validation API_ Validation APIs..isValidDecimalString) ⇒
* [~isValidFloat(value)](#module_Validation API_ Validation APIs..isValidFloat) ⇒
Expand All @@ -18934,6 +18933,7 @@ things were successful or not.
* [~extractBigIntegerValue(value)](#module_Validation API_ Validation APIs..extractBigIntegerValue) ⇒
* [~isBigInteger(bits)](#module_Validation API_ Validation APIs..isBigInteger) ⇒
* [~getBoundsInteger(attribute, typeSize, isSigned)](#module_Validation API_ Validation APIs..getBoundsInteger) ⇒
* [~getTypeRange(typeSize, isSigned, isMin)](#module_Validation API_ Validation APIs..getTypeRange) ⇒
* [~unsignedToSignedInteger(value, typeSize)](#module_Validation API_ Validation APIs..unsignedToSignedInteger) ⇒
* [~getIntegerFromAttribute(attribute, typeSize, isSigned)](#module_Validation API_ Validation APIs..getIntegerFromAttribute) ⇒
* [~getIntegerAttributeSize(db, zapSessionId, attribType)](#module_Validation API_ Validation APIs..getIntegerAttributeSize) ⇒ <code>\*</code>
Expand Down Expand Up @@ -18976,7 +18976,7 @@ Enforce zigbee specific common cluster initialization.

### Validation API: Validation APIs~validateAttribute(db, endpointTypeId, attributeRef, clusterRef, zapSessionId) ⇒
Main attribute validation function.
Returns a promise of an object which stores a list of validational issues.
Returns a promise of an object which stores a list of validation issues.
Such issues as "Invalid type" or "Out of Range".

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
Expand Down Expand Up @@ -19057,18 +19057,6 @@ This applies to both actual numbers as well as octet strings.
| --- | --- |
| value | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..isValidSignedNumberString"></a>

### Validation API: Validation APIs~isValidSignedNumberString(value) ⇒
Check if value is a valid signed number in string form.

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
**Returns**: boolean

| Param | Type |
| --- | --- |
| value | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..isValidHexString"></a>

### Validation API: Validation APIs~isValidHexString(value) ⇒
Expand Down Expand Up @@ -19169,6 +19157,20 @@ Get the integer attribute's bounds.
| typeSize | <code>\*</code> |
| isSigned | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..getTypeRange"></a>

### Validation API: Validation APIs~getTypeRange(typeSize, isSigned, isMin) ⇒
Gets the range of an integer type.

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
**Returns**: integer

| Param | Type |
| --- | --- |
| typeSize | <code>\*</code> |
| isSigned | <code>\*</code> |
| isMin | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..unsignedToSignedInteger"></a>

### Validation API: Validation APIs~unsignedToSignedInteger(value, typeSize) ⇒
Expand Down Expand Up @@ -19300,7 +19302,6 @@ things were successful or not.
* [~validateSpecificAttribute(endpointAttribute, attribute, db, zapSessionId)](#module_Validation API_ Validation APIs..validateSpecificAttribute) ⇒
* [~validateSpecificEndpoint(endpoint)](#module_Validation API_ Validation APIs..validateSpecificEndpoint) ⇒
* [~isValidNumberString(value)](#module_Validation API_ Validation APIs..isValidNumberString) ⇒
* [~isValidSignedNumberString(value)](#module_Validation API_ Validation APIs..isValidSignedNumberString) ⇒
* [~isValidHexString(value)](#module_Validation API_ Validation APIs..isValidHexString) ⇒
* [~isValidDecimalString(value)](#module_Validation API_ Validation APIs..isValidDecimalString) ⇒
* [~isValidFloat(value)](#module_Validation API_ Validation APIs..isValidFloat) ⇒
Expand All @@ -19309,6 +19310,7 @@ things were successful or not.
* [~extractBigIntegerValue(value)](#module_Validation API_ Validation APIs..extractBigIntegerValue) ⇒
* [~isBigInteger(bits)](#module_Validation API_ Validation APIs..isBigInteger) ⇒
* [~getBoundsInteger(attribute, typeSize, isSigned)](#module_Validation API_ Validation APIs..getBoundsInteger) ⇒
* [~getTypeRange(typeSize, isSigned, isMin)](#module_Validation API_ Validation APIs..getTypeRange) ⇒
* [~unsignedToSignedInteger(value, typeSize)](#module_Validation API_ Validation APIs..unsignedToSignedInteger) ⇒
* [~getIntegerFromAttribute(attribute, typeSize, isSigned)](#module_Validation API_ Validation APIs..getIntegerFromAttribute) ⇒
* [~getIntegerAttributeSize(db, zapSessionId, attribType)](#module_Validation API_ Validation APIs..getIntegerAttributeSize) ⇒ <code>\*</code>
Expand Down Expand Up @@ -19351,7 +19353,7 @@ Enforce zigbee specific common cluster initialization.

### Validation API: Validation APIs~validateAttribute(db, endpointTypeId, attributeRef, clusterRef, zapSessionId) ⇒
Main attribute validation function.
Returns a promise of an object which stores a list of validational issues.
Returns a promise of an object which stores a list of validation issues.
Such issues as "Invalid type" or "Out of Range".

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
Expand Down Expand Up @@ -19432,18 +19434,6 @@ This applies to both actual numbers as well as octet strings.
| --- | --- |
| value | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..isValidSignedNumberString"></a>

### Validation API: Validation APIs~isValidSignedNumberString(value) ⇒
Check if value is a valid signed number in string form.

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
**Returns**: boolean

| Param | Type |
| --- | --- |
| value | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..isValidHexString"></a>

### Validation API: Validation APIs~isValidHexString(value) ⇒
Expand Down Expand Up @@ -19544,6 +19534,20 @@ Get the integer attribute's bounds.
| typeSize | <code>\*</code> |
| isSigned | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..getTypeRange"></a>

### Validation API: Validation APIs~getTypeRange(typeSize, isSigned, isMin) ⇒
Gets the range of an integer type.

**Kind**: inner method of [<code>Validation API: Validation APIs</code>](#module_Validation API_ Validation APIs)
**Returns**: integer

| Param | Type |
| --- | --- |
| typeSize | <code>\*</code> |
| isSigned | <code>\*</code> |
| isMin | <code>\*</code> |

<a name="module_Validation API_ Validation APIs..unsignedToSignedInteger"></a>

### Validation API: Validation APIs~unsignedToSignedInteger(value, typeSize) ⇒
Expand Down
45 changes: 18 additions & 27 deletions src-electron/validation/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const queryPackage = require('../db/query-package.js')

/**
* Main attribute validation function.
* Returns a promise of an object which stores a list of validational issues.
* Returns a promise of an object which stores a list of validation issues.
* Such issues as "Invalid type" or "Out of Range".
* @param {*} db db reference
* @param {*} endpointTypeId endpoint reference
Expand Down Expand Up @@ -128,20 +128,6 @@ async function validateSpecificAttribute(
//Interpreting float values
if (!checkAttributeBoundsFloat(attribute, endpointAttribute))
defaultAttributeIssues.push('Out of range')
} else if (await types.isSignedInteger(db, zapSessionId, attribute.type)) {
// we shouldn't check boundaries for an invalid number string
if (!isValidSignedNumberString(endpointAttribute.defaultValue)) {
defaultAttributeIssues.push('Invalid Integer')
} else if (
!(await checkAttributeBoundsInteger(
attribute,
endpointAttribute,
db,
zapSessionId
))
) {
defaultAttributeIssues.push('Out of range')
}
} else {
// we shouldn't check boundaries for an invalid number string
if (!isValidNumberString(endpointAttribute.defaultValue)) {
Expand Down Expand Up @@ -210,16 +196,6 @@ function isValidNumberString(value) {
return /^(0x)?[\dA-F]+$/i.test(value) || Number.isInteger(Number(value))
}

/**
* Check if value is a valid signed number in string form.
*
* @param {*} value
* @returns boolean
*/
function isValidSignedNumberString(value) {
return /^(0x)?[\dA-F]+$/i.test(value) || Number.isInteger(Number(value))
}

/**
* Check if value is a valid hex string.
*
Expand Down Expand Up @@ -315,11 +291,26 @@ async function getBoundsInteger(attribute, typeSize, isSigned) {
return {
min: attribute.min
? await getIntegerFromAttribute(attribute.min, typeSize, isSigned)
: null,
: getTypeRange(typeSize, isSigned, true),
max: attribute.max
? await getIntegerFromAttribute(attribute.max, typeSize, isSigned)
: null
: getTypeRange(typeSize, isSigned, false)
}
}

/**
* Gets the range of an integer type.
*
* @param {*} typeSize
* @param {*} isSigned
* @param {*} isMin
* @returns integer
*/
function getTypeRange(typeSize, isSigned, isMin) {
if (isMin) {
return isSigned ? -Math.pow(2, typeSize - 1) : 0
}
return isSigned ? Math.pow(2, typeSize - 1) - 1 : Math.pow(2, typeSize) - 1
}

/**
Expand Down
77 changes: 77 additions & 0 deletions test/validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,83 @@ test(
timeout.medium()
)

test('validate Attribute without min/max', async () => {
//Invalid default value
let fakeEndpointAttribute = { defaultValue: '300' }

let fakeAttribute = { type: 'int8u' }

let attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)

expect(attributeValidation.defaultValue.length == 1).toBeTruthy()
expect(
attributeValidation.defaultValue[0].includes('Out of range')
).toBeTruthy()

//Valid default value
fakeEndpointAttribute.defaultValue = '30'
attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)
expect(attributeValidation.defaultValue.length == 0).toBeTruthy()

//Invalid default value for enum16
fakeEndpointAttribute.defaultValue = '66000'
fakeAttribute.type = 'enum16'
attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)
expect(attributeValidation.defaultValue.length == 1).toBeTruthy()
expect(
attributeValidation.defaultValue[0].includes('Out of range')
).toBeTruthy()

//Valid default value for enum16
fakeEndpointAttribute.defaultValue = '65535'
attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)
expect(attributeValidation.defaultValue.length == 0).toBeTruthy()

//Invalid default value for bitmap8
fakeEndpointAttribute.defaultValue = '-2'
fakeAttribute.type = 'bitmap8'
attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)
expect(attributeValidation.defaultValue.length == 1).toBeTruthy()
expect(
attributeValidation.defaultValue[0].includes('Out of range')
).toBeTruthy()

//Valid default value for bitmap8
fakeEndpointAttribute.defaultValue = '255'
attributeValidation = await validation.validateSpecificAttribute(
fakeEndpointAttribute,
fakeAttribute,
db,
sid
)
expect(attributeValidation.defaultValue.length == 0).toBeTruthy()
})

test(
'validate endpoint test',
() => {
Expand Down

0 comments on commit 5289d6c

Please sign in to comment.