7
7
from cosmpy .aerial .tx_helpers import SubmittedTx
8
8
from gql import gql
9
9
10
- from src .genesis .helpers .field_enums import Agents , AlmanacRecords , AlmanacRegistrations
10
+ from src .genesis .helpers .field_enums import (
11
+ Agents ,
12
+ AlmanacRecords ,
13
+ AlmanacRegistrations ,
14
+ AlmanacResolutions ,
15
+ )
11
16
from tests .helpers .contracts import AlmanacContract , DefaultAlmanacContractConfig
12
17
from tests .helpers .entity_test import EntityTest
13
18
from tests .helpers .graphql import filtered_test_query
14
19
from tests .helpers .regexes import block_id_regex , msg_id_regex , tx_id_regex
15
20
from uagents .src .nexus .crypto import Identity
16
21
17
22
23
+ def gql_by_endpoint_port (resolution_node : Dict ) -> int :
24
+ return int (resolution_node ["record" ]["service" ]["endpoints" ][0 ]["url" ][- 4 :])
25
+
26
+
18
27
def gql_by_expiry_height (registration_node : Dict ) -> int :
19
28
return int (registration_node ["expiryHeight" ])
20
29
@@ -32,13 +41,14 @@ class Scenario:
32
41
33
42
class TestAlmanac (EntityTest ):
34
43
test_registrations_endpoints = [
35
- "127.0.0.1:9999" ,
36
- "127.0.0.1:8888" ,
37
- "127.0.0.1:7777" ,
38
44
"127.0.0.1:6666" ,
45
+ "127.0.0.1:7777" ,
46
+ "127.0.0.1:8888" ,
47
+ "127.0.0.1:9999" ,
39
48
]
40
49
submitted_txs : List [SubmittedTx ] = []
41
50
expected_registrations : List [Dict ] = []
51
+ expected_resolutions : List [Dict ] = []
42
52
expected_records : List [Dict ] = [
43
53
{
44
54
"service" : {
@@ -92,16 +102,114 @@ def setUpClass(cls):
92
102
cls .expected_registrations .append (
93
103
{
94
104
"agentId" : agent_address ,
105
+ "contractId" : str (cls ._contract .address ),
95
106
"expiryHeight" : tx .response .height
96
107
+ DefaultAlmanacContractConfig .expiry_height ,
97
108
"sequence" : sequence ,
98
109
"signature" : signature ,
99
110
"record" : expected_record ,
100
111
}
101
112
)
113
+ cls .expected_resolutions .append (
114
+ {
115
+ "agentId" : agent_address ,
116
+ "contractId" : str (cls ._contract .address ),
117
+ "record" : expected_record ,
118
+ }
119
+ )
102
120
# NB: wait for the indexer
103
121
time .sleep (7 )
104
122
123
+ # NB: test resolutions first as it's sensitive to the current height
124
+ def test_resolutions_sql (self ):
125
+ resolutions = self .db_cursor .execute (
126
+ AlmanacResolutions .select_query ()
127
+ ).fetchall ()
128
+ actual_resolution_count = len (resolutions )
129
+
130
+ current_height = int (
131
+ self .db_cursor .execute (
132
+ """SELECT b.height FROM app.blocks b
133
+ ORDER BY b.height
134
+ LIMIT 1"""
135
+ ).fetchone ()[0 ]
136
+ )
137
+
138
+ last_expired_height = (
139
+ current_height - DefaultAlmanacContractConfig .expiry_height
140
+ )
141
+ first_unexpired = next (
142
+ tx for tx in self .submitted_txs if tx .response .height >= last_expired_height
143
+ )
144
+ last_expired_index = self .submitted_txs .index (first_unexpired ) - 1
145
+ expected_resolutions = resolutions [last_expired_index + 1 :]
146
+ expected_resolutions_count = len (expected_resolutions )
147
+
148
+ self .assertEqual (expected_resolutions_count , actual_resolution_count )
149
+ # TODO: more assertions
150
+
151
+ def test_resolutions_gql (self ):
152
+ resolutions_query = gql (
153
+ """
154
+ query {
155
+ almanacResolutions {
156
+ nodes {
157
+ id
158
+ agentId
159
+ contractId
160
+ record {
161
+ id
162
+ service
163
+ # registrationId
164
+ # eventId
165
+ transactionId
166
+ blockId
167
+ }
168
+ }
169
+ }
170
+ }
171
+ """
172
+ )
173
+
174
+ current_height = int (
175
+ self .db_cursor .execute (
176
+ """SELECT b.height FROM app.blocks b
177
+ ORDER BY b.height DESC
178
+ LIMIT 1"""
179
+ ).fetchone ()[0 ]
180
+ )
181
+ last_expired_height = (
182
+ current_height - DefaultAlmanacContractConfig .expiry_height
183
+ )
184
+ first_unexpired = next (
185
+ r for r in self .submitted_txs if r .response .height > last_expired_height
186
+ )
187
+ first_unexpired_index = self .submitted_txs .index (first_unexpired )
188
+ expected_resolutions = self .expected_resolutions [first_unexpired_index :]
189
+
190
+ gql_result = self .gql_client .execute (resolutions_query )
191
+ resolutions = gql_result ["almanacResolutions" ]["nodes" ]
192
+ self .assertEqual (len (expected_resolutions ), len (resolutions ))
193
+
194
+ # TODO: use respective gql order by when available
195
+ # NB: sort by expiry height so that indexes match
196
+ # their respective expected_resolutions index
197
+ list .sort (resolutions , key = gql_by_endpoint_port )
198
+ self .assertEqual (len (expected_resolutions ), len (resolutions ))
199
+
200
+ for (i , resolution ) in enumerate (resolutions ):
201
+ self .assertRegex (resolution ["id" ], msg_id_regex )
202
+ self .assertEqual (expected_resolutions [i ]["agentId" ], resolution ["agentId" ])
203
+ self .assertEqual (str (self ._contract .address ), resolution ["contractId" ])
204
+ record = resolution ["record" ]
205
+ self .assertEqual (
206
+ record ["service" ],
207
+ resolution ["record" ]["service" ],
208
+ )
209
+ self .assertRegex (record ["transactionId" ], tx_id_regex )
210
+ self .assertRegex (record ["blockId" ], block_id_regex )
211
+ # TODO: assert record equality
212
+
105
213
def test_registrations_sql (self ):
106
214
registrations = self .db_cursor .execute (
107
215
AlmanacRegistrations .select_query ()
@@ -254,22 +362,6 @@ def test_registrations_gql(self):
254
362
self .assertRegex (registration ["blockId" ], block_id_regex )
255
363
# TODO: assert record equality
256
364
257
- # GQL query
258
- # - historical registrations: where expired
259
- # - resolutions success
260
- # - resolutions expired (empty result)
261
- # assertions
262
-
263
- def test_resolutions_sql (self ):
264
- pass
265
- # SQL query
266
- # assertions
267
-
268
- def test_resolutions_gql (self ):
269
- pass
270
- # GQL query
271
- # assertions
272
-
273
365
274
366
if __name__ == "__main__" :
275
367
unittest .main ()
0 commit comments