dagolden / Data-Fake

Declaratively generate fake structured data for testing
https://metacpan.org/author/DAGOLDEN
5 stars 4 forks source link

Test failure on 32bit systems #15

Open gregoa opened 3 months ago

gregoa commented 3 months ago

t/dates.t fails on X86_32, as seen on https://ci.debian.net/packages/libd/libdata-fake-perl/testing/i386/46574760/#S6

Running the tests locally I get on amd64 (X86_64):

t/dates.t .............. 
# Subtest: fake epochs
    ok 1 - fake_past_epoch looks like integer
    ok 2 - fake_past_epoch (1706722699) is in the past
    ok 3 - fake_past_epoch looks like integer
    ok 4 - fake_past_epoch (625057194) is in the past
    ok 5 - fake_past_epoch looks like integer
    ok 6 - fake_past_epoch (187364841) is in the past
    ok 7 - fake_past_epoch looks like integer
    ok 8 - fake_past_epoch (162623226) is in the past
    ok 9 - fake_past_epoch looks like integer
    ok 10 - fake_past_epoch (397224917) is in the past
    ok 11 - fake_past_epoch looks like integer
    ok 12 - fake_past_epoch (1683722299) is in the past
    ok 13 - fake_future_epoch looks like integer
    ok 14 - fake_future_epoch (2307397715) is in the future
    ok 15 - fake_future_epoch looks like integer
    ok 16 - fake_future_epoch (3176897530) is in the future
    ok 17 - fake_future_epoch looks like integer
    ok 18 - fake_future_epoch (2348710298) is in the future
    ok 19 - fake_future_epoch looks like integer
    ok 20 - fake_future_epoch (3249142863) is in the future
    ok 21 - fake_future_epoch looks like integer
    ok 22 - fake_future_epoch (1983262946) is in the future
    ok 23 - fake_future_epoch looks like integer
    ok 24 - fake_future_epoch (3053760535) is in the future
    1..24
ok 1 - fake epochs
# Subtest: fake datetimes
    ok 1 - fake_past_datetime (1973-04-21T11:39:50Z) looks like ISO-8601
    ok 2 - fake_past_datetime (2018-03-08T05:57:43Z) looks like ISO-8601
    ok 3 - fake_past_datetime (1976-09-29T14:53:22Z) looks like ISO-8601
    ok 4 - fake_past_datetime (1977-04-09T02:01:24Z) looks like ISO-8601
    ok 5 - fake_past_datetime (1979-10-12T05:08:59Z) looks like ISO-8601
    ok 6 - fake_past_datetime (2010-04-05T13:15:17Z) looks like ISO-8601
    ok 7 - fake_future_datetime (2056-09-26T06:24:01Z) looks like ISO-8601
    ok 8 - fake_future_datetime (2049-05-11T02:27:14Z) looks like ISO-8601
    ok 9 - fake_future_datetime (2029-12-22T05:46:01Z) looks like ISO-8601
    ok 10 - fake_future_datetime (2024-10-19T16:52:12Z) looks like ISO-8601
    ok 11 - fake_future_datetime (2074-02-16T20:41:35Z) looks like ISO-8601
    ok 12 - fake_future_datetime (2055-11-28T00:22:58Z) looks like ISO-8601
    ok 13 - fake_past_datetime('%Y-%m-%d') (1985-02-02)
    ok 14 - fake_future_datetime('%Y-%m-%d') (2072-01-21)
    1..14
ok 2 - fake datetimes
1..2
ok

On i386 (X86_32) I get:

Error parsing time at /usr/lib/i386-linux-gnu/perl/5.38/Time/Piece.pm line 598.
# Tests were run but no plan was declared and done_testing() was not seen.
# Looks like your test exited with 255 just after 2.
t/dates.t .............. 
# Subtest: fake epochs
    ok 1 - fake_past_epoch looks like integer
    ok 2 - fake_past_epoch (1028045073) is in the past
    ok 3 - fake_past_epoch looks like integer
    ok 4 - fake_past_epoch (1562708424) is in the past
    ok 5 - fake_past_epoch looks like integer
    ok 6 - fake_past_epoch (153300181) is in the past
    ok 7 - fake_past_epoch looks like integer
    ok 8 - fake_past_epoch (1014821026) is in the past
    ok 9 - fake_past_epoch looks like integer
    ok 10 - fake_past_epoch (1095754107) is in the past
    ok 11 - fake_past_epoch looks like integer
    ok 12 - fake_past_epoch (1713911634) is in the past
    ok 13 - fake_future_epoch looks like integer
    ok 14 - fake_future_epoch (1994713476) is in the future
    ok 15 - fake_future_epoch looks like integer
    ok 16 - fake_future_epoch (2180774967) is in the future
    ok 17 - fake_future_epoch looks like integer
    ok 18 - fake_future_epoch (2116559546) is in the future
    ok 19 - fake_future_epoch looks like integer
    ok 20 - fake_future_epoch (1876274998) is in the future
    ok 21 - fake_future_epoch looks like integer
    ok 22 - fake_future_epoch (3021111817) is in the future
    ok 23 - fake_future_epoch looks like integer
    ok 24 - fake_future_epoch (3267920067) is in the future
    1..24
ok 1 - fake epochs
# Subtest: fake datetimes
    ok 1 - fake_past_datetime (1972-05-11T02:14:54Z) looks like ISO-8601
    ok 2 - fake_past_datetime (1994-08-08T10:00:59Z) looks like ISO-8601
    ok 3 - fake_past_datetime (2021-08-25T20:50:38Z) looks like ISO-8601
    ok 4 - fake_past_datetime (1977-09-07T16:52:27Z) looks like ISO-8601
    ok 5 - fake_past_datetime (1974-01-14T15:07:43Z) looks like ISO-8601
    ok 6 - fake_past_datetime (2018-02-19T09:35:40Z) looks like ISO-8601
    1..6
ok 2 - fake datetimes
Dubious, test returned 255 (wstat 65280, 0xff00)
All 2 subtests passed 

It looks to me like fake_future_datetime in lib/Data/Fake/Dates.pm calls Time::Piece which fails in strptime() with dates beyond the infamous time_t 32bit / 2038 border …

Not sure if this is a bug in Data::Fake, Time::Piece, Debian's perl or somewhere else but maybe handling Time::Piece errors more gracefully in Data::Fake might be possible.

Cheers, gregor, Debian Perl Group

perlpunk commented 2 months ago

We see the same on openSUSE: https://build.opensuse.org/package/live_build_log/devel:languages:perl/perl-Data-Fake/openSUSE_Tumbleweed/i586

gregoa commented 1 month ago

Here's a workaround that seems to work on Debian 32bit architectures:

Description: Time::Piece's strptime() fails with timestampgs >= 2**31 on 32bit perls
 As a workaround, add an upper limit for future timestamps.
Origin: vendor
Bug: https://github.com/dagolden/Data-Fake/issues/15
Bug-Debian: https://bugs.debian.org/1071967
Author: gregor herrmann <gregoa@debian.org>
Last-Update: 2024-07-13

--- a/lib/Data/Fake/Dates.pm
+++ b/lib/Data/Fake/Dates.pm
@@ -17,12 +17,17 @@
 );

 use Time::Piece 1.27; # portability fixes
+use Config;

 sub _past { int( rand(time) ) }

 sub _future {
     my $now = time;
-    return $now + int( rand($now) );
+    if ($Config{longsize} == 8) {
+      return $now + int( rand($now) );
+    } else {
+      return $now + int( rand(2**31 - 1 - $now) );
+    }
 }

 #pod =func fake_past_epoch

Does this make sense for openSUSE as well, @perlpunk?

(Ultimately, this feels like a Time::Piece bug …)

perlpunk commented 1 month ago

@gregoa yes, this works, thanks :)