I'm trying to "mock" some things in my unit testing of a C project.
I am using the Check framework for testing and I have a function that reads from a file on disk to verify the contents.
My function is:
#include "verifier.h"
#include <stdio.h>
int verify_content(char *path, char *verify_string) {
File *fptr
fptr = fopen(path, "r")
// Do verification
return 0
and my test is
START_TEST (verify_content_test)
{
char *test_path = "test_path";
char *test_string = "unique_string_content_here";
ck_assert_str_eq(verify_content(test_path, test_string), 0);
}
END_TEST
However, I don't want this to read from disk, because that would be slow, and I'd have to have multiple static files just for testing against.
Is there a way to "mock"/"fake" the fopen?
I'm still new to C development and super new to unit testing in C so if I should approach this problem differently, please point me in the right direction.
You can write your own fopen() and put anything you like into it. Link this module with all other modules that need the mocked version.
The function will only be linked from the standard library if there are unresolved references. Providing your own implementation resolves all references and so the standard version will not be used.
With GCC you also have another alternative: use the linker's --wrap option. For example --wrap=fopen will change all references of fopen() into __wrap_fopen() and change the defined symbols of fopen() into __real_fopen(). This way you can "intercept" the call and massage it to you liking:
FILE* __wrap_fopen(const char* filename, const char* mode) {
/* Do anthing you want, including changing arguments or not calling __real_fopen() at all. */
FILE* result = __real_fopen(filename, mode);
/* Do anthing you want, including changing the result. */
return result;
}
Related
just installed eclipse on my linux and trying working with files.
I wanted to use fgetc function but it seems that its not working..
while debugging: even if Im using step over its crush, and while letting it run its just dont do anything.
its happen also for every function related to files like fscanf,fgets etc..
the error messege is:
Can't find a source file at "/build/glibc-OTsEL5/glibc-2.27/libio/getc.c"
Locate the file or edit the source lookup path to include its location.
any ideas?
thnk's in advanced
and this is my code:
#include <stdio.h>
#include <stdlib.h>
int main(){
func();
return 0;
}
void func(){
int ch;
int fd = open("out.txt", O_RDONLY);
if(fd < 0)
perror("fd");
ch = fgetc(fd);
printf("%d",ch);
}
The error message comes from the debugger. It indicates that whoever built glibc for your system did not add source files to the debugging information. As a result, stepping through system library functions such as fgetc is very confusing. But this is independent of your actual problem.
You cannot mix file descriptor functions like open with file stream functions like fgetc. The compiler will have print a type mismatch warning; you really should not ignore these.
Something like this should fix the type error:
File *fp = fopen("out.txt", "r");
if (fp == NULL) {
perror("fopen");
return 1;
}
ch = fgetc(fp);
If you want to keep using unbuffered I/O and open, you will have to use the read function instead of fgetc to read bytes.
This question already has answers here:
Using a variable file name in C to read from multiple files with similar names?
(2 answers)
Closed 7 years ago.
Using Visual Studio 2015 how would i open and read all the file in a directory.
The Input Parameters for the program are
Number of Sensors (N): Determines the number of input files
File Location: A local directory/folder where the files are located. Each file will be named: sensor_0.txt, sensor_1.txt, ... sensor_(n - 1).txt
I can open and read individual files in the directory by hard coding them using fopen, but since the number of input files is not constant I don't know how I would read all of the files in the directory regardless of how many input files there are.
I was thinking that i would need to create the file names since the only thing changing in the file names is the sensor number but that doesn't seem to work since fopen requires a const char * file name.
I have searched for solutions and i found a DIR variable type in dirent.h header file, but that doesn't work with the the Visual Studio Compiler and a package needs to be installed in order to use that header file.
I am in an intro to programming class so i feel like installing outside programs would be the wrong approach to solving this issue, but I could be wrong. I have also looked into functions like FindFirstFile, and FindNextFile but those also seem too advanced for me.
Any help would be really would be appreciated. Thank you in advance.
If you're writing a Windows-specific application (rather than something that needs to be portable to other operating systems) then look into the FindFirstFile, FindNextFile, and FindClose APIs.
Here's a sample of how to use these APIs (based somewhat on the samples from the above links):
#include <windows.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
if (argc != 2) {
printf("Usage: %s [target_file]\n", argv[0]);
return 1;
}
printf("Target file is %s\n", argv[1]);
hFind = FindFirstFile(argv[1], &FindFileData);
if (hFind == INVALID_HANDLE_VALUE) {
printf("FindFirstFile failed, error %d\n", GetLastError());
return 1;
}
do {
printf("File name = %s\n", FileFindData.cFileName);
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
return 0;
}
Disclaimer: I haven't had a Windows dev environment years, so I have no way to compile & verify this sample. It should get you pointed in the right direction, though.
You can just do it by hardcoding the base name and iterating with an index to generate the specific name, something like this
for (size_t i = 0 ; ; ++i)
{
char filepath[MAX_PATH];
FILE *file;
// In principle, you should check the return value to ensure
// it didn't truncate the name
snprintf(filepath, sizeof(filepath), "sensor_%d.txt", i);
// Try to open the file, if it fails it's probably because
// the file did not exist, but it's not the only possible
// reason.
file = fopen(filepath, "r"); // Or "rb", depends ...
if ((done = (file == NULL)) != 0)
break; // Cannot open this, probably there are no more files.
// Process the file here
}
A better way would be to pass the name to another function, so you can later change the name generation method by looking at the directory instead of assuming it.
NOTE 1: Secure c Runtime, in MSVC compiler will probably complain about fopen() and snprintf() since snprintf() uses the POSIX name style or something like that (perhaps using the safe version snprintf_s()) I don't remember. But this is standard c (as per C11) so it should compile with any c compiler.
NOTE 2: You should also, use the full path unless the files are in the CWD. Something like (assuming the files are in drive "C:")
snprintf(filepath, sizeof(filepath), "C:\\full\\path\\sensor_%d.txt", i);
Background
I am developing a module using the PAM specification and I would like to test one of the pam functions (specifically pam_sm_authenticate) to make sure that the helper functions that I have implement play nice with the specification.
The pam_sm_[authenticate, acct_mgmt...etc.] series functions all take the same parameters.
int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
I am having trouble mocking struct pam_handle, but need to as this structure will contain information vital to authenticating users.
Using PAM header information from the internet (pam_appl.h and pam_private.h) I have attempted to use the structure directly as pam_handle_t normalPamh; and populate it myself, but when I try to I get the following error:
error: aggregate 'pam_handle_t normalPamh' has incomplete type and cannot be defined
I would really like to test my module to make sure that I haven't done anything that will cause segmentation faults and that I'm using memory within reasonable limits, but I am having trouble doing so because I can't mock this structure.
Question
How do I mock the pam_handle_t struct?
It sounds like, the headers you're referring to declare the pam-handle type along the lines of:
typedef struct pam_handle pam_handle_t;
However the actual definition of the struct pam_handle is NOT part of the headers you describe. To mock it, you would need to specify the actual structure before writing any code that code accessing the struct pam_handle members (whatever they are). I.E:
In your interface definitions, you "post-pone" the structure definition, by using handle only:
int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv);
In your test code, where you modify handle-members for testing purposes, you have to define it, e.g.
#include "interface_to_be_tested.h"
// declare the pam_handle
struct pam_handle
{
// provide definition of struct-members here
};
...
// Test code here
Update: The structure seems to be defined in libpam/pam_private.h, so including that file in your test-code ought to be sufficient. Note the header is "private", so your actual implementation should of course NOT use this.
Hope that helps!
I found some open source software that does exactly what I need it to.
It's called pamtester and it compiles on a number of *nix systems.
Once it's installed you can run it like:
pamtester -v -I user=test01#test.com -I rhost=192.168.2.150 dovecot test01#test.com "authenticate(PAM_ESTABLISH_CRED)"
It will take care of everything else that is needed to establish user credentials.
I wanted to use it in automated testing through C, so I wrapped a lot of the calls in a bash script where I could specify input I wanted to change like user and ruser.
The problem is passwords need to be entered when the program asks for it. I solved this using popen in my C source.
Here is an example of what I did for reference. It's not perfect, but for anyone else that might run into a similar situation this might serve as a starting point.
int testPamSmAuthenticate(char * username, char * hostname, char * password) {
//--------------------------------------
// declarations
//--------------------------------------
char testCommand[512];
char passwordPromptResponse[128];
char resultLine[3];
FILE * testFile;
//--------------------------------------
// declarations
//--------------------------------------
sprintf(testCommand, "%s %s %s", PAM_TEST_SCRIPT_PATH, username, hostname);
sprintf(passwordPromptResponse, "%s\n", password);
//--------------------------------------
// run the command and enter a password
//--------------------------------------
if (!(testFile = popen(testCommand, "w"))){
return(1);
}
fputs(passwordPromptResponse, testFile);
pclose(testFile);
//--------------------------------------
// get the output of the command from
// the text file written by bash
//--------------------------------------
testFile = fopen(PAM_TEST_RESULT_PATH, "r");
while (fgets(resultLine, sizeof(resultLine), testFile)) {
printf("%s", resultLine);
}
fclose(testFile);
//--------------------------------------
// evaulate and return a code
// 1 == authentication good
// 0 == authentication bad
//--------------------------------------
if (strchr(resultLine, '0')) {
printf("Authentication successful!\n");
return(1);
}
printf("Authentication failed!\n");
return(0);
}
More information about the use of this program is available by downloading the source and reading it's README file.
I want to move the contents of one directory to another. I specify the source and destination directories via command line arguments. Here's the code:
#include <stdlib.h>
#include <stdio.h>
void move_dir(FILE *src, FILE *dest) {
int c = getc(src);
while(getc(src)!=EOF) {
putc(c,dest);
}
}
int main(int argc, char* argv[])
{
FILE *src=fopen(argv[1]);
FILE *dest=fopen(argv[2]);
while(--argc>0) {
if(src!=NULL && dest!=NULL) {
move_dir(src,dest);
}
}
fclose(src);
fclose(dest);
return 0;
}
For example:
./a.out /Folder1/Folder2/Source /Folder1
This will move the folder called Source inside of Folder1. However when I execute this code it doesn't work. It compiles just fine with g++ and no errors when running but it just doesn't move anything at all. Any ideas on what could be wrong?
Edit: This is referring to the original post, which read FILE * src = opendir( argv[1] );.
The function opendir() returns a DIR *, which is quite different from a FILE * (and cannot be used as a parameter to getc() / putc().
You have to read directory entries from that DIR * using readdir(), which will yield a filename, then copying that file using that information.
Edit: This is referring to the updated post.
You don't use file functions (fopen(), getc() etc.) on directories. The way to go is opendir() followed by readdir(), then acting on the yielded filenames.
I don't really know why fopen() on a directory actually returns a non-null pointer. Personally, I consider this a design flaw, as the operations possible on FILE * are not defined for directories. I would stay well clear of this construct.
Generally speaking, you should read the documentation (man page) of the functions you are using, not (wrongly) assuming things about them. And while you are at it, check return values, too - they might tell you why things don't work as expected.
If I wanted to run a shell command in linux with a c program, I would use
system("ls");
Is there a way I can accomplish this in Wind River vxworks?
I found the below example but I'm wondering do I need to include vxworks header files for this to work? I assume I do, but how do I figure out which one?
Example:
// This function runs a shell command and captures the output to the
// specified file
//
extern int consoleFd;
typedef unsigned int (*UINTFUNCPTR) ();
extern "C" int shellToFile(char * shellCmd, char * outputFile)
{
int rtn;
int STDFd;
int outFileFd;
outFileFd = creat( outputFile, O_RDWR);
printf("creat returned %x as a file desc\n",outFileFd);
if (outFileFd != -1)
{
STDFd=ioGlobalStdGet(STD_OUT);
ioGlobalStdSet(STD_OUT,outFileFd);
rtn=execute(shellCmd);
if (rtn !=0)
printf("execute returned %d \n",outFileFd);
ioGlobalStdSet(STD_OUT,STDFd);
}
close(outFileFd);
return (rtn);
}
I found the code segment below worked for me. For some reason changing the globalStdOut didn't work. Also the execute function did not work for me. But my setting the specific task out to my file, I was able to obtain the data I needed.
/* This function directs the output from the devs command into a new file*/
int devsToFile(const char * outputFile)
{
int stdTaskFd;
int outputFileFd;
outputFileFd = creat( outputFile, O_RDWR);
if (outputFileFd != ERROR)
{
stdTaskFd = ioTaskStdGet(0,1);
ioTaskStdSet(0,1,outputFileFd);
devs();
ioTaskStdSet(0,1,stdTaskFd);
close(outputFileFd);
return (OK);
}
else
return (ERROR);
}
If this is a target/kernel shell (i.e. running on the target itself), then remember that all the shell commands are simply translated to function calls.
Thus "ls" really is a call to ls(), which I believe is declared in dirLib.h
I think that the ExecCmd function is what you are looking for.
http://www.dholloway.com/vxworks/6.5/man/cat2/ExecCmd.shtml
As ever, read the documentation. ioLib.h is required for most of the functions used in that example, and stdio.h of course for printf().
As to the general question of whether you need to include any particular headers for any code to compile, you do need to declare all symbols used, and generally that means including appropriate headers. The compiler will soon tell you about any undefined symbols, either by warning or error (in C89/90 undefined functions are not an error, just a bad idea).