views:

103

answers:

3

I'm looking for the cross-platform way to test some features in my application which required access to the filesystem (to write and read binary data). In the real life my application running on Linux and store special data in /usr/local/etc directory. But main part of the application is cross-platform library and it should be tested both on Windows and Linux. Furthermore, I don't want for my tests to write/read data directly to /usr/local/etc because in that case it will break test isolation.

So I'm thinking about replacing real access to the filesystem with special emulator of filesystem. Thus every test which required access to the filesystem can create new instance of vistual filesystem object and I can run tests in isolation, and properly support testing on Windows.

I've tried to find some existing open/free implementation, but so far found none for C code. Any hints?

UPDATE: Linux-only solutions with chroot is not option for me.

+1  A: 

Under linux you can do the fakeroot trick: LD_PRELOAD a library which intercepts open, read and write calls and redirect them to whatever you want to do. I don't know if there is an equivalent way to inject code this way into a windows binary.

chroot is another way to give the test program its own fs hierarchy. You can also try to write your own libc stubs for fopen and friends and link this lib to your test program, but this will not intercept calls made by other libraries.

Another approach could be an io abstraction layer, like openssl BIO, where the io calls can easily be intercepted by replacing the abstraction library.

Rudi
`chroot` is likely the easy option.
caf
Yes, I'm thinking about IO abstraction layer approach, but then anyway I need implementation of my fake filesystem for testing.Other linux-only solutions is no option for me.
bialix
You have to make sure that your fake library handles all file access routines that your application uses either directly or indirectly. It would be very easy to miss `ioctl` or `fcntl` but there are also things like `pwrite` and `writev` to consider. These could all be used by libc even if you don't call them. And most likely stdout, stderr, and stdin would still need to work normally. Same arguments hold for trying to wrap the stdio functionality. If you do this I suggest having your open return high positive file descriptors.
nategoose
+1  A: 

What about testing under qemu and starting each run with the same pre-crafted filesystem image?

R..
It's overly complicated. Simpler solution found.
bialix
+3  A: 

I would make the filesystem location configurable - either with a command-line option, or with an environment variable (both of these work just as well with Linux and Windows).

The default can be /usr/local/etc/, but for testing (or on Windows) you can specify a different location. If you are running multiple commands then the environment variable method works particularly well, as you can set the variable once, then just run the commands the same way they would be run if they were using the default storage location.

For both methods, it's worth considering whether there are any security implications in having the location configurable - usually there won't be (the executable will only be able to do things that the user could have already done), but if you're running the executable setuid you may need more thought.

psmears
Thank you. It's very simple solution and it should work for me. Initially I've thought that using fake filesystem will be better. So I've missed this obvious solution. Thank you for idea.
bialix