public void TestMissingHeader() { var fakeHeaders = new FakeHeaders(); var header0 = fakeHeaders.GenesisChained(); var header1 = fakeHeaders.NextChained(); var header2 = fakeHeaders.NextChained(); var rules = Mock.Of <ICoreRules>(); var coreStorage = new Mock <ICoreStorage>(); var storageManager = new Mock <IStorageManager>(); var chainStateCursor = new Mock <IChainStateCursor>(); storageManager.Setup(x => x.OpenChainStateCursor()).Returns( new DisposeHandle <IChainStateCursor>(_ => { }, chainStateCursor.Object)); // don't mock header 1 so it is missing chainStateCursor.Setup(x => x.TryGetHeader(header0.Hash, out header0)).Returns(true); chainStateCursor.Setup(x => x.TryGetHeader(header2.Hash, out header2)).Returns(true); // return header 2 as the chain tip chainStateCursor.Setup(x => x.ChainTip).Returns(header2); // init chain state builder with missing header StorageCorruptException actualEx; AssertMethods.AssertThrows <StorageCorruptException>(() => { var chain = new ChainStateBuilder(rules, coreStorage.Object, storageManager.Object).Chain; }, out actualEx); Assert.AreEqual(StorageType.ChainState, actualEx.StorageType); Assert.AreEqual("ChainState is missing header.", actualEx.Message); }
public void TestCreateFromInvalidEnumerable() { // create a chain var fakeHeaders = new FakeHeaders(); var header0 = fakeHeaders.GenesisChained(); var header1 = fakeHeaders.NextChained(); // create builder from out of order enumerable AssertMethods.AssertThrows <InvalidOperationException>(() => new ChainBuilder(new[] { header1, header0 })); }
public void TestChainTipOutOfSync() { var fakeHeaders = new FakeHeaders(); var header0 = fakeHeaders.GenesisChained(); var header1 = fakeHeaders.NextChained(); var header2 = fakeHeaders.NextChained(); var rules = Mock.Of <ICoreRules>(); var coreStorage = new Mock <ICoreStorage>(); var storageManager = new Mock <IStorageManager>(); var chainStateCursor = new Mock <IDeferredChainStateCursor>(); storageManager.Setup(x => x.OpenChainStateCursor()).Returns( new DisposeHandle <IChainStateCursor>(_ => { }, chainStateCursor.Object)); storageManager.Setup(x => x.OpenDeferredChainStateCursor(It.IsAny <IChainState>())).Returns( new DisposeHandle <IDeferredChainStateCursor>(_ => { }, chainStateCursor.Object)); chainStateCursor.Setup(x => x.TryGetHeader(header0.Hash, out header0)).Returns(true); chainStateCursor.Setup(x => x.TryGetHeader(header1.Hash, out header1)).Returns(true); chainStateCursor.Setup(x => x.TryGetHeader(header2.Hash, out header2)).Returns(true); // return header 1 as the chain tip chainStateCursor.Setup(x => x.ChainTip).Returns(header1); // init chain state builder seeing header 1 var chainStateBuilder = new ChainStateBuilder(rules, coreStorage.Object, storageManager.Object); Assert.AreEqual(header1.Hash, chainStateBuilder.Chain.LastBlock.Hash); // alter the chain tip outside of the chain state builder chainStateCursor.Setup(x => x.ChainTip).Returns(header2); // attempt to add block when out of sync ChainStateOutOfSyncException actualEx; AssertMethods.AssertAggregateThrows <ChainStateOutOfSyncException>(() => chainStateBuilder.AddBlockAsync(header2, Enumerable.Empty <BlockTx>()).Wait(), out actualEx); Assert.AreEqual(header1.Hash, actualEx.ExpectedChainTip.Hash); Assert.AreEqual(header2.Hash, actualEx.ActualChainTip.Hash); // attempt to rollback block when out of sync AssertMethods.AssertThrows <ChainStateOutOfSyncException>(() => chainStateBuilder.RollbackBlock(header2, Enumerable.Empty <BlockTx>()), out actualEx); Assert.AreEqual(header1.Hash, actualEx.ExpectedChainTip.Hash); Assert.AreEqual(header2.Hash, actualEx.ActualChainTip.Hash); }
public void TestRemoveBlockInvalid() { var fakeHeaders = new FakeHeaders(); var header0 = fakeHeaders.GenesisChained(); var header1 = fakeHeaders.NextChained(); var header2 = fakeHeaders.NextChained(); var chainBuilder = new ChainBuilder(new[] { header0, header1, header2 }); // removing header 1 first should fail AssertMethods.AssertThrows <InvalidOperationException>(() => chainBuilder.RemoveBlock(header1)); // remove header 2 chainBuilder.RemoveBlock(header2); // removing header 0 with header 1 present should fail AssertMethods.AssertThrows <InvalidOperationException>(() => chainBuilder.AddBlock(header0)); }
public void TestAddBlockInvalid() { var fakeHeaders = new FakeHeaders(); var header0 = fakeHeaders.GenesisChained(); var header1 = fakeHeaders.NextChained(); var header2 = fakeHeaders.NextChained(); var chainBuilder = new ChainBuilder(); // adding header 1 first should fail AssertMethods.AssertThrows <InvalidOperationException>(() => chainBuilder.AddBlock(header1)); // add header 0 chainBuilder.AddBlock(header0); // adding header 2 without header 1 should fail AssertMethods.AssertThrows <InvalidOperationException>(() => chainBuilder.AddBlock(header2)); }
public void TestNavigateTowardsInvalidChains() { // create distinct chains var fakeHeadersA = new FakeHeaders(); var header0A = fakeHeadersA.GenesisChained(); var header1A = fakeHeadersA.NextChained(); var fakeHeadersB = new FakeHeaders(); var header0B = fakeHeadersB.GenesisChained(); var header1B = fakeHeadersB.NextChained(); var chainEmpty = new ChainBuilder().ToImmutable(); var chainA = new ChainBuilder(new[] { header0A, header1A }).ToImmutable(); var chainB = new ChainBuilder(new[] { header0B, header1B, }).ToImmutable(); // unrelated chains should error AssertMethods.AssertThrows <InvalidOperationException>(() => chainA.NavigateTowards(chainB).ToList()); AssertMethods.AssertThrows <InvalidOperationException>(() => chainB.NavigateTowards(chainA).ToList()); }