views:

357

answers:

4

I'm trying to create a test that simulates a system failure to ensure the integrity of a Oracle Berkeley DB XML database. Data loss is currently being experienced during an insert operation so I'd like to setup a test that starts inserting an arbitrary number of documents and sack the process along the way (akin to someone yanking the power cord). After the process dies I want to spawn a new process and open the database to ensure it opens properly.

The unit test is one of many in a maven build and this test has to run in linux and windows XP environments. My current thought process is to hammer out a script for both operating systems since I can use the script to kill the process and start a new one in its place. Do I have any other options? Can I create a separate process space / VM using JUnit?

+1  A: 

I wouldn't consider this kind of test a unit test but nevertheless you may be able to do something like this.

  1. Use the ProcessBuilder class to construct and start the process, store the returned Process object.
  2. Start inserting records.
  3. At some point destroy() the process.

Please bear in mind previous comments on the non-deterministic nature of this test.

I have come across the SQLite team also doing a simulated failure strategy as part of their automated test suite.

BenM
A: 

This type of behavior is perfect for transactions. If your code were to start a transaction, the database would know how to keep the data consistent when a transaction aborted due to a process dying. You might be reinventing the wheel here. The Daily WTF has a good example of how we fool ourselves into reinventing the wheel.

Take a good hard look at your first revision and say to yourself, "gloves."

Kelly French
You're preaching to the choir. I was told we couldn't use the transactional version of the DB...so I think I'll need to ask "why not?" before going much further.
toddk
A: 

What about using just threads insead of whole process? For example:

  • You can create a background worker thread and give it a few loads of work.
  • Then in main test's thread wait a random number of milisecond. Then kill the thread.
  • Then maybe you want to wait again to have cached data saved (or not, depending on what you are testing)
  • Then run your sanity. If it's throwing, the test will fail here as you need!
  • Here you are done.

I would rather call the above test an integration test. Anyway it will do what you needed. Running will multiple times will test different data corruption case on each run.

Tomas Tintera
A: 

I would not consider this suitable for a UNIT test. in unit tests you want to test small sections of code, for example your sanity code, possibly with a mock DB. or by calling only part of your code. What you are referring to is a more complicated test that may be worth doing but not necessarily worth automating and running repeatedly as part of your unit tests which you presumably run fairly often(on build or nightly or whenever). Adding this kind of test will also probably slow down your unit testing and will impose restrictions on the environment your unit testing can run in. I suggest writing smaller unit tests, and testing the whole thing together separately.

Me.

Meir