Skip to content

Commit a6b4777

Browse files
authored
Merge pull request #1127 from ethho/dev-tests-plat-154-external
PLAT-154: Migrate test_external
2 parents 10185a2 + 9392959 commit a6b4777

File tree

2 files changed

+166
-10
lines changed

2 files changed

+166
-10
lines changed

tests/conftest.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import networkx as nx
1111
import json
1212
from pathlib import Path
13-
import tempfile
1413
from datajoint import errors
1514
from datajoint.errors import ADAPTED_TYPE_SWITCH, FILEPATH_FEATURE_SWITCH
1615
from . import (
@@ -176,23 +175,52 @@ def connection_test(connection_root):
176175

177176

178177
@pytest.fixture(scope="session")
179-
def stores_config():
178+
def stores_config(tmpdir_factory):
180179
stores_config = {
181-
"raw": dict(protocol="file", location=tempfile.mkdtemp()),
180+
"raw": dict(protocol="file", location=tmpdir_factory.mktemp("raw")),
182181
"repo": dict(
183-
stage=tempfile.mkdtemp(), protocol="file", location=tempfile.mkdtemp()
182+
stage=tmpdir_factory.mktemp("repo"),
183+
protocol="file",
184+
location=tmpdir_factory.mktemp("repo"),
184185
),
185186
"repo-s3": dict(
186-
S3_CONN_INFO, protocol="s3", location="dj/repo", stage=tempfile.mkdtemp()
187+
S3_CONN_INFO,
188+
protocol="s3",
189+
location="dj/repo",
190+
stage=tmpdir_factory.mktemp("repo-s3"),
191+
),
192+
"local": dict(
193+
protocol="file", location=tmpdir_factory.mktemp("local"), subfolding=(1, 1)
187194
),
188-
"local": dict(protocol="file", location=tempfile.mkdtemp(), subfolding=(1, 1)),
189195
"share": dict(
190196
S3_CONN_INFO, protocol="s3", location="dj/store/repo", subfolding=(2, 4)
191197
),
192198
}
193199
return stores_config
194200

195201

202+
@pytest.fixture
203+
def mock_stores(stores_config):
204+
og_stores_config = dj.config.get("stores")
205+
dj.config["stores"] = stores_config
206+
yield
207+
if og_stores_config is None:
208+
del dj.config["stores"]
209+
else:
210+
dj.config["stores"] = og_stores_config
211+
212+
213+
@pytest.fixture
214+
def mock_cache(tmpdir_factory):
215+
og_cache = dj.config.get("cache")
216+
dj.config["cache"] = tmpdir_factory.mktemp("cache")
217+
yield
218+
if og_cache is None:
219+
del dj.config["cache"]
220+
else:
221+
dj.config["cache"] = og_cache
222+
223+
196224
@pytest.fixture
197225
def schema_any(connection_test):
198226
schema_any = dj.Schema(
@@ -287,15 +315,12 @@ def schema_adv(connection_test):
287315

288316

289317
@pytest.fixture
290-
def schema_ext(connection_test, stores_config, enable_filepath_feature):
318+
def schema_ext(connection_test, enable_filepath_feature, mock_stores, mock_cache):
291319
schema = dj.Schema(
292320
PREFIX + "_extern",
293321
context=schema_external.LOCALS_EXTERNAL,
294322
connection=connection_test,
295323
)
296-
dj.config["stores"] = stores_config
297-
dj.config["cache"] = tempfile.mkdtemp()
298-
299324
schema(schema_external.Simple)
300325
schema(schema_external.SimpleRemote)
301326
schema(schema_external.Seed)

tests/test_external.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import numpy as np
2+
from numpy.testing import assert_array_equal
3+
from datajoint.external import ExternalTable
4+
from datajoint.blob import pack, unpack
5+
import datajoint as dj
6+
from .schema_external import SimpleRemote, Simple
7+
import os
8+
9+
10+
def test_external_put(schema_ext, mock_stores, mock_cache):
11+
"""
12+
external storage put and get and remove
13+
"""
14+
ext = ExternalTable(
15+
schema_ext.connection, store="raw", database=schema_ext.database
16+
)
17+
initial_length = len(ext)
18+
input_ = np.random.randn(3, 7, 8)
19+
count = 7
20+
extra = 3
21+
for i in range(count):
22+
hash1 = ext.put(pack(input_))
23+
for i in range(extra):
24+
hash2 = ext.put(pack(np.random.randn(4, 3, 2)))
25+
26+
fetched_hashes = ext.fetch("hash")
27+
assert all(hash in fetched_hashes for hash in (hash1, hash2))
28+
assert len(ext) == initial_length + 1 + extra
29+
30+
output_ = unpack(ext.get(hash1))
31+
assert_array_equal(input_, output_)
32+
33+
34+
class TestLeadingSlash:
35+
def test_s3_leading_slash(self, schema_ext, mock_stores, mock_cache, minio_client):
36+
"""
37+
s3 external storage configured with leading slash
38+
"""
39+
self._leading_slash(schema_ext, index=100, store="share")
40+
41+
def test_file_leading_slash(
42+
self, schema_ext, mock_stores, mock_cache, minio_client
43+
):
44+
"""
45+
File external storage configured with leading slash
46+
"""
47+
self._leading_slash(schema_ext, index=200, store="local")
48+
49+
def _leading_slash(self, schema_ext, index, store):
50+
oldConfig = dj.config["stores"][store]["location"]
51+
value = np.array([1, 2, 3])
52+
53+
id = index
54+
dj.config["stores"][store]["location"] = "leading/slash/test"
55+
SimpleRemote.insert([{"simple": id, "item": value}])
56+
assert np.array_equal(
57+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
58+
)
59+
60+
id = index + 1
61+
dj.config["stores"][store]["location"] = "/leading/slash/test"
62+
SimpleRemote.insert([{"simple": id, "item": value}])
63+
assert np.array_equal(
64+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
65+
)
66+
67+
id = index + 2
68+
dj.config["stores"][store]["location"] = "leading\\slash\\test"
69+
SimpleRemote.insert([{"simple": id, "item": value}])
70+
assert np.array_equal(
71+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
72+
)
73+
74+
id = index + 3
75+
dj.config["stores"][store]["location"] = "f:\\leading\\slash\\test"
76+
SimpleRemote.insert([{"simple": id, "item": value}])
77+
assert np.array_equal(
78+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
79+
)
80+
81+
id = index + 4
82+
dj.config["stores"][store]["location"] = "f:\\leading/slash\\test"
83+
SimpleRemote.insert([{"simple": id, "item": value}])
84+
assert np.array_equal(
85+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
86+
)
87+
88+
id = index + 5
89+
dj.config["stores"][store]["location"] = "/"
90+
SimpleRemote.insert([{"simple": id, "item": value}])
91+
assert np.array_equal(
92+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
93+
)
94+
95+
id = index + 6
96+
dj.config["stores"][store]["location"] = "C:\\"
97+
SimpleRemote.insert([{"simple": id, "item": value}])
98+
assert np.array_equal(
99+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
100+
)
101+
102+
id = index + 7
103+
dj.config["stores"][store]["location"] = ""
104+
SimpleRemote.insert([{"simple": id, "item": value}])
105+
assert np.array_equal(
106+
value, (SimpleRemote & "simple={}".format(id)).fetch1("item")
107+
)
108+
109+
dj.config["stores"][store]["location"] = oldConfig
110+
111+
112+
def test_remove_fail(schema_ext, mock_stores, mock_cache, minio_client):
113+
"""
114+
https://github.com/datajoint/datajoint-python/issues/953
115+
"""
116+
assert dj.config["stores"]["local"]["location"]
117+
118+
data = dict(simple=2, item=[1, 2, 3])
119+
Simple.insert1(data)
120+
path1 = dj.config["stores"]["local"]["location"] + "/djtest_extern/4/c/"
121+
currentMode = int(oct(os.stat(path1).st_mode), 8)
122+
os.chmod(path1, 0o40555)
123+
(Simple & "simple=2").delete()
124+
listOfErrors = schema_ext.external["local"].delete(delete_external_files=True)
125+
126+
assert (
127+
len(schema_ext.external["local"] & dict(hash=listOfErrors[0][0])) == 1
128+
), "unexpected number of rows in external table"
129+
# ---------------------CLEAN UP--------------------
130+
os.chmod(path1, currentMode)
131+
listOfErrors = schema_ext.external["local"].delete(delete_external_files=True)

0 commit comments

Comments
 (0)