Skip to content

Commit 88f7b53

Browse files
committed
Merge remote-tracking branch 'upstream/dev-tests' into dev-tests-plat-160-privileges
2 parents a8e20eb + 911184f commit 88f7b53

File tree

4 files changed

+237
-2
lines changed

4 files changed

+237
-2
lines changed

tests/conftest.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
import json
1313
from pathlib import Path
1414
from datajoint import errors
15-
from datajoint.errors import ADAPTED_TYPE_SWITCH, FILEPATH_FEATURE_SWITCH
15+
from datajoint.errors import (
16+
ADAPTED_TYPE_SWITCH,
17+
FILEPATH_FEATURE_SWITCH,
18+
DataJointError,
19+
)
1620
from . import (
1721
PREFIX,
1822
CONN_INFO,
@@ -233,6 +237,10 @@ def schema_any(connection_test):
233237
PREFIX + "_test1", schema.LOCALS_ANY, connection=connection_test
234238
)
235239
assert schema.LOCALS_ANY, "LOCALS_ANY is empty"
240+
try:
241+
schema_any.jobs.delete()
242+
except DataJointError:
243+
pass
236244
schema_any(schema.TTest)
237245
schema_any(schema.TTest2)
238246
schema_any(schema.TTest3)
@@ -270,6 +278,10 @@ def schema_any(connection_test):
270278
schema_any(schema.Stimulus)
271279
schema_any(schema.Longblob)
272280
yield schema_any
281+
try:
282+
schema_any.jobs.delete()
283+
except DataJointError:
284+
pass
273285
schema_any.drop()
274286

275287

tests/schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class SimpleSource(dj.Lookup):
258258
definition = """
259259
id : int # id
260260
"""
261-
contents = ((x,) for x in range(10))
261+
contents = [(x,) for x in range(10)]
262262

263263

264264
class SigIntTable(dj.Computed):

tests/test_fetch_same.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import pytest
2+
from . import PREFIX, CONN_INFO
3+
import numpy as np
4+
import datajoint as dj
5+
6+
7+
class ProjData(dj.Manual):
8+
definition = """
9+
id : int
10+
---
11+
resp : float
12+
sim : float
13+
big : longblob
14+
blah : varchar(10)
15+
"""
16+
17+
18+
@pytest.fixture
19+
def schema_fetch_same(connection_root):
20+
schema = dj.Schema(
21+
PREFIX + "_fetch_same",
22+
context=dict(ProjData=ProjData),
23+
connection=connection_root,
24+
)
25+
schema(ProjData)
26+
ProjData().insert(
27+
[
28+
{"id": 0, "resp": 20.33, "sim": 45.324, "big": 3, "blah": "yes"},
29+
{
30+
"id": 1,
31+
"resp": 94.3,
32+
"sim": 34.23,
33+
"big": {"key1": np.random.randn(20, 10)},
34+
"blah": "si",
35+
},
36+
{
37+
"id": 2,
38+
"resp": 1.90,
39+
"sim": 10.23,
40+
"big": np.random.randn(4, 2),
41+
"blah": "sim",
42+
},
43+
]
44+
)
45+
yield schema
46+
schema.drop()
47+
48+
49+
@pytest.fixture
50+
def projdata():
51+
yield ProjData()
52+
53+
54+
class TestFetchSame:
55+
def test_object_conversion_one(self, schema_fetch_same, projdata):
56+
new = projdata.proj(sub="resp").fetch("sub")
57+
assert new.dtype == np.float64
58+
59+
def test_object_conversion_two(self, schema_fetch_same, projdata):
60+
[sub, add] = projdata.proj(sub="resp", add="sim").fetch("sub", "add")
61+
assert sub.dtype == np.float64
62+
assert add.dtype == np.float64
63+
64+
def test_object_conversion_all(self, schema_fetch_same, projdata):
65+
new = projdata.proj(sub="resp", add="sim").fetch()
66+
assert new["sub"].dtype == np.float64
67+
assert new["add"].dtype == np.float64
68+
69+
def test_object_no_convert(self, schema_fetch_same, projdata):
70+
new = projdata.fetch()
71+
assert new["big"].dtype == "object"
72+
assert new["blah"].dtype == "object"

tests/test_jobs.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import pytest
2+
from . import schema
3+
from datajoint.jobs import ERROR_MESSAGE_LENGTH, TRUNCATION_APPENDIX
4+
import random
5+
import string
6+
import datajoint as dj
7+
8+
9+
@pytest.fixture
10+
def subjects():
11+
yield schema.Subject()
12+
13+
14+
def test_reserve_job(schema_any, subjects):
15+
assert subjects
16+
table_name = "fake_table"
17+
18+
# reserve jobs
19+
for key in subjects.fetch("KEY"):
20+
assert schema_any.jobs.reserve(table_name, key), "failed to reserve a job"
21+
22+
# refuse jobs
23+
for key in subjects.fetch("KEY"):
24+
assert not schema_any.jobs.reserve(
25+
table_name, key
26+
), "failed to respect reservation"
27+
28+
# complete jobs
29+
for key in subjects.fetch("KEY"):
30+
schema_any.jobs.complete(table_name, key)
31+
assert not schema_any.jobs, "failed to free jobs"
32+
33+
# reserve jobs again
34+
for key in subjects.fetch("KEY"):
35+
assert schema_any.jobs.reserve(table_name, key), "failed to reserve new jobs"
36+
37+
# finish with error
38+
for key in subjects.fetch("KEY"):
39+
schema_any.jobs.error(table_name, key, "error message")
40+
41+
# refuse jobs with errors
42+
for key in subjects.fetch("KEY"):
43+
assert not schema_any.jobs.reserve(
44+
table_name, key
45+
), "failed to ignore error jobs"
46+
47+
# clear error jobs
48+
(schema_any.jobs & dict(status="error")).delete()
49+
assert not schema_any.jobs, "failed to clear error jobs"
50+
51+
52+
def test_restrictions(schema_any):
53+
jobs = schema_any.jobs
54+
jobs.delete()
55+
jobs.reserve("a", {"key": "a1"})
56+
jobs.reserve("a", {"key": "a2"})
57+
jobs.reserve("b", {"key": "b1"})
58+
jobs.error("a", {"key": "a2"}, "error")
59+
jobs.error("b", {"key": "b1"}, "error")
60+
61+
assert len(jobs & {"table_name": "a"}) == 2
62+
assert len(jobs & {"status": "error"}) == 2
63+
assert len(jobs & {"table_name": "a", "status": "error"}) == 1
64+
jobs.delete()
65+
66+
67+
def test_sigint(schema_any):
68+
try:
69+
schema.SigIntTable().populate(reserve_jobs=True)
70+
except KeyboardInterrupt:
71+
pass
72+
73+
assert len(schema_any.jobs.fetch()), "SigInt jobs table is empty"
74+
status, error_message = schema_any.jobs.fetch1("status", "error_message")
75+
assert status == "error"
76+
assert error_message == "KeyboardInterrupt"
77+
78+
79+
def test_sigterm(schema_any):
80+
try:
81+
schema.SigTermTable().populate(reserve_jobs=True)
82+
except SystemExit:
83+
pass
84+
85+
assert len(schema_any.jobs.fetch()), "SigTerm jobs table is empty"
86+
status, error_message = schema_any.jobs.fetch1("status", "error_message")
87+
assert status == "error"
88+
assert error_message == "SystemExit: SIGTERM received"
89+
90+
91+
def test_suppress_dj_errors(schema_any):
92+
"""test_suppress_dj_errors: dj errors suppressible w/o native py blobs"""
93+
with dj.config(enable_python_native_blobs=False):
94+
schema.ErrorClass.populate(reserve_jobs=True, suppress_errors=True)
95+
assert len(schema.DjExceptionName()) == len(schema_any.jobs) > 0
96+
97+
98+
def test_long_error_message(schema_any, subjects):
99+
# create long error message
100+
long_error_message = "".join(
101+
random.choice(string.ascii_letters) for _ in range(ERROR_MESSAGE_LENGTH + 100)
102+
)
103+
short_error_message = "".join(
104+
random.choice(string.ascii_letters) for _ in range(ERROR_MESSAGE_LENGTH // 2)
105+
)
106+
assert subjects
107+
table_name = "fake_table"
108+
109+
key = subjects.fetch("KEY")[0]
110+
111+
# test long error message
112+
schema_any.jobs.reserve(table_name, key)
113+
schema_any.jobs.error(table_name, key, long_error_message)
114+
error_message = schema_any.jobs.fetch1("error_message")
115+
assert (
116+
len(error_message) == ERROR_MESSAGE_LENGTH
117+
), "error message is longer than max allowed"
118+
assert error_message.endswith(
119+
TRUNCATION_APPENDIX
120+
), "appropriate ending missing for truncated error message"
121+
schema_any.jobs.delete()
122+
123+
# test long error message
124+
schema_any.jobs.reserve(table_name, key)
125+
schema_any.jobs.error(table_name, key, short_error_message)
126+
error_message = schema_any.jobs.fetch1("error_message")
127+
assert error_message == short_error_message, "error messages do not agree"
128+
assert not error_message.endswith(
129+
TRUNCATION_APPENDIX
130+
), "error message should not be truncated"
131+
schema_any.jobs.delete()
132+
133+
134+
def test_long_error_stack(schema_any, subjects):
135+
# create long error stack
136+
STACK_SIZE = (
137+
89942 # Does not fit into small blob (should be 64k, but found to be higher)
138+
)
139+
long_error_stack = "".join(
140+
random.choice(string.ascii_letters) for _ in range(STACK_SIZE)
141+
)
142+
assert subjects
143+
table_name = "fake_table"
144+
145+
key = subjects.fetch("KEY")[0]
146+
147+
# test long error stack
148+
schema_any.jobs.reserve(table_name, key)
149+
schema_any.jobs.error(table_name, key, "error message", long_error_stack)
150+
error_stack = schema_any.jobs.fetch1("error_stack")
151+
assert error_stack == long_error_stack, "error stacks do not agree"

0 commit comments

Comments
 (0)