Accessing a C++ function from a CXX test - c++

I'm writing a few CXX unit tests for a class I have written. I have never written CXX tests before (also this is the only framework I can use). I am trying to call a function contained within my class so that I can test the output is what is expected, but I am unsure if you can do this, and if so, how.
Test.h:
class Test..... {
public:
std::string GenerateHash(const std::string& user, const std::string& url) const;
...
}
Test.cpp:
string
Test::GenerateHash(const string& user, const string& urrl) const {
...
}
I have included the header file in the CXX test, but cannot access the GenerateHash function.
Test.cxx_h:
void testCheckHashGeneration( void ) {
TS_ASSERT_EQUALS (GenerateHash("testuser", "http://www.stackoverflow.com"), "DFEGEC.....");
}
Error: error: âGenerateHashâ was not declared in this scope
I also tried:
Test.cxx_h:
void testCheckHashGeneration( void ) {
Test test;
TS_ASSERT_EQUALS (test->GenerateHash("testuser", "http://www.stackoverflow.com"), "DFEGEC.....");
}
Error: error: âTestâ has not been declared
Any help will be greatly appreciated.

In the first case, you're trying to call a member function without an instance of Test. You need a Test to call it on, as you've done in the second case.
In the second case, you're trying to call a member using the syntax for having a pointer to the object, '->', when you actually have an object. You want the second to look like this:
test.GenerateHash(...)
If you somehow had a Test*, then you could call it like
test->GenerateHash(...)
use . for objects, -> for pointers to objects.
More code and error output would be helpful.

If the GenerateHash function can be a static method, then make it static. Then call it using Test::GenerateHash(/*your arguments*/);
Considering the way you initially attempted to call GenerateHash, I would guess that this should be a static method. If its execution does not depend on a particular instance of the Test class, then it can be static.
Otherwise, use test.GenerateHash rather than test->GenerateHash

Related

Using callbacks in C++

I'm working on a project in C++, but at some point in the application it fails and generates a core dump. The application uses a couple of classes, which for the purposes here I'm concentrating on one of the classes, which I'm calling A, and is instantiated as object a. This has a large number of member functions, of which at the moment only a few are being used, but one of these generates a log to produce diagnostics to be used for debugging. I want to use this to find out why the application is failing.
The project is to put together code that invokes the various member functions, and although I have access to the source code and some limited documentation, none of the code can be changed, with all changes being in the code that makes use of the classes and invokes the member functions. The member function in question is:
void enable_log (log_callback callback, void * user_data = nullptr)
where the 1st argument callback contains the message and 2nd argument is optional. For now it can be set to nullptr, so would be invoked as:
a.enable_log(callback, nullptr);
From this documentation it's not at all clear what exactly callback is. However, in looking at the source code this is:
using log_callback = void (*)(const std::string& message, void* user_data);
in a header file, where log_callback is an alias for const std::string& if I understand this correctly.
I already have dummy classes on a platform using Visual Studio 2019 with some test member functions to simulate invoking the member functions on a remote Linux server, but I'm unable to find a way of making use of the member function above. I added the test member function to the dummy class as follows:
void enable_log(const std::string& callback, void* user_data = nullptr) {
callback = "ABCD";
}
which is supposed to generate a test string which is returned, such that in the real application this string will have diagnostic information that will be written to a file. However, the "=" is an error.
The idea is that in the main function an empty string will be declared, then enable_log() should populate this string, which can be printed out.
I've spent some time looking at various resources, including Stackoverflow, but I cannot find a way of returning a string with the information that can be printed out. I need a simple way to simulate this, and as I said above, I must not change the source code of the real member function, so the simulated member function has to produce a string in the same way. How is this done? Some advice would be appreciated.
Callback, in simple words, is some function that will be called later at some point. Example:
void callback_fn(int a);
using callback_t = (void)(*)(int a);
void some_func(callback_t);
You can use some_func() like so:
some_func(callback_fn);
Full example here: https://godbolt.org/z/ET3GhfYrv
For your usecase the parameters of the callback are slightly different. Here's how to read the syntax:
using log_callback = // this just creates an alias for whatever is on the right handside
void // the return type of the "callable" should be void
(*) // this tells us that it is a function pointer
(const std::string& message, void* user_data) // These are the arguments the callable takes. It is a "std::string" and a "void *"
To use this, just create a free function with the same signature:
void callable(const std::string &msg, void *userData = nullptr)
{
// msg is the data sent by the function. use it in whatever way
// you want.
std::cout << msg << '\n';
}
// Pass it to the enable_log
enable_log(callable);

C++ class function chain-calling compilation error

I have an assignment where i was given c++ code that has multiple test functions, and i have to write the stri class with all the functions necesary for these tests to pass. I am having difficulty with one particular test about chain linking.
void Lab4Tests::testChainedSet() {
stri greet = "Hello";
assert(0==strcmp("Hello", greet.get()), "testChainedSet", "internal representation error");
greet.set("Hi").set("Buna");
assert(0==strcmp("Buna", greet.get()), "testChainedSet", "set failed");
}
My function inside the class that I wrote to solve this test is the following
char* set(const char* s){
len=strlen(s);
repres=new char(len+1);
strcpy(repres,s);
return repres;
}
I get an error when compiling the code
error: request for member 'set' in 'greet.stri::set(((const char*)"Hi"))', which is of non-class type 'char*'|
I dont understand chain linking that well, I would appreciate if somebody could point out what I'm doing wrong. Thanks in advance!
If you want to be able to chain calls you need to return a reference to the this object.
For instance
stri& set(const char* s)
{
repres = std::strdup(s);
return *this;
}
I've taken the liberty of simplifying your string duplication. I haven't fixed the memory leak that you will get if you call set when repres already contains dynamically allocated memory.

How to run the Function Pass before the Module Pass in LLVM?

I'm implementing several Passes on the LLVM in order to add original optimization,
These Passes are based on FunctionPass and ModulePass.
Now, each Pass is invoked by corresponding opt command option which is
registerd by RegisterPass template.
In future, I'd like to these Passes to be invoked only by one opt command option.
My idea is as follows:
First, Function passes to run, and finally Module pass to run.
Each Function passes to use the former Function passes' analysis information.
The final Module pass to construct a new function using the former Function passes' result.
All of these Passes sequence to invoke by only one opt command option specifying the final Module pass.
I thought I could make it with addRequired method in the AnalysisUsage class.
However, it doesn't seem to work:
In the Function pass, several Function passes may be addRequired in the order.
In the Function pass, only one Module pass may be addRequired.
In the Function pass(X), Function pass and Module pass cannot be addRequired simultaneously.
i.e. opt command execution with option X causes to a lock status.
In the Module pass, only one Module pass may be addRequired.
In the Module pass(Y), Function pass(Z) cannot be addRequired.
i.e. opt command with option Y executes only Y, and Function pass(Z) is ignored.
I am not familiar to the Pass manager mechanism.
Anybody help me how to run the Function pass before the Module pass with only one opt command option?
The case of execution is shown below:-
$ opt -stats -load ~/samples/tryPass4.so -MPass4 hello2.ll -S -o tryPass4.ll -debug-pass=Structure
Pass Arguments: -targetlibinfo -datalayout -notti -basictti -x86tti -MPass4 -verify -verify-di -print-module
Target Library Information ↑
Data Layout                              -FPass4 doesn't appear here
No target information
Target independent code generator's TTI
X86 Target Transform Info
ModulePass Manager
Module Pass
Unnamed pass: implement Pass::getPassName()
FunctionPass Manager
Module Verifier
Debug Info Verifier
Print module to stderr
Pass Arguments: -FPass4    <- here -FPass4 appears, but not executed
FunctionPass Manager
Function Pass
***** Module Name : hello2.ll <- output from the Module pass
The source code for above is as follows:-
using namespace llvm;
namespace{
class tryFPass4 : public FunctionPass {
public :
static char ID;
tryFPass4() : FunctionPass(ID){}
~tryFPass4(){}
virtual bool runOnFunction(llvm::Function &F);
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;
};
class tryMPass4 : public ModulePass {
public :
static char ID;
tryMPass4() : ModulePass(ID){}
~tryMPass4(){}
virtual bool runOnModule(llvm::Module &M);
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;
};
}
bool tryFPass4::runOnFunction(Function &F) {
bool change = false;
....
return change;
}
bool tryMPass4::runOnModule(Module &M) {
bool change = false ;
....
return change;
}
void tryFPass4::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
}
void tryMPass4::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<tryFPass4>();
}
char tryFPass4::ID = 0;
static RegisterPass<tryFPass4> X("FPass4", "Function Pass", false, false);
char tryMPass4::ID = 0;
static RegisterPass<tryMPass4> Y("MPass4", "Module Pass", false, false);
I tried to simulate the problem here using LLVM 3.8.1.
I believe your Function pass gets to run here:
Module Pass
Unnamed pass: implement Pass::getPassName()
I do not know why it is marked as unnamed although getPassName is overriden.
A fine detail that you need to watch is that in order for the function pass to actually execute its runOnFunction method, you need to invoke the Function & specific method of getAnalysis as in:
getAnalysis<tryFPass4>(f); // where f is the current Function operating on
It seems if the dependent pass operates on a small unit of IR than the pass that requires it, it needs to be executed explicitly. I might be mistaken since I have not yet tried it with a BasicBlockPass required by a FunctionPass.

Using functions from classes

I am learning C++ and very new at using classes, and I am getting very confused in trying to use them. I am trying to convert my existing code (which used structs) so that it uses classes - so while I know what I am trying to do I don't know if I'm doing it correctly.
I was told that when using functions from the class, I first need to instantiate an object of the class. So what I have tried (a snippet) in my main function is:
int main()// line 1
{
string message_fr_client = "test"; //line2
msgInfo message_processed; //line 3
message_processed.incMsgClass(message_fr_client); //line 4
if (!message_processed.priority_check(qos_levels, message_processed)) //line 5
cout << "failure: priority level out of bounds\n"; //line 6
return 0; //line 7
}
Could you help me clarify if my following assumptions are correct? The compiler is not showing any error and so I don't know if it is error-free, or if there are ones lurking beneath.
At line 4, is the function incMsgClass being performed on the string message_fr_client and returning the resultant (and modified) message_processed?
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/*arguments*/)?
I haven't included the body of the functions because I know they work - I would just like to find out how the class functions interact. Please let me know if I can be clearer - just trying to clear up some confusion here.
Here is my class:
#ifndef clientMsgHandling_H
#define clientMsgHandling_H
#include <list>
#include <map>
#include <queue>
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
/*classifying message*/
msgInfo incMsgClass(std::string original_msg);
/*message error checks*/
bool priority_check(int syst_priority, msgInfo msg); //check that message is within qos levels
bool route_check(std::map<std::pair<int, int>, int> route_table, msgInfo msg); //check that route exists
void getPath(msgInfo msg, std::map<std::pair<int, int>, int> route_info, int max_hop);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
#endif
While it may compile (and even run), there are a few oddities with the code as shown:-
First off, class methods know which object they are operating on - so your priority_check and route_check methods probably don't need msgInfo as a parameter.,
for example, your old non-class function might be like this
bool priority_check(int p, msgInfo msg)
{
return msg.priority < p;
}
But the new one should look like this:
bool msgInfo::priority_check(int p)
{
return priority < p;
}
Also, incMsgClass is a bit odd, as it's a non-static class method that returns a msgInfo object. It's difficult to tell without understanding what it's supposed to do, but it seems possible that this function should actually be a constructor, rather than a regular method.
One other thing is that you're currently passing a msgInfo by value to those methods. So if the method needed to modify the passed msgInfo, it would not have any effect. It's generally better to pass objects by reference or const reference to other methods. So, back to the previous non-method example, it should really be this.
bool priority_check(int p, const msgInfo &msg)
...
But, as I said, you probably don't need the msgInfo parameters anyway.
At line 4, is the function incMsgClass being performed on the string message_fr_client
Yes
and returning the resultant (and modified) message_processed?
Whatever it's returning, you're ignoring the return value. It can modify the object itself, yes, because the function is not const.
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
Yes
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/arguments/)?
If a member function is intended to modify one of the class members, it's just a matter of not marking that function const
Hard to tell without implementation-details, but here we go:
I. You are passing a std::string as value (C++ is call-by-value by default), so you get a copy of the std::string in your method. If you want to work on the object you passed and manipulate it, use a reference on the object, like
msgInfo incMsgClass(std::string& original_msg); // notice the ampersand
then you can change your signature to
void incMsgClass(std::string& original_msg);
as you don't need to return the std::string you passed.
II. Yes, at least according to your signature
III. Can see a node_path only as a member.
For all your questions, see C++-FAQ.
Your basic assumptions are correct.
message_processed.incMsgClass(message_fr_client); //line 4
This line is not correct. The function you call returns msgInfo which is simply dropped. You should assign it to something. But it is not as it is usually done. You should make it a constructor of msgInfo, like
class msgInfo
{
public:
msgInfo(std::string original_msg);
...
}
Then you could call it like this
msgInfo message_processed(message_fr_client);
That line would create a msgInfo that is already properly initialized.
There is another pattern for creating class instances - static creating function. In your case you could mark incMsgClass static and then call it like
msgInfo message_processed = msgInfo.incMsgClass(message_fr_client);
I seriously doubt you need this pattern here, so I'd advise to move to constructor.
As of other functions, I see no problems there. Just note that all member functions not marked as const can modify the object they are called on. So, you don't need to pass this object explicitly. For functions a pointer to the object they are called on is available by name this. Also the functions can access all class variables as if these variables are global for normal (non-member) functions.

C++ boost function issue

I did something to break the functionality in my program, but I can't figure out what. I define a typedef in a class headerfile:
typedef boost::function<void(instr_ptr, std::vector<ResultBase*>) > GenFunction;
And inside that class I have two instances:
GenFunction Gen;
GenFunction Kill
I set them as follows:
void DataFlowSolver::SetGenFunction(GenFunction &func)
{
Gen = func;
}
void DataFlowSolver::SetKillFunction(GenFunction &func)
{
Kill = func;
}
I have another function in a seperate header file:
void GenLiveVar(const instr_ptr instr, std::vector<ResultBase*> &list);
I create an instance of the DataFlowSolver class, and attempt to assign into it as follows:
blockSolver.SetGenFunction(GenLiveVar);
However, the compiler complains:
CFG.cc:617: error: no matching function for call to
'DataFlowSolver::SetGenFunction(void (&)(instr_ptr,
std::vector >&))'
DataFlowSolver.h:21: note: candidates are: void
DataFlowSolver::SetGenFunction(GenFunction&)
But it lets me do this:
GenFunction fun = GenLiveVar;
blockSolver.SetGenFunction(fun);
Anyone have an idea what might be wrong? I know this worked before, but I'm not sure how I managed to break it...
You are passing the boost::function into Set*Function by non-const reference. That prevents temporaries from being used as arguments, and the conversion from a normal function to a boost::function creates a temporary value. You will need to use a const reference for your parameter type for the code to work correctly.