Skip to content

Commit 27937d8

Browse files
committed
Sync with Cecille's PR, but in handlebars format
#3
1 parent 8f1f1b1 commit 27937d8

File tree

9 files changed

+124
-54
lines changed

9 files changed

+124
-54
lines changed

testplan/conformance.go

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,34 +40,55 @@ func conformanceHelper(doc conformance.ReferenceStore, cluster matter.Cluster, c
4040
return raymond.SafeString(b.String())
4141
}
4242

43+
func renderChoice(c *conformance.Optional, b *strings.Builder) {
44+
// PICS tool does not support + style conformances, so unless this is a "pick one" choice,
45+
//render as fully optional, we'll check the choice conformance properly in the tests.
46+
o := conformance.ChoiceExactLimit{Limit: 1}
47+
if c.Choice != nil && o.Equal(c.Choice.Limit) {
48+
b.WriteRune('.')
49+
b.WriteString(c.Choice.ASCIIDocString())
50+
}
51+
}
52+
4353
func renderConformance(cs conformance.Set, b *strings.Builder, doc conformance.ReferenceStore, cluster *matter.Cluster, formatter conformanceEntityFormatter) {
44-
for _, c := range cs {
45-
switch c := c.(type) {
46-
case *conformance.Mandatory:
47-
if c.Expression == nil {
48-
b.WriteString("M")
49-
continue
50-
}
51-
renderExpression(b, doc, cluster, c.Expression, formatter)
52-
case *conformance.Optional:
53-
if c.Expression == nil {
54-
b.WriteString("O")
55-
if c.Choice != nil {
56-
b.WriteRune('.')
57-
b.WriteString(c.Choice.ASCIIDocString())
58-
}
59-
continue
60-
}
61-
b.WriteRune('[')
62-
renderExpression(b, doc, cluster, c.Expression, formatter)
63-
b.WriteRune(']')
64-
if c.Choice != nil {
65-
b.WriteRune('.')
66-
b.WriteString(c.Choice.ASCIIDocString())
67-
}
54+
// PICS tool can't handle otherwise conformances, so render anything with an otherwise conformance as optional for the purposes of the
55+
// test plan PICS. This can be fully evaluated in the tests.
56+
// The only exception is if it is provisional, which should be rendered as X.
57+
if len(cs) != 1 {
58+
switch cs[0].(type) {
59+
case *conformance.Provisional:
60+
b.WriteRune('X')
6861
default:
69-
b.WriteString(fmt.Sprintf("unknown conformance: %T", c))
62+
b.WriteString("{PICS_S}: O")
63+
}
64+
return
65+
}
66+
switch c := cs[0].(type) {
67+
case *conformance.Mandatory:
68+
if c.Expression == nil {
69+
b.WriteString("{PICS_S}: M")
70+
return
7071
}
72+
renderExpression(b, doc, cluster, c.Expression, formatter)
73+
case *conformance.Optional:
74+
if c.Expression == nil {
75+
b.WriteString("{PICS_S}: O")
76+
renderChoice(c, b)
77+
return
78+
}
79+
renderExpression(b, doc, cluster, c.Expression, formatter)
80+
b.WriteString(": O")
81+
renderChoice(c, b)
82+
case *conformance.Provisional:
83+
b.WriteRune('X')
84+
case *conformance.Disallowed:
85+
b.WriteRune('X')
86+
case *conformance.Deprecated:
87+
b.WriteRune('X')
88+
case *conformance.Described:
89+
b.WriteString("{PICS_S}: O")
90+
default:
91+
b.WriteString(fmt.Sprintf("unknown conformance: %T", c))
7192
}
7293
}
7394

@@ -87,7 +108,7 @@ func renderExpression(b *strings.Builder, doc conformance.ReferenceStore, cluste
87108
b.WriteString(renderReference(doc, exp.Reference, formatter))
88109
case *conformance.LogicalExpression:
89110
if exp.Not {
90-
b.WriteRune('!')
111+
b.WriteString("NOT")
91112
}
92113
b.WriteRune('(')
93114
renderExpression(b, doc, cluster, exp.Left, formatter)

testplan/generate.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,20 @@ import (
2020
"github.com/project-chip/alchemy/matter/types"
2121
)
2222

23+
type GeneratorOption func(g *Generator)
24+
2325
type Generator struct {
2426
testPlanRoot string
27+
templateRoot string
2528
overwrite bool
2629
}
2730

31+
func TemplateRoot(templateRoot string) func(*Generator) {
32+
return func(g *Generator) {
33+
g.templateRoot = templateRoot
34+
}
35+
}
36+
2837
func (sp Generator) Name() string {
2938
return "Generating test plans"
3039
}
@@ -46,7 +55,7 @@ func (sp *Generator) Process(cxt context.Context, input *pipeline.Data[*spec.Doc
4655
destinations := buildDestinations(sp.testPlanRoot, entities, doc.Errata().TestPlan)
4756

4857
var t *raymond.Template
49-
t, err = loadTemplate()
58+
t, err = sp.loadTemplate()
5059
if err != nil {
5160
return
5261
}
@@ -100,8 +109,12 @@ func (sp *Generator) Process(cxt context.Context, input *pipeline.Data[*spec.Doc
100109
return
101110
}
102111

103-
func NewGenerator(testPlanRoot string, overwrite bool) *Generator {
104-
return &Generator{testPlanRoot: testPlanRoot, overwrite: overwrite}
112+
func NewGenerator(testPlanRoot string, overwrite bool, options ...GeneratorOption) *Generator {
113+
g := &Generator{testPlanRoot: testPlanRoot, overwrite: overwrite}
114+
for _, o := range options {
115+
o(g)
116+
}
117+
return g
105118
}
106119

107120
func getTestPlanPath(testplanRoot string, name string) string {
@@ -133,20 +146,25 @@ func buildDestinations(testplanRoot string, entities []types.Entity, errata erra
133146
switch e := e.(type) {
134147
case *matter.ClusterGroup:
135148
for _, c := range e.Clusters {
136-
fileName := strings.ToLower(strcase.ToSnake(c.Name))
137-
newPath := getTestPlanPath(testplanRoot, fileName)
138-
destinations[newPath] = c
149+
destinations[getTestPlanPathForCluster(testplanRoot, c, errata)] = c
139150
}
140151
case *matter.Cluster:
141-
var newPath string
142-
if errata.TestPlanPath != "" {
143-
newPath = filepath.Join(testplanRoot, errata.TestPlanPath)
144-
} else {
145-
newPath = getTestPlanPath(testplanRoot, strings.ToLower(strcase.ToSnake(e.Name)))
146-
}
147-
destinations[newPath] = e
152+
destinations[getTestPlanPathForCluster(testplanRoot, e, errata)] = e
148153
}
149154
}
150155
return
151156

152157
}
158+
159+
func getTestPlanPathForCluster(testplanRoot string, cluster *matter.Cluster, errata errata.TestPlan) string {
160+
if len(errata.TestPlanPaths) > 0 {
161+
tpp, ok := errata.TestPlanPaths[cluster.Name]
162+
if ok {
163+
return filepath.Join(testplanRoot, tpp.Path)
164+
}
165+
}
166+
if errata.TestPlanPath != "" {
167+
return filepath.Join(testplanRoot, errata.TestPlanPath)
168+
}
169+
return getTestPlanPath(testplanRoot, strings.ToLower(strcase.ToSnake(cluster.Name)))
170+
}

testplan/identifiers.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package testplan
22

33
import (
44
"fmt"
5+
"strings"
56

6-
"github.com/iancoleman/strcase"
77
"github.com/mailgun/raymond/v2"
88
"github.com/project-chip/alchemy/internal/handlebars"
99
"github.com/project-chip/alchemy/matter"
@@ -23,14 +23,14 @@ func entityIdentifier(entity types.Entity) string {
2323
case *matter.Field:
2424
switch entity.EntityType() {
2525
case types.EntityTypeAttribute:
26-
return fmt.Sprintf("A_%s", strcase.ToScreamingSnake(entity.Name))
26+
return fmt.Sprintf("A_%s", strings.ToUpper(matter.CaseWithSeparator(entity.Name, '_')))
2727
}
2828
case *matter.Feature:
2929
return fmt.Sprintf("F_%s", entity.Code)
3030
case *matter.Event:
31-
return fmt.Sprintf("E_%s", strcase.ToScreamingSnake(entity.Name))
31+
return fmt.Sprintf("E_%s", strings.ToUpper(matter.CaseWithSeparator(entity.Name, '_')))
3232
case *matter.Command:
33-
return fmt.Sprintf("C_%s", strcase.ToScreamingSnake(entity.Name))
33+
return fmt.Sprintf("C_%s", strings.ToUpper(matter.CaseWithSeparator(entity.Name, '_')))
3434
}
3535
return fmt.Sprintf("UNKNOWN_TYPE_%T", entity)
3636
}
@@ -50,6 +50,18 @@ func entityIdentifierPaddedHelper(list any, entity types.Entity) raymond.SafeStr
5050
return raymond.SafeString(fmt.Sprintf("%-*s", longest, entityIdentifier(entity)))
5151
}
5252

53+
func entityIdentifierPaddingHelper(list any, entity types.Entity) raymond.SafeString {
54+
var longest int
55+
for entity := range handlebars.Iterate[types.Entity](list) {
56+
id := entityIdentifier(entity)
57+
if len(id) > longest {
58+
longest = len(id)
59+
}
60+
}
61+
id := entityIdentifier(entity)
62+
return raymond.SafeString(strings.Repeat(" ", longest-len(id)))
63+
}
64+
5365
func idHelper(id matter.Number, options *raymond.Options) raymond.SafeString {
5466
format := options.HashStr("format")
5567
if format == "" {

testplan/template.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package testplan
33
import (
44
"embed"
55
"fmt"
6+
"io/fs"
67
"path/filepath"
78
"strings"
89

@@ -21,9 +22,12 @@ type templateContext struct {
2122
ReferenceStore conformance.ReferenceStore
2223
}
2324

24-
func loadTemplate() (*raymond.Template, error) {
25+
func (sp *Generator) loadTemplate() (*raymond.Template, error) {
2526
t, err := template.Do(func() (*raymond.Template, error) {
26-
files, err := templateFiles.ReadDir("templates")
27+
28+
ov := handlebars.NewOverlay(sp.templateRoot, templateFiles)
29+
30+
files, err := ov.ReadDir("templates")
2731
if err != nil {
2832
return nil, err
2933
}
@@ -43,6 +47,7 @@ func loadTemplate() (*raymond.Template, error) {
4347
t.RegisterHelper("shortId", shortIdHelper)
4448
t.RegisterHelper("entityId", entityIdentifierHelper)
4549
t.RegisterHelper("entityIdPadded", entityIdentifierPaddedHelper)
50+
t.RegisterHelper("entityIdPadding", entityIdentifierPaddingHelper)
4651
t.RegisterHelper("dataType", dataTypeHelper)
4752
t.RegisterHelper("dataTypeArticle", dataTypeArticleHelper)
4853
t.RegisterHelper("ifHasQuality", ifHasQualityHelper)
@@ -57,7 +62,7 @@ func loadTemplate() (*raymond.Template, error) {
5762
continue
5863
}
5964
name := file.Name()
60-
val, err := templateFiles.ReadFile(filepath.Join("templates/", name))
65+
val, err := fs.ReadFile(ov, filepath.Join("templates/", name))
6166
if err != nil {
6267
return nil, fmt.Errorf("error reading template file %s: %w", name, err)
6368
}

testplan/templates/attributes.handlebars

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@
88

99

1010
{{#each attributes}}
11-
:PICS_S{{entityIdPadded attributes this}} : {PICS_S}.A{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
11+
:PICS_S{{id this.ID}}{{entityIdPadding attributes this}} : {PICS_S}.A{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
12+
{{/each}}
13+
14+
15+
{{#each attributes}}
16+
:PICS_S{{id this.ID}}_CONFORMANCE{{entityIdPadding attributes this}} : {PICS_S}.A{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
1217
{{/each}}
1318

1419

1520
|===
1621
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
1722
{{#each attributes}}
18-
| {{#brace}}PICS_S{{entityId this}}{{/brace}}| {devimp} the _{{#brace}}{{entityId this}}{{/brace}}_ attribute?| {{#if this.conformance}}{PICS_S}: {{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
23+
| {{#brace}}PICS_S{{entityId this}}{{/brace}}| {devimp} the _{{#brace}}{{entityId this}}{{/brace}}_ attribute?| {{#if this.conformance}}{{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
1924
{{/each}}
2025
|===
2126

testplan/templates/commands.handlebars

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
|===
1515
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
1616
{{#each commandsAccepted}}
17-
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} the _{{#brace}}{{entityId this}}{{/brace}}_ command?| {{#if this.conformance}}{PICS_S}: {{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
17+
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} the _{{#brace}}{{entityId this}}{{/brace}}_ command?| {{#if this.conformance}}{{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
1818
{{/each}}
1919
|===
2020

@@ -35,7 +35,7 @@
3535
|===
3636
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
3737
{{#each commandsGenerated}}
38-
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} sending the _{{#brace}}{{entityId this}}{{/brace}}_ command?| {{#if this.conformance}}{PICS_S}: {{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
38+
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} sending the _{{#brace}}{{entityId this}}{{/brace}}_ command?| {{#if this.conformance}}{{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
3939
{{/each}}
4040
|===
4141

testplan/templates/events.handlebars

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33

44

55
{{#each events}}
6-
:{{entityIdPadded events this}}: {{raw this.Name}}
6+
:{{entityId this}}{{entityIdPadding events this}}: {{raw this.Name}}
77
{{/each}}
88

99
{{#each events}}
10-
:PICS_S{{entityIdPadded events this}} : {PICS_S}.E{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
10+
:PICS_S{{entityId this}}{{entityIdPaddin events this}} : {PICS_S}.E{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
11+
{{/each}}
12+
13+
{{#each events}}
14+
:PICS_S{{entityId this}}_CONFORMANCE{{entityIdPaddin events this}} : {PICS_S}.E{{id this.ID}}({{#brace}}{{entityId this}}{{/brace}})
1115
{{/each}}
1216

1317
|===
1418
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
1519
{{#each events}}
16-
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} sending the _{{#brace}}{{entityId this}}{{/brace}}_ event?| {{#if this.conformance}}{PICS_S}: {{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
20+
| {{#brace}}PICS_S{{entityId this}}{{/brace}} | {devimp} sending the _{{#brace}}{{entityId this}}{{/brace}}_ event?| {{#if this.conformance}}{{picsConformance context.referenceStore cluster this.conformance}}{{/if}} |
1721
{{/each}}
1822
|===
1923

testplan/templates/features.handlebars

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@
1010
:PICS_SF_{{raw this.Code}}: {PICS_S}.F{{format @index "%02d"}}({{#brace}}F_{{raw this.Code}}{{/brace}})
1111
{{/each}}
1212

13+
{{#each features}}
14+
:PICS_SF_{{raw this.Code}}_CONFORMANCE: {PICS_S}.F{{format @index "%02d"}}({{#brace}}F_{{raw this.Code}}{{/brace}})
15+
{{/each}}
16+
1317
|===
1418
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
1519
{{#each features}}
1620
| {PICS_SF_{{raw this.Code ~}}
17-
} | {devsup} | {{raw this.Summary}} | {{#if this.Conformance}}{PICS_S}: {{conformance context.referenceStore cluster this.Conformance}}{{/if}}
21+
} | {devsup} | {{raw this.Summary}} | {{#if this.Conformance}}{{conformance context.referenceStore cluster this.Conformance}}{{/if}}
1822
{{/each}}
1923
|===
2024

testplan/templates/test_plan.handlebars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ This section covers the {clustername} Cluster Test Plan related PICS items that
3232
|===
3333
| *Variable* | *Description* | *Mandatory/Optional* | *Notes/Additional Constraints*
3434
| {PICS_S} | {devimp} the {clustername} cluster as a server? | O |
35+
| {PICS_C} | {devimp} the {clustername} cluster as a client? | O |
3536
|===
3637

3738
=== Server

0 commit comments

Comments
 (0)