Example #1
0
  def build_dir(self):
    # Reads filenames; extends inums
    fn_to_ino = {}
    for symfn, fn in self.filenames.items():
      if not self.fs.root_dir.contains(symfn):
        continue
      syminum = self.fs.root_dir[symfn]
      fn_to_ino[fn] = self.inums[syminum]

    # Reads procs[pid].fds and procs[pid].vas; extends nothing
    (fdmap0, vamap0) = self.build_proc(False)
    (fdmap1, vamap1) = self.build_proc(True)

    # Compute known pipe end FDs.  This map is system-wide because,
    # for example, process 1 may be holding open a pipe that's only
    # used by testing in process 0.
    pipe_end_fds = collections.defaultdict(list)
    for pid, fdmap in [(False, fdmap0), (True, fdmap1)]:
      for fd, (symfd, inode) in fdmap.items():
        if symfd.ispipe:
          key = (z3util.HashableAst(symfd.pipeid.someval), symfd.pipewriter.val)
          if key not in pipe_end_fds:
            # Make sure both ends are in the map, even if we never
            # come across an example of the other end
            pipe_end_fds[key] = (symfd.pipeid, {True: 0, False: 0})
            okey = (key[0], not key[1])
            pipe_end_fds[okey] = (symfd.pipeid, {True: 0, False: 0})
          pipe_end_fds[key][1][pid] += 1

    setup = {'common': testgen.CodeWriter(),
             'proc0': testgen.CodeWriter(),
             'proc1': testgen.CodeWriter(),
             'procfinal': testgen.CodeWriter(),
             'final': testgen.CodeWriter()}

    try:
      # setup_proc reads nothing; extends inums, datavals, pipes
      self.emit = setup['proc0']
      self.setup_proc(False, fdmap0, vamap0, pipe_end_fds)
      self.emit = setup['proc1']
      self.setup_proc(True, fdmap1, vamap1, pipe_end_fds),
      # setup_inodes reads inums, pipes; extends datavals
      self.emit = setup['common']; self.setup_inodes()
      # setup_filenames reads nothing; extends nothing
      self.emit = setup['common']; self.setup_filenames(fn_to_ino)
      # setup_proc_finalize reads pipes; extends nothing
      self.emit = setup['procfinal']; self.setup_proc_finalize()
      # setup_inodes_finalize reads inums, pipes; extends nothing
      self.emit = setup['final']; self.setup_inodes_finalize()
    finally:
      self.emit = None
    return setup
Example #2
0
  def __check(self, res):
    """Return code to check the expected values of res.

    res must be a dictionary mapping variable names to expected
    values.  'errno' and DataVals are handled specially.
    """
    emit = testgen.CodeWriter()
    for var, val in res.items():
      if var == 'errno':
        continue
      if isinstance(val, DataVal):
        cval = val.first_byte
        var += '[0]'
      elif isinstance(val, fs_module.SOffset):
        # We can't map this through the per-file offsets interpreter
        # because we don't know which file to look in.
        cval = val.someval * DATAVAL_BYTES
      elif isinstance(val, simsym.Symbolic):
        # XXX Should we enumerate result values?  This might only come
        # up in lseek.
        cval = val.someval
      else:
        cval = val
      emit('expect_result("%s", %s, %d);' % (var, var, cval))
    if 'errno' in res:
      emit('expect_errno(%d);' % res['errno'])
    return emit
Example #3
0
    def on_model(self, testid, model, constraint):
        super(FsTestGenerator, self).on_model(testid, model, constraint)

        emit = testgen.CodeWriter()
        self.__pending_funcs.clear()

        try:
            emit("""\

/*
 * calls: %s
 */""" % " ".join(self.callset_names))
            fs = FsState(model['Fs'], self.sar, constraint)
            pids = []
            fns = {}
            for callidx, callname in enumerate(self.callset_names):
                # Generate test code for this call.  As a side-effect, this will
                # fill in structures we need to write the setup code.
                args = self.get_call_args(callidx)
                res = self.get_result(callidx)
                fns['test_%d' % callidx] \
                  = self.func(emit, 'int', 'test_%s_%d' % (testid, callidx),
                              fs.gen_code(callname, args, res))
                if hasattr(args, 'pid'):
                    pids.append(args.pid.val)
                else:
                    # Some calls don't take a pid because their process doesn't matter
                    pids.append(False)
            # Write setup code
            setup = fs.build_dir()
            for phase in ('common', 'proc0', 'proc1', 'final', 'procfinal'):
                fns['setup_' + phase] \
                  = self.func(emit, 'void', 'setup_%s_%s' % (testid, phase),
                              setup[phase])
        except SkipTest as e:
            print "Skipping test %s: %s" % (testid, e)
            return

        # Commit to this code
        self.__funcs.update(self.__pending_funcs)
        self.emit(emit)

        strargs = {
            'testid': testid,
            'pid0': pids[0],
            'pid1': pids[1],
            'name0': self.callset_names[0],
            'name1': self.callset_names[1]
        }
        strargs.update(fns)
        self.fstests.append("""\
  { "fs-%(testid)s",
    &%(setup_common)s,
    { { &%(setup_proc0)s }, { &%(setup_proc1)s } },
    &%(setup_procfinal)s,
    &%(setup_final)s,
    { { &%(test_0)s, %(pid0)d, "%(name0)s" },
      { &%(test_1)s, %(pid1)d, "%(name1)s" } },
    &cleanup }""" % strargs)
Example #4
0
 def gen_code(self, callname, args, res):
   f = getattr(self, callname)
   self.emit = writer = testgen.CodeWriter()
   try:
     f(args, res.copy())
   finally:
     self.emit = None
   return writer
Example #5
0
 def gen_code(self, callname, args, res):
   f = getattr(self, callname, None)
   if f is None:
     raise SkipTest('Test generation for %s not implemented' % callname)
   self.emit = writer = testgen.CodeWriter()
   try:
     f(args, res.copy())
   finally:
     self.emit = None
   return writer
Example #6
0
 def func(self, emit, ret, fname, body):
   key = (ret, str(body))
   existing = self.__funcs.get(key)
   code = 'static %s %s(void) {\n%s\n}' % (ret, fname, body.indent())
   if existing is None:
     self.__pending_funcs[key] = fname
     emit(code)
     return fname
   else:
     # Put the original body in as a comment for readability
     emit(testgen.CodeWriter()(code).indent('// '))
     emit('// ^ See %s' % existing)
     return existing
Example #7
0
  def __init__(self, test_file_name):
    super(FsTestGenerator, self).__init__(test_file_name)
    self.emit = testgen.CodeWriter(open(test_file_name, 'w'))
    self.fstests = []
    self.__funcs = {}
    self.__pending_funcs = {}

    # Get some constants from fs
    global DATAVAL_BYTES
    DATAVAL_BYTES = fs_module.DATAVAL_BYTES

    self.emit("""\
//+++ common
#define _GNU_SOURCE 1
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stdbool.h>
#include "fstest.h"

__attribute__((__unused__)) static void
init_map_anon(uintptr_t va, bool writable, char value)
{
  char *r = mmap((void*)va, 4096, PROT_READ | PROT_WRITE,
                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  if (r == MAP_FAILED) setup_error("mmap");
  *r = value;
  if (!writable) {
    int r2 = mprotect(r, 4096, PROT_READ);
    if (r2 < 0) setup_error("mprotect");
  }
  // Ensure test cores don't shoot down the setup core
  xinvalidate(r, 4096);
}

__attribute__((__unused__)) static void
init_map_file(uintptr_t va, bool writable, const char *fname, off_t offset)
{
  int fd = open(fname, O_RDWR);
  if (fd < 0) setup_error("open");
  void *r = mmap((void*)va, 4096, PROT_READ | (writable ? PROT_WRITE : 0),
                 MAP_SHARED | MAP_FIXED, fd, offset);
  if (r == MAP_FAILED) setup_error("mmap");
  close(fd);
}
""")

    # Generate datavals
    for i, d in enumerate(all_datavals):
      self.emit("__attribute__((__weak__)) const char %s[%d] = {%d};" %
                (d.expr, DATAVAL_BYTES, d.first_byte))
    # Create a buffer for datavals.  This is in the BSS, so we'll
    # touch it after fork (unlike, say, if it were on the stack).
    self.emit("__attribute__((__weak__)) char datavalbuf[%d];" % DATAVAL_BYTES)
    self.emit()

    self.emit("//+++ tests")