Ejemplo n.º 1
0
 /**
  * This does the work of main, but it never calls System.exit, so it is appropriate to be called
  * progrmmatically. Termination of the program with a message to the user is indicated by throwing
  * Daikon.TerminationMessage.
  *
  * @see #main(String[])
  * @see daikon.Daikon.TerminationMessage
  */
 public static void mainHelper(final String[] args)
     throws FileNotFoundException, IOException, ClassNotFoundException {
   daikon.LogHelper.setupLogs(daikon.LogHelper.INFO);
   LongOpt[] longopts =
       new LongOpt[] {
         new LongOpt(Daikon.suppress_redundant_SWITCH, LongOpt.NO_ARGUMENT, null, 0),
         new LongOpt(Daikon.config_option_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0),
         new LongOpt(Daikon.debugAll_SWITCH, LongOpt.NO_ARGUMENT, null, 0),
         new LongOpt(Daikon.debug_SWITCH, LongOpt.REQUIRED_ARGUMENT, null, 0),
       };
   Getopt g = new Getopt("daikon.ExtractConsequent", args, "h", longopts);
   int c;
   while ((c = g.getopt()) != -1) {
     switch (c) {
       case 0:
         // got a long option
         String option_name = longopts[g.getLongind()].getName();
         if (Daikon.help_SWITCH.equals(option_name)) {
           System.out.println(usage);
           throw new Daikon.TerminationMessage();
         } else if (Daikon.suppress_redundant_SWITCH.equals(option_name)) {
           Daikon.suppress_redundant_invariants_with_simplify = true;
         } else if (Daikon.config_option_SWITCH.equals(option_name)) {
           String item = Daikon.getOptarg(g);
           daikon.config.Configuration.getInstance().apply(item);
           break;
         } else if (Daikon.debugAll_SWITCH.equals(option_name)) {
           Global.debugAll = true;
         } else if (Daikon.debug_SWITCH.equals(option_name)) {
           LogHelper.setLevel(Daikon.getOptarg(g), LogHelper.FINE);
         } else {
           throw new RuntimeException("Unknown long option received: " + option_name);
         }
         break;
       case 'h':
         System.out.println(usage);
         throw new Daikon.TerminationMessage();
       case '?':
         break; // getopt() already printed an error
       default:
         System.out.println("getopt() returned " + c);
         break;
     }
   }
   // The index of the first non-option argument -- the name of the file
   int fileIndex = g.getOptind();
   if (args.length - fileIndex != 1) {
     throw new Daikon.TerminationMessage("Wrong number of arguments." + Daikon.lineSep + usage);
   }
   String filename = args[fileIndex];
   PptMap ppts =
       FileIO.read_serialized_pptmap(
           new File(filename), true // use saved config
           );
   extract_consequent(ppts);
 }
    private void add(PptTopLevel ppt, ValueTuple vt, int nonce) {

      // if this is a numbered exit, apply to the combined exit as well
      if (ppt.ppt_name.isNumberedExitPoint()) {

        // Daikon.create_combined_exits(all_ppts);
        PptTopLevel parent = all_ppts.get(ppt.ppt_name.makeExit());
        if (parent != null) {
          parent.get_missingOutOfBounds(ppt, vt);
          add(parent, vt, nonce);

        } else {
          // make parent and apply

          // this is a hack. it should probably filter out orig and derived
          // vars instead of taking the first n.
          int len = ppt.num_tracevars + ppt.num_static_constant_vars;
          VarInfo[] exit_vars = new VarInfo[len];
          for (int j = 0; j < len; j++) {
            exit_vars[j] = new VarInfo(ppt.var_infos[j]);
            exit_vars[j].varinfo_index = ppt.var_infos[j].varinfo_index;
            exit_vars[j].value_index = ppt.var_infos[j].value_index;
            exit_vars[j].equalitySet = null;
          }

          parent = new PptTopLevel(ppt.ppt_name.makeExit().getName(), exit_vars);
          Daikon.init_ppt(parent, all_ppts);
          all_ppts.add(parent);
          parent.get_missingOutOfBounds(ppt, vt);
          add(parent, vt, nonce);
        }
      }

      // If the point has no variables, skip it
      if (ppt.var_infos.length == 0) {
        // The sample should be skipped but Daikon does not do this so
        // DaikonSimple will not do this to be consistent.
        // The better idea is for Daikon to assert that these valuetuples are
        // empty and then skip the sample.
        assert vt.size() == 0;
        return;
      }

      // Instantiate slices and invariants if this is the first sample
      if (ppt.num_samples() == 0) {
        instantiate_views_and_invariants(ppt);
      }

      // manually inc the sample number because DaikonSimple does not
      // use any of PptTopLevel's add methods which increase the sample
      // number
      ppt.incSampleNumber();

      // Loop through each slice
      for (Iterator<PptSlice> i = ppt.views_iterator(); i.hasNext(); ) {
        PptSlice slice = i.next();
        Iterator<Invariant> k = slice.invs.iterator();
        boolean missing = false;

        for (VarInfo v : slice.var_infos) {
          // If any var has encountered out of array bounds values,
          // stop all invariants in this slice. The presumption here is that
          // an index out of bounds implies that the derived variable (eg a[i])
          // doesn't really make any sense (essentially that i is not a valid
          // index for a). Invariants on the derived variable are thus not
          // relevant.
          // If any variables are out of bounds, remove the invariants
          if (v.missingOutOfBounds()) {
            while (k.hasNext()) {
              Invariant inv = k.next();
              k.remove();
            }
            missing = true;
            break;
          }

          // If any variables are missing, skip this slice
          if (v.isMissing(vt)) {
            missing = true;
            break;
          }
        }

        // keep a list of the falsified invariants
        if (!missing) {
          while (k.hasNext()) {

            Invariant inv = k.next();
            Invariant pre_inv = inv.clone();
            for (VarInfo vi : inv.ppt.var_infos) {
              assert vt.getValue(vi) != null : vi;
            }
            if (inv.ppt instanceof PptSlice2) assert inv.ppt.var_infos.length == 2;
            InvariantStatus status = inv.add_sample(vt, 1);
            if (status == InvariantStatus.FALSIFIED) {
              k.remove();
            }
          }
        }

        // update num_samples and num_values of a slice manually
        // because DaikonSimple does not call any of PptTopLevel's
        // add methods
        for (int j = 0; j < vt.vals.length; j++) {
          if (!vt.isMissing(j)) {
            ValueSet vs = ppt.value_sets[j];
            vs.add(vt.vals[j]);
          }
        }
        ppt.mbtracker.add(vt, 1);
      }
    }
  /**
   * This does the work of main, but it never calls System.exit, so it is appropriate to be called
   * progrmmatically. Termination of the program with a message to the user is indicated by throwing
   * Daikon.TerminationMessage.
   *
   * <p>Difference from Daikon's mainHelper: turn off optimization flags (equality, dynamic
   * constants, NIS suppression).
   *
   * @see #main(String[])
   * @see daikon.Daikon.TerminationMessage
   * @see daikon.Daikon#mainHelper(String[])
   */
  public static void mainHelper(final String[] args) throws IOException, FileNotFoundException {

    // set up logging information
    daikon.LogHelper.setupLogs(daikon.LogHelper.INFO);

    // No optimizations used in the simple incremental algorithm so
    // optimizations are turned off.
    Daikon.use_equality_optimization = false;
    Daikon.dkconfig_use_dynamic_constant_optimization = false;
    Daikon.suppress_implied_controlled_invariants = false;
    NIS.dkconfig_enabled = false;

    // The flag tells FileIO and Daikon to use DaikonSimple
    // specific methods (e.g. FileIO.read_declaration_file).
    // When FileIO reads and processes
    // samples, it must use the SimpleProcessor rather than the
    // default Processor.
    Daikon.using_DaikonSimple = true;

    // Read command line options
    Daikon.FileOptions files = Daikon.read_options(args, usage);
    // DaikonSimple does not supply nor use the spinfo_files and map_files
    Set<File> decls_files = files.decls;
    Set<String> dtrace_files = files.dtrace;

    if ((decls_files.size() == 0) && (dtrace_files.size() == 0)) {
      throw new Daikon.TerminationMessage("No .decls or .dtrace files specified");
    }

    // Create the list of all invariant types
    Daikon.setup_proto_invs();

    // Create the program points for enter and numbered exits and
    // initializes the points (adding orig and derived variables)
    all_ppts = FileIO.read_declaration_files(decls_files);

    // Create the combined exits (and add orig and derived vars)
    // Daikon.create_combined_exits(all_ppts);

    // Read and process the data trace files
    SimpleProcessor processor = new SimpleProcessor();
    FileIO.read_data_trace_files(dtrace_files, all_ppts, processor, true);

    // System.exit(0);

    // Print out the invariants for each program point (sort first)
    for (Iterator<PptTopLevel> t = all_ppts.pptIterator(); t.hasNext(); ) {
      PptTopLevel ppt = t.next();

      // We do not need to print out program points that have not seen
      // any samples.
      if (ppt.num_samples() == 0) {
        continue;
      }
      List<Invariant> invs = PrintInvariants.sort_invariant_list(ppt.invariants_vector());
      List<Invariant> filtered_invs = Daikon.filter_invs(invs);
      // The dkconfig_quiet printing is used for creating diffs between
      // DaikonSimple
      // and Daikon's output. The second kind of printing is used for
      // debugging. Since the names of the program points are the same for both
      // Daikon and DaikonSimple, diffing the two output will result in
      // only differences in the invariants, but we can not see at which program
      // points these differing invariants appear. Using the second kind of
      // printing,
      // Daikon's output does not have the '+' in the program point name, so in
      // addition
      // to the invariants showing up in the diff, we will also see the program
      // point
      // names.

      if (Daikon.dkconfig_quiet) {
        System.out.println("====================================================");
        System.out.println(ppt.name());
      } else {
        System.out.println("===================================================+");
        System.out.println(ppt.name() + " +");
      }

      // Sometimes the program points actually differ in number of
      // samples seen due to differences in how Daikon and DaikonSimple
      // see the variable hierarchy.
      System.out.println(ppt.num_samples());

      for (Invariant inv : filtered_invs) {
        System.out.println(inv.getClass());
        System.out.println(inv);
      }
    }
  }