Mercurial > p > roundup > code
comparison test/rest_common.py @ 7555:451232f83244
test: Modify testRestRateLimit test to report when system is too slow.
Add an explicit check on the runtime and an error message that reports
that the runtime was exceeded for the test to complete as written.
testRestRateLimit requires that it finish within 3 seconds. Otherwise
the number of remaining requests in the rate limit does not decrease
on every call. If disk I/O is high, the anydbm version of this test
can take > 3 seconds and result in a failed test.
My other alternative was to measure the runtime and adjust the test to
match the values that are returned. This seems like too much work and
is unlikely to be an issue outside of a developers under powered
system.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 18 Jul 2023 23:18:09 -0400 |
| parents | 613f822f1f24 |
| children | 978285986b2c |
comparison
equal
deleted
inserted
replaced
| 7554:27476d1fca9f | 7555:451232f83244 |
|---|---|
| 1074 # page_size < 0 | 1074 # page_size < 0 |
| 1075 # page_index < 0 | 1075 # page_index < 0 |
| 1076 | 1076 |
| 1077 def testRestRateLimit(self): | 1077 def testRestRateLimit(self): |
| 1078 | 1078 |
| 1079 self.db.config['WEB_API_CALLS_PER_INTERVAL'] = 20 | 1079 calls_per_interval = 20 |
| 1080 self.db.config['WEB_API_INTERVAL_IN_SEC'] = 60 | 1080 interval_sec = 60 |
| 1081 wait_time_str = str(int(interval_sec/calls_per_interval)) | |
| 1082 | |
| 1083 self.db.config['WEB_API_CALLS_PER_INTERVAL'] = calls_per_interval | |
| 1084 self.db.config['WEB_API_INTERVAL_IN_SEC'] = interval_sec | |
| 1081 | 1085 |
| 1082 # Otk code never passes through the | 1086 # Otk code never passes through the |
| 1083 # retry loop. Not sure why but I can force it | 1087 # retry loop. Not sure why but I can force it |
| 1084 # through the loop by setting the internal _db_type | 1088 # through the loop by setting the internal _db_type |
| 1085 # setting once the db is created by the previous command. | 1089 # setting once the db is created by the previous command. |
| 1088 except AttributeError: | 1092 except AttributeError: |
| 1089 # if dir attribute doesn't exist the primary db is not | 1093 # if dir attribute doesn't exist the primary db is not |
| 1090 # sqlite or anydbm. So don't need to exercise code. | 1094 # sqlite or anydbm. So don't need to exercise code. |
| 1091 pass | 1095 pass |
| 1092 | 1096 |
| 1093 print("Now realtime start:", datetime.utcnow()) | 1097 start_time = datetime.utcnow() |
| 1094 # don't set an accept header; json should be the default | 1098 # don't set an accept header; json should be the default |
| 1095 # use up all our allowed api calls | 1099 # use up all our allowed api calls |
| 1096 for i in range(20): | 1100 for i in range(calls_per_interval): |
| 1097 # i is 0 ... 19 | 1101 # i is 0 ... calls_per_interval |
| 1098 self.client_error_message = [] | 1102 self.client_error_message = [] |
| 1099 self.server.client.env.update({'REQUEST_METHOD': 'GET'}) | 1103 self.server.client.env.update({'REQUEST_METHOD': 'GET'}) |
| 1100 results = self.server.dispatch('GET', | 1104 results = self.server.dispatch('GET', |
| 1101 "/rest/data/user/%s/realname"%self.joeid, | 1105 "/rest/data/user/%s/realname"%self.joeid, |
| 1102 self.empty_form) | 1106 self.empty_form) |
| 1103 | 1107 |
| 1108 loop_time = datetime.utcnow() | |
| 1109 self.assertLess((loop_time-start_time).total_seconds(), | |
| 1110 int(wait_time_str), | |
| 1111 "Test system is too slow to complete test as configured") | |
| 1112 | |
| 1104 # is successful | 1113 # is successful |
| 1105 self.assertEqual(self.server.client.response_code, 200) | 1114 self.assertEqual(self.server.client.response_code, 200) |
| 1106 # does not have Retry-After header as we have | 1115 # does not have Retry-After header as we have |
| 1107 # suceeded with this query | 1116 # suceeded with this query |
| 1108 self.assertFalse("Retry-After" in | 1117 self.assertFalse("Retry-After" in |
| 1134 self.assertAlmostEqual( | 1143 self.assertAlmostEqual( |
| 1135 float(self.server.client.additional_headers["X-RateLimit-Reset"]), | 1144 float(self.server.client.additional_headers["X-RateLimit-Reset"]), |
| 1136 59, delta=5) | 1145 59, delta=5) |
| 1137 self.assertEqual( | 1146 self.assertEqual( |
| 1138 str(self.server.client.additional_headers["Retry-After"]), | 1147 str(self.server.client.additional_headers["Retry-After"]), |
| 1139 "3") # check as string | 1148 wait_time_str) # check as string |
| 1140 | 1149 |
| 1141 print("Reset:", self.server.client.additional_headers["X-RateLimit-Reset"]) | 1150 print("Reset:", self.server.client.additional_headers["X-RateLimit-Reset"]) |
| 1142 print("Now realtime pre-sleep:", datetime.utcnow()) | 1151 print("Now realtime pre-sleep:", datetime.utcnow()) |
| 1143 sleep(3.1) # sleep as requested so we can do another login | 1152 # sleep as requested so we can do another login |
| 1153 sleep(float(wait_time_str) + 0.1) | |
| 1144 print("Now realtime post-sleep:", datetime.utcnow()) | 1154 print("Now realtime post-sleep:", datetime.utcnow()) |
| 1145 | 1155 |
| 1146 # this should succeed | 1156 # this should succeed |
| 1147 self.server.client.additional_headers.clear() | 1157 self.server.client.additional_headers.clear() |
| 1148 results = self.server.dispatch('GET', | 1158 results = self.server.dispatch('GET', |
| 1179 self.empty_form) | 1189 self.empty_form) |
| 1180 | 1190 |
| 1181 self.assertEqual(self.server.client.response_code, 429) | 1191 self.assertEqual(self.server.client.response_code, 429) |
| 1182 self.assertEqual( | 1192 self.assertEqual( |
| 1183 str(self.server.client.additional_headers["Retry-After"]), | 1193 str(self.server.client.additional_headers["Retry-After"]), |
| 1184 "3") # check as string | 1194 wait_time_str) # check as string |
| 1185 | 1195 |
| 1186 json_dict = json.loads(b2s(results)) | 1196 json_dict = json.loads(b2s(results)) |
| 1187 self.assertEqual(json_dict['error']['msg'], | 1197 self.assertEqual( |
| 1188 "Api rate limits exceeded. Please wait: 3 seconds.") | 1198 json_dict['error']['msg'], |
| 1199 "Api rate limits exceeded. Please wait: %s seconds." % | |
| 1200 wait_time_str) | |
| 1189 | 1201 |
| 1190 # reset rest params | 1202 # reset rest params |
| 1191 self.db.config['WEB_API_CALLS_PER_INTERVAL'] = 0 | 1203 self.db.config['WEB_API_CALLS_PER_INTERVAL'] = 0 |
| 1192 self.db.config['WEB_API_INTERVAL_IN_SEC'] = 3600 | 1204 self.db.config['WEB_API_INTERVAL_IN_SEC'] = 3600 |
| 1193 | 1205 |
