Skip to content

Commit

Permalink
test: add unit tests (#1075)
Browse files Browse the repository at this point in the history
This PR intends to add more unit tests to increase the code coverage.

---------

Signed-off-by: Patrick Zheng <[email protected]>
  • Loading branch information
Two-Hearts authored Nov 1, 2024
1 parent eb76e2a commit 445030b
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 10 deletions.
5 changes: 4 additions & 1 deletion .github/.codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ coverage:
status:
project:
default:
target: 70%
target: 70%
patch:
default:
target: 80%
27 changes: 27 additions & 0 deletions cmd/notation/internal/truststore/testdata/NotationTestRoot.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEizCCAvOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEb
MBkGA1UEAxMSTm90YXRpb24gVGVzdCBSb290MCAXDTIwMDkwOTA3MDAwMFoYDzIx
MjIwOTA1MjAzODQ1WjBaMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNV
BAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEbMBkGA1UEAxMSTm90YXRpb24g
VGVzdCBSb290MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxxAZ8VZe
gqBUctz3BkwhObZKnW+KsN5/N1/u2vPLmEzHDj6xgd8Hn0JoughDaxeQCV66NC2o
bqPnPp4+68G/qZnxkXVXdFyqVodu4FgPUjiqcJjft7bh45BVgLFpOqSqDQ3ko30B
7gdGfIIkoBj/8gz3tHnmIvl3MywtOhDeGnlLNzBY52wVmhPIdKOaW/7WkMrXKFCk
LkNICGnIpWuyBtC+7RfM8hG6eRW1KCm5xrkRmn5ptonjxix/JTGj4me/NMkwdVkz
6wcCSAJnqTgHi2oqk73qqNu0LHsEMFBF8IGqmVkn2MOHkFamPBokzQ6HXXfvR4nb
cWQZCUgRinPTVg9CF0B6XSCEMCSH5kveZxTQtAFRB6NosbzuU5jDmJgpbDfauev7
Eg/6bZzphcugRkVuwulymzsake5Jbvs9Kyw3CNPYH2G3Kli1FNhfc46ugXHbIfXg
NQcou3xabcu+r6cFRqqK6NmV9ouMQRj8Ri95Gp2BUlpTEFhcvMb9d4nXAgMBAAGj
WjBYMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMB
Af8ECDAGAQH/AgEBMB0GA1UdDgQWBBS5FZjt9UsEPkcKrStrnjSpTq4kDTANBgkq
hkiG9w0BAQsFAAOCAYEAKtxfv12LzM85bxOMp5++pIDa6eMcBaurYbAM2yC9B6Lu
Hf0JGeFdNqt4Fw38Ajooj2vWMWBrARVEZRVqTC5+ZSN2meGBXBXlT4n8FdEdmv+0
5iwVYdmDFp8FKeoOZZZF23u+r2OrazJo1ufWmoSI2P0lEfZQQFQElltWu3QH+OLO
WXJmB7KbLKyheelGK5XhtAYYapRdW4sKJ398ybpv5C1oALCcTwoSmvH8wW5J4/gj
mhKICYh2goMauf0lesdxj+0His7E8blOWrUmfOB5dp73XawLKcd/UxHN8zAPC08L
DL9NMcihn3ZHKi7/dtkiV2iSaDPD1ChSGdqfXIysYqOhYoktgAfBZ43CWnqQhgB8
NezRKdOStYC3P2AGJW18irxxTRp2CO+gnXEcyhyr+cvyf0j8MkRSaHLXzjIrECu8
BUitB6sKughdN13fs5t5SIiO6foeFdvIpZFFKO8s+4oTOSDCos2WFoC+8TZS6r58
3OtFLmywl1HRgQkobGgw
-----END CERTIFICATE-----
1 change: 1 addition & 0 deletions cmd/notation/internal/truststore/testdata/invalid.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid test cert
20 changes: 20 additions & 0 deletions cmd/notation/internal/truststore/testdata/self-signed.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDPjCCAiagAwIBAgIBeTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEP
MA0GA1UEAxMGYWxwaW5lMB4XDTIzMDUwOTA0NTUxMloXDTMzMDUxMDA0NTUxMlow
TjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8w
DQYDVQQKEwZOb3RhcnkxDzANBgNVBAMTBmFscGluZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK5hpq1229GGLjMK6i9KZhuUO+SV7rUFnWIDiIPO5yWx
YDkl+bGroeAvJYu6MVCMQ6FMRXD9jhnG6R+sAHwY7gVgcJ1OXak87PkLp/Ii1Cr7
XkkySZeD+Br1vSQzfxs3pFG+iBCeVVkeZdsg+xqwnAlqAILXwIbTGRyJP1Xiu9nw
OeuX1YmxPl2m29Pt1EtfVCL9COsVKt5LgOVyWP/9ISWevOBqSCU9bk35HFo9VTeU
f6+ffhSMjv0Y9uwkFFOKXpcV8Sa3ArqyBmgQlUfGg1iwYlqiDE0fTYxiB3gLgETA
lmTm50J+WB9LoDrnrQpbXFLoegm+JV+uSD8J8H7DL2sCAwEAAaMnMCUwDgYDVR0P
AQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IB
AQAt0Nvna1c4pPn8kzoN5VvmFmeIgdO/BJpmdhdg0WIQ9aeN/xPXXaVjPp1Mk7ed
XHAvBwQr0Gyzqyy7g/h0gdnAFG7f6blrRNzbrRBCq6cNqX8iwgK/9+2OYKxk1QWj
8Gx0cvu1DN1aXjPPGgQ2j3tHjJvJv32J/zuZa8gU40RPPSLaBlc5ZjpFmyi29sKl
TeeZ+F/Ssic51qXXw2CsYGGWK5yQ3xSCxbw6bb2G/s/YI7/KlWg9BktBJHzRu04Z
NR77W7/dyJ3Lj17PlW1XKmMOFHsQivagXeRCbmYZ43fX4ugFRFKL7KE0EgmGOWpJ
0xv+6ig93sqHzQ/0uv1YgFov
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDPjCCAiagAwIBAgIBeTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzANBgNVBAoTBk5vdGFyeTEP
MA0GA1UEAxMGYWxwaW5lMB4XDTIzMDUwOTA0NTUxMloXDTMzMDUxMDA0NTUxMlow
TjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8w
DQYDVQQKEwZOb3RhcnkxDzANBgNVBAMTBmFscGluZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK5hpq1229GGLjMK6i9KZhuUO+SV7rUFnWIDiIPO5yWx
YDkl+bGroeAvJYu6MVCMQ6FMRXD9jhnG6R+sAHwY7gVgcJ1OXak87PkLp/Ii1Cr7
XkkySZeD+Br1vSQzfxs3pFG+iBCeVVkeZdsg+xqwnAlqAILXwIbTGRyJP1Xiu9nw
OeuX1YmxPl2m29Pt1EtfVCL9COsVKt5LgOVyWP/9ISWevOBqSCU9bk35HFo9VTeU
f6+ffhSMjv0Y9uwkFFOKXpcV8Sa3ArqyBmgQlUfGg1iwYlqiDE0fTYxiB3gLgETA
lmTm50J+WB9LoDrnrQpbXFLoegm+JV+uSD8J8H7DL2sCAwEAAaMnMCUwDgYDVR0P
AQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IB
AQAt0Nvna1c4pPn8kzoN5VvmFmeIgdO/BJpmdhdg0WIQ9aeN/xPXXaVjPp1Mk7ed
XHAvBwQr0Gyzqyy7g/h0gdnAFG7f6blrRNzbrRBCq6cNqX8iwgK/9+2OYKxk1QWj
8Gx0cvu1DN1aXjPPGgQ2j3tHjJvJv32J/zuZa8gU40RPPSLaBlc5ZjpFmyi29sKl
TeeZ+F/Ssic51qXXw2CsYGGWK5yQ3xSCxbw6bb2G/s/YI7/KlWg9BktBJHzRu04Z
NR77W7/dyJ3Lj17PlW1XKmMOFHsQivagXeRCbmYZ43fX4ugFRFKL7KE0EgmGOWpJ
0xv+6ig93sqHzQ/0uv1YgFov
-----END CERTIFICATE-----
2 changes: 1 addition & 1 deletion cmd/notation/internal/truststore/truststore.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func DeleteCert(storeType, namedStore, cert string, confirmed bool) error {
return nil
}

// CheckNonErrNotExistError returns nil when no err or err is fs.ErrNotExist
// CheckNonErrNotExistError returns nil when err is nil or err is fs.ErrNotExist
func CheckNonErrNotExistError(err error) error {
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
Expand Down
106 changes: 99 additions & 7 deletions cmd/notation/internal/truststore/truststore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,107 @@ package truststore

import (
"errors"
"os"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/notaryproject/notation-go/dir"
)

func TestEmptyCertFile(t *testing.T) {
path := filepath.FromSlash("../../../../internal/testdata/Empty.txt")
expectedErr := errors.New("no valid certificate found in the empty file")
err := AddCert(path, "ca", "test", false)
if err == nil || err.Error() != "no valid certificate found in the file" {
t.Fatalf("expected err: %v, got: %v", expectedErr, err)
}
func TestAddCert(t *testing.T) {
defer func(oldDir string) {
dir.UserConfigDir = oldDir
}(dir.UserConfigDir)

t.Run("empty store type", func(t *testing.T) {
expectedErrMsg := "store type cannot be empty"
err := AddCert("", "", "test", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})

t.Run("invalid store type", func(t *testing.T) {
expectedErrMsg := "unsupported store type: invalid"
err := AddCert("", "invalid", "test", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})

t.Run("invalid store name", func(t *testing.T) {
expectedErrMsg := "named store name needs to follow [a-zA-Z0-9_.-]+ format"
err := AddCert("", "ca", "test%", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})

t.Run("no valid certificate in file", func(t *testing.T) {
path := filepath.FromSlash("testdata/invalid.txt")
expectedErrMsg := "x509: malformed certificate"
err := AddCert(path, "ca", "test", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})

t.Run("cert already exists", func(t *testing.T) {
dir.UserConfigDir = "testdata"
path := filepath.FromSlash("testdata/self-signed.crt")
expectedErrMsg := "certificate already exists in the Trust Store"
err := AddCert(path, "ca", "test", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})

t.Run("empty file", func(t *testing.T) {
path := filepath.FromSlash("../../../../internal/testdata/Empty.txt")
expectedErr := errors.New("no valid certificate found in the empty file")
err := AddCert(path, "ca", "test", false)
if err == nil || err.Error() != "no valid certificate found in the file" {
t.Fatalf("expected err: %v, but got: %v", expectedErr, err)
}
})

t.Run("failed to add cert to store", func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}

dir.UserConfigDir = t.TempDir()
if err := os.Chmod(dir.UserConfigDir, 0000); err != nil {
t.Fatal(err)
}
defer os.Chmod(dir.UserConfigDir, 0700)

path := filepath.FromSlash("testdata/NotationTestRoot.pem")
expectedErrMsg := "permission denied"
err := AddCert(path, "ca", "test", false)
if err == nil || !strings.Contains(err.Error(), expectedErrMsg) {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})
}

func TestDeleteAllCerts(t *testing.T) {
defer func(oldDir string) {
dir.UserConfigDir = oldDir
}(dir.UserConfigDir)

t.Run("store does not exist", func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}

dir.UserConfigDir = "testdata"
expectedErrMsg := `stat testdata/truststore/x509/tsa/test: no such file or directory`
err := DeleteAllCerts("tsa", "test", true)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected err: %v, but got: %v", expectedErrMsg, err)
}
})
}
2 changes: 1 addition & 1 deletion cmd/notation/plugin/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func install(command *cobra.Command, opts *pluginInstallOpts) error {
}
pluginURL, err := url.Parse(opts.pluginSource)
if err != nil {
return fmt.Errorf("failed to parse plugin download URL %s with error: %w", pluginURL, err)
return fmt.Errorf("failed to parse plugin download URL %s with error: %w", opts.pluginSource, err)
}
if pluginURL.Scheme != "https" {
return fmt.Errorf("failed to download plugin from URL: only the HTTPS scheme is supported, but got %s", pluginURL.Scheme)
Expand Down
96 changes: 96 additions & 0 deletions cmd/notation/plugin/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright The Notary Project Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package plugin

import (
"context"
"os"
"path/filepath"
"runtime"
"strings"
"testing"

notationplugin "github.com/notaryproject/notation/cmd/notation/internal/plugin"
"github.com/notaryproject/notation/internal/osutil"
"github.com/spf13/cobra"
)

func TestInstall(t *testing.T) {
t.Run("invalid plugin source url", func(t *testing.T) {
opts := &pluginInstallOpts{
pluginSourceType: notationplugin.PluginSourceTypeURL,
inputChecksum: "dummy",
pluginSource: "http://[::1]/%",
}
expectedErrMsg := `failed to parse plugin download URL http://[::1]/% with error: parse "http://[::1]/%": invalid URL escape "%"`
err := install(&cobra.Command{}, opts)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected error %s, but got %s", expectedErrMsg, err)
}
})

t.Run("unknown plugin source type", func(t *testing.T) {
opts := &pluginInstallOpts{
pluginSourceType: -1,
}
expectedErrMsg := `plugin installation failed: unknown plugin source type`
err := install(&cobra.Command{}, opts)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected error %s, but got %s", expectedErrMsg, err)
}
})
}

func TestInstallPlugin(t *testing.T) {
ctx := context.Background()
t.Run("input path does not exist", func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}
expectedErrMsg := `stat invalid: no such file or directory`
err := installPlugin(ctx, "invalid", "", false)
if err == nil || err.Error() != expectedErrMsg {
t.Fatalf("expected error %s, but got %s", expectedErrMsg, err)
}
})

t.Run("failed to get file type", func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}

tempDir := t.TempDir()
data := []byte("data")
filename := filepath.Join(tempDir, "a", "file.txt")
if err := osutil.WriteFile(filename, data); err != nil {
t.Fatal(err)
}
err := os.Chmod(tempDir, 0)
if err != nil {
t.Fatal(err)
}
defer func() {
err := os.Chmod(tempDir, 0700)
if err != nil {
t.Fatal(err)
}
}()

expectedErrMsg := `permission denied`
err = installPlugin(ctx, filename, "", false)
if err == nil || !strings.Contains(err.Error(), expectedErrMsg) {
t.Fatalf("expected permission denied error, but got %s", err)
}
})
}

0 comments on commit 445030b

Please sign in to comment.