mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Documenting ifacedecomp
This commit is contained in:
parent
ab76cc6095
commit
6cc2d18349
9 changed files with 793 additions and 208 deletions
|
@ -457,7 +457,7 @@ RECURSIVE = NO
|
||||||
# excluded from the INPUT source files. This way you can easily exclude a
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||||
|
|
||||||
EXCLUDE = unify.hh unify.cc rulecompile.hh rulecompile.cc slgh_compile.hh slgh_compile.cc slghparse.cc slghparse.hh slghscan.cc slghpattern.hh slghpattern.cc slghpatexpress.hh slghpatexpress.cc slghsymbol.hh slghsymbol.cc ifacedecomp.hh ifacedecomp.cc codedata.hh codedata.cc semantics.hh semantics.cc grammar.hh grammar.cc callgraph.hh callgraph.cc filemanage.hh filemanage.cc graph.hh graph.cc loadimage_bfd.hh loadimage_bfd.cc pcodecompile.cc pcodecompile.hh pcodeparse.hh pcodeparse.cc inject_sleigh.hh inject_sleigh.cc context.hh context.cc consolemain.cc sleighexample.cc xml.cc double.hh double.cc paramid.hh paramid.cc prefersplit.hh prefersplit.cc
|
EXCLUDE = unify.hh unify.cc rulecompile.hh rulecompile.cc slgh_compile.hh slgh_compile.cc slghparse.cc slghparse.hh slghscan.cc slghpattern.hh slghpattern.cc slghpatexpress.hh slghpatexpress.cc slghsymbol.hh slghsymbol.cc codedata.hh codedata.cc semantics.hh semantics.cc grammar.hh grammar.cc callgraph.hh callgraph.cc filemanage.hh filemanage.cc graph.hh graph.cc loadimage_bfd.hh loadimage_bfd.cc pcodecompile.cc pcodecompile.hh pcodeparse.hh pcodeparse.cc inject_sleigh.hh inject_sleigh.cc context.hh context.cc consolemain.cc sleighexample.cc xml.cc double.hh double.cc paramid.hh paramid.cc prefersplit.hh prefersplit.cc
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||||
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
||||||
|
@ -870,18 +870,6 @@ GENERATE_XML = NO
|
||||||
|
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
|
|
||||||
# The XML_SCHEMA tag can be used to specify an XML schema,
|
|
||||||
# which can be used by a validating XML parser to check the
|
|
||||||
# syntax of the XML files.
|
|
||||||
|
|
||||||
XML_SCHEMA =
|
|
||||||
|
|
||||||
# The XML_DTD tag can be used to specify an XML DTD,
|
|
||||||
# which can be used by a validating XML parser to check the
|
|
||||||
# syntax of the XML files.
|
|
||||||
|
|
||||||
XML_DTD =
|
|
||||||
|
|
||||||
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
|
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
|
||||||
# dump the program listings (including syntax highlighting
|
# dump the program listings (including syntax highlighting
|
||||||
# and cross-referencing information) to the XML output. Note that
|
# and cross-referencing information) to the XML output. Note that
|
||||||
|
|
|
@ -574,7 +574,10 @@ int4 FlowBlock::getOutIndex(const FlowBlock *bl) const
|
||||||
void FlowBlock::printHeader(ostream &s) const
|
void FlowBlock::printHeader(ostream &s) const
|
||||||
|
|
||||||
{
|
{
|
||||||
s << dec << index << ' ' << getStart() << '-' << getStop();
|
s << dec << index;
|
||||||
|
if (!getStart().isInvalid() && !getStop().isInvalid()) {
|
||||||
|
s << ' ' << getStart() << '-' << getStop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively print out the hierarchical structure of \b this FlowBlock.
|
/// Recursively print out the hierarchical structure of \b this FlowBlock.
|
||||||
|
|
|
@ -54,8 +54,8 @@ public:
|
||||||
};
|
};
|
||||||
Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt); ///< Constructor
|
Comment(uint4 tp,const Address &fad,const Address &ad,int4 uq,const string &txt); ///< Constructor
|
||||||
Comment(void) {} ///< Constructor for use with restoreXml
|
Comment(void) {} ///< Constructor for use with restoreXml
|
||||||
void setEmitted(bool val) const { emitted = val; }
|
void setEmitted(bool val) const { emitted = val; } ///< Mark that \b this comment has been emitted
|
||||||
bool isEmitted(void) const { return emitted; }
|
bool isEmitted(void) const { return emitted; } ///< Return \b true if \b this comment is already emitted
|
||||||
uint4 getType(void) const { return type; } ///< Get the properties associated with the comment
|
uint4 getType(void) const { return type; } ///< Get the properties associated with the comment
|
||||||
const Address &getFuncAddr(void) const { return funcaddr; } ///< Get the address of the function containing the comment
|
const Address &getFuncAddr(void) const { return funcaddr; } ///< Get the address of the function containing the comment
|
||||||
const Address &getAddr(void) const { return addr; } ///< Get the address to which the instruction is attached
|
const Address &getAddr(void) const { return addr; } ///< Get the address to which the instruction is attached
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,8 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
// Interface to the decompilation routines
|
/// \file ifacedecomp.hh
|
||||||
|
/// \brief Console interface commands for the decompiler engine
|
||||||
|
|
||||||
#ifndef __IFACE_DECOMP__
|
#ifndef __IFACE_DECOMP__
|
||||||
#define __IFACE_DECOMP__
|
#define __IFACE_DECOMP__
|
||||||
|
@ -27,20 +28,22 @@
|
||||||
#include "rulecompile.hh"
|
#include "rulecompile.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// \brief Interface capability point for all decompiler commands
|
||||||
class IfaceDecompCapability : public IfaceCapability {
|
class IfaceDecompCapability : public IfaceCapability {
|
||||||
static IfaceDecompCapability ifaceDecompCapability; // Singleton instance
|
static IfaceDecompCapability ifaceDecompCapability; ///< Singleton instance
|
||||||
IfaceDecompCapability(void); // Singleton
|
IfaceDecompCapability(void); ///< Singleton constructor
|
||||||
IfaceDecompCapability(const IfaceDecompCapability &op2); // Not implemented
|
IfaceDecompCapability(const IfaceDecompCapability &op2); ///< Not implemented
|
||||||
IfaceDecompCapability &operator=(const IfaceDecompCapability &op2); // Not implemented
|
IfaceDecompCapability &operator=(const IfaceDecompCapability &op2); ///< Not implemented
|
||||||
public:
|
public:
|
||||||
virtual void registerCommands(IfaceStatus *status);
|
virtual void registerCommands(IfaceStatus *status);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Common data shared by decompiler commands
|
||||||
class IfaceDecompData : public IfaceData {
|
class IfaceDecompData : public IfaceData {
|
||||||
public:
|
public:
|
||||||
Funcdata *fd; // Current function data
|
Funcdata *fd; ///< Current function active in the console
|
||||||
Architecture *conf;
|
Architecture *conf; ///< Current architecture/program active in the console
|
||||||
CallGraph *cgraph;
|
CallGraph *cgraph; ///< Call-graph information for the program
|
||||||
|
|
||||||
map<Funcdata*,PrototypePieces> prototypePieces;
|
map<Funcdata*,PrototypePieces> prototypePieces;
|
||||||
void storePrototypePieces( Funcdata *fd_in, PrototypePieces pp_in ) { prototypePieces.insert(pair<Funcdata*,PrototypePieces>(fd_in,pp_in)); }
|
void storePrototypePieces( Funcdata *fd_in, PrototypePieces pp_in ) { prototypePieces.insert(pair<Funcdata*,PrototypePieces>(fd_in,pp_in)); }
|
||||||
|
@ -52,18 +55,24 @@ public:
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
bool jumptabledebug;
|
bool jumptabledebug;
|
||||||
#endif
|
#endif
|
||||||
IfaceDecompData(void);
|
IfaceDecompData(void); ///< Constructor
|
||||||
virtual ~IfaceDecompData(void);
|
virtual ~IfaceDecompData(void);
|
||||||
void allocateCallGraph(void);
|
void allocateCallGraph(void); ///< Allocate the call-graph object
|
||||||
void abortFunction(ostream &s);
|
void abortFunction(ostream &s); ///< Clear references to current function
|
||||||
void clearArchitecture(void);
|
void clearArchitecture(void); ///< Free all resources for the current architecture/program
|
||||||
|
void followFlow(ostream &s,int4 size);
|
||||||
|
Varnode *readVarnode(istream &s); ///< Read a varnode from the given stream
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Disassembly emitter that prints to a console stream
|
||||||
|
///
|
||||||
|
/// An instruction is printed to a stream simply, as an address
|
||||||
|
/// followed by the mnemonic and then column aligned operands.
|
||||||
class IfaceAssemblyEmit : public AssemblyEmit {
|
class IfaceAssemblyEmit : public AssemblyEmit {
|
||||||
int4 mnemonicpad; // How much to pad the mnemonic
|
int4 mnemonicpad; ///< How much to pad the mnemonic
|
||||||
ostream *s;
|
ostream *s; ///< The current stream to write to
|
||||||
public:
|
public:
|
||||||
IfaceAssemblyEmit(ostream *val,int4 mp) { s = val; mnemonicpad=mp; }
|
IfaceAssemblyEmit(ostream *val,int4 mp) { s = val; mnemonicpad=mp; } ///< Constructor
|
||||||
virtual void dump(const Address &addr,const string &mnem,const string &body) {
|
virtual void dump(const Address &addr,const string &mnem,const string &body) {
|
||||||
addr.printRaw(*s);
|
addr.printRaw(*s);
|
||||||
*s << ": " << mnem;
|
*s << ": " << mnem;
|
||||||
|
@ -72,22 +81,31 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void execute(IfaceStatus *status,IfaceDecompData *dcp);
|
extern void execute(IfaceStatus *status,IfaceDecompData *dcp); ///< Execute one command for the console
|
||||||
extern void mainloop(IfaceStatus *status);
|
extern void mainloop(IfaceStatus *status); ///< Execute commands as they become available
|
||||||
|
|
||||||
|
/// \brief Root class for all decompiler specific commands
|
||||||
|
///
|
||||||
|
/// Commands share the data object IfaceDecompData and are capable of
|
||||||
|
/// iterating over all functions in the program/architecture.
|
||||||
class IfaceDecompCommand : public IfaceCommand {
|
class IfaceDecompCommand : public IfaceCommand {
|
||||||
protected:
|
protected:
|
||||||
IfaceStatus *status;
|
IfaceStatus *status; ///< The console owning \b this command
|
||||||
IfaceDecompData *dcp;
|
IfaceDecompData *dcp; ///< Data common to decompiler commands
|
||||||
void iterateScopesRecursive(Scope *scope);
|
void iterateScopesRecursive(Scope *scope); ///< Iterate recursively over all functions in given scope
|
||||||
void iterateFunctionsAddrOrder(Scope *scope);
|
void iterateFunctionsAddrOrder(Scope *scope); ///< Iterate over all functions in a given scope
|
||||||
public:
|
public:
|
||||||
virtual void setData(IfaceStatus *root,IfaceData *data) { status = root; dcp = (IfaceDecompData *)data; }
|
virtual void setData(IfaceStatus *root,IfaceData *data) { status = root; dcp = (IfaceDecompData *)data; }
|
||||||
virtual string getModule(void) const { return "decompile"; }
|
virtual string getModule(void) const { return "decompile"; }
|
||||||
virtual IfaceData *createData(void) { return new IfaceDecompData(); }
|
virtual IfaceData *createData(void) { return new IfaceDecompData(); }
|
||||||
|
|
||||||
|
/// \brief Perform the per-function aspect of \b this command.
|
||||||
|
///
|
||||||
|
/// \param fd is the particular function to operate on
|
||||||
virtual void iterationCallback(Funcdata *fd) {}
|
virtual void iterationCallback(Funcdata *fd) {}
|
||||||
void iterateFunctionsAddrOrder(void);
|
|
||||||
void iterateFunctionsLeafOrder(void);
|
void iterateFunctionsAddrOrder(void); ///< Iterate command over all functions in all scopes
|
||||||
|
void iterateFunctionsLeafOrder(void); ///< Iterate command over all functions in a call-graph traversal
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcSource : public IfaceDecompCommand {
|
class IfcSource : public IfaceDecompCommand {
|
||||||
|
@ -257,11 +275,6 @@ public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcBreakjump : public IfaceDecompCommand {
|
|
||||||
public:
|
|
||||||
virtual void execute(istream &s);
|
|
||||||
};
|
|
||||||
|
|
||||||
class IfcPrintTree : public IfaceDecompCommand {
|
class IfcPrintTree : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
|
@ -282,18 +295,10 @@ public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcParamIDAnalysis : public IfaceDecompCommand {
|
|
||||||
public:
|
|
||||||
virtual void execute(istream &s);
|
|
||||||
};
|
|
||||||
class IfcPrintParamMeasures : public IfaceDecompCommand {
|
class IfcPrintParamMeasures : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
class IfcPrintParamMeasuresXml : public IfaceDecompCommand {
|
|
||||||
public:
|
|
||||||
virtual void execute(istream &s);
|
|
||||||
};
|
|
||||||
|
|
||||||
class IfcRename : public IfaceDecompCommand {
|
class IfcRename : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
|
@ -403,6 +408,10 @@ public:
|
||||||
class IfcPrintInputs : public IfaceDecompCommand {
|
class IfcPrintInputs : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
|
static bool nonTrivialUse(Varnode *vn); ///< Check for non-trivial use of given Varnode
|
||||||
|
static int4 checkRestore(Varnode *vn); ///< Check if a Varnode is \e restored to its original input value
|
||||||
|
static bool findRestore(Varnode *vn,Funcdata *fd); ///< Check if storage is \e restored
|
||||||
|
static void print(Funcdata *fd,ostream &s); ///< Print information about function inputs
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcPrintInputsAll : public IfaceDecompCommand {
|
class IfcPrintInputsAll : public IfaceDecompCommand {
|
||||||
|
@ -465,6 +474,8 @@ class IfcDuplicateHash : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
virtual void iterationCallback(Funcdata *fd);
|
virtual void iterationCallback(Funcdata *fd);
|
||||||
|
static void check(Funcdata *fd,ostream &s); ///< Check for duplicate hashes in given function
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcCallGraphDump : public IfaceDecompCommand {
|
class IfcCallGraphDump : public IfaceDecompCommand {
|
||||||
|
@ -474,7 +485,7 @@ public:
|
||||||
|
|
||||||
class IfcCallGraphBuild : public IfaceDecompCommand {
|
class IfcCallGraphBuild : public IfaceDecompCommand {
|
||||||
protected:
|
protected:
|
||||||
bool quick;
|
bool quick; ///< Set to \b true if a quick analysis is desired
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
virtual void iterationCallback(Funcdata *fd);
|
virtual void iterationCallback(Funcdata *fd);
|
||||||
|
@ -490,8 +501,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcCallGraphList : public IfaceDecompCommand {
|
class IfcCallGraphList : public IfaceDecompCommand {
|
||||||
protected:
|
|
||||||
bool quick;
|
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
virtual void iterationCallback(Funcdata *fd);
|
virtual void iterationCallback(Funcdata *fd);
|
||||||
|
@ -505,6 +514,8 @@ public:
|
||||||
class IfcCallFixup : public IfaceDecompCommand {
|
class IfcCallFixup : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
|
static void readPcodeSnippet(istream &s,string &name,string &outname,vector<string> &inname,
|
||||||
|
string &pcodestring);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IfcCallOtherFixup : public IfaceDecompCommand {
|
class IfcCallOtherFixup : public IfaceDecompCommand {
|
||||||
|
@ -557,12 +568,12 @@ class IfcParseRule : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class IfcExperimentalRules : public IfaceDecompCommand {
|
class IfcExperimentalRules : public IfaceDecompCommand {
|
||||||
public:
|
public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OPACTION_DEBUG
|
#ifdef OPACTION_DEBUG
|
||||||
class IfcDebugAction : public IfaceDecompCommand {
|
class IfcDebugAction : public IfaceDecompCommand {
|
||||||
|
@ -600,6 +611,11 @@ public:
|
||||||
virtual void execute(istream &s);
|
virtual void execute(istream &s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IfcBreakjump : public IfaceDecompCommand {
|
||||||
|
public:
|
||||||
|
virtual void execute(istream &s);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -249,7 +249,7 @@ void Override::printRaw(ostream &s,Architecture *glb) const
|
||||||
s << "dead code delay on " << spc->getName() << " set to " << dec << deadcodedelay[i] << endl;
|
s << "dead code delay on " << spc->getName() << " set to " << dec << deadcodedelay[i] << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(iter=forcegoto.begin();iter!=forcegoto.end();++iter)
|
for(iter=indirectover.begin();iter!=indirectover.end();++iter)
|
||||||
s << "override indirect at " << (*iter).first << " to call directly to " << (*iter).second << endl;
|
s << "override indirect at " << (*iter).first << " to call directly to " << (*iter).second << endl;
|
||||||
|
|
||||||
map<Address,FuncProto *>::const_iterator fiter;
|
map<Address,FuncProto *>::const_iterator fiter;
|
||||||
|
|
|
@ -162,6 +162,12 @@ public:
|
||||||
bool doTrace(void); ///< Trace logical value as far as possible
|
bool doTrace(void); ///< Trace logical value as far as possible
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Class for splitting data-flow on \e laned registers
|
||||||
|
///
|
||||||
|
/// From a root Varnode and a description of its \e lanes, trace data-flow as far as
|
||||||
|
/// possible through the function, propagating each lane, using the doTrace() method. Then
|
||||||
|
/// using the apply() method, data-flow can be split, making each lane in every traced
|
||||||
|
/// register into an explicit Varnode
|
||||||
class LaneDivide : public TransformManager {
|
class LaneDivide : public TransformManager {
|
||||||
/// \brief Description of a large Varnode that needs to be traced (in the worklist)
|
/// \brief Description of a large Varnode that needs to be traced (in the worklist)
|
||||||
class WorkNode {
|
class WorkNode {
|
||||||
|
|
|
@ -20,7 +20,7 @@ vector<UnitTest *> UnitTest::tests;
|
||||||
|
|
||||||
/// Run all the tests unless a non-empty set of names is passed in.
|
/// Run all the tests unless a non-empty set of names is passed in.
|
||||||
/// In which case, only the named tests in the set are run.
|
/// In which case, only the named tests in the set are run.
|
||||||
/// \param testnames is the set of names
|
/// \param testNames is the set of names
|
||||||
void UnitTest::run(set<string> &testNames)
|
void UnitTest::run(set<string> &testNames)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
/// Include this file and any additional headers. Use TEST(testname) as
|
/// Include this file and any additional headers. Use TEST(testname) as
|
||||||
/// prototype in test function definitions. E.g.
|
/// prototype in test function definitions. E.g.
|
||||||
/// test.cc:
|
/// test.cc:
|
||||||
/// #include "float.hh"
|
/// \#include "float.hh"
|
||||||
/// #include "test.hh"
|
/// \#include "test.hh"
|
||||||
///
|
///
|
||||||
/// TEST(zero_is_less_than_one) {
|
/// TEST(zero_is_less_than_one) {
|
||||||
/// ASSERT(0.0 < 1.0);
|
/// ASSERT(0.0 < 1.0);
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
typedef void (*testfunc_t)();
|
typedef void (*testfunc_t)(); ///< A unit-test function
|
||||||
|
|
||||||
/// \brief Simple unit test class
|
/// \brief Simple unit test class
|
||||||
///
|
///
|
||||||
|
@ -58,17 +58,20 @@ struct UnitTest {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// \brief Main unit test macro
|
||||||
#define TEST(testname) \
|
#define TEST(testname) \
|
||||||
void testname(); \
|
void testname(); \
|
||||||
UnitTest testname##_obj{ #testname, testname }; \
|
UnitTest testname##_obj{ #testname, testname }; \
|
||||||
void testname()
|
void testname()
|
||||||
|
|
||||||
|
/// \brief Assert that a boolean is \b true for a unit test
|
||||||
#define ASSERT(test) \
|
#define ASSERT(test) \
|
||||||
if (!(test)) { \
|
if (!(test)) { \
|
||||||
std::cerr << " failed at " << __FILE__ << ":" << __LINE__ << " asserting \"" << #test << "\"." << std::endl; \
|
std::cerr << " failed at " << __FILE__ << ":" << __LINE__ << " asserting \"" << #test << "\"." << std::endl; \
|
||||||
throw 0; \
|
throw 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Assert that two values are equal for a unit test
|
||||||
#define ASSERT_EQUALS(a, b) \
|
#define ASSERT_EQUALS(a, b) \
|
||||||
if ((a) != (b)) { \
|
if ((a) != (b)) { \
|
||||||
std::stringstream ssa, ssb; \
|
std::stringstream ssa, ssb; \
|
||||||
|
@ -79,6 +82,7 @@ struct UnitTest {
|
||||||
throw 0; \
|
throw 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Assert that two values are not equal for a unit test
|
||||||
#define ASSERT_NOT_EQUALS(a, b) \
|
#define ASSERT_NOT_EQUALS(a, b) \
|
||||||
if ((a) == (b)) { \
|
if ((a) == (b)) { \
|
||||||
std::stringstream ssa, ssb; \
|
std::stringstream ssa, ssb; \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue