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