diff --git a/.github/.codecov.yml b/.github/.codecov.yml index 9c2f90a..ae05785 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -15,4 +15,4 @@ coverage: status: project: default: - target: 70% + target: 80% diff --git a/cli/cli.go b/cli/cli.go index 820db5a..28a3a46 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -122,7 +122,7 @@ func (c *CLI) Execute(ctx context.Context, args []string) { func (c *CLI) printVersion(ctx context.Context) { md := c.getMetadata(ctx, c.pl) - fmt.Printf("%s - %s\nVersion: %s \n", md.Name, md.Description, md.Version) + fmt.Printf("%s - %s\nVersion: %s\n", md.Name, md.Description, md.Version) } // validateArgs validate commands/arguments passed to executable. @@ -142,7 +142,10 @@ func (c *CLI) unmarshalRequest(request plugin.Request) error { if err := request.Validate(); err != nil { c.logger.Errorf("%s validation error :%v", reflect.TypeOf(request), err) - return plugin.NewValidationError(plugin.ErrorMsgMalformedInput) + if e, ok := err.(*plugin.Error); ok { + return plugin.NewValidationErrorf("%s:%s", plugin.ErrorMsgMalformedInput, e.Message) + } + return plugin.NewValidationErrorf("%s", plugin.ErrorMsgMalformedInput) } return nil diff --git a/cli/cli_test.go b/cli/cli_test.go index 68fd93c..fd65c97 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -121,36 +121,43 @@ func TestExecuteSuccess(t *testing.T) { sigGenCli, _ := New(mock.NewSigGeneratorPlugin(false)) tests := map[string]struct { c *CLI + in string op string }{ string(plugin.CommandGetMetadata): { c: cli, + in: "{}", op: "{\"name\":\"Example Plugin\",\"description\":\"This is an description of example plugin. 🍺\",\"version\":\"1.0.0\",\"url\":\"https://example.com/notation/plugin\",\"capabilities\":[\"SIGNATURE_VERIFIER.TRUSTED_IDENTITY\",\"SIGNATURE_VERIFIER.REVOCATION_CHECK\",\"SIGNATURE_GENERATOR.ENVELOPE\"]}", }, string(plugin.Version): { c: cli, - op: "Example Plugin - This is an description of example plugin. 🍺\nVersion: 1.0.0 \n", + in: "", + op: "Example Plugin - This is an description of example plugin. 🍺\nVersion: 1.0.0\n", }, string(plugin.CommandGenerateEnvelope): { c: cli, - op: "{\"signatureEnvelope\":\"\",\"signatureEnvelopeType\":\"\",\"annotations\":{\"manifestAnntnKey1\":\"value1\"}}", + in: "{\"contractVersion\":\"1.0\",\"keyId\":\"someKeyId\",\"payloadType\":\"somePT\",\"signatureEnvelopeType\":\"someSET\",\"payload\":\"em9w\"}", + op: "{\"signatureEnvelope\":\"\",\"signatureEnvelopeType\":\"someSET\",\"annotations\":{\"manifestAnntnKey1\":\"value1\"}}", }, string(plugin.CommandVerifySignature): { c: cli, + in: "{\"contractVersion\":\"1.0\",\"signature\":{\"criticalAttributes\":{\"contentType\":\"someCT\",\"signingScheme\":\"someSigningScheme\"},\"unprocessedAttributes\":null,\"certificateChain\":[\"emFw\",\"em9w\"]},\"trustPolicy\":{\"trustedIdentities\":null,\"signatureVerification\":[\"SIGNATURE_GENERATOR.RAW\"]}}", op: "{\"verificationResults\":{\"SIGNATURE_VERIFIER.REVOCATION_CHECK\":{\"success\":true,\"reason\":\"Not revoked\"},\"SIGNATURE_VERIFIER.TRUSTED_IDENTITY\":{\"success\":true,\"reason\":\"Valid trusted Identity\"}},\"processedAttributes\":[]}", }, string(plugin.CommandGenerateSignature): { c: sigGenCli, + in: "{\"contractVersion\":\"1.0\",\"keyId\":\"someKeyId\",\"keySpec\":\"EC-384\",\"hashAlgorithm\":\"SHA-384\",\"payload\":\"em9w\"}", op: "{\"keyId\":\"someKeyId\",\"signature\":\"YWJjZA==\",\"signingAlgorithm\":\"RSASSA-PSS-SHA-256\",\"certificateChain\":[\"YWJjZA==\",\"d3h5eg==\"]}", }, string(plugin.CommandDescribeKey): { c: sigGenCli, + in: "{\"contractVersion\":\"1.0\",\"keyId\":\"someKeyId\"}", op: "{\"keyId\":\"someKeyId\",\"keySpec\":\"RSA-2048\"}", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { - closer := setupReader("{}") + closer := setupReader(test.in) defer closer() op := captureStdOut(func() { test.c.Execute(context.Background(), []string{"notation", name}) diff --git a/plugin/describekey_test.go b/plugin/describekey_test.go index 0a7d89e..32a5197 100644 --- a/plugin/describekey_test.go +++ b/plugin/describekey_test.go @@ -57,6 +57,13 @@ func TestDescribeKeyRequest_Validate_Error(t *testing.T) { } } +func TestDescribeKeyRequest_Command(t *testing.T) { + req := getDescribeKeyRequest(ContractVersion, "someKeyId") + if cmd := req.Command(); cmd != CommandDescribeKey { + t.Errorf("DescribeKeyRequest#Command, expected %s but returned %s", CommandDescribeKey, cmd) + } +} + func getDescribeKeyRequest(cv, kid string) DescribeKeyRequest { return DescribeKeyRequest{ ContractVersion: cv, diff --git a/plugin/errors.go b/plugin/errors.go index dcf5cb1..08b1a25 100644 --- a/plugin/errors.go +++ b/plugin/errors.go @@ -53,7 +53,7 @@ func NewGenericError(msg string) *Error { return NewError(ErrorCodeGeneric, msg) } -func NewGenericErrorf(format string, msg string) *Error { +func NewGenericErrorf(format string, msg ...string) *Error { return NewError(ErrorCodeGeneric, fmt.Sprintf(format, msg)) } @@ -65,7 +65,7 @@ func NewValidationError(msg string) *Error { return NewError(ErrorCodeValidation, msg) } -func NewValidationErrorf(format string, msg string) *Error { +func NewValidationErrorf(format string, msg ...string) *Error { return NewError(ErrorCodeValidation, fmt.Sprintf(format, msg)) } diff --git a/plugin/errors_test.go b/plugin/errors_test.go new file mode 100644 index 0000000..1ea297c --- /dev/null +++ b/plugin/errors_test.go @@ -0,0 +1,65 @@ +// 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 ( + "testing" +) + +func TestNewError(t *testing.T) { + msg := "someMSg" + err := NewError(ErrorCodeValidation, msg) + if err != nil { + if ErrorCodeValidation != err.ErrCode { + t.Errorf("NewError, expected errorCode '%s' but found'%s'", ErrorCodeValidation, err.ErrCode) + } + + if msg != err.Message { + t.Errorf("NewError, expected message'%s' but found '%s'", msg, err.Message) + } + + if err.Metadata != nil { + t.Errorf("NewError, expected metadata to be nil but found '%s'", err.Metadata) + } + + expError := "{\"errorCode\":\"VALIDATION_ERROR\",\"errorMessage\":\"someMSg\"}" + if expError != err.Error() { + t.Errorf("NewError#Error, expected error to be '%s' but found '%s'", expError, err.Error()) + + } + + } else { + t.Error("NewError didn't return an error") + } +} + +func TestErrorCodes(t *testing.T) { + testCases := []struct { + err *Error + errCode ErrorCode + }{ + {err: NewValidationError(""), errCode: ErrorCodeValidation}, + {err: NewValidationErrorf("%s", ""), errCode: ErrorCodeValidation}, + {err: NewUnsupportedError(""), errCode: ErrorCodeValidation}, + {err: NewGenericError(""), errCode: ErrorCodeGeneric}, + {err: NewGenericErrorf("%s", ""), errCode: ErrorCodeGeneric}, + {err: NewJSONParsingError(""), errCode: ErrorCodeValidation}, + {err: NewUnsupportedContractVersionError(""), errCode: ErrorCodeUnsupportedContractVersion}, + } + for _, test := range testCases { + if test.errCode != test.err.ErrCode { + t.Errorf("Expected errorCode %s but found %s", test.errCode, test.err.ErrCode) + } + } +} diff --git a/plugin/metadata_test.go b/plugin/metadata_test.go index c7dce84..a393cbe 100644 --- a/plugin/metadata_test.go +++ b/plugin/metadata_test.go @@ -53,3 +53,10 @@ func TestGetMetadataRequest_Validate(t *testing.T) { } } } + +func TestGetMetadataRequest_Command(t *testing.T) { + req := GetMetadataRequest{} + if cmd := req.Command(); cmd != CommandGetMetadata { + t.Errorf("DescribeKeyRequest#Command, expected %s but returned %s", CommandGetMetadata, cmd) + } +} diff --git a/plugin/sign_test.go b/plugin/sign_test.go index f255e5c..2df620b 100644 --- a/plugin/sign_test.go +++ b/plugin/sign_test.go @@ -66,6 +66,13 @@ func TestGenerateSignatureRequest_Validate_Error(t *testing.T) { } } +func TestGenerateSignatureRequest_Command(t *testing.T) { + req := getGenerateSignatureRequest(ContractVersion, "someKeyId", string(KeySpecEC384), string(HashAlgorithmSHA384), []byte("zop")) + if cmd := req.Command(); cmd != CommandGenerateSignature { + t.Errorf("DescribeKeyRequest#Command, expected %s but returned %s", CommandGenerateSignature, cmd) + } +} + func TestGenerateEnvelopeRequest_Validate(t *testing.T) { reqs := []GenerateEnvelopeRequest{ getGenerateEnvelopeRequest(ContractVersion, "someKeyId", "someSET", "somePT", []byte("zop")), @@ -108,13 +115,19 @@ func TestGenerateEnvelopeRequest_Validate_Error(t *testing.T) { t.Errorf("expected error message '%s' but got '%s'", expMsg, err.Error()) } } else { - fmt.Println(testcase.req) t.Error("GenerateEnvelopeRequest#Validate didn't returned error") } }) } } +func TestGenerateEnvelopeRequest_Command(t *testing.T) { + req := getGenerateEnvelopeRequest(ContractVersion, "someKeyId", string(KeySpecEC384), string(HashAlgorithmSHA384), []byte("zop")) + if cmd := req.Command(); cmd != CommandGenerateEnvelope { + t.Errorf("DescribeKeyRequest#Command, expected %s but returned %s", CommandGenerateEnvelope, cmd) + } +} + func getGenerateSignatureRequest(cv, kid, ks, ha string, pl []byte) GenerateSignatureRequest { return GenerateSignatureRequest{ ContractVersion: cv, diff --git a/plugin/verify_test.go b/plugin/verify_test.go index 2ee0730..90793b6 100644 --- a/plugin/verify_test.go +++ b/plugin/verify_test.go @@ -55,6 +55,9 @@ func TestVerifySignatureRequest_Validate_Error(t *testing.T) { reqWithoutSignature := getVerifySignatureRequest("1.0", "someCT", "someSigningScheme", mockCertChain, []Capability{CapabilitySignatureGenerator}) reqWithoutSignature.Signature = Signature{} + reqWithoutCriticalAttr := getVerifySignatureRequest("1.0", "someCT", "someSigningScheme", mockCertChain, []Capability{CapabilitySignatureGenerator}) + reqWithoutCriticalAttr.Signature.CriticalAttributes = CriticalAttributes{} + testCases := []struct { name string req VerifySignatureRequest @@ -67,6 +70,7 @@ func TestVerifySignatureRequest_Validate_Error(t *testing.T) { {name: "signature's trustPolicy", req: getVerifySignatureRequest(ContractVersion, "someCT", "someSigningScheme", mockCertChain, nil)}, {name: "signature's trustPolicy's signatureVerification", req: getVerifySignatureRequest(ContractVersion, "someCT", "someSigningScheme", mockCertChain, []Capability{})}, {name: "signature", req: reqWithoutSignature}, + {name: "signature's criticalAttributes", req: reqWithoutCriticalAttr}, } for _, testcase := range testCases { @@ -83,6 +87,13 @@ func TestVerifySignatureRequest_Validate_Error(t *testing.T) { } } +func TestVerifySignatureRequest_Command(t *testing.T) { + req := getVerifySignatureRequest(ContractVersion, "someCT", "someSigningScheme", mockCertChain, []Capability{CapabilitySignatureGenerator}) + if cmd := req.Command(); cmd != CommandVerifySignature { + t.Errorf("DescribeKeyRequest#Command, expected %s but returned %s", CommandVerifySignature, cmd) + } +} + func getVerifySignatureRequest(cv, ct, ss string, cc [][]byte, sv []Capability) VerifySignatureRequest { return VerifySignatureRequest{ ContractVersion: cv,