Skip to content

Commit c655e2e

Browse files
committed
test: Add test code for evidence query
1 parent adfc252 commit c655e2e

File tree

3 files changed

+277
-7
lines changed

3 files changed

+277
-7
lines changed

test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Libplanet.Types.Tx;
1717
using Libplanet.Store;
1818
using Libplanet.Store.Trie;
19+
using Libplanet.Tests.Blockchain.Evidence;
1920

2021
namespace Libplanet.Explorer.Tests;
2122

@@ -29,6 +30,8 @@ public class GeneratedBlockChainFixture
2930

3031
public int MaxTxCount { get; }
3132

33+
public int MaxEvidenceCount { get; }
34+
3235
public ImmutableDictionary<Address, ImmutableArray<Block>>
3336
MinedBlocks { get; private set; }
3437

@@ -43,7 +46,8 @@ public GeneratedBlockChainFixture(
4346
int maxTxCount = 20,
4447
int privateKeyCount = 10,
4548
ImmutableArray<ImmutableArray<ImmutableArray<SimpleAction>>>?
46-
txActionsForSuffixBlocks = null)
49+
txActionsForSuffixBlocks = null,
50+
int maxEvidenceCount = 2)
4751
{
4852
txActionsForSuffixBlocks ??=
4953
ImmutableArray<ImmutableArray<ImmutableArray<SimpleAction>>>.Empty;
@@ -65,6 +69,7 @@ public GeneratedBlockChainFixture(
6569
.ToImmutableDictionary(
6670
key => key.Address,
6771
key => ImmutableArray<Transaction>.Empty);
72+
MaxEvidenceCount = maxEvidenceCount;
6873

6974
var privateKey = new PrivateKey();
7075
var policy = new BlockPolicy(
@@ -105,22 +110,24 @@ public GeneratedBlockChainFixture(
105110

106111
while (Chain.Count < blockCount)
107112
{
108-
AddBlock(GetRandomTransactions());
113+
AddBlock(GetRandomTransactions(), GetRandomEvidence(height: Chain.Count - 1));
109114
}
110115

111116
if (txActionsForSuffixBlocks is { } txActionsForSuffixBlocksVal)
112117
{
113118
foreach (var actionsForTransactions in txActionsForSuffixBlocksVal)
114119
{
115120
var pk = PrivateKeys[Random.Next(PrivateKeys.Length)];
116-
AddBlock(actionsForTransactions
121+
var txs = actionsForTransactions
117122
.Select(actions =>
118123
Transaction.Create(
119124
nonce: Chain.GetNextTxNonce(pk.Address),
120125
privateKey: pk,
121126
genesisHash: Chain.Genesis.Hash,
122127
actions: actions.ToPlainValues()))
123-
.ToImmutableArray());
128+
.ToImmutableArray();
129+
var evs = ImmutableArray<EvidenceBase>.Empty;
130+
AddBlock(txs, evs);
124131
}
125132
}
126133
}
@@ -159,6 +166,21 @@ private Transaction GetRandomTransaction(PrivateKey pk, long nonce)
159166
gasLimit: null);
160167
}
161168

169+
private ImmutableArray<EvidenceBase> GetRandomEvidence(long height)
170+
{
171+
return Enumerable
172+
.Range(0, Random.Next(MaxEvidenceCount))
173+
.Select<int, EvidenceBase>(_ =>
174+
{
175+
return new TestEvidence(
176+
height: height,
177+
validatorAddress: new PrivateKey().Address,
178+
timestamp: DateTimeOffset.UtcNow);
179+
})
180+
.OrderBy(ev => ev.Id)
181+
.ToImmutableArray();
182+
}
183+
162184
private ImmutableArray<SimpleAction> GetRandomActions()
163185
{
164186
return Enumerable
@@ -167,7 +189,8 @@ private ImmutableArray<SimpleAction> GetRandomActions()
167189
.ToImmutableArray();
168190
}
169191

170-
private void AddBlock(ImmutableArray<Transaction> transactions)
192+
private void AddBlock(
193+
ImmutableArray<Transaction> transactions, ImmutableArray<EvidenceBase> evidence)
171194
{
172195
var proposer = PrivateKeys[Random.Next(PrivateKeys.Length)];
173196
var block = Chain.EvaluateAndSign(
@@ -179,9 +202,9 @@ private void AddBlock(ImmutableArray<Transaction> transactions)
179202
Chain.Tip.Hash,
180203
BlockContent.DeriveTxHash(transactions),
181204
Chain.Store.GetChainBlockCommit(Chain.Store.GetCanonicalChainId()!.Value),
182-
evidenceHash: null),
205+
evidenceHash: BlockContent.DeriveEvidenceHash(evidence)),
183206
transactions,
184-
evidence: Array.Empty<EvidenceBase>()).Propose(),
207+
evidence: evidence).Propose(),
185208
proposer);
186209
Chain.Append(
187210
block,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using GraphQL.Language.AST;
3+
using Libplanet.Common;
4+
using Libplanet.Explorer.GraphTypes;
5+
using Libplanet.Types.Evidence;
6+
using Xunit;
7+
8+
namespace Libplanet.Explorer.Tests.GraphTypes
9+
{
10+
public class EvidenceIdTypeTest : ScalarGraphTypeTestBase<EvidenceIdType>
11+
{
12+
[Fact]
13+
public void ParseLiteral()
14+
{
15+
Assert.Null(_type.ParseLiteral(new NullValue()));
16+
17+
var bytes = TestUtils.GetRandomBytes(EvidenceId.Size);
18+
var evidenceId = new EvidenceId(bytes);
19+
var hex = ByteUtil.Hex(bytes);
20+
Assert.Equal(
21+
evidenceId,
22+
Assert.IsType<EvidenceId>(_type.ParseLiteral(new StringValue(hex))));
23+
24+
Assert.Throws<InvalidOperationException>(
25+
() => _type.ParseLiteral(new LongValue(1234)));
26+
Assert.Throws<InvalidOperationException>(
27+
() => _type.ParseValue(new StringValue("evidenceId")));
28+
}
29+
30+
[Fact]
31+
public void ParseValue()
32+
{
33+
Assert.Null(_type.ParseValue(null));
34+
35+
var bytes = TestUtils.GetRandomBytes(EvidenceId.Size);
36+
var evidenceId = new EvidenceId(bytes);
37+
var hex = ByteUtil.Hex(bytes);
38+
Assert.Equal(evidenceId, _type.ParseValue(hex));
39+
40+
Assert.Throws<InvalidOperationException>(() => _type.ParseValue(0));
41+
Assert.Throws<InvalidOperationException>(() => _type.ParseValue(new EvidenceId()));
42+
Assert.Throws<InvalidOperationException>(() => _type.ParseValue(new object()));
43+
}
44+
45+
[Fact]
46+
public void Serialize()
47+
{
48+
var bytes = TestUtils.GetRandomBytes(EvidenceId.Size);
49+
var evidenceId = new EvidenceId(bytes);
50+
var hex = ByteUtil.Hex(bytes);
51+
Assert.Equal(hex, _type.Serialize(evidenceId));
52+
53+
Assert.Throws<InvalidOperationException>(() => _type.Serialize(0));
54+
Assert.Throws<InvalidOperationException>(() => _type.Serialize(""));
55+
Assert.Throws<InvalidOperationException>(() => _type.Serialize(new object()));
56+
}
57+
}
58+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using GraphQL.Execution;
5+
using Libplanet.Explorer.Queries;
6+
using Xunit;
7+
using static Libplanet.Explorer.Tests.GraphQLTestUtils;
8+
using Libplanet.Types.Blocks;
9+
using System;
10+
using Libplanet.Tests.Blockchain.Evidence;
11+
using Libplanet.Crypto;
12+
using Libplanet.Types.Evidence;
13+
14+
namespace Libplanet.Explorer.Tests.Queries;
15+
16+
public class EvidenceQueryTest
17+
{
18+
private readonly GeneratedBlockChainFixture _fixture;
19+
private readonly MockBlockChainContext _source;
20+
private readonly EvidenceQuery _queryGraph;
21+
22+
public EvidenceQueryTest()
23+
{
24+
_fixture = new GeneratedBlockChainFixture(seed: 0);
25+
_source = new MockBlockChainContext(_fixture.Chain);
26+
_queryGraph = new EvidenceQuery();
27+
var _ = new ExplorerQuery(_source);
28+
}
29+
30+
[Fact]
31+
public async Task ExecuteCommittedEvidenceByHeightAsync()
32+
{
33+
var blocks = GetBlocks().ToArray();
34+
var block = blocks[Random.Shared.Next(blocks.Length)];
35+
36+
var result = await ExecuteQueryAsync(@$"{{
37+
committedEvidence(
38+
index: {block.Index}) {{
39+
id
40+
type
41+
height
42+
targetAddress
43+
timestamp
44+
}}
45+
}}", _queryGraph, source: _source);
46+
Assert.Null(result.Errors);
47+
var resultData = Assert.IsAssignableFrom<ExecutionNode>(result.Data);
48+
var resultDict =
49+
Assert.IsAssignableFrom<IDictionary<string, object>>(resultData.ToValue());
50+
var resultEvidence = Assert.IsAssignableFrom<object[]>(resultDict["committedEvidence"]);
51+
52+
for (var i = 0; i < block.Evidence.Count; i++)
53+
{
54+
var evidence = block.Evidence[i];
55+
var resultEvidenceDict
56+
= Assert.IsAssignableFrom<IDictionary<string, object>>(resultEvidence[i]);
57+
Assert.Equal(evidence.Id.ToString(), resultEvidenceDict["id"]);
58+
Assert.Equal(evidence.GetType().FullName, resultEvidenceDict["type"]);
59+
Assert.Equal(evidence.Height, resultEvidenceDict["height"]);
60+
Assert.Equal(evidence.TargetAddress.ToString(), resultEvidenceDict["targetAddress"]);
61+
Assert.Equal(
62+
evidence.Timestamp, DateTimeOffset.Parse($"{resultEvidenceDict["timestamp"]}"));
63+
}
64+
}
65+
66+
[Fact]
67+
public async Task ExecuteCommittedEvidenceByHashAsync()
68+
{
69+
var blocks = GetBlocks().ToArray();
70+
var block = blocks[Random.Shared.Next(blocks.Length)];
71+
72+
var result = await ExecuteQueryAsync(@$"{{
73+
committedEvidence(
74+
hash: ""{block.Hash}"") {{
75+
id
76+
type
77+
height
78+
targetAddress
79+
timestamp
80+
}}
81+
}}", _queryGraph, source: _source);
82+
Assert.Null(result.Errors);
83+
var resultData = Assert.IsAssignableFrom<ExecutionNode>(result.Data);
84+
var resultDict =
85+
Assert.IsAssignableFrom<IDictionary<string, object>>(resultData.ToValue());
86+
var resultEvidence = Assert.IsAssignableFrom<object[]>(resultDict["committedEvidence"]);
87+
88+
for (var i = 0; i < block.Evidence.Count; i++)
89+
{
90+
var evidence = block.Evidence[i];
91+
var resultEvidenceDict
92+
= Assert.IsAssignableFrom<IDictionary<string, object>>(resultEvidence[i]);
93+
Assert.Equal(evidence.Id.ToString(), resultEvidenceDict["id"]);
94+
Assert.Equal(evidence.GetType().FullName, resultEvidenceDict["type"]);
95+
Assert.Equal(evidence.Height, resultEvidenceDict["height"]);
96+
Assert.Equal(evidence.TargetAddress.ToString(), resultEvidenceDict["targetAddress"]);
97+
Assert.Equal(
98+
evidence.Timestamp, DateTimeOffset.Parse($"{resultEvidenceDict["timestamp"]}"));
99+
}
100+
}
101+
102+
[Fact]
103+
public async Task ExecutePendingEvidenceAsync()
104+
{
105+
var evidenceList = new List<EvidenceBase>
106+
{
107+
new TestEvidence(
108+
height: _fixture.Chain.Count - 3,
109+
validatorAddress: new PrivateKey().Address,
110+
timestamp: DateTimeOffset.UtcNow)
111+
};
112+
113+
foreach (var evidence in evidenceList)
114+
{
115+
_fixture.Chain.AddEvidence(evidence);
116+
}
117+
118+
var result = await ExecuteQueryAsync(@$"{{
119+
pendingEvidence {{
120+
id
121+
type
122+
height
123+
targetAddress
124+
timestamp
125+
}}
126+
}}", _queryGraph, source: _source);
127+
Assert.Null(result.Errors);
128+
var resultData = Assert.IsAssignableFrom<ExecutionNode>(result.Data);
129+
var resultDict =
130+
Assert.IsAssignableFrom<IDictionary<string, object>>(resultData.ToValue());
131+
var resultEvidence = Assert.IsAssignableFrom<object[]>(resultDict["pendingEvidence"]);
132+
133+
for (var i = 0; i < evidenceList.Count; i++)
134+
{
135+
var evidence = evidenceList[i];
136+
var resultEvidenceDict
137+
= Assert.IsAssignableFrom<IDictionary<string, object>>(resultEvidence[i]);
138+
Assert.Equal(evidence.Id.ToString(), resultEvidenceDict["id"]);
139+
Assert.Equal(evidence.GetType().FullName, resultEvidenceDict["type"]);
140+
Assert.Equal(evidence.Height, resultEvidenceDict["height"]);
141+
Assert.Equal(evidence.TargetAddress.ToString(), resultEvidenceDict["targetAddress"]);
142+
Assert.Equal(
143+
evidence.Timestamp, DateTimeOffset.Parse($"{resultEvidenceDict["timestamp"]}"));
144+
}
145+
}
146+
147+
[Fact]
148+
public async Task ExecuteEvidenceByIdAsync()
149+
{
150+
var blocks = GetBlocks().ToArray();
151+
var block = blocks[Random.Shared.Next(blocks.Length)];
152+
var evidence = block.Evidence[Random.Shared.Next(block.Evidence.Count)];
153+
154+
var result = await ExecuteQueryAsync(@$"{{
155+
evidence(id: ""{evidence.Id}"") {{
156+
id
157+
type
158+
height
159+
targetAddress
160+
timestamp
161+
}}
162+
}}", _queryGraph, source: _source);
163+
Assert.Null(result.Errors);
164+
var resultData = Assert.IsAssignableFrom<ExecutionNode>(result.Data);
165+
var resultDict =
166+
Assert.IsAssignableFrom<IDictionary<string, object>>(resultData.ToValue());
167+
168+
var resultEvidenceDict
169+
= Assert.IsAssignableFrom<IDictionary<string, object>>(resultDict["evidence"]);
170+
Assert.Equal(evidence.Id.ToString(), resultEvidenceDict["id"]);
171+
Assert.Equal(evidence.GetType().FullName, resultEvidenceDict["type"]);
172+
Assert.Equal(evidence.Height, resultEvidenceDict["height"]);
173+
Assert.Equal(evidence.TargetAddress.ToString(), resultEvidenceDict["targetAddress"]);
174+
Assert.Equal(
175+
evidence.Timestamp, DateTimeOffset.Parse($"{resultEvidenceDict["timestamp"]}"));
176+
}
177+
178+
private IEnumerable<Block> GetBlocks()
179+
{
180+
for (var i = 0; i < _fixture.Chain.Count; i++)
181+
{
182+
var block = _fixture.Chain[i];
183+
if (block.Evidence.Count > 0)
184+
{
185+
yield return block;
186+
}
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)