I am writing a unit test for embedded C codes using google test/mock. The C function code looks like this.
int readGPIOSysfs(int ioport){
...
FILE *f = fopen("/sys/class/gpio/export", "w");
..
fclose(f);
}
How can I implement a google mock on fopen function call?
Thank you in advance.
I do it using CppuTest instead of Gtest :
//io.c -> imlementation
#include "drivers/io.h"
#include <string.h>
#include <stdio.h>
bool read_io()
{
FILE *fp_driver = fopen("/dev/io/my_device", "rw");
char msg[255] = {0};
if (fp_driver == NULL)
return false;
fread(msg, sizeof(char), 255, fp_driver);
if (strcmp(msg, "This is a test"))
return false;
return true;
}
//io.cpp -> Tests functions
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"
#include <stdio.h>
#include <string.h>
extern "C"
{
#include "drivers/io.h"
}
TEST_GROUP(IO)
{
void setup() {
}
void teardown() {
mock().clear();
}
};
// Mocking function
FILE *fopen (const char *__restrict __filename, const char *__restrict __modes)
{
void * r = mock().actualCall(__func__).returnPointerValue();
return (FILE *)r;
}
TEST(IO, simpleTest)
{
/* Create a temp file with a test string inside to match with
implementation function expectation */
FILE * tmp_log_file = tmpfile();
char str[] = "This is a test";
fwrite(str, sizeof(char), strlen(str), tmp_log_file);
rewind(tmp_log_file);
/* Return or temp file pointer for the next call of fopen */
mock().expectOneCall("fopen").andReturnValue(tmp_log_file);
bool r = read_io();
CHECK_TRUE(r);
mock().checkExpectations();
}
int main(int ac, char** av)
{
return CommandLineTestRunner::RunAllTests(ac, av);
}
Related
I'm trying to create the module on C for python, but I got some troubles with it:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
FILE *fp = fopen("write.txt", "w");
fputs("Real Python!", fp);
fclose(fp);
return 1;
}
static PyObject *method_fputs(PyObject *self, PyObject *args) {
char *str, *filename = NULL;
int bytes_copied = -1;
/* Parse arguments */
if(!PyArg_ParseTuple(args, "ss", &str, &filename))
return NULL;
FILE *fp = fopen(filename, "w");
bytes_copied = fputs(str, fp);
fclose(fp);
return PyLong_FromLong(bytes_copied);
}
static PyMethodDef FputsMethods[] = {
{"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef fputsmodule = {
PyModuleDef_HEAD_INIT,
"fputs",
"Python interface for the fputs C library function",
-1,
FputsMethods
};
I use this code, and I got such mistakes when I try to build it
undefined reference to `__imp__PyArg_ParseTuple_SizeT'
undefined reference to `__imp_PyLong_FromLong'
error: ld returned 1 exit status
What's wrong with it?
Outside of using a hash function, I'd like to write a basic mapping of a key/value lookup of a few movie-credits related items. Does the following macro seem like an acceptable way to do it?
#include <stdio.h>
#include <string.h>
#define TOMAP(input_str, output_buf, from, to) \
if (strcmp(input_str, from) == 0) \
strcpy(output_buf, to)
void map_imdb_position(const char* pos, char output[])
{
TOMAP(pos, output, "Director", "director");
TOMAP(pos, output, "Writer", "scribe");
}
int main(void) {
char position[20];
map_imdb_position("Director", position);
printf("Director->%s\n", position);
}
If not, what might be a better approach to doing a sort of switch statement on a string comparison?
As suggested in the comments a cleaner way to do this would be with a map of credits in a function, for example:
#include <stdio.h>
#include <string.h>
typedef struct map {
char from[20];
char to[20];
} Map;
void map_imdb_position(const char* credit, char output[])
{
static Map credits[] = {
{"Director", "director"},
{"Writer", "scribe"}
};
for (int i=0; i < sizeof(credits)/sizeof(*credits); i++) {
if (strcmp(credit,credits[i].from) == 0) {
strcpy(output, credits[i].to);
break;
}
}
printf("%s --> %s\n", credit, output);
}
int main(void) {
char position[20];
map_imdb_position("Director", position);
map_imdb_position("Writer", position);
}
Working example: https://onlinegdb.com/Sk_t76aQ_
Side note: I was working on this solution but Carl already came up with a similar one.
But, I prefer to use the ptr->field syntax and to have an end-of-table sentinel at the end (vs. the sizeof construct to get the count).
And, I think designated initializers when constructing the table make things more readable [especially if more fields need to be added to the struct].
So, here's my version:
#include <stdio.h>
#include <string.h>
typedef struct {
const char *from;
const char *to;
} mapimdb_t;
mapimdb_t mapimdb[] = {
{ .from = "Director", .to = "director" },
{ .from = "Writer", .to = "scribe" },
// ...
{ .from = NULL }
};
void
map_imdb_position(const char *pos, char *output)
{
for (const mapimdb_t *map = mapimdb; map->from != NULL; ++map) {
if (strcmp(pos,map->from) == 0) {
strcpy(output,map->to);
break;
}
}
}
void
dotest(const char *from,char *out)
{
map_imdb_position(from,out);
printf("dotest: %s->%s\n",from,out);
}
int
main(void)
{
char position[20];
dotest("Director", position);
dotest("Writer", position);
}
X macros can be used:
#include <stdio.h>
#include <string.h>
#define STR_LIST \
X("Director", "director") \
X("Writer", "scribe")
void map_imdb_position(const char* pos, char output[])
{
#define X(from, to) \
if (strcmp(pos, from) == 0) \
{ strcpy(output, to); return; } // "return" was missing?
STR_LIST
#undef X
}
int main(void) {
char position[20];
map_imdb_position("Director", position);
printf("Director->%s\n", position);
}
I have a header file containing:
extern char *finalLoggerPath;
I am trying to implement a function that can initialize or modify the finalLoggerPath variable.
My main function indirectly calls a function defined in a second file. This second function generates a path which does not yet exist, and saves it in two file-scope variables, finalPath and finalLoggerPath. After that is done, I would like another function defined in a third file to be able to print the finalLoggerPath.
I have attempted to implement this, but I get an error:
Memory access error (memory dump used)
How can I fix my program?
My code:
// First File
void initLog() {
generateFileNameWithDate();
}
int main(void) {
initLog();
}
// Second File
#define PATHTEST "../TestLogSystem/"
#include "Info.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
char pathToFile[100] = "../TestLogSystem/";
char *actual;
char *finalPath;
char *finalLoggerPath;
int generateFileNameWithDate() {
int counter = 1;
char filename[999];
char filenameBuffer[999];
int notCreatetFile = 1;
char counterS[999];
time_t now = time(NULL);
if (now == -1) {
puts("The time() function failed");
return 1;
}
struct tm *ptm = localtime(&now);
if (ptm == NULL) {
puts("The localtime() function failed");
return 1;
}
strftime(filename, sizeof(filename),
strcat(strcat(pathToFile, "%Y%m%d"), ".json"), ptm);
while (notCreatetFile) {
if (access(filename, F_OK) != -1) {
// file exists
memset(filename, 0, sizeof(filename));
memset(pathToFile, 0, sizeof(pathToFile));
sprintf(pathToFile, "%s", PATHTEST);
memset(filenameBuffer, 0, sizeof(filenameBuffer));
sprintf(counterS, "%d", counter);
strftime(filename, sizeof(filename),
strcat(
strcat(
strcat(
strcat(strcat(pathToFile, filenameBuffer),
"%Y%m%d"), "-Test-"),
counterS), ".json"), ptm);
} else {
// file doesn't exist
finalPath = malloc(strlen(filename) + 1);
printf("finalPath: %s \n", finalPath);
strcpy(finalPath, filename);
strcpy(finalLoggerPath, finalPath);
fopen(finalPath, "w");
notCreatetFile = 0;
}
++counter;
}
return 0;
}
// Third File
#include "Info.h"
void print() {
printf("FinalLoggerPath: %s", finalLoggerPath);
}
I compile it:
gcc CallFileExists.c FileExists.c GetVariableFromFileExists.c
I have three binary files: cipher01.bin, cipher02.bin and cipher03.bin.
Additionally I have a sign.bin and a pubkey.pem file. The task is to hash all three ciphers and compare it to the signature. Therefore I used RSA to decrypt the sign.bin with the public key from pubkey.pem.
The result looks good but none of the cipher-hashes belongs to the signature. But I know, that there is at least one cipher which belongs to the signature because it is a task from our university. Maybe I forgot something but I can't figure out what.
Here is my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/** converts unsigned character to readble string*/
char *pt(unsigned char *md) {
int i;
char *buf = (char*)malloc(sizeof(char)*80);
for(int i = 0; i < SHA_DIGEST_LENGTH;i++) {
sprintf(&(buf[i*2]),"%02x",md[i]);
}
return (buf);
}
/** returns error */
void err_exit(void) {
printf("%s\n",ERR_error_string(ERR_get_error(),NULL));
ERR_free_strings();
exit(EXIT_FAILURE);
}
/** reads a file */
char * readFile(char * filename,long int * filesize) {
FILE *fin;
char *buf;
if((fin=fopen(filename,"r"))==NULL) {
printf("Error opening %s.\n",filename);
exit(EXIT_FAILURE);
}
fseek(fin,0L,SEEK_END);
*filesize = ftell(fin);
rewind(fin);
if(!(buf=malloc(*filesize))) {
printf("Memory exhausted. Stop.\n");
exit(EXIT_FAILURE);
}
fread(buf,*filesize,1,fin);
fclose(fin);
return buf;
}
/** hash a file with sha1 */
char * hashBinaryFile(char * filename) {
long int filesize = 0;
EVP_MD_CTX c;
unsigned char md[SHA_DIGEST_LENGTH];
ERR_load_crypto_strings();
EVP_MD_CTX_init(&c);
/** reads files into buf */
char * buf = readFile(filename,&filesize);
if((EVP_DigestInit(&c,EVP_sha1()))==0) {
err_exit();
}
if((EVP_DigestUpdate(&c,buf,filesize))==0) {
err_exit();
}
if((EVP_DigestFinal(&c,md,NULL))==0) {
err_exit();
}
//printf("%s\n",pt(md));
EVP_MD_CTX_cleanup(&c);
free(buf);
ERR_free_strings();
return pt(md);
}
int padding = RSA_PKCS1_PADDING;
/** loads public key and creates rsa */
RSA * createRSAWithFilename(char * filename,int public) {
FILE * fp = fopen(filename,"rb");
if(fp == NULL) {
printf("Unable to open file %s \n",filename);
return NULL;
}
RSA *rsa= RSA_new() ;
if(public) {
rsa = PEM_read_RSA_PUBKEY(fp, &rsa,NULL, NULL);
} else {
rsa = PEM_read_RSAPrivateKey(fp, &rsa,NULL, NULL);
}
return rsa;
}
/** decrypt signature */
char * public_decrypt(unsigned char * enc_data,int data_len, unsigned char *decrypted) {
RSA * rsa = createRSAWithFilename("archieve/pubkey.pem",1);
int result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
return pt(decrypted);
}
int main(int argc,char *argv[]) {
/** decrypt signature */
long int encrypted_length;
long int decrypted_length;
unsigned char decrypted[4098]={};
char * encrypted = readFile("archieve/s72897-sig.bin",&encrypted_length);
char * sign = public_decrypt(encrypted,encrypted_length, decrypted);
char * cipher01 = hashBinaryFile("archieve/s72897-cipher01.bin");
char * cipher02 = hashBinaryFile("archieve/s72897-cipher02.bin");
char * cipher03 = hashBinaryFile("archieve/s72897-cipher03.bin");
if(strcmp(sign,cipher01)==0) {
printf("cipher01\n");
} else if(strcmp(sign,cipher02)==0) {
printf("cipher02\n");
} else if(strcmp(sign,cipher03)==0) {
printf("cipher03\n");
} else {
printf("No cipher matches the signature\n");
}
return 0;
}
Thanks for any kind of help.
Edit: fixed some code
Edit2: link to the *.zip https://ufile.io/tqwoh
You transform your files in human readable format twice:
char * public_decrypt(...)
{
return pt(decrypted);
// ^
}
int main(int argc,char *argv[])
{
char * sign = pt(public_decrypt(encrypted,encrypted_length, decrypted));
// ^
Additionally, you actually have some memory leaks: You do not free the rsa instance in public_decrypt neither do you free the strings returned (encrypted, sign, cypher0x)...
Further recommendation in for pt:
char *buf = (char*)malloc(sizeof(char) * 2 * SHA_DIGEST_LENGTH);
If you have an appropriate constant already, use it... sizeof(char) always is 1 by definition, so you could drop it...
I am new in C. I want to create a file in linux C program and write environment variables in it. If file already exist I want to open and append. I have written the following code.
char *envFile=getenv("FILENAME");
int fdEnv=-1;
fdEnv=open(envFile,O_CREAT,O_RDWR,O_APPEND);
printf("%d",fdEnv);
char** env;
if(fdEnv>0)
{
for (env = environ; *env != 0; env++)
{
char *thisEnv = *env;
printf("%s",thisEnv);
write(fdEnv,thisEnv,strlen(thisEnv));
}
close(fdEnv);
}
But when I run it first time. A blank file is created. And it stays locked after execution. Looks like some error. Second time it fdEnv stays less than 0.
I really don't understand what is happening here. Please help.
Try using | to separate the flags.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
extern char **environ;
int main(void)
{
char *envFile = getenv("FILENAME");
int fdEnv = -1;
fdEnv = open(envFile, O_CREAT|O_RDWR|O_APPEND, 0644);
printf("%d\n", fdEnv);
int i = 0;
while (environ[i]) {
printf("%s\n", environ[i]);
write(fdEnv, environ[i], strlen(environ[i]));
char lf = '\n';
write(fdEnv, &lf, 1);
i++;
}
close(fdEnv);
return 0;
}
I've run above code on my linux computer and it works.
extern char **environ;
int main()
{
char **env;
char* filename = getenv("FILENAME")
const char* mode = "a";
FILE* file = fopen( filename, mode );
for ( env = environ; *env; ++env )
fprintf( file, "%s\n", *env );
fclose(file);
return(0);
}
You should think about handling when getenv fails, is blank, etc; let me know if you have any questions.