test_system.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. # import asyncio
  2. # import uuid
  3. # import pytest
  4. # import time
  5. # from datetime import datetime
  6. # from r2r import R2RClient, R2RException, LimitSettings
  7. # async def test_health_endpoint(aclient):
  8. # """Test health endpoint is accessible and not rate limited"""
  9. # # Health endpoint doesn't require authentication
  10. # for _ in range(20): # Well above our global limit
  11. # response = await aclient.system.health()
  12. # assert response["results"]["message"] == "ok"
  13. # async def test_system_status(aclient, config):
  14. # """Test system status endpoint returns correct data"""
  15. # # Login as superuser for system status
  16. # await aclient.users.login(config.superuser_email, config.superuser_password)
  17. # response = await aclient.system.status()
  18. # stats = response["results"]
  19. # assert isinstance(stats["start_time"], str)
  20. # assert isinstance(stats["uptime_seconds"], (int, float))
  21. # assert isinstance(stats["cpu_usage"], (int, float))
  22. # assert isinstance(stats["memory_usage"], (int, float))
  23. # datetime.fromisoformat(stats["start_time"])
  24. # async def test_per_minute_route_limit(aclient, test_collection):
  25. # """Test route-specific per-minute limit for search endpoint"""
  26. # # Create and login as new user
  27. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  28. # test_pass = "test_password"
  29. # await aclient.users.register(test_user, test_pass)
  30. # await aclient.users.login(test_user, test_pass)
  31. # # Should succeed for first 5 requests (route_per_min limit)
  32. # for i in range(5):
  33. # # use `search` route which is at `per_route_limit: 5` in `test_limits` config
  34. # response = await aclient.retrieval.search(
  35. # f"test query {i}",
  36. # )
  37. # assert "results" in response
  38. # # Next request should fail with rate limit error
  39. # with pytest.raises(R2RException) as exc_info:
  40. # await aclient.retrieval.search(
  41. # "over limit query",
  42. # )
  43. # assert "rate limit" in str(exc_info.value).lower()
  44. # await aclient.users.logout()
  45. # async def test_global_per_minute_limit(aclient, test_collection):
  46. # """Test global per-minute limit"""
  47. # # Create and login as new user
  48. # # email, _ = create_test_user()
  49. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  50. # test_pass = "test_password"
  51. # await aclient.users.register(test_user, test_pass)
  52. # await aclient.users.login(test_user, test_pass)
  53. # # Make requests up to global limit
  54. # for i in range(25):
  55. # try:
  56. # # use `me` route which is at `global_limit` in `test_limits` config
  57. # result = await aclient.users.me()
  58. # except R2RException as e:
  59. # if "rate limit" not in str(e).lower():
  60. # raise # Re-raise if it's not a rate limit exception
  61. # # Verify global limit is enforced
  62. # with pytest.raises(R2RException) as exc_info:
  63. # await aclient.users.me()
  64. # assert "rate limit" in str(exc_info.value).lower()
  65. # await aclient.users.logout()
  66. # async def test_global_per_minute_limit_split(aclient, test_collection):
  67. # """Test global per-minute limit"""
  68. # # Create and login as new user
  69. # # email, _ = create_test_user()
  70. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  71. # test_pass = "test_password"
  72. # await aclient.users.register(test_user, test_pass)
  73. # await aclient.users.login(test_user, test_pass)
  74. # # Make requests up to global limit
  75. # for i in range(10): ## ramp up to 20 total queries
  76. # try:
  77. # # use `me` route which is at `global_limit` in `test_limits` config
  78. # await aclient.users.me()
  79. # await aclient.retrieval.search("whoami?")
  80. # except R2RException as e:
  81. # if "rate limit" not in str(e).lower():
  82. # raise # Re-raise if it's not a rate limit exception
  83. # # Verify global limit is enforced
  84. # with pytest.raises(R2RException) as exc_info:
  85. # await aclient.users.me()
  86. # assert "rate limit" in str(exc_info.value).lower()
  87. # await aclient.users.logout()
  88. # ## TOO SLOW
  89. # # def test_route_monthly_limit(client, test_collection):
  90. # # """Test route-specific monthly limit for search endpoint"""
  91. # # # Create and login as new user
  92. # # test_user = f"test_user_{uuid.uuid4()}@example.com"
  93. # # test_pass = "test_password"
  94. # # client.users.register(test_user, test_pass)
  95. # # client.users.login(test_user, test_pass)
  96. # # # Make requests up to route monthly limit
  97. # # for i in range(5): # route_per_month limit
  98. # # response = client.retrieval.search(
  99. # # f"monthly test query {i}",
  100. # # )
  101. # # assert "results" in response
  102. # # time.sleep(61) # Avoid per-minute limits
  103. # # # Make requests up to route monthly limit
  104. # # for i in range(5): # route_per_month limit
  105. # # response = client.retrieval.search(
  106. # # f"monthly test query {i}",
  107. # # )
  108. # # assert "results" in response
  109. # # time.sleep(61) # Avoid per-minute limits
  110. # # # Next request should fail with monthly limit error
  111. # # with pytest.raises(R2RException) as exc_info:
  112. # # client.retrieval.search(
  113. # # "over monthly limit query",
  114. # # )
  115. # # assert "monthly" in str(exc_info.value).lower()
  116. # # client.users.logout()
  117. # async def test_non_superuser_system_access(aclient):
  118. # """Test system endpoint access control"""
  119. # # Create and login as regular user
  120. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  121. # test_pass = "test_password"
  122. # await aclient.users.register(test_user, test_pass)
  123. # await aclient.users.login(test_user, test_pass)
  124. # # Health should be accessible
  125. # response = await aclient.system.health()
  126. # assert response["results"]["message"] == "ok"
  127. # # Other endpoints should be restricted
  128. # for endpoint in [
  129. # lambda: aclient.system.status(),
  130. # lambda: aclient.system.settings(),
  131. # lambda: aclient.system.logs(),
  132. # ]:
  133. # with pytest.raises(R2RException) as exc_info:
  134. # await endpoint()
  135. # # assert exc_info.value.status_code == 403
  136. # async def test_limit_reset(aclient, test_collection):
  137. # """Test that per-minute limits reset after one minute"""
  138. # # Create and login as new user
  139. # # Create and login as new user
  140. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  141. # test_pass = "test_password"
  142. # await aclient.users.register(test_user, test_pass)
  143. # await aclient.users.login(test_user, test_pass)
  144. # # Use up the route limit
  145. # for _ in range(5):
  146. # await aclient.retrieval.search(
  147. # "test query",
  148. # )
  149. # print('going sleepy sweep now...')
  150. # t = datetime.now()
  151. # # Wait for reset
  152. # # time.sleep(62)
  153. # await asyncio.sleep(70)
  154. # print('wakey wakey')
  155. # print('dt = ', datetime.now() - t)
  156. # # Should be able to make requests again
  157. # response = await aclient.retrieval.search(
  158. # "test query after reset",
  159. # )
  160. # assert "results" in response
  161. # ## THIS FAILS, BUT WE ARE OK WITH THIS EDGE CASE
  162. # # async def test_concurrent_requests(aclient, test_collection):
  163. # # """Test concurrent requests properly handle rate limits"""
  164. # # # Create and login as new user
  165. # # # Create and login as new user
  166. # # test_user = f"test_user_{uuid.uuid4()}@example.com"
  167. # # test_pass = "test_password"
  168. # # await aclient.users.register(test_user, test_pass)
  169. # # await aclient.users.login(test_user, test_pass)
  170. # # import asyncio
  171. # # tasks = []
  172. # # for i in range(10):
  173. # # tasks.append(aclient.retrieval.search(f"concurrent query {i}"))
  174. # # results = await asyncio.gather(*tasks, return_exceptions=True)
  175. # # success_count = sum(1 for r in results if isinstance(r, dict))
  176. # # assert success_count <= 5 # route_per_min limit
  177. # async def test_user_specific_limits(aclient, config):
  178. # """Test user-specific limit overrides"""
  179. # # Create and login as new user
  180. # test_user = f"test_user_specific_harcoded@example.com"
  181. # test_pass = "test_password"
  182. # await aclient.users.register(test_user, test_pass)
  183. # await aclient.users.login(test_user, test_pass)
  184. # me = await aclient.users.me()
  185. # print("me = ", me)
  186. # # Configure user-specific limits
  187. # # SET INSIDE THE CONFIG
  188. # # user_id = client.users.me().results.id
  189. # # config.user_limits[user_id] = LimitSettings(
  190. # # global_per_min=2,
  191. # # route_per_min=1
  192. # # )
  193. # # Verify user's custom limits are enforced
  194. # for i in range(3):
  195. # try:
  196. # await aclient.retrieval.search(f"test query {i}")
  197. # if i >= 2:
  198. # assert False, "Should have raised exception"
  199. # except R2RException as e:
  200. # assert "rate limit" in str(e).lower()
  201. # assert i >= 1 # Should fail after first request
  202. # break
  203. # async def test_global_monthly_limit(aclient, test_collection):
  204. # """Test global monthly limit across all routes"""
  205. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  206. # test_pass = "test_password"
  207. # await aclient.users.register(test_user, test_pass)
  208. # await aclient.users.login(test_user, test_pass)
  209. # # Make requests up to global monthly limit (20)
  210. # for i in range(10):
  211. # if i % 2 == 0:
  212. # response = await aclient.users.me()
  213. # else:
  214. # response = await aclient.retrieval.search(f"test query {i}")
  215. # await asyncio.sleep(61) # Avoid per-minute limits
  216. # for i in range(10):
  217. # if i % 2 == 0:
  218. # response = await aclient.users.me()
  219. # else:
  220. # response = await aclient.retrieval.search(f"test query {i}")
  221. # await asyncio.sleep(61) # Avoid per-minute limits
  222. # # Next request should fail with monthly limit error
  223. # with pytest.raises(R2RException) as exc_info:
  224. # await aclient.users.me()
  225. # assert "monthly" in str(exc_info.value).lower()
  226. # async def test_mixed_limits(aclient, test_collection):
  227. # """Test interaction between different types of limits"""
  228. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  229. # test_pass = "test_password"
  230. # await aclient.users.register(test_user, test_pass)
  231. # await aclient.users.login(test_user, test_pass)
  232. # # Hit route-specific limit first
  233. # for i in range(5):
  234. # await aclient.retrieval.search(f"test query {i}")
  235. # # Try different route to test global limit still applies
  236. # with pytest.raises(R2RException) as exc_info:
  237. # for i in range(10):
  238. # await aclient.users.me()
  239. # assert "rate limit" in str(exc_info.value).lower()
  240. # async def test_route_limit_inheritance(aclient, test_collection):
  241. # """Test that routes without specific limits inherit global limits"""
  242. # test_user = f"test_user_{uuid.uuid4()}@example.com"
  243. # test_pass = "test_password"
  244. # await aclient.users.register(test_user, test_pass)
  245. # await aclient.users.login(test_user, test_pass)
  246. # # Test unspecified route (should use global limits)
  247. # for i in range(10): # global_per_min = 10
  248. # await aclient.users.me()
  249. # # Next request should hit global limit
  250. # with pytest.raises(R2RException) as exc_info:
  251. # await aclient.users.me()
  252. # assert "rate limit" in str(exc_info.value).lower()