Skip to content

Commit d8028b6

Browse files
committed
fix: update ValidateBricks to return all validation errors as a slice and adjust related tests
1 parent 3708460 commit d8028b6

File tree

2 files changed

+49
-39
lines changed

2 files changed

+49
-39
lines changed

internal/orchestrator/app/parser.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,35 +141,35 @@ func (a *AppDescriptor) IsValid() error {
141141

142142
// ValidateBricks checks that all bricks referenced in the given AppDescriptor exist in the provided BricksIndex,
143143
// and that all required variables for each brick are present and valid. It collects and returns all validation
144-
// errors found, allowing the caller to see all issues at once rather than stopping at the first error.
144+
// errors found as a slice, allowing the caller to see all issues at once rather than stopping at the first error.
145145
// If the index is nil, validation is skipped and nil is returned.
146-
func (a *AppDescriptor) ValidateBricks(index *bricksindex.BricksIndex) error {
146+
func (a *AppDescriptor) ValidateBricks(index *bricksindex.BricksIndex) []error {
147147
if index == nil {
148148
return nil
149149
}
150150

151-
var allErrors error
151+
var allErrors []error
152152

153153
for _, appBrick := range a.Bricks {
154154
indexBrick, found := index.FindBrickByID(appBrick.ID)
155155
if !found {
156-
allErrors = errors.Join(allErrors, fmt.Errorf("brick %q not found", appBrick.ID))
156+
allErrors = append(allErrors, fmt.Errorf("brick %q not found", appBrick.ID))
157157
continue // Skip further validation for this brick since it doesn't exist
158158
}
159159

160160
// Check that all app variables exist in brick definition
161161
for appBrickName := range appBrick.Variables {
162162
_, exist := indexBrick.GetVariable(appBrickName)
163163
if !exist {
164-
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID))
164+
allErrors = append(allErrors, fmt.Errorf("variable %q does not exist on brick %q", appBrickName, indexBrick.ID))
165165
}
166166
}
167167

168168
// Check that all required brick variables are provided by app
169169
for _, indexBrickVariable := range indexBrick.Variables {
170170
if indexBrickVariable.IsRequired() {
171171
if _, exist := appBrick.Variables[indexBrickVariable.Name]; !exist {
172-
allErrors = errors.Join(allErrors, fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID))
172+
allErrors = append(allErrors, fmt.Errorf("variable %q is required by brick %q", indexBrickVariable.Name, indexBrick.ID))
173173
}
174174
}
175175
}

internal/orchestrator/app/validator_test.go

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package app
22

33
import (
4+
"errors"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
78
"github.com/stretchr/testify/require"
8-
"go.bug.st/f"
99

1010
"github.com/arduino/go-paths-helper"
1111

@@ -18,49 +18,58 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
1818
require.NotNil(t, bricksIndex)
1919

2020
testCases := []struct {
21-
name string
22-
filename string
23-
expectedErr *string
21+
name string
22+
filename string
23+
expectedErrors []error // Now expecting a slice of error messages
2424
}{
2525
{
26-
name: "valid with all required filled",
27-
filename: "all-required-app.yaml",
28-
expectedErr: nil,
26+
name: "valid with all required filled",
27+
filename: "all-required-app.yaml",
28+
expectedErrors: nil,
2929
},
3030
{
31-
name: "valid with missing bricks",
32-
filename: "no-bricks-app.yaml",
33-
expectedErr: nil,
31+
name: "valid with missing bricks",
32+
filename: "no-bricks-app.yaml",
33+
expectedErrors: nil,
3434
},
3535
{
36-
name: "valid with empty list of bricks",
37-
filename: "empty-bricks-app.yaml",
38-
expectedErr: nil,
36+
name: "valid with empty list of bricks",
37+
filename: "empty-bricks-app.yaml",
38+
expectedErrors: nil,
3939
},
4040
{
41-
name: "valid if required variable is empty string",
42-
filename: "empty-required-app.yaml",
43-
expectedErr: nil,
41+
name: "valid if required variable is empty string",
42+
filename: "empty-required-app.yaml",
43+
expectedErrors: nil,
4444
},
4545
{
46-
name: "invalid if required variable is omitted",
47-
filename: "omitted-required-app.yaml",
48-
expectedErr: f.Ptr("variable \"ARDUINO_DEVICE_ID\" is required by brick \"arduino:arduino_cloud\"\nvariable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
46+
name: "invalid if required variable is omitted",
47+
filename: "omitted-required-app.yaml",
48+
expectedErrors: []error{
49+
errors.New("variable \"ARDUINO_DEVICE_ID\" is required by brick \"arduino:arduino_cloud\""),
50+
errors.New("variable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
51+
},
4952
},
5053
{
51-
name: "invalid if a required variable among two is omitted",
52-
filename: "omitted-mixed-required-app.yaml",
53-
expectedErr: f.Ptr("variable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
54+
name: "invalid if a required variable among two is omitted",
55+
filename: "omitted-mixed-required-app.yaml",
56+
expectedErrors: []error{
57+
errors.New("variable \"ARDUINO_SECRET\" is required by brick \"arduino:arduino_cloud\""),
58+
},
5459
},
5560
{
56-
name: "invalid if brick id not found",
57-
filename: "not-found-brick-app.yaml",
58-
expectedErr: f.Ptr("brick \"arduino:not_existing_brick\" not found"),
61+
name: "invalid if brick id not found",
62+
filename: "not-found-brick-app.yaml",
63+
expectedErrors: []error{
64+
errors.New("brick \"arduino:not_existing_brick\" not found"),
65+
},
5966
},
6067
{
61-
name: "invalid if variable does not exist in the brick",
62-
filename: "not-found-variable-app.yaml",
63-
expectedErr: f.Ptr("variable \"NOT_EXISTING_VARIABLE\" does not exist on brick \"arduino:arduino_cloud\""),
68+
name: "invalid if variable does not exist in the brick",
69+
filename: "not-found-variable-app.yaml",
70+
expectedErrors: []error{
71+
errors.New("variable \"NOT_EXISTING_VARIABLE\" does not exist on brick \"arduino:arduino_cloud\""),
72+
},
6473
},
6574
}
6675

@@ -69,12 +78,13 @@ func TestValidateAppDescriptorBricks(t *testing.T) {
6978
appDescriptor, err := ParseDescriptorFile(paths.New("testdata/validator/" + tc.filename))
7079
require.NoError(t, err)
7180

72-
err = appDescriptor.ValidateBricks(bricksIndex)
73-
if tc.expectedErr == nil {
74-
assert.NoError(t, err)
81+
errs := appDescriptor.ValidateBricks(bricksIndex)
82+
if tc.expectedErrors == nil {
83+
require.Nil(t, errs)
84+
assert.Empty(t, errs, "Expected no validation errors")
7585
} else {
76-
require.Error(t, err)
77-
assert.Equal(t, *tc.expectedErr, err.Error())
86+
require.Len(t, errs, len(tc.expectedErrors), "Expected %d errors but got %d", len(tc.expectedErrors), len(errs))
87+
require.Exactly(t, tc.expectedErrors, errs)
7888
}
7989
})
8090
}

0 commit comments

Comments
 (0)