test_throttling.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from datetime import timedelta
  2. from django.core import mail
  3. from django.test import TestCase, override_settings
  4. from django.utils import timezone
  5. from freezegun import freeze_time
  6. from model_bakery import baker
  7. from ..models import Organization
  8. from ..tasks import (
  9. check_all_organizations_throttle,
  10. check_organization_throttle,
  11. )
  12. class OrganizationThrottleCheckTestCase(TestCase):
  13. @classmethod
  14. def setUpTestData(cls):
  15. cls.product = baker.make(
  16. "djstripe.Product", active=True, metadata={"events": 10}
  17. )
  18. cls.plan = baker.make(
  19. "djstripe.Plan", active=True, amount=0, product=cls.product
  20. )
  21. cls.organization = baker.make("organizations_ext.Organization")
  22. cls.user = baker.make("users.user")
  23. cls.organization.add_user(cls.user)
  24. cls.customer = baker.make(
  25. "djstripe.Customer", subscriber=cls.organization, livemode=False
  26. )
  27. cls.subscription = baker.make(
  28. "djstripe.Subscription",
  29. customer=cls.customer,
  30. livemode=False,
  31. plan=cls.plan,
  32. status="active",
  33. current_period_end=timezone.now() + timedelta(hours=1),
  34. )
  35. def _make_events(self, i: int):
  36. baker.make(
  37. "projects.IssueEventProjectHourlyStatistic",
  38. project__organization=self.organization,
  39. count=i,
  40. )
  41. def _make_transaction_events(self, i: int):
  42. baker.make(
  43. "projects.TransactionEventProjectHourlyStatistic",
  44. project__organization=self.organization,
  45. count=i,
  46. )
  47. @override_settings(
  48. CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}
  49. )
  50. def test_check_organization_throttle(self):
  51. check_organization_throttle(self.organization.id)
  52. self.assertTrue(Organization.objects.filter(event_throttle_rate=0).exists())
  53. baker.make(
  54. "projects.IssueEventProjectHourlyStatistic",
  55. project__organization=self.organization,
  56. count=11,
  57. )
  58. check_organization_throttle(self.organization.id)
  59. self.organization.refresh_from_db()
  60. self.assertEqual(self.organization.event_throttle_rate, 10)
  61. self.assertEqual(len(mail.outbox), 1)
  62. baker.make(
  63. "projects.IssueEventProjectHourlyStatistic",
  64. project__organization=self.organization,
  65. count=100,
  66. )
  67. check_organization_throttle(self.organization.id)
  68. self.organization.refresh_from_db()
  69. self.assertEqual(self.organization.event_throttle_rate, 100)
  70. self.assertEqual(len(mail.outbox), 2)
  71. def test_check_all_organizations_throttle(self):
  72. org = self.organization
  73. # No events, no throttle
  74. with self.assertNumQueries(2):
  75. check_all_organizations_throttle()
  76. org.refresh_from_db()
  77. self.assertEqual(org.event_throttle_rate, 0)
  78. # 6 events (of 10), no throttle
  79. self._make_events(3)
  80. self._make_transaction_events(3)
  81. check_all_organizations_throttle()
  82. org.refresh_from_db()
  83. self.assertEqual(org.event_throttle_rate, 0)
  84. self.assertEqual(len(mail.outbox), 0)
  85. # 11 events (of 10), small throttle
  86. self._make_events(5)
  87. check_all_organizations_throttle()
  88. org.refresh_from_db()
  89. self.assertEqual(org.event_throttle_rate, 10)
  90. self.assertEqual(len(mail.outbox), 1)
  91. # New time period, should reset throttle
  92. now = self.subscription.current_period_start + timedelta(hours=1)
  93. self.subscription.current_period_start = now
  94. self.subscription.current_period_end = now + timedelta(hours=1)
  95. self.subscription.save()
  96. check_all_organizations_throttle()
  97. org.refresh_from_db()
  98. self.assertEqual(org.event_throttle_rate, 0)
  99. self.assertEqual(len(mail.outbox), 1)
  100. # Throttle again
  101. with freeze_time(now):
  102. self._make_events(16)
  103. check_all_organizations_throttle()
  104. org.refresh_from_db()
  105. self.assertEqual(org.event_throttle_rate, 50)
  106. # Throttle 100%
  107. with freeze_time(now):
  108. self._make_events(5)
  109. check_all_organizations_throttle()
  110. org.refresh_from_db()
  111. self.assertEqual(org.event_throttle_rate, 100)
  112. def test_no_plan_throttle(self):
  113. """
  114. It's possible to not sign up for a free plan, they should be throttled
  115. """
  116. self.subscription.delete()
  117. check_all_organizations_throttle()
  118. self.organization.refresh_from_db()
  119. self.assertEqual(self.organization.event_throttle_rate, 100)
  120. # Make plan active
  121. subscription = baker.make(
  122. "djstripe.Subscription",
  123. customer=self.customer,
  124. livemode=False,
  125. plan=self.plan,
  126. status="active",
  127. current_period_end=timezone.now() + timedelta(hours=1),
  128. )
  129. check_all_organizations_throttle()
  130. self.organization.refresh_from_db()
  131. self.assertEqual(self.organization.event_throttle_rate, 0)
  132. # Cancel plan
  133. subscription.status = "canceled"
  134. subscription.save()
  135. check_all_organizations_throttle()
  136. self.organization.refresh_from_db()
  137. self.assertEqual(self.organization.event_throttle_rate, 100)
  138. # Add new active plan (still has canceled plan)
  139. subscription = baker.make(
  140. "djstripe.Subscription",
  141. customer=self.customer,
  142. livemode=False,
  143. plan=self.plan,
  144. status="active",
  145. current_period_end=timezone.now() + timedelta(hours=1),
  146. )
  147. check_all_organizations_throttle()
  148. self.organization.refresh_from_db()
  149. self.assertEqual(self.organization.event_throttle_rate, 0)