Google unit testing in C++: how to write a persistent data file? - c++

Questions:
1) Where do files go that are created by a C++ Google unit test?
2) Is there a way to write a persistent data file in a C++ Google unit test, such that the file is accessible after the test runs?
Code and desired behavior
I'm running the unit test on Ubuntu 14.04 with catkin_make. I would like the code to write a file somewhere that I can find it after the test runs. The following code writes a file, but I don't know where it goes, or if it persists after the unit tests complete.
TEST(GUnitTestFileIo, Test_One)
{
std::ofstream csvFile;
csvFile.open("helloWorldTestFile.csv");
if (csvFile.is_open()) {
csvFile << "Hello, World, !" << std::endl;
csvFile.close();
} else {
std::cout << "Failed to open the file!" << std::endl;
}
}
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

One solution is to simply write to an absolute file path. The following code writes a file to the user's home directory from inside of a google unit test:
TEST(GUnitTestFileIo, Test_One)
{
char const* tmp = getenv( "HOME" );
if ( tmp == NULL ) {
std::cout << "$(HOME) environment variable is not defined!";
} else {
std::string home( tmp ); // string for the home directory
std::ofstream csvFile; // write the file
csvFile.open(home + "/helloWorldTestFile.csv");
if (csvFile.is_open()) {
csvFile << "Hello, World, !" << std::endl;
csvFile.close();
} else {
std::cout << "Failed to open the file!" << std::endl;
}
}
}
// Run all the tests that were declared with TEST()
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Related

unexpected getline behavior

Originally was trying to read data using char* but switched to string cause was getting behavior as if there was a missing null terminator. made the problem minimal below but still getting very weird output
int main(int argc, char * argv[]){
// file one: flightData
std::ifstream inFile1(argv[1]);
if (!inFile1.is_open())
{
std::cout << "Could not open the file 1." << std::endl;
return -1;
}
// file two: flightPlans
std::ifstream inFile2(argv[2]);
if (!inFile2.is_open())
{
std::cout << "Could not open the file 2." << std::endl;
return -1;
}
//File three: output
std::ofstream outputfile(argv[3]);
if (!outputfile.is_open())
{
std::cout << "Could not open the output file" << std::endl;
return -1;
}
std::string buffer;
getline(inFile1, buffer);
std::cout<<buffer<<std::endl;
while (getline(inFile1, buffer)) {
std::cout<<buffer;
std::cout<<"help";
}
// flightPlanner system(inFile1);
// system.printF();
// system.planFlights(inFile2,outputfile);
return 0;
}
output is
4
helpDallas|Austin|50|50help
which i'm pretty sure is incorrect, interestingly when i add endl to cout buffer it gives me output i would expect not really sure whats going on
inFile1
4
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
When i run in debugger i get the output i expect:
4
Dallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50help
any idea what could be going on?
Do you need flushing your stdout?
std::cout << std::flush;
Any chance your shell ate your outputs?
Try pipping the output to "cat -A":
./a.out | cat -A
(Drive by comment - I may not know what I'm talking about ^_^)

How to grant access to hosts.txt file using C++ 11 on MacOS

I am attempting to write a program that can append text to a given host file on MacOS, but due to permission issues I am not allowed to do so.
Here's my code:
#include <iostream>
#include <fstream>
int main(int argc, const char * argv[]) {
std::ofstream myfile;
myfile.open("/private/etc/hosts.txt", std::ios::app);
if(!myfile.is_open()){
std::cout << "Host file could not be opened or located" << std::endl;
} else {
myfile << "data to be appended" << std::endl;
std::cout << "Host file has been modified" << std::endl;
myfile.close();
}
return 0;
}
I created a public folder with a mock of the hosts.txt file in the same root directory and it worked so I'm positive it is a permission error but I am BRAND new to working with files in C++ and have no idea how to proceed or if what I'm doing is even possible.
Thanks

Cannot rename rosbag file after recording

I would like to record a rosbag file with a specific name; however, I only know it after the recording is halfway done, so I cannot set the filename here:
cfg.enable_record_to_file("some/path/filename.bag");
I have tried to rename the new file as shown below without satisfactory success. I have also used std::experimental::filesystem::rename, with the same outcome. What did work was to record a second video (on the fly) and only then rename the first. This indicates that the (both) rename functions work, but I cannot change the filename it as it seems the file is still open in my current program.
int main(int argc, char* argv[])
{
rs2::config cfg;
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
device.as<rs2::recorder>().pause();
pipe->stop();
int res = std::rename("tmp.bag", "test.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
return 0;
}
I wonder how to 'unload' the produced video from the pipeline (pipe->stop() did not work), so I can rename the generated rosbag files on the fly.
As suggested by #TedLyngmo, adding curly brackets allowed me to change the filename on the fly. Code as follows:
int main(int argc, char* argv[])
{
{
rs2::config cfg;
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
device.as<rs2::recorder>().pause();
pipe->stop();
}
int res = std::rename("tmp.bag", "test.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
return 0;
}
EDIT
I studied rs-record-playback a bit more and the code below fixes the renaming issue.
int main(int argc, char* argv[])
{
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
pipe->start();
device = pipe->get_active_profile().get_device();
if (!device.as<rs2::recorder>())
{
pipe->stop(); // Stop the pipeline with the default configuration
pipe = std::make_shared<rs2::pipeline>();
rs2::config cfg;
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
}
// record for 1 sec, if conditions can be added to check if recorder is initialised
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// if condition can be added to check if recording has been completed
pipe->stop();
pipe = std::make_shared<rs2::pipeline>(); // reset the shared pointer
pipe->start();
device = pipe->get_active_profile().get_device();
int res = std::rename("tmp.bag", "testing.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
pipe->stop();
pipe = std::make_shared<rs2::pipeline>();
}

Using std::cout in Qt Gui

I have an application that when run through terminal, the user has the option between command-line mode or GUI mode.
There doesn't seem to be any output to the console at all when using std::cout. std::cout statements don't work in the main event loop.
I have added CONFIG += console to my .pro file.
For now, I have been using QTextStream() which works fine:
QTextStream(cout) << "Hello World" << std::endl;
My question is:
Why can I not use std::cout? Does this have something to do with Qt affecting input and output streams? I couldn't find any documentation in Qt's docs on this.
int main(int argc, char *argv[])
{
std::cout << argv[1] << std::endl; //This is being outputted.
//if(argc == 2 && !strcmp(argv[1],"-win")){
if(true){ //Just for this example's sake
QApplication a(argc, argv);
std::cout << "Hello" << std::endl; //This is not being ouputted.
MainWindow w;
w.show();
return a.exec();
}
else
{
qDebug() << "Console Mode.\n";
std::cout << "Console Mode.\n";
//Do stuff
}
}
This is not a Qt issue, but how std::cout works. You seem to blow up your std::cout in here:
std::cout << argv[1] << std::endl;
Your issue can be reproduced even with a simple program like this:
main.pro
TEMPLATE = app
TARGET = main
CONFIG -= qt
SOURCES += main.cpp
main.cpp
#include <iostream>
int main(int /*argc*/, char **argv)
{
std::cout << argv[1] << std::endl;
std::cout << "Hello stdout!" << std::endl;
if (std::cout.bad())
std::cerr << "I/O error while reading\n";
return 0;
}
Build and Run
Success: qmake && make && ./main foo
Failure: qmake && make && ./main
In your case argv[1] is nil and so this makes std::cout not to print anything more. I would suggest to either pass an argument all the time and/or check against argc with some help usage print. The best would be to use the builtin command line parser in QtCore these days.
You could ask why? Because it is undefined behavior. You can read the details from the documentation:
basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);
After constructing and checking the sentry object, checks if sb is a null pointer. If it is, executes setstate(badbit) and exits.
If you happen to have an issue with the IDE itself, for instance QtCreator, then follow these steps in case of QtCreator:
Projects -> Select a kit -> Run tab -> Run section -> Arguments
Works OK for me:
QT += core
QT -= gui
TARGET = untitled
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
main.cpp:
#include <QCoreApplication>
#include <QTextStream>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout << "Hello World" << std::endl;
return a.exec();
}
EDIT:
#include <QCoreApplication>
#include <QTextStream>
#include <QtWidgets/QWidget>
#include <QDebug>
#include <iostream>
int main(int argc, char *argv[]) {
std::cout << "test" << std::endl; // <--- THE PROBLEM IS HERE...IF YOU TRY A SIMPLE STRING IT WORKS FINE SO THE PROBLEM IS argv[1] IS AN EMPTY STRING
//if(argc == 2 && !strcmp(argv[1],"-win")){
if(true){
//Just for this example's sake
QCoreApplication a(argc, argv);
std::cout << "Hello" << std::endl; //This is not being ouputted.
return a.exec();
}
else
{
qDebug() << "Console Mode.\n";
std::cout << "Console Mode.\n";
//Do stuff
} }

OpenCV, C++ cvCaptureFromFile not working but Python VideoCapture is

Im working with some legacy code that I need to use, as well as do some work in Python. I am able to read from file in Python but not in C++. Here is the C++ code
int main(int argc, char** argv) {
CvCapture *capture = NULL;
capture = cvCaptureFromFile("path/to/foo.mov");
if (!capture) {
std::cerr << "Cannot open " << "path/to/foo.mov" << std::endl;
return 1;
}
return 0;
}