Skip to content

Commit

Permalink
Prevent tests from generating unwanted test artifacts (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
peytondmurray authored Feb 9, 2024
1 parent 3832979 commit 37d8d4a
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 42 deletions.
22 changes: 20 additions & 2 deletions versioned_hdf5/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import os
from typing import Optional, Callable
import uuid

import h5py
from pytest import fixture
from .helpers import setup_vfile

from ..api import VersionedHDF5File
from ..backend import initialize

# Run tests marked with @pytest.mark.slow last. See
# https://stackoverflow.com/questions/61533694/run-slow-pytest-commands-at-the-end-of-the-test-suite
Expand All @@ -23,7 +26,7 @@ def filepath(tmp_path, request):
yield file_name

@fixture
def h5file(tmp_path, request):
def h5file(setup_vfile, tmp_path, request):
file_name = os.path.join(tmp_path, 'file.hdf5')
version_name = None
m = request.node.get_closest_marker('setup_args')
Expand Down Expand Up @@ -308,3 +311,18 @@ def _check_running_version(target):
f"versioned_hdf5=={__version__} installed; "
f"this file only generates bad data for DATA_VERSION=={target}"
)


@fixture
def setup_vfile(tmp_path: str) -> Callable[[Optional[str], Optional[str]], h5py.File]:
"""Fixture which provides a function that creates an hdf5 file, optionally with groups."""
def _setup_vfile(file_name='file.hdf5', *, version_name=None):
f = h5py.File(tmp_path / file_name, 'w')
initialize(f)
if version_name:
if isinstance(version_name, str):
version_name = [version_name]
for name in version_name:
f['_version_data/versions'].create_group(name)
return f
return _setup_vfile
13 changes: 0 additions & 13 deletions versioned_hdf5/tests/helpers.py

This file was deleted.

46 changes: 27 additions & 19 deletions versioned_hdf5/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import numpy as np
from numpy.testing import assert_equal

from .helpers import setup_vfile
from ..backend import DEFAULT_CHUNK_SIZE, DATA_VERSION
from ..api import VersionedHDF5File
from ..versions import TIMESTAMP_FMT, all_versions
Expand Down Expand Up @@ -1046,24 +1045,27 @@ def test_group_contains(vfile):
assert '/_version_data/versions/version1/group1/group2' in version1
assert '/_version_data/versions/version1/group1/group2' not in version2

@mark.setup_args(file_name='test.hdf5')
def test_moved_file(tmp_path, h5file):
def test_moved_file(setup_vfile, tmpdir):
h5file = setup_vfile()
path = pathlib.Path(h5file.filename)

# See issue #28. Make sure the virtual datasets do not hard-code the filename.
file = VersionedHDF5File(h5file)
data = np.ones(2*DEFAULT_CHUNK_SIZE)
with file.stage_version('version1') as group:
group['dataset'] = data
file.close()

with h5py.File('test.hdf5', 'r') as f:
with h5py.File(h5file.filename, 'r') as f:
file = VersionedHDF5File(f)
assert_equal(file['version1']['dataset'][:], data)
file.close()

# XXX: os.replace
os.rename('test.hdf5', 'test2.hdf5')
new_path = path.parent / 'test2.hdf5'
os.rename(path, new_path)

with h5py.File('test2.hdf5', 'r') as f:
with h5py.File(new_path, 'r') as f:
file = VersionedHDF5File(f)
assert_equal(file['version1']['dataset'][:], data)
file.close()
Expand Down Expand Up @@ -1292,7 +1294,7 @@ def test_closes(vfile):
raises(ValueError, lambda: vfile['version2'])
assert repr(vfile) == "<Closed VersionedHDF5File>"

def test_scalar_dataset():
def test_scalar_dataset(setup_vfile):
for data1, data2 in [
(b'baz', b'foo'),
(np.asarray('baz', dtype='S'), np.asarray('foo', dtype='S')),
Expand Down Expand Up @@ -1406,7 +1408,7 @@ def test_InMemoryArrayDataset_chunks(vfile):
assert data_group['g/bar'].compression_opts == 3


def test_string_dtypes():
def test_string_dtypes(setup_vfile):

# Make sure the fillvalue logic works correctly for custom h5py string
# dtypes.
Expand Down Expand Up @@ -1473,8 +1475,10 @@ def test_empty(vfile):
assert_equal(vfile['version2']['data2'][()], np.empty((1, 0, 2)))


def test_read_only():
with setup_vfile('test.hdf5') as f:
def test_read_only(setup_vfile):
vfile = setup_vfile()
filename = vfile.filename
with vfile as f:
file = VersionedHDF5File(f)
timestamp = datetime.datetime.now(datetime.timezone.utc)
with file.stage_version('version1', timestamp=timestamp) as g:
Expand All @@ -1495,7 +1499,7 @@ def test_read_only():
with raises(ValueError):
file[timestamp]['data2'] = [1, 2, 3]

with h5py.File('test.hdf5', 'r+') as f:
with h5py.File(filename, 'r+') as f:
file = VersionedHDF5File(f)

with raises(ValueError):
Expand Down Expand Up @@ -1596,21 +1600,23 @@ def test_auto_create_group(vfile):

assert_equal(vfile['version1']['a']['b']['c'][:], [0, 1, 2])

def test_scalar():
with setup_vfile('test.hdf5') as f:
def test_scalar(setup_vfile):
file = setup_vfile()
filename = file.filename
with file as f:
vfile = VersionedHDF5File(f)
with vfile.stage_version('version1') as g:
dtype = h5py.special_dtype(vlen=bytes)
g.create_dataset('bar', data=np.array(['aaa'], dtype='O'), dtype=dtype)

with h5py.File('test.hdf5', 'r+') as f:
with h5py.File(filename, 'r+') as f:
vfile = VersionedHDF5File(f)
assert isinstance(vfile['version1']['bar'], DatasetWrapper)
assert isinstance(vfile['version1']['bar'].dataset, InMemoryDataset)
# Should return a scalar, not a shape () array
assert isinstance(vfile['version1']['bar'][0], bytes)

with h5py.File('test.hdf5', 'r') as f:
with h5py.File(filename, 'r') as f:
vfile = VersionedHDF5File(f)
assert isinstance(vfile['version1']['bar'], h5py.Dataset)
# Should return a scalar, not a shape () array
Expand Down Expand Up @@ -1825,20 +1831,22 @@ def test_mask_reading_read_only(tmp_path):
b = sv['bar'][mask]
assert_equal(b, [1, 2])

def test_read_only_no_wrappers():
def test_read_only_no_wrappers(setup_vfile):
file = setup_vfile()
filename = file.filename
# Read-only files should not use the wrapper classes
with setup_vfile('test.hdf5') as f:
with file as f:
vfile = VersionedHDF5File(f)
with vfile.stage_version('version1') as g:
g.create_dataset('bar', data=np.array([0, 1, 2]))

with h5py.File('test.hdf5', 'r+') as f:
with h5py.File(filename, 'r+') as f:
vfile = VersionedHDF5File(f)
assert isinstance(vfile['version1'], InMemoryGroup)
assert isinstance(vfile['version1']['bar'], DatasetWrapper)
assert isinstance(vfile['version1']['bar'].dataset, InMemoryDataset)

with h5py.File('test.hdf5', 'r') as f:
with h5py.File(filename, 'r') as f:
vfile = VersionedHDF5File(f)
assert isinstance(vfile['version1'], h5py.Group)
assert isinstance(vfile['version1']['bar'], h5py.Dataset)
Expand Down
4 changes: 1 addition & 3 deletions versioned_hdf5/tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@

import itertools

from .helpers import setup_vfile

from ..backend import (create_base_dataset, write_dataset,
create_virtual_dataset, DEFAULT_CHUNK_SIZE,
write_dataset_chunks)

CHUNK_SIZE_3D = 2**4 # = cbrt(DEFAULT_CHUNK_SIZE)


def test_initialize():
def test_initialize(setup_vfile):
with setup_vfile() as f:
pass
f.close()
Expand Down
11 changes: 6 additions & 5 deletions versioned_hdf5/tests/test_hashtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from ..backend import create_base_dataset
from ..hashtable import Hashtable
from .helpers import setup_vfile
from .. import VersionedHDF5File

def test_hashtable(h5file):
Expand All @@ -30,7 +29,7 @@ def test_hashtable(h5file):
with raises(ValueError):
h[b'\x01'*32] = slice(0, 4, 2)

def test_from_raw_data():
def test_from_raw_data(setup_vfile):
with setup_vfile('test.h5') as f:
vf = VersionedHDF5File(f)
with vf.stage_version('0') as sv:
Expand All @@ -50,13 +49,15 @@ def test_hashtable_multidimension(h5file):
h = Hashtable(h5file, 'test_data')
assert h.hash(np.ones((1, 2, 3,))) != h.hash(np.ones((3, 2, 1)))

def test_issue_208():
with setup_vfile('test.h5') as f:
def test_issue_208(setup_vfile):
file = setup_vfile()
filename = file.filename
with file as f:
vf = VersionedHDF5File(f)
with vf.stage_version('0') as sv:
sv.create_dataset('bar', data=np.arange(10))

with h5py.File('test.h5', 'r+') as f:
with h5py.File(filename, 'r+') as f:
vf = VersionedHDF5File(f)
with vf.stage_version('1') as sv:
sv['bar'].resize((12,))
Expand Down

0 comments on commit 37d8d4a

Please sign in to comment.