473,387 Members | 1,892 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Has anyone released a Python "mock filesystem" for automated testing?

The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.

Googling the archives and the web suggests that only I and
Remy Blank have done much along these lines. I don't see
any sign that anyone has actually released such a beast
yet, however.

My own past work in this area was always proprietary, and
as "you can't take it with you" I've been starting over
on a new project and have the basics working. If nobody
can point me to a more complete implementation, I'll be
happy to continue to work on mine and release it in the
near future.

For now, in case anyone is interested, I have support
for basic open, read/write, __iter__, close, "r" and "w"
modes, a couple of the most basic exceptions, and a
tiny handful of lesser things. All well supported by
their own unit tests, of course, to ensure quality.
Stripped class/def lines shown below, as that may be
an easier way for you to picture what this is about:

class MockFile(object):
def __init__(self, fs, path, data='', mode=''):
def _getContents(self):
def read(self):
def write(self, data):
def close(self):
def __iter__(self):
class FileSystem(object):
'''Acts like a real file system to support testing.'''
def __init__(self, mocktime=False):
def _createFile(self, path, data):
def _getFile(self, path):
def open(self, path, mode='r'):

Thanks for any pointers to more advanced stuff.

-Peter
Jul 18 '05 #1
9 5779
On Thu, Nov 04, 2004 at 09:31:04PM -0500, Peter Hansen wrote:
The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.

Googling the archives and the web suggests that only I and
Remy Blank have done much along these lines. I don't see
any sign that anyone has actually released such a beast
yet, however.


If linux only support is OK you should check out FUSE
http://fuse.sourceforge.net/
It allows userspace implementations of file systems in python. The gmailfs
(mount your gmail account) uses it. You could use it to write a 'real' file
system that just has no disk backend store.

It would be easy to implement special files to do things for testing,
echo '1' > /op/nuke # clean everything
echo '1' > /op/push # push the state of the filesystem
echo '1' > /op/pop # restore the state of the filesystem to last 'push'
And any other handy thing you can think of.
It has the advantage that you can use regular python files in your
program. Bugs in the implementation would hurt testing but that is the
case any way you do it.
Unrelated:
I'm strongly tempted to [re]write a simple webapp like a blog as a
filesystem. Just put apache on top to handle GETs and cat POSTs/PUTs
directly to the filesystem. Can't get more unix-y than that!

-Jack
Jul 18 '05 #2
Peter Hansen <pe***@engcorp.com> writes:
The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.


Just out of curiosity, does your os implement some form of disk in
memory disk? Go to <URL: http://www.FreeBSD.org/cgi/man.cgi > and
search for either mfs or md for examples.

Second, consider using os.sep for path seperation, so that testing can
be done correctly for the OS the project is running on. Or possibly a
flag to indicate whether or not you want to use os.sep.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Jul 18 '05 #3
On Thu, 04 Nov 2004 21:31:04 -0500, Peter Hansen <pe***@engcorp.com> wrote:
The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.

Googling the archives and the web suggests that only I and
Remy Blank have done much along these lines. I don't see
any sign that anyone has actually released such a beast
yet, however.

My own past work in this area was always proprietary, and
as "you can't take it with you" I've been starting over
on a new project and have the basics working. If nobody
can point me to a more complete implementation, I'll be
happy to continue to work on mine and release it in the
near future.

For now, in case anyone is interested, I have support
for basic open, read/write, __iter__, close, "r" and "w"
modes, a couple of the most basic exceptions, and a
tiny handful of lesser things. All well supported by
their own unit tests, of course, to ensure quality.
Stripped class/def lines shown below, as that may be
an easier way for you to picture what this is about:

class MockFile(object):
def __init__(self, fs, path, data='', mode=''):
def _getContents(self):
def read(self):
def write(self, data):
def close(self):
def __iter__(self):
class FileSystem(object):
'''Acts like a real file system to support testing.'''
def __init__(self, mocktime=False):
def _createFile(self, path, data):
def _getFile(self, path):
def open(self, path, mode='r'):

Thanks for any pointers to more advanced stuff.

In a recent post, I suggested a way to virtualize selected files or glob-pattern
sets of files specified by string.

The idea was/is to make open and/or file check whether the path it's being passed
has been registered in a hook registry of substitute classes or factory functions
to be called instead of the normal file builtin functionality, so that the returned
object is an instance of _your_ registered custom class.

"Registering" might be as simple API-wise as sys.filehook['filename.ext'] = MockFile
(to use your example ;-)

*args, **kw would be passed to Mockfile and the resulting instance would be passed
back to the caller of file, so e.g. file('filename.ext', 'rb').read() would
have the effect of Mockfile('filename.ext', rb').read()

Of course there are a bunch of other file things that might have to be supplied if
you wanted to virtualize using low level os.open & friends.

Re a whole file system virtualization, I tried to float that one time long ago, but got
no enthusiasm, even though I only wanted to introduce a virtual branch of the root.

If you do do something with a VFS, IMO it should be mountable and require mounting. Maybe
unix-style mapping of the file tree like msys does for windows would allow mounting
in a platform-independent way, referring to c:\some\path\ as /c/some/path/ and so forth.
Not sure about virtualizing fstab... I guess you could do os.filehook['fstab'] = Something
to feed something special to the mount.

With a mount command you could also specify text file cooking or not, etc.

Just stirring the pot, but I think it would open up some different testing possibilities ;-)
If the hook really hooks well, I would think you could write

sys.filehook['foo'] = __import__('StringIO').StringIO("print 'hi from dummy foo.py'\n")
import foo

and expect a greeting (the first time)(untested ;-)

I guess it depends on where i/o funnels back to common layer interfaces.

Regards,
Bengt Richter
Jul 18 '05 #4
Peter Hansen wrote:
Googling the archives and the web suggests that only I and
Remy Blank have done much along these lines. I don't see
any sign that anyone has actually released such a beast
yet, however.
Not yet, not yet...
For now, in case anyone is interested, I have support
for basic open, read/write, __iter__, close, "r" and "w"
modes, a couple of the most basic exceptions, and a
tiny handful of lesser things. All well supported by
their own unit tests, of course, to ensure quality.


The status on my side is that I have the "read-only" portion working
quite well, with support for file attributes (stat) but no access
checking yet. Also supported by a unit test suite.

However, when I started on the "write" code, I stumbeled on a few areas
where I wasn't sure how the system should behave. A few examples:

- Where do you land if you chdir("/dir1/symlink/../subdir") when
symlink points to /dir2/subdir? If you os.abspath() the path before
interpretation, you land in /dir1/subdir. If you don't, you land in
/dir2/subdir.
- Who can remove a file?
- Who can change the mode of a file? Its owner and group?
- Which operations change atime? mtime? ctime?
- What exceptions are thrown for various error conditions?

Those are the simple ones I remember, but I know there were other where
I couldn't find the solution easily in manpages. And I didn't want to
have to look everything up in the Linux kernel source code. So the next
idea was to change the test suite so that it could run either on the
real filesystem, or on the mockfs. That way, I could ensure that the
behaviour was identical.

This proved to be more challenging than I thought, because for most
tests (chmod, chown, access control) you need to be root to run the test
suite. And I felt too uncomfortable running a test suite that could "rm
-rf /" by mistake, as root.

So the next idea was to write a framework where you could run test cases
within a chroot()'ed environment, so that (as long as you don't use
chroot() in you test cases) you were pretty safe not to wipe your harddisk.

This has finally worked out better than I had expected. I have a
"JailTestCase" that creates a new directory for every test case,
chroot()s to it in setUp(), runs the test case and exits the chroot jail
in tearDown() (that part was tricky). There is also a preJailEntry()
hook for e.g. unpacking a tar archive into the directory before entering
the chroot jail. The jail directories are never removed automatically,
so they can be examined in case of failure. Obviously, it works only on
*nix type systems.

I have also implemented a FileSystem class that allows the easy creation
of all filesystem entities (files, directories, pipes, sockets, ...).

Here's a class/def description of the library:

def enterJail(path):
def exitJail():

class JailTestCase(unittest.TestCase):
def setJailDir(path):
setJailDir = staticmethod(setJailDir)
def jailDir():
jailDir = staticmethod(jailDir)
def __init__(self, methodName='runTest'):
def preJailEntry(self):
def setUp(self):
def tearDown(self):

class RealFilesystem:
def createFile(self, path, mode=None, uid=None, gid=None,
atime=None, mtime=None, content=None):
def createDir(self, path, mode=None, uid=None, gid=None,
atime=None, mtime=None):
def createSymlink(self, path, uid=None, gid=None, atime=None,
mtime=None, target=None):
def createCharDevice(self, path, major, minor, mode=None,
uid=None, gid=None, atime=None, mtime=None):
def createBlockDevice(self, path, major, minor, mode=None,
uid=None, gid=None, atime=None, mtime=None):
def createPipe(self, path, mode=None, uid=None, gid=None,
atime=None, mtime=None):
def createSocket(self, path, mode=None, uid=None, gid=None,
atime=None, mtime=None):

So I am now at the point where I could resume working on mockfs. Now,
one of the reasons why I wanted a mockfs library (besides having to run
tests as root) was that I was afraid that using the real filesystem
would be too slow. Well, I was proven wrong while implementing this
ChrootJail module: it is actually quite fast. At the moment, I am
wondering if it wouldn't be more efficient to just polish up this
ChrootJail module and use that instead of a mockfs.

If you're interested, I can send you the module with its unit test
suite. Feedback is as always very welcome.

Best regards.
-- Remy
PS: Here's the class/def state of my mockfs (some functions are not yet
fully functional):

class Inode(object):
def Size(self):
def IsDirectory(self):
def IsSymLink(self):
def AddLink(self):
def RemoveLink(self):
def ExtraStatFields(self):
def Stat(self):

class DirectoryInode(Inode, dict):
def __setitem__(self, Key, Value):
def __delitem__(self, Key):
def clear(self):
def update(self, Rhs):
def setdefault(self, Key, Value):
def pop(self, *Args):
def popitem(self):

class FileInode(Inode):
class SymLinkInode(Inode):
class PipeInode(Inode):
class SocketInode(Inode):
class DeviceInode(Inode):
class BlockDeviceInode(DeviceInode):
class CharDeviceInode(DeviceInode):

class File(object):
def __init__(self, FileName, Mode="r", BufSize=-1):
def close(self):
def flush(self):
def read(self, Size=-1):
def readline(self, Size=-1):
def readlines(self, SizeHint=None):
def xreadlines(self):
def seek(self, Offset, Whence=0):
def tell(self):
def truncate(self, Size=None):
def write(self, Str):
def writelines(self, Sequence):
def __iter__(self):
def next(self):

class MockFilesystem(object):
def __init__(self):
def AddDirectory(self, Path, **KwArgs):
def AddFile(self, Path, **KwArgs):
def AddSymLink(self, Path, **KwArgs):
def AddPipe(self, Path, **KwArgs):
def AddSocket(self, Path, **KwArgs):
def AddBlockDevice(self, Path, **KwArgs):
def AddCharDevice(self, Path, **KwArgs):
def AddHardLink(self, Path, Target):
# Substitutes for os functions
def chdir(self, Path):
def getcwd(self):
def getcwdu(self):
def chroot(self, Path):
def chmod(self, Path, Mode):
def chown(self, Path, Uid, Gid):
def lchown(self, Path, Uid, Gid):
def listdir(self, Path):
def lstat(self, Path):
def readlink(self, Path):
def remove(self, Path):
def rmdir(self, Path):
def stat(self, Path):
def statvfs(self, Path):
def unlink(self, Path):
def utime(self, Path, Times):

Remove underscore and suffix in reply address for a timely response.

Jul 18 '05 #5
Mike Meyer wrote:
Peter Hansen <pe***@engcorp.com> writes:
The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.
Just out of curiosity, does your os implement some form of disk in
memory disk? Go to <URL: http://www.FreeBSD.org/cgi/man.cgi > and
search for either mfs or md for examples.


I need to be cross-platform, so Windows and Linux must both
be supported. I suspect there isn't good support on Windows
for the sort of thing you describe.

In any case, though I thank you and Jack for the ideas,
the pure-Python in-memory approach seems to be quite
viable and probably quite a bit simpler. In addition it
allows testing with paths and operations that could not
be safely supported if real file access was permitted at
all, so I think I'll stick with it.
Second, consider using os.sep for path seperation, so that testing can
be done correctly for the OS the project is running on. Or possibly a
flag to indicate whether or not you want to use os.sep.


I've never had to resort to using os.sep myself. I use
os.path.split() and os.path.join() and it seems they do the
job for me. ;-)

-Peter
Jul 18 '05 #6
Em Qui, 2004-11-04 Ã*s 21:31 -0500, Peter Hansen escreveu:
The term "mock filesystem" refers to code allowing unit
or acceptance tests to create, read and write, and manipulate
in other ways "virtual" files, without any actual disk
access. Everything is held in memory and therefore fast,
without risk of damaging real files, and with none of the
messiness of leftover files after testing.


Maybe StringIO is a good start point. Depending on what you need (if
it's just read/write), everything is already there.

Fabio
Jul 18 '05 #7
On Fri, 05 Nov 2004 01:04:34 -0600, Mike Meyer <mw*@mired.org> wrote:
....
Second, consider using os.sep for path seperation, so that testing can
be done correctly for the OS the project is running on. Or possibly a
flag to indicate whether or not you want to use os.sep.


The mock file system should probably have a really bizarre os.sep, to
provoke code which assumes '/'.

Overall, it's an interesting idea.

--
// Jorgen Grahn <jgrahn@ Ph'nglui mglw'nafh Cthulhu
\X/ algonet.se> R'lyeh wgah'nagl fhtagn!
Jul 18 '05 #8
Jorgen Grahn wrote:
The mock file system should probably have a really bizarre os.sep, to
provoke code which assumes '/'.


Nice idea! One could think of a variety of ways to use such
a thing to help improve "cross-platform-ness".
Jul 18 '05 #9
Peter Hansen schreef:
Just out of curiosity, does your os implement some form of disk in
memory disk? Go to <URL: http://www.FreeBSD.org/cgi/man.cgi > and
search for either mfs or md for examples.


I need to be cross-platform, so Windows and Linux must both
be supported. I suspect there isn't good support on Windows
for the sort of thing you describe.


DOS (and later Windows) have had "ram disks" for at least 20 years...

One freeware example for Windows:
<http://www.arsoft-online.de/products/product.php?id=1>

--
JanC

"Be strict when sending and tolerant when receiving."
RFC 1958 - Architectural Principles of the Internet - section 3.9
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Remy Blank | last post by:
Hello unittest users, In a project I am working on, I have a series of tests that have to be run as root, and others as a normal user. One solution is to separate the tests into two different...
36
by: Andrea Griffini | last post by:
I did it. I proposed python as the main language for our next CAD/CAM software because I think that it has all the potential needed for it. I'm not sure yet if the decision will get through, but...
0
by: Peter Hansen | last post by:
Along the lines of my post just now about a mock filesystem, I'm also interested in any work in the area of mock timing. Testing time-based* systems can be a real bitch. The most annoying part...
15
by: Josef Meile | last post by:
Hi, Textually from the highlights of python 2.4: "Assigning to None - the compiler now treats assigning to None as a SyntaxError." I think in general assignments to built-in types,...
1
by: ischenko | last post by:
There is a (relatively) widely used technique in unit testing, called mock objects. There is even a pMock library which provides a Mock class for a Python environment. Given the "duck typing"...
38
by: Christoph Zwerschke | last post by:
In August 2001, there was a thread about the "Art of Unit Testing": http://groups.google.com/group/comp.lang.python/browse_frm/thread/aa2bd17e7f995d05/71a29faf0a0485d5 Paul Moore asked the...
1
by: Steve Howell | last post by:
--- Steven Bethard <steven.bethard@gmail.comwrote: Changed the subject line. Nope, I haven't. I'm a tremendous advocate of unit testing, but I've never felt compelled to try out other...
1
by: mamoon | last post by:
I am using RHEL4. Last time while booting it shows "repair filesystem". i have used in this way sda1,sda2 and others are ok. BUT when i run this command on sda7 (which is mounted on root) it...
0
by: Fuzzyman | last post by:
Mock 0.4.0 has just been released, the first release in about ten months (but worth the wait). Mock is a simple library for testing: specifically for mocking, stubbing and patching. * Mock...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.