1
- from tokenomics_decentralization .analyze import get_output_row , analyze_snapshot , analyze , write_csv_output
1
+ from tokenomics_decentralization .analyze import analyze_snapshot , analyze , get_entries
2
+ from unittest .mock import call
2
3
import pathlib
3
- import os
4
-
5
-
6
- def test_get_output_row (mocker ):
7
- get_metrics_mock = mocker .patch ('tokenomics_decentralization.helper.get_metrics' )
8
- get_metrics_mock .return_value = ['hhi' , 'gini' ]
9
-
10
- get_clustering_mock = mocker .patch ('tokenomics_decentralization.helper.get_clustering_flag' )
11
- get_exclude_contracts_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_contracts_flag' )
12
- get_exclude_below_fees_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_fees_flag' )
13
- get_exclude_below_usd_cent_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_usd_cent_flag' )
14
- get_top_limit_type_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_type' )
15
- get_top_limit_value_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_value' )
16
-
17
- get_clustering_mock .return_value = True
18
- get_exclude_contracts_mock .return_value = False
19
- get_exclude_below_fees_mock .return_value = False
20
- get_exclude_below_usd_cent_mock .return_value = False
21
- get_top_limit_type_mock .return_value = 'absolute'
22
- get_top_limit_value_mock .return_value = 0
23
-
24
- metrics = {'hhi' : 1 , 'gini' : 0 }
25
- csv_row = get_output_row ('bitcoin' , '2010-01-01' , metrics )
26
- assert csv_row == ['bitcoin' , '2010-01-01' , True , False , 'absolute' , 0 , False , False , 1 , 0 ]
27
-
28
- get_clustering_mock .return_value = False
29
- metrics = {'non-clustered hhi' : 1 , 'non-clustered gini' : 0 }
30
- csv_row = get_output_row ('bitcoin' , '2010-01-01' , metrics )
31
- assert csv_row == ['bitcoin' , '2010-01-01' , False , False , 'absolute' , 0 , False , False , 1 , 0 ]
32
-
33
- get_exclude_contracts_mock .return_value = True
34
- metrics = {'exclude_contracts non-clustered hhi' : 1 , 'exclude_contracts non-clustered gini' : 0 }
35
- csv_row = get_output_row ('bitcoin' , '2010-01-01' , metrics )
36
- assert csv_row == ['bitcoin' , '2010-01-01' , False , True , 'absolute' , 0 , False , False , 1 , 0 ]
37
-
38
- get_top_limit_value_mock .return_value = 1
39
- metrics = {'top-1_absolute exclude_contracts non-clustered hhi' : 1 , 'top-1_absolute exclude_contracts non-clustered gini' : 0 }
40
- csv_row = get_output_row ('bitcoin' , '2010-01-01' , metrics )
41
- assert csv_row == ['bitcoin' , '2010-01-01' , False , True , 'absolute' , 1 , False , False , 1 , 0 ]
42
-
43
- get_exclude_below_fees_mock .return_value = True
44
- get_top_limit_value_mock .return_value = 1
45
- metrics = {'top-1_absolute exclude_below_fees exclude_contracts non-clustered hhi' : 1 , 'top-1_absolute exclude_below_fees exclude_contracts non-clustered gini' : 0 }
46
- csv_row = get_output_row ('bitcoin' , '2010-01-01' , metrics )
47
- assert csv_row == ['bitcoin' , '2010-01-01' , False , True , 'absolute' , 1 , True , False , 1 , 0 ]
48
4
49
5
50
6
def test_analyze_snapshot (mocker ):
51
- get_force_analyze_mock = mocker .patch ('tokenomics_decentralization.helper.get_force_analyze_flag' )
52
7
get_clustering_mock = mocker .patch ('tokenomics_decentralization.helper.get_clustering_flag' )
53
8
get_exclude_contracts_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_contracts_flag' )
54
9
get_exclude_below_fees_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_fees_flag' )
55
10
get_exclude_below_usd_cent_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_usd_cent_flag' )
56
- get_median_tx_fee_mock = mocker .patch ('tokenomics_decentralization.helper.get_median_tx_fee' )
57
11
get_top_limit_type_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_type' )
58
12
get_top_limit_value_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_value' )
13
+
59
14
get_metrics_mock = mocker .patch ('tokenomics_decentralization.helper.get_metrics' )
60
- get_snapshot_info_mock = mocker .patch ('tokenomics_decentralization.db_helper.get_snapshot_info' )
61
- get_metric_value_mock = mocker .patch ('tokenomics_decentralization.db_helper.get_metric_value' )
62
- get_clustered_entries_mock = mocker .patch ('tokenomics_decentralization.db_helper.get_balance_entries' )
63
- get_nonclustered_entries_mock = mocker .patch ('tokenomics_decentralization.db_helper.get_non_clustered_balance_entries' )
64
- db_insert_mock = mocker .patch ('tokenomics_decentralization.db_helper.insert_metric' )
65
- db_commit_mock = mocker .patch ('tokenomics_decentralization.db_helper.commit_database' )
66
15
67
16
compute_hhi_mock = mocker .patch ('tokenomics_decentralization.analyze.compute_hhi' )
68
17
compute_tau_mock = mocker .patch ('tokenomics_decentralization.analyze.compute_tau' )
69
18
70
- get_force_analyze_mock .return_value = False
71
19
get_clustering_mock .return_value = True
72
20
get_exclude_contracts_mock .return_value = False
73
21
get_exclude_below_fees_mock .return_value = False
74
22
get_exclude_below_usd_cent_mock .return_value = False
75
- get_median_tx_fee_mock .return_value = 0
76
23
get_top_limit_type_mock .return_value = 'absolute'
77
24
get_top_limit_value_mock .return_value = 0
78
25
79
- get_snapshot_info_mock .return_value = [1 , 1 , '2010-01-01' , 8 ]
26
+ get_circulation_mock = mocker .patch ('tokenomics_decentralization.helper.get_circulation_from_entries' )
27
+ circulation = 5
28
+ get_circulation_mock .return_value = circulation
80
29
81
30
get_metrics_mock .return_value = ['hhi' ]
82
31
83
- get_metric_value_mock .return_value = [1 ]
32
+ compute_hhi_mock .return_value = 1
33
+
34
+ entries = [(1 , ), (2 , )]
35
+
36
+ hhi_calls = []
84
37
85
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
38
+ output = analyze_snapshot (entries )
39
+ hhi_calls .append (call (entries , circulation ))
40
+ assert compute_hhi_mock .call_args_list == hhi_calls
86
41
assert output == {'hhi' : 1 }
87
42
88
43
get_clustering_mock .return_value = False
@@ -91,132 +46,137 @@ def test_analyze_snapshot(mocker):
91
46
get_top_limit_type_mock .return_value = 'absolute'
92
47
get_top_limit_value_mock .return_value = 1
93
48
94
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
49
+ output = analyze_snapshot (entries )
50
+ hhi_calls .append (call (entries [:1 ], circulation ))
51
+ assert compute_hhi_mock .call_args_list == hhi_calls
95
52
assert output == {'top-1_absolute exclude_below_fees exclude_contracts non-clustered hhi' : 1 }
96
53
97
- get_clustered_entries_mock .return_value = [[4 , ], [4 , ]]
98
- get_nonclustered_entries_mock .return_value = [[4 , ], [4 , ]]
99
-
100
- get_force_analyze_mock .return_value = True
101
-
102
- db_insert_mock .return_value = None
103
- db_commit_mock .return_value = None
104
-
105
54
compute_hhi_mock .return_value = 2
106
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
55
+ output = analyze_snapshot (entries )
56
+ hhi_calls .append (call (entries [:1 ], circulation ))
57
+ assert compute_hhi_mock .call_args_list == hhi_calls
107
58
assert output == {'top-1_absolute exclude_below_fees exclude_contracts non-clustered hhi' : 2 }
108
59
109
60
get_clustering_mock .return_value = True
110
-
111
61
compute_hhi_mock .return_value = 3
112
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
62
+ output = analyze_snapshot (entries )
63
+ hhi_calls .append (call (entries [:1 ], circulation ))
64
+ assert compute_hhi_mock .call_args_list == hhi_calls
113
65
assert output == {'top-1_absolute exclude_below_fees exclude_contracts hhi' : 3 }
114
66
115
67
get_top_limit_value_mock .return_value = 0
116
-
117
68
compute_hhi_mock .return_value = 4
118
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
69
+ output = analyze_snapshot (entries )
70
+ hhi_calls .append (call (entries , circulation ))
71
+ assert compute_hhi_mock .call_args_list == hhi_calls
119
72
assert output == {'exclude_below_fees exclude_contracts hhi' : 4 }
120
73
121
74
get_top_limit_type_mock .return_value = 'percentage'
122
75
get_top_limit_value_mock .return_value = 0.5
123
-
124
76
compute_hhi_mock .return_value = 5
125
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
77
+ output = analyze_snapshot (entries )
78
+ hhi_calls .append (call (entries [:int (len (entries )* 0.5 )], circulation ))
79
+ assert compute_hhi_mock .call_args_list == hhi_calls
126
80
assert output == {'top-0.5_percentage exclude_below_fees exclude_contracts hhi' : 5 }
127
81
128
82
get_top_limit_value_mock .return_value = 0
83
+ get_exclude_below_usd_cent_mock .return_value = True
84
+ get_exclude_below_fees_mock .return_value = False
129
85
get_metrics_mock .return_value = ['tau=0.5' ]
130
-
131
86
compute_tau_mock .return_value = [100 , None ]
132
- output = analyze_snapshot (None , 'bitcoin' , '2010-01-01' )
133
- assert output == {'exclude_below_fees exclude_contracts tau=0.5' : 100 }
87
+ output = analyze_snapshot (entries )
88
+ assert compute_tau_mock .call_args_list == [call (entries , circulation , 0.5 )]
89
+ assert output == {'exclude_below_usd_cent exclude_contracts tau=0.5' : 100 }
134
90
135
91
136
- def test_write_csv_output (mocker ):
137
- get_metrics_mock = mocker .patch ('tokenomics_decentralization.helper.get_metrics' )
138
- get_metrics_mock .return_value = ['hhi' ]
139
-
140
- get_output_directories_mock = mocker .patch ('tokenomics_decentralization.helper.get_output_directories' )
141
- get_output_directories_mock .return_value = [pathlib .Path (__file__ ).resolve ().parent ]
142
-
143
- get_clustering_mock = mocker .patch ('tokenomics_decentralization.helper.get_clustering_flag' )
144
- get_exclude_contracts_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_contracts_flag' )
92
+ def test_get_entries (mocker ):
145
93
get_exclude_below_fees_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_fees_flag' )
146
- get_exclude_below_usd_cent_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_usd_cent_flag' )
147
- get_top_limit_type_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_type' )
148
- get_top_limit_value_mock = mocker .patch ('tokenomics_decentralization.helper.get_top_limit_value' )
149
-
150
- get_clustering_mock .return_value = True
151
- get_exclude_contracts_mock .return_value = False
152
94
get_exclude_below_fees_mock .return_value = False
95
+ get_exclude_below_usd_cent_mock = mocker .patch ('tokenomics_decentralization.helper.get_exclude_below_usd_cent_flag' )
153
96
get_exclude_below_usd_cent_mock .return_value = False
154
- get_top_limit_type_mock .return_value = 'absolute'
155
- get_top_limit_value_mock .return_value = 0
156
97
157
- write_csv_output ([
158
- ['bitcoin' , '2010-01-01' , True , False , 'absolute' , 0 , False , False , 100 ],
159
- ['ethereum' , '2010-01-01' , True , False , 'absolute' , 0 , False , False , 200 ],
160
- ])
161
- with open (pathlib .Path (__file__ ).resolve ().parent / 'output.csv' ) as f :
162
- lines = f .readlines ()
163
- assert lines [0 ] == ',' .join (['ledger' , 'snapshot_date' , 'clustering' , 'exclude_contract_addresses' ,
164
- 'top_limit_type' , 'top_limit_value' , 'exclude_below_fees' ,
165
- 'exclude_below_usd_cent' , 'hhi' ]) + '\n '
166
- assert lines [1 ] == ',' .join (['bitcoin' , '2010-01-01' , 'True' , 'False' , 'absolute' , '0' , 'False' , 'False' ,
167
- '100' ]) + '\n '
168
- assert lines [2 ] == ',' .join (['ethereum' , '2010-01-01' , 'True' , 'False' , 'absolute' , '0' , 'False' , 'False' ,
169
- '200' ]) + '\n '
170
- os .remove (pathlib .Path (__file__ ).resolve ().parent / 'output.csv' )
98
+ get_median_tx_fee_mock = mocker .patch ('tokenomics_decentralization.helper.get_median_tx_fee' )
99
+ get_median_tx_fee_mock .return_value = 0
100
+ get_usd_cent_equivalent_mock = mocker .patch ('tokenomics_decentralization.helper.get_usd_cent_equivalent' )
101
+ get_usd_cent_equivalent_mock .return_value = 0
171
102
172
- get_clustering_mock . return_value = False
173
- get_exclude_contracts_mock .return_value = True
174
- get_exclude_below_fees_mock . return_value = True
175
- get_top_limit_type_mock . return_value = 'absolute'
176
- get_top_limit_value_mock .return_value = 10
177
-
178
- write_csv_output ([
179
- [ 'bitcoin' , '2010-01-01' , False , False , 'absolute' , 0 , False , False , 100 ],
180
- [ 'ethereum' , '2010-01-01' , False , False , 'absolute' , 0 , False , False , 200 ],
181
- ] )
182
- with open ( pathlib . Path ( __file__ ). resolve (). parent / 'output-no_clustering-exclude_contract_addresses-absolute_10-exclude_below_fees.csv' ) as f :
183
- lines = f . readlines ( )
184
- assert lines [ 0 ] == ',' . join ([ 'ledger' , 'snapshot_date' , 'clustering' , 'exclude_contract_addresses' ,
185
- 'top_limit_type' , 'top_limit_value' , 'exclude_below_fees ' ,
186
- 'exclude_below_usd_cent' , 'hhi' ]) + ' \n '
187
- assert lines [ 1 ] == ',' . join ([ 'bitcoin' , '2010-01-01' , 'False' , 'False' , 'absolute' , '0' , 'False' , 'False' ,
188
- '100' ]) + ' \n '
189
- assert lines [ 2 ] == ',' . join ([ 'ethereum ' , '2010-01-01' , 'False' , 'False' , 'absolute' , '0' , 'False' , 'False' ,
190
- '200' ]) + ' \n '
191
- os . remove ( pathlib . Path ( __file__ ). resolve (). parent / 'output-no_clustering-exclude_contract_addresses-absolute_10-exclude_below_fees.csv' )
103
+ get_db_connector_mock = mocker . patch ( 'tokenomics_decentralization.db_helper.get_connector' )
104
+ get_db_connector_mock .return_value = 'connector'
105
+
106
+ get_special_addresses_mock = mocker . patch ( 'tokenomics_decentralization.helper.get_special_addresses' )
107
+ get_special_addresses_mock .return_value = set ([ 'addr2' ])
108
+
109
+ get_db_filename_mock = mocker . patch ( 'tokenomics_decentralization.db_helper.get_db_filename' )
110
+ get_db_filename_mock . return_value = 'bitcoin_Test.db'
111
+
112
+ mocker . patch ( 'builtins.open' , mocker . mock_open ( read_data = 'address,balance \n addr1,1 \n addr2,2' ) )
113
+
114
+ get_address_entity_mock = mocker . patch ( 'tokenomics_decentralization.db_helper.get_address_entity' )
115
+ get_address_entity_mock . side_effect = {
116
+ 'addr1' : 'entity1 ' ,
117
+ 'addr2' : 'entity2' ,
118
+ }. get
119
+
120
+ entries = get_entries ( 'bitcoin ' , '2010-01-01' , 'test_filename' )
121
+ assert entries == [( 1 ,)]
122
+ assert get_db_connector_mock . call_args_list == [ call ( 'bitcoin_Test.db' )]
192
123
193
124
194
125
def test_analyze (mocker ):
195
- get_output_directories_mock = mocker .patch ('tokenomics_decentralization.helper.get_output_directories ' )
196
- get_output_directories_mock .return_value = [pathlib .Path (__file__ ).resolve (). parent ]
126
+ get_input_directories_mock = mocker .patch ('tokenomics_decentralization.helper.get_input_directories ' )
127
+ get_input_directories_mock .return_value = [pathlib .Path ('/' ).resolve ()]
197
128
198
129
is_file_mock = mocker .patch ('os.path.isfile' )
199
- is_file_mock .return_value = True
200
-
201
- get_db_connector_mock = mocker .patch ('tokenomics_decentralization.analyze.get_connector' )
130
+ is_file_mock .side_effect = {
131
+ pathlib .Path ('/bitcoin_2010-01-01_raw_data.csv' ).resolve (): True ,
132
+ pathlib .Path ('/bitcoin_2011-01-01_raw_data.csv' ).resolve (): False ,
133
+ pathlib .Path ('/ethereum_2010-01-01_raw_data.csv' ).resolve (): False ,
134
+ pathlib .Path ('/ethereum_2011-01-01_raw_data.csv' ).resolve (): True ,
135
+ }.get
136
+
137
+ get_db_connector_mock = mocker .patch ('tokenomics_decentralization.db_helper.get_connector' )
202
138
get_db_connector_mock .return_value = 'connector'
203
139
140
+ get_entries_mock = mocker .patch ('tokenomics_decentralization.analyze.get_entries' )
141
+ entries = [(1 , ), (2 , )]
142
+ get_entries_mock .return_value = entries
143
+
204
144
analyze_snapshot_mock = mocker .patch ('tokenomics_decentralization.analyze.analyze_snapshot' )
205
145
analyze_snapshot_mock .return_value = {'hhi' : 1 }
206
146
207
- write_csv_output_mock = mocker .patch ('tokenomics_decentralization.analyze.write_csv_output' )
208
- write_csv_output_mock .return_value = None
209
-
210
- get_output_row_mock = mocker .patch ('tokenomics_decentralization.analyze.get_output_row' )
147
+ get_output_row_mock = mocker .patch ('tokenomics_decentralization.helper.get_output_row' )
211
148
get_output_row_mock .return_value = 'row'
212
149
213
- output_rows = analyze (['bitcoin' ], ['2010-01-01' ])
214
- assert output_rows == ['row' ]
215
- analyze_snapshot_mock .assert_called_with ('connector' , 'bitcoin' , '2010-01-01' )
216
-
217
- output_rows = analyze (['bitcoin' , 'ethereum' ], ['2010-01-01' , '2011-01-01' ])
218
- assert output_rows == ['row' , 'row' , 'row' , 'row' ]
219
-
220
- is_file_mock .return_value = False
221
- output_rows = analyze (['bitcoin' , 'ethereum' ], ['2010-01-01' , '2011-01-01' ])
222
- assert output_rows == []
150
+ write_csv_output_mock = mocker .patch ('tokenomics_decentralization.helper.write_csv_output' )
151
+
152
+ get_input_dirs_calls = []
153
+ get_entries_calls = []
154
+ analyze_snapshot_calls = []
155
+ get_row_calls = []
156
+ write_output_calls = []
157
+
158
+ analyze (['bitcoin' ], ['2010-01-01' ])
159
+ get_input_dirs_calls .append (call ())
160
+ assert get_input_directories_mock .call_args_list == get_input_dirs_calls
161
+ get_entries_calls .append (call ('bitcoin' , '2010-01-01' , pathlib .Path ('/bitcoin_2010-01-01_raw_data.csv' ).resolve ()))
162
+ assert get_entries_mock .call_args_list == get_entries_calls
163
+ analyze_snapshot_calls .append (call (entries ))
164
+ assert analyze_snapshot_mock .call_args_list == analyze_snapshot_calls
165
+ get_row_calls .append (call ('bitcoin' , '2010-01-01' , {'hhi' : 1 }))
166
+ assert get_output_row_mock .call_args_list == get_row_calls
167
+ write_output_calls .append (call (['row' ]))
168
+ assert write_csv_output_mock .call_args_list == write_output_calls
169
+
170
+ analyze (['bitcoin' , 'ethereum' ], ['2010-01-01' , '2011-01-01' ])
171
+ get_input_dirs_calls += 4 * [call ()]
172
+ assert get_input_directories_mock .call_args_list == get_input_dirs_calls
173
+ get_entries_calls .append (call ('bitcoin' , '2010-01-01' , pathlib .Path ('/bitcoin_2010-01-01_raw_data.csv' ).resolve ()))
174
+ get_entries_calls .append (call ('ethereum' , '2011-01-01' , pathlib .Path ('/ethereum_2011-01-01_raw_data.csv' ).resolve ()))
175
+ assert get_entries_mock .call_args_list == get_entries_calls
176
+ analyze_snapshot_calls += 2 * [call (entries )]
177
+ assert analyze_snapshot_mock .call_args_list == analyze_snapshot_calls
178
+ get_row_calls .append (call ('bitcoin' , '2010-01-01' , {'hhi' : 1 }))
179
+ get_row_calls .append (call ('ethereum' , '2011-01-01' , {'hhi' : 1 }))
180
+ assert get_output_row_mock .call_args_list == get_row_calls
181
+ write_output_calls .append (call (['row' , 'row' ]))
182
+ assert write_csv_output_mock .call_args_list == write_output_calls
0 commit comments