//===- DSTest.cpp - Queries DSA results for testing -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines various commandline options to DSA to help in regression tests.
// These options are:
// -print-node-for-value=<list>     Print the DSNodes for the given values
//   -print-only-flags                Only print Flags for the given values
//   -print-only-values               Only print the values pointed to by the given values
//   -print-only-types                Only print the types for the given values
// -check-same-node=<list>          Verify the given values' nodes were merged.
// -check-not-same-node=<list>      Verify the given values' nodes weren't merged.
// -check-type=<list>,type          Verify the given nodes have the given type
// -check-callees=caller,<list>     Verify the given caller has the following callees
// -check-not-callees=caller,<list> Verify the given caller does not have the following callees
// -verify-flags=<list>             Verify the given values match the flag specifications.
//
// In general a 'value' query on the DSA results looks like this:
// graph:value[:offset]*
//  Examples:
//    "value"  specifies 'value' in the globals graph
//    "func:value" specifies 'value' in graph for function 'func'
//    "func:value:0" the node pointed to at offset 0 from the above
//    "func:value:0:1" the node pointed to at offset 1 from the above
//    ..etc
//    We are also robust to "@value" and "@func" notation for convenience
// The -verify-flags option takes values in this format, but also followed
// by any number of 'flag specifiers' of the form '+flags' and '-flags',
// which indicate flags that the node should and shouldn't have.
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dsgraph-test"

#include "dsa/DataStructure.h"
#include "dsa/DSGraph.h"
#include "dsa/DSNode.h"
#include "dsa/DSCallGraph.h"
#include "llvm/Module.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Assembly/Writer.h"
using namespace llvm;

namespace {
  cl::list<std::string> PrintNodesForValues("print-node-for-value",
      cl::CommaSeparated, cl::ReallyHidden);
  cl::opt<bool> OnlyPrintFlags("print-only-flags", cl::ReallyHidden);
  cl::opt<bool> OnlyPrintValues("print-only-values", cl::ReallyHidden);
  cl::opt<bool> OnlyPrintTypes("print-only-types", cl::ReallyHidden);
  // Test if all mentioned values are in the same node (merged)
  cl::list<std::string> CheckNodesSame("check-same-node",
      cl::CommaSeparated, cl::ReallyHidden);
  // Test if all mentioned values are in distinct nodes
  cl::list<std::string> CheckNodesNotSame("check-not-same-node",
      cl::CommaSeparated, cl::ReallyHidden);
  // For each value, verify they have (or don't have) the specified flags
  cl::list<std::string> VerifyFlags("verify-flags",
      cl::CommaSeparated, cl::ReallyHidden);
  // For each value, verify that type is as given
  cl::list<std::string> CheckType("check-type",
      cl::CommaSeparated, cl::ReallyHidden);
  // For first function, verify that it calls the other functions
  cl::list<std::string> CheckCallees("check-callees",
      cl::CommaSeparated, cl::ReallyHidden);
  // For first function, verify that it does not call the other functions
  cl::list<std::string> CheckNotCallees("check-not-callees",
      cl::CommaSeparated, cl::ReallyHidden);
}

typedef std::set<const Function*> FuncSetTy;

/// NodeValue -- represents a particular node in a DSGraph
/// constructed from a serialized string representation of a value
///
/// FIXME: Make this integrated into cl parsing, as mentioned:
///   http://llvm.org/docs/CommandLine.html#customparser
///
/// FIXME: Support querying special nodes like return nodes, VANodes, etc
class NodeValue {
  // Containing Function, if applicable.
  Function *F;
  Module *ParentM;
  // Value in that graph's scalarmap that we base off of
  // (note that the NH we have below could be indexed a few times
  // from this value, only corresponds directly if no offsets)
  Value *V;
  // DSNodehandle
  DSNodeHandle NH;

  // String version (that we were given)
  std::string serialized;

  // Parsed list of offsets
  typedef SmallVector<unsigned,3> OffsetVectorTy;
  OffsetVectorTy offsets;

  NodeValue() {}
  void operator=(const NodeValue&);
  NodeValue(const NodeValue&);

  void initialize(const Module *M, const DataStructures *DS) {
    parseValue(M);
    assert(V && "Failed to parse value?");
    if (isa<GlobalValue>(V)) {
      DSGraph *G = DS->getGlobalsGraph();
      assert(G->hasNodeForValue(V) && "Node not in specified graph!");
      NH = G->getNodeForValue(V);
    } else {
      assert(F && "No function?");
      DSGraph *G = DS->getDSGraph(*F);
      assert(G->hasNodeForValue(V) && "Node not in specified graph!");
      NH = G->getNodeForValue(V);
    }
    // Handle offsets, if any
    // For each offset in the offsets vector, follow the link at that offset
    for (OffsetVectorTy::const_iterator I = offsets.begin(), E = offsets.end();
        I != E; ++I ) {
      assert(!NH.isNull() && "Null NodeHandle?");
      assert(NH.hasLink(*I) && "Handle doesn't have link?");
      // Follow the offset
      NH = NH.getLink(*I);
    }
  }

  /// stripOffsets -- strips the offsets
  /// Walks backwards, stripping offsets.
  /// Returns serialized without the offsets
  ///
  std::string stripOffsets() {
    std::vector<unsigned> offsets_reversed;
    SmallVector<StringRef,5> colonSeparated;
    StringRef serializedRef = serialized;
    serializedRef.split(colonSeparated,":");
    SmallVector<StringRef,5>::reverse_iterator I = colonSeparated.rbegin(),
      E = colonSeparated.rend();
    for(; I != E; ++I ) {
      unsigned offset;
      // If this isn't an integer (offset), then bail
      if (I->getAsInteger(0,offset))
        break;
      offsets_reversed.push_back(offset);
    }
    // Okay so we built reversed list of offsets, now put things back together

    // If we have more than 2 values left, then we have something like:
    // name1:name2:name3[:offset]*, which is no good.
    // Also, if we have *nothing* left, something is similarly wrong.
    assert(((E - I) > 0) && "Node was entirely made of offsets?");
    assert(((E - I) <= 2) && "Too many colons! (Invalid node/offset given)");

    // Now rebuild the string, without the offsets.
    std::string rebuilt = I++->str();
    for(; I != E; ++I) {
      rebuilt = I->str() + ":" + rebuilt;
    }

    // Reverse the offsets (since we parsed backwards) and put the result
    // into the 'offsets' vector for use elsewhere.
    offsets.insert(offsets.begin(),
        offsets_reversed.rbegin(),offsets_reversed.rend());

    return rebuilt;
  }


  /// parseValue -- sets value for the string we were constructed on,
  /// using the provided module as the context to find the value
  void parseValue(const Module *M) {
    // Parse the offsets, and remove from the string
    StringRef stripped = stripOffsets();

    unsigned count = stripped.count(':');
    if (count == 0) {
      // Global case
      // format: "[@]value"
      StringRef globalName = stripAtIfRequired(stripped);

      V = M->getNamedValue(globalName);
      assert(V && "Unable to find specified global!");
    } else if (count == 1) {
      // Function-specific case
      // format: "[@]func:value"

      std::pair<StringRef,StringRef> split = stripped.split(':');
      StringRef func = stripAtIfRequired(split.first);
      StringRef value = split.second;

      // First, find the function
      F = M->getFunction(func);
      ParentM = const_cast<Module*>(M);
      assert(F && "Unable to find function specified!");

      // Now we try to find the value...
      // FIXME: This only works for named values, things like "%1" don't work.
      // That might not be a deal breaker, but should be clear.
      V = F->getValueSymbolTable().lookup(value);

      assert(V && "Unable to find value in specified function!");

    } else {
      assert(0 && "Too many colons, offsets not stripped?");
    }

    assert(V && "Parsing value failed!");
  }

  /// stripAtIfRequired -- removes the leading '@' character if one exists
  ///
  StringRef stripAtIfRequired(StringRef v) {
    if (!v.startswith("@"))
        return v;

    assert(v.size() > 1 && "String too short");

    return v.substr(1);
  }
public:
  /// Constructor (from string)
  NodeValue(std::string & raw, const Module * M, const DataStructures *DS)
    : F(NULL), V(NULL), serialized(raw) {
      initialize(M,DS);
      assert(V && NH.getNode() && "Parse failed!");
  }

  /// Accessors
  DSNodeHandle & getNodeH() { return NH;                          }
  DSGraph  * getGraph()     { return getNode()->getParentGraph(); }
  // FIXME: These two (value/function) aren't used presently, and furthermore
  // are a bit confusing in the context of offsets.  Make this not lame.
  Value    * getValue()     { return V;                           }
  Function * getFunction()  { return F;                           }
  Module * getParentModule()  { return ParentM;                           }

  /// Helper to fetch the node from the nodehandle
  DSNode * getNode() {
    assert(NH.getNode() && "NULL node?");
    return NH.getNode();
  }
};

/// printAllValuesForNode -- prints all values for a given node, without a newline
/// (meant to be a helper)
static void printAllValuesForNode(llvm::raw_ostream &O, NodeValue &NV) {
  // We only consider other values that are in the graph
  // containing the specified node (by design)

  // Look for values that have an equivalent NH
  DSNodeHandle &NH = NV.getNodeH();
  const DSGraph::ScalarMapTy &SM = NV.getGraph()->getScalarMap();
  bool first = true;

  for (DSGraph::ScalarMapTy::const_iterator I = SM.begin(), E = SM.end();
      I != E; ++I )
    if (NH == I->second) {
      //Found one!
      const Value *V = I->first;

      //Print them out, separated by commas
      if (!first) O << ",";
      first = false;

      // Print out name, if it has one.
      // FIXME: Get "%0, "%1", naming like the .ll has?
      if (V->hasName())
        O << V->getName();
      else
        O << "<tmp>";
    }

  //FIXME: Search globals in this graph too (not just scalarMap)?
}

// printTypesForNode --prints all the types for the given NodeValue, without a newline
// (meant to be called as a helper)
static void printTypesForNode(llvm::raw_ostream &O, NodeValue &NV) {
  DSNode *N = NV.getNode();

  if (N->isNodeCompletelyFolded()) {
    O << "Folded";
  }
  // Go through all the types, and just dump them.
  // FIXME: Lifted from Printer.cpp, probably should be shared
  bool firstType = true;
  if (N->type_begin() != N->type_end())
    for (DSNode::TyMapTy::const_iterator ii = N->type_begin(),
        ee = N->type_end(); ii != ee; ++ii) {
      if (!firstType) O << "::";
      firstType = false;
      O << ii->first << ":";
      if (ii->second) {
        bool first = true;
        for (svset<Type*>::const_iterator ni = ii->second->begin(),
            ne = ii->second->end(); ni != ne; ++ni) {
          if (!first) O << "|";
          Type * t = *ni;
          t->print (O);
          first = false;
        }
      }
      else
        O << "VOID";
    }
  else
    O << "VOID";

  if (N->isArrayNode())
    O << "Array";
}

FuncSetTy
getCalleesFor(const Function * caller, const DSCallGraph & cg)
{
  FuncSetTy callees;

  Function const*leader = cg.sccLeader(&*caller);

  // Add all methods in same SCC as caller...
  for(DSCallGraph::scc_iterator sccii = cg.scc_begin(leader),
      sccee = cg.scc_end(leader); sccii != sccee; ++sccii)
    callees.insert(*sccii);

  // And all methods in the SCC's called by the caller
  for(DSCallGraph::flat_iterator CI = cg.flat_callee_begin(caller);
      CI != cg.flat_callee_end(caller); CI ++) {
    callees.insert(*CI);
    for(DSCallGraph::scc_iterator sccii = cg.scc_begin(*CI),
        sccee = cg.scc_end(*CI); sccii != sccee; ++sccii)
      callees.insert(*sccii);
  }

  return callees;
}

static void printCallees(FuncSetTy & Funcs, raw_ostream & O)
{
  FuncSetTy::iterator I = Funcs.begin(),
                      E = Funcs.end();
  if (I != E)
  {
    O << (*I)->getName();
    while(++I != E)
      O << ", " << (*I)->getName();
  }
}

static std::string getFlags(DSNode *N) {
  std::string flags("");

  // FIXME: This code is lifted directly from Printer.cpp
  // Probably would be good to make this code shared...
  // Leaving it separate for now to minimize invasiveness
  if (unsigned NodeType = N->getNodeFlags()) {
    if (NodeType & DSNode::AllocaNode       ) flags += "S";
    if (NodeType & DSNode::HeapNode         ) flags += "H";
    if (NodeType & DSNode::GlobalNode       ) flags += "G";
    if (NodeType & DSNode::UnknownNode      ) flags += "U";
    if (NodeType & DSNode::IncompleteNode   ) flags += "I";
    if (NodeType & DSNode::ModifiedNode     ) flags += "M";
    if (NodeType & DSNode::ReadNode         ) flags += "R";
    if (NodeType & DSNode::ExternalNode     ) flags += "E";
    if (NodeType & DSNode::ExternFuncNode   ) flags += "X";
    if (NodeType & DSNode::IntToPtrNode     ) flags += "P";
    if (NodeType & DSNode::PtrToIntNode     ) flags += "2";
    if (NodeType & DSNode::VAStartNode      ) flags += "V";
  }

  return flags;
}

static void printFlags(llvm::raw_ostream &O, DSNode *N) {
  O << getFlags(N);
}

/// printNodes -- print the node specified by NV
///
/// Format:
/// "flags:{value(s)}:{type(s)}"
///
/// Additionally, the user can specify to print just one piece
static void printNode(llvm::raw_ostream &O, NodeValue &NV) {
  assert(
      ((!OnlyPrintFlags && !OnlyPrintValues)||
      (!OnlyPrintFlags && !OnlyPrintTypes) ||
      (!OnlyPrintValues && !OnlyPrintTypes)) &&
      "Only one \"Only\" option allowed!");

  if (OnlyPrintFlags) {
    printFlags(O,NV.getNode());
  } else if (OnlyPrintValues) {
    printAllValuesForNode(O, NV);
  } else if (OnlyPrintTypes) {
    printTypesForNode(O, NV);
  } else {
    //Print all of them
    printFlags(O,NV.getNode());
    O << ":{";
    printAllValuesForNode(O, NV);
    O << "}:{";
    printTypesForNode(O, NV);
    O << "}";
  }

  O << "\n";
}


/// printNodes -- For each node the user indicated, print the node.
/// See 'printNode' for more details.
/// Returns true iff the user specified nodes to print.
///
static bool printNodes(llvm::raw_ostream &O, const Module *M,
                       const DataStructures *DS) {
  cl::list<std::string>::iterator I = PrintNodesForValues.begin(),
                                  E = PrintNodesForValues.end();
  if (I != E) {
    for ( ; I != E; ++I ) {
      // Make sense of what the user gave us
      NodeValue NV(*I, M, DS);
      // Print corresponding node
      printNode(O, NV);
    }
    return true;
  }
  return false;
}

/// checkIfNodesAreSame -- Verify each node that the user indicated
/// should be merged, is in fact merged.
/// Returns true iff the user specified any nodes for this option.
///
static bool checkIfNodesAreSame(llvm::raw_ostream &O, const Module *M,
                                const DataStructures *DS) {

  // Verify all nodes listed in "CheckNodesSame" belong to the same node.
  cl::list<std::string>::iterator I = CheckNodesSame.begin(),
                                  E = CheckNodesSame.end();
  // If the user specified that a set of values should be in the same node...
  if (I != E) {
    // Take the first such value as the reference to compare to the others
    NodeValue NVReference(*I++, M, DS);

    // Iterate through the remaining to verify they're the same node.
    for(; I != E; ++I) {
      NodeValue NV(*I, M, DS);
      assert(NVReference.getNodeH()==NV.getNodeH() && "Nodes don't match!");
    }
    return true;
  }

  return false;
}

/// checkIfNodesAreNotSame -- Verify each node that the user indicated
/// shouldn't be merged, wasn't merged
/// Returns true iff the user specified any nodes for this option.
///
static bool checkIfNodesAreNotSame(llvm::raw_ostream &O, const Module *M,
                                   const DataStructures *DS) {

  // Verify all nodes listed in "CheckNodesNotSame" belong to distinct nodes.
  cl::list<std::string>::iterator I = CheckNodesNotSame.begin(),
                                  E = CheckNodesNotSame.end();

  // If the user specified that a set of values should be in separate nodes...
  if (I != E) {
    // Lookup all the values
    unsigned count = E - I;
    NodeValue ** NV = new NodeValue*[count];
    for(unsigned i = 0; I != E; ++I, ++i)
      NV[i] = new NodeValue(*I, M, DS);

    //Compare all pairs to make sure they're distinct
    for(unsigned i = 0; i < count; ++i)
      for(unsigned j = i+1; j < count; ++j) {
        assert(NV[i]->getNodeH() != NV[j]->getNodeH() && "Nodes not distinct!");
      }

    for(unsigned i = 0; i < count; ++i)
      delete NV[i];
    delete [] NV;

    return true;
  }

  return false;
}

/// checkTypes -- Verify type for the given nodes.
/// Returns true iff the user specified anything for this option
///

static bool checkTypes(llvm::raw_ostream &O, const Module *M,
                       const DataStructures *DS) {

  // Verify all nodes listed in "CheckType" have the same Type
  cl::list<std::string>::iterator I = CheckType.begin(),
                                  E = CheckType.end();
  // If the user specified that a set of values should be in the same node...
  if (I != E) {
    // last value is type string
    std::string typeRef = *(--E);
    //typeRef = typeRef.substr(1, typeRef.length()-2);
    // Iterate through the remaining to verify they're the same node.
    for(; I != E; ++I) {
      NodeValue NV(*I, M, DS);
      std::string *type = new std::string();
      llvm::raw_string_ostream *test= new llvm::raw_string_ostream(*type);
      printTypesForNode(*test, NV);
      std::string type1 = test->str();
      type1.erase(remove_if(type1.begin(), type1.end(), isspace), type1.end());
      typeRef.erase(remove_if(typeRef.begin(), typeRef.end(), isspace), typeRef.end());

      if(type1 != typeRef) {
        errs() << "ERROR: Testing for type :   \t" <<
          typeRef  << "\n";
        errs() << "       But found this type :\t" <<
          test->str() << "\n";
        assert(0 && "Type verification failed!");
      }
    }
    return true;
  }
  return false;
}

/// VerifyFlags -- Verify flag properties for the given nodes.
/// This is a common enough testing process that this was added to make it simpler.
/// Returns true iff the user specified anything for this option.
///
/// This builds upon the node notation used elsewhere, and tacks on
/// node+flags, node-flags, node+flags-flags
/// Where +flags means 'this node should have these flags'
/// And -flags means 'this node should NOT have these flags'
///
static bool verifyFlags(llvm::raw_ostream &O, const Module *M,
                        const DataStructures *DS) {
  cl::list<std::string>::iterator I = VerifyFlags.begin(),
                                  E = VerifyFlags.end();
  if (I != E) {
    for(; I != E; ++I) {
      std::string NodeFlagOption = *I;
      std::string::size_type FlagPos = NodeFlagOption.find_first_of("+-");
      if (FlagPos == std::string::npos) {
        errs() << "No flags given for option \"" << NodeFlagOption << "\"!\n";
        assert(0 && "Invalid input!");
      }

      // Grab the part before the flag specifiers and parse that as a node
      std::string NodeString = std::string(I->begin(),I->begin()+FlagPos);
      NodeValue NV(NodeString, M, DS);

      // Process each of the flag specifiers (+flag, or -flag)
      do {
        bool shouldHaveFlag = (NodeFlagOption[FlagPos] == '+');

        // Find the next specifier...
        std::string::size_type NextPos = NodeFlagOption.find_first_of("+-",FlagPos+1);

        // Parse out the flags for this option
        std::string FlagsListed;
        if (NextPos != std::string::npos)
          FlagsListed = std::string(I->begin()+FlagPos+1,I->begin()+NextPos);
        else
          FlagsListed = std::string(I->begin()+FlagPos+1,I->end());

        // Do the checking!
        std::string ActualFlags = getFlags(NV.getNode());
        for (std::string::iterator I = FlagsListed.begin(), E = FlagsListed.end();
            I != E; ++I ) {
          if (shouldHaveFlag == (ActualFlags.find(*I) == std::string::npos))
          {
            errs() << "ERROR: Verify flags for:      \t" <<
              NodeFlagOption  << "\n";
            errs() << "       But found these flags: \t" <<
              ActualFlags << "\n";
            assert(0 && "Flag verification failed!");
          }
        }


        // Update FlagPos
        FlagPos = NextPos;
      } while(FlagPos != std::string::npos);
    }
    return true;
  }
  return false;
}
/// checkNotCallees -- Verify non-callees for the given function
/// Returns true iff the user specified anything for this option
///
/// checks that the first function does not callsthe rest of the
/// functions in the list
static bool checkNotCallees(llvm::raw_ostream &O, const Module *M,
                         const DataStructures *DS) {
  //Mangled names must be provided for C++
  cl::list<std::string>::iterator I = CheckNotCallees.begin(),
  E = CheckNotCallees.end();

  // User didn't specify this option, bail.
  if (I == E) return false;

  std::string &func = *(I);
  Function *caller = M->getFunction(func);
  assert(caller && "Function not found in module");

  FuncSetTy notCallees;
  while (++I != E) {
    std::string &func = *(I);
    const Function *callee = M->getFunction(func);
    assert(callee && "Specified callee function not found in module!");
    notCallees.insert(callee);
  }

  const DSCallGraph callgraph = DS->getCallGraph();
  FuncSetTy analysisCallees = getCalleesFor(caller, callgraph);

  if (std::includes(analysisCallees.begin(), analysisCallees.end(),
                    notCallees.begin(), notCallees.end())) {
    FuncSetTy invalid;
    std::set_intersection(analysisCallees.begin(), analysisCallees.end(),
                          notCallees.begin(), notCallees.end(),
                          std::inserter(invalid, invalid.begin()));
    errs() << "ERROR: Callgraph check failed for: \t" << caller->getName() << "\n";
    errs() << "              Analysis says calls: \t";
    printCallees(analysisCallees, errs()); errs() << "\n";
    errs() << "              Testing to not call: \t";
    printCallees(notCallees, errs()); errs() << "\n";
    errs() << "                      *** Overlap: \t";
    printCallees(invalid, errs()); errs() << "\n";
    assert(0 && "Analysis contained the specified callees!");
  }

  return true;
}

/// checkCallees -- Verify callees for the given function
/// Returns true iff the user specified anything for this option
///
/// checks that the first function calls the rest of the
/// functions in the list
static bool checkCallees(llvm::raw_ostream &O, const Module *M,
                         const DataStructures *DS) {

  //Mangled names must be provided for C++
  cl::list<std::string>::iterator I = CheckCallees.begin(),
  E = CheckCallees.end();

  // User didn't specify this option, bail.
  if (I == E) return false;

  std::string &func = *(I);
  Function *caller = M->getFunction(func);
  assert(caller && "Function not found in module");

  FuncSetTy expectedCallees;
  while (++I != E) {
    std::string &func = *(I);
    const Function *callee = M->getFunction(func);
    assert(callee && "Specified callee function not found in module!");
    expectedCallees.insert(callee);
  }

  const DSCallGraph callgraph = DS->getCallGraph();
  FuncSetTy analysisCallees = getCalleesFor(caller, callgraph);

  if (!std::includes(analysisCallees.begin(), analysisCallees.end(),
                     expectedCallees.begin(), expectedCallees.end())) {
    FuncSetTy missing;
    std::set_difference(expectedCallees.begin(), expectedCallees.end(),
                        analysisCallees.begin(), analysisCallees.end(),
                        std::inserter(missing, missing.begin()));
    errs() << "ERROR: Callgraph check failed for: \t" << caller->getName() << "\n";
    errs() << "              Analysis says calls: \t";
    printCallees(analysisCallees, errs()); errs() << "\n";
    errs() << "       Testing to make sure calls: \t";
    printCallees(expectedCallees, errs()); errs() << "\n";
    errs() << "                      *** Missing: \t";
    printCallees(missing, errs()); errs() << "\n";
    assert(0 && "Analysis didn't contain the specified callees!");
  }

  return true;
}

/// handleTest -- handles any user-specified testing options.
/// returns true iff the user specified something to test.
///
bool DataStructures::handleTest(llvm::raw_ostream &O, const Module *M) const {

  bool tested = false;

  tested |= printNodes(O,M,this);
  tested |= checkIfNodesAreSame(O,M,this);
  tested |= checkIfNodesAreNotSame(O,M,this);
  tested |= verifyFlags(O,M,this);
  tested |= checkTypes(O,M,this);
  tested |= checkCallees(O,M,this);
  tested |= checkNotCallees(O,M,this);

  return tested;
}

