From f00857ca7379b3a66ae80158b512f6b02c77e2e0 Mon Sep 17 00:00:00 2001 From: Sharon Nam Date: Mon, 26 Jun 2023 16:46:01 -0700 Subject: [PATCH] Add unit test --- internal/service/events/rule.go | 61 +++++++++++++++------------- internal/service/events/rule_test.go | 36 ++++++++++++++++ 2 files changed, 68 insertions(+), 29 deletions(-) diff --git a/internal/service/events/rule.go b/internal/service/events/rule.go index df25ef6b686a..89d5dd35dbcc 100644 --- a/internal/service/events/rule.go +++ b/internal/service/events/rule.go @@ -14,7 +14,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" @@ -67,7 +66,7 @@ func ResourceRule() *schema.Resource { ValidateFunc: validateEventPatternValue(), AtLeastOneOf: []string{"schedule_expression", "event_pattern"}, StateFunc: func(v interface{}) string { - json, _ := jsonMarshal(v.(string)) + json, _ := RuleEventPatternJSONDecoder(v.(string)) return json }, }, @@ -111,30 +110,6 @@ func ResourceRule() *schema.Resource { } } -func jsonMarshal(jsonString interface{}) (string, error) { - var j interface{} - - if jsonString == nil || jsonString.(string) == "" { - return "", nil - } - - s := jsonString.(string) - - err := json.Unmarshal([]byte(s), &j) - if err != nil { - return s, err - } - - b, _ := json.Marshal(j) - - if bytes.Contains(b, []byte("\\u003c")) || bytes.Contains(b, []byte("\\u003e")) || bytes.Contains(b, []byte("\\u0026")) { - b = bytes.Replace(b, []byte("\\u003c"), []byte("<"), -1) - b = bytes.Replace(b, []byte("\\u003e"), []byte(">"), -1) - b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1) - } - return string(b[:]), nil -} - func resourceRuleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).EventsConn(ctx) @@ -211,7 +186,7 @@ func resourceRuleRead(ctx context.Context, d *schema.ResourceData, meta interfac d.Set("description", output.Description) d.Set("event_bus_name", eventBusName) // Use event bus name from resource ID as API response may collapse any ARN. if output.EventPattern != nil { - pattern, err := structure.NormalizeJsonString(aws.StringValue(output.EventPattern)) + pattern, err := RuleEventPatternJSONDecoder(aws.StringValue(output.EventPattern)) if err != nil { return sdkdiag.AppendErrorf(diags, "event pattern contains an invalid JSON: %s", err) } @@ -321,6 +296,34 @@ func FindRuleByTwoPartKey(ctx context.Context, conn *eventbridge.EventBridge, ev return output, nil } +// Decodes unicode translation of <,>,& +func RuleEventPatternJSONDecoder(jsonString interface{}) (string, error) { + var j interface{} + + if jsonString == nil || jsonString.(string) == "" { + return "", nil + } + + s := jsonString.(string) + + err := json.Unmarshal([]byte(s), &j) + if err != nil { + return s, err + } + + b, err := json.Marshal(j) + if err != nil { + return "", err + } + + if bytes.Contains(b, []byte("\\u003c")) || bytes.Contains(b, []byte("\\u003e")) || bytes.Contains(b, []byte("\\u0026")) { + b = bytes.Replace(b, []byte("\\u003c"), []byte("<"), -1) + b = bytes.Replace(b, []byte("\\u003e"), []byte(">"), -1) + b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1) + } + return string(b[:]), nil +} + func expandPutRuleInput(d *schema.ResourceData, name string) *eventbridge.PutRuleInput { apiObject := &eventbridge.PutRuleInput{ Name: aws.String(name), @@ -335,7 +338,7 @@ func expandPutRuleInput(d *schema.ResourceData, name string) *eventbridge.PutRul } if v, ok := d.GetOk("event_pattern"); ok { - json, _ := structure.NormalizeJsonString(v) + json, _ := RuleEventPatternJSONDecoder(v.(string)) apiObject.EventPattern = aws.String(json) } @@ -358,7 +361,7 @@ func expandPutRuleInput(d *schema.ResourceData, name string) *eventbridge.PutRul func validateEventPatternValue() schema.SchemaValidateFunc { return func(v interface{}, k string) (ws []string, errors []error) { - json, err := structure.NormalizeJsonString(v) + json, err := RuleEventPatternJSONDecoder(v.(string)) if err != nil { errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %w", k, err)) diff --git a/internal/service/events/rule_test.go b/internal/service/events/rule_test.go index 6383dff823ce..36939b5fffd0 100644 --- a/internal/service/events/rule_test.go +++ b/internal/service/events/rule_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/eventbridge" + "github.com/google/go-cmp/cmp" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -29,6 +30,41 @@ func testAccErrorCheckSkip(t *testing.T) resource.ErrorCheckFunc { ) } +func TestRuleEventPatternJSONDecoder(t *testing.T) { + t.Parallel() + + type testCase struct { + input string + expected string + } + tests := map[string]testCase{ + "lessThanGreaterThan": { + input: `{"detail": {"count": [ { "numeric": [ "\\u003e", 0, "\\u003c", 5 ] } ]}}`, + expected: `{"detail": {"count": [ { "numeric": [ ">", 0, "<", 5 ] } ]}}`, + }, + "ampersand": { + input: `{"detail": {"count": [ { "numeric": [ "\\u0026", 0, "\\u0026", 5 ] } ]}}`, + expected: `{"detail": {"count": [ { "numeric": [ "&", 0, "&", 5 ] } ]}}`, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := tfevents.RuleEventPatternJSONDecoder(test.input) + if err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestAccEventsRule_basic(t *testing.T) { ctx := acctest.Context(t) var v1, v2, v3 eventbridge.DescribeRuleOutput