-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy pathtest_environments.py
199 lines (177 loc) · 9.16 KB
/
test_environments.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
from siftool.common import *
from siftool import command, environments, project, sifchain, cosmos
def get_validators(env):
sifnoded = env._sifnoded_for(env.node_info[0])
return {v["description"]["moniker"]: v for v in sifnoded.query_staking_validators()}
def test_transfer(env):
sifnoded = env.sifnoded
sifnoded.send_and_check(env.faucet, sifnoded.create_addr(), {sifchain.ROWAN: 10 ** sifchain.ROWAN_DECIMALS})
def assert_validators_working(env):
expected_monikers = [node_info["moniker"] for node_info in env.node_info if node_info["is_validator"]]
assert set(get_validators(env)) == set(expected_monikers)
number_of_nodes = len(env.node_info)
for i in range(number_of_nodes):
# Send transactions using "keyring" profile that has all the private keys, but is directed at a particular node.
# Cross check balaces on all nodes.
sifnoded = env._client_for(i)
from_address = env.faucet
to_address = sifnoded.create_addr() # This pollutes "client" keyring with temporary addresses, but we don't care
from_balance_before = sifnoded.get_balance(from_address)
to_balance_before = sifnoded.get_balance(to_address)
for j in range(number_of_nodes):
sifnoded_crosscheck = env._client_for(j)
assert cosmos.balance_equal(sifnoded_crosscheck.get_balance(from_address), from_balance_before)
assert cosmos.balance_equal(sifnoded_crosscheck.get_balance(to_address), to_balance_before)
sifnoded.send_and_check(from_address, to_address, {sifchain.ROWAN: 10 ** sifchain.ROWAN_DECIMALS})
at_block = sifnoded.get_current_block()
from_balance_after = sifnoded.get_balance(from_address)
to_balance_after = sifnoded.get_balance(to_address)
for j in range(number_of_nodes):
sifnoded_crosscheck = env._client_for(j)
sifnoded_crosscheck.wait_for_block(at_block) # Make sure the change has propagated
assert cosmos.balance_equal(sifnoded_crosscheck.get_balance(from_address), from_balance_after)
assert cosmos.balance_equal(sifnoded_crosscheck.get_balance(to_address), to_balance_after)
class TestSifnodedEnvironment:
def setup_method(self):
self.cmd = command.Command()
self.sifnoded_home_root = self.cmd.tmpdir("siftool.tmp")
self.cmd.rmdir(self.sifnoded_home_root)
self.cmd.mkdir(self.sifnoded_home_root)
prj = project.Project(self.cmd, project_dir())
prj.pkill()
def teardown_method(self):
prj = project.Project(self.cmd, project_dir())
prj.pkill()
def test_environment_setup_basic_1_validator(self):
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
env.add_validator()
env.start()
assert_validators_working(env)
def test_environment_setup_basic_4_validators(self):
env = environments.SifnodedEnvironment(self.cmd, chain_id="cownet-2", sifnoded_home_root=self.sifnoded_home_root)
assert len(env.node_info) == 0
env.add_validator(moniker="ant")
env.add_validator(moniker="bee")
env.add_validator(moniker="cat")
env.add_validator(moniker="dog")
assert len(env.node_info) == 4
env.start()
assert_validators_working(env)
def test_environment_setup_mix_of_nodes_and_validators(self):
env = environments.SifnodedEnvironment(self.cmd, chain_id="cownet-2", sifnoded_home_root=self.sifnoded_home_root)
assert len(env.node_info) == 0
env.add_validator(moniker="ant", is_validator=True)
env.add_validator(moniker="bee", is_validator=False)
env.add_validator(moniker="cat", is_validator=True)
assert len(env.node_info) == 3
env.start()
assert_validators_working(env)
def test_add_validator_before_and_after_start(self):
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
assert len(env.node_info) == 0
env.add_validator()
env.add_validator()
assert len(env.node_info) == 2
env.init()
env.start()
env.add_validator()
assert len(env.node_info) == 3
assert_validators_working(env)
def test_environment_fails_to_start_if_commission_rate_is_over_max(self):
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
env.add_validator(commission_rate=0.10, commission_max_rate=0.05)
exception = None
try:
env.start()
except Exception as e:
exception = e
# The validator will exit immediately, writing error to the log.
# What we get here is a "timeout waiting for sifnoded to come up".
assert type(exception) == sifchain.SifnodedException
def test_need_2_out_of_3_validators_running_for_consensus(self):
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
env.add_validator()
env.add_validator()
env.add_validator()
env.add_validator()
env.start()
assert len(env.running_processes) == 4
test_transfer(env) # 4 out of 4 => should work
env.running_processes[-1].terminate()
env.running_processes[-1].wait()
env.open_log_files[-1].close()
env.running_processes.pop()
env.open_log_files.pop()
test_transfer(env) # 3 out of 4 => should work
env.running_processes[-1].terminate()
env.running_processes[-1].wait()
env.open_log_files[-1].close()
env.running_processes.pop()
env.open_log_files.pop()
exception = None
try:
test_transfer(env) # 2 out of 4 => should fail
except Exception as e:
exception = e
assert type(exception) == sifchain.SifnodedException
def test_can_have_validators_with_same_moniker(self):
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
env.add_validator()
env.start()
sifnoded = env.sifnoded
home1 = self.cmd.mktempdir()
home2 = self.cmd.mktempdir()
try:
env.add_validator(moniker="juniper", home=home1)
assert len(sifnoded.query_staking_validators()) == 2
env.add_validator(moniker="juniper", home=home2)
assert len(sifnoded.query_staking_validators()) == 3
finally:
self.cmd.rmdir(home1)
self.cmd.rmdir(home2)
def test_balances(self):
number_of_validators = 3
number_of_denoms = 10 # > 1
number_of_wallets = 100
faucet_balance = cosmos.balance_add({"foo{}".format(i): (i + 1) * 10**30 for i in range(10)},
{sifchain.ROWAN: 10**30})
tmpdir = self.cmd.mktempdir()
try:
sifnoded = sifchain.Sifnoded(self.cmd, home=tmpdir)
extra_accounts = {sifnoded.create_addr(): {"bar{}".format(j): (i * number_of_denoms + j + 1) * 10**25
for j in range(number_of_denoms)} for i in range(number_of_wallets)}
env = environments.SifnodedEnvironment(self.cmd, sifnoded_home_root=self.sifnoded_home_root)
for _ in range(number_of_validators):
env.add_validator()
env.init(faucet_balance=faucet_balance, extra_accounts=extra_accounts)
env.start()
# Check faucet balances
for i in range(number_of_validators):
sifnoded = env._sifnoded_for(env.node_info[i])
assert cosmos.balance_equal(sifnoded.get_balance(env.faucet), faucet_balance)
# Check balances of extra_accounts
for i in range(number_of_validators):
sifnoded = env._sifnoded_for(env.node_info[i])
assert cosmos.balance_equal(sifnoded.get_balance(env.faucet), faucet_balance)
for addr, balance in extra_accounts.items():
assert cosmos.balance_equal(sifnoded.get_balance(addr), balance)
# Check funding
for i in range(number_of_validators):
addr = sifnoded.create_addr()
amount = {"foo0": 100 * 10**18, "foo1": 100 * 10**18}
env.fund(addr, amount)
assert cosmos.balance_equal(sifnoded.get_balance(addr), amount)
# On each node, do a sample transfer of one rowan from admin to a new wallet and check that the change of
# balances is visible on all nodes
test_transfer_amount = {sifchain.ROWAN: 10**sifchain.ROWAN_DECIMALS}
for i in range(number_of_validators):
sifnoded_i = env._sifnoded_for(env.node_info[i])
test_addr = sifnoded_i.create_addr()
# Sending also requires rowan, this way we're making sure that each validator has some
admin_addr = env.node_info[i]["admin_addr"]
sifnoded_i.send(admin_addr, test_addr, test_transfer_amount)
for j in range(number_of_validators):
sifnoded_j = env._sifnoded_for(env.node_info[j])
sifnoded_j.wait_for_balance_change(test_addr, {}, test_transfer_amount)
finally:
self.cmd.rmdir(tmpdir)