Get the last string printed in C/C++ - c++

I am trying to create a tester using googletest. the problem is that the function that I am testing is returning void and printing a result instead. I want to get the last string printed into the console so I can test the output. the string may include \n.
so I have the function itself:
void f_sequence(char sequenceStr[])
{
//logic...
if(condotion1)
printf("somthing1");
else if(condotion2)
printf("somthing2")
(...)
}
and then the tester:
TEST(TesterGroup, TesterName)
{
f_sequence("input");
EXPECT_EQ("somthing1", /*how do i get the output?*/);
}
Is it possible?
The functions I test are in c, while the Test function itself (the tester) is in c++. the output is printed using printf. I cannot change the function itself. I am using CLion latest version.

Redirect the standard output to a buffer.
Live on Coliru
#include <stdio.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int stdoutSave;
char outputBuffer[BUFFER_SIZE];
void replaceStdout()
{
fflush(stdout); //clean everything first
stdoutSave = dup(STDOUT_FILENO); //save the stdout state
freopen("NUL", "a", stdout); //redirect stdout to null pointer
setvbuf(stdout, outputBuffer, _IOFBF, 1024); //set buffer to stdout
}
void restoreStdout()
{
freopen("NUL", "a", stdout); //redirect stdout to null again
dup2(stdoutSave, STDOUT_FILENO); //restore the previous state of stdout
setvbuf(stdout, NULL, _IONBF, BUFFER_SIZE); //disable buffer to print to screen instantly
}
void printHelloWorld()
{
printf("hello\n");
printf("world");
}
int main()
{
replaceStdout();
printHelloWorld();
restoreStdout();
// Use outputBuffer to test EXPECT_EQ("somthing1", outputBuffer);
printf("Fetched output: (%s)", outputBuffer);
return 0;
}
References: http://kaskavalci.com/redirecting-stdout-to-array-and-restoring-it-back-in-c/

I don't know if it's possible to get what was last printed, but if you control the environment before your test function is called, you can redirect where standard output goes, which lets you write it to a file, which you can then check.
See this old answer which IMO was neglected. The example from it is modified here:
FILE *fp_old = stdout; // preserve the original stdout
stdout = fopen("/path/to/file/you/want.txt","w"); // redirect stdout to anywhere you can open
// CALL YOUR FUNCTION UNDER TEST HERE
fclose(stdout); // Close the file with the output contents
stdout=fp_old; // restore stdout to normal
// Re-open the file from above, and read it to make sure it contains what you expect.

Two ways:
If you're on a POSIX compatibile system, you can redirect the output of the program to a file using >, then read from the file later to confirm that the output is correct.
The other way is something like this:
freopen("output.txt", "w", stdout);
f_sequence();
freopen("/dev/tty", "w", stdout);
for POSIX compatible systems. On other platforms you'd need to change the "/dev/tty" to something else. I'm not aware of a completely portable way to do this.
And then read from output.txt. What the above snippet does is change what stdout is, so that it prints to a file instead of the normal stdout.

One solution: You can write a separate program that executes the function, and in the unit test, you can execute that program as a sub process and inspect the output. This can be done with std::system, but be very careful to not pass any non-constant input to it. You don't want shell injection vulnerability even in a unit test. System specific functions exist that avoid the use of shell in the subprocess.
Another solution, which is possible at least on POSIX: Replace the the standard out / err streams with file descriptors, and read the files afterwards.
Googletest specific: There seems to be testing::internal::CaptureStdout, which appears to implement the idea of replacing standard streams. But as the namespace implies, this is not official API, so may change in future.

There is a solution ( in C ) for an API call ( cmd_rsp ) with source code here, that when called in your program, creates a separate process, and pipes to both stdin and stdout, from which it accepts a command and returns the response via an auto sizing buffer. Similar in concept to popen(...).
A simple use case:
char *buf = NULL;
/// test cmd_rsp
buf = calloc(BUF_SIZE, 1);
if(!buf)return 0;
if (!cmd_rsp("dir /s", &buf, BUF_SIZE))//note the first argument can be any legal command that
//can be sent via the CMD prompt in windows,
//including a custom executable
{
printf("%s", buf);
}
else
{
printf("failed to send command.\n");
}
free(buf);

Related

call gnuplot via fork and pipe and update plot

I want to do some realtime-plots during a simulation. For this, i would like to use octave or gnuplot. My current approach is to use a frontend to gnuplot, feedgnuplot, which fits actually very well.
The Simulation is written in C++, so i thought about forking (new process for feedgnuplot) and piping the relevant data to feedgnuplot.
The problem i have is that the output is only visible after the simulation.
But i want to see the plot updated during simulation.
Here is a MWE:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int main()
{
FILE* stream = popen("feedgnuplot", "w");
for(int i = 0; i < 10; ++i)
{
fprintf(stream, "%d\n", i * i);
fflush(stream);
sleep(1);
}
}
The program stops after 10 secons, showing the plot.
When using feedgnuplot directly in the shell, everything works as expected.
(That is, newly added data is plotted without the need to end the process)
What am i doing wrong? I think i lack some understanding of how popen really works.
First, let's write a fake feedgnuplot.c:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buf = NULL;
size_t n = 0;
while (getline (&buf, &n, stdin) != -1) {
printf ("%s", buf);
}
free (buf);
return 0;
}
With this, your code works, i.e. the lines are printed as they arrive.
I suspect the problem lies in the way your feedgnuplot program reads incoming data. You should show the relevant part of that code.
If I had to take a guess, you probably need to add
setvbuf (stdin, NULL, _IOLBF, 0);
in feedgnuplot before you start to read from stdin.
That is because by default, when stdin corresponds to a terminal it is line buffered, whereas when it corresponds to a pipe it is fully buffered. The code above makes stdin line buffered no matter what so there should be no difference between reading from a terminal or a pipe.

How do I run a program from another program and pass data to it via stdin in c or c++?

Say I have an .exe, lets say sum.exe. Now say the code for sum.exe is
void main ()
{
int a,b;
scanf ("%d%d", &a, &b);
printf ("%d", a+b);
}
I wanted to know how I could run this program from another c/c++ program and pass input via stdin like they do in online compiler sites like ideone where I type the code in and provide the stdin data in a textbox and that data is accepted by the program using scanf or cin. Also, I wanted to know if there was any way to read the output of this program from the original program that started it.
The easiest way I know for doing this is by using the popen() function. It works in Windows and UNIX. On the other way, popen() only allows unidirectional communication.
For example, to pass information to sum.exe (although you won't be able to read back the result), you can do this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
f = popen ("sum.exe", "w");
if (!f)
{
perror ("popen");
exit(1);
}
printf ("Sending 3 and 4 to sum.exe...\n");
fprintf (f, "%d\n%d\n", 3, 4);
pclose (f);
return 0;
}
In C on platforms whose name end with X (i.e. not Windows), the key components are:
pipe - Returns a pair of file descriptors, so that what's written to one can be read from the other.
fork - Forks the process to two, both keep running the same code.
dup2 - Renumbers file descriptors. With this, you can take one end of a pipe and turn it into stdin or stdout.
exec - Stop running the current program, start running another, in the same process.
Combine them all, and you can get what you asked for.
This is my solution and it worked:
sum.cpp
#include "stdio.h"
int main (){
int a,b;
scanf ("%d%d", &a, &b);
printf ("%d", a+b);
return 0;
}
test.cpp
#include <stdio.h>
#include <stdlib.h>
int main(){
system("./sum.exe < data.txt");
return 0;
}
data.txt
3 4
Try this solution :)
How to do so is platform dependent.
Under windows, Use CreatePipe and CreateProcess. You can find example from MSDN :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
Under Linux/Unix, you can use dup() / dup2()
One simple way to do so is to use a Terminal (like command prompt in windows) and use | to redirect input/output.
Example:
program1 | program2
This will redirect program1's output to program2's input.
To retrieve/input date, you can use temporary files, If you don't want to use temporary files, you will have to use pipe.
For Windows, (use command prompt):
program1 <input >output
For Linux, you can use tee utility, you can find detail instruction by typing man tee in linux terminal
It sounds like you're coming from a Windows environment, so this might not be the answer you are looking for, but from the command line you can use the pipe redirection operator '|' to redirect the stdout of one program to the stdin of another. http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
You're probably better off working in a bash shell, which you can get on Windows with cygwin http://cygwin.com/
Also, your example looks like a mix of C++ and C, and the declaration of main isn't exactly an accepted standard for either.
How to do this (you have to check for errors ie. pipe()==-1, dup()!=0, etc, I'm not doing this in the following snippet).
This code runs your program "sum", writes "2 3" to it, and than reads sum's output. Next, it writes the output on the stdout.
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int parent_to_child[2], child_to_parent[2];
pipe(parent_to_child);
pipe(child_to_parent);
char name[] = "sum";
char *args[] = {name, NULL};
switch (fork()) {
case 0:
// replace stdin with reading from parent
close(fileno(stdin));
dup(parent_to_child[0]);
close(parent_to_child[0]);
// replace stdout with writing to parent
close(fileno(stdout));
dup(child_to_parent[1]);
close(child_to_parent[1]);
close(parent_to_child[1]); // dont write on this pipe
close(child_to_parent[0]); // dont read from this pipe
execvp("./sum", args);
break;
default:
char msg[] = "2 3\n";
close(parent_to_child[0]); // dont read from this pipe
close(child_to_parent[1]); // dont write on this pipe
write(parent_to_child[1], msg, sizeof(msg));
close(parent_to_child[1]);
char res[64];
wait(0);
read(child_to_parent[0], res, 64);
printf("%s", res);
exit(0);
}
}
I'm doing what #ugoren suggested in their answer:
Create two pipes for communication between processes
Fork
Replace stdin, and stdout with pipes' ends using dup
Send the data through the pipe
Based on a few answers posted above and various tutorials/manuals, I just did this in Linux using pipe() and shell redirection. The strategy is to first create a pipe, call another program and redirect the output of the callee from stdout to one end of the pipe, and then read the other end of the pipe. As long as the callee writes to stdout there's no need to modify it.
In my application, I needed to read a math expression input from the user, call a standalone calculator and retrieve its answer. Here's my simplified solution to demonstrate the redirection:
#include <string>
#include <unistd.h>
#include <sstream>
#include <iostream>
// this function is used to wait on the pipe input and clear input buffer after each read
std::string pipeRead(int fd) {
char data[100];
ssize_t size = 0;
while (size == 0) {
size = read(fd, data, 100);
}
std::string ret = data;
return ret;
}
int main() {
// create pipe
int calculatorPipe[2];
if(pipe(calculatorPipe) < 0) {
exit(1);
}
std::string answer = "";
std::stringstream call;
// redirect calculator's output from stdout to one end of the pipe and execute
// e.g. ./myCalculator 1+1 >&8
call << "./myCalculator 1+1 >&" << calculatorPipe[1];
system(call.str().c_str());
// now read the other end of the pipe
answer = pipeRead(calculatorPipe[0]);
std::cout << "pipe data " << answer << "\n";
return 0;
}
Obviously there are other solutions out there but this is what I can think of without modifying the callee program. Things might be different in Windows though.
Some useful links:
https://www.geeksforgeeks.org/pipe-system-call/
https://www.gnu.org/software/bash/manual/html_node/Redirections.html

Standard output hangs after adding fprintf() statement with custom standard error

I have a C++ class Archive with a member function extractData(). This function calls realExtractData(), which is implemented in a separate C library.
I want to pass the extractData() function a pair of FILE * instances that are usually stdout and stderr, but I want to provide the option of custom file pointers, as well:
class Archive {
public:
...
int extractData(string id, FILE *customOut, FILE *customErr);
...
};
int
Archive::extractData(string id, FILE *customOut, FILE *customErr)
{
if (realExtractData(id.c_str(), customOut) != EXIT_SUCCESS) {
fprintf(stderr, "something went wrong...\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
If I call the above as listed, there is no delay in outputting data to standard output. All extracted data get sent to standard output (stdout) almost immediately:
FILE *outFp = stdout;
FILE *errFp = stderr;
Archive *archive = new Archive(inFilename);
if (archive->extractData(id, outFp, errFp) != EXIT_SUCCESS) {
fprintf(errFp, "[error] - could not extract %s\n", archive->getInFnCStr());
return EXIT_FAILURE;
}
If I change extractData() so that its fprintf() call uses customErr:
int
Archive::extractData(string id, FILE *customOut, FILE *customErr)
{
if (realExtractData(id.c_str(), customOut) != EXIT_SUCCESS) {
fprintf(customErr, "something went wrong...\n"); /* <-- changed this line */
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
...then when I run the binary, the binary seems to hang in processing input and printing to standard output.
If I change fprintf() back to using stderr and not customErr, things once again work properly, i.e., data are flushed to standard output (my customOut) immediately.
Is this a buffering issue? Is there a way to fix this?
"stderr and not customErr"
Standard error is un-buffered which means it prints out almost immediately. other output streams are buffered unless you're using low-level OS calls, which means they will take longer to print unless you do a buffer flush with something like an endl, ::flush, or whatever else.
If you want to go for the low-level OS calls and you're working with unix, check this out:
http://www.annrich.com/cs590/notes/cs590_lecture_2.pdf
I haven't read the whole thing, but on scanning it it looks as if it has similar info to the good Stevens Advanced Programming in Unix book which defitely talks through this.

How to restore stdout after using freopen

I try to redirect output in my c++ program from stdout with the following:
freopen(cmd.c_str(),"w",stdout);
Then I call system to execute cmd. I have also tried forking and then calling execvp. Either way, when program control returns to my program, things written to stdout are no longer showing. How can normal behavior be restored?
Here is solution for stdin if doing in loop, needed to figure this out for a program wherein freopen of stdin happens in a loop on some condition. Took some time for me to figure out (with help of search and all) and so posting here
savestdin = dup(STDIN_FILENO);
while (1) {
.
.
if (inputfile) {
savestdin = dup(savestdin);
freopen(inputfile, "r", stdin);
restorestdin = TRUE;
}
.
.
if (restorestdin) {
fflush(stdin);
fclose(stdin);
stdin = fdopen(savestdin, "r");
restorestdin = FALSE;
}
.
.
}
Do this:
fclose(stdout);
stdout = fdopen(1, "w"); //reopen: 1 is file descriptor of std output
If you can use STDOUT_FILENO from <unistd.h>, instead of 1 as first argument to fdopen.

C/C++ add input to stdin from the program?

Is that even possible ?
Lets say that the code has a lot of scanf lines. Instead of manually running and adding values by hand when debugging, is it possible to "feed" stdin with data so that when the scanf starts reading, it will read the inputted data without any need to interact with the terminal.
Put the test lines into a file, and run the program like this:
myprogram < mytestlines.txt
Better than hacking your program to somehow do that itself.
When you're debugging the code, you can set up the debugger to run it with that command line.
To make your program a little more versatile, you might want to consider rewriting your program to use fscanf, fprintf, etc. so that it can already handle file IO as opposed to just console IO; then when you want to read from stdin or write to stdout, you would just do something along the lines of:
FILE *infile, *outfile;
if (use_console) {
infile = stdin;
outfile = stdout;
} else {
infile = fopen("intest.txt", "r");
outfile = fopen("output.txt", "w");
}
fscanf(infile, "%d", &x);
fprintf(outfile, "2*x is %d", 2*x);
Because how often do programs only handle stdin/stdout and not allow files? Especially if you end up using your program in shell scripts, it can be more explicit to specify input and outputs on the command line.
int fd[2];
pipe(fd);
close(0); // 0:stdin
dup(fd[0], 0); // make read pipe be stdin
close(fd[0]);
fd[0] = 0;
write(fd[1], "some text", 9); // write "some text" to stdin