github.com/zorawar87/trillian@v1.2.1/server/log_rpc_server_test.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package server
    16  
    17  import (
    18  	"context"
    19  	"crypto"
    20  	"errors"
    21  	"fmt"
    22  	"reflect"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/golang/mock/gomock"
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/google/trillian"
    29  	"github.com/google/trillian/extension"
    30  	"github.com/google/trillian/merkle/rfc6962"
    31  	"github.com/google/trillian/storage"
    32  	"github.com/google/trillian/types"
    33  	"github.com/kylelemons/godebug/pretty"
    34  	"google.golang.org/genproto/googleapis/rpc/code"
    35  	"google.golang.org/grpc/codes"
    36  	"google.golang.org/grpc/status"
    37  
    38  	tcrypto "github.com/google/trillian/crypto"
    39  	stestonly "github.com/google/trillian/storage/testonly"
    40  )
    41  
    42  func newTestLeaf(data []byte, extra []byte, index int64) *trillian.LogLeaf {
    43  	hash, _ := th.HashLeaf(data)
    44  	return &trillian.LogLeaf{
    45  		MerkleLeafHash: hash,
    46  		LeafValue:      data,
    47  		ExtraData:      extra,
    48  		LeafIndex:      index,
    49  	}
    50  }
    51  
    52  var (
    53  	th = rfc6962.DefaultHasher
    54  
    55  	logID1 = int64(1)
    56  	logID2 = int64(2)
    57  	logID3 = int64(3)
    58  
    59  	leaf1 = newTestLeaf([]byte("value"), []byte("extra"), 1)
    60  	leaf2 = newTestLeaf([]byte("value2"), []byte("extra"), 2)
    61  	leaf3 = newTestLeaf([]byte("value3"), []byte("extra3"), 3)
    62  
    63  	leaf0Request     = trillian.GetLeavesByIndexRequest{LogId: logID1, LeafIndex: []int64{0}}
    64  	leaf03Request    = trillian.GetLeavesByIndexRequest{LogId: logID1, LeafIndex: []int64{0, 3}}
    65  	leaf0Log2Request = trillian.GetLeavesByIndexRequest{LogId: logID2, LeafIndex: []int64{0}}
    66  
    67  	queueRequest0     = trillian.QueueLeavesRequest{LogId: logID1, Leaves: []*trillian.LogLeaf{leaf1}}
    68  	queueRequest0Log2 = trillian.QueueLeavesRequest{LogId: logID2, Leaves: []*trillian.LogLeaf{leaf1}}
    69  
    70  	addSeqRequest0 = trillian.AddSequencedLeavesRequest{LogId: logID3, Leaves: []*trillian.LogLeaf{leaf1}}
    71  
    72  	fixedGoSigner = newSignerWithFixedSig([]byte("signed"))
    73  	fixedSigner   = tcrypto.NewSigner(0, fixedGoSigner, crypto.SHA256)
    74  
    75  	tree1              = addTreeID(stestonly.LogTree, logID1)
    76  	getLogRootRequest1 = trillian.GetLatestSignedLogRootRequest{LogId: logID1}
    77  	revision1          = int64(5)
    78  	root1              = &types.LogRootV1{TimestampNanos: 987654321, RootHash: []byte("A NICE HASH"), TreeSize: 7, Revision: uint64(revision1)}
    79  	signedRoot1, _     = fixedSigner.SignLogRoot(root1)
    80  
    81  	getByHashRequest1 = trillian.GetLeavesByHashRequest{LogId: logID1, LeafHash: [][]byte{[]byte("test"), []byte("data")}}
    82  	getByHashRequest2 = trillian.GetLeavesByHashRequest{LogId: logID2, LeafHash: [][]byte{[]byte("test"), []byte("data")}}
    83  
    84  	getInclusionProofByHashRequest7  = trillian.GetInclusionProofByHashRequest{LogId: logID1, TreeSize: 7, LeafHash: []byte("ahash")}
    85  	getInclusionProofByHashRequest25 = trillian.GetInclusionProofByHashRequest{LogId: logID1, TreeSize: 25, LeafHash: []byte("ahash")}
    86  
    87  	getInclusionProofByIndexRequest7  = trillian.GetInclusionProofRequest{LogId: logID1, TreeSize: 7, LeafIndex: 2}
    88  	getInclusionProofByIndexRequest25 = trillian.GetInclusionProofRequest{LogId: logID1, TreeSize: 50, LeafIndex: 25}
    89  
    90  	getEntryAndProofRequest17    = trillian.GetEntryAndProofRequest{LogId: logID1, TreeSize: 17, LeafIndex: 3}
    91  	getEntryAndProofRequest17_2  = trillian.GetEntryAndProofRequest{LogId: logID1, TreeSize: 17, LeafIndex: 2}
    92  	getEntryAndProofRequest17_11 = trillian.GetEntryAndProofRequest{LogId: logID1, TreeSize: 17, LeafIndex: 11}
    93  	getEntryAndProofRequest7     = trillian.GetEntryAndProofRequest{LogId: logID1, TreeSize: 7, LeafIndex: 2}
    94  
    95  	getConsistencyProofRequest7  = trillian.GetConsistencyProofRequest{LogId: logID1, FirstTreeSize: 4, SecondTreeSize: 7}
    96  	getConsistencyProofRequest44 = trillian.GetConsistencyProofRequest{LogId: logID1, FirstTreeSize: 4, SecondTreeSize: 4}
    97  	getConsistencyProofRequest48 = trillian.GetConsistencyProofRequest{LogId: logID1, FirstTreeSize: 4, SecondTreeSize: 8}
    98  
    99  	nodeIdsInclusionSize7Index2 = []storage.NodeID{
   100  		stestonly.MustCreateNodeIDForTreeCoords(0, 3, 64),
   101  		stestonly.MustCreateNodeIDForTreeCoords(1, 0, 64),
   102  		stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64)}
   103  
   104  	nodeIdsConsistencySize4ToSize7 = []storage.NodeID{stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64)}
   105  )
   106  
   107  func TestGetLeavesByIndexBeginFailsCausesError(t *testing.T) {
   108  	ctrl := gomock.NewController(t)
   109  	defer ctrl.Finish()
   110  
   111  	fakeStorage := storage.NewMockLogStorage(ctrl)
   112  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(nil, errors.New("TX"))
   113  	registry := extension.Registry{
   114  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: leaf0Request.LogId, numSnapshots: 1}),
   115  		LogStorage:   fakeStorage,
   116  	}
   117  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   118  
   119  	_, err := server.GetLeavesByIndex(context.Background(), &leaf0Request)
   120  	if err == nil || !strings.Contains(err.Error(), "TX") {
   121  		t.Fatalf("Returned wrong error response when begin failed: %v", err)
   122  	}
   123  }
   124  
   125  func TestGetLeavesByIndexStorageError(t *testing.T) {
   126  	ctrl := gomock.NewController(t)
   127  	defer ctrl.Finish()
   128  
   129  	test := newParameterizedTest(ctrl, "GetLeavesByIndex", readOnly, nopStorage,
   130  		func(t *storage.MockLogTreeTX) {
   131  			t.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{0}).Return(nil, errors.New("STORAGE"))
   132  		},
   133  		func(s *TrillianLogRPCServer) error {
   134  			_, err := s.GetLeavesByIndex(context.Background(), &leaf0Request)
   135  			return err
   136  		})
   137  
   138  	test.executeStorageFailureTest(t, leaf0Request.LogId)
   139  }
   140  
   141  func TestGetLeavesByIndexInvalidLogId(t *testing.T) {
   142  	ctrl := gomock.NewController(t)
   143  	defer ctrl.Finish()
   144  
   145  	test := newParameterizedTest(ctrl, "GetLeavesByIndex", readOnly, nopStorage,
   146  		func(t *storage.MockLogTreeTX) {},
   147  		func(s *TrillianLogRPCServer) error {
   148  			_, err := s.GetLeavesByIndex(context.Background(), &leaf0Log2Request)
   149  			return err
   150  		})
   151  
   152  	test.executeInvalidLogIDTest(t, true /* snapshot */)
   153  }
   154  
   155  func TestGetLeavesByIndexCommitFails(t *testing.T) {
   156  	ctrl := gomock.NewController(t)
   157  	defer ctrl.Finish()
   158  
   159  	test := newParameterizedTest(ctrl, "GetLeavesByIndex", readOnly, nopStorage,
   160  		func(t *storage.MockLogTreeTX) {
   161  			t.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{0}).Return([]*trillian.LogLeaf{leaf1}, nil)
   162  		},
   163  		func(s *TrillianLogRPCServer) error {
   164  			_, err := s.GetLeavesByIndex(context.Background(), &leaf0Request)
   165  			return err
   166  		})
   167  
   168  	test.executeCommitFailsTest(t, leaf0Request.LogId)
   169  }
   170  
   171  func TestGetLeavesByIndex(t *testing.T) {
   172  	ctrl := gomock.NewController(t)
   173  	defer ctrl.Finish()
   174  
   175  	fakeStorage := storage.NewMockLogStorage(ctrl)
   176  	mockTX := storage.NewMockLogTreeTX(ctrl)
   177  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   178  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{0}).Return([]*trillian.LogLeaf{leaf1}, nil)
   179  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   180  	mockTX.EXPECT().Commit().Return(nil)
   181  	mockTX.EXPECT().Close().Return(nil)
   182  	mockTX.EXPECT().IsOpen().AnyTimes().Return(false)
   183  
   184  	registry := extension.Registry{
   185  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: leaf0Request.LogId, numSnapshots: 1}),
   186  		LogStorage:   fakeStorage,
   187  	}
   188  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   189  
   190  	resp, err := server.GetLeavesByIndex(context.Background(), &leaf0Request)
   191  	if err != nil {
   192  		t.Fatalf("Failed to get leaf by index: %v", err)
   193  	}
   194  
   195  	if len(resp.Leaves) != 1 || !proto.Equal(resp.Leaves[0], leaf1) {
   196  		t.Fatalf("Expected leaf: %v but got: %v", leaf1, resp.Leaves[0])
   197  	}
   198  }
   199  
   200  func TestGetLeavesByIndexMultiple(t *testing.T) {
   201  	ctrl := gomock.NewController(t)
   202  	defer ctrl.Finish()
   203  
   204  	fakeStorage := storage.NewMockLogStorage(ctrl)
   205  	mockTX := storage.NewMockLogTreeTX(ctrl)
   206  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   207  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{0, 3}).Return([]*trillian.LogLeaf{leaf1, leaf3}, nil)
   208  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   209  	mockTX.EXPECT().Commit().Return(nil)
   210  	mockTX.EXPECT().Close().Return(nil)
   211  	mockTX.EXPECT().IsOpen().AnyTimes().Return(false)
   212  
   213  	registry := extension.Registry{
   214  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: leaf03Request.LogId, numSnapshots: 1}),
   215  		LogStorage:   fakeStorage,
   216  	}
   217  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   218  
   219  	resp, err := server.GetLeavesByIndex(context.Background(), &leaf03Request)
   220  	if err != nil {
   221  		t.Fatalf("Failed to get leaf by index: %v", err)
   222  	}
   223  
   224  	if len(resp.Leaves) != 2 {
   225  		t.Fatalf("Expected two leaves but got %d", len(resp.Leaves))
   226  	}
   227  
   228  	if !proto.Equal(resp.Leaves[0], leaf1) {
   229  		t.Fatalf("Expected leaf1: %v but got: %v", leaf1, resp.Leaves[0])
   230  	}
   231  
   232  	if !proto.Equal(resp.Leaves[1], leaf3) {
   233  		t.Fatalf("Expected leaf3: %v but got: %v", leaf3, resp.Leaves[0])
   234  	}
   235  }
   236  
   237  func TestGetLeavesByRange(t *testing.T) {
   238  	ctx := context.Background()
   239  	ctrl := gomock.NewController(t)
   240  	defer ctrl.Finish()
   241  	fakeStorage := storage.NewMockLogStorage(ctrl)
   242  	fakeAdmin := storage.NewMockAdminStorage(ctrl)
   243  	tree := &trillian.Tree{TreeId: 6962, TreeType: trillian.TreeType_LOG, TreeState: trillian.TreeState_ACTIVE}
   244  
   245  	var tests = []struct {
   246  		start, count int64
   247  		skipTX       bool
   248  		adminErr     error
   249  		txErr        error
   250  		getErr       error
   251  		want         []*trillian.LogLeaf
   252  		wantErr      string
   253  	}{
   254  		{
   255  			start:    1,
   256  			count:    1,
   257  			adminErr: errors.New("admin_err"),
   258  			wantErr:  "admin_err",
   259  		},
   260  		{
   261  			start: 1,
   262  			count: 1,
   263  			want:  []*trillian.LogLeaf{leaf1},
   264  		},
   265  		{
   266  			start:   1,
   267  			count:   1,
   268  			txErr:   errors.New("test error xyzzy"),
   269  			wantErr: "test error xyzzy",
   270  		},
   271  		{
   272  			start:   1,
   273  			count:   1,
   274  			getErr:  errors.New("test error plugh"),
   275  			wantErr: "test error plugh",
   276  		},
   277  		{
   278  			start: 1,
   279  			count: 3,
   280  			want:  []*trillian.LogLeaf{leaf1, leaf2, leaf3},
   281  		},
   282  		{
   283  			start: 1,
   284  			count: 30,
   285  			want:  []*trillian.LogLeaf{leaf1, leaf2, leaf3},
   286  		},
   287  		{
   288  			start:   -1,
   289  			count:   1,
   290  			skipTX:  true,
   291  			wantErr: "want >= 0",
   292  		},
   293  		{
   294  			start:   1,
   295  			count:   0,
   296  			skipTX:  true,
   297  			wantErr: "want > 0",
   298  		},
   299  		{
   300  			start:   1,
   301  			count:   -1,
   302  			skipTX:  true,
   303  			wantErr: "want > 0",
   304  		},
   305  	}
   306  
   307  	for _, test := range tests {
   308  		if !test.skipTX {
   309  			mockTX := storage.NewMockLogTreeTX(ctrl)
   310  			mockAdminTX := storage.NewMockAdminTX(ctrl)
   311  			mockAdminTX.EXPECT().GetTree(gomock.Any(), tree.TreeId).Return(tree, test.adminErr)
   312  			mockAdminTX.EXPECT().Close().Return(nil)
   313  			fakeAdmin.EXPECT().Snapshot(gomock.Any()).Return(mockAdminTX, nil)
   314  			if test.adminErr == nil {
   315  				mockAdminTX.EXPECT().Commit().Return(nil)
   316  				if test.txErr != nil {
   317  					fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree).Return(nil, test.txErr)
   318  				} else {
   319  					fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree).Return(mockTX, nil)
   320  					mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   321  					if test.getErr != nil {
   322  						mockTX.EXPECT().GetLeavesByRange(gomock.Any(), test.start, test.count).Return(nil, test.getErr)
   323  					} else {
   324  						mockTX.EXPECT().GetLeavesByRange(gomock.Any(), test.start, test.count).Return(test.want, nil)
   325  						mockTX.EXPECT().Commit().Return(nil)
   326  					}
   327  					mockTX.EXPECT().Close().Return(nil)
   328  				}
   329  			} else {
   330  				if test.txErr != nil {
   331  					mockTX.EXPECT().Commit().Return(nil)
   332  				}
   333  			}
   334  		}
   335  		registry := extension.Registry{LogStorage: fakeStorage, AdminStorage: fakeAdmin}
   336  		server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   337  
   338  		req := trillian.GetLeavesByRangeRequest{
   339  			LogId:      tree.TreeId,
   340  			StartIndex: test.start,
   341  			Count:      test.count,
   342  		}
   343  		rsp, err := server.GetLeavesByRange(ctx, &req)
   344  		if err != nil {
   345  			if test.wantErr == "" {
   346  				t.Errorf("GetLeavesByRange(%d, %+d)=nil,%v; want _,nil", req.StartIndex, req.Count, err)
   347  			} else if !strings.Contains(err.Error(), test.wantErr) {
   348  				t.Errorf("GetLeavesByRange(%d, %+d)=nil,%v; want _, err containing %q", req.StartIndex, req.Count, err, test.wantErr)
   349  			}
   350  			continue
   351  		}
   352  		if test.wantErr != "" {
   353  			t.Errorf("GetLeavesByRange(%d, %+d)=_,nil; want nil, err containing %q", req.StartIndex, req.Count, test.wantErr)
   354  		}
   355  		if got := rsp.Leaves; !reflect.DeepEqual(got, test.want) {
   356  			t.Errorf("GetLeavesByRange(%d, %+d)=%+v; want %+v", req.StartIndex, req.Count, got, test.want)
   357  		}
   358  	}
   359  }
   360  
   361  func TestQueueLeavesStorageError(t *testing.T) {
   362  	ctrl := gomock.NewController(t)
   363  	defer ctrl.Finish()
   364  
   365  	test := newParameterizedTest(ctrl, "QueueLeaves", noTX,
   366  		func(s *stestonly.FakeLogStorage) {
   367  			s.QueueLeavesErr = errors.New("STORAGE")
   368  		},
   369  		nopTX,
   370  		func(s *TrillianLogRPCServer) error {
   371  			_, err := s.QueueLeaves(context.Background(), &queueRequest0)
   372  			return err
   373  		})
   374  
   375  	test.executeStorageFailureTest(t, queueRequest0.LogId)
   376  }
   377  
   378  func TestQueueLeavesInvalidLogId(t *testing.T) {
   379  	ctrl := gomock.NewController(t)
   380  	defer ctrl.Finish()
   381  
   382  	test := newParameterizedTest(ctrl, "QueueLeaves", noTX, nopStorage, nopTX,
   383  		func(s *TrillianLogRPCServer) error {
   384  			_, err := s.QueueLeaves(context.Background(), &queueRequest0Log2)
   385  			return err
   386  		})
   387  
   388  	test.executeInvalidLogIDTest(t, false /* snapshot */)
   389  }
   390  
   391  func okQueuedLeaf(l *trillian.LogLeaf) *trillian.QueuedLogLeaf {
   392  	return &trillian.QueuedLogLeaf{
   393  		Leaf:   l,
   394  		Status: status.New(codes.OK, "OK").Proto(),
   395  	}
   396  }
   397  func dupeQueuedLeaf(l *trillian.LogLeaf) *trillian.QueuedLogLeaf {
   398  	return &trillian.QueuedLogLeaf{
   399  		Leaf:   l,
   400  		Status: status.New(codes.AlreadyExists, "Seen this before, mate").Proto(),
   401  	}
   402  }
   403  
   404  func TestQueueLeaves(t *testing.T) {
   405  	ctx := context.Background()
   406  	ctrl := gomock.NewController(t)
   407  	defer ctrl.Finish()
   408  
   409  	mockStorage := storage.NewMockLogStorage(ctrl)
   410  	c1 := mockStorage.EXPECT().QueueLeaves(gomock.Any(), tree1, []*trillian.LogLeaf{leaf1}, fakeTime).Return([]*trillian.QueuedLogLeaf{okQueuedLeaf(leaf1)}, nil)
   411  	mockStorage.EXPECT().QueueLeaves(gomock.Any(), tree1, []*trillian.LogLeaf{leaf1}, fakeTime).After(c1).Return([]*trillian.QueuedLogLeaf{dupeQueuedLeaf(leaf1)}, nil)
   412  
   413  	registry := extension.Registry{
   414  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: queueRequest0.LogId, numSnapshots: 2}),
   415  		LogStorage:   mockStorage,
   416  	}
   417  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   418  
   419  	rsp, err := server.QueueLeaves(ctx, &queueRequest0)
   420  	if err != nil {
   421  		t.Fatalf("Failed to queue leaf: %v", err)
   422  	}
   423  	if len(rsp.QueuedLeaves) != 1 {
   424  		t.Errorf("QueueLeaves() returns %d leaves; want 1", len(rsp.QueuedLeaves))
   425  	}
   426  	queuedLeaf := rsp.QueuedLeaves[0]
   427  	if queuedLeaf.Status.Code != int32(code.Code_OK) {
   428  		t.Errorf("QueueLeaves().Status=%d,nil; want %d,nil", queuedLeaf.Status.Code, code.Code_OK)
   429  	}
   430  	if !proto.Equal(queueRequest0.Leaves[0], queuedLeaf.Leaf) {
   431  		diff := pretty.Compare(queueRequest0.Leaves[0], queuedLeaf.Leaf)
   432  		t.Errorf("post-QueueLeaves() diff:\n%v", diff)
   433  	}
   434  
   435  	// Repeating the operation gives ALREADY_EXISTS.
   436  	rsp, err = server.QueueLeaves(ctx, &queueRequest0)
   437  	if err != nil {
   438  		t.Fatalf("Failed to re-queue leaf: %v", err)
   439  	}
   440  	if len(rsp.QueuedLeaves) != 1 {
   441  		t.Errorf("QueueLeaves() returns %d leaves; want 1", len(rsp.QueuedLeaves))
   442  	}
   443  	queuedLeaf = rsp.QueuedLeaves[0]
   444  	if queuedLeaf.Status == nil || queuedLeaf.Status.Code != int32(code.Code_ALREADY_EXISTS) {
   445  		sc := "nil"
   446  		if queuedLeaf.Status != nil {
   447  			sc = fmt.Sprintf("%v", queuedLeaf.Status.Code)
   448  		}
   449  		t.Errorf("QueueLeaves().Status=%v,nil; want %v,nil", sc, code.Code_ALREADY_EXISTS)
   450  	}
   451  	if !proto.Equal(queueRequest0.Leaves[0], queuedLeaf.Leaf) {
   452  		diff := pretty.Compare(queueRequest0.Leaves[0], queuedLeaf.Leaf)
   453  		t.Errorf("post-QueueLeaves() diff:\n%v", diff)
   454  	}
   455  }
   456  
   457  func TestAddSequencedLeavesStorageError(t *testing.T) {
   458  	ctrl := gomock.NewController(t)
   459  	defer ctrl.Finish()
   460  
   461  	test := newParameterizedTest(ctrl, "AddSequencedLeaves", noTX,
   462  		func(s *stestonly.FakeLogStorage) {
   463  			s.AddSequencedLeavesErr = errors.New("STORAGE")
   464  		},
   465  		nopTX,
   466  		func(s *TrillianLogRPCServer) error {
   467  			_, err := s.AddSequencedLeaves(context.Background(), &addSeqRequest0)
   468  			return err
   469  		})
   470  	test.preordered = true
   471  
   472  	test.executeStorageFailureTest(t, addSeqRequest0.LogId)
   473  }
   474  
   475  func TestAddSequencedLeavesInvalidLogId(t *testing.T) {
   476  	ctrl := gomock.NewController(t)
   477  	defer ctrl.Finish()
   478  
   479  	test := newParameterizedTest(ctrl, "AddSequencedLeaves", noTX, nopStorage, nopTX,
   480  		func(s *TrillianLogRPCServer) error {
   481  			_, err := s.AddSequencedLeaves(context.Background(), &addSeqRequest0)
   482  			return err
   483  		})
   484  
   485  	test.executeInvalidLogIDTest(t, false /* snapshot */)
   486  }
   487  
   488  func TestAddSequencedLeaves(t *testing.T) {
   489  	ctx := context.Background()
   490  	ctrl := gomock.NewController(t)
   491  	defer ctrl.Finish()
   492  
   493  	tree := addTreeID(stestonly.PreorderedLogTree, addSeqRequest0.LogId)
   494  	mockStorage := storage.NewMockLogStorage(ctrl)
   495  	mockStorage.EXPECT().AddSequencedLeaves(gomock.Any(), tree, []*trillian.LogLeaf{leaf1}, gomock.Any()).
   496  		Return([]*trillian.QueuedLogLeaf{{Status: status.New(codes.OK, "OK").Proto()}}, nil)
   497  
   498  	registry := extension.Registry{
   499  		AdminStorage: fakeAdminStorage(ctrl, storageParams{addSeqRequest0.LogId, true, 1}),
   500  		LogStorage:   mockStorage,
   501  	}
   502  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   503  
   504  	rsp, err := server.AddSequencedLeaves(ctx, &addSeqRequest0)
   505  	if err != nil {
   506  		t.Fatalf("Failed to add leaf: %v", err)
   507  	}
   508  	if len(rsp.Results) != 1 {
   509  		t.Errorf("AddSequencedLeaves() returns %d leaves; want 1", len(rsp.Results))
   510  	}
   511  	result := rsp.Results[0]
   512  	if got, want := result.Status.Code, int32(code.Code_OK); got != want {
   513  		t.Errorf("AddSequencedLeaves().Status.Code=%d; want %d", got, want)
   514  	}
   515  	if result.Leaf != nil {
   516  		t.Errorf("AddSequencedLeaves().Leaf=%d; want nil", result.Leaf)
   517  	}
   518  }
   519  
   520  type latestRootTest struct {
   521  	req         trillian.GetLatestSignedLogRootRequest
   522  	wantRoot    trillian.GetLatestSignedLogRootResponse
   523  	errStr      string
   524  	noSnap      bool
   525  	snapErr     error
   526  	noRoot      bool
   527  	storageRoot trillian.SignedLogRoot
   528  	rootErr     error
   529  	noCommit    bool
   530  	commitErr   error
   531  	noClose     bool
   532  }
   533  
   534  func TestGetLatestSignedLogRoot2(t *testing.T) {
   535  	ctrl := gomock.NewController(t)
   536  	defer ctrl.Finish()
   537  
   538  	tests := []latestRootTest{
   539  		{
   540  			// Test error case when failing to get a snapshot from storage.
   541  			req:      getLogRootRequest1,
   542  			snapErr:  errors.New("SnapshotForTree() error"),
   543  			errStr:   "SnapshotFor",
   544  			noRoot:   true,
   545  			noCommit: true,
   546  			noClose:  true,
   547  		},
   548  		{
   549  			// Test error case when storage fails to provide a root.
   550  			req:      getLogRootRequest1,
   551  			errStr:   "LatestSigned",
   552  			rootErr:  errors.New("LatestSignedLogRoot() error"),
   553  			noCommit: true,
   554  		},
   555  		{
   556  			// Test error case where storage fails to commit the tx.
   557  			req:       getLogRootRequest1,
   558  			errStr:    "commit",
   559  			commitErr: errors.New("commit() error"),
   560  		},
   561  		{
   562  			// Test normal case where a root is returned correctly.
   563  			req:         getLogRootRequest1,
   564  			wantRoot:    trillian.GetLatestSignedLogRootResponse{SignedLogRoot: signedRoot1},
   565  			storageRoot: *signedRoot1,
   566  		},
   567  	}
   568  
   569  	for _, test := range tests {
   570  		fakeStorage := storage.NewMockLogStorage(ctrl)
   571  		mockTX := storage.NewMockLogTreeTX(ctrl)
   572  		if !test.noSnap {
   573  			fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, test.snapErr)
   574  		}
   575  		if !test.noRoot {
   576  			mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(test.storageRoot, test.rootErr)
   577  		}
   578  		if !test.noCommit {
   579  			mockTX.EXPECT().Commit().Return(test.commitErr)
   580  		}
   581  		if !test.noClose {
   582  			mockTX.EXPECT().Close().Return(nil)
   583  		}
   584  
   585  		registry := extension.Registry{
   586  			AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: test.req.LogId, numSnapshots: 1}),
   587  			LogStorage:   fakeStorage,
   588  		}
   589  		s := NewTrillianLogRPCServer(registry, fakeTimeSource)
   590  		got, err := s.GetLatestSignedLogRoot(context.Background(), &test.req)
   591  		if len(test.errStr) > 0 {
   592  			if err == nil || !strings.Contains(err.Error(), test.errStr) {
   593  				t.Errorf("GetLatestSignedLogRoot(%+v)=_,nil, want: _,err contains: %s but got: %v", test.req, test.errStr, err)
   594  			}
   595  		} else {
   596  			if err != nil {
   597  				t.Errorf("GetLatestSignedLogRoot(%+v)=_,%v, want: _,nil", test.req, err)
   598  				continue
   599  			}
   600  			// Ensure we got the expected root back.
   601  			if !proto.Equal(got.SignedLogRoot, test.wantRoot.SignedLogRoot) {
   602  				t.Errorf("GetConsistencyProof(%+v)=%v,nil, want: %v,nil", test.req, got, test.wantRoot)
   603  			}
   604  		}
   605  	}
   606  }
   607  
   608  func TestGetLeavesByHashBeginFails(t *testing.T) {
   609  	ctrl := gomock.NewController(t)
   610  	defer ctrl.Finish()
   611  
   612  	fakeStorage := storage.NewMockLogStorage(ctrl)
   613  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(nil, errors.New("TX"))
   614  	registry := extension.Registry{
   615  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getByHashRequest1.LogId, numSnapshots: 1}),
   616  		LogStorage:   fakeStorage,
   617  	}
   618  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   619  
   620  	_, err := server.GetLeavesByHash(context.Background(), &getByHashRequest1)
   621  	if err == nil || !strings.Contains(err.Error(), "TX") {
   622  		t.Fatalf("Returned wrong error response when begin failed: %v", err)
   623  	}
   624  }
   625  
   626  func TestGetLeavesByHashStorageFails(t *testing.T) {
   627  	ctrl := gomock.NewController(t)
   628  	defer ctrl.Finish()
   629  
   630  	test := newParameterizedTest(ctrl, "GetLeavesByHash", readOnly, nopStorage,
   631  		func(t *storage.MockLogTreeTX) {
   632  			t.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("test"), []byte("data")}, false).Return(nil, errors.New("STORAGE"))
   633  		},
   634  		func(s *TrillianLogRPCServer) error {
   635  			_, err := s.GetLeavesByHash(context.Background(), &getByHashRequest1)
   636  			return err
   637  		})
   638  
   639  	test.executeStorageFailureTest(t, getByHashRequest1.LogId)
   640  }
   641  
   642  func TestLeavesByHashCommitFails(t *testing.T) {
   643  	ctrl := gomock.NewController(t)
   644  	defer ctrl.Finish()
   645  
   646  	test := newParameterizedTest(ctrl, "GetLeavesByHash", readOnly, nopStorage,
   647  		func(t *storage.MockLogTreeTX) {
   648  			t.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("test"), []byte("data")}, false).Return(nil, nil)
   649  			t.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   650  		},
   651  		func(s *TrillianLogRPCServer) error {
   652  			_, err := s.GetLeavesByHash(context.Background(), &getByHashRequest1)
   653  			return err
   654  		})
   655  
   656  	test.executeCommitFailsTest(t, getByHashRequest1.LogId)
   657  }
   658  
   659  func TestGetLeavesByHashInvalidLogId(t *testing.T) {
   660  	ctrl := gomock.NewController(t)
   661  	defer ctrl.Finish()
   662  
   663  	test := newParameterizedTest(ctrl, "GetLeavesByHash", readOnly, nopStorage,
   664  		func(t *storage.MockLogTreeTX) {},
   665  		func(s *TrillianLogRPCServer) error {
   666  			_, err := s.GetLeavesByHash(context.Background(), &getByHashRequest2)
   667  			return err
   668  		})
   669  
   670  	test.executeInvalidLogIDTest(t, true /* snapshot */)
   671  }
   672  
   673  func TestGetLeavesByHash(t *testing.T) {
   674  	ctrl := gomock.NewController(t)
   675  	defer ctrl.Finish()
   676  
   677  	fakeStorage := storage.NewMockLogStorage(ctrl)
   678  	mockTX := storage.NewMockLogTreeTX(ctrl)
   679  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   680  	mockTX.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("test"), []byte("data")}, false).Return([]*trillian.LogLeaf{leaf1, leaf3}, nil)
   681  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   682  	mockTX.EXPECT().Commit().Return(nil)
   683  	mockTX.EXPECT().Close().Return(nil)
   684  
   685  	registry := extension.Registry{
   686  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getByHashRequest1.LogId, numSnapshots: 1}),
   687  		LogStorage:   fakeStorage,
   688  	}
   689  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   690  
   691  	resp, err := server.GetLeavesByHash(context.Background(), &getByHashRequest1)
   692  	if err != nil {
   693  		t.Fatalf("Got error trying to get leaves by hash: %v", err)
   694  	}
   695  
   696  	if len(resp.Leaves) != 2 || !proto.Equal(resp.Leaves[0], leaf1) || !proto.Equal(resp.Leaves[1], leaf3) {
   697  		t.Fatalf("Expected leaves %v and %v but got: %v", leaf1, leaf3, resp.Leaves)
   698  	}
   699  }
   700  
   701  func TestGetProofByHashBeginTXFails(t *testing.T) {
   702  	ctrl := gomock.NewController(t)
   703  	defer ctrl.Finish()
   704  
   705  	test := newParameterizedTest(ctrl, "GetInclusionProofByHash", readOnly, nopStorage,
   706  		func(t *storage.MockLogTreeTX) {},
   707  		func(s *TrillianLogRPCServer) error {
   708  			_, err := s.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest25)
   709  			return err
   710  		})
   711  
   712  	test.executeBeginFailsTest(t, getInclusionProofByHashRequest25.LogId)
   713  }
   714  
   715  func TestGetProofByHashNoLeafForHash(t *testing.T) {
   716  	ctrl := gomock.NewController(t)
   717  	defer ctrl.Finish()
   718  
   719  	test := newParameterizedTest(ctrl, "GetInclusionProofByHash", readOnly, nopStorage,
   720  		func(t *storage.MockLogTreeTX) {
   721  			t.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return(nil, errors.New("STORAGE"))
   722  		},
   723  		func(s *TrillianLogRPCServer) error {
   724  			_, err := s.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest25)
   725  			return err
   726  		})
   727  
   728  	test.executeStorageFailureTest(t, getInclusionProofByHashRequest25.LogId)
   729  }
   730  
   731  func TestGetProofByHashGetNodesFails(t *testing.T) {
   732  	ctrl := gomock.NewController(t)
   733  	defer ctrl.Finish()
   734  
   735  	test := newParameterizedTest(ctrl, "GetInclusionProofByHash", readOnly, nopStorage,
   736  		func(t *storage.MockLogTreeTX) {
   737  			t.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   738  			t.EXPECT().ReadRevision().Return(int64(root1.Revision))
   739  			t.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return([]*trillian.LogLeaf{{LeafIndex: 2}}, nil)
   740  			t.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{}, errors.New("STORAGE"))
   741  		},
   742  		func(s *TrillianLogRPCServer) error {
   743  			_, err := s.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest7)
   744  			return err
   745  		})
   746  
   747  	test.executeStorageFailureTest(t, getInclusionProofByHashRequest7.LogId)
   748  }
   749  
   750  func TestGetProofByHashWrongNodeCountFetched(t *testing.T) {
   751  	ctrl := gomock.NewController(t)
   752  	defer ctrl.Finish()
   753  
   754  	fakeStorage := storage.NewMockLogStorage(ctrl)
   755  	mockTX := storage.NewMockLogTreeTX(ctrl)
   756  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   757  
   758  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   759  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
   760  	mockTX.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return([]*trillian.LogLeaf{{LeafIndex: 2}}, nil)
   761  	// The server expects three nodes from storage but we return only two
   762  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeRevision: 3}, {NodeRevision: 2}}, nil)
   763  	mockTX.EXPECT().Close().Return(nil)
   764  
   765  	registry := extension.Registry{
   766  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
   767  		LogStorage:   fakeStorage,
   768  	}
   769  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   770  
   771  	_, err := server.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest7)
   772  	if err == nil || !strings.Contains(err.Error(), "expected 3 nodes") {
   773  		t.Fatalf("get inclusion proof by hash returned no or wrong error when get nodes returns wrong count: %v", err)
   774  	}
   775  }
   776  
   777  func TestGetProofByHashWrongNodeReturned(t *testing.T) {
   778  	ctrl := gomock.NewController(t)
   779  	defer ctrl.Finish()
   780  
   781  	fakeStorage := storage.NewMockLogStorage(ctrl)
   782  	mockTX := storage.NewMockLogTreeTX(ctrl)
   783  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   784  
   785  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   786  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
   787  	mockTX.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return([]*trillian.LogLeaf{{LeafIndex: 2}}, nil)
   788  	// We set this up so one of the returned nodes has the wrong ID
   789  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3}, {NodeID: stestonly.MustCreateNodeIDForTreeCoords(4, 5, 64), NodeRevision: 2}, {NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3}}, nil)
   790  	mockTX.EXPECT().Close().Return(nil)
   791  
   792  	registry := extension.Registry{
   793  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
   794  		LogStorage:   fakeStorage,
   795  	}
   796  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   797  
   798  	_, err := server.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest7)
   799  	if err == nil || !strings.Contains(err.Error(), "expected node ") {
   800  		t.Fatalf("get inclusion proof by hash returned no or wrong error when get nodes returns wrong node: %v", err)
   801  	}
   802  }
   803  
   804  func TestGetProofByHashCommitFails(t *testing.T) {
   805  	ctrl := gomock.NewController(t)
   806  	defer ctrl.Finish()
   807  
   808  	test := newParameterizedTest(ctrl, "GetInclusionProofByHash", readOnly, nopStorage,
   809  		func(t *storage.MockLogTreeTX) {
   810  			t.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   811  			t.EXPECT().ReadRevision().Return(int64(root1.Revision))
   812  			t.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return([]*trillian.LogLeaf{{LeafIndex: 2}}, nil)
   813  			t.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3}, {NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2}, {NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3}}, nil)
   814  		},
   815  		func(s *TrillianLogRPCServer) error {
   816  			_, err := s.GetInclusionProofByHash(context.Background(), &getInclusionProofByHashRequest7)
   817  			return err
   818  		})
   819  
   820  	test.executeCommitFailsTest(t, getInclusionProofByHashRequest7.LogId)
   821  }
   822  
   823  func TestGetProofByHash(t *testing.T) {
   824  	ctx := context.Background()
   825  	for _, tc := range []struct {
   826  		desc            string
   827  		wantCode        codes.Code
   828  		leavesByHashVal []*trillian.LogLeaf
   829  	}{
   830  		{desc: "OK", leavesByHashVal: []*trillian.LogLeaf{{LeafIndex: 2}}},
   831  		{desc: "NotFoundTreeSize", wantCode: codes.NotFound, leavesByHashVal: []*trillian.LogLeaf{{LeafIndex: 7}}},
   832  	} {
   833  		t.Run(tc.desc, func(t *testing.T) {
   834  			ctrl := gomock.NewController(t)
   835  			defer ctrl.Finish()
   836  
   837  			fakeStorage := storage.NewMockLogStorage(ctrl)
   838  			mockTX := storage.NewMockLogTreeTX(ctrl)
   839  			fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   840  
   841  			mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   842  			mockTX.EXPECT().GetLeavesByHash(gomock.Any(), [][]byte{[]byte("ahash")}, false).Return(tc.leavesByHashVal, nil)
   843  			mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision)).AnyTimes()
   844  			mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
   845  				{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
   846  				{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
   847  				{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil).AnyTimes()
   848  			mockTX.EXPECT().Commit().Return(nil)
   849  			mockTX.EXPECT().Close().Return(nil)
   850  
   851  			registry := extension.Registry{
   852  				AdminStorage: fakeAdminStorage(ctrl, storageParams{
   853  					treeID:       logID1,
   854  					numSnapshots: 1,
   855  				}),
   856  				LogStorage: fakeStorage,
   857  			}
   858  			server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   859  
   860  			proofResponse, err := server.GetInclusionProofByHash(ctx,
   861  				&trillian.GetInclusionProofByHashRequest{
   862  					LogId:    logID1,
   863  					TreeSize: 7,
   864  					LeafHash: []byte("ahash"),
   865  				})
   866  			if got, want := status.Code(err), tc.wantCode; got != want {
   867  				t.Fatalf("GetInclusionProofByHash(): %v, want %v", err, want)
   868  			}
   869  			if err != nil {
   870  				return
   871  			}
   872  
   873  			if proofResponse == nil {
   874  				t.Fatalf("server response was not successful: %v", proofResponse)
   875  			}
   876  
   877  			expectedProof := trillian.Proof{
   878  				LeafIndex: 2,
   879  				Hashes: [][]byte{
   880  					[]byte("nodehash0"),
   881  					[]byte("nodehash1"),
   882  					[]byte("nodehash2"),
   883  				},
   884  			}
   885  
   886  			if !proto.Equal(proofResponse.Proof[0], &expectedProof) {
   887  				t.Fatalf("expected proof: %v but got: %v", expectedProof, proofResponse.Proof[0])
   888  			}
   889  		})
   890  	}
   891  }
   892  
   893  func TestGetProofByIndexBeginTXFails(t *testing.T) {
   894  	ctrl := gomock.NewController(t)
   895  	defer ctrl.Finish()
   896  
   897  	test := newParameterizedTest(ctrl, "GetInclusionProof", readOnly, nopStorage,
   898  		func(t *storage.MockLogTreeTX) {},
   899  		func(s *TrillianLogRPCServer) error {
   900  			_, err := s.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest25)
   901  			return err
   902  		})
   903  
   904  	test.executeBeginFailsTest(t, getInclusionProofByIndexRequest25.LogId)
   905  }
   906  
   907  func TestGetProofByIndexGetNodesFails(t *testing.T) {
   908  	ctrl := gomock.NewController(t)
   909  	defer ctrl.Finish()
   910  
   911  	test := newParameterizedTest(ctrl, "GetInclusionProof", readOnly, nopStorage,
   912  		func(t *storage.MockLogTreeTX) {
   913  			t.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   914  			t.EXPECT().ReadRevision().Return(int64(root1.Revision))
   915  			t.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{}, errors.New("STORAGE"))
   916  		},
   917  		func(s *TrillianLogRPCServer) error {
   918  			_, err := s.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest7)
   919  			return err
   920  		})
   921  
   922  	test.executeStorageFailureTest(t, getInclusionProofByIndexRequest7.LogId)
   923  }
   924  
   925  func TestGetProofByIndexWrongNodeCountFetched(t *testing.T) {
   926  	ctrl := gomock.NewController(t)
   927  	defer ctrl.Finish()
   928  
   929  	fakeStorage := storage.NewMockLogStorage(ctrl)
   930  	mockTX := storage.NewMockLogTreeTX(ctrl)
   931  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   932  
   933  	// The server expects three nodes from storage but we return only two
   934  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   935  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
   936  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeRevision: 3}, {NodeRevision: 2}}, nil)
   937  	mockTX.EXPECT().Close().Return(nil)
   938  
   939  	registry := extension.Registry{
   940  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
   941  		LogStorage:   fakeStorage,
   942  	}
   943  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   944  
   945  	_, err := server.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest7)
   946  	if err == nil || !strings.Contains(err.Error(), "expected 3 nodes") {
   947  		t.Fatalf("get inclusion proof by index returned no or wrong error when get nodes returns wrong count: %v", err)
   948  	}
   949  }
   950  
   951  func TestGetProofByIndexWrongNodeReturned(t *testing.T) {
   952  	ctrl := gomock.NewController(t)
   953  	defer ctrl.Finish()
   954  
   955  	fakeStorage := storage.NewMockLogStorage(ctrl)
   956  	mockTX := storage.NewMockLogTreeTX(ctrl)
   957  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
   958  
   959  	// We set this up so one of the returned nodes has the wrong ID
   960  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   961  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
   962  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3}, {NodeID: stestonly.MustCreateNodeIDForTreeCoords(4, 5, 64), NodeRevision: 2}, {NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3}}, nil)
   963  	mockTX.EXPECT().Close().Return(nil)
   964  
   965  	registry := extension.Registry{
   966  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
   967  		LogStorage:   fakeStorage,
   968  	}
   969  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
   970  
   971  	_, err := server.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest7)
   972  	if err == nil || !strings.Contains(err.Error(), "expected node ") {
   973  		t.Fatalf("get inclusion proof by index returned no or wrong error when get nodes returns wrong node: %v", err)
   974  	}
   975  }
   976  
   977  func TestGetProofByIndexCommitFails(t *testing.T) {
   978  	ctrl := gomock.NewController(t)
   979  	defer ctrl.Finish()
   980  
   981  	test := newParameterizedTest(ctrl, "GetInclusionProof", readOnly, nopStorage,
   982  		func(t *storage.MockLogTreeTX) {
   983  			t.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
   984  			t.EXPECT().ReadRevision().Return(int64(root1.Revision))
   985  			t.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3}, {NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2}, {NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3}}, nil)
   986  		},
   987  		func(s *TrillianLogRPCServer) error {
   988  			_, err := s.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest7)
   989  			return err
   990  		})
   991  
   992  	test.executeCommitFailsTest(t, getInclusionProofByIndexRequest7.LogId)
   993  }
   994  
   995  func TestGetProofByIndex(t *testing.T) {
   996  	ctrl := gomock.NewController(t)
   997  	defer ctrl.Finish()
   998  
   999  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1000  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1001  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1002  
  1003  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1004  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1005  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1006  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1007  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1008  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1009  	mockTX.EXPECT().Commit().Return(nil)
  1010  	mockTX.EXPECT().Close().Return(nil)
  1011  
  1012  	registry := extension.Registry{
  1013  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest17.LogId, numSnapshots: 1}),
  1014  		LogStorage:   fakeStorage,
  1015  	}
  1016  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1017  
  1018  	proofResponse, err := server.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest7)
  1019  	if err != nil {
  1020  		t.Fatalf("get inclusion proof by index should have succeeded but we got: %v", err)
  1021  	}
  1022  
  1023  	if proofResponse == nil {
  1024  		t.Fatalf("server response was not successful: %v", proofResponse)
  1025  	}
  1026  
  1027  	expectedProof := trillian.Proof{
  1028  		LeafIndex: 2,
  1029  		Hashes: [][]byte{
  1030  			[]byte("nodehash0"),
  1031  			[]byte("nodehash1"),
  1032  			[]byte("nodehash2"),
  1033  		},
  1034  	}
  1035  
  1036  	if !proto.Equal(proofResponse.Proof, &expectedProof) {
  1037  		t.Fatalf("expected proof: %v but got: %v", expectedProof, proofResponse.Proof)
  1038  	}
  1039  }
  1040  
  1041  func TestGetProofByIndexBeyondSTH(t *testing.T) {
  1042  	ctrl := gomock.NewController(t)
  1043  	defer ctrl.Finish()
  1044  
  1045  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1046  	mockTx := storage.NewMockLogTreeTX(ctrl)
  1047  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTx, nil)
  1048  
  1049  	mockTx.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1050  	mockTx.EXPECT().Close().Return(nil)
  1051  
  1052  	registry := extension.Registry{
  1053  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest17.LogId, numSnapshots: 1}),
  1054  		LogStorage:   fakeStorage,
  1055  	}
  1056  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1057  
  1058  	proofResponse, err := server.GetInclusionProof(context.Background(), &getInclusionProofByIndexRequest25)
  1059  	if err != nil {
  1060  		t.Fatalf("get inclusion proof by index should have succeeded but we got: %v", err)
  1061  	}
  1062  
  1063  	if proofResponse == nil {
  1064  		t.Fatalf("server response was not successful: %v", proofResponse)
  1065  	}
  1066  
  1067  	if proofResponse.Proof != nil {
  1068  		t.Fatalf("expected nil proof but got: %v", proofResponse.Proof)
  1069  	}
  1070  }
  1071  
  1072  func TestGetEntryAndProofBeginTXFails(t *testing.T) {
  1073  	ctrl := gomock.NewController(t)
  1074  	defer ctrl.Finish()
  1075  
  1076  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1077  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(nil, errors.New("BeginTX"))
  1078  	registry := extension.Registry{
  1079  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest17.LogId, numSnapshots: 1}),
  1080  		LogStorage:   fakeStorage,
  1081  	}
  1082  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1083  
  1084  	_, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest17)
  1085  	if err == nil || !strings.Contains(err.Error(), "BeginTX") {
  1086  		t.Fatalf("get entry and proof returned no or wrong error when begin tx failed: %v", err)
  1087  	}
  1088  }
  1089  
  1090  func TestGetEntryAndProofGetMerkleNodesFails(t *testing.T) {
  1091  	ctrl := gomock.NewController(t)
  1092  	defer ctrl.Finish()
  1093  
  1094  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1095  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1096  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1097  
  1098  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1099  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1100  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{}, errors.New("GetNodes"))
  1101  	mockTX.EXPECT().Close().Return(nil)
  1102  
  1103  	registry := extension.Registry{
  1104  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
  1105  		LogStorage:   fakeStorage,
  1106  	}
  1107  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1108  
  1109  	_, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest7)
  1110  	if err == nil || !strings.Contains(err.Error(), "GetNodes") {
  1111  		t.Fatalf("get entry and proof returned no or wrong error when get nodes failed: %v", err)
  1112  	}
  1113  }
  1114  
  1115  func TestGetEntryAndProofGetLeavesFails(t *testing.T) {
  1116  	ctrl := gomock.NewController(t)
  1117  	defer ctrl.Finish()
  1118  
  1119  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1120  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1121  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1122  
  1123  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1124  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1125  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1126  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1127  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1128  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1129  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{2}).Return(nil, errors.New("GetLeaves"))
  1130  	mockTX.EXPECT().Close().Return(nil)
  1131  
  1132  	registry := extension.Registry{
  1133  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
  1134  		LogStorage:   fakeStorage,
  1135  	}
  1136  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1137  
  1138  	_, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest7)
  1139  	if err == nil || !strings.Contains(err.Error(), "GetLeaves") {
  1140  		t.Fatalf("get entry and proof returned no or wrong error when get leaves failed: %v", err)
  1141  	}
  1142  }
  1143  
  1144  func TestGetEntryAndProofGetLeavesReturnsMultiple(t *testing.T) {
  1145  	ctrl := gomock.NewController(t)
  1146  	defer ctrl.Finish()
  1147  
  1148  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1149  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1150  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1151  
  1152  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1153  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1154  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1155  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1156  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1157  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1158  	// Code passed one leaf index so expects one result, but we return more
  1159  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{2}).Return([]*trillian.LogLeaf{leaf1, leaf3}, nil)
  1160  	mockTX.EXPECT().Close().Return(nil)
  1161  
  1162  	registry := extension.Registry{
  1163  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
  1164  		LogStorage:   fakeStorage,
  1165  	}
  1166  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1167  
  1168  	_, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest7)
  1169  	if err == nil || !strings.Contains(err.Error(), "expected one leaf") {
  1170  		t.Fatalf("get entry and proof returned no or wrong error when storage returns multiple leaves: %v", err)
  1171  	}
  1172  }
  1173  
  1174  func TestGetEntryAndProofCommitFails(t *testing.T) {
  1175  	ctrl := gomock.NewController(t)
  1176  	defer ctrl.Finish()
  1177  
  1178  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1179  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1180  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1181  
  1182  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1183  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1184  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1185  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1186  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1187  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1188  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{2}).Return([]*trillian.LogLeaf{leaf1}, nil)
  1189  	mockTX.EXPECT().Commit().Return(errors.New("COMMIT"))
  1190  	mockTX.EXPECT().Close().Return(nil)
  1191  
  1192  	registry := extension.Registry{
  1193  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
  1194  		LogStorage:   fakeStorage,
  1195  	}
  1196  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1197  
  1198  	_, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest7)
  1199  	if err == nil || !strings.Contains(err.Error(), "COMMIT") {
  1200  		t.Fatalf("get entry and proof returned no or wrong error when commit failed: %v", err)
  1201  	}
  1202  }
  1203  
  1204  func TestGetEntryAndProof(t *testing.T) {
  1205  	ctrl := gomock.NewController(t)
  1206  	defer ctrl.Finish()
  1207  
  1208  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1209  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1210  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1211  
  1212  	mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1213  	mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1214  	mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1215  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1216  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1217  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1218  	mockTX.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{2}).Return([]*trillian.LogLeaf{leaf1}, nil)
  1219  	mockTX.EXPECT().Commit().Return(nil)
  1220  	mockTX.EXPECT().Close().Return(nil)
  1221  
  1222  	registry := extension.Registry{
  1223  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest7.LogId, numSnapshots: 1}),
  1224  		LogStorage:   fakeStorage,
  1225  	}
  1226  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1227  
  1228  	response, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest7)
  1229  	if err != nil {
  1230  		t.Fatalf("get entry and proof should have succeeded but we got: %v", err)
  1231  	}
  1232  
  1233  	// Check the proof is the one we expected
  1234  	expectedProof := trillian.Proof{
  1235  		LeafIndex: 2,
  1236  		Hashes: [][]byte{
  1237  			[]byte("nodehash0"),
  1238  			[]byte("nodehash1"),
  1239  			[]byte("nodehash2"),
  1240  		},
  1241  	}
  1242  
  1243  	if !proto.Equal(response.Proof, &expectedProof) {
  1244  		t.Fatalf("expected proof: %v but got: %v", expectedProof, response.Proof)
  1245  	}
  1246  
  1247  	// Check we got the correct leaf data
  1248  	if !proto.Equal(response.Leaf, leaf1) {
  1249  		t.Fatalf("Expected leaf %v but got: %v", leaf1, response.Leaf)
  1250  	}
  1251  }
  1252  
  1253  func TestGetEntryAndProofSkewNoProof(t *testing.T) {
  1254  	ctrl := gomock.NewController(t)
  1255  	defer ctrl.Finish()
  1256  
  1257  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1258  	mockTx := storage.NewMockLogTreeTX(ctrl)
  1259  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTx, nil)
  1260  
  1261  	mockTx.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1262  	mockTx.EXPECT().Commit().Return(nil)
  1263  	mockTx.EXPECT().Close().Return(nil)
  1264  
  1265  	registry := extension.Registry{
  1266  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest17_11.LogId, numSnapshots: 1}),
  1267  		LogStorage:   fakeStorage,
  1268  	}
  1269  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1270  
  1271  	response, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest17_11)
  1272  	if err != nil {
  1273  		t.Errorf("get entry and proof should have succeeded but we got: %v", err)
  1274  	}
  1275  
  1276  	if response.Proof != nil {
  1277  		t.Errorf("expected nil proof but got: %v", response.Proof)
  1278  	}
  1279  
  1280  	if response.Leaf != nil {
  1281  		t.Fatalf("Expected nil leaf but got: %v", response.Leaf)
  1282  	}
  1283  }
  1284  
  1285  func TestGetEntryAndProofSkewSmallerTree(t *testing.T) {
  1286  	ctrl := gomock.NewController(t)
  1287  	defer ctrl.Finish()
  1288  
  1289  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1290  	mockTx := storage.NewMockLogTreeTX(ctrl)
  1291  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTx, nil)
  1292  
  1293  	mockTx.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  1294  	mockTx.EXPECT().ReadRevision().Return(signedRoot1.TreeRevision) // nolint: megacheck
  1295  	mockTx.EXPECT().GetMerkleNodes(gomock.Any(), revision1, nodeIdsInclusionSize7Index2).Return([]storage.Node{
  1296  		{NodeID: nodeIdsInclusionSize7Index2[0], NodeRevision: 3, Hash: []byte("nodehash0")},
  1297  		{NodeID: nodeIdsInclusionSize7Index2[1], NodeRevision: 2, Hash: []byte("nodehash1")},
  1298  		{NodeID: nodeIdsInclusionSize7Index2[2], NodeRevision: 3, Hash: []byte("nodehash2")}}, nil)
  1299  	mockTx.EXPECT().GetLeavesByIndex(gomock.Any(), []int64{2}).Return([]*trillian.LogLeaf{leaf1}, nil)
  1300  	mockTx.EXPECT().Commit().Return(nil)
  1301  	mockTx.EXPECT().Close().Return(nil)
  1302  
  1303  	registry := extension.Registry{
  1304  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: getEntryAndProofRequest17_2.LogId, numSnapshots: 1}),
  1305  		LogStorage:   fakeStorage,
  1306  	}
  1307  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1308  
  1309  	response, err := server.GetEntryAndProof(context.Background(), &getEntryAndProofRequest17_2)
  1310  	if err != nil {
  1311  		t.Fatalf("get entry and proof should have succeeded but we got: %v", err)
  1312  	}
  1313  
  1314  	// Check the proof is the one we expected
  1315  	expectedProof := trillian.Proof{
  1316  		LeafIndex: 2,
  1317  		Hashes: [][]byte{
  1318  			[]byte("nodehash0"),
  1319  			[]byte("nodehash1"),
  1320  			[]byte("nodehash2"),
  1321  		},
  1322  	}
  1323  
  1324  	if !proto.Equal(response.Proof, &expectedProof) {
  1325  		t.Fatalf("expected proof: %v but got: %v", expectedProof, response.Proof)
  1326  	}
  1327  
  1328  	// Check we got the correct leaf data
  1329  	if !proto.Equal(response.Leaf, leaf1) {
  1330  		t.Fatalf("Expected leaf %v but got: %v", leaf1, response.Leaf)
  1331  	}
  1332  
  1333  	// Check we got the right signed log root
  1334  	if !proto.Equal(response.SignedLogRoot, signedRoot1) {
  1335  		t.Fatalf("expected root: %v got: %v", signedRoot1, response.SignedLogRoot)
  1336  	}
  1337  }
  1338  
  1339  func TestGetSequencedLeafCountBeginTXFails(t *testing.T) {
  1340  	ctrl := gomock.NewController(t)
  1341  	defer ctrl.Finish()
  1342  
  1343  	test := newParameterizedTest(ctrl, "GetSequencedLeafCount", readOnly, nopStorage,
  1344  		func(t *storage.MockLogTreeTX) {},
  1345  		func(s *TrillianLogRPCServer) error {
  1346  			_, err := s.GetSequencedLeafCount(context.Background(), &trillian.GetSequencedLeafCountRequest{LogId: logID1})
  1347  			return err
  1348  		})
  1349  
  1350  	test.executeBeginFailsTest(t, logID1)
  1351  }
  1352  
  1353  func TestGetSequencedLeafCountStorageFails(t *testing.T) {
  1354  	ctrl := gomock.NewController(t)
  1355  	defer ctrl.Finish()
  1356  
  1357  	test := newParameterizedTest(ctrl, "GetSequencedLeafCount", readOnly, nopStorage,
  1358  		func(t *storage.MockLogTreeTX) {
  1359  			t.EXPECT().GetSequencedLeafCount(gomock.Any()).Return(int64(0), errors.New("STORAGE"))
  1360  		},
  1361  		func(s *TrillianLogRPCServer) error {
  1362  			_, err := s.GetSequencedLeafCount(context.Background(), &trillian.GetSequencedLeafCountRequest{LogId: logID1})
  1363  			return err
  1364  		})
  1365  
  1366  	test.executeStorageFailureTest(t, logID1)
  1367  }
  1368  
  1369  func TestGetSequencedLeafCountCommitFails(t *testing.T) {
  1370  	ctrl := gomock.NewController(t)
  1371  	defer ctrl.Finish()
  1372  
  1373  	test := newParameterizedTest(ctrl, "GetSequencedLeafCount", readOnly, nopStorage,
  1374  		func(t *storage.MockLogTreeTX) {
  1375  			t.EXPECT().GetSequencedLeafCount(gomock.Any()).Return(int64(27), nil)
  1376  		},
  1377  		func(s *TrillianLogRPCServer) error {
  1378  			_, err := s.GetSequencedLeafCount(context.Background(), &trillian.GetSequencedLeafCountRequest{LogId: logID1})
  1379  			return err
  1380  		})
  1381  
  1382  	test.executeCommitFailsTest(t, logID1)
  1383  }
  1384  
  1385  func TestGetSequencedLeafCount(t *testing.T) {
  1386  	ctrl := gomock.NewController(t)
  1387  	defer ctrl.Finish()
  1388  
  1389  	fakeStorage := storage.NewMockLogStorage(ctrl)
  1390  	mockTX := storage.NewMockLogTreeTX(ctrl)
  1391  	fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, nil)
  1392  
  1393  	mockTX.EXPECT().GetSequencedLeafCount(gomock.Any()).Return(int64(268), nil)
  1394  	mockTX.EXPECT().Commit().Return(nil)
  1395  	mockTX.EXPECT().Close().Return(nil)
  1396  
  1397  	registry := extension.Registry{
  1398  		AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: logID1, numSnapshots: 1}),
  1399  		LogStorage:   fakeStorage,
  1400  	}
  1401  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1402  
  1403  	response, err := server.GetSequencedLeafCount(context.Background(), &trillian.GetSequencedLeafCountRequest{LogId: logID1})
  1404  	if err != nil {
  1405  		t.Fatalf("expected no error getting leaf count but got: %v", err)
  1406  	}
  1407  
  1408  	if got, want := response.LeafCount, int64(268); got != want {
  1409  		t.Fatalf("expected leaf count: %d but got: %d", want, got)
  1410  	}
  1411  }
  1412  
  1413  type consistProofTest struct {
  1414  	req         trillian.GetConsistencyProofRequest
  1415  	errStr      string
  1416  	wantHashes  [][]byte
  1417  	noSnap      bool
  1418  	snapErr     error
  1419  	noRoot      bool
  1420  	rootErr     error
  1421  	noRev       bool
  1422  	nodeIDs     []storage.NodeID
  1423  	nodes       []storage.Node
  1424  	getNodesErr error
  1425  	noCommit    bool
  1426  	commitErr   error
  1427  	noClose     bool
  1428  }
  1429  
  1430  func TestGetConsistencyProof(t *testing.T) {
  1431  	tests := []consistProofTest{
  1432  		{
  1433  			// Storage snapshot fails, should result in an error. Happens before we have a TX so
  1434  			// no Close() etc.
  1435  			req:      getConsistencyProofRequest7,
  1436  			errStr:   "SnapshotFor",
  1437  			snapErr:  errors.New("SnapshotForTree() failed"),
  1438  			noRoot:   true,
  1439  			noRev:    true,
  1440  			noCommit: true,
  1441  			noClose:  true,
  1442  		},
  1443  		{
  1444  			// Storage fails to read the log root, should result in an error.
  1445  			req:      getConsistencyProofRequest7,
  1446  			errStr:   "LatestSigned",
  1447  			rootErr:  errors.New("LatestSignedLogRoot() failed"),
  1448  			noRev:    true,
  1449  			noCommit: true,
  1450  		},
  1451  		{
  1452  			// Storage fails to get nodes, should result in an error
  1453  			req:         getConsistencyProofRequest7,
  1454  			errStr:      "getMerkle",
  1455  			nodeIDs:     nodeIdsConsistencySize4ToSize7,
  1456  			wantHashes:  [][]byte{[]byte("nodehash")},
  1457  			nodes:       []storage.Node{{NodeID: stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64), NodeRevision: 3, Hash: []byte("nodehash")}},
  1458  			getNodesErr: errors.New("getMerkleNodes() failed"),
  1459  			noCommit:    true,
  1460  		},
  1461  		{
  1462  			// Storage fails to commit, should result in an error.
  1463  			req:        getConsistencyProofRequest7,
  1464  			errStr:     "commit",
  1465  			wantHashes: [][]byte{[]byte("nodehash")},
  1466  			nodeIDs:    nodeIdsConsistencySize4ToSize7,
  1467  			nodes:      []storage.Node{{NodeID: stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64), NodeRevision: 3, Hash: []byte("nodehash")}},
  1468  			commitErr:  errors.New("commit() failed"),
  1469  		},
  1470  		{
  1471  			// Storage doesn't return the requested node, should result in an error.
  1472  			req:        getConsistencyProofRequest7,
  1473  			errStr:     "expected node {{[0 0 0 0 0 0 0 4] 62}",
  1474  			wantHashes: [][]byte{[]byte("nodehash")},
  1475  			nodeIDs:    nodeIdsConsistencySize4ToSize7,
  1476  			nodes:      []storage.Node{{NodeID: stestonly.MustCreateNodeIDForTreeCoords(3, 1, 64), NodeRevision: 3, Hash: []byte("nodehash")}},
  1477  			noCommit:   true,
  1478  		},
  1479  		{
  1480  			// Storage returns an unexpected extra node, should result in an error.
  1481  			req:        getConsistencyProofRequest7,
  1482  			errStr:     "expected 1 nodes",
  1483  			wantHashes: [][]byte{[]byte("nodehash")},
  1484  			nodeIDs:    nodeIdsConsistencySize4ToSize7,
  1485  			nodes:      []storage.Node{{NodeID: stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64), NodeRevision: 3, Hash: []byte("nodehash")}, {NodeID: stestonly.MustCreateNodeIDForTreeCoords(3, 10, 64), NodeRevision: 37, Hash: []byte("nodehash2")}},
  1486  			noCommit:   true,
  1487  		},
  1488  		{
  1489  			// Ask for a proof from size 4 to 8 but the tree is only size 7. This should succeed but with no proof.
  1490  			req:        getConsistencyProofRequest48,
  1491  			wantHashes: nil,
  1492  			nodeIDs:    nil,
  1493  			noRev:      true,
  1494  			noCommit:   true,
  1495  		},
  1496  		{
  1497  			// A normal request which should succeed.
  1498  			req:        getConsistencyProofRequest7,
  1499  			wantHashes: [][]byte{[]byte("nodehash")},
  1500  			nodeIDs:    nodeIdsConsistencySize4ToSize7,
  1501  			nodes:      []storage.Node{{NodeID: stestonly.MustCreateNodeIDForTreeCoords(2, 1, 64), NodeRevision: 3, Hash: []byte("nodehash")}},
  1502  		},
  1503  		{
  1504  			// Tests first==second edge case, which should succeed but is an empty proof.
  1505  			req:        getConsistencyProofRequest44,
  1506  			wantHashes: [][]byte{},
  1507  			nodeIDs:    []storage.NodeID{},
  1508  			nodes:      []storage.Node{},
  1509  		},
  1510  	}
  1511  
  1512  	ctrl := gomock.NewController(t)
  1513  	defer ctrl.Finish()
  1514  
  1515  	for _, test := range tests {
  1516  		fakeStorage := storage.NewMockLogStorage(ctrl)
  1517  		mockTX := storage.NewMockLogTreeTX(ctrl)
  1518  		if !test.noSnap {
  1519  			fakeStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(mockTX, test.snapErr)
  1520  		}
  1521  		if !test.noRoot {
  1522  			mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, test.rootErr)
  1523  		}
  1524  		if !test.noRev {
  1525  			mockTX.EXPECT().ReadRevision().Return(int64(root1.Revision))
  1526  		}
  1527  		if test.nodeIDs != nil {
  1528  			mockTX.EXPECT().GetMerkleNodes(gomock.Any(), revision1, test.nodeIDs).Return(test.nodes, test.getNodesErr)
  1529  		}
  1530  		if !test.noCommit {
  1531  			mockTX.EXPECT().Commit().Return(test.commitErr)
  1532  		}
  1533  		if !test.noClose {
  1534  			mockTX.EXPECT().Close().Return(nil)
  1535  		}
  1536  
  1537  		registry := extension.Registry{
  1538  			AdminStorage: fakeAdminStorage(ctrl, storageParams{treeID: test.req.LogId, numSnapshots: 1}),
  1539  			LogStorage:   fakeStorage,
  1540  		}
  1541  		server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1542  		response, err := server.GetConsistencyProof(context.Background(), &test.req)
  1543  
  1544  		if len(test.errStr) > 0 {
  1545  			if err == nil || !strings.Contains(err.Error(), test.errStr) {
  1546  				t.Errorf("GetConsistencyProof(%+v)=_, %v; want _, err containing %q", test.req, err, test.errStr)
  1547  			}
  1548  		} else {
  1549  			if err != nil {
  1550  				t.Errorf("GetConsistencyProof(%+v)=_,%v; want: _,nil", test.req, err)
  1551  				continue
  1552  			}
  1553  			if test.wantHashes == nil {
  1554  				if response.Proof != nil {
  1555  					t.Errorf("GetConsistencyProof(%+v) want nil proof, got %v", test.req, response.Proof)
  1556  				}
  1557  				continue
  1558  			}
  1559  			// Ensure we got the expected proof.
  1560  			wantProof := trillian.Proof{
  1561  				LeafIndex: 0,
  1562  				Hashes:    test.wantHashes,
  1563  			}
  1564  			if got, want := response.Proof, &wantProof; !proto.Equal(got, want) {
  1565  				t.Errorf("GetConsistencyProof(%+v)=%v,nil, want: %v,nil", test.req, got, want)
  1566  			}
  1567  		}
  1568  	}
  1569  }
  1570  
  1571  func TestTrillianLogRPCServer_GetConsistencyProofErrors(t *testing.T) {
  1572  	tests := []struct {
  1573  		desc string
  1574  		req  *trillian.GetConsistencyProofRequest
  1575  	}{
  1576  		{
  1577  			desc: "badFirstSize",
  1578  			req: &trillian.GetConsistencyProofRequest{
  1579  				LogId:          1,
  1580  				FirstTreeSize:  -10,
  1581  				SecondTreeSize: 20,
  1582  			},
  1583  		},
  1584  		{
  1585  			desc: "badSecondSize",
  1586  			req: &trillian.GetConsistencyProofRequest{
  1587  				LogId:          1,
  1588  				FirstTreeSize:  10,
  1589  				SecondTreeSize: -20,
  1590  			},
  1591  		},
  1592  		{
  1593  			desc: "firstGreaterThanSecond",
  1594  			req: &trillian.GetConsistencyProofRequest{
  1595  				LogId:          1,
  1596  				FirstTreeSize:  10,
  1597  				SecondTreeSize: 9,
  1598  			},
  1599  		},
  1600  	}
  1601  
  1602  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1603  	ctx := context.Background()
  1604  	for _, test := range tests {
  1605  		_, err := logServer.GetConsistencyProof(ctx, test.req)
  1606  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1607  			t.Errorf("%v: GetConsistencyProof() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1608  		}
  1609  	}
  1610  }
  1611  
  1612  func TestTrillianLogRPCServer_GetEntryAndProofErrors(t *testing.T) {
  1613  	tests := []struct {
  1614  		desc string
  1615  		req  *trillian.GetEntryAndProofRequest
  1616  	}{
  1617  		{
  1618  			desc: "badLeafIndex",
  1619  			req: &trillian.GetEntryAndProofRequest{
  1620  				LogId:     1,
  1621  				LeafIndex: -10,
  1622  				TreeSize:  20,
  1623  			},
  1624  		},
  1625  		{
  1626  			desc: "badTreeSize",
  1627  			req: &trillian.GetEntryAndProofRequest{
  1628  				LogId:     1,
  1629  				LeafIndex: 10,
  1630  				TreeSize:  -20,
  1631  			},
  1632  		},
  1633  		{
  1634  			desc: "indexGreaterThanSize",
  1635  			req: &trillian.GetEntryAndProofRequest{
  1636  				LogId:     1,
  1637  				LeafIndex: 10,
  1638  				TreeSize:  9,
  1639  			},
  1640  		},
  1641  	}
  1642  
  1643  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1644  	ctx := context.Background()
  1645  	for _, test := range tests {
  1646  		_, err := logServer.GetEntryAndProof(ctx, test.req)
  1647  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1648  			t.Errorf("%v: GetEntryAndProof() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1649  		}
  1650  	}
  1651  }
  1652  
  1653  func TestTrillianLogRPCServer_GetInclusionProofErrors(t *testing.T) {
  1654  	tests := []struct {
  1655  		desc string
  1656  		req  *trillian.GetInclusionProofRequest
  1657  	}{
  1658  		{
  1659  			desc: "badLeafIndex",
  1660  			req: &trillian.GetInclusionProofRequest{
  1661  				LogId:     1,
  1662  				LeafIndex: -10,
  1663  				TreeSize:  20,
  1664  			},
  1665  		},
  1666  		{
  1667  			desc: "badTreeSize",
  1668  			req: &trillian.GetInclusionProofRequest{
  1669  				LogId:     1,
  1670  				LeafIndex: 10,
  1671  				TreeSize:  -20,
  1672  			},
  1673  		},
  1674  		{
  1675  			desc: "indexGreaterThanSize",
  1676  			req: &trillian.GetInclusionProofRequest{
  1677  				LogId:     1,
  1678  				LeafIndex: 10,
  1679  				TreeSize:  9,
  1680  			},
  1681  		},
  1682  	}
  1683  
  1684  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1685  	ctx := context.Background()
  1686  	for _, test := range tests {
  1687  		_, err := logServer.GetInclusionProof(ctx, test.req)
  1688  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1689  			t.Errorf("%v: GetInclusionProof() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1690  		}
  1691  	}
  1692  }
  1693  
  1694  func TestTrillianLogRPCServer_GetInclusionProofByHashErrors(t *testing.T) {
  1695  	tests := []struct {
  1696  		desc string
  1697  		req  *trillian.GetInclusionProofByHashRequest
  1698  	}{
  1699  		{
  1700  			desc: "nilLeafHash",
  1701  			req: &trillian.GetInclusionProofByHashRequest{
  1702  				LogId:    1,
  1703  				TreeSize: 20,
  1704  			},
  1705  		},
  1706  		{
  1707  			desc: "badTreeSize",
  1708  			req: &trillian.GetInclusionProofByHashRequest{
  1709  				LogId:    1,
  1710  				LeafHash: []byte("32.bytes.hash..................."),
  1711  				TreeSize: -20,
  1712  			},
  1713  		},
  1714  	}
  1715  
  1716  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1717  	ctx := context.Background()
  1718  	for _, test := range tests {
  1719  		_, err := logServer.GetInclusionProofByHash(ctx, test.req)
  1720  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1721  			t.Errorf("%v: GetInclusionProofByHash() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1722  		}
  1723  	}
  1724  }
  1725  
  1726  func TestTrillianLogRPCServer_GetLeavesByHashErrors(t *testing.T) {
  1727  	tests := []struct {
  1728  		desc string
  1729  		req  *trillian.GetLeavesByHashRequest
  1730  	}{
  1731  		{
  1732  			desc: "nilLeafHashes",
  1733  			req: &trillian.GetLeavesByHashRequest{
  1734  				LogId: 1,
  1735  			},
  1736  		},
  1737  		{
  1738  			desc: "nilLeafHash",
  1739  			req: &trillian.GetLeavesByHashRequest{
  1740  				LogId: 1,
  1741  				LeafHash: [][]byte{
  1742  					[]byte("32.bytes.hash.a................."),
  1743  					nil,
  1744  					[]byte("32.bytes.hash.b................."),
  1745  				},
  1746  			},
  1747  		},
  1748  	}
  1749  
  1750  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1751  	ctx := context.Background()
  1752  	for _, test := range tests {
  1753  		_, err := logServer.GetLeavesByHash(ctx, test.req)
  1754  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1755  			t.Errorf("%v: GetLeavesByHash() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1756  		}
  1757  	}
  1758  }
  1759  
  1760  func TestTrillianLogRPCServer_GetLeavesByIndexErrors(t *testing.T) {
  1761  	tests := []struct {
  1762  		desc string
  1763  		req  *trillian.GetLeavesByIndexRequest
  1764  	}{
  1765  		{
  1766  			desc: "nilLeafIndex",
  1767  			req: &trillian.GetLeavesByIndexRequest{
  1768  				LogId: 1,
  1769  			},
  1770  		},
  1771  		{
  1772  			desc: "badLeadIndex",
  1773  			req: &trillian.GetLeavesByIndexRequest{
  1774  				LogId:     1,
  1775  				LeafIndex: []int64{10, -11, 12},
  1776  			},
  1777  		},
  1778  	}
  1779  
  1780  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1781  	ctx := context.Background()
  1782  	for _, test := range tests {
  1783  		_, err := logServer.GetLeavesByIndex(ctx, test.req)
  1784  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1785  			t.Errorf("%v: GetLeavesByIndex() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1786  		}
  1787  	}
  1788  }
  1789  
  1790  func TestTrillianLogRPCServer_QueueLeafErrors(t *testing.T) {
  1791  	leafValue := []byte("leaf value")
  1792  
  1793  	tests := []struct {
  1794  		desc string
  1795  		req  *trillian.QueueLeafRequest
  1796  	}{
  1797  		{
  1798  			desc: "nilLeaf",
  1799  			req: &trillian.QueueLeafRequest{
  1800  				LogId: 1,
  1801  			},
  1802  		},
  1803  		{
  1804  			desc: "nilLeafValue",
  1805  			req: &trillian.QueueLeafRequest{
  1806  				LogId: 1,
  1807  				Leaf:  &trillian.LogLeaf{},
  1808  			},
  1809  		},
  1810  		{
  1811  			desc: "badLeafIndex",
  1812  			req: &trillian.QueueLeafRequest{
  1813  				LogId: 1,
  1814  				Leaf: &trillian.LogLeaf{
  1815  					LeafValue: leafValue,
  1816  					LeafIndex: -10,
  1817  				},
  1818  			},
  1819  		},
  1820  	}
  1821  
  1822  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1823  	ctx := context.Background()
  1824  	for _, test := range tests {
  1825  		_, err := logServer.QueueLeaf(ctx, test.req)
  1826  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1827  			t.Errorf("%v: QueueLeaf() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1828  		}
  1829  	}
  1830  }
  1831  
  1832  func TestTrillianLogRPCServer_QueueLeavesErrors(t *testing.T) {
  1833  	leafValue := []byte("leaf value")
  1834  	goodLeaf := &trillian.LogLeaf{
  1835  		LeafValue: leafValue,
  1836  	}
  1837  
  1838  	tests := []struct {
  1839  		desc string
  1840  		req  *trillian.QueueLeavesRequest
  1841  	}{
  1842  		{
  1843  			desc: "nilLeaves",
  1844  			req: &trillian.QueueLeavesRequest{
  1845  				LogId: 1,
  1846  			},
  1847  		},
  1848  		{
  1849  			desc: "nilLeaf",
  1850  			req: &trillian.QueueLeavesRequest{
  1851  				LogId:  1,
  1852  				Leaves: []*trillian.LogLeaf{goodLeaf, nil},
  1853  			},
  1854  		},
  1855  		{
  1856  			desc: "nilLeafValue",
  1857  			req: &trillian.QueueLeavesRequest{
  1858  				LogId: 1,
  1859  				Leaves: []*trillian.LogLeaf{
  1860  					goodLeaf,
  1861  					{},
  1862  				},
  1863  			},
  1864  		},
  1865  		{
  1866  			desc: "badLeafIndex",
  1867  			req: &trillian.QueueLeavesRequest{
  1868  				LogId: 1,
  1869  				Leaves: []*trillian.LogLeaf{
  1870  					goodLeaf,
  1871  					{
  1872  						LeafValue: leafValue,
  1873  						LeafIndex: -10,
  1874  					},
  1875  				},
  1876  			},
  1877  		},
  1878  	}
  1879  
  1880  	logServer := NewTrillianLogRPCServer(extension.Registry{}, fakeTimeSource)
  1881  	ctx := context.Background()
  1882  	for _, test := range tests {
  1883  		_, err := logServer.QueueLeaves(ctx, test.req)
  1884  		if s, ok := status.FromError(err); !ok || s.Code() != codes.InvalidArgument {
  1885  			t.Errorf("%v: QueueLeaves() returned err = %v, wantCode = %s", test.desc, err, codes.InvalidArgument)
  1886  		}
  1887  	}
  1888  }
  1889  
  1890  func TestInitLog(t *testing.T) {
  1891  	ctx := context.Background()
  1892  	// A non-empty log root
  1893  	signedRoot, err := fixedSigner.SignLogRoot(&types.LogRootV1{})
  1894  	if err != nil {
  1895  		t.Fatalf("SignedLogRoot(): %v", err)
  1896  	}
  1897  
  1898  	for _, tc := range []struct {
  1899  		desc       string
  1900  		preordered bool
  1901  		getRootErr error
  1902  		wantInit   bool
  1903  		slr        trillian.SignedLogRoot
  1904  		wantCode   codes.Code
  1905  	}{
  1906  		{desc: "init new log", getRootErr: storage.ErrTreeNeedsInit, wantInit: true, wantCode: codes.OK},
  1907  		{desc: "init new preordered log", preordered: true, getRootErr: storage.ErrTreeNeedsInit, wantInit: true, wantCode: codes.OK},
  1908  		{desc: "init new log, no err", getRootErr: nil, wantInit: true, wantCode: codes.OK},
  1909  		{desc: "init already initialised log", getRootErr: nil, wantInit: false, slr: *signedRoot, wantCode: codes.AlreadyExists},
  1910  	} {
  1911  		t.Run(tc.desc, func(t *testing.T) {
  1912  			ctrl := gomock.NewController(t)
  1913  			defer ctrl.Finish()
  1914  
  1915  			mockTX := storage.NewMockLogTreeTX(ctrl)
  1916  			fakeStorage := &stestonly.FakeLogStorage{TX: mockTX}
  1917  			if tc.getRootErr != nil {
  1918  				mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(trillian.SignedLogRoot{}, tc.getRootErr)
  1919  			} else {
  1920  
  1921  				mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(tc.slr, nil)
  1922  			}
  1923  			mockTX.EXPECT().IsOpen().AnyTimes().Return(false)
  1924  			mockTX.EXPECT().Close().Return(nil)
  1925  			if tc.wantInit {
  1926  				mockTX.EXPECT().Commit().Return(nil)
  1927  				mockTX.EXPECT().StoreSignedLogRoot(gomock.Any(), gomock.Any())
  1928  			}
  1929  
  1930  			registry := extension.Registry{
  1931  				AdminStorage: fakeAdminStorage(ctrl, storageParams{logID1, tc.preordered, 1}),
  1932  				LogStorage:   fakeStorage,
  1933  			}
  1934  			logServer := NewTrillianLogRPCServer(registry, fakeTimeSource)
  1935  
  1936  			c, err := logServer.InitLog(ctx, &trillian.InitLogRequest{LogId: logID1})
  1937  			if got, want := status.Code(err), tc.wantCode; got != want {
  1938  				t.Errorf("InitLog returned %v (%v), want %v", got, err, want)
  1939  			}
  1940  			if tc.wantInit {
  1941  				if err != nil {
  1942  					t.Fatalf("InitLog returned %v, want no error", err)
  1943  				}
  1944  				if c.Created == nil {
  1945  					t.Error("InitLog first attempt didn't return the created STH.")
  1946  				}
  1947  			} else {
  1948  				if err == nil {
  1949  					t.Errorf("InitLog returned nil, want error")
  1950  				}
  1951  			}
  1952  		})
  1953  	}
  1954  }
  1955  
  1956  type prepareFakeStorageFunc func(*stestonly.FakeLogStorage)
  1957  type prepareMockTXFunc func(*storage.MockLogTreeTX)
  1958  type makeRPCFunc func(*TrillianLogRPCServer) error
  1959  
  1960  type txMode int
  1961  
  1962  func nopTX(*storage.MockLogTreeTX)         {}
  1963  func nopStorage(*stestonly.FakeLogStorage) {}
  1964  
  1965  const (
  1966  	readOnly txMode = iota
  1967  	readWrite
  1968  	noTX
  1969  )
  1970  
  1971  type parameterizedTest struct {
  1972  	ctrl       *gomock.Controller
  1973  	operation  string
  1974  	mode       txMode
  1975  	preordered bool
  1976  
  1977  	prepareStorage prepareFakeStorageFunc
  1978  	prepareTX      prepareMockTXFunc
  1979  	makeRPC        makeRPCFunc
  1980  }
  1981  
  1982  func newParameterizedTest(ctrl *gomock.Controller, operation string, m txMode, prepareStorage prepareFakeStorageFunc, prepareTx prepareMockTXFunc, makeRPC makeRPCFunc) *parameterizedTest {
  1983  	return &parameterizedTest{ctrl, operation, m, false /* preordered */, prepareStorage, prepareTx, makeRPC}
  1984  }
  1985  
  1986  func (p *parameterizedTest) executeCommitFailsTest(t *testing.T, logID int64) {
  1987  	withRoot := false
  1988  	t.Helper()
  1989  
  1990  	mockTX := storage.NewMockLogTreeTX(p.ctrl)
  1991  	fakeStorage := &stestonly.FakeLogStorage{}
  1992  
  1993  	switch p.mode {
  1994  	case readOnly:
  1995  		fakeStorage.ReadOnlyTX = mockTX
  1996  	case readWrite:
  1997  		fakeStorage.TX = mockTX
  1998  	}
  1999  	if p.mode != noTX {
  2000  		p.prepareTX(mockTX)
  2001  		if withRoot {
  2002  			mockTX.EXPECT().LatestSignedLogRoot(gomock.Any()).Return(*signedRoot1, nil)
  2003  		}
  2004  		mockTX.EXPECT().Commit().Return(errors.New("bang"))
  2005  		mockTX.EXPECT().Close().Return(errors.New("bang"))
  2006  		mockTX.EXPECT().IsOpen().AnyTimes().Return(false)
  2007  	}
  2008  
  2009  	registry := extension.Registry{
  2010  		AdminStorage: fakeAdminStorage(p.ctrl, storageParams{logID, p.preordered, 1}),
  2011  		LogStorage:   fakeStorage,
  2012  	}
  2013  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  2014  
  2015  	err := p.makeRPC(server)
  2016  	if err == nil {
  2017  		t.Fatalf("returned OK when commit failed: %s", p.operation)
  2018  	}
  2019  }
  2020  
  2021  func (p *parameterizedTest) executeInvalidLogIDTest(t *testing.T, snapshot bool) {
  2022  	badLogErr := errors.New("BADLOGID")
  2023  
  2024  	adminStorage := storage.NewMockAdminStorage(p.ctrl)
  2025  	adminTX := storage.NewMockReadOnlyAdminTX(p.ctrl)
  2026  	adminStorage.EXPECT().Snapshot(gomock.Any()).MaxTimes(1).Return(adminTX, nil)
  2027  	adminTX.EXPECT().GetTree(gomock.Any(), gomock.Any()).MaxTimes(1).Return(nil, badLogErr)
  2028  	adminTX.EXPECT().Close().MaxTimes(1).Return(nil)
  2029  
  2030  	fakeStorage := storage.NewMockLogStorage(p.ctrl)
  2031  	if ctx := gomock.Any(); snapshot {
  2032  		fakeStorage.EXPECT().SnapshotForTree(ctx, tree1).MaxTimes(1).Return(nil, badLogErr)
  2033  	}
  2034  
  2035  	registry := extension.Registry{
  2036  		AdminStorage: adminStorage,
  2037  		LogStorage:   fakeStorage,
  2038  	}
  2039  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  2040  
  2041  	// Make a request for a nonexistent log id
  2042  	if err := p.makeRPC(server); err == nil || !strings.Contains(err.Error(), badLogErr.Error()) {
  2043  		t.Fatalf("Returned wrong error response for nonexistent log: %s: %v", p.operation, err)
  2044  	}
  2045  }
  2046  
  2047  func (p *parameterizedTest) executeStorageFailureTest(t *testing.T, logID int64) {
  2048  	fakeStorage := &stestonly.FakeLogStorage{}
  2049  	mockTX := storage.NewMockLogTreeTX(p.ctrl)
  2050  	mockTX.EXPECT().Close().AnyTimes()
  2051  
  2052  	p.prepareStorage(fakeStorage)
  2053  	switch p.mode {
  2054  	case readOnly:
  2055  		fakeStorage.ReadOnlyTX = mockTX
  2056  	case readWrite:
  2057  		fakeStorage.TX = mockTX
  2058  	}
  2059  	if p.mode != noTX {
  2060  		p.prepareTX(mockTX)
  2061  	}
  2062  
  2063  	registry := extension.Registry{
  2064  		AdminStorage: fakeAdminStorage(p.ctrl, storageParams{logID, p.preordered, 1}),
  2065  		LogStorage:   fakeStorage,
  2066  	}
  2067  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  2068  
  2069  	if err := p.makeRPC(server); err == nil || !strings.Contains(err.Error(), "STORAGE") {
  2070  		t.Fatalf("Returned wrong error response when storage failed: %s: %v", p.operation, err)
  2071  	}
  2072  }
  2073  
  2074  func (p *parameterizedTest) executeBeginFailsTest(t *testing.T, logID int64) {
  2075  	logStorage := storage.NewMockLogStorage(p.ctrl)
  2076  	logTX := storage.NewMockLogTreeTX(p.ctrl)
  2077  
  2078  	switch p.mode {
  2079  	case readOnly:
  2080  		logStorage.EXPECT().SnapshotForTree(gomock.Any(), tree1).Return(logTX, errors.New("TX"))
  2081  	case readWrite:
  2082  		logStorage.EXPECT().ReadWriteTransaction(gomock.Any(), logID, gomock.Any()).Return(errors.New("TX"))
  2083  	}
  2084  
  2085  	registry := extension.Registry{
  2086  		AdminStorage: fakeAdminStorage(p.ctrl, storageParams{logID, p.preordered, 1}),
  2087  		LogStorage:   logStorage,
  2088  	}
  2089  	server := NewTrillianLogRPCServer(registry, fakeTimeSource)
  2090  
  2091  	if err := p.makeRPC(server); err == nil || !strings.Contains(err.Error(), "TX") {
  2092  		t.Fatalf("Returned wrong error response when begin failed: %v", err)
  2093  	}
  2094  }
  2095  
  2096  type storageParams struct {
  2097  	treeID       int64
  2098  	preordered   bool
  2099  	numSnapshots int
  2100  }
  2101  
  2102  func fakeAdminStorage(ctrl *gomock.Controller, params storageParams) storage.AdminStorage {
  2103  	tree := *stestonly.LogTree
  2104  	if params.preordered {
  2105  		tree = *stestonly.PreorderedLogTree
  2106  	}
  2107  	tree.TreeId = params.treeID
  2108  
  2109  	adminStorage := storage.NewMockAdminStorage(ctrl)
  2110  	adminTX := storage.NewMockReadOnlyAdminTX(ctrl)
  2111  
  2112  	adminStorage.EXPECT().Snapshot(gomock.Any()).MaxTimes(params.numSnapshots).Return(adminTX, nil)
  2113  	adminTX.EXPECT().GetTree(gomock.Any(), params.treeID).MaxTimes(params.numSnapshots).Return(&tree, nil)
  2114  	adminTX.EXPECT().Close().MaxTimes(params.numSnapshots).Return(nil)
  2115  	adminTX.EXPECT().Commit().MaxTimes(params.numSnapshots).Return(nil)
  2116  
  2117  	return adminStorage
  2118  }
  2119  
  2120  func addTreeID(tree *trillian.Tree, treeID int64) *trillian.Tree {
  2121  	newTree := proto.Clone(tree).(*trillian.Tree)
  2122  	newTree.TreeId = treeID
  2123  	return newTree
  2124  }