Skip to content

Commit d814b12

Browse files
authored
Handling struct items properly when we have a global and cluster specific struct with the same name (#1557)
- Fixed the zcl_struct_items_by_struct_and_cluster_name helper for this global vs cluster specific struct items - Added tests for it - Github: ZAP#1551
1 parent eceeced commit d814b12

File tree

7 files changed

+125
-61
lines changed

7 files changed

+125
-61
lines changed

docs/sdk-integration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ The `templates` key contained in the `gen-templates.json` file above, is an arra
8282

8383
The _replacement pattern_ inside the output key, comes handy when iterator key is used and defines how each generated file will be named. Replacement patterns are in a format of `{key}` or `{key:modifier}`. The `key` can be any usual key that the iterated object provides. For example, if you iterate over cluster, these can be `code`, `name`, `description`, `define` and all the usual keys that a cluster supports. So if your output contains `{code}` then this pattern will be replaced by the actual cluster code.
8484

85-
The modifier can be one of the following: `hexuppercase`, `hexlowercase`, `tolowercase`, `touppercase`, `tocamelcase`, `tosnakecase` aor `tosnakecaseallcaps`.
85+
The modifier can be one of the following: `hexuppercase`, `hexlowercase`, `tolowercase`, `touppercase`, `tocamelcase`, `tosnakecase` or `tosnakecaseallcaps`.
8686

8787
## Templates key: options
8888

src-electron/db/db-mapping.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ exports.map = {
357357
isFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
358358
caption: `Struct, named ${x.NAME}`,
359359
structClusterCount: x.STRUCT_CLUSTER_COUNT,
360+
structCount: x.STRUCT_COUNT,
360361
clusterName: x.CLUSTER_NAME,
361362
apiMaturity: x.API_MATURITY
362363
}

src-electron/db/query-struct.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ WHERE
9595
* @returns Promise of Struct
9696
*/
9797
async function selectStructByName(db, name, packageIds) {
98+
//STRUCT_COUNT counts the structs where there could be one global and one cluster specific with same name.
9899
return dbApi
99100
.dbGet(
100101
db,
@@ -105,6 +106,7 @@ SELECT
105106
STRUCT.API_MATURITY,
106107
DATA_TYPE.NAME,
107108
(SELECT COUNT(1) FROM DATA_TYPE_CLUSTER WHERE DATA_TYPE_CLUSTER.DATA_TYPE_REF = STRUCT.STRUCT_ID) AS STRUCT_CLUSTER_COUNT,
109+
(SELECT COUNT(1) FROM STRUCT INNER JOIN DATA_TYPE ON STRUCT.STRUCT_ID = DATA_TYPE.DATA_TYPE_ID WHERE DATA_TYPE.NAME = "${name}" AND PACKAGE_REF IN (${dbApi.toInClause(packageIds)})) AS STRUCT_COUNT,
108110
DATA_TYPE.DISCRIMINATOR_REF
109111
FROM
110112
STRUCT

src-electron/db/query-zcl.js

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -498,66 +498,73 @@ async function selectAllStructItemsByStructName(
498498
packageIds,
499499
clusterName = null
500500
) {
501-
let clusterJoinQuery = ''
502-
let clusterWhereQuery = ''
501+
let clusterCondition = clusterName
502+
? `CLUSTER.NAME = "${clusterName}"`
503+
: `CLUSTER.NAME IS NULL`
504+
505+
let structItemQuery = `
506+
SELECT
507+
SI.FIELD_IDENTIFIER,
508+
SI.NAME,
509+
(SELECT DATA_TYPE.NAME FROM DATA_TYPE WHERE DATA_TYPE.DATA_TYPE_ID = SI.DATA_TYPE_REF) AS TYPE,
510+
DT.NAME AS DATA_TYPE_REF_NAME,
511+
DISCRIMINATOR.NAME AS DISCRIMINATOR_NAME,
512+
SI.STRUCT_REF,
513+
SI.IS_ARRAY,
514+
SI.IS_ENUM,
515+
SI.MIN_LENGTH,
516+
SI.MAX_LENGTH,
517+
SI.IS_WRITABLE,
518+
SI.IS_NULLABLE,
519+
SI.IS_OPTIONAL,
520+
SI.IS_FABRIC_SENSITIVE,
521+
SI.DATA_TYPE_REF
522+
FROM
523+
STRUCT_ITEM AS SI
524+
INNER JOIN
525+
STRUCT
526+
ON
527+
STRUCT.STRUCT_ID = SI.STRUCT_REF
528+
INNER JOIN
529+
DATA_TYPE AS DT
530+
ON
531+
DT.DATA_TYPE_ID = STRUCT.STRUCT_ID
532+
LEFT JOIN
533+
DATA_TYPE_CLUSTER
534+
ON
535+
DATA_TYPE_CLUSTER.DATA_TYPE_REF = DT.DATA_TYPE_ID
536+
LEFT JOIN
537+
CLUSTER
538+
ON
539+
DATA_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
540+
INNER JOIN
541+
DISCRIMINATOR
542+
ON
543+
DT.DISCRIMINATOR_REF = DISCRIMINATOR.DISCRIMINATOR_ID
544+
WHERE
545+
DT.NAME = ?
546+
AND
547+
DT.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
548+
AND
549+
${clusterCondition}
550+
ORDER BY FIELD_IDENTIFIER`
551+
552+
let rows = []
553+
// Attempt to retrieve struct items with given cluster name
503554
if (clusterName) {
504-
clusterJoinQuery = `
505-
INNER JOIN
506-
DATA_TYPE_CLUSTER
507-
ON
508-
DATA_TYPE_CLUSTER.DATA_TYPE_REF = DT.DATA_TYPE_ID
509-
INNER JOIN
510-
CLUSTER
511-
ON
512-
DATA_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
513-
`
514-
clusterWhereQuery = `
515-
AND
516-
CLUSTER.NAME = "${clusterName}"
517-
`
555+
rows = await dbApi.dbAll(db, structItemQuery, [name])
518556
}
519-
return dbApi
520-
.dbAll(
521-
db,
522-
`
523-
SELECT
524-
SI.FIELD_IDENTIFIER,
525-
SI.NAME,
526-
(SELECT DATA_TYPE.NAME FROM DATA_TYPE WHERE DATA_TYPE.DATA_TYPE_ID = SI.DATA_TYPE_REF) AS TYPE,
527-
DT.NAME AS DATA_TYPE_REF_NAME,
528-
DISCRIMINATOR.NAME AS DISCRIMINATOR_NAME,
529-
SI.STRUCT_REF,
530-
SI.IS_ARRAY,
531-
SI.IS_ENUM,
532-
SI.MIN_LENGTH,
533-
SI.MAX_LENGTH,
534-
SI.IS_WRITABLE,
535-
SI.IS_NULLABLE,
536-
SI.IS_OPTIONAL,
537-
SI.IS_FABRIC_SENSITIVE,
538-
SI.DATA_TYPE_REF
539-
FROM
540-
STRUCT_ITEM AS SI
541-
INNER JOIN
542-
STRUCT
543-
ON
544-
STRUCT.STRUCT_ID = SI.STRUCT_REF
545-
INNER JOIN
546-
DATA_TYPE AS DT
547-
ON
548-
DT.DATA_TYPE_ID = STRUCT.STRUCT_ID
549-
${clusterJoinQuery}
550-
INNER JOIN
551-
DISCRIMINATOR
552-
ON
553-
DT.DISCRIMINATOR_REF = DISCRIMINATOR.DISCRIMINATOR_ID
554-
WHERE DT.NAME = ?
555-
AND DT.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
556-
${clusterWhereQuery}
557-
ORDER BY FIELD_IDENTIFIER`,
558-
[name]
557+
558+
// If no rows were found then find a global struct by turning cluster name to null
559+
if (rows.length === 0) {
560+
structItemQuery = structItemQuery.replace(
561+
clusterCondition,
562+
`CLUSTER.NAME IS NULL`
559563
)
560-
.then((rows) => rows.map(dbMapping.map.structItem))
564+
rows = await dbApi.dbAll(db, structItemQuery, [name])
565+
}
566+
567+
return rows.map(dbMapping.map.structItem)
561568
}
562569

563570
/**

src-electron/generator/helper-zcl.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ async function zcl_struct_items_by_struct_and_cluster_name(
348348
name,
349349
packageIds
350350
)
351-
if (structObj.structClusterCount == 0) {
351+
352+
if (structObj.structClusterCount == 0 && structObj.structCount == 1) {
352353
// Just ignore the cluster name.
353354
return zcl_struct_items_by_struct_name.call(this, name, options)
354355
}

test/gen-matter-3-1.test.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,50 @@ test(
477477
expect(ept).toContain(
478478
'TargetStruct item 4 from Binding cluster: FabricIndex'
479479
)
480-
481480
expect(ept).toContain('Struct with array: NestedStructList')
482481
expect(ept).toContain('Struct with array: DoubleNestedStructList')
482+
483+
// Mode Select SemanticTagStruct items not giving global SemanticTagStruct struct items
484+
expect(ept).toContain(
485+
'SemanticTagStruct item 0 from Mode Select cluster: MfgCode'
486+
)
487+
expect(ept).toContain(
488+
'SemanticTagStruct item 1 from Mode Select cluster: Value'
489+
)
490+
expect(ept).not.toContain(
491+
'SemanticTagStruct item 2 from Mode Select cluster'
492+
)
493+
expect(ept).not.toContain('SemanticTagStruct item 2 from Mode Select')
494+
495+
// global SemanticTagStruct struct items not giving Mode Select SemanticTagStruct items
496+
// In this case Descriptor cluster is using the global struct
497+
expect(ept).toContain(
498+
'SemanticTagStruct item 0 from Descriptor cluster: MfgCode'
499+
)
500+
expect(ept).toContain(
501+
'SemanticTagStruct item 1 from Descriptor cluster: NamespaceID'
502+
)
503+
expect(ept).toContain(
504+
'SemanticTagStruct item 2 from Descriptor cluster: Tag'
505+
)
506+
expect(ept).toContain(
507+
'SemanticTagStruct item 3 from Descriptor cluster: Label'
508+
)
509+
expect(ept).not.toContain(
510+
'SemanticTagStruct item 4 from Descriptor cluster'
511+
)
512+
// Checking with Identify cluster too
513+
expect(ept).toContain(
514+
'SemanticTagStruct item 0 from Identify cluster: MfgCode'
515+
)
516+
expect(ept).toContain(
517+
'SemanticTagStruct item 1 from Identify cluster: NamespaceID'
518+
)
519+
expect(ept).toContain('SemanticTagStruct item 2 from Identify cluster: Tag')
520+
expect(ept).toContain(
521+
'SemanticTagStruct item 3 from Identify cluster: Label'
522+
)
523+
expect(ept).not.toContain('SemanticTagStruct item 4 from Identify cluster')
483524
},
484525
testUtil.timeout.long()
485526
)
@@ -706,7 +747,7 @@ test(
706747
commandNames.push(commandName['NAME'])
707748
}
708749
}
709-
console.log('BHarat test commands: ' + JSON.stringify(commandNames))
750+
710751
// Verify specific commands from the extension
711752
expect(commandNames).toContain('ReviewFabricRestrictions')
712753

test/gen-template/matter3/miscellaneous_helper_tests.zapt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ TargetStruct item {{index}} from Access Control cluster: {{name}}
3030
TargetStruct item {{index}} from Binding cluster: {{name}}
3131
{{/zcl_struct_items_by_struct_and_cluster_name}}
3232

33+
{{#zcl_struct_items_by_struct_and_cluster_name "SemanticTagStruct" "Mode Select"}}
34+
SemanticTagStruct item {{index}} from Mode Select cluster: {{name}}
35+
{{/zcl_struct_items_by_struct_and_cluster_name}}
36+
37+
{{#zcl_struct_items_by_struct_and_cluster_name "SemanticTagStruct" "Descriptor"}}
38+
SemanticTagStruct item {{index}} from Descriptor cluster: {{name}}
39+
{{/zcl_struct_items_by_struct_and_cluster_name}}
40+
41+
{{#zcl_struct_items_by_struct_and_cluster_name "SemanticTagStruct" "Identify"}}
42+
SemanticTagStruct item {{index}} from Identify cluster: {{name}}
43+
{{/zcl_struct_items_by_struct_and_cluster_name}}
44+
3345
{{#zcl_structs}}
3446
{{#if struct_contains_array}} Struct with array: {{name}}
3547
{{/if}}

0 commit comments

Comments
 (0)