Skip to content

Commit 20b8c56

Browse files
committed
test: Add test for GasTracer cancelling
1 parent 6d4da2a commit 20b8c56

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using Bencodex.Types;
5+
using Libplanet.Action;
6+
using Libplanet.Action.Loader;
7+
using Libplanet.Action.State;
8+
using Libplanet.Blockchain;
9+
using Libplanet.Blockchain.Policies;
10+
using Libplanet.Crypto;
11+
using Libplanet.Store;
12+
using Libplanet.Store.Trie;
13+
using Libplanet.Types.Assets;
14+
using Libplanet.Types.Blocks;
15+
using Libplanet.Types.Tx;
16+
using Xunit;
17+
using static Libplanet.Action.State.KeyConverters;
18+
using static Libplanet.Tests.TestUtils;
19+
20+
namespace Libplanet.Tests.Action
21+
{
22+
public partial class ActionEvaluatorTest
23+
{
24+
[Theory]
25+
[InlineData(false, 1, 1)]
26+
[InlineData(true, 1, 0)]
27+
public void Evaluate_WithGasTracer(
28+
bool cancelTrace, long goldAmount, long expectedGoldAmount)
29+
{
30+
var gold = Currency.Uncapped("FOO", 18, null);
31+
var gas = Currency.Uncapped("GAS", 18, null);
32+
var privateKey = new PrivateKey();
33+
var policy = new BlockPolicy(
34+
new PolicyActionsRegistry(
35+
beginBlockActions: ImmutableArray<IAction>.Empty,
36+
endBlockActions: ImmutableArray<IAction>.Empty,
37+
beginTxActions: ImmutableArray.Create<IAction>(
38+
new GasTraceAction() { CancelTrace = cancelTrace }),
39+
endTxActions: ImmutableArray<IAction>.Empty),
40+
getMaxTransactionsBytes: _ => 50 * 1024);
41+
42+
var store = new MemoryStore();
43+
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
44+
var chain = TestUtils.MakeBlockChain(
45+
policy: policy,
46+
store: store,
47+
stateStore: stateStore,
48+
actionLoader: new SingleActionLoader(typeof(UseGasAction)));
49+
var action = new UseGasAction
50+
{
51+
GasUsage = 10,
52+
MintValue = gold * goldAmount,
53+
Receiver = privateKey.Address,
54+
Memo = string.Empty,
55+
};
56+
57+
var tx = Transaction.Create(
58+
nonce: 0,
59+
privateKey: privateKey,
60+
genesisHash: chain.Genesis.Hash,
61+
actions: new[] { action }.ToPlainValues(),
62+
maxGasPrice: gas * 10,
63+
gasLimit: 10);
64+
var expectedGold = gold * expectedGoldAmount;
65+
66+
chain.StageTransaction(tx);
67+
var miner = new PrivateKey();
68+
Block block = chain.ProposeBlock(miner);
69+
chain.Append(block, CreateBlockCommit(block));
70+
var evaluations = chain.ActionEvaluator.Evaluate(
71+
block, chain.GetNextStateRootHash((BlockHash)block.PreviousHash));
72+
73+
var actualGold = chain.GetNextWorldState().GetBalance(privateKey.Address, gold);
74+
75+
Assert.Equal(expectedGold, actualGold);
76+
}
77+
78+
[Fact]
79+
public void Evaluate_CancelTrace_BeginBlockAction_Throw()
80+
{
81+
var policy = new BlockPolicy(
82+
new PolicyActionsRegistry(
83+
beginBlockActions: ImmutableArray.Create<IAction>(
84+
new GasTraceAction() { CancelTrace = true }),
85+
endBlockActions: ImmutableArray<IAction>.Empty,
86+
beginTxActions: ImmutableArray<IAction>.Empty,
87+
endTxActions: ImmutableArray<IAction>.Empty),
88+
getMaxTransactionsBytes: _ => 50 * 1024);
89+
var evaluations = Evaluate_CancelTrace(policy);
90+
var exception = (UnexpectedlyTerminatedActionException)evaluations[0].Exception;
91+
92+
Assert.IsType<GasTraceAction>(exception.Action);
93+
Assert.IsType<InvalidOperationException>(exception.InnerException);
94+
Assert.Equal(
95+
"CancelTrace can only be called in TxAction.", exception.InnerException.Message);
96+
}
97+
98+
[Fact]
99+
public void Evaluate_CancelTrace_EndBlockAction_Throw()
100+
{
101+
var policy = new BlockPolicy(
102+
new PolicyActionsRegistry(
103+
beginBlockActions: ImmutableArray<IAction>.Empty,
104+
endBlockActions: ImmutableArray.Create<IAction>(
105+
new GasTraceAction() { CancelTrace = true }),
106+
beginTxActions: ImmutableArray<IAction>.Empty,
107+
endTxActions: ImmutableArray<IAction>.Empty),
108+
getMaxTransactionsBytes: _ => 50 * 1024);
109+
var evaluations = Evaluate_CancelTrace(policy);
110+
var exception = (UnexpectedlyTerminatedActionException)evaluations[1].Exception;
111+
112+
Assert.IsType<GasTraceAction>(exception.Action);
113+
Assert.IsType<InvalidOperationException>(exception.InnerException);
114+
Assert.Equal(
115+
"CancelTrace can only be called in TxAction.", exception.InnerException.Message);
116+
}
117+
118+
[Fact]
119+
public void Evaluate_CancelTrace_EndTxAction_Throw()
120+
{
121+
var policy = new BlockPolicy(
122+
new PolicyActionsRegistry(
123+
beginBlockActions: ImmutableArray<IAction>.Empty,
124+
endBlockActions: ImmutableArray<IAction>.Empty,
125+
beginTxActions: ImmutableArray<IAction>.Empty,
126+
endTxActions: ImmutableArray.Create<IAction>(
127+
new GasTraceAction() { CancelTrace = true })),
128+
getMaxTransactionsBytes: _ => 50 * 1024);
129+
var evaluations = Evaluate_CancelTrace(policy);
130+
var exception = (UnexpectedlyTerminatedActionException)evaluations[1].Exception;
131+
132+
Assert.IsType<GasTraceAction>(exception.Action);
133+
Assert.IsType<InvalidOperationException>(exception.InnerException);
134+
Assert.Equal(
135+
"CancelTrace can only be called in TxAction.", exception.InnerException.Message);
136+
}
137+
138+
[Fact]
139+
public void Evaluate_CancelTrace_Action_Throw()
140+
{
141+
var policy = new BlockPolicy(
142+
new PolicyActionsRegistry(
143+
beginBlockActions: ImmutableArray<IAction>.Empty,
144+
endBlockActions: ImmutableArray<IAction>.Empty,
145+
beginTxActions: ImmutableArray<IAction>.Empty,
146+
endTxActions: ImmutableArray<IAction>.Empty),
147+
getMaxTransactionsBytes: _ => 50 * 1024);
148+
var gold = Currency.Uncapped("FOO", 18, null);
149+
var gas = Currency.Uncapped("GAS", 18, null);
150+
var privateKey = new PrivateKey();
151+
152+
var store = new MemoryStore();
153+
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
154+
var chain = TestUtils.MakeBlockChain(
155+
policy: policy,
156+
store: store,
157+
stateStore: stateStore,
158+
actionLoader: new SingleActionLoader(typeof(GasTraceAction)));
159+
var action = new GasTraceAction
160+
{
161+
CancelTrace = true,
162+
};
163+
164+
var tx = Transaction.Create(
165+
nonce: 0,
166+
privateKey: privateKey,
167+
genesisHash: chain.Genesis.Hash,
168+
actions: new[] { action }.ToPlainValues(),
169+
maxGasPrice: gas * 10,
170+
gasLimit: 10);
171+
172+
chain.StageTransaction(tx);
173+
var miner = new PrivateKey();
174+
Block block = chain.ProposeBlock(miner);
175+
chain.Append(block, CreateBlockCommit(block));
176+
var evaluations = chain.ActionEvaluator.Evaluate(
177+
block, chain.GetNextStateRootHash((BlockHash)block.PreviousHash));
178+
var exception = (UnexpectedlyTerminatedActionException)evaluations[0].Exception;
179+
180+
Assert.IsType<GasTraceAction>(exception.Action);
181+
Assert.IsType<InvalidOperationException>(exception.InnerException);
182+
Assert.Equal(
183+
"CancelTrace can only be called in TxAction.", exception.InnerException.Message);
184+
}
185+
186+
private IReadOnlyList<ICommittedActionEvaluation> Evaluate_CancelTrace(BlockPolicy policy)
187+
{
188+
var gold = Currency.Uncapped("FOO", 18, null);
189+
var gas = Currency.Uncapped("GAS", 18, null);
190+
var privateKey = new PrivateKey();
191+
192+
var store = new MemoryStore();
193+
var stateStore = new TrieStateStore(new MemoryKeyValueStore());
194+
var chain = TestUtils.MakeBlockChain(
195+
policy: policy,
196+
store: store,
197+
stateStore: stateStore,
198+
actionLoader: new SingleActionLoader(typeof(UseGasAction)));
199+
var action = new UseGasAction
200+
{
201+
GasUsage = 10,
202+
MintValue = gold * 10,
203+
Receiver = privateKey.Address,
204+
Memo = string.Empty,
205+
};
206+
207+
var tx = Transaction.Create(
208+
nonce: 0,
209+
privateKey: privateKey,
210+
genesisHash: chain.Genesis.Hash,
211+
actions: new[] { action }.ToPlainValues(),
212+
maxGasPrice: gas * 10,
213+
gasLimit: 10);
214+
215+
chain.StageTransaction(tx);
216+
var miner = new PrivateKey();
217+
Block block = chain.ProposeBlock(miner);
218+
chain.Append(block, CreateBlockCommit(block));
219+
return chain.ActionEvaluator.Evaluate(
220+
block, chain.GetNextStateRootHash((BlockHash)block.PreviousHash));
221+
}
222+
223+
private sealed class GasTraceAction : IAction
224+
{
225+
public bool CancelTrace { get; set; }
226+
227+
public IValue PlainValue => new List(
228+
(Bencodex.Types.Boolean)CancelTrace);
229+
230+
public void LoadPlainValue(IValue plainValue)
231+
{
232+
var list = (List)plainValue;
233+
CancelTrace = (Bencodex.Types.Boolean)list[0];
234+
}
235+
236+
public IWorld Execute(IActionContext context)
237+
{
238+
if (CancelTrace)
239+
{
240+
GasTracer.CancelTrace();
241+
}
242+
243+
return context.PreviousState;
244+
}
245+
}
246+
}
247+
}

0 commit comments

Comments
 (0)