#ifndef pthread_mocked#define pthread_mocked
//thr.c
//Direct implementation where I want to mock pthread_create.
#define TESTING 1#ifndef TESTING#include <pthread.h>#else#include "tests/pthread_mock.h"#endiflong th_start_thread_name(TH_THREAD_FUNC thread, void *arg, th_opts *opts, const char* name){ pthread_t thr; int ret, sret; ret = pthread_create(opts ? &opts->thr : &thr, NULL, thread, arg); if (ret == 0 && name != NULL) { extern int pthread_setname_np(pthread_t thr, const char *name); /* Fix warning from missing prototype. */ sret = pthread_setname_np(opts ? opts->thr : thr, name); /* pthreads says that thread names must not exceed 16, including NULL. */ if (sret != 0 && strlen(name) > 15) { ret = -1; } } return (long)ret;}
//thr_test.c
//CppUTest file
#include <CppUTest/CommandLineTestRunner.h>#include <CppUTest/TestHarness.h>#include <CppUTestExt/MockSupport.h>#include <stdio.h>
extern "C"{ #include "../thr.h"
}
static void *TestThread(void *arg);
/** * The definition of a TEST_GROUP */TEST_GROUP(ThreadTestGroup){
};
TEST(ThreadTestGroup, ThreadCreateFail)
{ // mock().expectOneCall("pthread_create").withParameter("thread", NULL) // .withParameter("arg", this) // .withParameter("opts", NULL) // .withParameter("name", "TestThread") // .andReturnValue(-1);
int4 thread_status = mock().actualCall("th_start_thread_name").returnValue().getIntValue();
CHECK_EQUAL(-1, thread_status);}
int main(int argc, char *argv[]){ CommandLineTestRunner::RunAllTests(argc, argv); return 0;}
// Attempt at creating a pthread_mock.h
#ifndef pthread_mocked#define pthread_mocked
#include <CppUTestExt/MockSupport.h>
/** * Mocked version of pthread_create */int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg){ return mock().actualCall("pthread_create").intReturnValue();}
#endif
--
You received this message because you are subscribed to the Google Groups "cpputest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cpputest+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hello Travis
I wrote most this before Bas weighed in. So I suggest you take Bas's advice and swap via function pointer or proceed with a linker fake but be on the look out for what Bas saw when he tried it.
--- Now for the problem with the code you posted --
I see several problems. For starters, it's best not to use conditional compilation and ask the question #ifdef TESTING in any production code. Additionally, you don't need to do it in this case. You should be trying to create a link time substitute instead.
You might want to start with my starter kit, get a simpler working example then work your way to pthread_mock. https://github.com/jwgrenning/cpputest-starter-project. Sometimes you have to tweak the build, depending on your setup.
I'm sitting in a airport and thought you might like a working mock of pthread_create, so here it is. From this example, you can probably mock the other pthread functions.
Usually I put all my mocks into CPP files; given that pthread.h is probably C++ aware (with #ifdef __cplusplus) it is likely to give you problems in a C file.
//pthread_mock.cpp -- link time fake
#include <pthread.h>
#include "CppUTestExt/MockSupport.h"
int pthread_create(pthread_t * __restrict pthread, const pthread_attr_t * __restrict attr,
void *(*entry)(void *), void * __restrict parameter)
{
return mock("pthread").actualCall("create")
.withParameter("pthread", pthread)
.withParameter("attr", attr)
.withParameter("entry", entry)
.withParameter("parameter", parameter)
.returnValue().getIntValue();
}
The pthread_create
signature is from my mac's pthread.h file.
Notice the actualCall()
is in the stub function not in the test case.
Here is the associated test case that calls the link-time stub of pthread_create. Not is uses expectOneCall()
to describe the expectation.
#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"
#include <pthread.h>
TEST_GROUP(pthread_mock)
{
void setup()
{
}
void teardown()
{
mock("pthread").checkExpectations();
mock().clear();
}
};
void * entry(void*)
{
return 0;
}
TEST(pthread_mock, create)
{
pthread_t pthread;
pthread_attr_t attr;
int resultYourThreadFillsIn;
mock("pthread").expectOneCall("create")
.withParameter("pthread", (void*)&pthread)
.withParameter("attr", (void*)&attr)
.withParameter("entry", (void*)&entry)
.withParameter("parameter", (void*)&resultYourThreadFillsIn)
.andReturnValue(0);
//Your production code will be making calls to pthread_create() and not know it is being mocked
int result = pthread_create(&pthread, &attr, &entry, &resultYourThreadFillsIn);
LONGS_EQUAL(0, result);
}
Hope that helps.
If you use Bas' function pointer approach, you'll need to rename pthread_create
linker stub to something like pthread_create_mock
James
James Grenning - Author of TDD for Embedded C - wingman-sw.com/tddec
wingman-sw.com
wingman-sw.com/blog
twitter.com/jwgrenning
facebook.com/wingman.sw