535 lines
16 KiB
Go
535 lines
16 KiB
Go
package cdn
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
|
|
)
|
|
|
|
func TestToCreatePayload(t *testing.T) {
|
|
headers := map[string]attr.Value{
|
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
|
}
|
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
|
"type": types.StringValue("http"),
|
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
|
"origin_request_headers": originRequestHeaders,
|
|
})
|
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
|
blockedCountries := []attr.Value{types.StringValue("XX"), types.StringValue("YY"), types.StringValue("ZZ")}
|
|
blockedCountriesFixture := types.ListValueMust(types.StringType, blockedCountries)
|
|
optimizer := types.ObjectValueMust(optimizerTypes, map[string]attr.Value{
|
|
"enabled": types.BoolValue(true),
|
|
})
|
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"blocked_countries": blockedCountriesFixture,
|
|
"optimizer": types.ObjectNull(optimizerTypes),
|
|
})
|
|
modelFixture := func(mods ...func(*Model)) *Model {
|
|
model := &Model{
|
|
DistributionId: types.StringValue("test-distribution-id"),
|
|
ProjectId: types.StringValue("test-project-id"),
|
|
Config: config,
|
|
}
|
|
for _, mod := range mods {
|
|
mod(model)
|
|
}
|
|
return model
|
|
}
|
|
tests := map[string]struct {
|
|
Input *Model
|
|
Expected *cdn.CreateDistributionPayload
|
|
IsValid bool
|
|
}{
|
|
"happy_path": {
|
|
Input: modelFixture(),
|
|
Expected: &cdn.CreateDistributionPayload{
|
|
OriginRequestHeaders: &map[string]string{
|
|
"testHeader0": "testHeaderValue0",
|
|
"testHeader1": "testHeaderValue1",
|
|
},
|
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
|
Regions: &[]cdn.Region{"EU", "US"},
|
|
BlockedCountries: &[]string{"XX", "YY", "ZZ"},
|
|
},
|
|
IsValid: true,
|
|
},
|
|
"happy_path_with_optimizer": {
|
|
Input: modelFixture(func(m *Model) {
|
|
m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"optimizer": optimizer,
|
|
"blocked_countries": blockedCountriesFixture,
|
|
})
|
|
}),
|
|
Expected: &cdn.CreateDistributionPayload{
|
|
OriginRequestHeaders: &map[string]string{
|
|
"testHeader0": "testHeaderValue0",
|
|
"testHeader1": "testHeaderValue1",
|
|
},
|
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
|
Regions: &[]cdn.Region{"EU", "US"},
|
|
Optimizer: cdn.NewOptimizer(true),
|
|
BlockedCountries: &[]string{"XX", "YY", "ZZ"},
|
|
},
|
|
IsValid: true,
|
|
},
|
|
"sad_path_model_nil": {
|
|
Input: nil,
|
|
Expected: nil,
|
|
IsValid: false,
|
|
},
|
|
"sad_path_config_error": {
|
|
Input: modelFixture(func(m *Model) {
|
|
m.Config = types.ObjectNull(configTypes)
|
|
}),
|
|
Expected: nil,
|
|
IsValid: false,
|
|
},
|
|
}
|
|
for tn, tc := range tests {
|
|
t.Run(tn, func(t *testing.T) {
|
|
res, err := toCreatePayload(context.Background(), tc.Input)
|
|
if err != nil && tc.IsValid {
|
|
t.Fatalf("Error converting model to create payload: %v", err)
|
|
}
|
|
if err == nil && !tc.IsValid {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tc.IsValid {
|
|
// set generated ID before diffing
|
|
tc.Expected.IntentId = res.IntentId
|
|
|
|
diff := cmp.Diff(res, tc.Expected)
|
|
if diff != "" {
|
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConvertConfig(t *testing.T) {
|
|
headers := map[string]attr.Value{
|
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
|
}
|
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
|
"type": types.StringValue("http"),
|
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
|
"origin_request_headers": originRequestHeaders,
|
|
})
|
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
|
blockedCountries := []attr.Value{types.StringValue("XX"), types.StringValue("YY"), types.StringValue("ZZ")}
|
|
blockedCountriesFixture := types.ListValueMust(types.StringType, blockedCountries)
|
|
optimizer := types.ObjectValueMust(optimizerTypes, map[string]attr.Value{"enabled": types.BoolValue(true)})
|
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"optimizer": types.ObjectNull(optimizerTypes),
|
|
"blocked_countries": blockedCountriesFixture,
|
|
})
|
|
modelFixture := func(mods ...func(*Model)) *Model {
|
|
model := &Model{
|
|
DistributionId: types.StringValue("test-distribution-id"),
|
|
ProjectId: types.StringValue("test-project-id"),
|
|
Config: config,
|
|
}
|
|
for _, mod := range mods {
|
|
mod(model)
|
|
}
|
|
return model
|
|
}
|
|
tests := map[string]struct {
|
|
Input *Model
|
|
Expected *cdn.Config
|
|
IsValid bool
|
|
}{
|
|
"happy_path": {
|
|
Input: modelFixture(),
|
|
Expected: &cdn.Config{
|
|
Backend: &cdn.ConfigBackend{
|
|
HttpBackend: &cdn.HttpBackend{
|
|
OriginRequestHeaders: &map[string]string{
|
|
"testHeader0": "testHeaderValue0",
|
|
"testHeader1": "testHeaderValue1",
|
|
},
|
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
|
Type: cdn.PtrString("http"),
|
|
},
|
|
},
|
|
Regions: &[]cdn.Region{"EU", "US"},
|
|
BlockedCountries: &[]string{"XX", "YY", "ZZ"},
|
|
},
|
|
IsValid: true,
|
|
},
|
|
"happy_path_with_optimizer": {
|
|
Input: modelFixture(func(m *Model) {
|
|
m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"optimizer": optimizer,
|
|
"blocked_countries": blockedCountriesFixture,
|
|
})
|
|
}),
|
|
Expected: &cdn.Config{
|
|
Backend: &cdn.ConfigBackend{
|
|
HttpBackend: &cdn.HttpBackend{
|
|
OriginRequestHeaders: &map[string]string{
|
|
"testHeader0": "testHeaderValue0",
|
|
"testHeader1": "testHeaderValue1",
|
|
},
|
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
|
Type: cdn.PtrString("http"),
|
|
},
|
|
},
|
|
Regions: &[]cdn.Region{"EU", "US"},
|
|
Optimizer: cdn.NewOptimizer(true),
|
|
BlockedCountries: &[]string{"XX", "YY", "ZZ"},
|
|
},
|
|
IsValid: true,
|
|
},
|
|
"sad_path_model_nil": {
|
|
Input: nil,
|
|
Expected: nil,
|
|
IsValid: false,
|
|
},
|
|
"sad_path_config_error": {
|
|
Input: modelFixture(func(m *Model) {
|
|
m.Config = types.ObjectNull(configTypes)
|
|
}),
|
|
Expected: nil,
|
|
IsValid: false,
|
|
},
|
|
}
|
|
for tn, tc := range tests {
|
|
t.Run(tn, func(t *testing.T) {
|
|
res, err := convertConfig(context.Background(), tc.Input)
|
|
if err != nil && tc.IsValid {
|
|
t.Fatalf("Error converting model to create payload: %v", err)
|
|
}
|
|
if err == nil && !tc.IsValid {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tc.IsValid {
|
|
diff := cmp.Diff(res, tc.Expected)
|
|
if diff != "" {
|
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapFields(t *testing.T) {
|
|
createdAt := time.Now()
|
|
updatedAt := time.Now()
|
|
headers := map[string]attr.Value{
|
|
"testHeader0": types.StringValue("testHeaderValue0"),
|
|
"testHeader1": types.StringValue("testHeaderValue1"),
|
|
}
|
|
originRequestHeaders := types.MapValueMust(types.StringType, headers)
|
|
backend := types.ObjectValueMust(backendTypes, map[string]attr.Value{
|
|
"type": types.StringValue("http"),
|
|
"origin_url": types.StringValue("https://www.mycoolapp.com"),
|
|
"origin_request_headers": originRequestHeaders,
|
|
})
|
|
regions := []attr.Value{types.StringValue("EU"), types.StringValue("US")}
|
|
regionsFixture := types.ListValueMust(types.StringType, regions)
|
|
blockedCountries := []attr.Value{types.StringValue("XX"), types.StringValue("YY"), types.StringValue("ZZ")}
|
|
blockedCountriesFixture := types.ListValueMust(types.StringType, blockedCountries)
|
|
optimizer := types.ObjectValueMust(optimizerTypes, map[string]attr.Value{
|
|
"enabled": types.BoolValue(true),
|
|
})
|
|
config := types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"blocked_countries": blockedCountriesFixture,
|
|
"optimizer": types.ObjectNull(optimizerTypes),
|
|
})
|
|
|
|
emtpyErrorsList := types.ListValueMust(types.StringType, []attr.Value{})
|
|
managedDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
|
"name": types.StringValue("test.stackit-cdn.com"),
|
|
"status": types.StringValue("ACTIVE"),
|
|
"type": types.StringValue("managed"),
|
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
|
})
|
|
domains := types.ListValueMust(types.ObjectType{AttrTypes: domainTypes}, []attr.Value{managedDomain})
|
|
expectedModel := func(mods ...func(*Model)) *Model {
|
|
model := &Model{
|
|
ID: types.StringValue("test-project-id,test-distribution-id"),
|
|
DistributionId: types.StringValue("test-distribution-id"),
|
|
ProjectId: types.StringValue("test-project-id"),
|
|
Config: config,
|
|
Status: types.StringValue("ACTIVE"),
|
|
CreatedAt: types.StringValue(createdAt.String()),
|
|
UpdatedAt: types.StringValue(updatedAt.String()),
|
|
Errors: emtpyErrorsList,
|
|
Domains: domains,
|
|
}
|
|
for _, mod := range mods {
|
|
mod(model)
|
|
}
|
|
return model
|
|
}
|
|
distributionFixture := func(mods ...func(*cdn.Distribution)) *cdn.Distribution {
|
|
distribution := &cdn.Distribution{
|
|
Config: &cdn.Config{
|
|
Backend: &cdn.ConfigBackend{
|
|
HttpBackend: &cdn.HttpBackend{
|
|
OriginRequestHeaders: &map[string]string{
|
|
"testHeader0": "testHeaderValue0",
|
|
"testHeader1": "testHeaderValue1",
|
|
},
|
|
OriginUrl: cdn.PtrString("https://www.mycoolapp.com"),
|
|
Type: cdn.PtrString("http"),
|
|
},
|
|
},
|
|
Regions: &[]cdn.Region{"EU", "US"},
|
|
BlockedCountries: &[]string{"XX", "YY", "ZZ"},
|
|
Optimizer: nil,
|
|
},
|
|
CreatedAt: &createdAt,
|
|
Domains: &[]cdn.Domain{
|
|
{
|
|
Name: cdn.PtrString("test.stackit-cdn.com"),
|
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
|
Type: cdn.DOMAINTYPE_MANAGED.Ptr(),
|
|
},
|
|
},
|
|
Id: cdn.PtrString("test-distribution-id"),
|
|
ProjectId: cdn.PtrString("test-project-id"),
|
|
Status: cdn.DISTRIBUTIONSTATUS_ACTIVE.Ptr(),
|
|
UpdatedAt: &updatedAt,
|
|
}
|
|
for _, mod := range mods {
|
|
mod(distribution)
|
|
}
|
|
return distribution
|
|
}
|
|
tests := map[string]struct {
|
|
Input *cdn.Distribution
|
|
Expected *Model
|
|
IsValid bool
|
|
}{
|
|
"happy_path": {
|
|
Expected: expectedModel(),
|
|
Input: distributionFixture(),
|
|
IsValid: true,
|
|
},
|
|
"happy_path_with_optimizer": {
|
|
Expected: expectedModel(func(m *Model) {
|
|
m.Config = types.ObjectValueMust(configTypes, map[string]attr.Value{
|
|
"backend": backend,
|
|
"regions": regionsFixture,
|
|
"optimizer": optimizer,
|
|
"blocked_countries": blockedCountriesFixture,
|
|
})
|
|
}),
|
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
|
d.Config.Optimizer = &cdn.Optimizer{
|
|
Enabled: cdn.PtrBool(true),
|
|
}
|
|
}),
|
|
IsValid: true,
|
|
},
|
|
"happy_path_status_error": {
|
|
Expected: expectedModel(func(m *Model) {
|
|
m.Status = types.StringValue("ERROR")
|
|
}),
|
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
|
d.Status = cdn.DISTRIBUTIONSTATUS_ERROR.Ptr()
|
|
}),
|
|
IsValid: true,
|
|
},
|
|
"happy_path_custom_domain": {
|
|
Expected: expectedModel(func(m *Model) {
|
|
managedDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
|
"name": types.StringValue("test.stackit-cdn.com"),
|
|
"status": types.StringValue("ACTIVE"),
|
|
"type": types.StringValue("managed"),
|
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
|
})
|
|
customDomain := types.ObjectValueMust(domainTypes, map[string]attr.Value{
|
|
"name": types.StringValue("mycoolapp.info"),
|
|
"status": types.StringValue("ACTIVE"),
|
|
"type": types.StringValue("custom"),
|
|
"errors": types.ListValueMust(types.StringType, []attr.Value{}),
|
|
})
|
|
domains := types.ListValueMust(types.ObjectType{AttrTypes: domainTypes}, []attr.Value{managedDomain, customDomain})
|
|
m.Domains = domains
|
|
}),
|
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
|
d.Domains = &[]cdn.Domain{
|
|
{
|
|
Name: cdn.PtrString("test.stackit-cdn.com"),
|
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
|
Type: cdn.DOMAINTYPE_MANAGED.Ptr(),
|
|
},
|
|
{
|
|
Name: cdn.PtrString("mycoolapp.info"),
|
|
Status: cdn.DOMAINSTATUS_ACTIVE.Ptr(),
|
|
Type: cdn.DOMAINTYPE_CUSTOM.Ptr(),
|
|
},
|
|
}
|
|
}),
|
|
IsValid: true,
|
|
},
|
|
"sad_path_distribution_nil": {
|
|
Expected: nil,
|
|
Input: nil,
|
|
IsValid: false,
|
|
},
|
|
"sad_path_project_id_missing": {
|
|
Expected: expectedModel(),
|
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
|
d.ProjectId = nil
|
|
}),
|
|
IsValid: false,
|
|
},
|
|
"sad_path_distribution_id_missing": {
|
|
Expected: expectedModel(),
|
|
Input: distributionFixture(func(d *cdn.Distribution) {
|
|
d.Id = nil
|
|
}),
|
|
IsValid: false,
|
|
},
|
|
}
|
|
for tn, tc := range tests {
|
|
t.Run(tn, func(t *testing.T) {
|
|
model := &Model{}
|
|
err := mapFields(tc.Input, model)
|
|
if err != nil && tc.IsValid {
|
|
t.Fatalf("Error mapping fields: %v", err)
|
|
}
|
|
if err == nil && !tc.IsValid {
|
|
t.Fatalf("Should have failed")
|
|
}
|
|
if tc.IsValid {
|
|
diff := cmp.Diff(model, tc.Expected)
|
|
if diff != "" {
|
|
t.Fatalf("Create Payload not as expected: %s", diff)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestValidateCountryCode tests the validateCountryCode function with a variety of inputs.
|
|
func TestValidateCountryCode(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
inputCountry string
|
|
wantOutput string
|
|
expectError bool
|
|
expectedError string
|
|
}{
|
|
// Happy Path
|
|
{
|
|
name: "Valid lowercase",
|
|
inputCountry: "us",
|
|
wantOutput: "US",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Valid uppercase",
|
|
inputCountry: "DE",
|
|
wantOutput: "DE",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Valid mixed case",
|
|
inputCountry: "cA",
|
|
wantOutput: "CA",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Valid country code FR",
|
|
inputCountry: "fr",
|
|
wantOutput: "FR",
|
|
expectError: false,
|
|
},
|
|
|
|
// Error Scenarios
|
|
{
|
|
name: "Invalid length - too short",
|
|
inputCountry: "a",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code must be exactly 2 characters long",
|
|
},
|
|
{
|
|
name: "Invalid length - too long",
|
|
inputCountry: "USA",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code must be exactly 2 characters long",
|
|
},
|
|
{
|
|
name: "Invalid characters - contains number",
|
|
inputCountry: "U1",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code 'U1' must consist of two alphabetical letters (A-Z or a-z)",
|
|
},
|
|
{
|
|
name: "Invalid characters - contains symbol",
|
|
inputCountry: "D!",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code 'D!' must consist of two alphabetical letters (A-Z or a-z)",
|
|
},
|
|
{
|
|
name: "Invalid characters - both are numbers",
|
|
inputCountry: "42",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code '42' must consist of two alphabetical letters (A-Z or a-z)",
|
|
},
|
|
{
|
|
name: "Empty string",
|
|
inputCountry: "",
|
|
wantOutput: "",
|
|
expectError: true,
|
|
expectedError: "country code must be exactly 2 characters long",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
gotOutput, err := validateCountryCode(tc.inputCountry)
|
|
|
|
if tc.expectError {
|
|
if err == nil {
|
|
t.Errorf("expected an error for input '%s', but got none", tc.inputCountry)
|
|
} else if err.Error() != tc.expectedError {
|
|
t.Errorf("for input '%s', expected error '%s', but got '%s'", tc.inputCountry, tc.expectedError, err.Error())
|
|
}
|
|
if gotOutput != "" {
|
|
t.Errorf("expected empty string on error, but got '%s'", gotOutput)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("did not expect an error for input '%s', but got: %v", tc.inputCountry, err)
|
|
}
|
|
if gotOutput != tc.wantOutput {
|
|
t.Errorf("for input '%s', expected output '%s', but got '%s'", tc.inputCountry, tc.wantOutput, gotOutput)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|