Skip to content

Commit e1b4ce4

Browse files
Zsailerkevin-bates
authored andcommitted
Add missing sessions test (#156)
* add session tests back * add sessions manager tests * remove outdated comment
1 parent 5c873e3 commit e1b4ce4

File tree

2 files changed

+557
-38
lines changed

2 files changed

+557
-38
lines changed

tests/services/sessions/test_api.py

Lines changed: 284 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,307 @@
1+
import time
12
import json
3+
import shutil
24
import pytest
35

6+
import tornado
47

5-
def get_session_model(
6-
path,
7-
type='notebook',
8-
kernel_name='python',
9-
kernel_id=None
10-
):
11-
return {
12-
'path': path,
13-
'type': type,
14-
'kernel': {
15-
'name': kernel_name,
16-
'id': kernel_id
8+
from nbformat.v4 import new_notebook
9+
from nbformat import writes
10+
11+
from ...conftest import expected_http_error
12+
13+
j = lambda r: json.loads(r.body.decode())
14+
15+
16+
class SessionClient:
17+
18+
def __init__(self, fetch_callable):
19+
self.fetch = fetch_callable
20+
21+
async def _req(self, *args, method, body=None):
22+
if body is not None:
23+
body = json.dumps(body)
24+
25+
r = await self.fetch(
26+
'api', 'sessions', *args,
27+
method=method,
28+
body=body,
29+
allow_nonstandard_methods=True
30+
)
31+
return r
32+
33+
async def list(self):
34+
return await self._req(method='GET')
35+
36+
async def get(self, id):
37+
return await self._req(id, method='GET')
38+
39+
async def create(
40+
self,
41+
path,
42+
type='notebook',
43+
kernel_name='python',
44+
kernel_id=None):
45+
body = {
46+
'path': path,
47+
'type': type,
48+
'kernel': {
49+
'name': kernel_name,
50+
'id': kernel_id
51+
}
1752
}
18-
}
53+
return await self._req(method='POST', body=body)
54+
55+
def create_deprecated(self, path):
56+
body = {
57+
'notebook': {
58+
'path': path
59+
},
60+
'kernel': {
61+
'name': 'python',
62+
'id': 'foo'
63+
}
64+
}
65+
return self._req(method='POST', body=body)
66+
67+
def modify_path(self, id, path):
68+
body = {'path': path}
69+
return self._req(id, method='PATCH', body=body)
70+
71+
def modify_path_deprecated(self, id, path):
72+
body = {'notebook': {'path': path}}
73+
return self._req(id, method='PATCH', body=body)
1974

75+
def modify_type(self, id, type):
76+
body = {'type': type}
77+
return self._req(id, method='PATCH', body=body)
2078

21-
async def test_create(fetch):
79+
def modify_kernel_name(self, id, kernel_name):
80+
body = {'kernel': {'name': kernel_name}}
81+
return self._req(id, method='PATCH', body=body)
82+
83+
def modify_kernel_id(self, id, kernel_id):
84+
# Also send a dummy name to show that id takes precedence.
85+
body = {'kernel': {'id': kernel_id, 'name': 'foo'}}
86+
return self._req(id, method='PATCH', body=body)
87+
88+
async def delete(self, id):
89+
return await self._req(id, method='DELETE')
90+
91+
async def cleanup(self):
92+
resp = await self.list()
93+
sessions = j(resp)
94+
for session in sessions:
95+
await self.delete(session['id'])
96+
time.sleep(0.1)
97+
98+
99+
100+
@pytest.fixture
101+
def session_client(root_dir, fetch):
102+
subdir = root_dir.joinpath('foo')
103+
subdir.mkdir()
104+
105+
# Write a notebook to subdir.
106+
nb = new_notebook()
107+
nb_str = writes(nb, version=4)
108+
nbpath = subdir.joinpath('nb1.ipynb')
109+
nbpath.write_text(nb_str, encoding='utf-8')
110+
111+
# Yield a session client
112+
client = SessionClient(fetch)
113+
yield client
114+
115+
# Remove subdir
116+
shutil.rmtree(str(subdir), ignore_errors=True)
117+
118+
119+
async def test_create(session_client):
22120
# Make sure no sessions exist.
23-
r = await fetch(
24-
'api', 'sessions',
25-
method='GET'
26-
)
27-
sessions = json.loads(r.body.decode())
121+
resp = await session_client.list()
122+
sessions = j(resp)
28123
assert len(sessions) == 0
29124

30125
# Create a session.
31-
model = get_session_model('foo/nb1.ipynb')
32-
r = await fetch(
33-
'api', 'sessions',
34-
method='POST',
35-
body=json.dumps(model)
36-
)
37-
assert r.code == 201
38-
new_session = json.loads(r.body.decode())
126+
resp = await session_client.create('foo/nb1.ipynb')
127+
assert resp.code == 201
128+
new_session = j(resp)
39129
assert 'id' in new_session
40130
assert new_session['path'] == 'foo/nb1.ipynb'
41131
assert new_session['type'] == 'notebook'
42-
assert r.headers['Location'] == '/api/sessions/' + new_session['id']
132+
assert resp.headers['Location'] == '/api/sessions/' + new_session['id']
43133

44134
# Check that the new session appears in list.
45-
r = await fetch(
46-
'api', 'sessions',
47-
method='GET'
48-
)
49-
sessions = json.loads(r.body.decode())
135+
resp = await session_client.list()
136+
sessions = j(resp)
50137
assert sessions == [new_session]
51138

52139
# Retrieve that session.
53140
sid = new_session['id']
54-
r = await fetch(
55-
'api', 'sessions', sid,
56-
method='GET'
57-
)
58-
got = json.loads(r.body.decode())
141+
resp = await session_client.get(sid)
142+
got = j(resp)
59143
assert got == new_session
60144

145+
# Need to find a better solution to this.
146+
await session_client.cleanup()
147+
148+
149+
async def test_create_file_session(session_client):
150+
resp = await session_client.create('foo/nb1.py', type='file')
151+
assert resp.code == 201
152+
newsession = j(resp)
153+
assert newsession['path'] == 'foo/nb1.py'
154+
assert newsession['type'] == 'file'
155+
await session_client.cleanup()
156+
157+
158+
async def test_create_console_session(session_client):
159+
resp = await session_client.create('foo/abc123', type='console')
160+
assert resp.code == 201
161+
newsession = j(resp)
162+
assert newsession['path'] == 'foo/abc123'
163+
assert newsession['type'] == 'console'
164+
# Need to find a better solution to this.
165+
await session_client.cleanup()
166+
167+
168+
async def test_create_deprecated(session_client):
169+
resp = await session_client.create_deprecated('foo/nb1.ipynb')
170+
assert resp.code == 201
171+
newsession = j(resp)
172+
assert newsession['path'] == 'foo/nb1.ipynb'
173+
assert newsession['type'] == 'notebook'
174+
assert newsession['notebook']['path'] == 'foo/nb1.ipynb'
175+
# Need to find a better solution to this.
176+
await session_client.cleanup()
177+
178+
179+
async def test_create_with_kernel_id(session_client, fetch):
180+
# create a new kernel
181+
resp = await fetch('api/kernels', method='POST', allow_nonstandard_methods=True)
182+
kernel = j(resp)
183+
184+
resp = await session_client.create('foo/nb1.ipynb', kernel_id=kernel['id'])
185+
assert resp.code == 201
186+
newsession = j(resp)
187+
assert 'id' in newsession
188+
assert newsession['path'] == 'foo/nb1.ipynb'
189+
assert newsession['kernel']['id'] == kernel['id']
190+
assert resp.headers['Location'] == '/api/sessions/{0}'.format(newsession['id'])
191+
192+
resp = await session_client.list()
193+
sessions = j(resp)
194+
assert sessions == [newsession]
195+
196+
# Retrieve it
197+
sid = newsession['id']
198+
resp = await session_client.get(sid)
199+
got = j(resp)
200+
assert got == newsession
201+
# Need to find a better solution to this.
202+
await session_client.cleanup()
203+
204+
async def test_delete(session_client):
205+
resp = await session_client.create('foo/nb1.ipynb')
206+
newsession = j(resp)
207+
sid = newsession['id']
208+
209+
resp = await session_client.delete(sid)
210+
assert resp.code == 204
211+
212+
resp = await session_client.list()
213+
sessions = j(resp)
214+
assert sessions == []
215+
216+
with pytest.raises(tornado.httpclient.HTTPClientError) as e:
217+
await session_client.get(sid)
218+
assert expected_http_error(e, 404)
219+
# Need to find a better solution to this.
220+
await session_client.cleanup()
221+
222+
async def test_modify_path(session_client):
223+
resp = await session_client.create('foo/nb1.ipynb')
224+
newsession = j(resp)
225+
sid = newsession['id']
226+
227+
resp = await session_client.modify_path(sid, 'nb2.ipynb')
228+
changed = j(resp)
229+
assert changed['id'] == sid
230+
assert changed['path'] == 'nb2.ipynb'
231+
# Need to find a better solution to this.
232+
await session_client.cleanup()
233+
234+
async def test_modify_path_deprecated(session_client):
235+
resp = await session_client.create('foo/nb1.ipynb')
236+
newsession = j(resp)
237+
sid = newsession['id']
238+
239+
resp = await session_client.modify_path_deprecated(sid, 'nb2.ipynb')
240+
changed = j(resp)
241+
assert changed['id'] == sid
242+
assert changed['notebook']['path'] == 'nb2.ipynb'
243+
# Need to find a better solution to this.
244+
await session_client.cleanup()
245+
246+
async def test_modify_type(session_client):
247+
resp = await session_client.create('foo/nb1.ipynb')
248+
newsession = j(resp)
249+
sid = newsession['id']
250+
251+
resp = await session_client.modify_type(sid, 'console')
252+
changed = j(resp)
253+
assert changed['id'] == sid
254+
assert changed['type'] == 'console'
255+
# Need to find a better solution to this.
256+
await session_client.cleanup()
257+
258+
async def test_modify_kernel_name(session_client, fetch):
259+
resp = await session_client.create('foo/nb1.ipynb')
260+
before = j(resp)
261+
sid = before['id']
262+
263+
resp = await session_client.modify_kernel_name(sid, before['kernel']['name'])
264+
after = j(resp)
265+
assert after['id'] == sid
266+
assert after['path'] == before['path']
267+
assert after['type'] == before['type']
268+
assert after['kernel']['id'] != before['kernel']['id']
269+
270+
# check kernel list, to be sure previous kernel was cleaned up
271+
resp = await fetch('api/kernels', method='GET')
272+
kernel_list = j(resp)
273+
after['kernel'].pop('last_activity')
274+
[ k.pop('last_activity') for k in kernel_list ]
275+
assert kernel_list == [after['kernel']]
276+
# Need to find a better solution to this.
277+
await session_client.cleanup()
278+
279+
280+
async def test_modify_kernel_id(session_client, fetch):
281+
resp = await session_client.create('foo/nb1.ipynb')
282+
before = j(resp)
283+
sid = before['id']
284+
285+
# create a new kernel
286+
resp = await fetch('api/kernels', method='POST', allow_nonstandard_methods=True)
287+
kernel = j(resp)
288+
289+
# Attach our session to the existing kernel
290+
resp = await session_client.modify_kernel_id(sid, kernel['id'])
291+
after = j(resp)
292+
assert after['id'] == sid
293+
assert after['path'] == before['path']
294+
assert after['type'] == before['type']
295+
assert after['kernel']['id'] != before['kernel']['id']
296+
assert after['kernel']['id'] == kernel['id']
297+
298+
# check kernel list, to be sure previous kernel was cleaned up
299+
resp = await fetch('api/kernels', method='GET')
300+
kernel_list = j(resp)
301+
302+
kernel.pop('last_activity')
303+
[ k.pop('last_activity') for k in kernel_list ]
304+
assert kernel_list == [kernel]
61305

306+
# Need to find a better solution to this.
307+
await session_client.cleanup()

0 commit comments

Comments
 (0)