github.com/yimialmonte/fabric@v2.1.1+incompatible/gossip/privdata/reconcile_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package privdata 8 9 import ( 10 "errors" 11 "sync" 12 "testing" 13 "time" 14 15 gossip2 "github.com/hyperledger/fabric-protos-go/gossip" 16 "github.com/hyperledger/fabric-protos-go/peer" 17 "github.com/hyperledger/fabric/common/metrics/disabled" 18 util2 "github.com/hyperledger/fabric/common/util" 19 "github.com/hyperledger/fabric/core/ledger" 20 "github.com/hyperledger/fabric/gossip/metrics" 21 gmetricsmocks "github.com/hyperledger/fabric/gossip/metrics/mocks" 22 privdatacommon "github.com/hyperledger/fabric/gossip/privdata/common" 23 "github.com/hyperledger/fabric/gossip/privdata/mocks" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/mock" 26 ) 27 28 func TestNoItemsToReconcile(t *testing.T) { 29 // Scenario: there is no missing private data to reconcile. 30 // reconciler should identify that we don't have missing data and it doesn't need to call reconciliationFetcher to 31 // fetch missing items. 32 // reconciler shouldn't get an error. 33 committer := &mocks.Committer{} 34 fetcher := &mocks.ReconciliationFetcher{} 35 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 36 var missingInfo ledger.MissingPvtDataInfo 37 missingInfo = make(map[uint64]ledger.MissingBlockPvtdataInfo) 38 39 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(missingInfo, nil) 40 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 41 fetcher.On("FetchReconciledItems", mock.Anything).Return(nil, errors.New("this function shouldn't be called")) 42 43 r := &Reconciler{ 44 channel: "", 45 metrics: metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics, 46 ReconcileSleepInterval: time.Minute, 47 ReconcileBatchSize: 1, 48 ReconciliationFetcher: fetcher, Committer: committer, 49 } 50 err := r.reconcile() 51 52 assert.NoError(t, err) 53 } 54 55 func TestNotReconcilingWhenCollectionConfigNotAvailable(t *testing.T) { 56 // Scenario: reconciler gets an error when trying to read collection config for the missing private data. 57 // as a result it removes the digest slice, and there are no digests to pull. 58 // shouldn't get an error. 59 committer := &mocks.Committer{} 60 fetcher := &mocks.ReconciliationFetcher{} 61 configHistoryRetriever := &mocks.ConfigHistoryRetriever{} 62 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 63 var missingInfo ledger.MissingPvtDataInfo 64 65 missingInfo = map[uint64]ledger.MissingBlockPvtdataInfo{ 66 1: map[uint64][]*ledger.MissingCollectionPvtDataInfo{ 67 1: {{Collection: "col1", Namespace: "chain1"}}, 68 }, 69 } 70 71 var collectionConfigInfo ledger.CollectionConfigInfo 72 73 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(missingInfo, nil) 74 configHistoryRetriever.On("MostRecentCollectionConfigBelow", mock.Anything, mock.Anything).Return(&collectionConfigInfo, errors.New("fail to get collection config")) 75 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 76 committer.On("GetConfigHistoryRetriever").Return(configHistoryRetriever, nil) 77 78 var fetchCalled bool 79 fetcher.On("FetchReconciledItems", mock.Anything).Run(func(args mock.Arguments) { 80 var dig2CollectionConfig = args.Get(0).(privdatacommon.Dig2CollectionConfig) 81 assert.Equal(t, 0, len(dig2CollectionConfig)) 82 fetchCalled = true 83 }).Return(nil, errors.New("called with no digests")) 84 85 r := &Reconciler{ 86 channel: "", 87 metrics: metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics, 88 ReconcileSleepInterval: time.Minute, 89 ReconcileBatchSize: 1, 90 ReconciliationFetcher: fetcher, Committer: committer, 91 } 92 err := r.reconcile() 93 94 assert.Error(t, err) 95 assert.Equal(t, "called with no digests", err.Error()) 96 assert.True(t, fetchCalled) 97 } 98 99 func TestReconciliationHappyPathWithoutScheduler(t *testing.T) { 100 // Scenario: happy path when trying to reconcile missing private data. 101 committer := &mocks.Committer{} 102 fetcher := &mocks.ReconciliationFetcher{} 103 configHistoryRetriever := &mocks.ConfigHistoryRetriever{} 104 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 105 var missingInfo ledger.MissingPvtDataInfo 106 107 missingInfo = map[uint64]ledger.MissingBlockPvtdataInfo{ 108 3: map[uint64][]*ledger.MissingCollectionPvtDataInfo{ 109 1: {{Collection: "col1", Namespace: "ns1"}}, 110 }, 111 } 112 113 collectionConfigInfo := ledger.CollectionConfigInfo{ 114 CollectionConfig: &peer.CollectionConfigPackage{ 115 Config: []*peer.CollectionConfig{ 116 {Payload: &peer.CollectionConfig_StaticCollectionConfig{ 117 StaticCollectionConfig: &peer.StaticCollectionConfig{ 118 Name: "col1", 119 }, 120 }}, 121 }, 122 }, 123 CommittingBlockNum: 1, 124 } 125 126 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(missingInfo, nil).Run(func(_ mock.Arguments) { 127 missingPvtDataTracker.Mock = mock.Mock{} 128 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(nil, nil) 129 }) 130 configHistoryRetriever.On("MostRecentCollectionConfigBelow", mock.Anything, mock.Anything).Return(&collectionConfigInfo, nil) 131 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 132 committer.On("GetConfigHistoryRetriever").Return(configHistoryRetriever, nil) 133 134 result := &privdatacommon.FetchedPvtDataContainer{} 135 fetcher.On("FetchReconciledItems", mock.Anything).Run(func(args mock.Arguments) { 136 var dig2CollectionConfig = args.Get(0).(privdatacommon.Dig2CollectionConfig) 137 assert.Equal(t, 1, len(dig2CollectionConfig)) 138 for digest := range dig2CollectionConfig { 139 hash := util2.ComputeSHA256([]byte("rws-pre-image")) 140 element := &gossip2.PvtDataElement{ 141 Digest: &gossip2.PvtDataDigest{ 142 TxId: digest.TxId, 143 BlockSeq: digest.BlockSeq, 144 Collection: digest.Collection, 145 Namespace: digest.Namespace, 146 SeqInBlock: digest.SeqInBlock, 147 }, 148 Payload: [][]byte{hash}, 149 } 150 result.AvailableElements = append(result.AvailableElements, element) 151 } 152 }).Return(result, nil) 153 154 var commitPvtDataOfOldBlocksHappened bool 155 var blockNum, seqInBlock uint64 156 blockNum = 3 157 seqInBlock = 1 158 committer.On("CommitPvtDataOfOldBlocks", mock.Anything).Run(func(args mock.Arguments) { 159 var reconciledPvtdata = args.Get(0).([]*ledger.ReconciledPvtdata) 160 assert.Equal(t, 1, len(reconciledPvtdata)) 161 assert.Equal(t, blockNum, reconciledPvtdata[0].BlockNum) 162 assert.Equal(t, seqInBlock, reconciledPvtdata[0].WriteSets[1].SeqInBlock) 163 assert.Equal(t, "ns1", reconciledPvtdata[0].WriteSets[1].WriteSet.NsPvtRwset[0].Namespace) 164 assert.Equal(t, "col1", reconciledPvtdata[0].WriteSets[1].WriteSet.NsPvtRwset[0].CollectionPvtRwset[0].CollectionName) 165 commitPvtDataOfOldBlocksHappened = true 166 }).Return([]*ledger.PvtdataHashMismatch{}, nil) 167 168 testMetricProvider := gmetricsmocks.TestUtilConstructMetricProvider() 169 metrics := metrics.NewGossipMetrics(testMetricProvider.FakeProvider).PrivdataMetrics 170 171 r := &Reconciler{ 172 channel: "mychannel", 173 metrics: metrics, 174 ReconcileSleepInterval: time.Minute, 175 ReconcileBatchSize: 1, 176 ReconciliationFetcher: fetcher, Committer: committer, 177 } 178 err := r.reconcile() 179 180 assert.NoError(t, err) 181 assert.True(t, commitPvtDataOfOldBlocksHappened) 182 183 assert.Equal(t, 184 []string{"channel", "mychannel"}, 185 testMetricProvider.FakeReconciliationDuration.WithArgsForCall(0), 186 ) 187 } 188 189 func TestReconciliationHappyPathWithScheduler(t *testing.T) { 190 // Scenario: happy path when trying to reconcile missing private data. 191 committer := &mocks.Committer{} 192 fetcher := &mocks.ReconciliationFetcher{} 193 configHistoryRetriever := &mocks.ConfigHistoryRetriever{} 194 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 195 var missingInfo ledger.MissingPvtDataInfo 196 197 missingInfo = map[uint64]ledger.MissingBlockPvtdataInfo{ 198 3: map[uint64][]*ledger.MissingCollectionPvtDataInfo{ 199 1: {{Collection: "col1", Namespace: "ns1"}}, 200 }, 201 } 202 203 collectionConfigInfo := ledger.CollectionConfigInfo{ 204 CollectionConfig: &peer.CollectionConfigPackage{ 205 Config: []*peer.CollectionConfig{ 206 {Payload: &peer.CollectionConfig_StaticCollectionConfig{ 207 StaticCollectionConfig: &peer.StaticCollectionConfig{ 208 Name: "col1", 209 }, 210 }}, 211 }, 212 }, 213 CommittingBlockNum: 1, 214 } 215 216 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(missingInfo, nil).Run(func(_ mock.Arguments) { 217 missingPvtDataTracker.Mock = mock.Mock{} 218 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(nil, nil) 219 }) 220 configHistoryRetriever.On("MostRecentCollectionConfigBelow", mock.Anything, mock.Anything).Return(&collectionConfigInfo, nil) 221 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 222 committer.On("GetConfigHistoryRetriever").Return(configHistoryRetriever, nil) 223 224 result := &privdatacommon.FetchedPvtDataContainer{} 225 fetcher.On("FetchReconciledItems", mock.Anything).Run(func(args mock.Arguments) { 226 var dig2CollectionConfig = args.Get(0).(privdatacommon.Dig2CollectionConfig) 227 assert.Equal(t, 1, len(dig2CollectionConfig)) 228 for digest := range dig2CollectionConfig { 229 hash := util2.ComputeSHA256([]byte("rws-pre-image")) 230 element := &gossip2.PvtDataElement{ 231 Digest: &gossip2.PvtDataDigest{ 232 TxId: digest.TxId, 233 BlockSeq: digest.BlockSeq, 234 Collection: digest.Collection, 235 Namespace: digest.Namespace, 236 SeqInBlock: digest.SeqInBlock, 237 }, 238 Payload: [][]byte{hash}, 239 } 240 result.AvailableElements = append(result.AvailableElements, element) 241 } 242 }).Return(result, nil) 243 244 var wg sync.WaitGroup 245 wg.Add(1) 246 247 var commitPvtDataOfOldBlocksHappened bool 248 var blockNum, seqInBlock uint64 249 blockNum = 3 250 seqInBlock = 1 251 committer.On("CommitPvtDataOfOldBlocks", mock.Anything).Run(func(args mock.Arguments) { 252 var reconciledPvtdata = args.Get(0).([]*ledger.ReconciledPvtdata) 253 assert.Equal(t, 1, len(reconciledPvtdata)) 254 assert.Equal(t, blockNum, reconciledPvtdata[0].BlockNum) 255 assert.Equal(t, seqInBlock, reconciledPvtdata[0].WriteSets[1].SeqInBlock) 256 assert.Equal(t, "ns1", reconciledPvtdata[0].WriteSets[1].WriteSet.NsPvtRwset[0].Namespace) 257 assert.Equal(t, "col1", reconciledPvtdata[0].WriteSets[1].WriteSet.NsPvtRwset[0].CollectionPvtRwset[0].CollectionName) 258 commitPvtDataOfOldBlocksHappened = true 259 wg.Done() 260 }).Return([]*ledger.PvtdataHashMismatch{}, nil) 261 262 r := NewReconciler( 263 "", 264 metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics, 265 committer, 266 fetcher, 267 &PrivdataConfig{ 268 ReconcileSleepInterval: time.Millisecond * 100, 269 ReconcileBatchSize: 1, 270 ReconciliationEnabled: true, 271 }) 272 r.Start() 273 wg.Wait() 274 r.Stop() 275 276 assert.True(t, commitPvtDataOfOldBlocksHappened) 277 } 278 279 func TestReconciliationPullingMissingPrivateDataAtOnePass(t *testing.T) { 280 // Scenario: define batch size to retrieve missing private data to 1 281 // and make sure that even though there are missing data for two blocks 282 // they will be reconciled with one shot. 283 committer := &mocks.Committer{} 284 fetcher := &mocks.ReconciliationFetcher{} 285 configHistoryRetriever := &mocks.ConfigHistoryRetriever{} 286 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 287 288 missingInfo := ledger.MissingPvtDataInfo{ 289 4: ledger.MissingBlockPvtdataInfo{ 290 1: {{Collection: "col1", Namespace: "ns1"}}, 291 }, 292 } 293 294 collectionConfigInfo := &ledger.CollectionConfigInfo{ 295 CollectionConfig: &peer.CollectionConfigPackage{ 296 Config: []*peer.CollectionConfig{ 297 {Payload: &peer.CollectionConfig_StaticCollectionConfig{ 298 StaticCollectionConfig: &peer.StaticCollectionConfig{ 299 Name: "col1", 300 }, 301 }}, 302 {Payload: &peer.CollectionConfig_StaticCollectionConfig{ 303 StaticCollectionConfig: &peer.StaticCollectionConfig{ 304 Name: "col2", 305 }, 306 }}, 307 }, 308 }, 309 CommittingBlockNum: 1, 310 } 311 312 stopC := make(chan struct{}) 313 nextC := make(chan struct{}) 314 315 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything). 316 Return(missingInfo, nil).Run(func(_ mock.Arguments) { 317 missingInfo := ledger.MissingPvtDataInfo{ 318 3: ledger.MissingBlockPvtdataInfo{ 319 2: {{Collection: "col2", Namespace: "ns2"}}, 320 }, 321 } 322 missingPvtDataTracker.Mock = mock.Mock{} 323 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything). 324 Return(missingInfo, nil).Run(func(_ mock.Arguments) { 325 // here we are making sure that we will first stop 326 // reconciliation so next call to GetMissingPvtDataInfoForMostRecentBlocks 327 // will go into same round 328 <-nextC 329 missingPvtDataTracker.Mock = mock.Mock{} 330 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything). 331 Return(nil, nil) 332 }) 333 // make sure we calling stop reconciliation loop, so for sure 334 // in this test we won't get to second round though making sure 335 // we are retrieving on single pass 336 stopC <- struct{}{} 337 }) 338 339 configHistoryRetriever. 340 On("MostRecentCollectionConfigBelow", mock.Anything, mock.Anything). 341 Return(collectionConfigInfo, nil) 342 343 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 344 committer.On("GetConfigHistoryRetriever").Return(configHistoryRetriever, nil) 345 346 result := &privdatacommon.FetchedPvtDataContainer{} 347 fetcher.On("FetchReconciledItems", mock.Anything).Run(func(args mock.Arguments) { 348 result.AvailableElements = make([]*gossip2.PvtDataElement, 0) 349 var dig2CollectionConfig = args.Get(0).(privdatacommon.Dig2CollectionConfig) 350 assert.Equal(t, 1, len(dig2CollectionConfig)) 351 for digest := range dig2CollectionConfig { 352 hash := util2.ComputeSHA256([]byte("rws-pre-image")) 353 element := &gossip2.PvtDataElement{ 354 Digest: &gossip2.PvtDataDigest{ 355 TxId: digest.TxId, 356 BlockSeq: digest.BlockSeq, 357 Collection: digest.Collection, 358 Namespace: digest.Namespace, 359 SeqInBlock: digest.SeqInBlock, 360 }, 361 Payload: [][]byte{hash}, 362 } 363 result.AvailableElements = append(result.AvailableElements, element) 364 } 365 }).Return(result, nil) 366 367 var wg sync.WaitGroup 368 wg.Add(2) 369 370 var commitPvtDataOfOldBlocksHappened bool 371 pvtDataStore := make([][]*ledger.ReconciledPvtdata, 0) 372 committer.On("CommitPvtDataOfOldBlocks", mock.Anything).Run(func(args mock.Arguments) { 373 var reconciledPvtdata = args.Get(0).([]*ledger.ReconciledPvtdata) 374 assert.Equal(t, 1, len(reconciledPvtdata)) 375 pvtDataStore = append(pvtDataStore, reconciledPvtdata) 376 commitPvtDataOfOldBlocksHappened = true 377 wg.Done() 378 }).Return([]*ledger.PvtdataHashMismatch{}, nil) 379 380 r := NewReconciler( 381 "", 382 metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics, 383 committer, 384 fetcher, 385 &PrivdataConfig{ 386 ReconcileSleepInterval: time.Millisecond * 100, 387 ReconcileBatchSize: 1, 388 ReconciliationEnabled: true, 389 }) 390 r.Start() 391 <-stopC 392 r.Stop() 393 nextC <- struct{}{} 394 wg.Wait() 395 396 assert.Equal(t, 2, len(pvtDataStore)) 397 assert.Equal(t, uint64(4), pvtDataStore[0][0].BlockNum) 398 assert.Equal(t, uint64(3), pvtDataStore[1][0].BlockNum) 399 400 assert.Equal(t, uint64(1), pvtDataStore[0][0].WriteSets[1].SeqInBlock) 401 assert.Equal(t, uint64(2), pvtDataStore[1][0].WriteSets[2].SeqInBlock) 402 403 assert.Equal(t, "ns1", pvtDataStore[0][0].WriteSets[1].WriteSet.NsPvtRwset[0].Namespace) 404 assert.Equal(t, "ns2", pvtDataStore[1][0].WriteSets[2].WriteSet.NsPvtRwset[0].Namespace) 405 406 assert.Equal(t, "col1", pvtDataStore[0][0].WriteSets[1].WriteSet.NsPvtRwset[0].CollectionPvtRwset[0].CollectionName) 407 assert.Equal(t, "col2", pvtDataStore[1][0].WriteSets[2].WriteSet.NsPvtRwset[0].CollectionPvtRwset[0].CollectionName) 408 409 assert.True(t, commitPvtDataOfOldBlocksHappened) 410 } 411 412 func TestReconciliationFailedToCommit(t *testing.T) { 413 committer := &mocks.Committer{} 414 fetcher := &mocks.ReconciliationFetcher{} 415 configHistoryRetriever := &mocks.ConfigHistoryRetriever{} 416 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 417 var missingInfo ledger.MissingPvtDataInfo 418 419 missingInfo = map[uint64]ledger.MissingBlockPvtdataInfo{ 420 3: map[uint64][]*ledger.MissingCollectionPvtDataInfo{ 421 1: {{Collection: "col1", Namespace: "ns1"}}, 422 }, 423 } 424 425 collectionConfigInfo := ledger.CollectionConfigInfo{ 426 CollectionConfig: &peer.CollectionConfigPackage{ 427 Config: []*peer.CollectionConfig{ 428 {Payload: &peer.CollectionConfig_StaticCollectionConfig{ 429 StaticCollectionConfig: &peer.StaticCollectionConfig{ 430 Name: "col1", 431 }, 432 }}, 433 }, 434 }, 435 CommittingBlockNum: 1, 436 } 437 438 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(missingInfo, nil).Run(func(_ mock.Arguments) { 439 missingPvtDataTracker.Mock = mock.Mock{} 440 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(nil, nil) 441 }) 442 configHistoryRetriever.On("MostRecentCollectionConfigBelow", mock.Anything, mock.Anything).Return(&collectionConfigInfo, nil) 443 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 444 committer.On("GetConfigHistoryRetriever").Return(configHistoryRetriever, nil) 445 446 result := &privdatacommon.FetchedPvtDataContainer{} 447 fetcher.On("FetchReconciledItems", mock.Anything).Run(func(args mock.Arguments) { 448 var dig2CollectionConfig = args.Get(0).(privdatacommon.Dig2CollectionConfig) 449 assert.Equal(t, 1, len(dig2CollectionConfig)) 450 for digest := range dig2CollectionConfig { 451 hash := util2.ComputeSHA256([]byte("rws-pre-image")) 452 element := &gossip2.PvtDataElement{ 453 Digest: &gossip2.PvtDataDigest{ 454 TxId: digest.TxId, 455 BlockSeq: digest.BlockSeq, 456 Collection: digest.Collection, 457 Namespace: digest.Namespace, 458 SeqInBlock: digest.SeqInBlock, 459 }, 460 Payload: [][]byte{hash}, 461 } 462 result.AvailableElements = append(result.AvailableElements, element) 463 } 464 }).Return(result, nil) 465 466 committer.On("CommitPvtDataOfOldBlocks", mock.Anything).Return(nil, errors.New("failed to commit")) 467 468 r := &Reconciler{ 469 channel: "", 470 metrics: metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics, 471 ReconcileSleepInterval: time.Minute, 472 ReconcileBatchSize: 1, 473 ReconciliationFetcher: fetcher, Committer: committer, 474 } 475 err := r.reconcile() 476 477 assert.Error(t, err) 478 assert.Contains(t, err.Error(), "failed to commit") 479 } 480 481 func TestFailuresWhileReconcilingMissingPvtData(t *testing.T) { 482 metrics := metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics 483 committer := &mocks.Committer{} 484 fetcher := &mocks.ReconciliationFetcher{} 485 committer.On("GetMissingPvtDataTracker").Return(nil, errors.New("failed to obtain missing pvt data tracker")) 486 487 r := NewReconciler( 488 "", 489 metrics, 490 committer, 491 fetcher, 492 &PrivdataConfig{ 493 ReconcileSleepInterval: time.Millisecond * 100, 494 ReconcileBatchSize: 1, 495 ReconciliationEnabled: true, 496 }) 497 err := r.reconcile() 498 assert.Error(t, err) 499 assert.Contains(t, "failed to obtain missing pvt data tracker", err.Error()) 500 501 committer.Mock = mock.Mock{} 502 committer.On("GetMissingPvtDataTracker").Return(nil, nil) 503 r = NewReconciler("", metrics, committer, fetcher, 504 &PrivdataConfig{ReconcileSleepInterval: time.Millisecond * 100, ReconcileBatchSize: 1, ReconciliationEnabled: true}) 505 err = r.reconcile() 506 assert.Error(t, err) 507 assert.Contains(t, "got nil as MissingPvtDataTracker, exiting...", err.Error()) 508 509 missingPvtDataTracker := &mocks.MissingPvtDataTracker{} 510 missingPvtDataTracker.On("GetMissingPvtDataInfoForMostRecentBlocks", mock.Anything).Return(nil, errors.New("failed get missing pvt data for recent blocks")) 511 512 committer.Mock = mock.Mock{} 513 committer.On("GetMissingPvtDataTracker").Return(missingPvtDataTracker, nil) 514 r = NewReconciler("", metrics, committer, fetcher, 515 &PrivdataConfig{ReconcileSleepInterval: time.Millisecond * 100, ReconcileBatchSize: 1, ReconciliationEnabled: true}) 516 err = r.reconcile() 517 assert.Error(t, err) 518 assert.Contains(t, "failed get missing pvt data for recent blocks", err.Error()) 519 }