#!/bin/sh
set -e
exec 2>&1 # autopkgtest fails by default on stderr output

set -x

# We deliberately eschew faketime's normal build system here:
# we want to know if the plumbing works for a "normal program".

# To run this with a libfaketime from the build tree,
#
#  mkdir d
#  FAKETIME_TEST_INTERPOSE="env LD_PRELOAD=$PWD/debian/libfaketime/usr/lib/arm-linux-gnueabihf/faketime/libfaketime.so.1" AUTOPKGTEST_TMP=$PWD/d debian/tests/simple-cprogs
#
# or similar.

export TZ=UTC

cd "$AUTOPKGTEST_TMP"

cat <<'END' >now.c

#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <stdint.h>
#include <sys/time.h>
#include <inttypes.h>

int p(const char *what, uint64_t val) {
    printf("%" PRIu64 "\t%s\n", val, what);
}

#define TRAIL 8
#define FOR_TRAIL \
    int i; \
    unsigned char *p; \
    unsigned char b; \
    for (i=0, b=(uintptr_t)trail, p=trail; i<TRAIL; i++, b++)

// Try to detect if faketime's structs are larger than the program expects,
// which would be some kind of horrible write overrun.
static void prep_around(unsigned char *trail) {
    FOR_TRAIL *p++ = b;
}
static void check_around(unsigned char *trail) {
    FOR_TRAIL assert(*p++ == b);
}

int main() {
    struct {
        struct timeval tv;
        unsigned char trail[TRAIL];
    } around_tv;

    struct {
        struct timespec ts;
        unsigned char trail[TRAIL];
    } around_ts;

    int r;

    p("time", time(NULL));

    prep_around(around_tv.trail);
    r = gettimeofday(&around_tv.tv, 0);  assert(r==0);
    p("gettimeofday", around_tv.tv.tv_sec);
    check_around(around_tv.trail);

    prep_around(around_ts.trail);
    r = clock_gettime(CLOCK_REALTIME, &around_ts.ts);  assert(r==0);
    p("clock_gettime", around_ts.ts.tv_sec);
    check_around(around_ts.trail);

    return 0;
}

END

cat <<END >expected-1980
315532800	time
315532800	gettimeofday
315532800	clock_gettime
END
cat <<END >expected-2040
2208988800	time
2208988800	gettimeofday
2208988800	clock_gettime
END

check_at () {
    which=$1
    fake=$2
    faketime "$fake" $FAKETIME_TEST_INTERPOSE ./a.out |tee actual-$which
    diff expected-$which actual-$which
}

check () {
    check_at 1980 '1980-01-01 00:00:00'

    case "$(dpkg --print-architecture)" in
	# 32-bit arches on Debian buildds as of 2025-01-17
	# At the time of writing, faketime stops working there on Y2038
	# https://github.com/wolfcw/libfaketime/issues/482
	armhf|armel|i386|hppa|hurd-i386|m68k|powerpc|sh4)
	    return
	    ;;
	*)
	    check_at 2040 '2040-01-01 00:00:00'
	    ;;
    esac
}

cc `dpkg-buildflags --get CPPFLAGS` now.c
check

cc now.c
check

echo ok.
exit 0
