Получить последнюю строку, напечатанную на C / C ++ - PullRequest
1 голос
/ 19 февраля 2020

Я пытаюсь создать тестер с помощью googletest. проблема в том, что функция, которую я тестирую, возвращает void и печатает результат. Я хочу, чтобы последняя строка была напечатана в консоли, чтобы я мог проверить вывод. строка может содержать \n.

, поэтому у меня есть сама функция:

void f_sequence(char sequenceStr[])
{
   //logic...
    if(condotion1)
        printf("somthing1");
    else if(condotion2)
        printf("somthing2")
(...)
}

, а затем тестер:

TEST(TesterGroup, TesterName)
{
    f_sequence("input");
    EXPECT_EQ("somthing1", /*how do i get the output?*/);
}

Возможно ли это?

Функции, которые я тестирую, находятся в c, в то время как сама функция Test (тестер) находится в c ++. вывод печатается с использованием printf. Я не могу изменить саму функцию. Я использую последнюю версию CLion.

Ответы [ 5 ]

1 голос
/ 19 февраля 2020

Перенаправить стандартный вывод в буфер.

Live на 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;
}

Ссылки: http://kaskavalci.com/redirecting-stdout-to-array-and-restoring-it-back-in-c/

0 голосов
/ 19 февраля 2020

Существует решение (в C) для вызова API (cmd_rsp) с исходным кодом здесь , которое при вызове в вашей программе создает отдельный процесс и направляет в оба stdin и stdout, от которых он принимает команду и возвращает ответ через буфер авторазмера. По концепции похож на popen(...).

Простой пример использования:

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);
0 голосов
/ 19 февраля 2020

Два способа:

Если вы работаете в POSIX-совместимой системе, вы можете перенаправить вывод программы в файл, используя >, а затем прочитать из файла позже, чтобы подтвердить, что вывод правильно.

Другой способ выглядит примерно так:

freopen("output.txt", "w", stdout);
f_sequence();
freopen("/dev/tty", "w", stdout);

для POSIX-совместимых систем. На других платформах вам нужно изменить "/dev/tty" на что-то другое. Я не знаю о полностью портативном способе сделать это.

А потом читать из output.txt. Приведенный выше фрагмент кода изменяет значение stdout и печатает в файл вместо обычного стандартного вывода.

0 голосов
/ 19 февраля 2020

Одно решение: вы можете написать отдельную программу, которая выполняет функцию, и в модульном тесте вы можете выполнить эту программу как подпроцесс и проверить вывод. Это можно сделать с помощью std::system, но будьте очень осторожны, чтобы не передавать какие-либо непостоянные входные данные. Вам не нужна уязвимость при внедрении оболочки даже в модульном тесте. Существуют системные спецификации c, которые позволяют избежать использования оболочки в подпроцессе.

Другое решение, которое возможно по крайней мере в POSIX: замените стандартные потоки out / err дескрипторами файлов и прочитайте файлы впоследствии.

Спецификация Googletest c: Кажется, есть testing::internal::CaptureStdout, который, похоже, реализует идею замены стандартных потоков. Но, как следует из пространства имен, это не официальный API, поэтому может измениться в будущем.

0 голосов
/ 19 февраля 2020

Я не знаю, возможно ли получить то, что было напечатано в последний раз, но если вы контролируете среду до , когда вызывается ваша тестовая функция, вы можете перенаправить туда, куда идет стандартный вывод, что позволяет вам записать это в файл, который вы затем можете проверить.

См. этот старый ответ , которым ИМО пренебрег. Пример из него модифицируется здесь:

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.
...