Skip to content

Commit

Permalink
faketime: use regular symbol iso nasty injection approach
Browse files Browse the repository at this point in the history
macOS doesn't allow injecting symbols (any more) and it's fugly as well,
so instead of preloading, just compile a separate binary for testing
purposes using the time/gettimeofday functions from faketime.
This is activating using a define via build, and therefore function nor
override are available in the produced binary (which is good).

Signed-off-by: Fabian Groffen <[email protected]>
  • Loading branch information
grobian committed Apr 27, 2024
1 parent 5d71a47 commit 0511eee
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 55 deletions.
16 changes: 10 additions & 6 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ man:
> relay.1

bin_PROGRAMS = relay
check_PROGRAMS = sendmetric
lib_LTLIBRARIES = libfaketime.la
check_PROGRAMS = relaytest sendmetric
relay_LINK = $(CCLD) $(AM_LDFLAGS) $(LDFLAGS) -o $@
relay_LDADD = $(LIBGZIP) $(LIBLZ4) $(LIBSNAPPY) $(LIBSSL) \
$(LIBONIGURUMA) $(LIBPCRE2) $(LIBPCRE)
Expand All @@ -59,10 +58,15 @@ relay_SOURCES = \
collector.c \
aggregator.c \
$(NULL)
relaytest_LINK = $(relay_LINK)
relaytest_LDADD = $(relay_LDADD)
relaytest_SOURCES = $(relay_SOURCES) \
faketime.c
relaytest_CPPFLAGS = $(AM_CPPFLAGS) \
-Dtime=faketime -Dgettimeofday=fakegettimeofday
sendmetric_LINK = $(CCLD) $(AM_LDFLAGS) $(LDFLAGS) -o $@
sendmetric_LDADD = $(LIBGZIP) $(LIBLZ4) $(LIBSNAPPY) $(LIBSSL)
sendmetric_SOURCES = sendmetric.c
libfaketime_la_SOURCES = faketime.c
noinst_HEADERS = \
relay.h \
md5.h \
Expand All @@ -79,6 +83,7 @@ noinst_HEADERS = \
collector.h \
aggregator.h \
posixregex.h \
faketime.h \
$(NULL)
man_MANS = relay.1

Expand Down Expand Up @@ -141,12 +146,11 @@ CRTESTS += dual-ssl large-ssl dual-large-ssl dual-mtls
endif

test: check
test-%: relay libfaketime.la sendmetric
test-%: relaytest sendmetric
@( cd test && ./run-test.sh $* )
approve-%: relay sendmetric
@( cd test && ./run-test.sh -a $* )
check-local:
@( cd test && ./run-test.sh $(CRTESTS) )
install-exec-local: # libtool refuses to build shared for check or noinst trg
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall \
rm -f "$(DESTDIR)$(libdir)/libfaketime.la"
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall
57 changes: 13 additions & 44 deletions faketime.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 Fabian Groffen
* Copyright 2013-2024 Fabian Groffen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,55 +18,23 @@
#include "config.h"
#endif

#ifndef HAVE_RTLD_NEXT
# error must have dlsym/RTLD_NEXT to fake time
#endif
/* avoid overrides here, we need the real thing */
#undef time
#undef gettimeofday

#if 0
/* we cannot include time.h and sys/time.h due to gettimeofday
* definition being different on some platforms with
* complex/incompatible restrict definitions, but we do need struct
* timeval, so we're faking the necessary bits here */
#include <time.h>
#include <sys/time.h>
#else
#define _TIME_H
#define _SYS_TIME_H
/* internal definition, we only access tv_sec so don't care about the
* type/definition of tv_usec */
#if SIZEOF_TIME_T == 4
#define fttime_t int
#elif SIZEOF_TIME_T == 8
#define fttime_t long long int
#else
#define fttime_t ssize_t
#endif
struct fttimeval {
fttime_t tv_sec;
};
#define NULL (void *)0
#endif

#include <dlfcn.h>

/* for repeatability, always return time starting from 1981-02-01 from the
* first call to time(). This way we can control the aggregator time
* buckets */
#define MYEPOCH 349830000

fttime_t (*orig_time)(fttime_t *tloc) = NULL;
int (*orig_gettimeofday)(struct fttimeval *tp, void *tz) = NULL;
fttime_t fake_offset = 0;
static time_t fake_offset = 0;
time_t faketime(time_t *tloc) {
time_t now;

__attribute__((constructor)) void init(void) {
orig_time = dlsym(RTLD_NEXT, "time");
orig_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
}

fttime_t time(fttime_t *tloc) {
fttime_t now;

(void)orig_time(&now);
(void)time(&now);

if (fake_offset == 0)
fake_offset = now - MYEPOCH;
Expand All @@ -77,18 +45,19 @@ fttime_t time(fttime_t *tloc) {
return now;
}

int gettimeofday(struct fttimeval *tp, void *tzp) {
int fakegettimeofday(struct timeval *tp, void *tzp) {
/* some platforms, like Darwin and Solaris, have an implementation
* of gettimeofday that does not call time(), others, like glibc do
* which means we need to deal with that here */
fttime_t now;
time_t now;

int ret = orig_gettimeofday(tp, tzp);
int ret = gettimeofday(tp, tzp);
if (ret != 0)
return ret;

/* setup clock offset */
now = time(NULL);
if (fake_offset == 0)
now = time(NULL);
now += fake_offset;

if (now >= tp->tv_sec)
Expand Down
30 changes: 30 additions & 0 deletions faketime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2013-2024 Fabian Groffen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef HAVE_FAKETIME_H
#define HAVE_FAKETIME_H 1

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <time.h>
#include <sys/time.h>

time_t faketime(time_t *tloc);
int fakegettimeofday(struct timeval *tp, void *tx);

#endif
6 changes: 1 addition & 5 deletions test/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

EXEC=../relay
EXEC=../relaytest
SMEXEC=../sendmetric
EFLAGS="-Htest.hostname -t"
DIFF="diff -Nu"
Expand All @@ -25,10 +25,6 @@ CNFCLN=( sed -e '/^configuration:/,/^parsed configuration follows:/d'
-e 's/^\[[0-9][0-9\-]* [0-9][0-9:]*\] //'
-e 's/_stub_[0-9a-fx][0-9a-fx]*__/_stub_0xc0d3__/')

export DYLD_FORCE_FLAT_NAMESPACE=1
export DYLD_INSERT_LIBRARIES=../.libs/libfaketime.dylib
export LD_PRELOAD=../.libs/libfaketime.so

buftest_generate() {
i=1
end=2000
Expand Down

0 comments on commit 0511eee

Please sign in to comment.