Skip to content

Commit

Permalink
test: improve test coverage to 80% (#405)
Browse files Browse the repository at this point in the history
Test:
- improved test coverage to over 80.16%

Fix:
- added ORAS copy library to copy the OCI Layout test data to a
temporary directory and avoid generating test time temporary files in
the repository directory.

---------

Signed-off-by: Junjie Gao <junjiegao@microsoft.com>
  • Loading branch information
JeyJeyGao committed May 28, 2024
1 parent 5e98995 commit b8508d0
Show file tree
Hide file tree
Showing 11 changed files with 839 additions and 86 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@
*.sublime-workspace

# Custom
coverage.txt
coverage.txt

# tmp directory was generated by example_remoteVerify_test.go
tmp/
12 changes: 12 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,15 @@ func TestSaveFile(t *testing.T) {
t.Fatal("save config file failed.")
}
}

func TestLoadNonExistedConfig(t *testing.T) {
dir.UserConfigDir = "./testdata/non-existed"
got, err := LoadConfig()
if err != nil {
t.Fatalf("LoadConfig() error. err = %v", err)
}

if !reflect.DeepEqual(got, NewConfig()) {
t.Errorf("loadFile() = %v, want %v", got, NewConfig())
}
}
26 changes: 24 additions & 2 deletions dir/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"testing"
)

func Test_sysFS_SysPath(t *testing.T) {
func TestSysFS_SysPath(t *testing.T) {
wantPath := filepath.FromSlash("/path/notation/config.json")
fsys := NewSysFS("/path/notation")
path, err := fsys.SysPath(PathConfigFile)
Expand All @@ -31,7 +31,7 @@ func Test_sysFS_SysPath(t *testing.T) {
}
}

func Test_OsFs(t *testing.T) {
func TestOsFs(t *testing.T) {
wantData := []byte("data")
fsys := NewSysFS("./testdata")

Expand All @@ -49,3 +49,25 @@ func Test_OsFs(t *testing.T) {
t.Fatalf("SysFS read failed. got data = %v, want %v", data, wantData)
}
}

func TestConfigFS(t *testing.T) {
configFS := ConfigFS()
path, err := configFS.SysPath(PathConfigFile)
if err != nil {
t.Fatalf("SysPath() failed. err = %v", err)
}
if path != filepath.Join(UserConfigDir, PathConfigFile) {
t.Fatalf(`SysPath() failed. got: %q, want: %q`, path, filepath.Join(UserConfigDir, PathConfigFile))
}
}

func TestPluginFS(t *testing.T) {
pluginFS := PluginFS()
path, err := pluginFS.SysPath("plugin")
if err != nil {
t.Fatalf("SysPath() failed. err = %v", err)
}
if path != filepath.Join(UserLibexecDir, PathPlugins, "plugin") {
t.Fatalf(`SysPath() failed. got: %q, want: %q`, path, filepath.Join(UserLibexecDir, PathPlugins, "plugin"))
}
}
93 changes: 93 additions & 0 deletions errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// 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 notation

import "testing"

func TestErrorMessages(t *testing.T) {
tests := []struct {
name string
err error
want string
}{
{
name: "ErrorPushSignatureFailed with message",
err: ErrorPushSignatureFailed{Msg: "test message"},
want: "failed to push signature to registry with error: test message",
},
{
name: "ErrorPushSignatureFailed without message",
err: ErrorPushSignatureFailed{},
want: "failed to push signature to registry",
},
{
name: "ErrorVerificationInconclusive with message",
err: ErrorVerificationInconclusive{Msg: "test message"},
want: "test message",
},
{
name: "ErrorVerificationInconclusive without message",
err: ErrorVerificationInconclusive{},
want: "signature verification was inclusive due to an unexpected error",
},
{
name: "ErrorNoApplicableTrustPolicy with message",
err: ErrorNoApplicableTrustPolicy{Msg: "test message"},
want: "test message",
},
{
name: "ErrorNoApplicableTrustPolicy without message",
err: ErrorNoApplicableTrustPolicy{},
want: "there is no applicable trust policy for the given artifact",
},
{
name: "ErrorSignatureRetrievalFailed with message",
err: ErrorSignatureRetrievalFailed{Msg: "test message"},
want: "test message",
},
{
name: "ErrorSignatureRetrievalFailed without message",
err: ErrorSignatureRetrievalFailed{},
want: "unable to retrieve the digital signature from the registry",
},
{
name: "ErrorVerificationFailed with message",
err: ErrorVerificationFailed{Msg: "test message"},
want: "test message",
},
{
name: "ErrorVerificationFailed without message",
err: ErrorVerificationFailed{},
want: "signature verification failed",
},
{
name: "ErrorUserMetadataVerificationFailed with message",
err: ErrorUserMetadataVerificationFailed{Msg: "test message"},
want: "test message",
},
{
name: "ErrorUserMetadataVerificationFailed without message",
err: ErrorUserMetadataVerificationFailed{},
want: "unable to find specified metadata in the signature",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.err.Error(); got != tt.want {
t.Errorf("Error() = %v, want %v", got, tt.want)
}
})
}
}
5 changes: 5 additions & 0 deletions internal/mock/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ type Repository struct {
FetchSignatureBlobError error
MissMatchDigest bool
ExceededNumOfSignatures bool
PushSignatureError error
}

func NewRepository() Repository {
Expand Down Expand Up @@ -163,6 +164,10 @@ func (t Repository) FetchSignatureBlob(ctx context.Context, desc ocispec.Descrip
}

func (t Repository) PushSignature(ctx context.Context, mediaType string, blob []byte, subject ocispec.Descriptor, annotations map[string]string) (blobDesc, manifestDesc ocispec.Descriptor, err error) {
if t.PushSignatureError != nil {
return ocispec.Descriptor{}, ocispec.Descriptor{}, t.PushSignatureError
}

return ocispec.Descriptor{}, ocispec.Descriptor{}, nil
}

Expand Down
47 changes: 47 additions & 0 deletions internal/mock/ocilayout/ocilayout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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 ocilayout

import (
"context"
"os"

"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content/oci"
)

// Copy creates a temporary OCI layout for testing
// and returns the path to the layout.
func Copy(sourcePath, destPath, tag string) error {
ctx := context.Background()

srcStore, err := oci.NewFromFS(ctx, os.DirFS(sourcePath))
if err != nil {
return err
}

// create a dest store for store the generated oci layout.
destStore, err := oci.New(destPath)
if err != nil {
return err
}

// copy data
_, err = oras.ExtendedCopy(ctx, srcStore, tag, destStore, "", oras.DefaultExtendedCopyOptions)
if err != nil {
return err
}

return nil
}
60 changes: 60 additions & 0 deletions internal/mock/ocilayout/ocilayout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// 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 ocilayout

import (
"os"
"testing"
)

func TestCopy(t *testing.T) {
t.Run("empty oci layout", func(t *testing.T) {
err := Copy("", "", "v2")
if err == nil {
t.Errorf("expected error, got nil")
}
})

t.Run("invalid target path", func(t *testing.T) {
tempDir := t.TempDir()
// change the permission of the tempDir to make it invalid
if err := os.Chmod(tempDir, 0); err != nil {
t.Fatalf("failed to change the permission of the tempDir: %v", err)
}
err := Copy("../../testdata/oci-layout", tempDir, "v2")
if err == nil {
t.Errorf("expected error, got nil")
}

if err := os.Chmod(tempDir, 0755); err != nil {
t.Fatalf("failed to change the permission of the tempDir: %v", err)
}
})

t.Run("copy failed", func(t *testing.T) {
tempDir := t.TempDir()
err := Copy("../../testdata/oci-layout", tempDir, "v3")
if err == nil {
t.Errorf("expected error, got nil")
}
})

t.Run("copy success", func(t *testing.T) {
tempDir := t.TempDir()
err := Copy("../../testdata/oci-layout", tempDir, "v2")
if err != nil {
t.Errorf("expected nil, got %v", err)
}
})
}
41 changes: 41 additions & 0 deletions log/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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 log provides logging functionality to notation.
// Users who want to enable logging option in notation should implement the
// log.Logger interface and include it in context by calling log.WithLogger.
// 3rd party loggers that implement log.Logger: github.com/uber-go/zap.SugaredLogger
// and github.com/sirupsen/logrus.Logger.
package log

import (
"context"
"testing"
)

func TestWithLoggerAndGetLogger(t *testing.T) {
tl := &discardLogger{}
ctx := WithLogger(context.Background(), tl)

if got := GetLogger(ctx); got != tl {
t.Errorf("GetLogger() = %v, want %v", got, tl)
}
}

func TestGetLoggerWithNoLogger(t *testing.T) {
ctx := context.Background()

if got := GetLogger(ctx); got != Discard {
t.Errorf("GetLogger() = %v, want Discard", got)
}
}
Loading

0 comments on commit b8508d0

Please sign in to comment.