7
7
import json
8
8
import os
9
9
import base64
10
+ import gzip
10
11
from molotov import scenario , setup , global_setup , teardown , global_teardown
11
12
from molotov import set_var , get_var
12
13
27
28
# This is the various file sizes we'll generate in the global setup.
28
29
_FILE_SIZES = (1 , 10 , 50 )
29
30
31
+ # These are gzip-compressed chunks of json that we'll concatenate later to
32
+ # generate our payload. This takes advantage that a gzip stream is made of
33
+ # concatenated gzip chunks.
34
+ _COMPRESSED_JSON_PREFIX = gzip .compress (b'{"foo":"' )
35
+ _COMPRESSED_JSON_SUFFIX = gzip .compress (b'"}' )
36
+
30
37
31
38
def setup_api_endpoint ():
32
39
"""Sets up the _API global that we use in all scenarii.
@@ -63,7 +70,11 @@ def test_starts(args):
63
70
* we generate the various files to be sent in the tests.
64
71
"""
65
72
setup_api_endpoint ()
66
- files = {x : os .urandom (x * 1024 ) for x in _FILE_SIZES }
73
+ # "512" instead of "1024" because writing in hexadecimal takes 2 bytes.
74
+ files = {x : gzip .compress (
75
+ os .urandom (x * 512 ).hex ().encode (),
76
+ compresslevel = 0 )
77
+ for x in _FILE_SIZES }
67
78
set_var ("files" , files )
68
79
69
80
@@ -132,6 +143,25 @@ def jwt_base64_decode(payload):
132
143
return decoded_str
133
144
134
145
146
+ def payload_from_raw_data (raw_data ):
147
+ """Returns a data suitable to publish, that's accepted by the profiler server.
148
+
149
+ This concatenates separate pre-created gzip-compressed chunks, because we
150
+ want that we do as less work as possible at runtime. Here at runtime we
151
+ only compress a very small chunk and otherwise concatenate everything.
152
+ """
153
+ # By adding some random bytes, the content will change for each test and
154
+ # therefore the filename too. This prevents google from erroring while we
155
+ # stress test.
156
+ unique_data = gzip .compress (os .urandom (10 ).hex ().encode (), compresslevel = 0 )
157
+ return (
158
+ _COMPRESSED_JSON_PREFIX +
159
+ raw_data +
160
+ unique_data +
161
+ _COMPRESSED_JSON_SUFFIX
162
+ )
163
+
164
+
135
165
async def publish (session , data_size ):
136
166
"""Publishes a profile with the passed data size
137
167
"""
@@ -144,10 +174,7 @@ async def publish(session, data_size):
144
174
)
145
175
146
176
data = get_var ('files' )[data_size ]
147
- # By adding some random bytes, the content will change for each test and
148
- # therefore the filename too. This prevents google from erroring while we
149
- # stress test.
150
- data = data + os .urandom (10 )
177
+ data = payload_from_raw_data (data )
151
178
152
179
async with session .post (_API + '/compressed-store' , data = data ) as resp :
153
180
assert resp .status == 200
@@ -173,6 +200,12 @@ async def delete(session, jwt_token):
173
200
174
201
# Each scenario has a weight. Molotov uses it to determine how often the
175
202
# scenario is picked.
203
+ @scenario (1 )
204
+ async def publish_and_delete (session ):
205
+ jwt_token = await publish (session = session , data_size = 10 )
206
+ await delete (session = session , jwt_token = jwt_token )
207
+
208
+
176
209
@scenario (2 )
177
210
async def publish_1k (session ):
178
211
await publish (session = session , data_size = 1 )
0 commit comments