Skip to content

Commit b53a686

Browse files
committed
all cases for TraverseIterator
1 parent eefa8c9 commit b53a686

File tree

3 files changed

+106
-14
lines changed

3 files changed

+106
-14
lines changed

src/Plugins/RpcServer/RpcServer.SmartContract.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private void Initialize_SmartContract()
3939
timer = new(OnTimer, null, settings.SessionExpirationTime, settings.SessionExpirationTime);
4040
}
4141

42-
private void Dispose_SmartContract()
42+
internal void Dispose_SmartContract()
4343
{
4444
timer?.Dispose();
4545
Session[] toBeDestroyed;
@@ -52,7 +52,7 @@ private void Dispose_SmartContract()
5252
session.Dispose();
5353
}
5454

55-
private void OnTimer(object state)
55+
internal void OnTimer(object state)
5656
{
5757
List<(Guid Id, Session Session)> toBeDestroyed = new();
5858
lock (sessions)

tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.SmartContract.cs

+87-11
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
using Microsoft.AspNetCore.Http;
1414
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
1515
using Microsoft.VisualStudio.TestTools.UnitTesting;
16+
using Neo.Cryptography.ECC;
1617
using Neo.IO;
1718
using Neo.Json;
1819
using Neo.Network.P2P.Payloads;
20+
using Neo.Persistence;
1921
using Neo.SmartContract;
2022
using Neo.SmartContract.Native;
2123
using Neo.UnitTests;
@@ -25,13 +27,12 @@
2527
using System.IO;
2628
using System.Linq;
2729
using System.Text;
30+
using System.Threading;
2831

2932
namespace Neo.Plugins.RpcServer.Tests;
3033

3134
public partial class UT_RpcServer
3235
{
33-
static readonly string NeoScriptHash = "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5";
34-
static readonly string GasScriptHash = "0xd2a4cff31913016155e38e474a2c06d08be276cf";
3536
static readonly string NeoTotalSupplyScript = "wh8MC3RvdGFsU3VwcGx5DBT1Y\u002BpAvCg9TQ4FxI6jBbPyoHNA70FifVtS";
3637
static readonly string NeoTransferScript = "CxEMFPlu76Cuc\u002BbgteStE4ozsOWTNUdrDBQtYNweHko3YcnMFOes3ceblcI/lRTAHwwIdHJhbnNmZXIMFPVj6kC8KD1NDgXEjqMFs/Kgc0DvQWJ9W1I=";
3738
static readonly UInt160 ValidatorScriptHash = Contract
@@ -59,12 +60,12 @@ public void TestInvokeFunction()
5960
{
6061
_rpcServer.wallet = _wallet;
6162

62-
JObject resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash, "totalSupply", new JArray([]), validatorSigner, true));
63+
JObject resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "totalSupply", new JArray([]), validatorSigner, true));
6364
Assert.AreEqual(resp.Count, 8);
6465
Assert.AreEqual(resp["script"], NeoTotalSupplyScript);
6566
Assert.IsTrue(resp.ContainsProperty("gasconsumed"));
6667
Assert.IsTrue(resp.ContainsProperty("diagnostics"));
67-
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash);
68+
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash.ToString());
6869
Assert.IsTrue(((JArray)resp["diagnostics"]["storagechanges"]).Count == 0);
6970
Assert.AreEqual(resp["state"], "HALT");
7071
Assert.AreEqual(resp["exception"], null);
@@ -73,7 +74,7 @@ public void TestInvokeFunction()
7374
Assert.AreEqual(resp["stack"][0]["value"], "100000000");
7475
Assert.IsTrue(resp.ContainsProperty("tx"));
7576

76-
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash, "symbol"));
77+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "symbol"));
7778
Assert.AreEqual(resp.Count, 6);
7879
Assert.IsTrue(resp.ContainsProperty("script"));
7980
Assert.IsTrue(resp.ContainsProperty("gasconsumed"));
@@ -84,7 +85,7 @@ public void TestInvokeFunction()
8485
Assert.AreEqual(resp["stack"][0]["value"], Convert.ToBase64String(Encoding.UTF8.GetBytes("NEO")));
8586

8687
// This call triggers not only NEO but also unclaimed GAS
87-
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash, "transfer", new JArray([
88+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "transfer", new JArray([
8889
new JObject() { ["type"] = "Hash160", ["value"] = MultisigScriptHash.ToString() },
8990
new JObject() { ["type"] = "Hash160", ["value"] = ValidatorScriptHash.ToString() },
9091
new JObject() { ["type"] = "Integer", ["value"] = "1" },
@@ -94,17 +95,17 @@ public void TestInvokeFunction()
9495
Assert.AreEqual(resp["script"], NeoTransferScript);
9596
Assert.IsTrue(resp.ContainsProperty("gasconsumed"));
9697
Assert.IsTrue(resp.ContainsProperty("diagnostics"));
97-
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash);
98+
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash.ToString());
9899
Assert.IsTrue(((JArray)resp["diagnostics"]["storagechanges"]).Count == 4);
99100
Assert.AreEqual(resp["state"], "HALT");
100101
Assert.AreEqual(resp["exception"], $"The smart contract or address {MultisigScriptHash.ToString()} is not found");
101102
JArray notifications = (JArray)resp["notifications"];
102103
Assert.AreEqual(notifications.Count, 2);
103104
Assert.AreEqual(notifications[0]["eventname"].AsString(), "Transfer");
104-
Assert.AreEqual(notifications[0]["contract"].AsString(), NeoScriptHash);
105+
Assert.AreEqual(notifications[0]["contract"].AsString(), NeoScriptHash.ToString());
105106
Assert.AreEqual(notifications[0]["state"]["value"][2]["value"], "1");
106107
Assert.AreEqual(notifications[1]["eventname"].AsString(), "Transfer");
107-
Assert.AreEqual(notifications[1]["contract"].AsString(), GasScriptHash);
108+
Assert.AreEqual(notifications[1]["contract"].AsString(), GasScriptHash.ToString());
108109
Assert.AreEqual(notifications[1]["state"]["value"][2]["value"], "50000000");
109110

110111
_rpcServer.wallet = null;
@@ -117,7 +118,7 @@ public void TestInvokeScript()
117118
Assert.AreEqual(resp.Count, 7);
118119
Assert.IsTrue(resp.ContainsProperty("gasconsumed"));
119120
Assert.IsTrue(resp.ContainsProperty("diagnostics"));
120-
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash);
121+
Assert.AreEqual(resp["diagnostics"]["invokedcontracts"]["call"][0]["hash"], NeoScriptHash.ToString());
121122
Assert.AreEqual(resp["state"], "HALT");
122123
Assert.AreEqual(resp["exception"], null);
123124
Assert.AreEqual(((JArray)resp["notifications"]).Count, 0);
@@ -133,7 +134,8 @@ public void TestInvokeScript()
133134
[TestMethod]
134135
public void TestTraverseIterator()
135136
{
136-
JObject resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash, "getAllCandidates", new JArray([]), validatorSigner, true));
137+
// GetAllCandidates that should return 0 candidates
138+
JObject resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "getAllCandidates", new JArray([]), validatorSigner, true));
137139
string sessionId = resp["session"].AsString();
138140
string iteratorId = resp["stack"][0]["id"].AsString();
139141
JArray respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 100]);
@@ -147,6 +149,80 @@ public void TestTraverseIterator()
147149
{
148150
Assert.AreEqual(e.Message, "Unknown session");
149151
}
152+
153+
// register candidate in snapshot
154+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "registerCandidate",
155+
new JArray([new JObject()
156+
{
157+
["type"] = "PublicKey",
158+
["value"] = TestProtocolSettings.SoleNode.StandbyCommittee[0].ToString(),
159+
}]), validatorSigner, true));
160+
Assert.AreEqual(resp["state"], "HALT");
161+
SnapshotCache snapshot = _neoSystem.GetSnapshotCache();
162+
Transaction? tx = new Transaction
163+
{
164+
Nonce = 233,
165+
ValidUntilBlock = NativeContract.Ledger.CurrentIndex(snapshot) + _neoSystem.Settings.MaxValidUntilBlockIncrement,
166+
Signers = [new Signer() { Account = ValidatorScriptHash, Scopes = WitnessScope.CalledByEntry }],
167+
Attributes = Array.Empty<TransactionAttribute>(),
168+
Script = Convert.FromBase64String(resp["script"].AsString()),
169+
Witnesses = null,
170+
};
171+
ApplicationEngine engine = ApplicationEngine.Run(tx.Script, snapshot, container: tx, settings: _neoSystem.Settings, gas: 1200_0000_0000);
172+
engine.SnapshotCache.Commit();
173+
174+
// GetAllCandidates that should return 1 candidate
175+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "getAllCandidates", new JArray([]), validatorSigner, true));
176+
sessionId = resp["session"].AsString();
177+
iteratorId = resp["stack"][0]["id"].AsString();
178+
respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 100]);
179+
Assert.AreEqual(respArray.Count, 1);
180+
Assert.AreEqual(respArray[0]["type"], "Struct");
181+
JArray value = (JArray)respArray[0]["value"];
182+
Assert.AreEqual(value.Count, 2);
183+
Assert.AreEqual(value[0]["type"], "ByteString");
184+
Assert.AreEqual(value[0]["value"], Convert.ToBase64String(TestProtocolSettings.SoleNode.StandbyCommittee[0].ToArray()));
185+
Assert.AreEqual(value[1]["type"], "Integer");
186+
Assert.AreEqual(value[1]["value"], "0");
187+
188+
// No result when traversed again
189+
respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 100]);
190+
Assert.AreEqual(respArray.Count, 0);
191+
192+
// GetAllCandidates again
193+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "getAllCandidates", new JArray([]), validatorSigner, true));
194+
sessionId = resp["session"].AsString();
195+
iteratorId = resp["stack"][0]["id"].AsString();
196+
197+
// Insufficient result count limit
198+
respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 0]);
199+
Assert.AreEqual(respArray.Count, 0);
200+
201+
// Mocking session timeout
202+
Thread.Sleep(_rpcServerSettings.SessionExpirationTime.Milliseconds + 1);
203+
_rpcServer.OnTimer(new object());
204+
try
205+
{
206+
respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 100]);
207+
}
208+
catch (RpcException e)
209+
{
210+
Assert.AreEqual(e.Message, "Unknown session");
211+
}
212+
213+
// Mocking disposal
214+
resp = (JObject)_rpcServer.InvokeFunction(new JArray(NeoScriptHash.ToString(), "getAllCandidates", new JArray([]), validatorSigner, true));
215+
sessionId = resp["session"].AsString();
216+
iteratorId = resp["stack"][0]["id"].AsString();
217+
_rpcServer.Dispose_SmartContract();
218+
try
219+
{
220+
respArray = (JArray)_rpcServer.TraverseIterator([sessionId, iteratorId, 100]);
221+
}
222+
catch (RpcException e)
223+
{
224+
Assert.AreEqual(e.Message, "Unknown session");
225+
}
150226
}
151227

152228
[TestMethod]

tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs

+17-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
using Microsoft.AspNetCore.Http;
1313
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
using Neo.IO;
1415
using Neo.Ledger;
1516
using Neo.Persistence;
1617
using Neo.SmartContract;
@@ -19,7 +20,9 @@
1920
using Neo.Wallets;
2021
using Neo.Wallets.NEP6;
2122
using System;
23+
using System.Linq;
2224
using System.Net;
25+
using System.Numerics;
2326
using System.Text;
2427

2528
namespace Neo.Plugins.RpcServer.Tests
@@ -28,19 +31,32 @@ namespace Neo.Plugins.RpcServer.Tests
2831
public partial class UT_RpcServer
2932
{
3033
private NeoSystem _neoSystem;
34+
private RpcServerSettings _rpcServerSettings;
3135
private RpcServer _rpcServer;
3236
private TestMemoryStoreProvider _memoryStoreProvider;
3337
private MemoryStore _memoryStore;
3438
private readonly NEP6Wallet _wallet = TestUtils.GenerateTestWallet("123");
3539
private WalletAccount _walletAccount;
3640

41+
static readonly UInt160 NeoScriptHash = UInt160.Parse("0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5");
42+
static readonly UInt160 GasScriptHash = UInt160.Parse("0xd2a4cff31913016155e38e474a2c06d08be276cf");
43+
const byte NativePrefixAccount = 20;
44+
const byte NativePrefixTotalSupply = 11;
45+
3746
[TestInitialize]
3847
public void TestSetup()
3948
{
4049
_memoryStore = new MemoryStore();
4150
_memoryStoreProvider = new TestMemoryStoreProvider(_memoryStore);
4251
_neoSystem = new NeoSystem(TestProtocolSettings.SoleNode, _memoryStoreProvider);
43-
_rpcServer = new RpcServer(_neoSystem, RpcServerSettings.Default with { SessionEnabled = true, Network = TestProtocolSettings.SoleNode.Network });
52+
_rpcServerSettings = RpcServerSettings.Default with
53+
{
54+
SessionEnabled = true,
55+
SessionExpirationTime = TimeSpan.FromSeconds(1),
56+
MaxGasInvoke = 1500_0000_0000,
57+
Network = TestProtocolSettings.SoleNode.Network,
58+
};
59+
_rpcServer = new RpcServer(_neoSystem, _rpcServerSettings);
4460
_walletAccount = _wallet.Import("KxuRSsHgJMb3AMSN6B9P3JHNGMFtxmuimqgR9MmXPcv3CLLfusTd");
4561
var key = new KeyBuilder(NativeContract.GAS.Id, 20).Add(_walletAccount.ScriptHash);
4662
var snapshot = _neoSystem.GetSnapshotCache();

0 commit comments

Comments
 (0)