How to write a test function for another function using stdin input?

I have the following functions as part of a college assignment:

int readMenuOption() { /* local declarations */ char option[2]; /* read in 1 char from stdin plus 1 char for string termination character */ readStdin(1 + 1, option); return (int)option[0] <= ASCII_OFFSET ? 0 : (int)option[0] - ASCII_OFFSET; } int readStdin(int limit, char *buffer) { char c; int i = 0; int read = FALSE; while ((c = fgetc(stdin)) != '\n') { /* if the input string buffer has already reached it maximum limit, then abandon any other excess characters. */ if (i <= limit) { *(buffer + i) = c; i++; read = TRUE; } } /* clear the remaining elements of the input buffer with a null character. */ for (i = i; i < strlen(buffer); i++) { *(buffer + i) = '\0'; } return read; } 

It works great for what I need (do keyboard input). I had to do this with stdin (like mine) due to a number of requirements set forth by my professor.

I want to write a series of โ€œunit testsโ€ for assignment, but I donโ€™t know how to get my test functions to call readMenuOption() and pass input (without having to do this at runtime).

Is this possible, and if so, how can I do this? (i.e. is it possible to write to stdin)?

+3
source share
3 answers

The only thing you can do is simply modify readStdin so that it can either receive data from real standard input or from a helper function, for example:

 char *fakeStdIn = ""; int myfgetc (FILE *fin) { if (*fakeStdIn == '\0') return fgetc (fin); return *fakeStdIn++; } int readStdin(int limit, char *buffer) { char c; int i = 0; int read = FALSE; while ((c = myfgetc(stdin)) != '\n') { /* if the input string buffer has already reached it maximum limit, then abandon any other excess characters. */ if (i <= limit) { *(buffer + i) = c; i++; read = TRUE; } } /* clear the remaining elements of the input buffer with a null character. */ for (i = i; i < strlen(buffer); i++) { *(buffer + i) = '\0'; } return read; } 

Then, to call it from your unit test, you can do:

 fakeStdIn = "1\npaxdiablo\nnice guy\n"; // Call your top-level input functions like readMenuOption(). 

By placing the hook on the lower levels, you can enter your own character sequence instead of standard input. And if at some point the fake standard input is exhausted, it returns to the real one.

Obviously this is the use of characters, so if you want to inject EOF events, you will need an array of integers, but this will be a minor modification to the circuit.

+5
source

Search for a non-standard but extremely useful forkpty function. Then do something like:

 int ptyfd; pid = forkpty(&ptyfd, 0, 0, 0); if (pid<0) perror("forkpty"), exit(1); if (!pid) { /* call your function to be tested */ _exit(1); } else { /* write to ptyfd here to generate input for the function */ } 

Please note that this will allow you to test your function exactly as if it were reading from an interactive terminal. If you do not need this level of testing, you can use a simple channel.

+1
source

Why can't you use redirection? Sort of:

 ./a.out < input.txt 

Where "input.txt" will contain any input that you want to pass to the program.

0
source

All Articles