github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/aws/validators_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/service/s3"
     9  )
    10  
    11  func TestValidateEcrRepositoryName(t *testing.T) {
    12  	validNames := []string{
    13  		"nginx-web-app",
    14  		"project-a/nginx-web-app",
    15  		"domain.ltd/nginx-web-app",
    16  		"3chosome-thing.com/01different-pattern",
    17  		"0123456789/999999999",
    18  		"double/forward/slash",
    19  		"000000000000000",
    20  	}
    21  	for _, v := range validNames {
    22  		_, errors := validateEcrRepositoryName(v, "name")
    23  		if len(errors) != 0 {
    24  			t.Fatalf("%q should be a valid ECR repository name: %q", v, errors)
    25  		}
    26  	}
    27  
    28  	invalidNames := []string{
    29  		// length > 256
    30  		"3cho_some-thing.com/01different.-_pattern01different.-_pattern01diff" +
    31  			"erent.-_pattern01different.-_pattern01different.-_pattern01different" +
    32  			".-_pattern01different.-_pattern01different.-_pattern01different.-_pa" +
    33  			"ttern01different.-_pattern01different.-_pattern234567",
    34  		// length < 2
    35  		"i",
    36  		"special@character",
    37  		"different+special=character",
    38  		"double//slash",
    39  		"double..dot",
    40  		"/slash-at-the-beginning",
    41  		"slash-at-the-end/",
    42  	}
    43  	for _, v := range invalidNames {
    44  		_, errors := validateEcrRepositoryName(v, "name")
    45  		if len(errors) == 0 {
    46  			t.Fatalf("%q should be an invalid ECR repository name", v)
    47  		}
    48  	}
    49  }
    50  
    51  func TestValidateCloudWatchEventRuleName(t *testing.T) {
    52  	validNames := []string{
    53  		"HelloWorl_d",
    54  		"hello-world",
    55  		"hello.World0125",
    56  	}
    57  	for _, v := range validNames {
    58  		_, errors := validateCloudWatchEventRuleName(v, "name")
    59  		if len(errors) != 0 {
    60  			t.Fatalf("%q should be a valid CW event rule name: %q", v, errors)
    61  		}
    62  	}
    63  
    64  	invalidNames := []string{
    65  		"special@character",
    66  		"slash/in-the-middle",
    67  		// Length > 64
    68  		"TooLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName",
    69  	}
    70  	for _, v := range invalidNames {
    71  		_, errors := validateCloudWatchEventRuleName(v, "name")
    72  		if len(errors) == 0 {
    73  			t.Fatalf("%q should be an invalid CW event rule name", v)
    74  		}
    75  	}
    76  }
    77  
    78  func TestValidateLambdaFunctionName(t *testing.T) {
    79  	validNames := []string{
    80  		"arn:aws:lambda:us-west-2:123456789012:function:ThumbNail",
    81  		"FunctionName",
    82  		"function-name",
    83  	}
    84  	for _, v := range validNames {
    85  		_, errors := validateLambdaFunctionName(v, "name")
    86  		if len(errors) != 0 {
    87  			t.Fatalf("%q should be a valid Lambda function name: %q", v, errors)
    88  		}
    89  	}
    90  
    91  	invalidNames := []string{
    92  		"/FunctionNameWithSlash",
    93  		"function.name.with.dots",
    94  		// length > 140
    95  		"arn:aws:lambda:us-west-2:123456789012:function:TooLoooooo" +
    96  			"ooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
    97  			"ooooooooooooooooongFunctionName",
    98  	}
    99  	for _, v := range invalidNames {
   100  		_, errors := validateLambdaFunctionName(v, "name")
   101  		if len(errors) == 0 {
   102  			t.Fatalf("%q should be an invalid Lambda function name", v)
   103  		}
   104  	}
   105  }
   106  
   107  func TestValidateLambdaQualifier(t *testing.T) {
   108  	validNames := []string{
   109  		"123",
   110  		"prod",
   111  		"PROD",
   112  		"MyTestEnv",
   113  		"$LATEST",
   114  	}
   115  	for _, v := range validNames {
   116  		_, errors := validateLambdaQualifier(v, "name")
   117  		if len(errors) != 0 {
   118  			t.Fatalf("%q should be a valid Lambda function qualifier: %q", v, errors)
   119  		}
   120  	}
   121  
   122  	invalidNames := []string{
   123  		// No ARNs allowed
   124  		"arn:aws:lambda:us-west-2:123456789012:function:prod",
   125  		// length > 128
   126  		"TooLooooooooooooooooooooooooooooooooooooooooooooooooooo" +
   127  			"ooooooooooooooooooooooooooooooooooooooooooooooooooo" +
   128  			"oooooooooooongQualifier",
   129  	}
   130  	for _, v := range invalidNames {
   131  		_, errors := validateLambdaQualifier(v, "name")
   132  		if len(errors) == 0 {
   133  			t.Fatalf("%q should be an invalid Lambda function qualifier", v)
   134  		}
   135  	}
   136  }
   137  
   138  func TestValidateLambdaPermissionAction(t *testing.T) {
   139  	validNames := []string{
   140  		"lambda:*",
   141  		"lambda:InvokeFunction",
   142  		"*",
   143  	}
   144  	for _, v := range validNames {
   145  		_, errors := validateLambdaPermissionAction(v, "action")
   146  		if len(errors) != 0 {
   147  			t.Fatalf("%q should be a valid Lambda permission action: %q", v, errors)
   148  		}
   149  	}
   150  
   151  	invalidNames := []string{
   152  		"yada",
   153  		"lambda:123",
   154  		"*:*",
   155  		"lambda:Invoke*",
   156  	}
   157  	for _, v := range invalidNames {
   158  		_, errors := validateLambdaPermissionAction(v, "action")
   159  		if len(errors) == 0 {
   160  			t.Fatalf("%q should be an invalid Lambda permission action", v)
   161  		}
   162  	}
   163  }
   164  
   165  func TestValidateAwsAccountId(t *testing.T) {
   166  	validNames := []string{
   167  		"123456789012",
   168  		"999999999999",
   169  	}
   170  	for _, v := range validNames {
   171  		_, errors := validateAwsAccountId(v, "account_id")
   172  		if len(errors) != 0 {
   173  			t.Fatalf("%q should be a valid AWS Account ID: %q", v, errors)
   174  		}
   175  	}
   176  
   177  	invalidNames := []string{
   178  		"12345678901",   // too short
   179  		"1234567890123", // too long
   180  		"invalid",
   181  		"x123456789012",
   182  	}
   183  	for _, v := range invalidNames {
   184  		_, errors := validateAwsAccountId(v, "account_id")
   185  		if len(errors) == 0 {
   186  			t.Fatalf("%q should be an invalid AWS Account ID", v)
   187  		}
   188  	}
   189  }
   190  
   191  func TestValidateArn(t *testing.T) {
   192  	v := ""
   193  	_, errors := validateArn(v, "arn")
   194  	if len(errors) != 0 {
   195  		t.Fatalf("%q should not be validated as an ARN: %q", v, errors)
   196  	}
   197  
   198  	validNames := []string{
   199  		"arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment", // Beanstalk
   200  		"arn:aws:iam::123456789012:user/David",                                             // IAM User
   201  		"arn:aws:rds:eu-west-1:123456789012:db:mysql-db",                                   // RDS
   202  		"arn:aws:s3:::my_corporate_bucket/exampleobject.png",                               // S3 object
   203  		"arn:aws:events:us-east-1:319201112229:rule/rule_name",                             // CloudWatch Rule
   204  		"arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction",                  // Lambda function
   205  		"arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction:Qualifier",        // Lambda func qualifier
   206  	}
   207  	for _, v := range validNames {
   208  		_, errors := validateArn(v, "arn")
   209  		if len(errors) != 0 {
   210  			t.Fatalf("%q should be a valid ARN: %q", v, errors)
   211  		}
   212  	}
   213  
   214  	invalidNames := []string{
   215  		"arn",
   216  		"123456789012",
   217  		"arn:aws",
   218  		"arn:aws:logs",
   219  		"arn:aws:logs:region:*:*",
   220  	}
   221  	for _, v := range invalidNames {
   222  		_, errors := validateArn(v, "arn")
   223  		if len(errors) == 0 {
   224  			t.Fatalf("%q should be an invalid ARN", v)
   225  		}
   226  	}
   227  }
   228  
   229  func TestValidatePolicyStatementId(t *testing.T) {
   230  	validNames := []string{
   231  		"YadaHereAndThere",
   232  		"Valid-5tatement_Id",
   233  		"1234",
   234  	}
   235  	for _, v := range validNames {
   236  		_, errors := validatePolicyStatementId(v, "statement_id")
   237  		if len(errors) != 0 {
   238  			t.Fatalf("%q should be a valid Statement ID: %q", v, errors)
   239  		}
   240  	}
   241  
   242  	invalidNames := []string{
   243  		"Invalid/StatementId/with/slashes",
   244  		"InvalidStatementId.with.dots",
   245  		// length > 100
   246  		"TooooLoooooooooooooooooooooooooooooooooooooooooooo" +
   247  			"ooooooooooooooooooooooooooooooooooooooooStatementId",
   248  	}
   249  	for _, v := range invalidNames {
   250  		_, errors := validatePolicyStatementId(v, "statement_id")
   251  		if len(errors) == 0 {
   252  			t.Fatalf("%q should be an invalid Statement ID", v)
   253  		}
   254  	}
   255  }
   256  
   257  func TestValidateCIDRNetworkAddress(t *testing.T) {
   258  	cases := []struct {
   259  		CIDR              string
   260  		ExpectedErrSubstr string
   261  	}{
   262  		{"notacidr", `must contain a valid CIDR`},
   263  		{"10.0.1.0/16", `must contain a valid network CIDR`},
   264  		{"10.0.1.0/24", ``},
   265  	}
   266  
   267  	for i, tc := range cases {
   268  		_, errs := validateCIDRNetworkAddress(tc.CIDR, "foo")
   269  		if tc.ExpectedErrSubstr == "" {
   270  			if len(errs) != 0 {
   271  				t.Fatalf("%d/%d: Expected no error, got errs: %#v",
   272  					i+1, len(cases), errs)
   273  			}
   274  		} else {
   275  			if len(errs) != 1 {
   276  				t.Fatalf("%d/%d: Expected 1 err containing %q, got %d errs",
   277  					i+1, len(cases), tc.ExpectedErrSubstr, len(errs))
   278  			}
   279  			if !strings.Contains(errs[0].Error(), tc.ExpectedErrSubstr) {
   280  				t.Fatalf("%d/%d: Expected err: %q, to include %q",
   281  					i+1, len(cases), errs[0], tc.ExpectedErrSubstr)
   282  			}
   283  		}
   284  	}
   285  }
   286  
   287  func TestValidateHTTPMethod(t *testing.T) {
   288  	type testCases struct {
   289  		Value    string
   290  		ErrCount int
   291  	}
   292  
   293  	invalidCases := []testCases{
   294  		{
   295  			Value:    "incorrect",
   296  			ErrCount: 1,
   297  		},
   298  		{
   299  			Value:    "delete",
   300  			ErrCount: 1,
   301  		},
   302  	}
   303  
   304  	for _, tc := range invalidCases {
   305  		_, errors := validateHTTPMethod(tc.Value, "http_method")
   306  		if len(errors) != tc.ErrCount {
   307  			t.Fatalf("Expected %q to trigger a validation error.", tc.Value)
   308  		}
   309  	}
   310  
   311  	validCases := []testCases{
   312  		{
   313  			Value:    "ANY",
   314  			ErrCount: 0,
   315  		},
   316  		{
   317  			Value:    "DELETE",
   318  			ErrCount: 0,
   319  		},
   320  		{
   321  			Value:    "OPTIONS",
   322  			ErrCount: 0,
   323  		},
   324  	}
   325  
   326  	for _, tc := range validCases {
   327  		_, errors := validateHTTPMethod(tc.Value, "http_method")
   328  		if len(errors) != tc.ErrCount {
   329  			t.Fatalf("Expected %q not to trigger a validation error.", tc.Value)
   330  		}
   331  	}
   332  }
   333  
   334  func TestValidateLogMetricFilterName(t *testing.T) {
   335  	validNames := []string{
   336  		"YadaHereAndThere",
   337  		"Valid-5Metric_Name",
   338  		"This . is also %% valid@!)+(",
   339  		"1234",
   340  		strings.Repeat("W", 512),
   341  	}
   342  	for _, v := range validNames {
   343  		_, errors := validateLogMetricFilterName(v, "name")
   344  		if len(errors) != 0 {
   345  			t.Fatalf("%q should be a valid Log Metric Filter Name: %q", v, errors)
   346  		}
   347  	}
   348  
   349  	invalidNames := []string{
   350  		"Here is a name with: colon",
   351  		"and here is another * invalid name",
   352  		"*",
   353  		// length > 512
   354  		strings.Repeat("W", 513),
   355  	}
   356  	for _, v := range invalidNames {
   357  		_, errors := validateLogMetricFilterName(v, "name")
   358  		if len(errors) == 0 {
   359  			t.Fatalf("%q should be an invalid Log Metric Filter Name", v)
   360  		}
   361  	}
   362  }
   363  
   364  func TestValidateLogMetricTransformationName(t *testing.T) {
   365  	validNames := []string{
   366  		"YadaHereAndThere",
   367  		"Valid-5Metric_Name",
   368  		"This . is also %% valid@!)+(",
   369  		"1234",
   370  		"",
   371  		strings.Repeat("W", 255),
   372  	}
   373  	for _, v := range validNames {
   374  		_, errors := validateLogMetricFilterTransformationName(v, "name")
   375  		if len(errors) != 0 {
   376  			t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors)
   377  		}
   378  	}
   379  
   380  	invalidNames := []string{
   381  		"Here is a name with: colon",
   382  		"and here is another * invalid name",
   383  		"also $ invalid",
   384  		"*",
   385  		// length > 255
   386  		strings.Repeat("W", 256),
   387  	}
   388  	for _, v := range invalidNames {
   389  		_, errors := validateLogMetricFilterTransformationName(v, "name")
   390  		if len(errors) == 0 {
   391  			t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v)
   392  		}
   393  	}
   394  }
   395  
   396  func TestValidateLogGroupName(t *testing.T) {
   397  	validNames := []string{
   398  		"ValidLogGroupName",
   399  		"ValidLogGroup.Name",
   400  		"valid/Log-group",
   401  		"1234",
   402  		"YadaValid#0123",
   403  		"Also_valid-name",
   404  		strings.Repeat("W", 512),
   405  	}
   406  	for _, v := range validNames {
   407  		_, errors := validateLogGroupName(v, "name")
   408  		if len(errors) != 0 {
   409  			t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors)
   410  		}
   411  	}
   412  
   413  	invalidNames := []string{
   414  		"Here is a name with: colon",
   415  		"and here is another * invalid name",
   416  		"also $ invalid",
   417  		"This . is also %% invalid@!)+(",
   418  		"*",
   419  		"",
   420  		// length > 512
   421  		strings.Repeat("W", 513),
   422  	}
   423  	for _, v := range invalidNames {
   424  		_, errors := validateLogGroupName(v, "name")
   425  		if len(errors) == 0 {
   426  			t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v)
   427  		}
   428  	}
   429  }
   430  
   431  func TestValidateS3BucketLifecycleTimestamp(t *testing.T) {
   432  	validDates := []string{
   433  		"2016-01-01",
   434  		"2006-01-02",
   435  	}
   436  
   437  	for _, v := range validDates {
   438  		_, errors := validateS3BucketLifecycleTimestamp(v, "date")
   439  		if len(errors) != 0 {
   440  			t.Fatalf("%q should be valid date: %q", v, errors)
   441  		}
   442  	}
   443  
   444  	invalidDates := []string{
   445  		"Jan 01 2016",
   446  		"20160101",
   447  	}
   448  
   449  	for _, v := range invalidDates {
   450  		_, errors := validateS3BucketLifecycleTimestamp(v, "date")
   451  		if len(errors) == 0 {
   452  			t.Fatalf("%q should be invalid date", v)
   453  		}
   454  	}
   455  }
   456  
   457  func TestValidateS3BucketLifecycleStorageClass(t *testing.T) {
   458  	validStorageClass := []string{
   459  		"STANDARD_IA",
   460  		"GLACIER",
   461  	}
   462  
   463  	for _, v := range validStorageClass {
   464  		_, errors := validateS3BucketLifecycleStorageClass(v, "storage_class")
   465  		if len(errors) != 0 {
   466  			t.Fatalf("%q should be valid storage class: %q", v, errors)
   467  		}
   468  	}
   469  
   470  	invalidStorageClass := []string{
   471  		"STANDARD",
   472  		"1234",
   473  	}
   474  	for _, v := range invalidStorageClass {
   475  		_, errors := validateS3BucketLifecycleStorageClass(v, "storage_class")
   476  		if len(errors) == 0 {
   477  			t.Fatalf("%q should be invalid storage class", v)
   478  		}
   479  	}
   480  }
   481  
   482  func TestValidateS3BucketReplicationRuleId(t *testing.T) {
   483  	validId := []string{
   484  		"YadaHereAndThere",
   485  		"Valid-5Rule_ID",
   486  		"This . is also %% valid@!)+*(:ID",
   487  		"1234",
   488  		strings.Repeat("W", 255),
   489  	}
   490  	for _, v := range validId {
   491  		_, errors := validateS3BucketReplicationRuleId(v, "id")
   492  		if len(errors) != 0 {
   493  			t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors)
   494  		}
   495  	}
   496  
   497  	invalidId := []string{
   498  		// length > 255
   499  		strings.Repeat("W", 256),
   500  	}
   501  	for _, v := range invalidId {
   502  		_, errors := validateS3BucketReplicationRuleId(v, "id")
   503  		if len(errors) == 0 {
   504  			t.Fatalf("%q should be an invalid replication configuration rule id", v)
   505  		}
   506  	}
   507  }
   508  
   509  func TestValidateS3BucketReplicationRulePrefix(t *testing.T) {
   510  	validId := []string{
   511  		"YadaHereAndThere",
   512  		"Valid-5Rule_ID",
   513  		"This . is also %% valid@!)+*(:ID",
   514  		"1234",
   515  		strings.Repeat("W", 1024),
   516  	}
   517  	for _, v := range validId {
   518  		_, errors := validateS3BucketReplicationRulePrefix(v, "id")
   519  		if len(errors) != 0 {
   520  			t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors)
   521  		}
   522  	}
   523  
   524  	invalidId := []string{
   525  		// length > 1024
   526  		strings.Repeat("W", 1025),
   527  	}
   528  	for _, v := range invalidId {
   529  		_, errors := validateS3BucketReplicationRulePrefix(v, "id")
   530  		if len(errors) == 0 {
   531  			t.Fatalf("%q should be an invalid replication configuration rule id", v)
   532  		}
   533  	}
   534  }
   535  
   536  func TestValidateS3BucketReplicationDestinationStorageClass(t *testing.T) {
   537  	validStorageClass := []string{
   538  		s3.StorageClassStandard,
   539  		s3.StorageClassStandardIa,
   540  		s3.StorageClassReducedRedundancy,
   541  	}
   542  
   543  	for _, v := range validStorageClass {
   544  		_, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class")
   545  		if len(errors) != 0 {
   546  			t.Fatalf("%q should be valid storage class: %q", v, errors)
   547  		}
   548  	}
   549  
   550  	invalidStorageClass := []string{
   551  		"FOO",
   552  		"1234",
   553  	}
   554  	for _, v := range invalidStorageClass {
   555  		_, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class")
   556  		if len(errors) == 0 {
   557  			t.Fatalf("%q should be invalid storage class", v)
   558  		}
   559  	}
   560  }
   561  
   562  func TestValidateS3BucketReplicationRuleStatus(t *testing.T) {
   563  	validRuleStatuses := []string{
   564  		s3.ReplicationRuleStatusEnabled,
   565  		s3.ReplicationRuleStatusDisabled,
   566  	}
   567  
   568  	for _, v := range validRuleStatuses {
   569  		_, errors := validateS3BucketReplicationRuleStatus(v, "status")
   570  		if len(errors) != 0 {
   571  			t.Fatalf("%q should be valid rule status: %q", v, errors)
   572  		}
   573  	}
   574  
   575  	invalidRuleStatuses := []string{
   576  		"FOO",
   577  		"1234",
   578  	}
   579  	for _, v := range invalidRuleStatuses {
   580  		_, errors := validateS3BucketReplicationRuleStatus(v, "status")
   581  		if len(errors) == 0 {
   582  			t.Fatalf("%q should be invalid rule status", v)
   583  		}
   584  	}
   585  }
   586  
   587  func TestValidateS3BucketLifecycleRuleId(t *testing.T) {
   588  	validId := []string{
   589  		"YadaHereAndThere",
   590  		"Valid-5Rule_ID",
   591  		"This . is also %% valid@!)+*(:ID",
   592  		"1234",
   593  		strings.Repeat("W", 255),
   594  	}
   595  	for _, v := range validId {
   596  		_, errors := validateS3BucketLifecycleRuleId(v, "id")
   597  		if len(errors) != 0 {
   598  			t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors)
   599  		}
   600  	}
   601  
   602  	invalidId := []string{
   603  		// length > 255
   604  		strings.Repeat("W", 256),
   605  	}
   606  	for _, v := range invalidId {
   607  		_, errors := validateS3BucketLifecycleRuleId(v, "id")
   608  		if len(errors) == 0 {
   609  			t.Fatalf("%q should be an invalid lifecycle rule id", v)
   610  		}
   611  	}
   612  }
   613  
   614  func TestValidateIntegerInRange(t *testing.T) {
   615  	validIntegers := []int{-259, 0, 1, 5, 999}
   616  	min := -259
   617  	max := 999
   618  	for _, v := range validIntegers {
   619  		_, errors := validateIntegerInRange(min, max)(v, "name")
   620  		if len(errors) != 0 {
   621  			t.Fatalf("%q should be an integer in range (%d, %d): %q", v, min, max, errors)
   622  		}
   623  	}
   624  
   625  	invalidIntegers := []int{-260, -99999, 1000, 25678}
   626  	for _, v := range invalidIntegers {
   627  		_, errors := validateIntegerInRange(min, max)(v, "name")
   628  		if len(errors) == 0 {
   629  			t.Fatalf("%q should be an integer outside range (%d, %d)", v, min, max)
   630  		}
   631  	}
   632  }
   633  
   634  func TestResourceAWSElastiCacheClusterIdValidation(t *testing.T) {
   635  	cases := []struct {
   636  		Value    string
   637  		ErrCount int
   638  	}{
   639  		{
   640  			Value:    "tEsting",
   641  			ErrCount: 1,
   642  		},
   643  		{
   644  			Value:    "t.sting",
   645  			ErrCount: 1,
   646  		},
   647  		{
   648  			Value:    "t--sting",
   649  			ErrCount: 1,
   650  		},
   651  		{
   652  			Value:    "1testing",
   653  			ErrCount: 1,
   654  		},
   655  		{
   656  			Value:    "testing-",
   657  			ErrCount: 1,
   658  		},
   659  		{
   660  			Value:    randomString(65),
   661  			ErrCount: 1,
   662  		},
   663  	}
   664  
   665  	for _, tc := range cases {
   666  		_, errors := validateElastiCacheClusterId(tc.Value, "aws_elasticache_cluster_cluster_id")
   667  
   668  		if len(errors) != tc.ErrCount {
   669  			t.Fatalf("Expected the ElastiCache Cluster cluster_id to trigger a validation error")
   670  		}
   671  	}
   672  }
   673  
   674  func TestValidateDbEventSubscriptionName(t *testing.T) {
   675  	validNames := []string{
   676  		"valid-name",
   677  		"valid02-name",
   678  		"Valid-Name1",
   679  	}
   680  	for _, v := range validNames {
   681  		_, errors := validateDbEventSubscriptionName(v, "name")
   682  		if len(errors) != 0 {
   683  			t.Fatalf("%q should be a valid RDS Event Subscription Name: %q", v, errors)
   684  		}
   685  	}
   686  
   687  	invalidNames := []string{
   688  		"Here is a name with: colon",
   689  		"and here is another * invalid name",
   690  		"also $ invalid",
   691  		"This . is also %% invalid@!)+(",
   692  		"*",
   693  		"",
   694  		" ",
   695  		"_",
   696  		// length > 255
   697  		strings.Repeat("W", 256),
   698  	}
   699  	for _, v := range invalidNames {
   700  		_, errors := validateDbEventSubscriptionName(v, "name")
   701  		if len(errors) == 0 {
   702  			t.Fatalf("%q should be an invalid RDS Event Subscription Name", v)
   703  		}
   704  	}
   705  }
   706  
   707  func TestValidateJsonString(t *testing.T) {
   708  	type testCases struct {
   709  		Value    string
   710  		ErrCount int
   711  	}
   712  
   713  	invalidCases := []testCases{
   714  		{
   715  			Value:    `{0:"1"}`,
   716  			ErrCount: 1,
   717  		},
   718  		{
   719  			Value:    `{'abc':1}`,
   720  			ErrCount: 1,
   721  		},
   722  		{
   723  			Value:    `{"def":}`,
   724  			ErrCount: 1,
   725  		},
   726  		{
   727  			Value:    `{"xyz":[}}`,
   728  			ErrCount: 1,
   729  		},
   730  	}
   731  
   732  	for _, tc := range invalidCases {
   733  		_, errors := validateJsonString(tc.Value, "json")
   734  		if len(errors) != tc.ErrCount {
   735  			t.Fatalf("Expected %q to trigger a validation error.", tc.Value)
   736  		}
   737  	}
   738  
   739  	validCases := []testCases{
   740  		{
   741  			Value:    ``,
   742  			ErrCount: 0,
   743  		},
   744  		{
   745  			Value:    `{}`,
   746  			ErrCount: 0,
   747  		},
   748  		{
   749  			Value:    `{"abc":["1","2"]}`,
   750  			ErrCount: 0,
   751  		},
   752  	}
   753  
   754  	for _, tc := range validCases {
   755  		_, errors := validateJsonString(tc.Value, "json")
   756  		if len(errors) != tc.ErrCount {
   757  			t.Fatalf("Expected %q not to trigger a validation error.", tc.Value)
   758  		}
   759  	}
   760  }
   761  
   762  func TestValidateApiGatewayIntegrationType(t *testing.T) {
   763  	type testCases struct {
   764  		Value    string
   765  		ErrCount int
   766  	}
   767  
   768  	invalidCases := []testCases{
   769  		{
   770  			Value:    "incorrect",
   771  			ErrCount: 1,
   772  		},
   773  		{
   774  			Value:    "aws_proxy",
   775  			ErrCount: 1,
   776  		},
   777  	}
   778  
   779  	for _, tc := range invalidCases {
   780  		_, errors := validateApiGatewayIntegrationType(tc.Value, "types")
   781  		if len(errors) != tc.ErrCount {
   782  			t.Fatalf("Expected %q to trigger a validation error.", tc.Value)
   783  		}
   784  	}
   785  
   786  	validCases := []testCases{
   787  		{
   788  			Value:    "MOCK",
   789  			ErrCount: 0,
   790  		},
   791  		{
   792  			Value:    "AWS_PROXY",
   793  			ErrCount: 0,
   794  		},
   795  	}
   796  
   797  	for _, tc := range validCases {
   798  		_, errors := validateApiGatewayIntegrationType(tc.Value, "types")
   799  		if len(errors) != tc.ErrCount {
   800  			t.Fatalf("Expected %q not to trigger a validation error.", tc.Value)
   801  		}
   802  	}
   803  }
   804  
   805  func TestValidateSQSQueueName(t *testing.T) {
   806  	validNames := []string{
   807  		"valid-name",
   808  		"valid02-name",
   809  		"Valid-Name1",
   810  		"_",
   811  		"-",
   812  		strings.Repeat("W", 80),
   813  	}
   814  	for _, v := range validNames {
   815  		if errors := validateSQSQueueName(v, "name"); len(errors) > 0 {
   816  			t.Fatalf("%q should be a valid SQS queue Name", v)
   817  		}
   818  	}
   819  
   820  	invalidNames := []string{
   821  		"Here is a name with: colon",
   822  		"another * invalid name",
   823  		"also $ invalid",
   824  		"This . is also %% invalid@!)+(",
   825  		"*",
   826  		"",
   827  		" ",
   828  		".",
   829  		strings.Repeat("W", 81), // length > 80
   830  	}
   831  	for _, v := range invalidNames {
   832  		if errors := validateSQSQueueName(v, "name"); len(errors) == 0 {
   833  			t.Fatalf("%q should be an invalid SQS queue Name", v)
   834  		}
   835  	}
   836  }
   837  
   838  func TestValidateSQSFifoQueueName(t *testing.T) {
   839  	validNames := []string{
   840  		"valid-name.fifo",
   841  		"valid02-name.fifo",
   842  		"Valid-Name1.fifo",
   843  		"_.fifo",
   844  		"a.fifo",
   845  		"A.fifo",
   846  		"9.fifo",
   847  		"-.fifo",
   848  		fmt.Sprintf("%s.fifo", strings.Repeat("W", 75)),
   849  	}
   850  	for _, v := range validNames {
   851  		if errors := validateSQSFifoQueueName(v, "name"); len(errors) > 0 {
   852  			t.Fatalf("%q should be a valid SQS FIFO queue Name: %v", v, errors)
   853  		}
   854  	}
   855  
   856  	invalidNames := []string{
   857  		"Here is a name with: colon",
   858  		"another * invalid name",
   859  		"also $ invalid",
   860  		"This . is also %% invalid@!)+(",
   861  		".fifo",
   862  		"*",
   863  		"",
   864  		" ",
   865  		".",
   866  		strings.Repeat("W", 81), // length > 80
   867  	}
   868  	for _, v := range invalidNames {
   869  		if errors := validateSQSFifoQueueName(v, "name"); len(errors) == 0 {
   870  			t.Fatalf("%q should be an invalid SQS FIFO queue Name: %v", v, errors)
   871  		}
   872  	}
   873  }
   874  
   875  func TestValidateSNSSubscriptionProtocol(t *testing.T) {
   876  	validProtocols := []string{
   877  		"lambda",
   878  		"sqs",
   879  		"sqs",
   880  		"application",
   881  		"http",
   882  		"https",
   883  	}
   884  	for _, v := range validProtocols {
   885  		if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) > 0 {
   886  			t.Fatalf("%q should be a valid SNS Subscription protocol: %v", v, errors)
   887  		}
   888  	}
   889  
   890  	invalidProtocols := []string{
   891  		"Email",
   892  		"email",
   893  		"Email-JSON",
   894  		"email-json",
   895  		"SMS",
   896  		"sms",
   897  	}
   898  	for _, v := range invalidProtocols {
   899  		if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) == 0 {
   900  			t.Fatalf("%q should be an invalid SNS Subscription protocol: %v", v, errors)
   901  		}
   902  	}
   903  }
   904  
   905  func TestValidateSecurityRuleType(t *testing.T) {
   906  	validTypes := []string{
   907  		"ingress",
   908  		"egress",
   909  	}
   910  	for _, v := range validTypes {
   911  		if _, errors := validateSecurityRuleType(v, "type"); len(errors) > 0 {
   912  			t.Fatalf("%q should be a valid Security Group Rule type: %v", v, errors)
   913  		}
   914  	}
   915  
   916  	invalidTypes := []string{
   917  		"foo",
   918  		"ingresss",
   919  	}
   920  	for _, v := range invalidTypes {
   921  		if _, errors := validateSecurityRuleType(v, "type"); len(errors) == 0 {
   922  			t.Fatalf("%q should be an invalid Security Group Rule type: %v", v, errors)
   923  		}
   924  	}
   925  }
   926  
   927  func TestValidateOnceAWeekWindowFormat(t *testing.T) {
   928  	cases := []struct {
   929  		Value    string
   930  		ErrCount int
   931  	}{
   932  		{
   933  			// once a day window format
   934  			Value:    "04:00-05:00",
   935  			ErrCount: 1,
   936  		},
   937  		{
   938  			// invalid day of week
   939  			Value:    "san:04:00-san:05:00",
   940  			ErrCount: 1,
   941  		},
   942  		{
   943  			// invalid hour
   944  			Value:    "sun:24:00-san:25:00",
   945  			ErrCount: 1,
   946  		},
   947  		{
   948  			// invalid min
   949  			Value:    "sun:04:00-sun:04:60",
   950  			ErrCount: 1,
   951  		},
   952  		{
   953  			// valid format
   954  			Value:    "sun:04:00-sun:05:00",
   955  			ErrCount: 0,
   956  		},
   957  		{
   958  			// "Sun" can also be used
   959  			Value:    "Sun:04:00-Sun:05:00",
   960  			ErrCount: 0,
   961  		},
   962  	}
   963  
   964  	for _, tc := range cases {
   965  		_, errors := validateOnceAWeekWindowFormat(tc.Value, "maintenance_window")
   966  
   967  		if len(errors) != tc.ErrCount {
   968  			t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value)
   969  		}
   970  	}
   971  }
   972  
   973  func TestValidateOnceADayWindowFormat(t *testing.T) {
   974  	cases := []struct {
   975  		Value    string
   976  		ErrCount int
   977  	}{
   978  		{
   979  			// once a week window format
   980  			Value:    "sun:04:00-sun:05:00",
   981  			ErrCount: 1,
   982  		},
   983  		{
   984  			// invalid hour
   985  			Value:    "24:00-25:00",
   986  			ErrCount: 1,
   987  		},
   988  		{
   989  			// invalid min
   990  			Value:    "04:00-04:60",
   991  			ErrCount: 1,
   992  		},
   993  		{
   994  			// valid format
   995  			Value:    "04:00-05:00",
   996  			ErrCount: 0,
   997  		},
   998  	}
   999  
  1000  	for _, tc := range cases {
  1001  		_, errors := validateOnceADayWindowFormat(tc.Value, "backup_window")
  1002  
  1003  		if len(errors) != tc.ErrCount {
  1004  			t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value)
  1005  		}
  1006  	}
  1007  }
  1008  
  1009  func TestValidateRoute53RecordType(t *testing.T) {
  1010  	validTypes := []string{
  1011  		"AAAA",
  1012  		"SOA",
  1013  		"A",
  1014  		"TXT",
  1015  		"CNAME",
  1016  		"MX",
  1017  		"NAPTR",
  1018  		"PTR",
  1019  		"SPF",
  1020  		"SRV",
  1021  		"NS",
  1022  	}
  1023  
  1024  	invalidTypes := []string{
  1025  		"a",
  1026  		"alias",
  1027  		"SpF",
  1028  		"Txt",
  1029  		"AaAA",
  1030  	}
  1031  
  1032  	for _, v := range validTypes {
  1033  		_, errors := validateRoute53RecordType(v, "route53_record")
  1034  		if len(errors) != 0 {
  1035  			t.Fatalf("%q should be a valid Route53 record type: %v", v, errors)
  1036  		}
  1037  	}
  1038  
  1039  	for _, v := range invalidTypes {
  1040  		_, errors := validateRoute53RecordType(v, "route53_record")
  1041  		if len(errors) == 0 {
  1042  			t.Fatalf("%q should not be a valid Route53 record type", v)
  1043  		}
  1044  	}
  1045  }