terraform-provider-stackitp.../stackit/internal/validate/validate_test.go
João Palet 31ce9ab36d
Allow managing members in the project resource (#480)
* Extend resource and datasource

* Adapt acc test to work without members

* Extend acc test and adjust resource

* Generate docs

* Fix lint

* Fix unit test

* Uniformize description with datasource and extend unit test

* Improve role field description

* Update TF state before adding/removing members

* Remove unused function

* Move intermediate map top state to mapProjectFields

* Improve code
2024-07-29 09:57:06 +01:00

684 lines
11 KiB
Go

package validate
import (
"context"
"testing"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)
func TestUUID(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"cae27bba-c43d-498a-861e-d11d241c4ff8",
true,
},
{
"too short",
"a-b-c-d",
false,
},
{
"Empty",
"",
false,
},
{
"not UUID",
"www-541-%",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
UUID().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestIP(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok IP4",
"111.222.111.222",
true,
},
{
"ok IP6",
"2001:0db8:85a3:08d3::0370:7344",
true,
},
{
"too short",
"0.1.2",
false,
},
{
"Empty",
"",
false,
},
{
"Not an IP",
"for-sure-not-an-IP",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
IP().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestRecordSet(t *testing.T) {
tests := []struct {
description string
record string
recordType string
isValid bool
}{
{
"A record ok IP4",
"111.222.111.222",
"A",
true,
},
{
"A record fail IP6",
"2001:0db8:85a3:08d3::0370:7344",
"A",
false,
},
{
"A record too short",
"0.1.2",
"A",
false,
},
{
"A record Empty",
"",
"A",
false,
},
{
"A record Not an IP",
"for-sure-not-an-IP",
"A",
false,
},
{
"AAAA record fail IP4",
"111.222.111.222",
"AAAA",
false,
},
{
"AAAA record ok IP6",
"2001:0db8:85a3:08d3::0370:7344",
"AAAA",
true,
},
{
"AAAA record too short",
"0.1.2",
"AAAA",
false,
},
{
"AAAA record Empty",
"",
"AAAA",
false,
},
{
"AAAA record Not an IP",
"for-sure-not-an-IP",
"AAAA",
false,
},
{
"CNAME record",
"some-record",
"CNAME",
true,
},
{
"NS record",
"some-record",
"NS",
true,
},
{
"MX record",
"some-record",
"MX",
true,
},
{
"TXT record",
"some-record",
"TXT",
true,
},
{
"ALIAS record",
"some-record",
"ALIAS",
true,
},
{
"DNAME record",
"some-record",
"DNAME",
true,
},
{
"CAA record",
"some-record",
"CAA",
true,
},
{
"random record",
"some-record",
"random",
true,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
scheme := tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"type": tftypes.String,
},
}
value := map[string]tftypes.Value{
"type": tftypes.NewValue(tftypes.String, tt.recordType),
}
record := tftypes.NewValue(scheme, value)
RecordSet().ValidateString(context.Background(), validator.StringRequest{
Config: tfsdk.Config{
Schema: schema.Schema{
Attributes: map[string]schema.Attribute{
"type": schema.StringAttribute{},
},
},
Raw: record,
},
ConfigValue: types.StringValue(tt.record),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestNoSeparator(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"ABCD",
true,
},
{
"ok-2",
"#$%&/()=.;-",
true,
},
{
"Empty",
"",
true,
},
{
"not ok",
"ab,",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
NoSeparator().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestNonLegacyProjectRole(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"owner",
true,
},
{
"ok-2",
"reader",
true,
},
{
"leagcy-role",
"project.owner",
false,
},
{
"leagcy-role-2",
"project.admin",
false,
},
{
"leagcy-role-3",
"project.member",
false,
},
{
"leagcy-role-4",
"project.auditor",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
NonLegacyProjectRole().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestMinorVersionNumber(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"1.20",
true,
},
{
"ok-2",
"1.3",
true,
},
{
"ok-3",
"10.1",
true,
},
{
"Empty",
"",
false,
},
{
"not ok",
"afssfdfs",
false,
},
{
"not ok-major-version",
"1",
false,
},
{
"not ok-patch-version",
"1.20.1",
false,
},
{
"not ok-version",
"v1.20.1",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
MinorVersionNumber().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestVersionNumber(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"1.20",
true,
},
{
"ok-2",
"1.3",
true,
},
{
"ok-3",
"10.1",
true,
},
{
"ok-patch-version",
"1.20.1",
true,
},
{
"ok-patch-version-2",
"1.20.10",
true,
},
{
"ok-patch-version-3",
"10.20.10",
true,
},
{
"Empty",
"",
false,
},
{
"not ok",
"afssfdfs",
false,
},
{
"not ok-major-version",
"1",
false,
},
{
"not ok-version",
"v1.20.1",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
VersionNumber().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestRFC3339SecondsOnly(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"9999-01-02T03:04:05Z",
true,
},
{
"ok_2",
"9999-01-02T03:04:05+06:00",
true,
},
{
"empty",
"",
false,
},
{
"not_ok",
"foo-bar",
false,
},
{
"with_sub_seconds",
"9999-01-02T03:04:05.678Z",
false,
},
{
"with_sub_seconds_2",
"9999-01-02T03:04:05.678+06:00",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
RFC3339SecondsOnly().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestCIDR(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"IPv4_block",
"198.51.100.14/24",
true,
},
{
"IPv4_block_2",
"111.222.111.222/22",
true,
},
{
"IPv4_single",
"198.51.100.14/32",
true,
},
{
"IPv4_entire_internet",
"0.0.0.0/0",
true,
},
{
"IPv4_block_invalid",
"198.51.100.14/33",
false,
},
{
"IPv4_no_block",
"111.222.111.222",
false,
},
{
"IPv6_block",
"2001:db8::/48",
true,
},
{
"IPv6_single",
"2001:0db8:85a3:08d3::0370:7344/128",
true,
},
{
"IPv6_all",
"::/0",
true,
},
{
"IPv6_block_invalid",
"2001:0db8:85a3:08d3::0370:7344/129",
false,
},
{
"IPv6_no_block",
"2001:0db8:85a3:08d3::0370:7344",
false,
},
{
"empty",
"",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
CIDR().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}
func TestRrule(t *testing.T) {
tests := []struct {
description string
input string
isValid bool
}{
{
"ok",
"DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=1",
true,
},
{
"ok-2",
"DTSTART;TZID=Europe/Sofia:20200803T023000\nRULE:FREQ=DAILY;INTERVAL=1",
true,
},
{
"Empty",
"",
false,
},
{
"not ok",
"afssfdfs",
false,
},
{
"not ok-missing-space-before-rrule",
"DTSTART;TZID=Europe/Sofia:20200803T023000RRULE:FREQ=DAILY;INTERVAL=1",
false,
},
{
"not ok-missing-interval",
"DTSTART;TZID=Europe/Sofia:20200803T023000 RRULE:FREQ=DAILY;INTERVAL=",
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
r := validator.StringResponse{}
Rrule().ValidateString(context.Background(), validator.StringRequest{
ConfigValue: types.StringValue(tt.input),
}, &r)
if !tt.isValid && !r.Diagnostics.HasError() {
t.Fatalf("Should have failed")
}
if tt.isValid && r.Diagnostics.HasError() {
t.Fatalf("Should not have failed: %v", r.Diagnostics.Errors())
}
})
}
}