From d8950a4e5c2f46a476483354135c2501e7f9aef5 Mon Sep 17 00:00:00 2001 From: Rasmus Dahlberg Date: Wed, 11 Nov 2020 16:48:36 +0100 Subject: move test helpers to testdata package --- handler_test.go | 62 +++++------------------------------------------ server/testdata/data.go | 4 +-- server/testdata/helper.go | 47 +++++++++++++++++++++++++++++++++++ server/testdata/type.go | 32 ++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 58 deletions(-) create mode 100644 server/testdata/helper.go create mode 100644 server/testdata/type.go diff --git a/handler_test.go b/handler_test.go index 934ddeb..5fd4818 100644 --- a/handler_test.go +++ b/handler_test.go @@ -2,7 +2,6 @@ package stfe import ( "bytes" - "context" "crypto" "fmt" "strings" @@ -18,7 +17,6 @@ import ( "github.com/google/certificate-transparency-go/trillian/mockclient" cttestdata "github.com/google/certificate-transparency-go/trillian/testdata" "github.com/google/trillian" - "github.com/google/trillian/types" "github.com/system-transparency/stfe/server/testdata" "github.com/system-transparency/stfe/x509util" ) @@ -190,33 +188,33 @@ func TestGetSth(t *testing.T) { }, { description: "incomplete trillian response: truncated log root", - trsp: makeTruncatedSignedLogRoot(t), + trsp: testdata.TruncatedSignedLogRootResponse(t), wantCode: http.StatusInternalServerError, wantErrText: http.StatusText(http.StatusInternalServerError) + "\n", }, { description: "incomplete trillian response: invalid root hash size", - trsp: makeSignedLogRoot(t, 0, 0, make([]byte, 31)), + trsp: testdata.NewGetLatestSignedLogRootResponse(t, 0, 0, make([]byte, 31)), wantCode: http.StatusInternalServerError, wantErrText: http.StatusText(http.StatusInternalServerError) + "\n", }, { description: "marshal failure: no signature", - trsp: makeSignedLogRoot(t, 0, 0, make([]byte, 32)), + trsp: testdata.NewGetLatestSignedLogRootResponse(t, 0, 0, make([]byte, 32)), wantCode: http.StatusInternalServerError, wantErrText: http.StatusText(http.StatusInternalServerError) + "\n", signer: cttestdata.NewSignerWithFixedSig(nil, make([]byte, 0)), }, { description: "signature failure", - trsp: makeSignedLogRoot(t, 0, 0, make([]byte, 32)), + trsp: testdata.NewGetLatestSignedLogRootResponse(t, 0, 0, make([]byte, 32)), wantCode: http.StatusInternalServerError, wantErrText: http.StatusText(http.StatusInternalServerError) + "\n", signer: cttestdata.NewSignerWithErr(nil, fmt.Errorf("signing failed")), }, { description: "valid request and response", - trsp: makeSignedLogRoot(t, 0, 0, make([]byte, 32)), + trsp: testdata.NewGetLatestSignedLogRootResponse(t, 0, 0, make([]byte, 32)), wantCode: http.StatusOK, signer: cttestdata.NewSignerWithFixedSig(nil, make([]byte, 32)), }, @@ -232,7 +230,7 @@ func TestGetSth(t *testing.T) { } w := httptest.NewRecorder() - th.client.EXPECT().GetLatestSignedLogRoot(newDeadlineMatcher(), gomock.Any()).Return(table.trsp, table.terr) + th.client.EXPECT().GetLatestSignedLogRoot(testdata.NewDeadlineMatcher(), gomock.Any()).Return(table.trsp, table.terr) th.getHandler(t, "get-sth").ServeHTTP(w, req) if w.Code != table.wantCode { t.Errorf("GET(%s)=%d, want http status code %d", url, w.Code, table.wantCode) @@ -282,51 +280,3 @@ func TestGetSth(t *testing.T) { }() } } - -func makeSignedLogRoot(t *testing.T, timestamp, size uint64, hash []byte) *trillian.GetLatestSignedLogRootResponse { - return &trillian.GetLatestSignedLogRootResponse{ - SignedLogRoot: mustMarshalRoot(t, &types.LogRootV1{ - TimestampNanos: timestamp, - TreeSize: size, - RootHash: hash, - }), - } -} - -func makeTruncatedSignedLogRoot(t *testing.T) *trillian.GetLatestSignedLogRootResponse { - slrr := makeSignedLogRoot(t, 0, 0, make([]byte, 32)) - slrr.SignedLogRoot.LogRoot = slrr.SignedLogRoot.LogRoot[1:] - return slrr -} - -func mustMarshalRoot(t *testing.T, lr *types.LogRootV1) *trillian.SignedLogRoot { - rootBytes, err := lr.MarshalBinary() - if err != nil { - t.Fatalf("failed to marshal root in test: %v", err) - } - return &trillian.SignedLogRoot{LogRoot: rootBytes} -} - -// deadlineMatcher implements gomock.Matcher, such that an error is detected if -// there is no context.Context deadline set -type deadlineMatcher struct{} - -// newDeadlineMatcher returns a new deadlineMatcher -func newDeadlineMatcher() gomock.Matcher { - return &deadlineMatcher{} -} - -// Matches returns true if the passed interface is a context with a deadline -func (dm *deadlineMatcher) Matches(i interface{}) bool { - ctx, ok := i.(context.Context) - if !ok { - return false - } - _, ok = ctx.Deadline() - return ok -} - -// String is needed to implement gomock.Matcher -func (dm *deadlineMatcher) String() string { - return fmt.Sprintf("deadlineMatcher{}") -} diff --git a/server/testdata/data.go b/server/testdata/data.go index dc61bb0..306b11f 100644 --- a/server/testdata/data.go +++ b/server/testdata/data.go @@ -1,6 +1,6 @@ - package testdata +package testdata - var ( +var ( PemAnchors = []byte(` -----BEGIN CERTIFICATE----- MIIB/TCCAa+gAwIBAgIUDYJzaC5VSkKwiLVAxO5MyphAkN8wBQYDK2VwMGwxCzAJ diff --git a/server/testdata/helper.go b/server/testdata/helper.go new file mode 100644 index 0000000..6874616 --- /dev/null +++ b/server/testdata/helper.go @@ -0,0 +1,47 @@ +package testdata + +import ( + "testing" + + "github.com/google/trillian" + "github.com/google/trillian/types" +) + +// NewGetLatestSignedLogRootResponse creates a new trillian STH. Revision, +// Metadata, Proof, KeyHint, and LogRootSignature are unsset. +func NewGetLatestSignedLogRootResponse(t *testing.T, timestamp, size uint64, hash []byte) *trillian.GetLatestSignedLogRootResponse { + t.Helper() + return &trillian.GetLatestSignedLogRootResponse{ + SignedLogRoot: marshalSignedLogRoot(t, &types.LogRootV1{ + TreeSize: size, + RootHash: hash, + TimestampNanos: timestamp, + Revision: 0, // not used by stfe + Metadata: nil, // not used by stfe + }), + Proof: nil, // not used by stfe + } +} + +// TruncatedSignedLogRootResponse creates a truncated signed log root response +// that cannot be unmarshalled, i.e., SignedLogRoot.LogRoot is invalid. +func TruncatedSignedLogRootResponse(t *testing.T) *trillian.GetLatestSignedLogRootResponse { + t.Helper() + slrr := NewGetLatestSignedLogRootResponse(t, 0, 0, make([]byte, 32)) + slrr.SignedLogRoot.LogRoot = slrr.SignedLogRoot.LogRoot[1:] + return slrr +} + +// marshalSignedLogRoot must marshal a signed log root +func marshalSignedLogRoot(t *testing.T, lr *types.LogRootV1) *trillian.SignedLogRoot { + t.Helper() + rootBytes, err := lr.MarshalBinary() + if err != nil { + t.Fatalf("failed to marshal root in test: %v", err) + } + return &trillian.SignedLogRoot{ + KeyHint: nil, // not used by stfe + LogRoot: rootBytes, + LogRootSignature: nil, // not used by stfe + } +} diff --git a/server/testdata/type.go b/server/testdata/type.go new file mode 100644 index 0000000..93041c9 --- /dev/null +++ b/server/testdata/type.go @@ -0,0 +1,32 @@ +package testdata + +import ( + "context" + "fmt" + + "github.com/golang/mock/gomock" +) + +// DeadlineMatcher implements gomock.Matcher, such that an error is raised if +// there is no context.Context deadline set +type DeadlineMatcher struct{} + +// NewDeadlineMatcher returns a new DeadlineMatcher +func NewDeadlineMatcher() gomock.Matcher { + return &DeadlineMatcher{} +} + +// Matches returns true if the passed interface is a context with a deadline +func (dm *DeadlineMatcher) Matches(i interface{}) bool { + ctx, ok := i.(context.Context) + if !ok { + return false + } + _, ok = ctx.Deadline() + return ok +} + +// String is needed to implement gomock.Matcher +func (dm *DeadlineMatcher) String() string { + return fmt.Sprintf("deadlineMatcher{}") +} -- cgit v1.2.3