Skip to content

Commit 9bb9a1f

Browse files
committed
begin adding invalid unit tests
1 parent 875b316 commit 9bb9a1f

File tree

2 files changed

+155
-33
lines changed

2 files changed

+155
-33
lines changed

provider/parameter.go

+52-33
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

+103
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
13+
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
1415

1516
"github.com/coder/terraform-provider-coder/v2/provider"
@@ -688,6 +689,7 @@ data "coder_parameter" "region" {
688689
}
689690
}
690691

692+
<<<<<<< HEAD
691693
// TestParameterValidationEnforcement tests various parameter states and the
692694
// validation enforcement that should be applied to them. The table is described
693695
// by a markdown table. This is done so that the test cases can be more easily
@@ -896,6 +898,107 @@ func TestParameterValidationEnforcement(t *testing.T) {
896898
})
897899
})
898900
}
901+
=======
902+
func TestParameterValidation(t *testing.T) {
903+
t.Parallel()
904+
opts := func(vals ...string) []provider.Option {
905+
options := make([]provider.Option, 0, len(vals))
906+
for _, val := range vals {
907+
options = append(options, provider.Option{
908+
Name: val,
909+
Value: val,
910+
})
911+
}
912+
return options
913+
}
914+
915+
for _, tc := range []struct {
916+
Name string
917+
Parameter provider.Parameter
918+
Value string
919+
ExpectError *regexp.Regexp
920+
}{
921+
{
922+
Name: "ValidStringParameter",
923+
Parameter: provider.Parameter{
924+
Type: "string",
925+
},
926+
Value: "alpha",
927+
},
928+
// Test invalid states
929+
{
930+
Name: "InvalidFormType",
931+
Parameter: provider.Parameter{
932+
Type: "string",
933+
Option: opts("alpha", "bravo", "charlie"),
934+
FormType: provider.ParameterFormTypeSlider,
935+
},
936+
Value: "alpha",
937+
ExpectError: regexp.MustCompile("Invalid form_type for parameter"),
938+
},
939+
{
940+
Name: "NotInOptions",
941+
Parameter: provider.Parameter{
942+
Type: "string",
943+
Option: opts("alpha", "bravo", "charlie"),
944+
},
945+
Value: "delta", // not in option set
946+
ExpectError: regexp.MustCompile("Value must be a valid option"),
947+
},
948+
{
949+
Name: "NonUniqueOptionNames",
950+
Parameter: provider.Parameter{
951+
Type: "string",
952+
Option: opts("alpha", "alpha"),
953+
},
954+
Value: "alpha",
955+
ExpectError: regexp.MustCompile("Option names must be unique"),
956+
},
957+
{
958+
Name: "NonUniqueOptionValues",
959+
Parameter: provider.Parameter{
960+
Type: "string",
961+
Option: []provider.Option{
962+
{Name: "Alpha", Value: "alpha"},
963+
{Name: "AlphaAgain", Value: "alpha"},
964+
},
965+
},
966+
Value: "alpha",
967+
ExpectError: regexp.MustCompile("Option values must be unique"),
968+
},
969+
{
970+
Name: "IncorrectValueTypeOption",
971+
Parameter: provider.Parameter{
972+
Type: "number",
973+
Option: opts("not-a-number"),
974+
},
975+
Value: "5",
976+
ExpectError: regexp.MustCompile("is not a number"),
977+
},
978+
{
979+
Name: "IncorrectValueType",
980+
Parameter: provider.Parameter{
981+
Type: "number",
982+
},
983+
Value: "not-a-number",
984+
ExpectError: regexp.MustCompile("Parameter value is not of type \"number\""),
985+
},
986+
} {
987+
tc := tc
988+
t.Run(tc.Name, func(t *testing.T) {
989+
t.Parallel()
990+
diags := tc.Parameter.Valid(tc.Value)
991+
if tc.ExpectError != nil {
992+
require.True(t, diags.HasError())
993+
errMsg := fmt.Sprintf("%+v", diags[0]) // close enough
994+
require.Truef(t, tc.ExpectError.MatchString(errMsg), "got: %s", errMsg)
995+
} else {
996+
if !assert.False(t, diags.HasError()) {
997+
t.Logf("got: %+v", diags[0])
998+
}
999+
}
1000+
})
1001+
>>>>>>> c640b02 (begin adding invalid unit tests)
8991002
}
9001003
}
9011004

0 commit comments

Comments
 (0)