• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cpputest / cpputest / 10776895588

09 Sep 2024 04:02PM UTC coverage: 99.279%. First build
10776895588

Pull #1810

github

web-flow
Revert "Encode newlines for -ojunit as their XML equivalent instead of {newline}"
Pull Request #1810: Revert "Encode newlines for -ojunit as their XML equivalent instead of {newline}"

1 of 1 new or added line in 1 file covered. (100.0%)

6748 of 6797 relevant lines covered (99.28%)

18724.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/Platforms/Gcc/UtestPlatform.cpp
1
/*
2
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *     * Redistributions of source code must retain the above copyright
8
 *       notice, this list of conditions and the following disclaimer.
9
 *     * Redistributions in binary form must reproduce the above copyright
10
 *       notice, this list of conditions and the following disclaimer in the
11
 *       documentation and/or other materials provided with the distribution.
12
 *     * Neither the name of the <organization> nor the
13
 *       names of its contributors may be used to endorse or promote products
14
 *       derived from this software without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ''AS IS'' AND ANY
17
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
20
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27

28
#include <stdlib.h>
29
#include "CppUTest/TestHarness.h"
30
#undef malloc
31
#undef free
32
#undef calloc
33
#undef realloc
34
#undef strdup
35
#undef strndup
36

37
#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
38
#include <sys/time.h>
39
#endif
40
#if defined(CPPUTEST_HAVE_FORK) && defined(CPPUTEST_HAVE_WAITPID)
41
#include <unistd.h>
42
#include <sys/wait.h>
43
#include <errno.h>
44
#endif
45

46
#include <time.h>
47
#include <stdio.h>
48
#include <stdarg.h>
49
#include <setjmp.h>
50
#include <string.h>
51
#include <math.h>
52
#include <ctype.h>
53
#include <signal.h>
54

55
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
56
#include <pthread.h>
57
#endif
58

59
#include "CppUTest/PlatformSpecificFunctions.h"
60

61
static jmp_buf test_exit_jmp_buf[10];
62
static int jmp_buf_index = 0;
63

64
// There is a possibility that a compiler provides fork but not waitpid.
65
#if !defined(CPPUTEST_HAVE_FORK) || !defined(CPPUTEST_HAVE_WAITPID)
66

67
static void GccPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin*, TestResult* result)
68
{
69
    result->addFailure(TestFailure(shell, "-p doesn't work on this platform, as it is lacking fork.\b"));
70
}
71

72
static int PlatformSpecificForkImplementation(void)
73
{
74
    return 0;
75
}
76

77
static int PlatformSpecificWaitPidImplementation(int, int*, int)
78
{
79
    return 0;
80
}
81

82
#else
83

84
static void SetTestFailureByStatusCode(UtestShell* shell, TestResult* result, int status)
17✔
85
{
86
    if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
17✔
87
        result->addFailure(TestFailure(shell, "Failed in separate process"));
2✔
88
    } else if (WIFSIGNALED(status)) {
15✔
89
        SimpleString message("Failed in separate process - killed by signal ");
2✔
90
        message += StringFrom(WTERMSIG(status));
2✔
91
        result->addFailure(TestFailure(shell, message));
2✔
92
    } else if (WIFSTOPPED(status)) {
15✔
93
        result->addFailure(TestFailure(shell, "Stopped in separate process - continuing"));
3✔
94
    }
95
}
17✔
96

97
static void GccPlatformSpecificRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
18✔
98
{
99
    const pid_t syscallError = -1;
18✔
100
    pid_t cpid;
101
    pid_t w;
102
    int status = 0;
18✔
103

104
    cpid = PlatformSpecificFork();
18✔
105

106
    if (cpid == syscallError) {
18✔
107
        result->addFailure(TestFailure(shell, "Call to fork() failed"));
1✔
108
        return;
3✔
109
    }
110

111
    if (cpid == 0) {            /* Code executed by child */
17✔
112
        const size_t initialFailureCount = result->getFailureCount(); // LCOV_EXCL_LINE
113
        shell->runOneTestInCurrentProcess(plugin, *result);        // LCOV_EXCL_LINE
114
        _exit(initialFailureCount < result->getFailureCount());    // LCOV_EXCL_LINE
115
    } else {                    /* Code executed by parent */
116
        size_t amountOfRetries = 0;
16✔
117
        do {
118
            w = PlatformSpecificWaitPid(cpid, &status, WUNTRACED);
60✔
119
            if (w == syscallError) {
60✔
120
                // OS X debugger causes EINTR
121
                if (EINTR == errno) {
43✔
122
                  if (amountOfRetries > 30) {
42✔
123
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed with EINTR. Tried 30 times and giving up! Sometimes happens in debugger"));
1✔
124
                    return;
1✔
125
                  }
126
                  amountOfRetries++;
41✔
127
                }
128
                else {
129
                    result->addFailure(TestFailure(shell, "Call to waitpid() failed"));
1✔
130
                    return;
1✔
131
                }
132
            } else {
133
                SetTestFailureByStatusCode(shell, result, status);
17✔
134
                if (WIFSTOPPED(status)) kill(w, SIGCONT);
17✔
135
            }
136
        } while ((w == syscallError) || (!WIFEXITED(status) && !WIFSIGNALED(status)));
58✔
137
    }
138
}
139

140
static pid_t PlatformSpecificForkImplementation(void)
17✔
141
{
142
    return fork();
17✔
143
}
144

145
static pid_t PlatformSpecificWaitPidImplementation(int pid, int* status, int options)
17✔
146
{
147
    return waitpid(pid, status, options);
17✔
148
}
149

150
#endif
151

152
TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
322✔
153
{
154
    return TestOutput::eclipse;
322✔
155
}
156

157
void (*PlatformSpecificRunTestInASeperateProcess)(UtestShell* shell, TestPlugin* plugin, TestResult* result) =
158
        GccPlatformSpecificRunTestInASeperateProcess;
159
int (*PlatformSpecificFork)(void) = PlatformSpecificForkImplementation;
160
int (*PlatformSpecificWaitPid)(int, int*, int) = PlatformSpecificWaitPidImplementation;
161

162
extern "C" {
163

164
static int PlatformSpecificSetJmpImplementation(void (*function) (void* data), void* data)
6,314✔
165
{
166
    if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
6,314✔
167
        jmp_buf_index++;
6,314✔
168
        function(data);
6,314✔
169
        jmp_buf_index--;
6,151✔
170
        return 1;
6,151✔
171
    }
172
    return 0;
43✔
173
}
174

175
/*
176
 * MacOSX clang 3.0 doesn't seem to recognize longjmp and thus complains about CPPUTEST_NORETURN.
177
 * The later clang compilers complain when it isn't there. So only way is to check the clang compiler here :(
178
 */
179
#ifdef __clang__
180
 #if !((__clang_major__ == 3) && (__clang_minor__ == 0))
181
 CPPUTEST_NORETURN
182
 #endif
183
#endif
184
static void PlatformSpecificLongJmpImplementation()
43✔
185
{
186
    jmp_buf_index--;
43✔
187
    longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
43✔
188
}
189

190
static void PlatformSpecificRestoreJumpBufferImplementation()
114✔
191
{
192
    jmp_buf_index--;
114✔
193
}
114✔
194

195
void (*PlatformSpecificLongJmp)() = PlatformSpecificLongJmpImplementation;
196
int (*PlatformSpecificSetJmp)(void (*)(void*), void*) = PlatformSpecificSetJmpImplementation;
197
void (*PlatformSpecificRestoreJumpBuffer)() = PlatformSpecificRestoreJumpBufferImplementation;
198

199
///////////// Time in millis
200

201
static unsigned long TimeInMillisImplementation()
11,302✔
202
{
203
#ifdef CPPUTEST_HAVE_GETTIMEOFDAY
204
    struct timeval tv;
205
    gettimeofday(&tv, NULL);
11,302✔
206
    return (((unsigned long)tv.tv_sec * 1000) + ((unsigned long)tv.tv_usec / 1000));
11,302✔
207
#else
208
    return 0;
209
#endif
210
}
211

212
static const char* TimeStringImplementation()
1✔
213
{
214
    time_t theTime = time(NULLPTR);
1✔
215
    static char dateTime[80];
216
#ifdef STDC_WANT_SECURE_LIB
217
    static struct tm lastlocaltime;
218
    localtime_s(&lastlocaltime, &theTime);
219
    struct tm *tmp = &lastlocaltime;
220
#else
221
    struct tm *tmp = localtime(&theTime);
1✔
222
#endif
223
    strftime(dateTime, 80, "%Y-%m-%dT%H:%M:%S", tmp);
1✔
224
    return dateTime;
1✔
225
}
226

227
unsigned long (*GetPlatformSpecificTimeInMillis)() = TimeInMillisImplementation;
228
const char* (*GetPlatformSpecificTimeString)() = TimeStringImplementation;
229

230
/* Wish we could add an attribute to the format for discovering mis-use... but the __attribute__(format) seems to not work on va_list */
231
#ifdef __clang__
232
#pragma clang diagnostic ignored "-Wformat-nonliteral"
233
#endif
234

235
#ifdef __clang__
236
#pragma clang diagnostic ignored "-Wused-but-marked-unused"
237
#endif
238
int (*PlatformSpecificVSNprintf)(char *str, size_t size, const char* format, va_list va_args_list) = vsnprintf;
239

240
static PlatformSpecificFile PlatformSpecificFOpenImplementation(const char* filename, const char* flag)
×
241
{
242
#ifdef STDC_WANT_SECURE_LIB
243
  FILE* file;
244
   fopen_s(&file, filename, flag);
245
   return file;
246
#else
247
   return fopen(filename, flag);
×
248
#endif
249
}
250

251
static void PlatformSpecificFPutsImplementation(const char* str, PlatformSpecificFile file)
6,885✔
252
{
253
   fputs(str, (FILE*)file);
6,885✔
254
}
6,885✔
255

256
static void PlatformSpecificFCloseImplementation(PlatformSpecificFile file)
×
257
{
258
   fclose((FILE*)file);
×
259
}
×
260

261
static void PlatformSpecificFlushImplementation()
6,951✔
262
{
263
  fflush(stdout);
6,951✔
264
}
6,951✔
265

266
PlatformSpecificFile PlatformSpecificStdOut = stdout;
267

268
PlatformSpecificFile (*PlatformSpecificFOpen)(const char*, const char*) = PlatformSpecificFOpenImplementation;
269
void (*PlatformSpecificFPuts)(const char*, PlatformSpecificFile) = PlatformSpecificFPutsImplementation;
270
void (*PlatformSpecificFClose)(PlatformSpecificFile) = PlatformSpecificFCloseImplementation;
271

272
void (*PlatformSpecificFlush)() = PlatformSpecificFlushImplementation;
273

274
void* (*PlatformSpecificMalloc)(size_t size) = malloc;
275
void* (*PlatformSpecificRealloc)(void*, size_t) = realloc;
276
void (*PlatformSpecificFree)(void* memory) = free;
277
void* (*PlatformSpecificMemCpy)(void*, const void*, size_t) = memcpy;
278
void* (*PlatformSpecificMemset)(void*, int, size_t) = memset;
279

280
/* GCC 4.9.x introduces -Wfloat-conversion, which causes a warning / error
281
 * in GCC's own (macro) implementation of isnan() and isinf().
282
 */
283
#if defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8))
284
#pragma GCC diagnostic ignored "-Wfloat-conversion"
285
#endif
286

287
static int IsNanImplementation(double d)
287✔
288
{
289
    return isnan(d);
287✔
290
}
291

292
static int IsInfImplementation(double d)
119✔
293
{
294
    return isinf(d);
119✔
295
}
296

297
double (*PlatformSpecificFabs)(double) = fabs;
298
void (*PlatformSpecificSrand)(unsigned int) = srand;
299
int (*PlatformSpecificRand)(void) = rand;
300
int (*PlatformSpecificIsNan)(double) = IsNanImplementation;
301
int (*PlatformSpecificIsInf)(double) = IsInfImplementation;
302
int (*PlatformSpecificAtExit)(void(*func)(void)) = atexit;  /// this was undefined before
303

304
static PlatformSpecificMutex PThreadMutexCreate(void)
139✔
305
{
306
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
307
    pthread_mutex_t *mutex = new pthread_mutex_t;
139✔
308

309
    pthread_mutex_init(mutex, NULLPTR);
139✔
310
    return (PlatformSpecificMutex)mutex;
139✔
311
#else
312
    return NULLPTR;
313
#endif
314

315
}
316

317
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
318
static void PThreadMutexLock(PlatformSpecificMutex mtx)
×
319
{
320
    pthread_mutex_lock((pthread_mutex_t *)mtx);
×
321
}
×
322
#else
323
static void PThreadMutexLock(PlatformSpecificMutex)
324
{
325
}
326
#endif
327

328
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
329
static void PThreadMutexUnlock(PlatformSpecificMutex mtx)
×
330
{
331
    pthread_mutex_unlock((pthread_mutex_t *)mtx);
×
332
}
×
333
#else
334
static void PThreadMutexUnlock(PlatformSpecificMutex)
335
{
336
}
337
#endif
338

339
#ifdef CPPUTEST_HAVE_PTHREAD_MUTEX_LOCK
340
static void PThreadMutexDestroy(PlatformSpecificMutex mtx)
138✔
341
{
342
    pthread_mutex_t *mutex = (pthread_mutex_t *)mtx;
138✔
343
    pthread_mutex_destroy(mutex);
138✔
344
    delete mutex;
138✔
345
}
138✔
346
#else
347
static void PThreadMutexDestroy(PlatformSpecificMutex)
348
{
349
}
350
#endif
351

352
PlatformSpecificMutex (*PlatformSpecificMutexCreate)(void) = PThreadMutexCreate;
353
void (*PlatformSpecificMutexLock)(PlatformSpecificMutex) = PThreadMutexLock;
354
void (*PlatformSpecificMutexUnlock)(PlatformSpecificMutex) = PThreadMutexUnlock;
355
void (*PlatformSpecificMutexDestroy)(PlatformSpecificMutex) = PThreadMutexDestroy;
356
void (*PlatformSpecificAbort)(void) = abort;
357

358
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc