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 ¶meterizedTest{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 }