1
1
"""Test TokenStatusList."""
2
2
3
+ import json
3
4
import pytest
5
+ from secrets import randbelow
4
6
5
7
from token_status_list import INVALID , SUSPENDED , TokenStatusList , VALID , b64url_decode
6
8
@@ -151,31 +153,44 @@ def test_performance(bits: int):
151
153
print ("Bits:" , bits )
152
154
153
155
# Create a large TokenStatusList
154
- size = 1000000 # Number of tokens
155
- token_list = TokenStatusList .of_size (bits , size )
156
+ size = 1000000 # Number of indices
157
+ status_list = TokenStatusList .of_size (bits , size )
158
+
159
+ # Generate random statuses
160
+ statuses = []
161
+ while len (statuses ) < size :
162
+ run = randbelow (10 )
163
+ status = randbelow (2 )
164
+ statuses .extend ([status ] * run )
165
+
166
+ diff = len (statuses ) - size
167
+ if diff > 1 :
168
+ for _ in range (diff + 1 ):
169
+ statuses .pop ()
156
170
157
171
# Test setting values
158
172
start_time = time .time ()
159
- for i in range ( size ):
160
- token_list [i ] = VALID if i % 2 == 0 else INVALID
173
+ for i , status in enumerate ( statuses ):
174
+ status_list [i ] = status
161
175
end_time = time .time ()
162
- print (f"Time to set { size } tokens : { end_time - start_time } seconds" )
176
+ print (f"Time to set { size } indices : { end_time - start_time :.3f } seconds" )
163
177
164
178
# Test getting values
165
179
start_time = time .time ()
166
180
for i in range (size ):
167
- status = token_list [i ]
181
+ status = status_list [i ]
168
182
end_time = time .time ()
169
- print (f"Time to get { size } tokens : { end_time - start_time } seconds" )
183
+ print (f"Time to get { size } indices : { end_time - start_time :.3f } seconds" )
170
184
171
185
# Test compression
172
186
start_time = time .time ()
173
- compressed_data = token_list .compressed ()
187
+ compressed_data = status_list .compressed ()
174
188
end_time = time .time ()
175
- print (f"Time to compress: { end_time - start_time } seconds" )
176
- print (f"Original length: { len (token_list .lst )} bytes" )
189
+ print (f"Time to compress: { end_time - start_time :.3f } seconds" )
190
+ print (f"Original length: { len (status_list .lst )} bytes" )
177
191
print (f"Compressed length: { len (compressed_data )} bytes" )
178
- print (f"Compression ratio: { len (compressed_data ) / len (token_list .lst ) * 100 :.3f} %" )
192
+ print (f"Compression ratio: { len (compressed_data ) / len (status_list .lst ) * 100 :.3f} %" )
193
+ # print(f"List in hex: {status_list.lst.hex()}")
179
194
180
195
181
196
def test_serde ():
@@ -200,3 +215,65 @@ def test_invalid_to_valid():
200
215
assert status [7 ] == INVALID
201
216
with pytest .raises (ValueError ):
202
217
status [7 ] = 0x00
218
+
219
+
220
+ def test_of_size ():
221
+ with pytest .raises (ValueError ):
222
+ status = TokenStatusList .of_size (1 , 3 )
223
+ with pytest .raises (ValueError ):
224
+ status = TokenStatusList .of_size (2 , 21 )
225
+ with pytest .raises (ValueError ):
226
+ status = TokenStatusList .of_size (4 , 31 )
227
+
228
+ # Lists with bits 8 can have arbitrary size since there's no byte
229
+ # boundaries to worry about
230
+ status = TokenStatusList .of_size (8 , 31 )
231
+ assert len (status .lst ) == 31
232
+
233
+ status = TokenStatusList .of_size (1 , 8 )
234
+ assert len (status .lst ) == 1
235
+ status = TokenStatusList .of_size (1 , 16 )
236
+ assert len (status .lst ) == 2
237
+ status = TokenStatusList .of_size (1 , 24 )
238
+ assert len (status .lst ) == 3
239
+ status = TokenStatusList .of_size (8 , 24 )
240
+ assert len (status .lst ) == 24
241
+
242
+
243
+ def test_with_at_least ():
244
+ status = TokenStatusList .with_at_least (1 , 3 )
245
+ assert len (status .lst ) == 1
246
+ status = TokenStatusList .with_at_least (2 , 21 )
247
+ assert len (status .lst ) == 6
248
+ status = TokenStatusList .with_at_least (4 , 31 )
249
+ assert len (status .lst ) == 16
250
+
251
+ status = TokenStatusList .with_at_least (1 , 8 )
252
+ assert len (status .lst ) == 1
253
+ status = TokenStatusList .with_at_least (2 , 24 )
254
+ assert len (status .lst ) == 6
255
+ status = TokenStatusList .with_at_least (4 , 32 )
256
+ assert len (status .lst ) == 16
257
+
258
+
259
+ def test_sign_payload ():
260
+ status = TokenStatusList (1 , b"\xb9 \xa3 " )
261
+ payload = status .sign_payload (
262
+ alg = "ES256" ,
263
+ kid = "12" ,
264
+ iss = "https://example.com" ,
265
+ sub = "https://example.com/statuslists/1" ,
266
+ iat = 1686920170 ,
267
+ exp = 2291720170 ,
268
+ )
269
+ headers , payload = payload .split (b"." )
270
+ headers = json .loads (b64url_decode (headers ))
271
+ payload = json .loads (b64url_decode (payload ))
272
+ assert headers == {"alg" : "ES256" , "kid" : "12" , "typ" : "statuslist+jwt" }
273
+ assert payload == {
274
+ "exp" : 2291720170 ,
275
+ "iat" : 1686920170 ,
276
+ "iss" : "https://example.com" ,
277
+ "status_list" : {"bits" : 1 , "lst" : "eNrbuRgAAhcBXQ" },
278
+ "sub" : "https://example.com/statuslists/1" ,
279
+ }
0 commit comments