Skip to content

Commit

Permalink
test: Reimplement MockStates
Browse files Browse the repository at this point in the history
  • Loading branch information
OnedgeLee committed Nov 9, 2023
1 parent 2ff505b commit c0c0284
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 47 deletions.
4 changes: 2 additions & 2 deletions Libplanet.Action.Tests/ActionEvaluationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public void Constructor()
0,
false),
new World(
new MockWorldState().SetAccount(
new MockWorldState().SetAccountState(
ReservedAddresses.LegacyAccount,
new Account(MockAccountState.Empty.SetState(address, (Text)"item"))))
new Account(new MockAccountState().SetState(address, (Text)"item"))))
);
var action = (DumbAction)evaluation.Action;

Expand Down
57 changes: 31 additions & 26 deletions Libplanet.Action.Tests/Mocks/MockAccountState.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System.Numerics;
using System.Security.Cryptography;
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
using static Libplanet.Action.State.KeyConverters;

namespace Libplanet.Action.Tests.Mocks
{
Expand Down Expand Up @@ -47,34 +49,31 @@ namespace Libplanet.Action.Tests.Mocks
/// </remarks>
public class MockAccountState : IAccountState
{
private static readonly MockAccountState _empty = new MockAccountState();
private readonly IStateStore _stateStore;

public MockAccountState()
: this(new TrieStateStore(new MemoryKeyValueStore()).GetStateRoot(null))
: this(new TrieStateStore(new MemoryKeyValueStore()), null)
{
}

private MockAccountState(ITrie trie)
public MockAccountState(
IStateStore stateStore,
HashDigest<SHA256>? stateRootHash = null)
{
Trie = trie;
_stateStore = stateStore;
Trie = stateStore.GetStateRoot(stateRootHash);
}

public static MockAccountState Empty => _empty;

public Address Address { get; }

public ITrie Trie { get; }

public BlockHash? BlockHash { get; }

public IValue GetState(Address address) =>
Trie.Get(KeyConverters.ToStateKey(address));
Trie.Get(ToStateKey(address));

public IReadOnlyList<IValue> GetStates(IReadOnlyList<Address> addresses) =>
addresses.Select(GetState).ToList();

public FungibleAssetValue GetBalance(Address address, Currency currency) =>
Trie.Get(KeyConverters.ToFungibleAssetKey(address, currency)) is Integer rawValue
Trie.Get(ToFungibleAssetKey(address, currency)) is Integer rawValue
? FungibleAssetValue.FromRawValue(currency, rawValue)
: currency * 0;

Expand All @@ -89,19 +88,20 @@ public FungibleAssetValue GetTotalSupply(Currency currency)
throw new TotalSupplyNotTrackableException(msg, currency);
}

return Trie.Get(KeyConverters.ToTotalSupplyKey(currency)) is Integer rawValue
return Trie.Get(ToTotalSupplyKey(currency)) is Integer rawValue
? FungibleAssetValue.FromRawValue(currency, rawValue)
: currency * 0;
}

public ValidatorSet GetValidatorSet() =>
Trie.Get(KeyConverters.ValidatorSetKey) is List list
Trie.Get(ValidatorSetKey) is List list
? new ValidatorSet(list)
: new ValidatorSet();

public MockAccountState SetState(Address address, IValue state) =>
new MockAccountState(
Trie.Set(KeyConverters.ToStateKey(address), state));
_stateStore,
_stateStore.Commit(Trie.Set(ToStateKey(address), state)).Hash);

public MockAccountState SetBalance(
Address address, FungibleAssetValue amount) =>
Expand All @@ -114,9 +114,11 @@ public MockAccountState SetBalance(
public MockAccountState SetBalance(
(Address Address, Currency Currency) pair, BigInteger rawAmount) =>
new MockAccountState(
Trie.Set(
KeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency),
new Integer(rawAmount)));
_stateStore,
_stateStore.Commit(
Trie.Set(
ToFungibleAssetKey(pair.Address, pair.Currency),
new Integer(rawAmount))).Hash);

public MockAccountState AddBalance(Address address, FungibleAssetValue amount) =>
AddBalance((address, amount.Currency), amount.RawValue);
Expand All @@ -129,7 +131,7 @@ public MockAccountState AddBalance(
(Address Address, Currency Currency) pair, BigInteger rawAmount) =>
SetBalance(
pair,
(Trie.Get(KeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency)) is
(Trie.Get(ToFungibleAssetKey(pair.Address, pair.Currency)) is
Integer amount ? amount : 0) + rawAmount);

public MockAccountState SubtractBalance(
Expand All @@ -144,7 +146,7 @@ public MockAccountState SubtractBalance(
(Address Address, Currency Currency) pair, BigInteger rawAmount) =>
SetBalance(
pair,
(Trie.Get(KeyConverters.ToFungibleAssetKey(pair.Address, pair.Currency)) is
(Trie.Get(ToFungibleAssetKey(pair.Address, pair.Currency)) is
Integer amount ? amount : 0) - rawAmount);

public MockAccountState TransferBalance(
Expand All @@ -163,7 +165,9 @@ public MockAccountState SetTotalSupply(Currency currency, BigInteger rawAmount)
? !(currency.MaximumSupply is FungibleAssetValue maximumSupply) ||
rawAmount <= maximumSupply.RawValue
? new MockAccountState(
Trie.Set(KeyConverters.ToTotalSupplyKey(currency), new Integer(rawAmount)))
_stateStore,
_stateStore.Commit(
Trie.Set(ToTotalSupplyKey(currency), new Integer(rawAmount))).Hash)
: throw new ArgumentException(
$"Given {currency}'s total supply is capped at {maximumSupply.RawValue} " +
$"and cannot be set to {rawAmount}.")
Expand All @@ -176,7 +180,7 @@ public MockAccountState AddTotalSupply(FungibleAssetValue amount) =>
public MockAccountState AddTotalSupply(Currency currency, BigInteger rawAmount) =>
SetTotalSupply(
currency,
(Trie.Get(KeyConverters.ToTotalSupplyKey(currency)) is
(Trie.Get(ToTotalSupplyKey(currency)) is
Integer amount ? amount : 0) + rawAmount);

public MockAccountState SubtractTotalSupply(FungibleAssetValue amount) =>
Expand All @@ -185,12 +189,13 @@ public MockAccountState SubtractTotalSupply(FungibleAssetValue amount) =>
public MockAccountState SubtractTotalSupply(Currency currency, BigInteger rawAmount) =>
SetTotalSupply(
currency,
(Trie.Get(KeyConverters.ToTotalSupplyKey(currency)) is
(Trie.Get(ToTotalSupplyKey(currency)) is
Integer amount ? amount : 0) - rawAmount);

public MockAccountState SetValidator(Validator validator) =>
new MockAccountState(
Trie.Set(
KeyConverters.ValidatorSetKey, GetValidatorSet().Update(validator).Bencoded));
_stateStore,
_stateStore.Commit(
Trie.Set(ValidatorSetKey, GetValidatorSet().Update(validator).Bencoded)).Hash);
}
}
46 changes: 28 additions & 18 deletions Libplanet.Action.Tests/Mocks/MockWorldState.cs
Original file line number Diff line number Diff line change
@@ -1,42 +1,52 @@
using System.Collections.Immutable;
using System.Security.Cryptography;
using Bencodex.Types;
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Store;
using Libplanet.Store.Trie;
using static Libplanet.Action.State.KeyConverters;

namespace Libplanet.Action.Tests.Mocks
{
public class MockWorldState : IWorldState
{
private readonly IImmutableDictionary<Address, IAccount> _accounts;
private readonly IStateStore _stateStore;

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (macos-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (macos-latest)

Remove unassigned field '_stateStore', or set its value.

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / docs

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / docs

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (ubuntu-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (ubuntu-latest)

Remove unassigned field '_stateStore', or set its value.

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (windows-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (windows-latest)

Remove unassigned field '_stateStore', or set its value.

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (macos-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (macos-latest)

Remove unassigned field '_stateStore', or set its value.

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / docs

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / docs

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (ubuntu-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (ubuntu-latest)

Remove unassigned field '_stateStore', or set its value.

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (windows-latest)

Field 'MockWorldState._stateStore' is never assigned to, and will always have its default value null

Check warning on line 14 in Libplanet.Action.Tests/Mocks/MockWorldState.cs

View workflow job for this annotation

GitHub Actions / Run Benchmark.Net benchmarks (windows-latest)

Remove unassigned field '_stateStore', or set its value.

public MockWorldState()
: this(ImmutableDictionary<Address, IAccount>.Empty)
: this(new TrieStateStore(new MemoryKeyValueStore()), null)
{
}

public MockWorldState(IImmutableDictionary<Address, IAccount> accounts)
: this(new TrieStateStore(new MemoryKeyValueStore()).GetStateRoot(null), accounts)
public MockWorldState(
IStateStore stateStore,
HashDigest<SHA256>? stateRootHash = null)
{
}

public MockWorldState(ITrie trie, IImmutableDictionary<Address, IAccount> accounts)
{
Trie = trie;
Legacy = true;
_accounts = accounts;
Trie = stateStore.GetStateRoot(stateRootHash);
Legacy = Trie
.Get(new[]
{
ToStateKey(ReservedAddresses.LegacyAccount),
})
.Any(v => v == null);
}

public ITrie Trie { get; }

public bool Legacy { get; private set; }

public IAccount GetAccount(Address address)
=> _accounts.TryGetValue(address, out IAccount account)
? account
: new Account(new MockAccountState());

public IWorldState SetAccount(Address address, IAccount account) =>
new MockWorldState(_accounts.SetItem(address, account));
=> Legacy && address.Equals(ReservedAddresses.LegacyAccount)
? new Account(new MockAccountState(_stateStore, Trie.Hash))
: new Account(new MockAccountState(
_stateStore, new HashDigest<SHA256>(Trie.Get(ToStateKey(address)))));

public IWorldState SetAccountState(Address address, IAccount account)
=> Legacy && address.Equals(ReservedAddresses.LegacyAccount)
? new MockWorldState(_stateStore, account.Trie.Hash)
: new MockWorldState(
_stateStore,
_stateStore.Commit(
Trie.Set(ToStateKey(address), new Binary(account.Trie.Hash.ByteArray))).Hash);
}
}
2 changes: 1 addition & 1 deletion Libplanet.Tests/Action/AccountTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected AccountTest(ITestOutputHelper output)
Currency.Capped("QUUX", 0, (100, 0), minter: _addr[0]),
};

_initAccount = new Account(MockAccountState.Empty
_initAccount = new Account(new MockAccountState()
.SetState(_addr[0], (Text)"a")
.SetState(_addr[1], (Text)"b")
.SetBalance(_addr[0], _currencies[0], 5)
Expand Down

0 comments on commit c0c0284

Please sign in to comment.