I am trying to use Google Test to test C code but I am encounter some problem related to write stub for system functions like: fopen,fclose,fread,fwrite, memcpy,memset,stat,...I don't known how to stub them correctly to cover all branchs in function that need to be tested.
Example , I have a function, how to test it by stub fopen, fclose, fwrite, fread?
Only Stub, not Mock.
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *f;
//initialize the arr1 with values
int arr1[5]={1,2,3,4,5};
int arr2[5];
int i=0;
//open the file for write operation
if((f=fopen("includehelp.txt","w"))==NULL){
//if the file does not exist print the string
printf("Cannot open the file...");
exit(1);
}
//write the values on the file
if((fwrite(arr1,sizeof(int),5,f))!=5){
printf("File write error....\n");
}
//close the file
fclose(f);
//open the file for read operation
if((f=fopen("includehelp.txt","r"))==NULL){
//if the file does not exist print the string
printf("Cannot open the file...");
exit(1);
}
//read the values from the file and store it into the array
if((fread(arr2,sizeof(int),5,f))!=5){
printf("File write error....\n");
}
fclose(f);
printf("The array content is-\n");
for(i=0;i<5;i++){
printf("%d\n",arr2[i]);
}
return 0;
}
Your file() function in sample.c calls fopen(). Defining fopen as something else in a totally different file (compilation unit) is not going to change that.
You cannot simply mock a free function.
You can change the file() function to take a pointer to the fopen() function to use. In your tests you then provide a pointer to your mock function when calling the file() function. This is a form of dependency injection.
Another option is to use conditional compilation.
An example of using dependency injection:
// Typedef for our "fopen interface". Makes our code a bit more readable.
typedef FILE *(*fopen_type)(const char *, const char *);
FILE *file(fopen_type fopen_func)
{
FILE *f = fopen_func("abc", "r"); // Call the provided "fopen" function.
return f; // Let's return the opened file or `NULL`.
}
And then in your test code:
TEST(OPEN_FILE, OK)
{
ASSERT_NE(NULL, file(&my_fopen));
}
If you use many system functions that you want to mock, you can also create a struct that contains pointers to all the relevant functions.
struct system_calls {
fopen_type fopen;
// Add more system calls here.
};
FILE *file(struct system_calls *p)
{
FILE *f = p->fopen("abc", "r");
return f;
}
The premise here is that if you want to test your code, you need to write testable code. Dependency injection is one way to achieve that.
Related
Below is a part of my code which is having issues with file handling. The file opens fine with fopen but when I try to read or just close the file my program exits without an error. I tried to run this code independently and it works fine. Would really appreciate if someone could help me out which pointing out what I am doing wrong.
int ctrlSend(char *etherPort, uint8_t *inPayload, int payloadLen, int vlanID)
{
char intName [10]; // Interface name from file
int intVlan; // Interface VLAN from file
printf("In ctrlSend\n");
FILE * pFile; // File pointer
pFile = fopen ("vlan.conf","r");
while(!feof(pFile))
{
fscanf(pFile,"%s %d",intName,&intVlan)
printf("In ctrlSend while loop");
}
fclose (pFile);
return 0;
}
UPDATE1: Updated above code
UPDATE2: Alternate code below which has same issue.
int ctrlSend(char *etherPort, uint8_t *inPayload, int payloadLen, int vlanID)
{
printf("In ctrlSend\n");
char intName [10]; // Interface name from file
int intVlan; // Interface VLAN from file
FILE * pFile; // File pointer
pFile = fopen ("vlan.conf","r");
while (fscanf (pFile,"%s %d",intName,&intVlan) == 2)
{
printf("In ctrlSend while loop");
}
fclose (pFile);
return 0;
}
UPDATE3: Seems like the file is not opening, looking into it.
When you do while (!feof ...) you check each time if you have reach the end of the file. However, at no point your advance in the file (fread ?). That means this will never terminate.
Check whether the file exists or not. You should always check whether File pointer is NULL or not after opening the file. I think your program is unable to open the file and you are trying to use the file pointer without checking which is causing undefined behavior.
I am new to C, I am just trying to read a simple text file I created in C. I made this file by clicking new -> empty file -> saving it to my desired location and then adding the file extension (.txt) the text file holds a sample sudoku board and the full file name is sudokuchar.txt.
The code I have to read from the file and print it is:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fpointer = fopen("sudokuchar.txt", "r");
char input[100];
while(fgets(input,100,fpointer))
{
printf("%s",input);
}
fclose(fpointer);
}
so when i compile the program does not print anything and returns -1. I assume something is wrong with the file i am trying to read from?? if some one could help it would be greatly appreciated.
Always check the return values of fopen and other standard library calls. It's most likely that your file doesn't exist. You can make a nice user friendly error message using errno, just make sure to include errno.h. Overall, your code should work, but you NEED to check the return values of things, because fopen returns NULL if it can't find the file.
FILE *fpointer = fopen("sudokuchar.txt", "r");
if(fpointer == NULL) {
fprintf(stderr, "Error: [Errno %d]: %s\n",
errno, strerror(errno));
return 1;
}
It is advisable to check what file pointer returns. If file pointer returns 0 or NULL then File pointer is unable to point to the file name you had provided. Also you can use this
File *fp = fopen(file name with full path (i.e. /home/chex/read.txt),"r")
Check man fopen
FILE *fopen(const char *path, const char *mode);
Ok, here is the deal...i remember creating a program past week that required me to open a file in binary mode and write data to it. At first, i tried using the fopen function, checking if the result is ok, then try to write data. I remember that at first try, the fwrite operation wasn't working. Then, after moving declaration of variables from a place to another, i was finally able to make the fwrite to insert data to the file.
Now, i need to create another similar program to do some other stuff, so i wanted to use the same allocation code (actually, i wanted to create a specific function to do the same), and here is what i was able to come up with:
#include <stdio.h>
int openfile(FILE *main, char *name, int option);
int main(void)
{
FILE *main;
int header_init;
int result;
switch (openfile(main,"main_file.bin",1)) {
case 1:
header_init = -1;
//fseek(main,0,SEEK_SET); --> useless
fwrite(&header_init,sizeof(int),1,main);
printf("ftell = %d\n",ftell(main)); break;
case 2:
fread(&header_init,sizeof(int),1,main);
printf("%d\n",header_init); break;
default:
printf("Error trying to open file\n");
}
printf("header_init is %d\n",header_init);
fclose(main); exit(0);
}
int openfile(FILE *main, char *name, int option)
{
int result_alloc;
int F_OK;
if (result_alloc = access (name, F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main= fopen(name,"w+b")) != NULL) return 1;
}
else {
printf("File exist, allocating as r+b\n");
if ((main= fopen(name,"r+b")) != NULL) return 2;
}
printf("Failure trying to open");
return 0;
}
For some unfortunate reason, the fwrite operation is not writing -1 to the allocated file. My intention with this program is so that it will always check for existence of that specific file: if there is one in place, simply open it with r+b to allow update functions without overwriting the actual file contents. Otherwise, allocate a new one with a header value of -1 (i will use this file as a record file with chained list structure).
Seriously, i cannot understand why this is not working. The idea is the same of my previous program. The only thing that changed is that i created a function, because this is going to happen me later (because of the 3rd parameter that will allow me to reduce my code and make it more "readable" - at least this is the intention!). I HAVE to admit that i have some attention to details problem, but i am working hard to get better at it, i am probably missing something stupid in this code, but after hours looking at it i really wanted to ask here for some help. Thanks
Edit: I am running it under z/Linux. What i am trying to understand is, why the code above doesn't write -1 to the file, but the one below writes ok?
#include <stdio.h>
int main(void)
{
FILE *main;
int result_alloc;
int header_init;
int F_OK;
if (result_alloc = access ("test.bin", F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main = fopen("test.bin","w+b")) == NULL) {
printf("Failure trying to open file");
return 1;
}
else {
header_init = -1;
printf("current pos is: w+b %d\n",ftell(main));
fwrite(&header_init,sizeof(int),1,main);
printf("current pos is: write header_init %d\n",ftell(main));
}
}
else {
if ((main = fopen("test.bin","r+b")) == NULL) {
printf("Failure trying to open file");
return 2;
}
else {
printf("current pos is: r+b %d\n",ftell(main));
fread(&header_init,sizeof(int),1,main);
printf("current pos is: read header_init %d\n",ftell(main));
}
}
}
The main issue that the assignment to the main variable inside of the openfile function is not seen by the calling function. Because C is pass by value, you're only changing the value of the function parameter, not the value of the variable that was passed in. So when openfile returns, the main variable inside of the main function is unchanged.
What you need to do is pass the address of that variable to the function, then within the function you dereference the local variable (which is a pointer) and assign a value to the dereferenced variable.
Also, it's not a good idea to have a variable with the same name as a function as it hides the function in that scope and can cause confusion.
So you would define your function as follows:
int openfile(FILE **fp, char *name, int option);
You would then call it like this (changing the name of the main variable to fp):
FILE *fp;
...
openfile(&fp,"main_file.bin",1)
Then inside of openfile, you dereference fp to change the value in the calling function:
*fp = fopen(name,"w+b")
The reason why the second code sample is working is that you're assigning directly to a local variable and then using that same variable later on in the function.
Also, you're "lucky" that the second piece of code is working because you did this:
int F_OK;
F_OK is already defined in unistd.h, where access() is defined. So by doing this you're redeclaring it and not giving it a value, causing undefined behavior. Get rid of this definition, and #include <unistd.h>, and the call to access() is guaranteed to work as expected.
How do I read in an external file and then either print the whole text or selected lines?
FILE *fp;
fp=fopen("c:\\students.txt", "r");
I understand that reads the file but after that I am lost. Help please!!!
Do I need to read in binary or is text file acceptable?
You get a pointer to the file stream with fopen()
fread() will only return the amount of actual data that the program
could find inside your .txt file - It's very misleading. The main use is getting the number of elements for your loops. You can upload a file into your program, and print it on the screen without ever touching this function, if you know exactly what the file should already have. Only use this if you don't know what's in your file.
getline() is your go-to for printing out a specific line. No way around this one, and you'll need the specific library for it.
Here's an Example Code I wrote while doing a self-study on this, just showing how each of these are used, and printing out on BOTH the program, and a separate txt file outside the program. It doesn't have getline() however.
/*
Goals:
Create an array of 5 values
Input 5 vales from a pre-created file, into the new array
Print out the 5 values into another file.
Close the file.
*/
#include <stdio.h>
#include <stdlib.h>
#define DATAFILE "E:/Data.txt"
#define REPORT "E:/Report.txt"
//prototypes
FILE *Open_File();
void Consolodate_Array(int a_array[], FILE *file_pointer);
void Print_File(int a_array[], FILE *report_pointer);
void end_function(FILE *file_pointer, FILE *report_pointer);
int main(int argc, char *argv[])
{
int array[5];
FILE *Datatext = Open_File();
//Declared "Datatext" to be equal to Open_File's Return value.
//FILE itself is like Int, Double, Float, ect.
FILE *ReportText = fopen(REPORT, "w");
//Did the same as above, just not in a separate function. This gives us a
//Pointer to the REPORT.txt file, in write mode instead of read mode.
Consolodate_Array(array, Datatext);
Print_File(array, ReportText);
end_function(Datatext, ReportText);
system("PAUSE");
return 0;
}
/*----------------------------------------------------------------------*/
//This function should open the file and pass a pointer
FILE *Open_File()
{
return fopen(DATAFILE, "rb");
}
/*----------------------------------------------------------------------*/
//This function should input the variables gotten for the file, into the array
void Consolodate_Array(int a_array[], FILE *file_pointer)
{
for(int i=0; i<5; i++)
fscanf(file_pointer, "%i", &a_array[i]);
}
/*----------------------------------------------------------------------*/
//This function prints out the values into the second file, & at us too.
void Print_File(int a_array[], FILE *report_pointer)
{
for(int i=0; i<5; i++)
{
printf("%i\n", a_array[i]);
fprintf(report_pointer, "%i\n", a_array[i]);
}
}
/*----------------------------------------------------------------------*/
//This function closes the file.
void end_function(FILE *file_pointer, FILE *report_pointer)
{
fclose(file_pointer);
fclose(report_pointer);
//closes both files we worked on.
}
I'm trying to make a program to open a file, called "write.txt".
#include <stdio.h>
main() {
FILE *fp;
fp = fopen("write.txt", "w");
return 0;
}
Should this work? Because it returns nothing.
Other than an old variant of main, there's not really much wrong with that code. It should, barring errors, create the file.
However, since you're not checking the return value from fopen, you may get an error of some sort and not know about it.
I'd start with:
#include <stdio.h>
#include <errno.h>
int main (void) {
FILE *fp;
fp = fopen ("write.txt","w");
if (fp == NULL) {
printf ("File not created okay, errno = %d\n", errno);
return 1;
}
//fprintf (fp, "Hello, there.\n"); // if you want something in the file.
fclose (fp);
printf ("File created okay\n");
return 0;
}
If you're adamant that the file isn't being created but the above code says it is, then you may be a victim of the dreaded "IDE is working in a different directory from what you think" syndrome :-)
Some IDEs (such as Visual Studio) will actually run your code while they're in a directory like <solution-name>\bin or <solution-name>\debug. You can find out by putting:
system ("cd"); // for Windows
system ("pwd") // for UNIXy systems
in to your code to see where it's running. That's where a file will be created if you specify a relative path line "write.txt". Otherwise, you can specify an absolute path to ensure it tries to create it at a specific point in the file system.
What did you expect it to 'return' - it opens a file, on most platforms creating one if it doesn't exist.
You should probably fclose(fp) the file at the end.
I think you want to print the contents of file write.txt. (Assume it contains characters).
#include <stdio.h>
int main()
{
FILE *fp,char ch;
fp=fopen("write.txt","r");
if(fp==NULL)
{
printf("Some problem in opening the file");
exit(0);
}
else
{
while((ch=fgetc(fp))!=EOF)
{
printf("%c",ch);
}
}
fclose(fp);
return 0;
}
I think you should study some more fundamentals in C before you start attempting to work with files. A return means some data is passed back to the calling code from the called function.In this case you return 0 at the end of your program. You did not do anything with your FILE pointer except cause a new file to be created...