Completed
Push — master ( f8e7c5...c10e9b )
by Ali-Akber
23s
created

RegressionTests.default()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
1
"""
2
3
"""
4
import time
5
6
import hiro
7
8
from flask_limiter.extension import C
9
from tests import FlaskLimiterTestCase
10
11
12
class RegressionTests(FlaskLimiterTestCase):
13
    def test_redis_request_slower_than_fixed_window(self):
14
        app, limiter = self.build_app(
15
            {
16
                C.GLOBAL_LIMITS: "5 per second",
17
                C.STORAGE_URL: "redis://localhost:6379",
18
                C.STRATEGY: "fixed-window",
19
                C.HEADERS_ENABLED: True
20
            }
21
        )
22
23
        @app.route("/t1")
24
        def t1():
25
            time.sleep(1.1)
26
            return "t1"
27
28
        with app.test_client() as cli:
29
            resp = cli.get("/t1")
30
            self.assertEqual(resp.headers["X-RateLimit-Remaining"], '5')
31
32
    def test_redis_request_slower_than_moving_window(self):
33
        app, limiter = self.build_app(
34
            {
35
                C.GLOBAL_LIMITS: "5 per second",
36
                C.STORAGE_URL: "redis://localhost:6379",
37
                C.STRATEGY: "moving-window",
38
                C.HEADERS_ENABLED: True
39
            }
40
        )
41
42
        @app.route("/t1")
43
        def t1():
44
            time.sleep(1.1)
45
            return "t1"
46
47
        with app.test_client() as cli:
48
            resp = cli.get("/t1")
49
            self.assertEqual(resp.headers["X-RateLimit-Remaining"], '5')
50
51 View Code Duplication
    def test_dynamic_limits(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
52
        app, limiter = self.build_app(
53
            {
54
                C.STRATEGY: "moving-window",
55
                C.HEADERS_ENABLED: True
56
            }
57
        )
58
59
        def func(*a):
60
            return "1/second; 2/minute"
61
62
        @app.route("/t1")
63
        @limiter.limit(func)
64
        def t1():
65
            return "t1"
66
67
        with hiro.Timeline().freeze() as timeline:
68
            with app.test_client() as cli:
69
                self.assertEqual(cli.get("/t1").status_code, 200)
70
                self.assertEqual(cli.get("/t1").status_code, 429)
71
                timeline.forward(2)
72
                self.assertEqual(cli.get("/t1").status_code, 200)
73
                self.assertEqual(cli.get("/t1").status_code, 429)
74
75
    def test_invalid_ratelimit_key(self):
76
        app, limiter = self.build_app({C.HEADERS_ENABLED: True})
77
78
        def func(*a):
79
            return None
80
81
        @app.route("/t1")
82
        @limiter.limit("2/second", key_func=func)
83
        def t1():
84
            return "t1"
85
86
        with app.test_client() as cli:
87
            cli.get("/t1")
88
            cli.get("/t1")
89
            cli.get("/t1")
90
            self.assertEqual(cli.get("/t1").status_code, 200)
91
            limiter.limit("1/second", key_func=lambda: "key")(t1)
92
            cli.get("/t1")
93
            self.assertEqual(cli.get("/t1").status_code, 429)
94
95
    def test_custom_key_prefix_with_headers(self):
96
        app1, limiter1 = self.build_app(
97
            key_prefix="moo",
98
            storage_uri="redis://localhost:6379",
99
            headers_enabled=True
100
        )
101
        app2, limiter2 = self.build_app(
102
            key_prefix="cow",
103
            storage_uri="redis://localhost:6379",
104
            headers_enabled=True
105
        )
106
107
        @app1.route("/test")
108
        @limiter1.limit("1/minute")
109
        def t1():
110
            return "app1 test"
111
112
        @app2.route("/test")
113
        @limiter2.limit("1/minute")
114
        def t2():
115
            return "app2 test"
116
117
        with app1.test_client() as cli:
118
            resp = cli.get("/test")
119
            self.assertEqual(200, resp.status_code)
120
            resp = cli.get("/test")
121
            self.assertEqual(resp.headers.get('Retry-After'), str(60))
122
            self.assertEqual(429, resp.status_code)
123
        with app2.test_client() as cli:
124
            resp = cli.get("/test")
125
            self.assertEqual(200, resp.status_code)
126
            resp = cli.get("/test")
127
            self.assertEqual(resp.headers.get('Retry-After'), str(60))
128
            self.assertEqual(429, resp.status_code)
129
130
    def test_default_limits_with_per_route_limit(self):
131
        app, limiter = self.build_app(
132
            application_limits=['3/minute']
133
        )
134
135
        @app.route("/explicit")
136
        @limiter.limit("1/minute")
137
        def explicit():
138
            return "explicit"
139
140
        @app.route("/default")
141
        def default():
142
            return "default"
143
144
        with app.test_client() as cli:
145
            with hiro.Timeline().freeze() as timeline:
146
                self.assertEqual(200, cli.get("/explicit").status_code)
147
                self.assertEqual(429, cli.get("/explicit").status_code)
148
                self.assertEqual(200, cli.get("/default").status_code)
149
                self.assertEqual(429, cli.get("/default").status_code)
150
                timeline.forward(60)
151
                self.assertEqual(200, cli.get("/explicit").status_code)
152
                self.assertEqual(200, cli.get("/default").status_code)
153
154