blob: 4f1a114b92b299ded65420aa4511a85e8bb243f4 [file] [log] [blame]
/**
*
* Copyright (c) 2020 Silicon Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* @jest-environment node
*/
const dbApi = require('../src-electron/db/db-api')
const dbEnum = require('../src-shared/db-enum')
const queryZcl = require('../src-electron/db/query-zcl')
const queryDeviceType = require('../src-electron/db/query-device-type')
const queryCommand = require('../src-electron/db/query-command')
const queryEvent = require('../src-electron/db/query-event')
const queryPackage = require('../src-electron/db/query-package')
const queryPackageNotification = require('../src-electron/db/query-package-notification')
const zclLoader = require('../src-electron/zcl/zcl-loader')
const env = require('../src-electron/util/env')
const types = require('../src-electron/util/types')
const testUtil = require('./test-util')
const testQuery = require('./test-query')
const fs = require('fs')
const genEngine = require('../src-electron/generator/generation-engine')
beforeAll(async () => {
env.setDevelopmentEnv()
})
test(
'test opening and closing the database',
async () => {
let db = await dbApi.initRamDatabase()
await dbApi.closeDatabase(db)
},
testUtil.timeout.medium()
)
test(
'test database schema loading in memory',
async () => {
let db = await dbApi.initRamDatabase()
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
await dbApi.closeDatabase(db)
},
testUtil.timeout.medium()
)
test(
'test Silabs zcl data loading in memory',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinSilabsZclMetafile())
let packageId = ctx.packageId
let packageNotif =
await queryPackageNotification.getNotificationByPackageId(db, packageId)
expect(
packageNotif.some((notif) =>
notif.message.includes('Duplicate command found')
)
).toBeTruthy() // checks if the correct duplicate command error is thrown
let p = await queryPackage.getPackageByPackageId(ctx.db, ctx.packageId)
expect(p.version).toEqual(1)
expect(p.description).toEqual('ZigbeePro test data')
expect(p.category).toEqual('zigbee')
let x = await queryPackage.getPackagesByType(
db,
dbEnum.packageType.zclProperties
)
expect(x.length).toEqual(1)
x = await queryZcl.selectAllClusters(db, packageId)
expect(x.length).toEqual(testUtil.totalClusterCount)
x = await queryZcl.selectAllDomains(db, packageId)
expect(x.length).toEqual(testUtil.totalDomainCount)
x = await queryZcl.selectAllEnums(db, packageId)
expect(x.length).toEqual(testUtil.totalEnumCount)
x = await queryZcl.selectAllStructsWithItems(db, [packageId])
expect(x.length).toEqual(54)
x = await queryZcl.selectAllBitmaps(db, packageId)
expect(x.length).toEqual(129)
x = await queryZcl.selectAllStrings(db, packageId)
x = x.map((item) => item.name)
let strings = [
'octet_string',
'char_string',
'long_octet_string',
'long_char_string'
]
expect(x.length).toEqual(4)
strings.forEach((s) => {
expect(x).toContain(s)
})
x = await queryDeviceType.selectAllDeviceTypes(db, packageId)
expect(x.length).toEqual(175)
x = await testQuery.selectCountFrom(db, 'COMMAND_ARG')
expect(x).toEqual(testUtil.totalCommandArgsCount)
x = await testQuery.selectCountFrom(db, 'COMMAND')
expect(x).toEqual(testUtil.totalCommandCount)
x = await testQuery.selectCountFrom(db, 'EVENT_FIELD')
expect(x).toEqual(testUtil.totalEventFieldCount)
x = await testQuery.selectCountFrom(db, 'EVENT')
expect(x).toEqual(testUtil.totalEventCount)
x = await testQuery.selectCountFrom(db, 'ENUM_ITEM')
expect(x).toEqual(testUtil.totalEnumItemCount)
x = await testQuery.selectCountFrom(db, 'ATTRIBUTE')
expect(x).toEqual(testUtil.totalAttributeCount)
x = await testQuery.selectCountFrom(db, 'BITMAP_FIELD')
expect(x).toEqual(726)
x = await testQuery.selectCountFrom(db, 'STRUCT_ITEM')
expect(x).toEqual(165)
x = await testQuery.selectCountFrom(db, 'GLOBAL_ATTRIBUTE_DEFAULT')
expect(x).toEqual(126)
x = await testQuery.selectCountFrom(db, 'SPEC')
expect(x).toEqual(testUtil.totalSpecCount)
x = await testQuery.selectCountFrom(db, 'TAG')
expect(x).toEqual(1)
x = await dbApi.dbAll(
db,
'SELECT MANUFACTURER_CODE FROM CLUSTER WHERE MANUFACTURER_CODE NOT NULL',
[]
)
expect(x.length).toEqual(5)
x = await dbApi.dbAll(
db,
'SELECT MANUFACTURER_CODE FROM COMMAND WHERE MANUFACTURER_CODE NOT NULL',
[]
)
expect(x.length).toEqual(58)
x = await dbApi.dbAll(
db,
'SELECT MANUFACTURER_CODE FROM ATTRIBUTE WHERE MANUFACTURER_CODE NOT NULL',
[]
)
expect(x.length).toEqual(30)
let rows = await dbApi.dbMultiSelect(
db,
'SELECT CLUSTER_ID FROM CLUSTER WHERE CODE = ?',
[[0], [6]]
)
expect(rows.length).toBe(2)
expect(rows[0]).not.toBeUndefined()
expect(rows[1]).not.toBeUndefined()
expect(rows[0].CLUSTER_ID).not.toBeUndefined()
expect(rows[1].CLUSTER_ID).not.toBeUndefined()
rows = await queryPackage.selectAllOptionsValues(
db,
packageId,
dbEnum.sessionOption.defaultResponsePolicy
)
expect(rows.length).toBe(3)
let commandTree = await queryCommand.selectCommandTree(db, [packageId])
let found = false
commandTree.forEach((c) => {
if (c.clusterCode == 0 && c.code == 0) found = true
})
expect(found).toBeTruthy()
x = await dbApi.dbAll(
db,
'SELECT DATA_TYPE.NAME AS NAME, BITMAP.BITMAP_ID, DATA_TYPE.PACKAGE_REF FROM BITMAP INNER JOIN DATA_TYPE ON BITMAP.BITMAP_ID = DATA_TYPE.DATA_TYPE_ID WHERE NAME IN (SELECT DATA_TYPE.NAME AS NAME FROM BITMAP INNER JOIN DATA_TYPE ON BITMAP.BITMAP_ID = DATA_TYPE.DATA_TYPE_ID GROUP BY NAME HAVING COUNT(*)>1)',
[]
)
x.forEach((c) => {
env.logWarning(
`Found Non Unique Bitmap in Silabs XML: ${c.NAME} ${c.TYPE} ${c.PACKAGE_REF}`
)
})
let attributes = await queryZcl.selectAllAttributes(db, [packageId])
expect(attributes.length).toBeGreaterThan(40)
let ps = []
attributes.forEach((a) => {
ps.push(types.typeSizeAttribute(db, [packageId], a))
})
x = await dbApi.dbAll(
db,
'SELECT DATA_TYPE.NAME, ENUM.ENUM_ID, DATA_TYPE.PACKAGE_REF FROM ENUM INNER JOIN DATA_TYPE ON ENUM.ENUM_ID = DATA_TYPE.DATA_TYPE_ID WHERE NAME IN (SELECT DATA_TYPE.NAME FROM ENUM INNER JOIN DATA_TYPE ON ENUM.ENUM_ID = DATA_TYPE.DATA_TYPE_ID GROUP BY DATA_TYPE.NAME HAVING COUNT(*)>1)',
[]
)
x.forEach((c) => {
env.logWarning(
`Found Non Unique Enum in Silabs XML: ${c.NAME} ${c.TYPE} ${c.PACKAGE_REF}`
)
})
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test changing xml file reloads all zcl packages',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(
db,
env.builtinSilabsZclSpecialMetafile()
)
let packageId = ctx.packageId
// Test Reloading of the zcl packages when an xml file changes
// (Simulating a gsdk upgrade from one branch to another which can change xml files)
// Step 1: Modify one of the xml files
let xmlFilePath = env.builtinSilabsSpecialZclGeneralSpecialXmlFile()
let originalString =
'<attribute side="server" code="0x0001" define="APPLICATION_VERSION" type="INT8U" min="0x00" max="0xFF" writable="false" default="0x00" optional="true">application version</attribute>'
let editString =
'<attribute side="server" code="0x0001" define="APPLICATION_VERSION" type="INT8U" min="0x00" max="0xFF" writable="false" default="0x01" optional="true">application version</attribute>'
let generalXmlFileOriginalContent = fs.readFileSync(xmlFilePath, 'utf8')
let generalXmlFileUpdatedContent = generalXmlFileOriginalContent.replace(
originalString,
editString
)
fs.writeFileSync(xmlFilePath, generalXmlFileUpdatedContent, 'utf8')
// Step 2: This will cause the all zcl packages from top level to all its
// children to be reloaded. Check for 2 top level packages with same path now.
// Count packages belonging to each top level package to make sure all packages
// are reloaded
ctx = await zclLoader.loadZcl(db, env.builtinSilabsZclSpecialMetafile())
let newPackageId = ctx.packageId
// Making sure the top level packages do not have the same packageId
expect(packageId).not.toEqual(newPackageId)
let oldPackages = await dbApi.dbAll(
db,
`SELECT * FROM PACKAGE WHERE PARENT_PACKAGE_REF = ${packageId}`
)
let newPackages = await dbApi.dbAll(
db,
`SELECT * FROM PACKAGE WHERE PARENT_PACKAGE_REF = ${newPackageId}`
)
// Making sure all packages are loaded again
expect(oldPackages.length).toEqual(newPackages.length)
let topLevelZclPackages = await dbApi.dbAll(
db,
`SELECT * FROM PACKAGE WHERE TYPE = '${dbEnum.packageType.zclProperties}' ORDER BY PACKAGE_ID`
)
expect(topLevelZclPackages[0].IS_IN_SYNC).toEqual(0)
expect(topLevelZclPackages[1].IS_IN_SYNC).toEqual(1)
// Step 3: Revert the xml file change in step 1.
fs.writeFileSync(xmlFilePath, generalXmlFileOriginalContent, 'utf8')
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test changing the zcl extension file in a top level templates json file and make sure it is re-loaded again',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let context = await genEngine.loadTemplates(
db,
testUtil.testTemplate.zigbee2
)
let existingPackageId = context.packageId
// Reload package
context = await genEngine.loadTemplates(db, testUtil.testTemplate.zigbee2)
expect(existingPackageId).toEqual(context.packageId)
let existingPackageDetails = await queryPackage.getPackageByPackageId(
db,
existingPackageId
)
expect(existingPackageDetails.isInSync).toEqual(1)
// Update the cluster-to-component.json extension file
let extensionFile =
testUtil.testTemplate.zclExtensionClusterToComponentFile
let originalString = '"clusterCode": "zll commissioning-server"'
let editString = '"clusterCode": "zll commissioningEdit-server"'
let generalExtensionFileOriginalContent = fs.readFileSync(
extensionFile,
'utf8'
)
let generalExtensionFileUpdatedContent =
generalExtensionFileOriginalContent.replace(originalString, editString)
fs.writeFileSync(
extensionFile,
generalExtensionFileUpdatedContent,
'utf8'
)
// Reload the templates json package after an extension file change above
context = await genEngine.loadTemplates(db, testUtil.testTemplate.zigbee2)
expect(existingPackageId).not.toEqual(context.packageId)
existingPackageDetails = await queryPackage.getPackageByPackageId(
db,
existingPackageId
)
// The old package should no longer be in sync
expect(existingPackageDetails.isInSync).toEqual(0)
let newPackageDetails = await queryPackage.getPackageByPackageId(
db,
context.packageId
)
// The new package should now be in sync
expect(newPackageDetails.isInSync).toEqual(1)
// Revert the zcl extension json file change which was done to run this test.
fs.writeFileSync(
extensionFile,
generalExtensionFileOriginalContent,
'utf8'
)
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test Dotdot zcl data loading in memory',
async () => {
let unmatched = []
let nullAttribute = []
let nonUniqueEnum = []
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinDotdotZclMetafile())
let packageId = ctx.packageId
let p = await queryPackage.getPackageByPackageId(ctx.db, packageId)
expect(p.version).toEqual(1)
let x = await queryPackage.getPackagesByType(
db,
dbEnum.packageType.zclProperties
)
expect(x.length).toEqual(1)
x = await queryZcl.selectAllClusters(db, packageId)
expect(x.length).toEqual(41)
x = await queryDeviceType.selectAllDeviceTypes(db, packageId)
expect(x.length).toEqual(108)
x = await testQuery.selectCountFrom(db, 'COMMAND_ARG')
expect(x).toEqual(644)
x = await testQuery.selectCountFrom(db, 'COMMAND')
expect(x).toEqual(238)
x = await testQuery.selectCountFrom(db, 'ATTRIBUTE')
expect(x).toEqual(630)
x = await queryZcl.selectAllAtomics(db, packageId)
expect(x.length).toEqual(56)
x = await queryZcl.selectAllStrings(db, packageId)
x = x.map((item) => item.name)
let strings = ['octstr', 'string', 'octstr16', 'string16']
expect(x.length).toEqual(5) // 5th string is a subatomic type
strings.forEach((s) => {
expect(x).toContain(s)
})
x = await queryZcl.selectAllBitmaps(db, packageId)
expect(x.length).toEqual(69)
x = await queryZcl.selectAllEnums(db, packageId)
expect(x.length).toEqual(testUtil.totalDotDotEnums)
x = await testQuery.selectCountFrom(db, 'ENUM_ITEM')
expect(x).toEqual(testUtil.totalDotDotEnumItems)
x = await queryZcl.selectAllStructsWithItemCount(db, [packageId])
expect(x.length).toEqual(20)
x = await testQuery.selectCountFrom(db, 'STRUCT_ITEM')
expect(x).toEqual(63)
//Do some checking on the device type metadata
x = await queryDeviceType.selectAllDeviceTypes(db, packageId)
x.forEach((d) => {
queryDeviceType
.selectDeviceTypeClustersByDeviceTypeRef(db, d.id)
.then((dc) => {
dc.forEach((dcr) => {
if (!dcr.clusterRef) {
unmatched.push(
`for ${d.caption} failed to match dcr ${dcr.clusterName}`
)
} else {
queryDeviceType
.selectDeviceTypeAttributesByDeviceTypeRef(
db,
dcr.deviceTypeRef
)
.then((dcas) => {
if (dcas.length > 0) {
dcas.forEach((dca) => {
if (!dca.attributeRef) {
nullAttribute.push(
`attributeRef for ${dca.attributeName} is NULL`
)
}
})
}
})
}
})
})
})
x = await dbApi.dbAll(
db,
'SELECT DATA_TYPE.NAME, ENUM.ENUM_ID, DATA_TYPE.PACKAGE_REF FROM ENUM INNER JOIN DATA_TYPE ON ENUM.ENUM_ID = DATA_TYPE.DATA_TYPE_ID WHERE NAME IN (SELECT DATA_TYPE.NAME FROM ENUM INNER JOIN DATA_TYPE ON ENUM.ENUM_ID = DATA_TYPE.DATA_TYPE_ID GROUP BY DATA_TYPE.NAME HAVING COUNT(*)>1)',
[]
)
x.forEach((c) => {
nonUniqueEnum.push(
`Found Non Unique Enum in Dotdot XML: ${c.NAME} ${c.TYPE} ${c.PACKAGE_REF}`
)
})
expect(nonUniqueEnum.length).toBe(0)
expect(unmatched.length).toBeGreaterThan(0)
expect(nullAttribute.length).toEqual(0)
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test Dotdot and Silabs zcl data loading in memory',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinSilabsZclMetafile())
let packageIdSilabs = ctx.packageId
let p = await queryPackage.getPackageByPackageId(ctx.db, packageIdSilabs)
expect(p.version).toEqual(1)
let rows = await queryPackage.getPackagesByType(
db,
dbEnum.packageType.zclProperties
)
expect(rows.length).toEqual(1)
ctx = await zclLoader.loadZcl(db, env.builtinDotdotZclMetafile())
let packageIdDotdot = ctx.packageId
p = await queryPackage.getPackageByPackageId(ctx.db, packageIdDotdot)
expect(p.version).toEqual(1)
rows = await queryPackage.getPackagesByType(
db,
dbEnum.packageType.zclProperties
)
expect(rows.length).toEqual(2)
let x = await dbApi.dbAll(
db,
'SELECT NAME, CODE, PACKAGE_REF FROM CLUSTER WHERE CODE IN (SELECT CODE FROM CLUSTER GROUP BY CODE HAVING COUNT(CODE)=1)',
[]
)
expect(x.length).toBeGreaterThan(0)
x = await dbApi.dbAll(
db,
'SELECT NAME, ATOMIC_IDENTIFIER, PACKAGE_REF FROM ATOMIC WHERE ATOMIC_IDENTIFIER IN (SELECT ATOMIC_IDENTIFIER FROM ATOMIC GROUP BY ATOMIC_IDENTIFIER HAVING COUNT(ATOMIC_IDENTIFIER)=1)',
[]
)
expect(x.length).toBeGreaterThan(0)
x = await dbApi.dbAll(
db,
'SELECT DATA_TYPE.NAME AS NAME, BITMAP.BITMAP_ID, DATA_TYPE.PACKAGE_REF FROM BITMAP INNER JOIN DATA_TYPE ON BITMAP.BITMAP_ID = DATA_TYPE.DATA_TYPE_ID WHERE NAME IN (SELECT DATA_TYPE.NAME AS NAME FROM BITMAP INNER JOIN DATA_TYPE ON BITMAP.BITMAP_ID = DATA_TYPE.DATA_TYPE_ID GROUP BY NAME HAVING COUNT(NAME)=1)',
[]
)
expect(x.length).toBeGreaterThan(0)
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test Matter zcl data loading in memory',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinMatterZclMetafile())
let packageId = ctx.packageId
let p = await queryPackage.getPackageByPackageId(ctx.db, packageId)
expect(p.version).toEqual(1)
let x = await queryPackage.getPackagesByType(
db,
dbEnum.packageType.zclProperties
)
expect(x.length).toEqual(1)
x = await queryZcl.selectAllClusters(db, packageId)
expect(x.length).toEqual(testUtil.totalMatterClusters)
x = await queryDeviceType.selectAllDeviceTypes(db, packageId)
expect(x.length).toEqual(testUtil.totalMatterDeviceTypes)
x = await testQuery.selectCountFrom(db, 'COMMAND_ARG')
expect(x).toEqual(testUtil.totalMatterCommandArgs)
x = await testQuery.selectCountFrom(db, 'COMMAND')
expect(x).toEqual(testUtil.totalMatterCommands)
x = await testQuery.selectCountFrom(db, 'ATTRIBUTE')
expect(x).toEqual(testUtil.totalMatterAttributes)
x = await testQuery.selectCountFrom(db, 'TAG')
expect(x).toEqual(testUtil.totalMatterTags)
x = await testQuery.selectCountFrom(db, 'EVENT')
expect(x).toEqual(testUtil.totalMatterEvents)
x = await testQuery.selectCountFrom(db, 'EVENT_FIELD')
expect(x).toEqual(testUtil.totalMatterEventFields)
x = await testQuery.selectCountFrom(db, 'GLOBAL_ATTRIBUTE_BIT')
expect(x).toBe(testUtil.totalMatterGlobalAttributeBits)
// Test for same named data type such that one is generic and the other
// is cluster specific. eg: SemanticTagStruct in xml
let structs = await dbApi.dbAll(
db,
`SELECT
*
FROM
DATA_TYPE
LEFT JOIN
DATA_TYPE_CLUSTER
ON
DATA_TYPE.DATA_TYPE_ID = DATA_TYPE_CLUSTER.DATA_TYPE_REF
WHERE
DATA_TYPE.NAME = 'SemanticTagStruct'`
)
expect(structs.length).toBe(2)
// Validate the generic struct
let genericStruct = structs.find((s) => s.CLUSTER_REF === null)
expect(genericStruct).not.toBeUndefined()
expect(genericStruct.NAME).toBe('SemanticTagStruct')
expect(genericStruct.CLUSTER_REF).toBeNull()
// Validate the cluster-specific struct
let clusterSpecificStruct = structs.find((s) => s.CLUSTER_REF !== null)
expect(clusterSpecificStruct).not.toBeUndefined()
expect(clusterSpecificStruct.NAME).toBe('SemanticTagStruct')
expect(clusterSpecificStruct.CLUSTER_REF).not.toBeNull()
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test Matter list-typed attribute loading in memory',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinMatterZclMetafile())
let packageId = ctx.packageId
let aclCluster = await queryZcl.selectClusterByCode(db, packageId, 0x001f)
/* Verify that the ACL attribute, defined using the list type format `array="true" type="X"` in XML,
is correctly parsed and stored in the database as an array of AccessControlEntryStruct. */
let attributes = await dbApi.dbAll(
db,
"SELECT * FROM ATTRIBUTE WHERE CLUSTER_REF = ? AND CODE = 0x0000 AND NAME = 'ACL'",
[aclCluster.id]
)
expect(attributes.length).toBe(1)
let aclAttribute = attributes[0]
expect(aclAttribute.TYPE).toBe('array')
expect(aclAttribute.ARRAY_TYPE).toBe('AccessControlEntryStruct')
// verify that the ACL attribute data retrieved from the database is an array of AccessControlEntryStruct after mapping
let aclAttributeMapped = await queryZcl.selectAttributeById(
db,
aclAttribute.ATTRIBUTE_ID
)
expect(aclAttributeMapped).not.toBe(null)
expect(aclAttributeMapped.name).toBe('ACL')
expect(aclAttributeMapped.entryType).toBe('AccessControlEntryStruct')
expect(aclAttributeMapped.isArray).toBe(1)
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)
test(
'test loading IS_OPTIONAL column for Matter attributes, commands, and events',
async () => {
let db = await dbApi.initRamDatabase()
try {
await dbApi.loadSchema(db, env.schemaFile(), env.zapVersion())
let ctx = await zclLoader.loadZcl(db, env.builtinMatterZclMetafile())
let packageId = ctx.packageId
let doorLockCluster = await queryZcl.selectClusterByCode(
db,
packageId,
0x0101
)
let doorLockClusterId = doorLockCluster.id
let attributes =
await queryZcl.selectAttributesByClusterIdIncludingGlobal(
db,
doorLockClusterId,
[packageId]
)
// optional attribute undefined, conformance undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(attributes, 'ActuatorEnabled')
).toBeFalsy()
// optional="true", conformance undefined -> optional
expect(
testQuery.checkIfElementIsOptional(attributes, 'DoorClosedEvents')
).toBeTruthy()
// optional="false", conformance undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(attributes, 'LockType')
).toBeFalsy()
// mandatory conformance, optional attribute undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(attributes, 'OperatingMode')
).toBeFalsy()
// optionalConform to feature DPS, optional="true" -> optional
expect(
testQuery.checkIfElementIsOptional(attributes, 'DoorOpenEvents')
).toBeTruthy()
// mandatory conformance, optional="true" -> optional as optional="true" takes precedence
expect(
testQuery.checkIfElementIsOptional(attributes, 'LockState')
).toBeTruthy()
// mandatoryConform to feature DPS, optional="false" -> mandatory as optional="false" takes precedence
expect(
testQuery.checkIfElementIsOptional(attributes, 'DoorState')
).toBeFalsy()
let commands = await queryCommand.selectCommandsByClusterId(
db,
doorLockClusterId,
[packageId]
)
// optional attribute undefined, conformance undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(commands, 'LockDoor')
).toBeFalsy()
// optional="true", conformance undefined -> optional
expect(
testQuery.checkIfElementIsOptional(commands, 'GetWeekDaySchedule')
).toBeTruthy()
// mandatory conformance, optional attribute undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(commands, 'UnlockDoor')
).toBeFalsy()
// mandatoryConform to feature WDSCH, optional="true" -> optional
expect(
testQuery.checkIfElementIsOptional(commands, 'SetWeekDaySchedule')
).toBeTruthy()
// optional conformance, optional="false" -> mandatory as optional="false" takes precedence
expect(
testQuery.checkIfElementIsOptional(commands, 'UnlockWithTimeout')
).toBeFalsy()
let events = await queryEvent.selectEventsByClusterId(
db,
doorLockClusterId
)
// optional attribute undefined, conformance undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(events, 'LockUserChange')
).toBeFalsy()
// optional="true", conformance undefined -> optional
expect(
testQuery.checkIfElementIsOptional(events, 'LockOperation')
).toBeTruthy()
// mandatory conformance, optional attribute undefined -> mandatory
expect(
testQuery.checkIfElementIsOptional(events, 'LockOperationError')
).toBeFalsy()
// mandatoryConform to feature DPS, optional="true" -> optional
expect(
testQuery.checkIfElementIsOptional(events, 'DoorStateChange')
).toBeTruthy()
// mandatory conformance, optional="true" -> optional as optional="true" takes precedence
expect(
testQuery.checkIfElementIsOptional(events, 'DoorLockAlarm')
).toBeTruthy()
} finally {
await dbApi.closeDatabase(db)
}
},
testUtil.timeout.long()
)