Skip to content

Commit

Permalink
Testing of FilesysElement creation and hashing
Browse files Browse the repository at this point in the history
Includes some minor fixes to the concrete filesys, and testing for a variety of
read/write File interactions.
  • Loading branch information
sirosen committed Aug 4, 2014
1 parent 5c62542 commit 505046a
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 5 deletions.
6 changes: 3 additions & 3 deletions salve/filesys/concrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ def chown(self, uid, gid):

def exists(self):
"""
Transparent implementation of exists() using os.lexists
Transparent implementation of exists() using os.path.lexists
"""
return os.lexists(self.path)
return os.path.lexists(self.path)

def hash(self):
"""
Expand All @@ -51,7 +51,7 @@ def hash(self):
"""
from salve.util.streams import hash_by_filename
assert self.exists()
hash_by_filename(self.path)
return hash_by_filename(self.path)


class File(FilesysElement, abstract.File):
Expand Down
174 changes: 174 additions & 0 deletions tests/unit/filesys/concrete_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/python

import os
import hashlib

from nose.tools import istest
from tests.utils.exceptions import ensure_except
Expand Down Expand Up @@ -145,3 +146,176 @@ def copy_link(self):

assert os.path.islink(dst_path)
assert os.readlink(dst_path) == link_target

@istest
def copy_dir(self):
"""
Unit: Filesys Concrete Dir Copy
Copying a directory must succeed.
"""
self.make_dir('a/b/c')
self.make_dir('z')

content = 'fooing a bar in here'
self.write_file('a/b/f1', content)

src_path = self.get_fullname('a')
dst_path = self.get_fullname('z/a')

fs = concrete.Filesys()
fs.copy(src_path, dst_path)

assert os.path.isdir(dst_path)
assert os.path.isfile(self.get_fullname('z/a/b/f1'))
assert content == self.read_file('z/a/b/f1')

@istest
def create_file(self):
"""
Unit: Filesys Concrete File Touch
Creating an empty file must always work (when the path is valid)
"""
full_path = self.get_fullname('a')

f = concrete.File(full_path)
f.touch()

assert os.path.isfile(full_path)
assert '' == self.read_file('a')

@istest
def create_link(self):
"""
Unit: Filesys Concrete Link Create
Creating a symlink must always work, even if it is a broken link
"""
full_path = self.get_fullname('a')
link_target = 'b'

l = concrete.Link(full_path)
l.symlink(link_target)

assert os.path.islink(full_path)
assert link_target == os.readlink(full_path)

@istest
def create_dir_nonrecursive(self):
"""
Unit: Filesys Concrete Dir Create (Non-Recursive)
Creating a single level of a directory tree should always succeed
"""
full_path = self.get_fullname('a')

d = concrete.Dir(full_path)
d.mkdir(recursive=False)

assert os.path.isdir(full_path)
assert len(os.listdir(full_path)) == 0

@istest
def create_dir_recursive(self):
"""
Unit: Filesys Concrete Dir Create (Recursive)
Creating a path of a directory tree should always succeed if recursive
is set.
"""
full_path = self.get_fullname('a/b/c')

d = concrete.Dir(full_path)
d.mkdir(recursive=True)

assert os.path.isdir(full_path)
assert len(os.listdir(full_path)) == 0

@istest
def double_create_dir(self):
"""
Unit: Filesys Concrete Dir Double Create No Error
Repeated creation of a single directory should not raise any errors
"""
full_path = self.get_fullname('a')

d = concrete.Dir(full_path)
d.mkdir(recursive=False)
d.mkdir(recursive=False)

assert os.path.isdir(full_path)
assert len(os.listdir(full_path)) == 0

@istest
def create_dir_nonrecursive_missing_parent(self):
"""
Unit: Filesys Concrete Dir Create (Non-Recursive) Missing Parent Error
Validates that creating a directory with recursive off raises an
OSError with errno=2 if there is a missing ancestor.
"""
full_path = self.get_fullname('a/b')

d = concrete.Dir(full_path)
e = ensure_except(OSError, d.mkdir, recursive=False)

assert e.errno == 2
assert not os.path.isdir(full_path)

@istest
def file_open_write_only(self):
"""
Unit: Filesys Concrete File Open Write-Only
Verifies that opening a file in write only mode works as expected
"""
full_path = self.get_fullname('a')

f = concrete.File(full_path)
f.touch()

with f.open('w') as fd:
fd.write('xyz')
ensure_except(IOError, fd.read)

assert os.path.isfile(full_path)
assert 'xyz' == self.read_file('a')

@istest
def file_open_read_only(self):
"""
Unit: Filesys Concrete File Open Read-Only
Verifies that opening a file in read only mode works as expected
"""
full_path = self.get_fullname('a')
self.write_file('a', 'xyz')

f = concrete.File(full_path)

with f.open('r') as fd:
ensure_except(IOError, fd.write, 'pqr')
assert fd.read() == 'xyz'

@istest
def file_get_hash(self):
"""
Unit: Filesys Concrete File Get Hash
Validates the result of getting a file's sha512 hash
"""
full_path = self.get_fullname('a')
self.write_file('a', 'xyz')

f = concrete.File(full_path)

hashval = f.hash()
expect = hashlib.sha512('xyz').hexdigest()
assert hashval == expect

@istest
def link_get_hash(self):
"""
Unit: Filesys Concrete Link Get Hash
Validates the result of getting a symlink's sha256 hash
"""
full_path = self.get_fullname('a')

f = concrete.Link(full_path)
f.symlink('xyz')

hashval = f.hash()
expect = hashlib.sha256('xyz').hexdigest()
assert hashval == expect
9 changes: 7 additions & 2 deletions tests/utils/scratch.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,14 @@ def get_backup_path(self, backup_dir):

def make_dir(self, relpath):
full_path = self.get_fullname(relpath)
# FIXME: should use EAFP style
if not os.path.exists(full_path):
try:
os.makedirs(full_path)
except OSError as e:
# 'File exists' errno
if e.errno == 17:
return
else:
raise

def exists(self, relpath):
return os.path.exists(self.get_fullname(relpath))
Expand Down

0 comments on commit 505046a

Please sign in to comment.