Przeglądaj źródła

Added test.py support for tmpfs-backed disks

RAM-backed testing is faster than file-backed testing. This is why
test.py uses rambd by default.

So why add support for tmpfs-backed disks if we can already run tests in
RAM? For reentrant testing.

Under reentrant testing we simulate power-loss by forcefully exiting the
test program at specific times. To make this power-loss meaningful, we need to
persist the disk across these power-losses. However, it's interesting to
note this persistence doesn't need to be actually backed by the
filesystem.

It may be possible to rearchitecture the tests to simulate power-loss a
different way, by say, using coroutines or setjmp/longjmp to leave
behind ongoing filesystem operations without terminating the program
completely. But at this point, I think it's best to work with what we
have.

And simply putting the test disks into a tmpfs mount-point seems to
work just fine.

Note this does force serialization of the tests, which isn't required
otherwise. Currently they are only serialized due to limitations in
test.py. If a future change wants to perallelize the tests, it may need
to rework RAM-backed reentrant tests.
Christopher Haster 5 lat temu
rodzic
commit
f4b17b379c
2 zmienionych plików z 15 dodań i 6 usunięć
  1. 6 0
      .travis.yml
  2. 9 6
      scripts/test.py

+ 6 - 0
.travis.yml

@@ -15,6 +15,12 @@ script:
         -Duser_provided_block_device_sync=NULL
         -include stdio.h"
 
+  # setup a ram-backed disk to speed up reentrant tests
+  - |
+    mkdir disks
+    sudo mount -t tmpfs -o size=100m tmpfs disks
+    export TFLAGS="$TFLAGS --disk=disks/disk"
+
   # run tests
   - make clean test TFLAGS+="-nrk"
 

+ 9 - 6
scripts/test.py

@@ -200,22 +200,25 @@ class TestCase:
             return True
 
     def test(self, exec=[], persist=False, cycles=None,
-            gdb=False, failure=None, **args):
+            gdb=False, failure=None, disk=None, **args):
         # build command
         cmd = exec + ['./%s.test' % self.suite.path,
             repr(self.caseno), repr(self.permno)]
 
         # persist disk or keep in RAM for speed?
         if persist:
+            if not disk:
+                disk = self.suite.path + '.disk'
             if persist != 'noerase':
                 try:
-                    os.remove(self.suite.path + '.disk')
+                    with open(disk, 'w') as f:
+                        f.truncate(0)
                     if args.get('verbose', False):
-                        print('rm', self.suite.path + '.disk')
+                        print('truncate --size=0', disk)
                 except FileNotFoundError:
                     pass
 
-            cmd.append(self.suite.path + '.disk')
+            cmd.append(disk)
 
         # simulate power-loss after n cycles?
         if cycles:
@@ -704,8 +707,6 @@ def main(**args):
                         stdout = perm.result.stdout[:-1]
                     else:
                         stdout = perm.result.stdout
-                    if (not args.get('verbose', False) and len(stdout) > 5):
-                        sys.stdout.write('...\n')
                     for line in stdout[-5:]:
                         sys.stdout.write(line)
                 if perm.result.assert_:
@@ -766,4 +767,6 @@ if __name__ == "__main__":
         help="Run non-leaky tests under valgrind to check for memory leaks.")
     parser.add_argument('-e', '--exec', default=[], type=lambda e: e.split(' '),
         help="Run tests with another executable prefixed on the command line.")
+    parser.add_argument('-d', '--disk',
+        help="Specify a file to use for persistent/reentrant tests.")
     sys.exit(main(**vars(parser.parse_args())))