Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9af5f68

Browse files
committed
test: add unit test to document validation behavior
1 parentf1a0fd5 commit9af5f68

File tree

2 files changed

+207
-218
lines changed

2 files changed

+207
-218
lines changed

‎provider/parameter_test.go‎

Lines changed: 207 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package provider_test
33
import (
44
"fmt"
55
"regexp"
6+
"strconv"
67
"strings"
78
"testing"
89

@@ -686,180 +687,224 @@ data "coder_parameter" "region" {
686687
}
687688
}
688689

690+
// TestParameterValidationEnforcement tests various parameter states and the
691+
// validation enforcement that should be applied to them. The table is described
692+
// by a markdown table. This is done so that the test cases can be more easily
693+
// edited and read.
694+
//
695+
// Copy and paste the table to https://www.tablesgenerator.com/markdown_tables for easier editing
696+
//
689697
//nolint:paralleltest,tparallel // Parameters load values from env vars
690698
funcTestParameterValidationEnforcement(t*testing.T) {
691-
for_,tc:=range []struct {
699+
table:=strings.TrimSpace(`
700+
| Name | Type | Input Value | Default | Options | Validation | -> | Output Value | Optional | Error |
701+
|---------------|---------------|-------------|---------|-------------------|------------|----|--------------|----------|--------------|
702+
| | Empty Vals | | | | | | | | |
703+
| Emty | string,number | | | | | | "" | false | |
704+
| EmtyOpts | string,number | | | 1,2,3 | | | "" | false | |
705+
| EmtyRegex | string | | | | world | | | | regex error |
706+
| EmtyMin | number | | | | 1-10 | | | | 1 < < 10 |
707+
| EmtyMinOpt | number | | | 1,2,3 | 2-5 | | | | 2 < < 5 |
708+
| EmtyRegexOpt | string | | | "hello","goodbye" | goodbye | | | | regex error |
709+
| EmtyRegexOk | string | | | | .* | | "" | false | |
710+
| | | | | | | | | | |
711+
| | Default Set | No inputs | | | | | | | |
712+
| NumDef | number | | 5 | | | | 5 | true | |
713+
| NumDefVal | number | | 5 | | 3-7 | | 5 | true | |
714+
| NumDefInv | number | | 5 | | 10- | | 5 | | 10 < 5 < 0 |
715+
| NumDefOpts | number | | 5 | 1,3,5,7 | 2-6 | | 5 | true | |
716+
| NumDefNotOpts | number | | 5 | 1,3,7,9 | 2-6 | | | | valid option |
717+
| | | | | | | | | | |
718+
| StrDef | string | | hello | | | | hello | true | |
719+
| StrDefInv | string | | hello | | world | | | | regex error |
720+
| StrDefOpts | string | | a | a,b,c | | | a | true | |
721+
| StrDefNotOpts | string | | a | b,c,d | | | | | valid option |
722+
| StrDefOpts | string | | a | a,b,c,d,e,f | [a-c] | | a | true | |
723+
| | | | | | | | | | |
724+
| | Input Vals | | | | | | | | |
725+
| NumIns | number | 3 | 5 | | | | 3 | true | |
726+
| | | | | | | | | | |
727+
| | | | | | | | | | |
728+
`)
729+
730+
typerowstruct {
692731
Namestring
693-
Configstring
694-
Valuestring
695-
ExpectError*regexp.Regexp
696-
Checkfunc(state*terraform.ResourceState)
697-
}{
698-
// Empty
699-
{
700-
Name:"EmptyString",
701-
Config:`
702-
data "coder_parameter" "parameter" {
703-
name = "parameter"
704-
type = "string"
705-
}
706-
`,
707-
ExpectError:nil,
708-
Check:func(state*terraform.ResourceState) {
709-
attrs:=state.Primary.Attributes
710-
forkey,value:=rangemap[string]interface{}{
711-
"default":"",
712-
"value":"",
713-
"optional":"false",
714-
} {
715-
require.Equal(t,value,attrs[key])
716-
}
717-
},
718-
},
719-
{
720-
Name:"EmptyNumber",
721-
Config:`
722-
data "coder_parameter" "parameter" {
723-
name = "parameter"
724-
type = "number"
732+
Types []string
733+
InputValuestring
734+
Defaultstring
735+
Options []string
736+
Validation*provider.Validation
737+
OutputValuestring
738+
Optionalbool
739+
Error*regexp.Regexp
740+
}
741+
742+
rows:=make([]row,0)
743+
lines:=strings.Split(table,"\n")
744+
validMinMax:=regexp.MustCompile("^[0-9]*-[0-9]*$")
745+
for_,line:=rangelines[2:] {
746+
columns:=strings.Split(line,"|")
747+
columns=columns[1 :len(columns)-1]
748+
fori:=rangecolumns {
749+
// Trim the whitespace from all columns
750+
columns[i]=strings.TrimSpace(columns[i])
751+
}
752+
753+
ifcolumns[0]=="" {
754+
continue// Skip rows with empty names
755+
}
756+
757+
optional,err:=strconv.ParseBool(columns[8])
758+
ifcolumns[8]!="" {
759+
// Value does not matter if not specified
760+
require.NoError(t,err)
761+
}
762+
763+
varrerr*regexp.Regexp
764+
ifcolumns[9]!="" {
765+
rerr,err=regexp.Compile(columns[9])
766+
iferr!=nil {
767+
t.Fatalf("failed to parse error column %q: %v",columns[9],err)
725768
}
726-
`,
727-
ExpectError:nil,
728-
Check:func(state*terraform.ResourceState) {
729-
attrs:=state.Primary.Attributes
730-
forkey,value:=rangemap[string]interface{}{
731-
"default":"",
732-
"value":"",
733-
"optional":"false",
734-
} {
735-
require.Equal(t,value,attrs[key])
736-
}
737-
},
738-
},
739-
// EmptyWithOption
740-
{
741-
Name:"EmptyWithOption",
742-
Config:`
743-
data "coder_parameter" "parameter" {
744-
name = "parameter"
745-
type = "number"
746-
747-
option {
748-
name = "option"
749-
value = "5"
769+
}
770+
varoptions []string
771+
ifcolumns[4]!="" {
772+
options=strings.Split(columns[4],",")
773+
}
774+
775+
varvalidation*provider.Validation
776+
ifcolumns[5]!="" {
777+
// Min-Max validation should look like:
778+
//1-10 :: min=1, max=10
779+
//-10 :: max=10
780+
//1- :: min=1
781+
ifvalidMinMax.MatchString(columns[5]) {
782+
parts:=strings.Split(columns[5],"-")
783+
min,_:=strconv.ParseInt(parts[0],10,64)
784+
max,_:=strconv.ParseInt(parts[1],10,64)
785+
validation=&provider.Validation{
786+
Min:int(min),
787+
MinDisabled:parts[0]=="",
788+
Max:int(max),
789+
MaxDisabled:parts[1]=="",
790+
Monotonic:"",
791+
Regex:"",
792+
Error:"{min} < {value} < {max}",
750793
}
751-
}
752-
`,
753-
ExpectError:nil,
754-
Check:func(state*terraform.ResourceState) {
755-
attrs:=state.Primary.Attributes
756-
forkey,value:=rangemap[string]interface{}{
757-
"default":"",
758-
"value":"",
759-
"optional":"false",
760-
} {
761-
require.Equal(t,value,attrs[key])
794+
}else {
795+
validation=&provider.Validation{
796+
Min:0,
797+
MinDisabled:true,
798+
Max:0,
799+
MaxDisabled:true,
800+
Monotonic:"",
801+
Regex:columns[5],
802+
Error:"regex error",
762803
}
763-
},
764-
},
765-
// DefaultSet
766-
{
767-
Name:"DefaultSet",
768-
Config:`
769-
data "coder_parameter" "parameter" {
770-
name = "parameter"
771-
type = "number"
772-
default = "5"
773804
}
774-
`,
775-
ExpectError:nil,
776-
Check:func(state*terraform.ResourceState) {
777-
attrs:=state.Primary.Attributes
778-
forkey,value:=rangemap[string]interface{}{
779-
"default":"5",
780-
"value":"5",
781-
"optional":"true",
782-
} {
783-
require.Equal(t,value,attrs[key])
784-
}
785-
},
786-
},
787-
{
788-
Name:"DefaultSetInOption",
789-
Config:`
790-
data "coder_parameter" "parameter" {
791-
name = "parameter"
792-
type = "number"
793-
default = "5"
794-
option {
795-
name = "option"
796-
value = "5"
805+
}
806+
807+
rows=append(rows,row{
808+
Name:columns[0],
809+
Types:strings.Split(columns[1],","),
810+
InputValue:columns[2],
811+
Default:columns[3],
812+
Options:options,
813+
Validation:validation,
814+
OutputValue:columns[7],
815+
Optional:optional,
816+
Error:rerr,
817+
})
818+
}
819+
820+
stringLiteral:=func(sstring)string {
821+
ifs=="" {
822+
return`""`
823+
}
824+
returnfmt.Sprintf("%q",s)
825+
}
826+
827+
forrowIndex,row:=rangerows {
828+
for_,rt:=rangerow.Types {
829+
//nolint:paralleltest,tparallel // Parameters load values from env vars
830+
t.Run(fmt.Sprintf("%d|%s:%s",rowIndex,row.Name,rt),func(t*testing.T) {
831+
ifrow.InputValue!="" {
832+
t.Setenv(provider.ParameterEnvironmentVariable("parameter"),row.InputValue)
797833
}
798-
}
799-
`,
800-
ExpectError:nil,
801-
Check:func(state*terraform.ResourceState) {
802-
attrs:=state.Primary.Attributes
803-
forkey,value:=rangemap[string]interface{}{
804-
"default":"5",
805-
"value":"5",
806-
"optional":"true",
807-
} {
808-
require.Equal(t,value,attrs[key])
834+
835+
varcfg strings.Builder
836+
cfg.WriteString("data\"coder_parameter\"\"parameter\" {\n")
837+
cfg.WriteString("\tname =\"parameter\"\n")
838+
cfg.WriteString(fmt.Sprintf("\ttype =\"%s\"\n",rt))
839+
ifrow.Default!="" {
840+
cfg.WriteString(fmt.Sprintf("\tdefault = %s\n",stringLiteral(row.Default)))
809841
}
810-
},
811-
},
812-
{
813-
Name:"DefaultSetOutOption",
814-
Config:`
815-
data "coder_parameter" "parameter" {
816-
name = "parameter"
817-
type = "number"
818-
default = "2"
819-
option {
820-
name = "option"
821-
value = "5"
842+
843+
for_,opt:=rangerow.Options {
844+
cfg.WriteString("\toption {\n")
845+
cfg.WriteString(fmt.Sprintf("\t\tname = %s\n",stringLiteral(opt)))
846+
cfg.WriteString(fmt.Sprintf("\t\tvalue = %s\n",stringLiteral(opt)))
847+
cfg.WriteString("\t}\n")
822848
}
823-
}
824-
`,
825-
ExpectError:nil,
826-
Check:func(state*terraform.ResourceState) {
827-
attrs:=state.Primary.Attributes
828-
forkey,value:=rangemap[string]interface{}{
829-
"default":"5",
830-
"value":"5",
831-
"optional":"true",
832-
} {
833-
require.Equal(t,value,attrs[key])
849+
850+
ifrow.Validation!=nil {
851+
cfg.WriteString("\tvalidation {\n")
852+
if!row.Validation.MinDisabled {
853+
cfg.WriteString(fmt.Sprintf("\t\tmin = %d\n",row.Validation.Min))
854+
}
855+
if!row.Validation.MaxDisabled {
856+
cfg.WriteString(fmt.Sprintf("\t\tmax = %d\n",row.Validation.Max))
857+
}
858+
ifrow.Validation.Monotonic!="" {
859+
cfg.WriteString(fmt.Sprintf("\t\tmonotonic =\"%s\"\n",row.Validation.Monotonic))
860+
}
861+
ifrow.Validation.Regex!="" {
862+
cfg.WriteString(fmt.Sprintf("\t\tregex = %q\n",row.Validation.Regex))
863+
}
864+
cfg.WriteString(fmt.Sprintf("\t\terror = %q\n",row.Validation.Error))
865+
cfg.WriteString("\t}\n")
834866
}
835-
},
836-
},
837-
} {
838-
tc:=tc
839-
//nolint:paralleltest,tparallel // Parameters load values from env vars
840-
t.Run(tc.Name,func(t*testing.T) {
841-
iftc.Value!="" {
842-
t.Setenv(provider.ParameterEnvironmentVariable("parameter"),tc.Value)
843-
}
844-
resource.Test(t, resource.TestCase{
845-
ProviderFactories:coderFactory(),
846-
IsUnitTest:true,
847-
Steps: []resource.TestStep{{
848-
Config:tc.Config,
849-
ExpectError:tc.ExpectError,
850-
Check:func(state*terraform.State)error {
851-
require.Len(t,state.Modules,1)
852-
require.Len(t,state.Modules[0].Resources,1)
853-
param:=state.Modules[0].Resources["data.coder_parameter.parameter"]
854-
require.NotNil(t,param)
855-
iftc.Check!=nil {
856-
tc.Check(param)
857-
}
858-
returnnil
859-
},
860-
}},
867+
868+
cfg.WriteString("}\n")
869+
870+
resource.Test(t, resource.TestCase{
871+
ProviderFactories:coderFactory(),
872+
IsUnitTest:true,
873+
Steps: []resource.TestStep{{
874+
Config:cfg.String(),
875+
ExpectError:row.Error,
876+
Check:func(state*terraform.State)error {
877+
require.Len(t,state.Modules,1)
878+
require.Len(t,state.Modules[0].Resources,1)
879+
param:=state.Modules[0].Resources["data.coder_parameter.parameter"]
880+
require.NotNil(t,param)
881+
882+
ifrow.Default=="" {
883+
_,ok:=param.Primary.Attributes["default"]
884+
require.False(t,ok,"default should not be set")
885+
}else {
886+
require.Equal(t,strings.Trim(row.Default,`"`),param.Primary.Attributes["default"])
887+
}
888+
889+
ifrow.OutputValue=="" {
890+
_,ok:=param.Primary.Attributes["value"]
891+
require.False(t,ok,"output value should not be set")
892+
}else {
893+
require.Equal(t,strings.Trim(row.OutputValue,`"`),param.Primary.Attributes["value"])
894+
}
895+
896+
forkey,expected:=rangemap[string]string{
897+
"optional":strconv.FormatBool(row.Optional),
898+
} {
899+
require.Equal(t,expected,param.Primary.Attributes[key])
900+
}
901+
902+
returnnil
903+
},
904+
}},
905+
})
861906
})
862-
})
907+
}
863908
}
864909
}
865910

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp