Browse Source

chore: refactor parameterstore unit test (#164)

* new parameterstoreTestCase struct
* remove swp files
* ignore vim swp
* refactor TestGetSecretMap
* refactor TestGetSecret
* add api error test
* fix test case
Lee Wei 4 years ago
parent
commit
add9c81932
2 changed files with 144 additions and 198 deletions
  1. 3 0
      .gitignore
  2. 141 198
      pkg/provider/aws/parameterstore/parameterstore_test.go

+ 3 - 0
.gitignore

@@ -2,6 +2,9 @@
 /vendor
 /vendor
 cover.out
 cover.out
 
 
+# ignore vim swp
+*.swp
+
 # ignore ide files (debug config etc...)
 # ignore ide files (debug config etc...)
 /.vscode
 /.vscode
 /.idea
 /.idea

+ 141 - 198
pkg/provider/aws/parameterstore/parameterstore_test.go

@@ -37,216 +37,159 @@ func TestConstructor(t *testing.T) {
 	assert.NotNil(t, c.client)
 	assert.NotNil(t, c.client)
 }
 }
 
 
+type parameterstoreTestCase struct {
+	fakeClient     *fake.Client
+	apiInput       *ssm.GetParameterInput
+	apiOutput      *ssm.GetParameterOutput
+	remoteRef      *esv1alpha1.ExternalSecretDataRemoteRef
+	apiErr         error
+	expectError    string
+	expectedSecret string
+	expectedData   map[string]string
+}
+
+func makeValidParameterStoreTestCase() *parameterstoreTestCase {
+	return &parameterstoreTestCase{
+		fakeClient:     &fake.Client{},
+		apiInput:       makeValidAPIInput(),
+		apiOutput:      makeValidAPIOutput(),
+		remoteRef:      makeValidRemoteRef(),
+		apiErr:         nil,
+		expectError:    "",
+		expectedSecret: "",
+		expectedData:   make(map[string]string),
+	}
+}
+
+func makeValidAPIInput() *ssm.GetParameterInput {
+	return &ssm.GetParameterInput{
+		Name:           aws.String("/baz"),
+		WithDecryption: aws.Bool(true),
+	}
+}
+
+func makeValidAPIOutput() *ssm.GetParameterOutput {
+	return &ssm.GetParameterOutput{
+		Parameter: &ssm.Parameter{
+			Value: aws.String("RRRRR"),
+		},
+	}
+}
+
+func makeValidRemoteRef() *esv1alpha1.ExternalSecretDataRemoteRef {
+	return &esv1alpha1.ExternalSecretDataRemoteRef{
+		Key: "/baz",
+	}
+}
+
+func makeValidParameterStoreTestCaseCustom(tweaks ...func(pstc *parameterstoreTestCase)) *parameterstoreTestCase {
+	pstc := makeValidParameterStoreTestCase()
+	for _, fn := range tweaks {
+		fn(pstc)
+	}
+	pstc.fakeClient.WithValue(pstc.apiInput, pstc.apiOutput, pstc.apiErr)
+	return pstc
+}
+
 // test the ssm<->aws interface
 // test the ssm<->aws interface
 // make sure correct values are passed and errors are handled accordingly.
 // make sure correct values are passed and errors are handled accordingly.
 func TestGetSecret(t *testing.T) {
 func TestGetSecret(t *testing.T) {
-	f := &fake.Client{}
-	p := &ParameterStore{
-		client: f,
+	// good case: key is passed in, output is sent back
+	setSecretString := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String("RRRRR")
+		pstc.expectedSecret = "RRRRR"
 	}
 	}
-	for i, row := range []struct {
-		apiInput       *ssm.GetParameterInput
-		apiOutput      *ssm.GetParameterOutput
-		rr             esv1alpha1.ExternalSecretDataRemoteRef
-		apiErr         error
-		expectError    string
-		expectedSecret string
-	}{
-		{
-			// good case: key is passed in, output is sent back
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/baz",
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String("RRRRR"),
-				},
-			},
-			apiErr:         nil,
-			expectError:    "",
-			expectedSecret: "RRRRR",
-		},
-		{
-			// good case: extract property
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key:      "/baz",
-				Property: "/shmoo",
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String(`{"/shmoo": "bang"}`),
-				},
-			},
-			apiErr:         nil,
-			expectError:    "",
-			expectedSecret: "bang",
-		},
-		{
-			// bad case: missing property
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key:      "/baz",
-				Property: "INVALPROP",
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String(`{"/shmoo": "bang"}`),
-				},
-			},
-			apiErr:         nil,
-			expectError:    "key INVALPROP does not exist in secret",
-			expectedSecret: "",
-		},
-		{
-			// bad case: extract property failure due to invalid json
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key:      "/baz",
-				Property: "INVALPROP",
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String(`------`),
-				},
-			},
-			apiErr:         nil,
-			expectError:    "key INVALPROP does not exist in secret",
-			expectedSecret: "",
-		},
-		{
-			// case: parameter.Value may be nil but binary is set
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/baz",
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: nil,
-				},
-			},
-			apiErr:         nil,
-			expectError:    "parameter value is nil for key",
-			expectedSecret: "",
-		},
-		{
-			// should return err
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/foo/bar"),
-				WithDecryption: aws.Bool(true),
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/foo/bar",
-			},
-			apiOutput:   &ssm.GetParameterOutput{},
-			apiErr:      fmt.Errorf("oh no"),
-			expectError: "oh no",
-		},
-	} {
-		f.WithValue(row.apiInput, row.apiOutput, row.apiErr)
-		out, err := p.GetSecret(context.Background(), row.rr)
-		if !ErrorContains(err, row.expectError) {
-			t.Errorf("[%d] unexpected error: %s, expected: '%s'", i, err.Error(), row.expectError)
+
+	// good case: extract property
+	setExtractProperty := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo": "bang"}`)
+		pstc.expectedSecret = "bang"
+		pstc.remoteRef.Property = "/shmoo"
+	}
+
+	// bad case: missing property
+	setMissingProperty := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo": "bang"}`)
+		pstc.remoteRef.Property = "INVALPROP"
+		pstc.expectError = "key INVALPROP does not exist in secret"
+	}
+
+	// bad case: extract property failure due to invalid json
+	setPropertyFail := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`------`)
+		pstc.remoteRef.Property = "INVALPROP"
+		pstc.expectError = "key INVALPROP does not exist in secret"
+	}
+
+	// bad case: parameter.Value may be nil but binary is set
+	setParameterValueNil := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = nil
+		pstc.expectError = "parameter value is nil for key"
+	}
+
+	// base case: api output return error
+	setAPIError := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput = &ssm.GetParameterOutput{}
+		pstc.apiErr = fmt.Errorf("oh no")
+		pstc.expectError = "oh no"
+	}
+
+	successCases := []*parameterstoreTestCase{
+		makeValidParameterStoreTestCaseCustom(setSecretString),
+		makeValidParameterStoreTestCaseCustom(setExtractProperty),
+		makeValidParameterStoreTestCaseCustom(setMissingProperty),
+		makeValidParameterStoreTestCaseCustom(setPropertyFail),
+		makeValidParameterStoreTestCaseCustom(setParameterValueNil),
+		makeValidParameterStoreTestCaseCustom(setAPIError),
+	}
+
+	ps := ParameterStore{}
+	for k, v := range successCases {
+		ps.client = v.fakeClient
+		out, err := ps.GetSecret(context.Background(), *v.remoteRef)
+		if !ErrorContains(err, v.expectError) {
+			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
 		}
 		}
-		if string(out) != row.expectedSecret {
-			t.Errorf("[%d] unexpected secret: expected %s, got %s", i, row.expectedSecret, string(out))
+		if cmp.Equal(out, v.expectedSecret) {
+			t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedSecret, out)
 		}
 		}
 	}
 	}
 }
 }
 
 
 func TestGetSecretMap(t *testing.T) {
 func TestGetSecretMap(t *testing.T) {
-	f := &fake.Client{}
-	p := &ParameterStore{
-		client: f,
+	// good case: default version & deserialization
+	setDeserialization := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`{"foo":"bar"}`)
+		pstc.expectedData["foo"] = "bar"
 	}
 	}
-	for i, row := range []struct {
-		apiInput     *ssm.GetParameterInput
-		apiOutput    *ssm.GetParameterOutput
-		rr           esv1alpha1.ExternalSecretDataRemoteRef
-		expectedData map[string]string
-		apiErr       error
-		expectError  string
-	}{
-		{
-			// good case: default version & deserialization
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String(`{"foo":"bar"}`),
-				},
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/baz",
-			},
-			expectedData: map[string]string{
-				"foo": "bar",
-			},
-			apiErr:      nil,
-			expectError: "",
-		},
-		{
-			// bad case: api error returned
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{},
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/baz",
-			},
-			expectedData: map[string]string{
-				"foo": "bar",
-			},
-			apiErr:      fmt.Errorf("some api err"),
-			expectError: "some api err",
-		},
-		{
-			// bad case: invalid json
-			apiInput: &ssm.GetParameterInput{
-				Name:           aws.String("/baz"),
-				WithDecryption: aws.Bool(true),
-			},
-			apiOutput: &ssm.GetParameterOutput{
-				Parameter: &ssm.Parameter{
-					Value: aws.String(`-----------------`),
-				},
-			},
-			rr: esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "/baz",
-			},
-			expectedData: map[string]string{},
-			apiErr:       nil,
-			expectError:  "unable to unmarshal secret",
-		},
-	} {
-		f.WithValue(row.apiInput, row.apiOutput, row.apiErr)
-		out, err := p.GetSecretMap(context.Background(), row.rr)
-		if !ErrorContains(err, row.expectError) {
-			t.Errorf("[%d] unexpected error: %s, expected: '%s'", i, err.Error(), row.expectError)
+
+	// bad case: api error returned
+	setAPIError := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter = &ssm.Parameter{}
+		pstc.expectError = "some api err"
+		pstc.apiErr = fmt.Errorf("some api err")
+	}
+	// bad case: invalid json
+	setInvalidJSON := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`-----------------`)
+		pstc.expectError = "unable to unmarshal secret"
+	}
+
+	successCases := []*parameterstoreTestCase{
+		makeValidParameterStoreTestCaseCustom(setDeserialization),
+		makeValidParameterStoreTestCaseCustom(setAPIError),
+		makeValidParameterStoreTestCaseCustom(setInvalidJSON),
+	}
+
+	ps := ParameterStore{}
+	for k, v := range successCases {
+		ps.client = v.fakeClient
+		out, err := ps.GetSecretMap(context.Background(), *v.remoteRef)
+		if !ErrorContains(err, v.expectError) {
+			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
 		}
 		}
-		if cmp.Equal(out, row.expectedData) {
-			t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", i, row.expectedData, out)
+		if cmp.Equal(out, v.expectedData) {
+			t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedData, out)
 		}
 		}
 	}
 	}
 }
 }