Skip to content

Commit

Permalink
unit tests and enable tests in CI
Browse files Browse the repository at this point in the history
  • Loading branch information
maastha committed Apr 23, 2024
1 parent 76d37c1 commit 3b46526
Show file tree
Hide file tree
Showing 4 changed files with 342 additions and 4 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/acceptance-tests-runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ jobs:
search_index: ${{ steps.filter.outputs.search_index == 'true' || env.mustTrigger == 'true' }}
serverless: ${{ steps.filter.outputs.serverless == 'true' || env.mustTrigger == 'true' }}
stream: ${{ steps.filter.outputs.stream == 'true' || env.mustTrigger == 'true' }}
push_based_log_export: ${{ steps.filter.outputs.push_based_log_export == 'true' || env.mustTrigger == 'true' }}
steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
Expand Down Expand Up @@ -234,6 +235,8 @@ jobs:
stream:
- 'internal/service/streamconnection/*.go'
- 'internal/service/streaminstance/*.go'
push_based_log_export:
- 'internal/service/pushbasedlogexport/*.go'
advanced_cluster:
needs: [ change-detection, get-provider-version ]
Expand Down Expand Up @@ -727,3 +730,27 @@ jobs:
./internal/service/streamconnection
./internal/service/streaminstance
run: make testacc

push_based_log_export:
needs: [ change-detection, get-provider-version ]
if: ${{ needs.change-detection.outputs.push_based_log_export == 'true' || inputs.test_group == 'push_based_log_export' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
with:
ref: ${{ inputs.ref || github.ref }}
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
with:
go-version-file: 'go.mod'
- uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36
with:
terraform_version: ${{ inputs.terraform_version }}
terraform_wrapper: false
- name: Acceptance Tests
env:
AWS_REGION: ${{ vars.AWS_REGION }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
MONGODB_ATLAS_LAST_VERSION: ${{ needs.get-provider-version.outputs.provider_version }}
ACCTEST_PACKAGES: ./internal/service/pushbasedlogexport
run: make testacc
149 changes: 149 additions & 0 deletions internal/service/pushbasedlogexport/model_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package pushbasedlogexport_test

import (
"context"
"reflect"
"testing"
"time"

"go.mongodb.org/atlas-sdk/v20231115010/admin"

"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion"
"github.com/mongodb/terraform-provider-mongodbatlas/internal/service/pushbasedlogexport"
)

var (
testBucketName = "test-bucket-name"
testIAMRoleID = "661fe3ad234b02027ddee196"
testPrefixPath = "prefix/path"
prefixPathEmpty = ""
testProjectID = "661fe3ad234b02027dabcabc"
)

type sdkToTFModelTestCase struct {
apiResp *admin.PushBasedLogExportProject
timeout *timeouts.Value
expectedTFModel *pushbasedlogexport.TFPushBasedLogExportRSModel
name string
projectID string
}

func TestNewTFPushBasedLogExport(t *testing.T) {
currentTime := time.Now()

testCases := []sdkToTFModelTestCase{
{
name: "Complete API response",
projectID: testProjectID,
apiResp: &admin.PushBasedLogExportProject{
BucketName: admin.PtrString(testBucketName),
CreateDate: admin.PtrTime(currentTime),
IamRoleId: admin.PtrString(testIAMRoleID),
PrefixPath: admin.PtrString(testPrefixPath),
State: admin.PtrString(activeState),
},
expectedTFModel: &pushbasedlogexport.TFPushBasedLogExportRSModel{
ProjectID: types.StringValue(testProjectID),
BucketName: types.StringValue(testBucketName),
IamRoleID: types.StringValue(testIAMRoleID),
PrefixPath: types.StringValue(testPrefixPath),
State: types.StringValue(activeState),
CreateDate: types.StringPointerValue(conversion.TimePtrToStringPtr(&currentTime)),
},
},
{
name: "Complete API response with empty prefix path",
projectID: testProjectID,
apiResp: &admin.PushBasedLogExportProject{
BucketName: admin.PtrString(testBucketName),
CreateDate: admin.PtrTime(currentTime),
IamRoleId: admin.PtrString(testIAMRoleID),
PrefixPath: admin.PtrString(prefixPathEmpty),
State: admin.PtrString(activeState),
},
expectedTFModel: &pushbasedlogexport.TFPushBasedLogExportRSModel{
ProjectID: types.StringValue(testProjectID),
BucketName: types.StringValue(testBucketName),
IamRoleID: types.StringValue(testIAMRoleID),
PrefixPath: types.StringValue(prefixPathEmpty),
State: types.StringValue(activeState),
CreateDate: types.StringPointerValue(conversion.TimePtrToStringPtr(&currentTime)),
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
resultModel, _ := pushbasedlogexport.NewTFPushBasedLogExport(context.Background(), tc.projectID, tc.apiResp, tc.timeout)
if !reflect.DeepEqual(resultModel, tc.expectedTFModel) {
t.Errorf("result model does not match expected output: expected %+v, got %+v", tc.expectedTFModel, resultModel)
}
})
}
}

type pushBasedLogExportReqTestCase struct {
input *pushbasedlogexport.TFPushBasedLogExportRSModel
expectedCreateReq *admin.CreatePushBasedLogExportProjectRequest
expectedUpdateReq *admin.PushBasedLogExportProject
name string
}

func TestNewPushBasedLogExportReq(t *testing.T) {
testCases := []pushBasedLogExportReqTestCase{
{
name: "Valid TF state",
input: &pushbasedlogexport.TFPushBasedLogExportRSModel{
BucketName: types.StringValue(testBucketName),
IamRoleID: types.StringValue(testIAMRoleID),
PrefixPath: types.StringValue(testPrefixPath),
},
expectedCreateReq: &admin.CreatePushBasedLogExportProjectRequest{
BucketName: testBucketName,
IamRoleId: testIAMRoleID,
PrefixPath: testPrefixPath,
},
expectedUpdateReq: &admin.PushBasedLogExportProject{
BucketName: admin.PtrString(testBucketName),
IamRoleId: admin.PtrString(testIAMRoleID),
PrefixPath: admin.PtrString(testPrefixPath),
},
},
{
name: "Valid TF state",
input: &pushbasedlogexport.TFPushBasedLogExportRSModel{
BucketName: types.StringValue(testBucketName),
IamRoleID: types.StringValue(testIAMRoleID),
PrefixPath: types.StringValue(prefixPathEmpty),
},
expectedCreateReq: &admin.CreatePushBasedLogExportProjectRequest{
BucketName: testBucketName,
IamRoleId: testIAMRoleID,
PrefixPath: prefixPathEmpty,
},
expectedUpdateReq: &admin.PushBasedLogExportProject{
BucketName: admin.PtrString(testBucketName),
IamRoleId: admin.PtrString(testIAMRoleID),
PrefixPath: admin.PtrString(prefixPathEmpty),
},
},
}

for _, tc := range testCases {
t.Run(tc.name+" Create", func(t *testing.T) {
createReq := pushbasedlogexport.NewPushBasedLogExportCreateReq(tc.input)
if !reflect.DeepEqual(createReq, tc.expectedCreateReq) {
t.Errorf("Create request does not match expected output: expected %+v, got %+v", tc.expectedCreateReq, createReq)
}
})
t.Run(tc.name+" Update", func(t *testing.T) {
updateReq := pushbasedlogexport.NewPushBasedLogExportUpdateReq(tc.input)
if !reflect.DeepEqual(updateReq, tc.expectedUpdateReq) {
t.Errorf("Update request does not match expected output: expected %+v, got %+v", tc.expectedUpdateReq, updateReq)
}
})
}
}
4 changes: 0 additions & 4 deletions internal/service/pushbasedlogexport/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,7 @@ func addAttrChecks(checks []resource.TestCheckFunc, mapChecks map[string]string)
func configBasic(projectID, s3BucketName1, s3BucketName2, s3BucketPolicyName, awsIAMRoleName, awsIAMRolePolicyName, prefixPath string, usePrefixPath bool) string {
test := fmt.Sprintf(`
locals {
#project_name = %[1]q
project_id = %[1]q
#org_id = %[2]q
s3_bucket_name_1 = %[2]q
s3_bucket_name_2 = %[3]q
s3_bucket_policy_name = %[4]q
Expand All @@ -131,9 +129,7 @@ func configBasic(projectID, s3BucketName1, s3BucketName2, s3BucketPolicyName, aw
func configBasicUpdated(projectID, s3BucketName1, s3BucketName2, s3BucketPolicyName, awsIAMRoleName, awsIAMRolePolicyName, prefixPath string, usePrefixPath bool) string {
test := fmt.Sprintf(`
locals {
#project_name = %[1]q
project_id = %[1]q
#org_id = %[2]q
s3_bucket_name_1 = %[2]q
s3_bucket_name_2 = %[3]q
s3_bucket_policy_name = %[4]q
Expand Down
166 changes: 166 additions & 0 deletions internal/service/pushbasedlogexport/state_transition_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package pushbasedlogexport_test

import (
"context"
"errors"
"net/http"
"testing"
"time"

"go.mongodb.org/atlas-sdk/v20231115010/admin"
"go.mongodb.org/atlas-sdk/v20231115010/mockadmin"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion"
"github.com/mongodb/terraform-provider-mongodbatlas/internal/common/retrystrategy"
"github.com/mongodb/terraform-provider-mongodbatlas/internal/service/pushbasedlogexport"
)

var (
activeState = "ACTIVE"
unconfiguredState = "UNCONFIGURED"
initiatingState = "INITIATING"
bucketVerifiedState = "BUCKET_VERIFIED"
assumeRoleFailedState = "ASSUME_ROLE_FAILED"
unknown = ""
sc500 = conversion.IntPtr(500)
currentTime = time.Now()
)

var testTimeoutConfig = retrystrategy.TimeConfig{
Timeout: 30 * time.Second,
MinTimeout: 100 * time.Millisecond,
Delay: 0,
}

type testCase struct {
expectedState *string
name string
mockResponses []response
expectedError bool
}

func TestPushBasedLogExportStateTransition(t *testing.T) {
testCases := []testCase{
{
name: "Successful transition to ACTIVE",
mockResponses: []response{
{state: &initiatingState},
{state: &bucketVerifiedState},
{state: &activeState},
},
expectedState: &activeState,
expectedError: false,
},
{
name: "Error when transitioning to an unknown state",
mockResponses: []response{
{state: &initiatingState},
{state: &assumeRoleFailedState},
},
expectedState: nil,
expectedError: true,
},
{
name: "Error when API responds with error",
mockResponses: []response{
{statusCode: sc500, err: errors.New("Internal server error")},
},
expectedState: nil,
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
m := mockadmin.NewPushBasedLogExportApi(t)
m.EXPECT().GetPushBasedLogConfiguration(mock.Anything, mock.Anything).Return(admin.GetPushBasedLogConfigurationApiRequest{ApiService: m})

for _, resp := range tc.mockResponses {
modelResp, httpResp, err := resp.get()
m.EXPECT().GetPushBasedLogConfigurationExecute(mock.Anything).Return(modelResp, httpResp, err).Once()
}
resp, err := pushbasedlogexport.WaitStateTransition(context.Background(), testProjectID, m, testTimeoutConfig)
assert.Equal(t, tc.expectedError, err != nil)
assert.Equal(t, responseWithState(tc.expectedState), resp)
})
}
}

func TestPushBasedLogExportStateTransitionForDelete(t *testing.T) {
testCases := []testCase{
{
name: "Successful transition to UNCONFIGURED from ACTIVE",
mockResponses: []response{
{state: &activeState},
{state: &unconfiguredState},
},
expectedError: false,
},
{
name: "Successful transition to UNCONFIGURED",
mockResponses: []response{
{state: &unconfiguredState},
},
expectedError: false,
},
{
name: "Error when API responds with error",
mockResponses: []response{
{statusCode: sc500, err: errors.New("Internal server error")},
},
expectedError: true,
},
{
name: "Failed delete when responding with unknown state",
mockResponses: []response{
{state: &activeState},
{state: &unknown},
},
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
m := mockadmin.NewPushBasedLogExportApi(t)
m.EXPECT().GetPushBasedLogConfiguration(mock.Anything, mock.Anything).Return(admin.GetPushBasedLogConfigurationApiRequest{ApiService: m})

for _, resp := range tc.mockResponses {
modelResp, httpResp, err := resp.get()
m.EXPECT().GetPushBasedLogConfigurationExecute(mock.Anything).Return(modelResp, httpResp, err).Once()
}
err := pushbasedlogexport.WaitResourceDelete(context.Background(), testProjectID, m, testTimeoutConfig)
assert.Equal(t, tc.expectedError, err != nil)
})
}
}

type response struct {
state *string
statusCode *int
err error
}

func (r *response) get() (*admin.PushBasedLogExportProject, *http.Response, error) {
var httpResp *http.Response
if r.statusCode != nil {
httpResp = &http.Response{StatusCode: *r.statusCode}
}
return responseWithState(r.state), httpResp, r.err
}

func responseWithState(state *string) *admin.PushBasedLogExportProject {
if state == nil {
return nil
}
return &admin.PushBasedLogExportProject{
BucketName: admin.PtrString(testBucketName),
CreateDate: admin.PtrTime(currentTime),
IamRoleId: admin.PtrString(testIAMRoleID),
PrefixPath: admin.PtrString(testPrefixPath),
State: state,
}
}

0 comments on commit 3b46526

Please sign in to comment.