From 559bccccd40d028e412d9f11709ded0250ba6dcd Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Tue, 24 May 2022 23:33:38 +0200 Subject: implement primary and secondary role, for replication --- internal/node/secondary/endpoint_internal_test.go | 111 ++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 internal/node/secondary/endpoint_internal_test.go (limited to 'internal/node/secondary/endpoint_internal_test.go') diff --git a/internal/node/secondary/endpoint_internal_test.go b/internal/node/secondary/endpoint_internal_test.go new file mode 100644 index 0000000..9637e29 --- /dev/null +++ b/internal/node/secondary/endpoint_internal_test.go @@ -0,0 +1,111 @@ +package secondary + +import ( + "crypto" + "crypto/ed25519" + "fmt" + "io" + "net/http" + "net/http/httptest" + "testing" + + mocksDB "git.sigsum.org/log-go/internal/mocks/db" + "git.sigsum.org/log-go/internal/node/handler" + "git.sigsum.org/sigsum-go/pkg/merkle" + "git.sigsum.org/sigsum-go/pkg/types" + "github.com/golang/mock/gomock" +) + +// TestSigner implements the signer interface. It can be used to mock +// an Ed25519 signer that always return the same public key, +// signature, and error. +// NOTE: Code duplication with internal/state/single_test.go +type TestSigner struct { + PublicKey [ed25519.PublicKeySize]byte + Signature [ed25519.SignatureSize]byte + Error error +} + +func (ts *TestSigner) Public() crypto.PublicKey { + return ed25519.PublicKey(ts.PublicKey[:]) +} + +func (ts *TestSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + return ts.Signature[:], ts.Error +} + +var ( + testTH = types.TreeHead{ + Timestamp: 0, + TreeSize: 0, + RootHash: *merkle.HashFn([]byte("root hash")), + } + testSignerFailing = TestSigner{types.PublicKey{}, types.Signature{}, fmt.Errorf("mocked error")} + testSignerSucceeding = TestSigner{types.PublicKey{}, types.Signature{}, nil} +) + +func TestGetTreeHeadToCosign(t *testing.T) { + for _, tbl := range []struct { + desc string + trillianTHErr error + trillianTHRet *types.TreeHead + signer crypto.Signer + httpStatus int + }{ + { + desc: "trillian GetTreeHead error", + trillianTHErr: fmt.Errorf("mocked error"), + httpStatus: http.StatusInternalServerError, + }, + { + desc: "signer error", + trillianTHRet: &testTH, + signer: &testSignerFailing, + httpStatus: http.StatusInternalServerError, + }, + { + desc: "success", + trillianTHRet: &testTH, + signer: &testSignerSucceeding, + httpStatus: http.StatusOK, + }, + } { + func() { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + trillianClient := mocksDB.NewMockClient(ctrl) + trillianClient.EXPECT().GetTreeHead(gomock.Any()).Return(tbl.trillianTHRet, tbl.trillianTHErr) + + node := Secondary{ + Config: testConfig, + TrillianClient: trillianClient, + Signer: tbl.signer, + } + + // Create HTTP request + url := types.EndpointAddLeaf.Path("http://example.com", node.Prefix()) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + t.Fatalf("must create http request: %v", err) + } + + // Run HTTP request + w := httptest.NewRecorder() + mustHandleInternal(t, node, types.EndpointGetTreeHeadToCosign).ServeHTTP(w, req) + if got, want := w.Code, tbl.httpStatus; got != want { + t.Errorf("got HTTP status code %v but wanted %v in test %q", got, want, tbl.desc) + } + }() + } +} + +func mustHandleInternal(t *testing.T, s Secondary, e types.Endpoint) handler.Handler { + for _, h := range s.InternalHTTPHandlers() { + if h.Endpoint == e { + return h + } + } + t.Fatalf("must handle endpoint: %v", e) + return handler.Handler{} +} -- cgit v1.2.3