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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Peter Hansen

    #1

    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(se lf):
    def read(self):
    def write(self, data):
    def close(self):
    def __iter__(self):


    class FileSystem(obje ct):
    '''Acts like a real file system to support testing.'''
    def __init__(self, mocktime=False) :
    def _createFile(sel f, path, data):
    def _getFile(self, path):
    def open(self, path, mode='r'):

    Thanks for any pointers to more advanced stuff.

    -Peter
  • Jack Diederich

    #2
    Re: Has anyone released a Python "mock filesystem&quot ; for automatedtestin g?

    On Thu, Nov 04, 2004 at 09:31:04PM -0500, Peter Hansen wrote:[color=blue]
    > 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.[/color]

    If linux only support is OK you should check out FUSE
    Download Filesystem in Userspace for free. The FUSE project has moved to https://github.com/libfuse/

    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

    Comment

    • Mike Meyer

      #3
      Re: Has anyone released a Python "mock filesystem&quot ; for automatedtestin g?

      Peter Hansen <peter@engcorp. com> writes:
      [color=blue]
      > 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.[/color]

      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 <mwm@mired.or g> http://www.mired.org/home/mwm/
      Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

      Comment

      • Bengt Richter

        #4
        Re: Has anyone released a Python &quot;mock filesystem&quot ; for automated testing?

        On Thu, 04 Nov 2004 21:31:04 -0500, Peter Hansen <peter@engcorp. com> wrote:
        [color=blue]
        >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(se lf):
        > def read(self):
        > def write(self, data):
        > def close(self):
        > def __iter__(self):
        >
        >
        >class FileSystem(obje ct):
        > '''Acts like a real file system to support testing.'''
        > def __init__(self, mocktime=False) :
        > def _createFile(sel f, path, data):
        > def _getFile(self, path):
        > def open(self, path, mode='r'):
        >
        >Thanks for any pointers to more advanced stuff.
        >[/color]
        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.

        "Registerin g" 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('filen ame.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__('Str ingIO').StringI O("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

        Comment

        • Remy Blank

          #5
          Re: Has anyone released a Python &quot;mock filesystem&quot ; for automatedtestin g?

          Peter Hansen wrote:[color=blue]
          > 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.[/color]

          Not yet, not yet...
          [color=blue]
          > 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.[/color]

          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
          "JailTestCa se" 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(un ittest.TestCase ):
          def setJailDir(path ):
          setJailDir = staticmethod(se tJailDir)
          def jailDir():
          jailDir = staticmethod(ja ilDir)
          def __init__(self, methodName='run Test'):
          def preJailEntry(se lf):
          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(s elf, path, uid=None, gid=None, atime=None,
          mtime=None, target=None):
          def createCharDevic e(self, path, major, minor, mode=None,
          uid=None, gid=None, atime=None, mtime=None):
          def createBlockDevi ce(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(se lf, 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(sel f):
          def IsSymLink(self) :
          def AddLink(self):
          def RemoveLink(self ):
          def ExtraStatFields (self):
          def Stat(self):

          class DirectoryInode( Inode, dict):
          def __setitem__(sel f, Key, Value):
          def __delitem__(sel f, 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(In ode):
          class PipeInode(Inode ):
          class SocketInode(Ino de):
          class DeviceInode(Ino de):
          class BlockDeviceInod e(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(se lf, 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(s elf, Path, **KwArgs):
          def AddHardLink(sel f, 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.

          Comment

          • Peter Hansen

            #6
            Re: Has anyone released a Python &quot;mock filesystem&quot ; for automatedtestin g?

            Mike Meyer wrote:[color=blue]
            > Peter Hansen <peter@engcorp. com> writes:
            >[color=green]
            >>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.[/color]
            >
            > 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.[/color]

            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.
            [color=blue]
            > 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.[/color]

            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

            Comment

            • Fábio Mendes

              #7
              Re: Has anyone released a Python &quot;mock filesystem&quot ; for automatedtestin g?

              Em Qui, 2004-11-04 às 21:31 -0500, Peter Hansen escreveu:[color=blue]
              > 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.[/color]

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

              Fabio

              Comment

              • Jorgen Grahn

                #8
                Re: Has anyone released a Python &quot;mock filesystem&quot ; for automated testing?

                On Fri, 05 Nov 2004 01:04:34 -0600, Mike Meyer <mwm@mired.or g> wrote:
                ....[color=blue]
                > 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.[/color]

                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!

                Comment

                • Peter Hansen

                  #9
                  Re: Has anyone released a Python &quot;mock filesystem&quot ; for automatedtestin g?

                  Jorgen Grahn wrote:[color=blue]
                  > The mock file system should probably have a really bizarre os.sep, to
                  > provoke code which assumes '/'.[/color]

                  Nice idea! One could think of a variety of ways to use such
                  a thing to help improve "cross-platform-ness".

                  Comment

                  • JanC

                    #10
                    Re: Has anyone released a Python &quot;mock filesystem&quot ; for automated testing?

                    Peter Hansen schreef:
                    [color=blue][color=green]
                    >> 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.[/color]
                    >
                    > 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.[/color]

                    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

                    Comment

                    Working...