Skip to content

Commit c640b02

Browse files
committed
begin adding invalid unit tests
1 parent d7fbec9 commit c640b02

File tree

2 files changed

+174
-33
lines changed

2 files changed

+174
-33
lines changed

provider/parameter.go

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ const (
5050
)
5151

5252
type Parameter struct {
53-
Value string
5453
Name string
5554
DisplayName string `mapstructure:"display_name"`
5655
Description string
@@ -86,7 +85,6 @@ func parameterDataSource() *schema.Resource {
8685

8786
var parameter Parameter
8887
err = mapstructure.Decode(struct {
89-
Value interface{}
9088
Name interface{}
9189
DisplayName interface{}
9290
Description interface{}
@@ -101,7 +99,6 @@ func parameterDataSource() *schema.Resource {
10199
Order interface{}
102100
Ephemeral interface{}
103101
}{
104-
Value: rd.Get("value"),
105102
Name: rd.Get("name"),
106103
DisplayName: rd.Get("display_name"),
107104
Description: rd.Get("description"),
@@ -126,14 +123,7 @@ func parameterDataSource() *schema.Resource {
126123
if err != nil {
127124
return diag.Errorf("decode parameter: %s", err)
128125
}
129-
var value string
130-
if parameter.Default != "" {
131-
err := valueIsType(parameter.Type, parameter.Default, defaultValuePath)
132-
if err != nil {
133-
return err
134-
}
135-
value = parameter.Default
136-
}
126+
value := parameter.Default
137127
envValue, ok := os.LookupEnv(ParameterEnvironmentVariable(parameter.Name))
138128
if ok {
139129
value = envValue
@@ -381,27 +371,27 @@ func fixValidationResourceData(rawConfig cty.Value, validation interface{}) (int
381371
return vArr, nil
382372
}
383373

384-
func valueIsType(typ OptionType, value string, attrPath cty.Path) diag.Diagnostics {
374+
func valueIsType(typ OptionType, value string) error {
385375
switch typ {
386376
case OptionTypeNumber:
387377
_, err := strconv.ParseFloat(value, 64)
388378
if err != nil {
389-
return diag.Errorf("%q is not a number", value)
379+
return fmt.Errorf("%q is not a number", value)
390380
}
391381
case OptionTypeBoolean:
392382
_, err := strconv.ParseBool(value)
393383
if err != nil {
394-
return diag.Errorf("%q is not a bool", value)
384+
return fmt.Errorf("%q is not a bool", value)
395385
}
396386
case OptionTypeListString:
397-
_, diags := valueIsListString(value, attrPath)
398-
if diags.HasError() {
399-
return diags
387+
_, err := valueIsListString(value)
388+
if err != nil {
389+
return err
400390
}
401391
case OptionTypeString:
402392
// Anything is a string!
403393
default:
404-
return diag.Errorf("invalid type %q", typ)
394+
return fmt.Errorf("invalid type %q", typ)
405395
}
406396
return nil
407397
}
@@ -447,9 +437,15 @@ func (v *Parameter) Valid(value string) diag.Diagnostics {
447437
},
448438
}
449439
}
450-
diags := valueIsType(optionType, option.Value, cty.Path{})
451-
if diags.HasError() {
452-
return diags
440+
err = valueIsType(optionType, option.Value)
441+
if err != nil {
442+
return diag.Diagnostics{
443+
{
444+
Severity: diag.Error,
445+
Summary: fmt.Sprintf("Option %q with value=%q is not of type %q", option.Name, option.Value, optionType),
446+
Detail: err.Error(),
447+
},
448+
}
453449
}
454450
optionValues[option.Value] = nil
455451
optionNames[option.Name] = nil
@@ -461,6 +457,18 @@ func (v *Parameter) Valid(value string) diag.Diagnostics {
461457

462458
// Validate the default value
463459
if v.Default != "" {
460+
err := valueIsType(v.Type, v.Default)
461+
if err != nil {
462+
return diag.Diagnostics{
463+
{
464+
Severity: diag.Error,
465+
Summary: fmt.Sprintf("Default value is not of type %q", v.Type),
466+
Detail: err.Error(),
467+
AttributePath: defaultValuePath,
468+
},
469+
}
470+
}
471+
464472
d := v.validValue(v.Default, optionType, optionValues, defaultValuePath)
465473
if d.HasError() {
466474
return d
@@ -473,6 +481,17 @@ func (v *Parameter) Valid(value string) diag.Diagnostics {
473481
return d
474482
}
475483

484+
err = valueIsType(v.Type, value)
485+
if err != nil {
486+
return diag.Diagnostics{
487+
{
488+
Severity: diag.Error,
489+
Summary: fmt.Sprintf("Parameter value is not of type %q", v.Type),
490+
Detail: err.Error(),
491+
},
492+
}
493+
}
494+
476495
return nil
477496
}
478497

@@ -488,9 +507,16 @@ func (v *Parameter) validValue(value string, optionType OptionType, optionValues
488507
if v.Type == OptionTypeListString && optionType == OptionTypeString {
489508
// If the type is list(string) and optionType is string, we have
490509
// to ensure all elements of the default exist as options.
491-
listValues, diags := valueIsListString(value, defaultValuePath)
492-
if diags.HasError() {
493-
return diags
510+
listValues, err := valueIsListString(value)
511+
if err != nil {
512+
return diag.Diagnostics{
513+
{
514+
Severity: diag.Error,
515+
Summary: "When using list(string) type, value must be a json encoded list of strings",
516+
Detail: err.Error(),
517+
AttributePath: defaultValuePath,
518+
},
519+
}
494520
}
495521

496522
// missing is used to construct a more helpful error message
@@ -608,18 +634,11 @@ func (v *Validation) Valid(typ OptionType, value string) error {
608634
return nil
609635
}
610636

611-
func valueIsListString(value string, path cty.Path) ([]string, diag.Diagnostics) {
637+
func valueIsListString(value string) ([]string, error) {
612638
var items []string
613639
err := json.Unmarshal([]byte(value), &items)
614640
if err != nil {
615-
return nil, diag.Diagnostics{
616-
{
617-
Severity: diag.Error,
618-
Summary: "When using list(string) type, value must be a json encoded list of strings",
619-
Detail: fmt.Sprintf("value %q is not a valid list of strings", value),
620-
AttributePath: path,
621-
},
622-
}
641+
return nil, fmt.Errorf("value %q is not a valid list of strings", value)
623642
}
624643
return items, nil
625644
}

provider/parameter_test.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1010
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
11+
"github.com/stretchr/testify/assert"
1112
"github.com/stretchr/testify/require"
1213

1314
"github.com/coder/terraform-provider-coder/v2/provider"
@@ -686,6 +687,108 @@ data "coder_parameter" "region" {
686687
}
687688
}
688689

690+
func TestParameterValidation(t *testing.T) {
691+
t.Parallel()
692+
opts := func(vals ...string) []provider.Option {
693+
options := make([]provider.Option, 0, len(vals))
694+
for _, val := range vals {
695+
options = append(options, provider.Option{
696+
Name: val,
697+
Value: val,
698+
})
699+
}
700+
return options
701+
}
702+
703+
for _, tc := range []struct {
704+
Name string
705+
Parameter provider.Parameter
706+
Value string
707+
ExpectError *regexp.Regexp
708+
}{
709+
{
710+
Name: "ValidStringParameter",
711+
Parameter: provider.Parameter{
712+
Type: "string",
713+
},
714+
Value: "alpha",
715+
},
716+
// Test invalid states
717+
{
718+
Name: "InvalidFormType",
719+
Parameter: provider.Parameter{
720+
Type: "string",
721+
Option: opts("alpha", "bravo", "charlie"),
722+
FormType: provider.ParameterFormTypeSlider,
723+
},
724+
Value: "alpha",
725+
ExpectError: regexp.MustCompile("Invalid form_type for parameter"),
726+
},
727+
{
728+
Name: "NotInOptions",
729+
Parameter: provider.Parameter{
730+
Type: "string",
731+
Option: opts("alpha", "bravo", "charlie"),
732+
},
733+
Value: "delta", // not in option set
734+
ExpectError: regexp.MustCompile("Value must be a valid option"),
735+
},
736+
{
737+
Name: "NonUniqueOptionNames",
738+
Parameter: provider.Parameter{
739+
Type: "string",
740+
Option: opts("alpha", "alpha"),
741+
},
742+
Value: "alpha",
743+
ExpectError: regexp.MustCompile("Option names must be unique"),
744+
},
745+
{
746+
Name: "NonUniqueOptionValues",
747+
Parameter: provider.Parameter{
748+
Type: "string",
749+
Option: []provider.Option{
750+
{Name: "Alpha", Value: "alpha"},
751+
{Name: "AlphaAgain", Value: "alpha"},
752+
},
753+
},
754+
Value: "alpha",
755+
ExpectError: regexp.MustCompile("Option values must be unique"),
756+
},
757+
{
758+
Name: "IncorrectValueTypeOption",
759+
Parameter: provider.Parameter{
760+
Type: "number",
761+
Option: opts("not-a-number"),
762+
},
763+
Value: "5",
764+
ExpectError: regexp.MustCompile("is not a number"),
765+
},
766+
{
767+
Name: "IncorrectValueType",
768+
Parameter: provider.Parameter{
769+
Type: "number",
770+
},
771+
Value: "not-a-number",
772+
ExpectError: regexp.MustCompile("Parameter value is not of type \"number\""),
773+
},
774+
} {
775+
tc := tc
776+
t.Run(tc.Name, func(t *testing.T) {
777+
t.Parallel()
778+
diags := tc.Parameter.Valid(tc.Value)
779+
if tc.ExpectError != nil {
780+
require.True(t, diags.HasError())
781+
errMsg := fmt.Sprintf("%+v", diags[0]) // close enough
782+
require.Truef(t, tc.ExpectError.MatchString(errMsg), "got: %s", errMsg)
783+
} else {
784+
if !assert.False(t, diags.HasError()) {
785+
t.Logf("got: %+v", diags[0])
786+
}
787+
}
788+
})
789+
}
790+
}
791+
689792
func TestValueValidatesType(t *testing.T) {
690793
t.Parallel()
691794
for _, tc := range []struct {
@@ -798,6 +901,25 @@ func TestValueValidatesType(t *testing.T) {
798901
Value: `[]`,
799902
MinDisabled: true,
800903
MaxDisabled: true,
904+
}, {
905+
Name: "ValidListOfStrings",
906+
Type: "list(string)",
907+
Value: `["first","second","third"]`,
908+
MinDisabled: true,
909+
MaxDisabled: true,
910+
}, {
911+
Name: "InvalidListOfStrings",
912+
Type: "list(string)",
913+
Value: `["first","second","third"`,
914+
MinDisabled: true,
915+
MaxDisabled: true,
916+
Error: regexp.MustCompile("is not valid list of strings"),
917+
}, {
918+
Name: "EmptyListOfStrings",
919+
Type: "list(string)",
920+
Value: `[]`,
921+
MinDisabled: true,
922+
MaxDisabled: true,
801923
}} {
802924
tc := tc
803925
t.Run(tc.Name, func(t *testing.T) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy