// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package model import ( "fmt" "strings" "testing" "github.com/stretchr/testify/assert" ) func TestErrorCauseValidationWhenCauseIsValid(t *testing.T) { validCauses := [][]byte{ []byte(`{"paths":[],"working_directory":"/foo/bar/baz","exceptions":[]}`), []byte(`{"paths":["foo", "bar"]}`), []byte(`{"working_directory":"/foo/bar/baz"}`), []byte(`{"exceptions":[{"message": "foo"}, {"message": "bar"}]}`), []byte(`{"exceptions":[{}]}`), []byte(`{"exceptions":[{}], "arbitrary":"field"}`), []byte(`{"message":"foo error"}`), } for _, c := range validCauses { _, err := ValidatedErrorCauseJSON(c) assert.Nil(t, err, "validation failed for valid cause") } } func TestWorkingDirCropping(t *testing.T) { } func TestErrorCauseMarshallingWhenCauseIsValid(t *testing.T) { causesAndExpectations := map[string]string{ `{"paths":[],"working_directory":"/","exceptions":[]}`: `{"paths":[],"working_directory":"/","exceptions":[]}`, `{"paths":["f"]}`: `{"paths":["f"],"working_directory":"","exceptions":null}`, `{"working_directory":"/foo"}`: `{"paths":null,"working_directory":"/foo","exceptions":null}`, `{"exceptions":[{}], "arbitrary":"field"}`: `{"paths":null,"working_directory":"","exceptions":[{}]}`, `{"message":"foo"}`: `{"paths":null,"working_directory":"","exceptions":null,"message":"foo"}`, } for causeJSON, expectedJSON := range causesAndExpectations { validCauseJSON, err := ValidatedErrorCauseJSON([]byte(causeJSON)) assert.Nil(t, err, "validation failed for valid cause") assert.JSONEq(t, string(expectedJSON), string(validCauseJSON)) } } func TestErrorCauseValidationWhenCauseIsInvalid(t *testing.T) { invalidCauses := [][]byte{ []byte(`{"paths":[],"working_directory":"","exceptions":[]}`), []byte(`{"paths":"","working_directory":"","exceptions":[]}`), []byte(`{"paths":"","exceptions":[]}`), []byte(`{foo: invalid}`), []byte(`{}`), []byte(`{"arbitrary":"field"}`), } for _, c := range invalidCauses { causeJSON, err := ValidatedErrorCauseJSON(c) assert.Error(t, err, "validation didn't return an error") assert.Nil(t, causeJSON) } } func TestErrorCauseCroppedJSONForEmptyCause(t *testing.T) { emptyCauseJSON := `{"exceptions":null, "paths":null, "working_directory":""}` cause := ErrorCause{} causeJSON := cause.croppedJSON() assert.JSONEq(t, emptyCauseJSON, string(causeJSON)) } func TestErrorCauseCroppedJSONForLargeCause(t *testing.T) { noOfElements := MaxErrorCauseSizeBytes largeExceptions := make([]exception, noOfElements) for i := range largeExceptions { largeExceptions[i] = exception{Message: "a"} } largePaths := make([]string, noOfElements) for i := range largePaths { largePaths[i] = "a" } largeCause := ErrorCause{ Message: strings.Repeat("a", noOfElements), WorkingDir: strings.Repeat("a", noOfElements), Exceptions: largeExceptions, Paths: largePaths, } expectedStringFieldsLen := (MaxErrorCauseSizeBytes - paddingForFieldNames) / 2 causeJSON := largeCause.croppedJSON() assert.True(t, len(causeJSON) <= MaxErrorCauseSizeBytes, fmt.Sprintf("cropped JSON too long: len=%d", len(causeJSON))) parsedCause, err := newErrorCause(causeJSON) assert.NoError(t, err, "failed to parse constructed JSON") assert.Len(t, parsedCause.Message, expectedStringFieldsLen, "Message length incorrect") assert.Len(t, parsedCause.WorkingDir, expectedStringFieldsLen, "WorkingDir length incorrect") assert.Len(t, parsedCause.Exceptions, 0, "Exceptions length incorrect") assert.Len(t, parsedCause.Paths, 0, "Paths length incorrect") } func TestErrorCauseCroppedJSONForLargeCauseWithOnlyExceptionsAndPaths(t *testing.T) { elementsAndExpectedLengthFactors := map[int]float64{ 100: 0.8, 5000: 0.6, 8000: 0.4, 10000: 0.2, MaxErrorCauseSizeBytes / 4: 0.0, } for noOfElements, factor := range elementsAndExpectedLengthFactors { largeExceptions := make([]exception, noOfElements) for i := range largeExceptions { largeExceptions[i] = exception{Message: "a"} } largePaths := make([]string, noOfElements) for i := range largePaths { largePaths[i] = "a" } largeCause := ErrorCause{ Exceptions: largeExceptions, Paths: largePaths, } causeJSON := largeCause.croppedJSON() assert.True(t, len(causeJSON) <= MaxErrorCauseSizeBytes, fmt.Sprintf("cropped JSON too long: len=%d", len(causeJSON))) parsedCause, err := newErrorCause(causeJSON) assert.NoError(t, err, "failed to parse constructed JSON") assert.Len(t, parsedCause.Message, 0, "Message length incorrect") assert.Len(t, parsedCause.WorkingDir, 0, "WorkingDir length incorrect") assert.Len(t, parsedCause.Exceptions, int(float64(noOfElements)*factor), "Exceptions length incorrect") assert.Len(t, parsedCause.Paths, int(float64(noOfElements)*factor), "Paths length incorrect") } }