minunit.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. * Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #ifndef MINUNIT_MINUNIT_H
  24. #define MINUNIT_MINUNIT_H
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28. #if defined(_WIN32)
  29. #include <Windows.h>
  30. #if defined(_MSC_VER) && _MSC_VER < 1900
  31. #define snprintf _snprintf
  32. #define __func__ __FUNCTION__
  33. #endif
  34. #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
  35. /* Change POSIX C SOURCE version for pure c99 compilers */
  36. #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
  37. #undef _POSIX_C_SOURCE
  38. #define _POSIX_C_SOURCE 200112L
  39. #endif
  40. #include <unistd.h> /* POSIX flags */
  41. #include <time.h> /* clock_gettime(), time() */
  42. #include <sys/time.h> /* gethrtime(), gettimeofday() */
  43. #include <sys/resource.h>
  44. #include <sys/times.h>
  45. #include <string.h>
  46. #if defined(__MACH__) && defined(__APPLE__)
  47. #include <mach/mach.h>
  48. #include <mach/mach_time.h>
  49. #endif
  50. #if __GNUC__ >= 5 && !defined(__STDC_VERSION__)
  51. #define __func__ __extension__ __FUNCTION__
  52. #endif
  53. #else
  54. // #error "Unable to define timers for an unknown OS."
  55. #endif
  56. #include <stdio.h>
  57. #include <math.h>
  58. /* Maximum length of last message */
  59. #define MINUNIT_MESSAGE_LEN 1024
  60. /* Accuracy with which floats are compared */
  61. #define MINUNIT_EPSILON 1E-12
  62. #include "minunit_vars_ex.h"
  63. /* Test setup and teardown function pointers */
  64. static void (*minunit_setup)(void) = NULL;
  65. static void (*minunit_teardown)(void) = NULL;
  66. /* Definitions */
  67. #define MU_TEST(method_name) static void method_name(void)
  68. #define MU_TEST_SUITE(suite_name) static void suite_name(void)
  69. #define MU__SAFE_BLOCK(block) do {\
  70. block\
  71. } while(0)
  72. /* Run test suite and unset setup and teardown functions */
  73. #define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\
  74. suite_name();\
  75. minunit_setup = NULL;\
  76. minunit_teardown = NULL;\
  77. )
  78. /* Configure setup and teardown functions */
  79. #define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\
  80. minunit_setup = setup_fun;\
  81. minunit_teardown = teardown_fun;\
  82. )
  83. /* Test runner */
  84. #define MU_RUN_TEST(test) MU__SAFE_BLOCK(\
  85. if (minunit_real_timer==0 && minunit_proc_timer==0) {\
  86. minunit_real_timer = mu_timer_real();\
  87. minunit_proc_timer = mu_timer_cpu();\
  88. }\
  89. if (minunit_setup) (*minunit_setup)();\
  90. minunit_status = 0;\
  91. test();\
  92. minunit_run++;\
  93. if (minunit_status) {\
  94. minunit_fail++;\
  95. printf("F");\
  96. printf("\n%s\n", minunit_last_message);\
  97. }\
  98. fflush(stdout);\
  99. if (minunit_teardown) (*minunit_teardown)();\
  100. )
  101. /* Report */
  102. #define MU_REPORT() MU__SAFE_BLOCK(\
  103. double minunit_end_real_timer;\
  104. double minunit_end_proc_timer;\
  105. printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, minunit_assert, minunit_fail);\
  106. minunit_end_real_timer = mu_timer_real();\
  107. minunit_end_proc_timer = mu_timer_cpu();\
  108. printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\
  109. minunit_end_real_timer - minunit_real_timer,\
  110. minunit_end_proc_timer - minunit_proc_timer);\
  111. )
  112. #define MU_EXIT_CODE minunit_fail
  113. /* Assertions */
  114. #define mu_check(test) MU__SAFE_BLOCK(\
  115. minunit_assert++;\
  116. if (!(test)) {\
  117. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, #test);\
  118. minunit_status = 1;\
  119. return;\
  120. } else {\
  121. printf(".");\
  122. }\
  123. )
  124. #define mu_fail(message) MU__SAFE_BLOCK(\
  125. minunit_assert++;\
  126. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
  127. minunit_status = 1;\
  128. return;\
  129. )
  130. #define mu_assert(test, message) MU__SAFE_BLOCK(\
  131. minunit_assert++;\
  132. if (!(test)) {\
  133. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
  134. minunit_status = 1;\
  135. return;\
  136. } else {\
  137. printf(".");\
  138. }\
  139. )
  140. #define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\
  141. int minunit_tmp_e;\
  142. int minunit_tmp_r;\
  143. minunit_assert++;\
  144. minunit_tmp_e = (expected);\
  145. minunit_tmp_r = (result);\
  146. if (minunit_tmp_e != minunit_tmp_r) {\
  147. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d expected but was %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
  148. minunit_status = 1;\
  149. return;\
  150. } else {\
  151. printf(".");\
  152. }\
  153. )
  154. #define mu_assert_int_not_eq(expected, result) MU__SAFE_BLOCK(\
  155. int minunit_tmp_e;\
  156. int minunit_tmp_r;\
  157. minunit_assert++;\
  158. minunit_tmp_e = (expected);\
  159. minunit_tmp_r = (result);\
  160. if (minunit_tmp_e == minunit_tmp_r) {\
  161. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: expected different results but both were %d", __func__, __FILE__, __LINE__, minunit_tmp_e);\
  162. minunit_status = 1;\
  163. return;\
  164. } else {\
  165. printf(".");\
  166. }\
  167. )
  168. #define mu_assert_int_greater_than(val, result) MU__SAFE_BLOCK(\
  169. int minunit_tmp_e;\
  170. int minunit_tmp_r;\
  171. minunit_assert++;\
  172. minunit_tmp_e = (val);\
  173. minunit_tmp_r = (result);\
  174. if (val >= minunit_tmp_r) {\
  175. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d <= %d", __func__, __FILE__, __LINE__, minunit_tmp_r, minunit_tmp_e);\
  176. minunit_status = 1;\
  177. return;\
  178. } else {\
  179. printf(".");\
  180. }\
  181. )
  182. #define mu_assert_int_less_than(val, result) MU__SAFE_BLOCK(\
  183. int minunit_tmp_e;\
  184. int minunit_tmp_r;\
  185. minunit_assert++;\
  186. minunit_tmp_e = (val);\
  187. minunit_tmp_r = (result);\
  188. if (val <= minunit_tmp_r) {\
  189. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d >= %d", __func__, __FILE__, __LINE__, minunit_tmp_r, minunit_tmp_e);\
  190. minunit_status = 1;\
  191. return;\
  192. } else {\
  193. printf(".");\
  194. }\
  195. )
  196. #define mu_assert_int_between(expected_lower, expected_upper, result) MU__SAFE_BLOCK(\
  197. int minunit_tmp_e;\
  198. int minunit_tmp_m;\
  199. int minunit_tmp_r;\
  200. minunit_assert++;\
  201. minunit_tmp_e = (expected_lower);\
  202. minunit_tmp_m = (expected_upper);\
  203. minunit_tmp_r = (result);\
  204. if (result < minunit_tmp_e || result > minunit_tmp_m) {\
  205. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d was not between (inclusive) %d and %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r, minunit_tmp_m);\
  206. minunit_status = 1;\
  207. return;\
  208. } else {\
  209. printf(".");\
  210. }\
  211. )
  212. #define mu_assert_int_in(expected, array_length, result) MU__SAFE_BLOCK(\
  213. int minunit_tmp_r;\
  214. minunit_assert++;\
  215. minunit_tmp_r = (result);\
  216. int t = 0;\
  217. int i;\
  218. for (i = 0; i < array_length; i++) {\
  219. if (expected[i] == minunit_tmp_r)\
  220. t = 1;\
  221. }\
  222. if (t == 0) {\
  223. char tmp[500] = {0};\
  224. tmp[0] = '[';\
  225. for (i = 0; i < array_length; i++) {\
  226. sprintf(tmp + strlen(tmp), "%d, ", expected[i]);\
  227. }\
  228. int len = strlen(tmp);\
  229. tmp[len - 2] = ']';\
  230. tmp[len - 1] = '\0';\
  231. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: expected to be one of %s but was %d", __func__, __FILE__, __LINE__, tmp, minunit_tmp_r);\
  232. minunit_status = 1;\
  233. return;\
  234. } else {\
  235. printf(".");\
  236. }\
  237. )
  238. #define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\
  239. double minunit_tmp_e;\
  240. double minunit_tmp_r;\
  241. minunit_assert++;\
  242. minunit_tmp_e = (expected);\
  243. minunit_tmp_r = (result);\
  244. if (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\
  245. int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON);\
  246. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %.*g expected but was %.*g", __func__, __FILE__, __LINE__, minunit_significant_figures, minunit_tmp_e, minunit_significant_figures, minunit_tmp_r);\
  247. minunit_status = 1;\
  248. return;\
  249. } else {\
  250. printf(".");\
  251. }\
  252. )
  253. #define mu_assert_double_greater_than(val, result) MU__SAFE_BLOCK(\
  254. double minunit_tmp_e;\
  255. double minunit_tmp_r;\
  256. minunit_assert++;\
  257. minunit_tmp_e = (val);\
  258. minunit_tmp_r = (result);\
  259. if (val >= minunit_tmp_r) {\
  260. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %f <= %f", __func__, __FILE__, __LINE__, minunit_tmp_r, minunit_tmp_e);\
  261. minunit_status = 1;\
  262. return;\
  263. } else {\
  264. printf(".");\
  265. }\
  266. )
  267. #define mu_assert_double_less_than(val, result) MU__SAFE_BLOCK(\
  268. double minunit_tmp_e;\
  269. double minunit_tmp_r;\
  270. minunit_assert++;\
  271. minunit_tmp_e = (val);\
  272. minunit_tmp_r = (result);\
  273. if (val <= minunit_tmp_r) {\
  274. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %f >= %f", __func__, __FILE__, __LINE__, minunit_tmp_r, minunit_tmp_e);\
  275. minunit_status = 1;\
  276. return;\
  277. } else {\
  278. printf(".");\
  279. }\
  280. )
  281. #define mu_assert_double_between(expected_lower, expected_upper, result) MU__SAFE_BLOCK(\
  282. double minunit_tmp_e;\
  283. double minunit_tmp_m;\
  284. double minunit_tmp_r;\
  285. minunit_assert++;\
  286. minunit_tmp_e = (expected_lower);\
  287. minunit_tmp_m = (expected_upper);\
  288. minunit_tmp_r = (result);\
  289. if (result < minunit_tmp_e || result > minunit_tmp_m) {\
  290. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %f was not between (inclusive) %f and %f", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r, minunit_tmp_m);\
  291. minunit_status = 1;\
  292. return;\
  293. } else {\
  294. printf(".");\
  295. }\
  296. )
  297. #define mu_assert_string_eq(expected, result) MU__SAFE_BLOCK(\
  298. const char* minunit_tmp_e = expected;\
  299. const char* minunit_tmp_r = result;\
  300. minunit_assert++;\
  301. if (!minunit_tmp_e) {\
  302. minunit_tmp_e = "<null pointer>";\
  303. }\
  304. if (!minunit_tmp_r) {\
  305. minunit_tmp_r = "<null pointer>";\
  306. }\
  307. if(strcmp(minunit_tmp_e, minunit_tmp_r)) {\
  308. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: '%s' expected but was '%s'", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
  309. minunit_status = 1;\
  310. return;\
  311. } else {\
  312. printf(".");\
  313. }\
  314. )
  315. #define mu_assert_null(result) MU__SAFE_BLOCK(\
  316. minunit_assert++;\
  317. if (result == NULL) {\
  318. printf(".");\
  319. } else {\
  320. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: Expected result was not NULL", __func__, __FILE__, __LINE__);\
  321. minunit_status = 1;\
  322. return;\
  323. }\
  324. )
  325. #define mu_assert_not_null(result) MU__SAFE_BLOCK(\
  326. minunit_assert++;\
  327. if (result != NULL) {\
  328. printf(".");\
  329. } else {\
  330. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: Expected result was not NULL", __func__, __FILE__, __LINE__);\
  331. minunit_status = 1;\
  332. return;\
  333. }\
  334. )
  335. #define mu_assert_pointers_eq(pointer1, pointer2) MU__SAFE_BLOCK(\
  336. minunit_assert++;\
  337. if (pointer1 == pointer2) {\
  338. printf(".");\
  339. } else {\
  340. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: Expected the pointers to point to the same memory location", __func__, __FILE__, __LINE__);\
  341. minunit_status = 1;\
  342. return;\
  343. }\
  344. )
  345. #define mu_assert_pointers_not_eq(pointer1, pointer2) MU__SAFE_BLOCK(\
  346. minunit_assert++;\
  347. if (pointer1 != pointer2) {\
  348. printf(".");\
  349. } else {\
  350. snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: Expected the pointers to point to the same memory location", __func__, __FILE__, __LINE__);\
  351. minunit_status = 1;\
  352. return;\
  353. }\
  354. )
  355. /*
  356. * The following two functions were written by David Robert Nadeau
  357. * from http://NadeauSoftware.com/ and distributed under the
  358. * Creative Commons Attribution 3.0 Unported License
  359. */
  360. /**
  361. * Returns the real time, in seconds, or -1.0 if an error occurred.
  362. *
  363. * Time is measured since an arbitrary and OS-dependent start time.
  364. * The returned real time is only useful for computing an elapsed time
  365. * between two calls to this function.
  366. */
  367. static double mu_timer_real(void)
  368. {
  369. #if defined(_WIN32)
  370. /* Windows 2000 and later. ---------------------------------- */
  371. LARGE_INTEGER Time;
  372. LARGE_INTEGER Frequency;
  373. QueryPerformanceFrequency(&Frequency);
  374. QueryPerformanceCounter(&Time);
  375. Time.QuadPart *= 1000000;
  376. Time.QuadPart /= Frequency.QuadPart;
  377. return (double)Time.QuadPart / 1000000.0;
  378. #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
  379. /* HP-UX, Solaris. ------------------------------------------ */
  380. return (double)gethrtime( ) / 1000000000.0;
  381. #elif defined(__MACH__) && defined(__APPLE__)
  382. /* OSX. ----------------------------------------------------- */
  383. static double timeConvert = 0.0;
  384. if ( timeConvert == 0.0 )
  385. {
  386. mach_timebase_info_data_t timeBase;
  387. (void)mach_timebase_info( &timeBase );
  388. timeConvert = (double)timeBase.numer /
  389. (double)timeBase.denom /
  390. 1000000000.0;
  391. }
  392. return (double)mach_absolute_time( ) * timeConvert;
  393. #elif defined(_POSIX_VERSION)
  394. /* POSIX. --------------------------------------------------- */
  395. struct timeval tm;
  396. #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
  397. {
  398. struct timespec ts;
  399. #if defined(CLOCK_MONOTONIC_PRECISE)
  400. /* BSD. --------------------------------------------- */
  401. const clockid_t id = CLOCK_MONOTONIC_PRECISE;
  402. #elif defined(CLOCK_MONOTONIC_RAW)
  403. /* Linux. ------------------------------------------- */
  404. const clockid_t id = CLOCK_MONOTONIC_RAW;
  405. #elif defined(CLOCK_HIGHRES)
  406. /* Solaris. ----------------------------------------- */
  407. const clockid_t id = CLOCK_HIGHRES;
  408. #elif defined(CLOCK_MONOTONIC)
  409. /* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
  410. const clockid_t id = CLOCK_MONOTONIC;
  411. #elif defined(CLOCK_REALTIME)
  412. /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
  413. const clockid_t id = CLOCK_REALTIME;
  414. #else
  415. const clockid_t id = (clockid_t)-1; /* Unknown. */
  416. #endif /* CLOCK_* */
  417. if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
  418. return (double)ts.tv_sec +
  419. (double)ts.tv_nsec / 1000000000.0;
  420. /* Fall thru. */
  421. }
  422. #endif /* _POSIX_TIMERS */
  423. /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
  424. gettimeofday( &tm, NULL );
  425. return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
  426. #else
  427. return -1.0; /* Failed. */
  428. #endif
  429. }
  430. /**
  431. * Returns the amount of CPU time used by the current process,
  432. * in seconds, or -1.0 if an error occurred.
  433. */
  434. static double mu_timer_cpu(void)
  435. {
  436. #if defined(_WIN32)
  437. /* Windows -------------------------------------------------- */
  438. FILETIME createTime;
  439. FILETIME exitTime;
  440. FILETIME kernelTime;
  441. FILETIME userTime;
  442. /* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */
  443. if ( GetProcessTimes( GetCurrentProcess( ),
  444. &createTime, &exitTime, &kernelTime, &userTime ) != 0 )
  445. {
  446. ULARGE_INTEGER userSystemTime;
  447. memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));
  448. return (double)userSystemTime.QuadPart / 10000000.0;
  449. }
  450. #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
  451. /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */
  452. #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
  453. /* Prefer high-res POSIX timers, when available. */
  454. {
  455. clockid_t id;
  456. struct timespec ts;
  457. #if _POSIX_CPUTIME > 0
  458. /* Clock ids vary by OS. Query the id, if possible. */
  459. if ( clock_getcpuclockid( 0, &id ) == -1 )
  460. #endif
  461. #if defined(CLOCK_PROCESS_CPUTIME_ID)
  462. /* Use known clock id for AIX, Linux, or Solaris. */
  463. id = CLOCK_PROCESS_CPUTIME_ID;
  464. #elif defined(CLOCK_VIRTUAL)
  465. /* Use known clock id for BSD or HP-UX. */
  466. id = CLOCK_VIRTUAL;
  467. #else
  468. id = (clockid_t)-1;
  469. #endif
  470. if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
  471. return (double)ts.tv_sec +
  472. (double)ts.tv_nsec / 1000000000.0;
  473. }
  474. #endif
  475. #if defined(RUSAGE_SELF)
  476. {
  477. struct rusage rusage;
  478. if ( getrusage( RUSAGE_SELF, &rusage ) != -1 )
  479. return (double)rusage.ru_utime.tv_sec +
  480. (double)rusage.ru_utime.tv_usec / 1000000.0;
  481. }
  482. #endif
  483. #if defined(_SC_CLK_TCK)
  484. {
  485. const double ticks = (double)sysconf( _SC_CLK_TCK );
  486. struct tms tms;
  487. if ( times( &tms ) != (clock_t)-1 )
  488. return (double)tms.tms_utime / ticks;
  489. }
  490. #endif
  491. #if defined(CLOCKS_PER_SEC)
  492. {
  493. clock_t cl = clock( );
  494. if ( cl != (clock_t)-1 )
  495. return (double)cl / (double)CLOCKS_PER_SEC;
  496. }
  497. #endif
  498. #endif
  499. return -1; /* Failed. */
  500. }
  501. #ifdef __cplusplus
  502. }
  503. #endif
  504. #endif /* MINUNIT_MINUNIT_H */