Skip to content

Commit ae8378a

Browse files
authored
#186: Refactoring/186 integration test for udf path correctness extraction (#243)
Closes #186 integration tests for correctness of UDF path generation
1 parent 6084840 commit ae8378a

File tree

3 files changed

+199
-91
lines changed

3 files changed

+199
-91
lines changed

doc/changes/unreleased.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Unreleased
22

33
## Refactorings
4-
* #186: Integration test for correctness of UDF path generation
4+
* #186: Integration test for correctness of UDF path generation, using as_udf_path and pathlike

test/integration/test_service_onprem.py

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
BACKEND_SAAS,
2929
)
3030

31+
import exasol.bucketfs as bfs
3132
from exasol.bucketfs import (
3233
Bucket,
3334
Service,
@@ -324,93 +325,3 @@ def test_any_log_message_get_emitted(httpserver, caplog):
324325
]
325326
# The log level DEBUG should emit at least one log message
326327
assert log_records
327-
328-
329-
def test_upload_and_udf_path(
330-
backend_aware_bucketfs_params, backend_aware_database_params, backend
331-
):
332-
# Upload file to BucketFS
333-
file_name = "Uploaded-File-From-Integration-test.bin"
334-
335-
if backend == BACKEND_ONPREM:
336-
bucket = Bucket(
337-
name=backend_aware_bucketfs_params["bucket_name"],
338-
service_name=backend_aware_bucketfs_params["service_name"],
339-
password=backend_aware_bucketfs_params["password"],
340-
username=backend_aware_bucketfs_params["username"],
341-
verify=backend_aware_bucketfs_params["verify"],
342-
service=backend_aware_bucketfs_params["url"],
343-
)
344-
elif backend == BACKEND_SAAS:
345-
bucket = SaaSBucket(
346-
url=backend_aware_bucketfs_params["url"],
347-
account_id=backend_aware_bucketfs_params["account_id"],
348-
database_id=backend_aware_bucketfs_params["database_id"],
349-
pat=backend_aware_bucketfs_params["pat"],
350-
)
351-
content = "".join("1" for _ in range(0, 10))
352-
try:
353-
bucket.upload(file_name, content)
354-
assert file_name in bucket.files, "File upload failed"
355-
356-
# Generate UDF path
357-
udf_path = bucket.udf_path
358-
assert udf_path is not None, "UDF path generation failed"
359-
360-
conn = pyexasol.connect(**backend_aware_database_params)
361-
362-
conn.execute("CREATE SCHEMA IF NOT EXISTS transact;")
363-
conn.execute("open schema transact;")
364-
365-
# Create UDF SQL
366-
create_udf_sql = dedent(
367-
f"""
368-
--/
369-
CREATE OR REPLACE PYTHON3 SCALAR
370-
SCRIPT CHECK_FILE_EXISTS_UDF(file_path VARCHAR(200000))
371-
RETURNS BOOLEAN AS
372-
import os
373-
def run(ctx):
374-
return os.path.exists(ctx.file_path)
375-
/
376-
"""
377-
)
378-
conn.execute(create_udf_sql)
379-
# Verify the path exists inside the UDF
380-
result = conn.execute(f"SELECT CHECK_FILE_EXISTS_UDF('{udf_path}')").fetchone()[
381-
0
382-
]
383-
assert result == True
384-
385-
# return the content of the file
386-
create_read_udf_sql = dedent(
387-
f"""
388-
--/
389-
CREATE OR REPLACE PYTHON3 SCALAR
390-
SCRIPT READ_FILE_CONTENT_UDF(file_path VARCHAR(200000))
391-
RETURNS VARCHAR(200000) AS
392-
def run(ctx):
393-
with open(ctx.file_path, 'rb') as f:
394-
return f.read().decode('utf-8', errors='replace')
395-
/
396-
"""
397-
)
398-
conn.execute(create_read_udf_sql)
399-
400-
file_content = conn.execute(
401-
f"SELECT READ_FILE_CONTENT_UDF('{udf_path}/{file_name}')"
402-
).fetchone()[0]
403-
assert file_content == content
404-
except Exception as e:
405-
print(e)
406-
407-
finally:
408-
# cleanup
409-
_, _ = delete_file(
410-
bucket._service,
411-
bucket.name,
412-
bucket._username,
413-
bucket._password,
414-
file_name,
415-
)
416-
pass

test/integration/test_udf_path.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import logging
2+
import random
3+
import string
4+
from collections.abc import (
5+
ByteString,
6+
Iterable,
7+
)
8+
from contextlib import (
9+
closing,
10+
contextmanager,
11+
)
12+
from inspect import cleandoc
13+
from test.integration.conftest import (
14+
File,
15+
delete_file,
16+
)
17+
from textwrap import dedent
18+
from typing import (
19+
Tuple,
20+
Union,
21+
)
22+
23+
import pyexasol
24+
import pytest
25+
import requests
26+
from exasol.pytest_backend import (
27+
BACKEND_ONPREM,
28+
BACKEND_SAAS,
29+
)
30+
31+
import exasol.bucketfs as bfs
32+
from exasol.bucketfs import (
33+
Bucket,
34+
Service,
35+
as_bytes,
36+
as_string,
37+
)
38+
39+
40+
@pytest.fixture(scope="module")
41+
def exa_bucket(backend_aware_bucketfs_params, backend):
42+
# create and return a Bucket or SaaSBucket depending on backend
43+
params = backend_aware_bucketfs_params
44+
if backend == BACKEND_ONPREM:
45+
bucket = Bucket(
46+
name=params["bucket_name"],
47+
service_name=params["service_name"],
48+
password=params["password"],
49+
username=params["username"],
50+
verify=params["verify"],
51+
service=params["url"],
52+
)
53+
elif backend == BACKEND_SAAS:
54+
bucket = SaaSBucket(
55+
url=params["url"],
56+
account_id=params["account_id"],
57+
database_id=params["database_id"],
58+
pat=params["pat"],
59+
)
60+
else:
61+
pytest.fail(f"Unknown backend: {backend}")
62+
return bucket
63+
64+
65+
@pytest.fixture(scope="module")
66+
def exa_pathlike(backend_aware_bucketfs_params, backend):
67+
# build the pathlike
68+
params = backend_aware_bucketfs_params
69+
file_name = "Uploaded-File-From-Integration-test.bin"
70+
if backend == BACKEND_ONPREM:
71+
return bfs.path.build_path(
72+
backend=bfs.path.StorageBackend.onprem,
73+
url=params["url"],
74+
bucket_name=params["bucket_name"],
75+
service_name=params["service_name"],
76+
path=file_name,
77+
username=params["username"],
78+
password=params["password"],
79+
verify=params["verify"],
80+
)
81+
elif backend == BACKEND_SAAS:
82+
return bfs.path.build_path(
83+
backend=bfs.path.StorageBackend.saas,
84+
url=params["url"],
85+
account_id=params["account_id"],
86+
database_id=params["database_id"],
87+
pat=params["pat"],
88+
path=file_name,
89+
)
90+
else:
91+
pytest.fail(f"Unknown backend: {backend}")
92+
93+
94+
@pytest.fixture(scope="module")
95+
def uploaded_file(exa_bucket, request):
96+
file_name = "Uploaded-File-From-Integration-test.bin"
97+
content = "1" * 10
98+
99+
exa_bucket.upload(file_name, content)
100+
101+
def cleanup():
102+
try:
103+
exa_bucket.delete(file_name)
104+
except Exception:
105+
pass
106+
107+
request.addfinalizer(cleanup)
108+
109+
return {
110+
"file_name": file_name,
111+
"content": content,
112+
}
113+
114+
115+
@pytest.fixture
116+
def setup_schema_and_udfs(backend_aware_database_params):
117+
conn = pyexasol.connect(**backend_aware_database_params)
118+
conn.execute("CREATE SCHEMA IF NOT EXISTS transact;")
119+
conn.execute("OPEN SCHEMA transact;")
120+
# Check file exists UDF
121+
create_check_udf_sql = dedent(
122+
"""
123+
--/
124+
CREATE OR REPLACE PYTHON3 SCALAR
125+
SCRIPT CHECK_FILE_EXISTS_UDF(file_path VARCHAR(200000))
126+
RETURNS BOOLEAN AS
127+
import os
128+
def run(ctx):
129+
return os.path.exists(ctx.file_path)
130+
/
131+
"""
132+
)
133+
conn.execute(create_check_udf_sql)
134+
# Read file content UDF
135+
create_read_udf_sql = dedent(
136+
"""
137+
--/
138+
CREATE OR REPLACE PYTHON3 SCALAR
139+
SCRIPT READ_FILE_CONTENT_UDF(file_path VARCHAR(200000))
140+
RETURNS VARCHAR(200000) AS
141+
def run(ctx):
142+
with open(ctx.file_path, 'rb') as f:
143+
return f.read().decode('utf-8', errors='replace')
144+
/
145+
"""
146+
)
147+
conn.execute(create_read_udf_sql)
148+
return conn
149+
150+
151+
def test_upload_and_udf_path(uploaded_file, setup_schema_and_udfs, exa_bucket):
152+
"""
153+
Test that verifies upload and UDF path availability using the uploaded_file_and_paths fixture.
154+
"""
155+
file_name = uploaded_file["file_name"]
156+
content = uploaded_file["content"]
157+
bucket_udf_path = exa_bucket.udf_path
158+
159+
assert bucket_udf_path is not None, "UDF path generation failed"
160+
conn = setup_schema_and_udfs
161+
162+
# Verify existence in UDF
163+
result = conn.execute(
164+
f"SELECT CHECK_FILE_EXISTS_UDF('{bucket_udf_path}/{file_name}')"
165+
).fetchone()[0]
166+
assert result is True
167+
168+
# Verify content from UDF path
169+
content_from_udf_path = conn.execute(
170+
f"SELECT READ_FILE_CONTENT_UDF('{bucket_udf_path}/{file_name}')"
171+
).fetchone()[0]
172+
print(content_from_udf_path)
173+
assert content_from_udf_path == content
174+
175+
176+
def test_upload_and_udf_pathlike(uploaded_file, setup_schema_and_udfs, exa_pathlike):
177+
"""
178+
Test that verifies upload and pathlike UDF path availability using the uploaded_file_and_paths fixture.
179+
"""
180+
content = uploaded_file["content"]
181+
file_udf_path = exa_pathlike.as_udf_path()
182+
183+
assert file_udf_path is not None, "Pathlike udf path generation failed"
184+
conn = setup_schema_and_udfs
185+
186+
# Verify file exists in UDF
187+
exists = conn.execute(
188+
f"SELECT CHECK_FILE_EXISTS_UDF('{file_udf_path}')"
189+
).fetchone()[0]
190+
assert exists is True
191+
192+
# Verify content from pathlike udf path
193+
content_of_file_udf_path = conn.execute(
194+
f"SELECT READ_FILE_CONTENT_UDF('{file_udf_path}')"
195+
).fetchone()[0]
196+
print(content_of_file_udf_path)
197+
assert content_of_file_udf_path == content

0 commit comments

Comments
 (0)