xref: /curl/tests/libtest/testutil.c (revision 2dbe75bd)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 #include "curl_setup.h"
25 #include <curl/curl.h>
26 #include "testutil.h"
27 #include "memdebug.h"
28 
29 #if defined(_WIN32)
30 
tutil_tvnow(void)31 struct timeval tutil_tvnow(void)
32 {
33   /*
34   ** GetTickCount() is available on _all_ Windows versions from W95 up
35   ** to nowadays. Returns milliseconds elapsed since last system boot,
36   ** increases monotonically and wraps once 49.7 days have elapsed.
37   */
38   struct timeval now;
39   DWORD milliseconds = GetTickCount();
40   now.tv_sec = (long)(milliseconds / 1000);
41   now.tv_usec = (long)((milliseconds % 1000) * 1000);
42   return now;
43 }
44 
45 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
46 
tutil_tvnow(void)47 struct timeval tutil_tvnow(void)
48 {
49   /*
50   ** clock_gettime() is granted to be increased monotonically when the
51   ** monotonic clock is queried. Time starting point is unspecified, it
52   ** could be the system start-up time, the Epoch, or something else,
53   ** in any case the time starting point does not change once that the
54   ** system has started up.
55   */
56   struct timeval now;
57   struct timespec tsnow;
58   if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
59     now.tv_sec = tsnow.tv_sec;
60     now.tv_usec = (int)(tsnow.tv_nsec / 1000);
61   }
62   /*
63   ** Even when the configure process has truly detected monotonic clock
64   ** availability, it might happen that it is not actually available at
65   ** run-time. When this occurs simply fallback to other time source.
66   */
67 #ifdef HAVE_GETTIMEOFDAY
68   else
69     (void)gettimeofday(&now, NULL);
70 #else
71   else {
72     now.tv_sec = time(NULL);
73     now.tv_usec = 0;
74   }
75 #endif
76   return now;
77 }
78 
79 #elif defined(HAVE_GETTIMEOFDAY)
80 
tutil_tvnow(void)81 struct timeval tutil_tvnow(void)
82 {
83   /*
84   ** gettimeofday() is not granted to be increased monotonically, due to
85   ** clock drifting and external source time synchronization it can jump
86   ** forward or backward in time.
87   */
88   struct timeval now;
89   (void)gettimeofday(&now, NULL);
90   return now;
91 }
92 
93 #else
94 
tutil_tvnow(void)95 struct timeval tutil_tvnow(void)
96 {
97   /*
98   ** time() returns the value of time in seconds since the Epoch.
99   */
100   struct timeval now;
101   now.tv_sec = time(NULL);
102   now.tv_usec = 0;
103   return now;
104 }
105 
106 #endif
107 
108 /*
109  * Make sure that the first argument is the more recent time, as otherwise
110  * we'll get a weird negative time-diff back...
111  *
112  * Returns: the time difference in number of milliseconds.
113  */
tutil_tvdiff(struct timeval newer,struct timeval older)114 long tutil_tvdiff(struct timeval newer, struct timeval older)
115 {
116   return (long)(newer.tv_sec-older.tv_sec)*1000+
117     (long)(newer.tv_usec-older.tv_usec)/1000;
118 }
119 
120 /*
121  * Same as tutil_tvdiff but with full usec resolution.
122  *
123  * Returns: the time difference in seconds with subsecond resolution.
124  */
tutil_tvdiff_secs(struct timeval newer,struct timeval older)125 double tutil_tvdiff_secs(struct timeval newer, struct timeval older)
126 {
127   if(newer.tv_sec != older.tv_sec)
128     return (double)(newer.tv_sec-older.tv_sec)+
129       (double)(newer.tv_usec-older.tv_usec)/1000000.0;
130   return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
131 }
132 
133 #ifdef _WIN32
win32_load_system_library(const TCHAR * filename)134 HMODULE win32_load_system_library(const TCHAR *filename)
135 {
136   size_t filenamelen = _tcslen(filename);
137   size_t systemdirlen = GetSystemDirectory(NULL, 0);
138   size_t written;
139   TCHAR *path;
140 
141   if(!filenamelen || filenamelen > 32768 ||
142      !systemdirlen || systemdirlen > 32768)
143     return NULL;
144 
145   /* systemdirlen includes null character */
146   path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
147   if(!path)
148     return NULL;
149 
150   /* if written >= systemdirlen then nothing was written */
151   written = GetSystemDirectory(path, (unsigned int)systemdirlen);
152   if(!written || written >= systemdirlen)
153     return NULL;
154 
155   if(path[written - 1] != _T('\\'))
156     path[written++] = _T('\\');
157 
158   _tcscpy(path + written, filename);
159 
160   return LoadLibrary(path);
161 }
162 #endif
163