Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PICS grammar: Adjust for tooling #3

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
PICS grammar: Adjust for tooling
Changes the way the PICS conformances are rendered to match
with the expected grammar in the tooling.

- added new macros for PICS used in conformance statements
- removed otherwise conformances
- degrade P, D conformances to X
- fix grammar on not
- omit choice conformances with + / - / N
- change optional conformance to use PICS: O style
- changed macros to use the squished together styles

Still to do:
- command PICS
- split PICS into separate file so it can be generated
- check grammar with Agustin

For later:
I like screaming snake case better and not just beccause the name
is awesome. Let's use that, but we'd need to search/replace the
whole test plan.
  • Loading branch information
cecille committed Jul 5, 2024
commit b89d9309a6f268d0447b5e3b5259ab3c7c44bfe6
5 changes: 4 additions & 1 deletion testplan/attributes.go
Original file line number Diff line number Diff line change
@@ -39,13 +39,16 @@ func renderAttributes(doc *spec.Doc, cluster *matter.Cluster, b *strings.Builder
for i, name := range names {
b.WriteString(fmt.Sprintf(":PICS_S%-*s : {PICS_S}.A%04x({%s})\n", longest, name, i, name))
}
b.WriteRune('\n')
for i, name := range names {
b.WriteString(fmt.Sprintf(":PICS_S%-*s_CONFORMANCE : {PICS_S}.A%04x\n", longest, name, i))
}
b.WriteString("\n\n|===\n")
b.WriteString("| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*\n")
for i, a := range cluster.Attributes {
name := names[i]
b.WriteString(fmt.Sprintf("| {PICS_S%s} | {devimp} the _{%s}_ attribute?| ", name, name))
if len(a.Conformance) > 0 {
b.WriteString("{PICS_S}: ")
renderPicsConformance(b, doc, cluster, a.Conformance)
}
b.WriteString(" |\n")
76 changes: 48 additions & 28 deletions testplan/conformance.go
Original file line number Diff line number Diff line change
@@ -16,45 +16,65 @@ func renderPicsConformance(b *strings.Builder, doc *spec.Doc, cluster *matter.Cl
if len(cs) == 0 {
return
}
renderConformance(cs, b, doc, cluster, entityPICS)
renderConformance(cs, b, doc, cluster, entityPICSConformance)
}

func renderFeatureConformance(b *strings.Builder, doc *spec.Doc, cluster *matter.Cluster, cs conformance.Set) {
if len(cs) == 0 {
return
}
b.WriteString("{PICS_S}: ")
renderConformance(cs, b, doc, cluster, entityVariable)
}

func renderChoice(c *conformance.Optional, b *strings.Builder) {
// PICS tool does not support + style conformances, so unless this is a "pick one" choice,
//render as fully optional, we'll check the choice conformance properly in the tests.
o := conformance.ChoiceExactLimit{Limit: 1}
if c.Choice != nil && o.Equal(c.Choice.Limit) {
b.WriteRune('.')
b.WriteString(c.Choice.ASCIIDocString())
}
}

func renderConformance(cs conformance.Set, b *strings.Builder, doc *spec.Doc, cluster *matter.Cluster, formatter conformanceEntityFormatter) {
for _, c := range cs {
switch c := c.(type) {
case *conformance.Mandatory:
if c.Expression == nil {
b.WriteString("M")
continue
}
renderExpression(b, doc, cluster, c.Expression, formatter)
case *conformance.Optional:
if c.Expression == nil {
b.WriteString("O")
if c.Choice != nil {
b.WriteRune('.')
b.WriteString(c.Choice.ASCIIDocString())
}
continue
}
b.WriteRune('[')
renderExpression(b, doc, cluster, c.Expression, formatter)
b.WriteRune(']')
if c.Choice != nil {
b.WriteRune('.')
b.WriteString(c.Choice.ASCIIDocString())
}
// PICS tool can't handle otherwise conformances, so render anything with an otherwise conformance as optional for the purposes of the
// test plan PICS. This can be fully evaluated in the tests.
// The only exception is if it is provisional, which should be rendered as X.
if len(cs) != 1 {
switch cs[0].(type) {
case *conformance.Provisional:
b.WriteRune('X')
default:
b.WriteString(fmt.Sprintf("unknown conformance: %T", c))
b.WriteString("{PICS_S}: O")
}
return
}
switch c := cs[0].(type) {
case *conformance.Mandatory:
if c.Expression == nil {
b.WriteString("{PICS_S}: M")
return
}
renderExpression(b, doc, cluster, c.Expression, formatter)
case *conformance.Optional:
if c.Expression == nil {
b.WriteString("{PICS_S}: O")
renderChoice(c, b)
return
}
renderExpression(b, doc, cluster, c.Expression, formatter)
b.WriteString(": O")
renderChoice(c, b)
case *conformance.Provisional:
b.WriteRune('X')
case *conformance.Disallowed:
b.WriteRune('X')
case *conformance.Deprecated:
b.WriteRune('X')
case *conformance.Described:
b.WriteString("{PICS_S}: O")
default:
b.WriteString(fmt.Sprintf("unknown conformance: %T", c))
}
}

@@ -74,7 +94,7 @@ func renderExpression(b *strings.Builder, doc *spec.Doc, cluster *matter.Cluster
b.WriteString(renderReference(doc, exp.Reference, formatter))
case *conformance.LogicalExpression:
if exp.Not {
b.WriteRune('!')
b.WriteString("NOT")
}
b.WriteRune('(')
renderExpression(b, doc, cluster, exp.Left, formatter)
7 changes: 5 additions & 2 deletions testplan/events.go
Original file line number Diff line number Diff line change
@@ -31,15 +31,18 @@ func renderEvents(doc *spec.Doc, cluster *matter.Cluster, b *strings.Builder) {
}
b.WriteRune('\n')
for i, name := range names {
b.WriteString(fmt.Sprintf(":PICS_S%-*s : {PICS_S}.A%04x({%s})\n", longest, name, i, name))
b.WriteString(fmt.Sprintf(":PICS_S%-*s : {PICS_S}.E%02x({%s})\n", longest, name, i, name))
}
b.WriteRune('\n')
for i, name := range names {
b.WriteString(fmt.Sprintf(":PICS_S%-*s_CONFORMANCE : {PICS_S}.E%02x\n", longest, name, i))
}
b.WriteString("\n\n|===\n")
b.WriteString("| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*\n")
for i, event := range cluster.Events {
name := names[i]
b.WriteString(fmt.Sprintf("| {PICS_S%s} | {devimp} sending the _{%s}_ event?| ", name, name))
if len(event.Conformance) > 0 {
b.WriteString("{PICS_S}: ")
renderPicsConformance(b, doc, cluster, event.Conformance)
}
b.WriteString(" |\n")
7 changes: 6 additions & 1 deletion testplan/features.go
Original file line number Diff line number Diff line change
@@ -21,6 +21,11 @@ func renderFeatures(doc *spec.Doc, cluster *matter.Cluster, b *strings.Builder)
b.WriteString(fmt.Sprintf(":PICS_SF_%s: {PICS_S}.F%02d({F_%s})\n", f.Code, i, f.Code))
}
b.WriteRune('\n')
for i, bit := range cluster.Features.Bits {
f := bit.(*matter.Feature)
b.WriteString(fmt.Sprintf(":PICS_SF_%s_CONFORMANCE: {PICS_S}.F%02d\n", f.Code, i))
}
b.WriteRune('\n')
b.WriteString("|===\n")
b.WriteString("| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*\n")
for _, bit := range cluster.Features.Bits {
@@ -30,7 +35,7 @@ func renderFeatures(doc *spec.Doc, cluster *matter.Cluster, b *strings.Builder)
b.WriteString("} | {devsup} ")
b.WriteString(f.Summary())
b.WriteString(" | ")
renderFeatureConformance(b, doc, cluster, f.Conformance())
renderPicsConformance(b, doc, cluster, f.Conformance())
b.WriteString(" | \n")
}
b.WriteString("|===\n\n\n")
1 change: 1 addition & 0 deletions testplan/header.go
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ This section covers the {clustername} Cluster Test Plan related PICS items that
|===
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
| {PICS_S} | {devimp} the {clustername} cluster as a server? | O |
| {PICS_C} | {devimp} the {clustername} cluster as a client? | O |
|===

`
9 changes: 7 additions & 2 deletions testplan/identifiers.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package testplan

import (
"fmt"
"strings"

"github.com/iancoleman/strcase"
"github.com/project-chip/alchemy/matter"
@@ -12,6 +13,10 @@ func entityPICS(entity types.Entity) string {
return fmt.Sprintf("{PICS_S%s}", entityIdentifier(entity))
}

func entityPICSConformance(entity types.Entity) string {
return fmt.Sprintf("{PICS_S%s_CONFORMANCE}", entityIdentifier(entity))
}

func entityVariable(entity types.Entity) string {
return fmt.Sprintf("{%s}", entityIdentifier(entity))
}
@@ -21,12 +26,12 @@ func entityIdentifier(entity types.Entity) string {
case *matter.Field:
switch entity.EntityType() {
case types.EntityTypeAttribute:
return fmt.Sprintf("A_%s", strcase.ToScreamingSnake(entity.Name))
return fmt.Sprintf("A_%s", strings.ToUpper(strcase.ToCamel(entity.Name)))
}
case *matter.Feature:
return fmt.Sprintf("F_%s", entity.Code)
case *matter.Event:
return fmt.Sprintf("E_%s", strcase.ToScreamingSnake(entity.Name))
return fmt.Sprintf("E_%s", strings.ToUpper(strcase.ToCamel(entity.Name)))
}
return fmt.Sprintf("UNKNOWN_TYPE_%T", entity)
}