How to access my code using Visual Studio CppUnitTestFramework - c++

I wish to unit test my code. It is a proprietary step in a task I have, the code of which I already wrote.
I am using VS Community 2017 v.15.9.7. I have followed the instructions of this site to the utmost detail, line by line:
https://blogs.msdn.microsoft.com/vcblog/2017/04/19/cpp-testing-in-visual-studio/#Setup
But after all the includes I get two errors :
1) Error LNK1120 1 unresolved externals UnitTest1 \source\repos\Primes\Debug\UnitTest1.dll 1
2) Error LNK2019 unresolved external symbol "public: bool __thiscall SearchPrimes::IsPrime(int)" (?IsPrime#SearchPrimes##QAE_NH#Z) referenced in function "public: void __thiscall UnitTest1::TestClass::IsOdd(void)" (?IsOdd#TestClass#UnitTest1##QAEXXZ) UnitTest1 C:\Users\Velzevoul\source\repos\Primes\UnitTest1\unittest1.obj
I have tried moving files, but I thing randomly moving them around will do more harm than good. I read about including the "stdafx.h" to my "source", but that made thing worse, as more errors kept popping up.
Here are the header files of the code I wrote:
#pragma once
#include <vector>
#include "XMLParser.h"
class SearchPrimes
{
public:
std::vector<int> RangePrime(const std::pair<int, int>&);
//Setting the range to search for prime numbers, executing the algorithm
bool IsPrime(int); //The algorithm that checks if a number is prime
bool IsOdd(int); //Checking if a number if even or odd
};
#pragma once
#include <iostream>
#include <vector>
class XMLParser
{
public:
void removeTags(std::string&); //Removing the brackets of the tags of the .xml
std::string openFile(std::string); //Opening a file
std::vector<std::string> readFile(const std::string&, std::string);
//Getting the text from the .xml file to a vector
std::vector<std::pair<int, int> > stringsToInts();
//Finding the values of the tags that contain the ranges
//and converting the string numbers to a vector<int>
};
Here is the test.cpp
#include "stdafx.h"
#include "CppUnitTest.h"
#include "/Users/Velzevoul/source/repos/Primes/Primes/SearchPrimes.h"
#include "/Users/Velzevoul/source/repos/Primes/Primes/XMLParser.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest1
{
TEST_CLASS(TestClass)
{
public:
TEST_METHOD(IsOdd)
{
SearchPrimes prime;
Assert::IsTrue(prime.IsPrime(4));
}
};
}
What do I have to do in order to solve the external dependencies? The article says, that once I follow the steps I can begin. The test is in a separate project, as the article suggests. If you think that the problem may be related to my main() function, please tell me to include it. I do not right now, because it's quite lengthy.
I thank you for your time in advance!

That article is suggesting that you can just link to a Windows executable the same way you would a DLL. I suppose this is theoretically be possible if your executable has been set up to export its functions, but it seems like an odd thing to do.
There are two options for accessing the code under test in a C++ unit test project:
Add the source modules (.cpp/.h) to your unit test project.
Link with a library containing the code.
If your project is relatively simple, with just a few .cpp modules, then option 1 is probably the way to go. Right-click your unit test project, select "Add -> Existing Item..." and add the .cpp modules you want to test.
For a more complex project with many source modules, option 2 might be a better option. Create one or more library projects (static or dynamic) to contain your source modules, then link both the executable and unit test projects with the library.
A good practice is to create one unit test project for each project to be tested. Give the unit test project a name that indicates what project it is testing, i.e. MyExecutable and MyExecutable.Test, MyLibrary and MyLibrary.Test, etc.

Related

Using static library in current project

I'm facing the error when I'm linking an external library and code with the current project. You will understand the problem by this example.
//foo.h
namespace LMS
{
class foo
{
foo(); //implementation in cpp
foo(int dummy) //implemented here
{
//something
}
};
} // namespace LMS
//foo.cpp
#include"foo.h"
namespace LMS
{
foo::foo()
{
//something
}
} // namespace LMS
//externalProgram.h
#include "foo.h"
LMS::foo *ptr;
ptr = new LMS::foo(); //Linking error: LNK 2019
ptr = new LMS::foo(2); //No error
Now the problem is that the external program doesn't know about the foo.cpp and the implementation of class foo methods in it. I'm currently using VS2019 and using two projects in the same solution. I've tried several ways to correct this but it didn't work out. The current way I'm seeing is to implement all the functions in header files.
EDIT: I've already linked the files!!
You should be able to mark your externalProgram project as dependent on the foo project. This will link foo.o in with external program.
Using the UI you will select this in
Project > Project Dependencies : Depends on ...
If that is correct, then the problem is more subtle, sometimes just a simple typo. At this point you want to use the command line tools to break apart the library and confirm the object files, and break apart the object files and confirm the symbols within. A ten year old SO posting discusses using lib.exe to example the library file. The dumpbin tool has a /symbols option that might also be handy for looking at the actual code generated.

Dealing with multiple projects in visual studios

I am trying to figure out how to deal with multiple projects under the banner of a single solution and how to correctly link projects in order to make things work in conjunction.
I began by making two projects in one solution - for simplicity's sake, ProjA and ProjB. ProjB is set as the StartUp project. Furthermore, ProjA is configured to be built as a .dll file which I am to link with ProjB, which in turn is configured to be built as a .exe file. So far I've linked ProjA to ProjB by adding a dependency to ProjB via referencing (RMB>Add>Reference).
With all that out of the way, I wanted to test whether the setup worked as intended. So I did the following. In ProjA, I wrote the following Test code:
Test.h
#pragma once
namespace ProjA {
_declspec(dllexport) void Print();
}
Test.cpp
#include "Test.h"
#include <stdio.h>
namespace ProjA {
void Print()
{
printf("Testing\n");
}
}
And in ProjB:
TestEntry.cpp
#include <stdio.h>
namespace ProjA {
_declspec(dllimport) void Print();
}
void main()
{
ProjA::Print(); //breakpoint1
printf("Testing (2)\n"); //breakpoint2
}
I set two breakpoints at the commented lines for debugging, built the projects and ran the program. At breakpoint1, I expected the console to print "Testing" and proceed to the next line, followed by breakpoint2 printing "Testing (2)" and proceeding to the next line before exiting. However, the console was blank at breakpoint1. It only printed the line from the main function at breakpoint2.
So what am I doing wrong here? Is there something wrong with the way I included the projects? Was there a linking procedure I skipped? Is there a specific way I need to set up Visual Studios 2017 in order for it to work? Are there other plugins/APIs I should be installing?
To test it out further, I commented out everything in ProjA. This time I expected a linking error when building the projects, but everything ran in the exact same manner. This confused me even more. It's as if I didn't even link the projects and the main function is not identifying the Test codes via the include. That's the only thing I could deduce so far.
As suggested by SoronelHaetir, I redid the whole thing using #defines and namespaces. It's working as intended now. In conclusion, the crude method was a bad idea from the getgo.

Global variables in C++ and CriticalSections

I have several global critical sections that need visibility across 3 or more classes defined in 3 or more .cpp files. They're defined in an h file as:
GlobalCS.h
#pragma once
#include "stdafx.h"
extern CRITICAL_SECTION g_cs1;
extern CRITICAL_SECTION g_cs2;
etc...
In a GlobalCS.cpp they are defined
#include "stdafx.h"
#include "GlobalCS.h"
CRITICAL_SECTION g_cs1;
CRITICAL_SECTION g_cs2;
Then in the cpp for the classes they need to work in they're included as
#include "stdafx.h"
#include "GlobalCS.h"
The linker is complaining giving unresolved external in the files where the critical sections are being used. I didn't expect this since the variables are defined as extern. What am I doing wrong or how do I get around this?
error LNK2001: unresolved external symbol "struct _RTL_CRITICAL_SECTION g_CS_SymbolStrPlotAccess" (?g_CS_SymbolStrPlotAccess##3U_RTL_CRITICAL_SECTION##A)
Not sure why you are getting the error. I tried the same thing in Visual Studio and in _tmain function I wrote the following:
int _tmain(int argc, _TCHAR* argv[])
{
//::g_cs1;
ZeroMemory(&g_cs1, sizeof(::g_cs1));
return 0;
}
And it built with no issues whatsoever.
Thank you all for your help. It always is helpful to have sanity checks. The issue was once again Visual Studio setup. Visual Studio will generate link errors if it doesn't like the way you have files added to your project. This is the second bug I've encountered that generated a link error based on the way the project was configured. If it's that important VS should either prevent you from modifying a project in a harmful way or provide a proper error message.
Anyway, the error is the same as this one:
LNK2019 Error under Visual Studio 2010
I had the GlobalCS.h and GlobalCS.cpp in the source directory. I prefer it this way because I find it makes finding files and code faster and in a large c++ project, just moving around the code base is a significant time waster. So much time could be saved writing c++ code if the IDE was designed to help find code faster. 2012 is A LOT better than 2010 so I'll give MSFT that but there could be a lot more features to that end (afterall VS has been around for almost 2 decades now)these types of persistent problems just get in the way of development. When I moved GlobalCS.h to the Header folder and cleaned the project and rebuilt, everything compiled as expected. The other similar error VS will throw at you is when the .h file is in the code directory (so #includes work) but not in the project. I got the same error messages when that happened and it took a good couple days to figure that one out. In a small project, it might not be as problematic but in big solution with multiple projects and dozens of files, it can be problematic.

undefined reference to function code blocks

main.cpp
#include <iostream>
#include <string>
using namespace std;
void echo(string);
int main()
{
echo("hello");
cout << "Hello world!" << endl;
return 0;
}
print.cpp
#include <iostream>
#include <string>
void echo(string code){
cout << code;
}
After compiling the code in code blocks 12.11, it gives me that error:
undefined reference to `echo(std::string)
I use windows 7 x64.
I have added the directory; Project>build options > search directories and added the current working directory.
All the files are in one console project in code blocks
I believe you should read up a bit more on namespaces usage. You are missing std in print.cpp.
Generally, while starting to learn cpp or getting a grip of the language you should always try writing full names of the classes along with the namespaces. Eventually with practice and some oversights (like now) you will learn why you really need them. In a nutshell namespaces are great:
When you are writing code over multiple files
Compartmentalize your code into separate blocks.
Also, using namespace std; should be used within cpp files mostly (otherwise headers get mangled up.
Anyways, try changing your code to this:
#include <iostream>
#include <string>
void echo(std::string code){
std::cout << code;
}
Then your results will look like this:
> g++ main.cpp print.cpp -o a.out
> ./a.out
helloHello world!
You should get more than that linker error, since you use string without any namespace in your print.cpp file. And if that source file doesn't compile it can't be linked with, and you will get the linker error you have.
Change to e.g.
void echo(std::string code) { ... }
And you do try to link with the object file created from print.cpp ?
I know this is old, but for anyone looking to solve this issue, the following may be a solution for you. If you have g++ follow c++ 11 under project->build options (check your options anyway) then you must check that box for all files you make in the project for the error to be cleared up. I had that annoying undefined reference thing too but now it is gone!
Try "Project/Properties/Build Targets tab". There you should find "Build target files" field. In that filed find "print.cpp" and click the checkbox (now the compiler will build print.cpp).
Some usefull information on Project management in CB
http://www.codeblocks.org/docs/main_codeblocks_en.html
When dealing with strings in C++ its best to sue std::string and your code seems to be wrong with a changes like using std::cout instead of plain cout another thing you need to be careful is linking your files especially files in different directories you need to tell code blocks were to find this print.cpp by going to build option and go for the search tab directory and point to where print.cpp is other wise the other approach is to just build a project which will have the main.cpp and and then add print.cpp class to current project I hope this will be of some help

Creating static library and linking to it with premake

I am currently trying to learn how to use premake 4 in order to apply it to the OpenGL sdk. I am currently trying to make a Visual Studio 2010 solution that constructs 2 projects, one being a static library, the other contains a single main source file, with the main method.
This project is extremely simple, and is solely for the purpose of learning premake. In the static library project, named Test, I have 2 files, Test.h and Test.cpp. Test.h contains the prototype for the method print(). print() simply prints a line to the console. Using premake, I linked the static library to the Main project, and in main.cpp I have included the Test.h file. My problem is this: in VS2010 I get this error when I attempt to build:
1>main.obj : error LNK2019: unresolved external symbol "void __cdecl print(void)" (? print##YAXXZ) referenced in function _main
1>.\Main.exe : fatal error LNK1120: 1 unresolved externals
Here is my code in the 4 files, the premake4.lua:
solution "HelloWorld"
configurations {"Debug", "Release"}
project "Main"
kind "ConsoleApp"
language "C++"
files{
"main.cpp"
}
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols" }
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize" }
links {"Test"}
project "Test"
kind "StaticLib"
language "C++"
files{
"test.h",
"test.cpp"
}
Test.cpp:
#include <iostream>
void print(){
std::cout << "HELLO" << std::endl;
}
Test.h:
void print();
Main.cpp:
#include <conio.h>
#include "test.h"
int main(){
print();
getch();
return 0;
}
If you are wondering why there is a getch() there, on my computer the console immediately closes once it reaches return 0, so I use getch() to combat that issue, which forces the window to wait until the user has pressed another key. Any advice on this issue would be wonderful, because I simply am not sure what the problem is. If it is something simple please dont castrate me on it, I have very little experience with premake and static libraries, which is why I am trying to learn them.
links {"Test"}
Lua is not Python. Whitespace is irrelevant to Lua, just like whitespace doesn't matter to C++. So your links statement only applies to the "Release" configuration. If you want it to apply to the project as a whole, it needs to go before the configuration statement, just like your kind, files, and other commands.
Premake4 works this way so that you could have certain libraries that are only used in a "Release" build (or Debug or whatever). Indeed, you can put almost any project command under a configuration. So you can have specific files that are used only in a debug build, or whatever.