xref: /unit/test/test_status.py (revision 2592:e079c44a8340)
1import time
2
3from unit.applications.lang.python import ApplicationPython
4from unit.option import option
5from unit.status import Status
6
7prerequisites = {'modules': {'python': 'any'}}
8
9client = ApplicationPython()
10
11
12def check_connections(accepted, active, idle, closed):
13    assert Status.get('/connections') == {
14        'accepted': accepted,
15        'active': active,
16        'idle': idle,
17        'closed': closed,
18    }
19
20
21def app_default(name="empty", module="wsgi"):
22    name_dir = f'{option.test_dir}/python/{name}'
23    return {
24        "type": client.get_application_type(),
25        "processes": {"spare": 0},
26        "path": name_dir,
27        "working_directory": name_dir,
28        "module": module,
29    }
30
31
32def test_status():
33    assert 'error' in client.conf_delete('/status'), 'DELETE method'
34
35
36def test_status_requests(skip_alert):
37    skip_alert(r'Python failed to import module "blah"')
38
39    assert 'success' in client.conf(
40        {
41            "listeners": {
42                "*:8080": {"pass": "routes"},
43                "*:8081": {"pass": "applications/empty"},
44                "*:8082": {"pass": "applications/blah"},
45            },
46            "routes": [{"action": {"return": 200}}],
47            "applications": {
48                "empty": app_default(),
49                "blah": {
50                    "type": client.get_application_type(),
51                    "processes": {"spare": 0},
52                    "module": "blah",
53                },
54            },
55        },
56    )
57
58    Status.init()
59
60    assert client.get()['status'] == 200
61    assert Status.get('/requests/total') == 1, '2xx'
62
63    assert client.get(port=8081)['status'] == 200
64    assert Status.get('/requests/total') == 2, '2xx app'
65
66    assert (
67        client.get(headers={'Host': '/', 'Connection': 'close'})['status']
68        == 400
69    )
70    assert Status.get('/requests/total') == 3, '4xx'
71
72    assert client.get(port=8082)['status'] == 503
73    assert Status.get('/requests/total') == 4, '5xx'
74
75    client.http(
76        b"""GET / HTTP/1.1
77Host: localhost
78
79GET / HTTP/1.1
80Host: localhost
81Connection: close
82
83""",
84        raw=True,
85    )
86    assert Status.get('/requests/total') == 6, 'pipeline'
87
88    sock = client.get(port=8081, no_recv=True)
89
90    time.sleep(1)
91
92    assert Status.get('/requests/total') == 7, 'no receive'
93
94    sock.close()
95
96
97def test_status_connections():
98    assert 'success' in client.conf(
99        {
100            "listeners": {
101                "*:8080": {"pass": "routes"},
102                "*:8081": {"pass": "applications/delayed"},
103            },
104            "routes": [{"action": {"return": 200}}],
105            "applications": {
106                "delayed": app_default("delayed"),
107            },
108        },
109    )
110
111    Status.init()
112
113    # accepted, closed
114
115    assert client.get()['status'] == 200
116    check_connections(1, 0, 0, 1)
117
118    # idle
119
120    (_, sock) = client.get(
121        headers={'Host': 'localhost', 'Connection': 'keep-alive'},
122        start=True,
123        read_timeout=1,
124    )
125
126    check_connections(2, 0, 1, 1)
127
128    client.get(sock=sock)
129    check_connections(2, 0, 0, 2)
130
131    # active
132
133    (_, sock) = client.get(
134        headers={
135            'Host': 'localhost',
136            'X-Delay': '2',
137            'Connection': 'close',
138        },
139        port=8081,
140        start=True,
141        read_timeout=1,
142    )
143    check_connections(3, 1, 0, 2)
144
145    client.get(sock=sock)
146    check_connections(3, 0, 0, 3)
147
148
149def test_status_applications():
150    def check_applications(expert):
151        apps = list(client.conf_get('/status/applications').keys()).sort()
152        assert apps == expert.sort()
153
154    def check_application(name, running, starting, idle, active):
155        assert Status.get(f'/applications/{name}') == {
156            'processes': {
157                'running': running,
158                'starting': starting,
159                'idle': idle,
160            },
161            'requests': {'active': active},
162        }
163
164    client.load('delayed')
165    Status.init()
166
167    check_applications(['delayed'])
168    check_application('delayed', 0, 0, 0, 0)
169
170    # idle
171
172    assert client.get()['status'] == 200
173    check_application('delayed', 1, 0, 1, 0)
174
175    assert 'success' in client.conf('4', 'applications/delayed/processes')
176    check_application('delayed', 4, 0, 4, 0)
177
178    # active
179
180    (_, sock) = client.get(
181        headers={
182            'Host': 'localhost',
183            'X-Delay': '2',
184            'Connection': 'close',
185        },
186        start=True,
187        read_timeout=1,
188    )
189    check_application('delayed', 4, 0, 3, 1)
190    sock.close()
191
192    # starting
193
194    assert 'success' in client.conf(
195        {
196            "listeners": {
197                "*:8080": {"pass": "applications/restart"},
198                "*:8081": {"pass": "applications/delayed"},
199            },
200            "routes": [],
201            "applications": {
202                "restart": app_default("restart", "longstart"),
203                "delayed": app_default("delayed"),
204            },
205        },
206    )
207    Status.init()
208
209    check_applications(['delayed', 'restart'])
210    check_application('restart', 0, 0, 0, 0)
211    check_application('delayed', 0, 0, 0, 0)
212
213    client.get(read_timeout=1)
214
215    check_application('restart', 0, 1, 0, 1)
216    check_application('delayed', 0, 0, 0, 0)
217
218
219def test_status_proxy():
220    assert 'success' in client.conf(
221        {
222            "listeners": {
223                "*:8080": {"pass": "routes"},
224                "*:8081": {"pass": "applications/empty"},
225            },
226            "routes": [
227                {
228                    "match": {"uri": "/"},
229                    "action": {"proxy": "http://127.0.0.1:8081"},
230                }
231            ],
232            "applications": {
233                "empty": app_default(),
234            },
235        },
236    )
237
238    Status.init()
239
240    assert client.get()['status'] == 200
241    check_connections(2, 0, 0, 2)
242    assert Status.get('/requests/total') == 2, 'proxy'
243