1
using System;
2
using System.Collections.Immutable;
3
using System.Linq;
4
using Bencodex.Types;
5
using Libplanet.Action;
6
using Libplanet.Assets;
7
using Libplanet.Store.Trie;
8
using Libplanet.Tests.Store.Trie;
9
using Xunit;
10

11
namespace Libplanet.Tests.Action
12
{
13
    public class ActionContextTest
14
    {
15
        [Fact]
16
        public void RandomShouldBeDeterministic()
17 1
        {
18 1
            (int Seed, int Expected)[] testCases =
19 1
            {
20 1
                (0, 1559595546),
21 1
                (1, 534011718),
22 1
            };
23 1
            var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
24 1
            foreach (var (seed, expected) in testCases)
25 1
            {
26 1
                var context = new ActionContext(
27 1
                    signer: address,
28 1
                    miner: address,
29 1
                    blockIndex: 1,
30 1
                    previousStates: new DumbAccountStateDelta(),
31 1
                    randomSeed: seed
32 1
                );
33 1
                IRandom random = context.Random;
34 1
                Assert.Equal(expected, random.Next());
35 1
            }
36 1
        }
37

38
        [Fact]
39
        public void GuidShouldBeDeterministic()
40 1
        {
41 1
            var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
42 1
            var context1 = new ActionContext(
43 1
                signer: address,
44 1
                miner: address,
45 1
                blockIndex: 1,
46 1
                previousStates: new DumbAccountStateDelta(),
47 1
                randomSeed: 0
48 1
            );
49

50 1
            var context2 = new ActionContext(
51 1
                signer: address,
52 1
                miner: address,
53 1
                blockIndex: 1,
54 1
                previousStates: new DumbAccountStateDelta(),
55 1
                randomSeed: 0
56 1
            );
57

58 1
            var context3 = new ActionContext(
59 1
                signer: address,
60 1
                miner: address,
61 1
                blockIndex: 1,
62 1
                previousStates: new DumbAccountStateDelta(),
63 1
                randomSeed: 1
64 1
            );
65

66 1
            (Guid Expected, Guid Diff)[] testCases =
67 1
            {
68 1
                (
69 1
                    new Guid("6f460c1a-755d-48e4-ad67-65d5f519dbc8"),
70 1
                    new Guid("8286d046-9740-43e4-95cf-ff46699c73c4")
71 1
                ),
72 1
                (
73 1
                    new Guid("3b347c2b-f837-4085-ac5e-64005393b30d"),
74 1
                    new Guid("3410cda1-5b13-434e-af84-a54adf7a0ea0")
75 1
                ),
76 1
            };
77

78 1
            foreach (var (expected, diff) in testCases)
79 1
            {
80 1
                Assert.Equal(expected, context1.Random.GenerateRandomGuid());
81 1
                Assert.Equal(expected, context2.Random.GenerateRandomGuid());
82 1
                Assert.Equal(diff, context3.Random.GenerateRandomGuid());
83 1
            }
84 1
        }
85

86
        [Fact]
87
        public void GuidVersionAndVariant()
88 1
        {
89 1
            var address = new Address("21744f4f08db23e044178dafb8273aeb5ebe6644");
90

91 1
            for (var i = 0; i < 100; i++)
92 1
            {
93 1
                var context = new ActionContext(
94 1
                        signer: address,
95 1
                        miner: address,
96 1
                        blockIndex: 1,
97 1
                        previousStates: new DumbAccountStateDelta(),
98 1
                        randomSeed: i
99 1
                    );
100 1
                var guid = context.Random.GenerateRandomGuid().ToString();
101

102 1
                Assert.Equal('4', guid[14]);
103 1
                Assert.True(guid[19] >= '8' && guid[19] <= 'b');
104 1
            }
105 1
        }
106

107
        [Fact]
108
        public void GetUnconsumedContext()
109 1
        {
110 1
            var random = new System.Random();
111 1
            var original = new ActionContext(
112 1
                signer: random.NextAddress(),
113 1
                miner: random.NextAddress(),
114 1
                blockIndex: 1,
115 1
                previousStates: new DumbAccountStateDelta(),
116 1
                randomSeed: random.Next()
117 1
            );
118

119
            // Consume original's random state...
120 1
            int[] values =
121 1
            {
122 1
                original.Random.Next(),
123 1
                original.Random.Next(),
124 1
                original.Random.Next(),
125 1
            };
126

127 1
            IActionContext clone = original.GetUnconsumedContext();
128 1
            Assert.Equal(
129 1
                values,
130 1
                new[] { clone.Random.Next(), clone.Random.Next(), clone.Random.Next() }
131 1
            );
132 1
        }
133

134
        [Theory]
135
        [InlineData(true)]
136
        [InlineData(false)]
137
        public void LazyPreviousStateRootHash(bool callPreviousStateRootHash)
138 1
        {
139 1
            var keyValueStore = new MemoryKeyValueStore();
140 1
            ITrie previousBlockStatesTrie = new MerkleTrie(keyValueStore);
141 1
            previousBlockStatesTrie = previousBlockStatesTrie.Set(new byte[0], default(Null));
142 1
            var random = new System.Random();
143 1
            var actionContext = new ActionContext(
144 1
                signer: random.NextAddress(),
145 1
                miner: random.NextAddress(),
146 1
                blockIndex: 1,
147 1
                previousStates: new DumbAccountStateDelta(),
148 1
                randomSeed: random.Next(),
149 1
                previousBlockStatesTrie: previousBlockStatesTrie
150 1
            );
151

152 1
            if (callPreviousStateRootHash)
153 1
            {
154 1
                _ = actionContext.PreviousStateRootHash;
155 1
            }
156

157 1
            Assert.Equal(callPreviousStateRootHash ? 1 : 0, keyValueStore.ListKeys().Count());
158 1
        }
159

160
        private class DumbAccountStateDelta : IAccountStateDelta
161
        {
162
            public IImmutableSet<Address> UpdatedAddresses =>
163 0
                ImmutableHashSet<Address>.Empty;
164

165
            public IImmutableSet<Address> StateUpdatedAddresses =>
166 1
                ImmutableHashSet<Address>.Empty;
167

168
            public IImmutableDictionary<Address, IImmutableSet<Currency>>
169
            UpdatedFungibleAssets =>
170 1
                ImmutableDictionary<Address, IImmutableSet<Currency>>.Empty;
171

172 0
            public IValue GetState(Address address) => null;
173

174 0
            public IAccountStateDelta SetState(Address address, IValue state) => this;
175

176
            public FungibleAssetValue GetBalance(Address address, Currency currency) =>
177 0
                new FungibleAssetValue(currency);
178

179
            public IAccountStateDelta MintAsset(Address recipient, FungibleAssetValue value) =>
180 0
                this;
181

182
            public IAccountStateDelta TransferAsset(
183
                Address sender,
184
                Address recipient,
185
                FungibleAssetValue value,
186
                bool allowNegativeBalance = false
187 0
            ) => this;
188

189 0
            public IAccountStateDelta BurnAsset(Address owner, FungibleAssetValue value) => this;
190
        }
191
    }
192
}

Read our documentation on viewing source code .

Loading