Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failing chtimes tests on mips64 #41850

Open
elboulangero opened this issue Jan 4, 2021 · 1 comment
Open

Failing chtimes tests on mips64 #41850

elboulangero opened this issue Jan 4, 2021 · 1 comment

Comments

@elboulangero
Copy link
Contributor

elboulangero commented Jan 4, 2021

While building docker on a mips64 machine, from the Debian infra, we observe that some tests fail. The full trace can be seen at https://buildd.debian.org/status/fetch.php?pkg=docker.io&arch=mips64el&ver=20.10.0%2Bdfsg2-1&stamp=1608299173. The relevant part is:

=== RUN   TestChtimesLinux
    chtimes_linux_test.go:87: Expected: 2262-04-11 23:47:16 +0000 UTC, got: 1990-01-27 10:50:44 +0000 UTC
--- FAIL: TestChtimesLinux (0.00s)
=== RUN   TestChtimes
    chtimes_test.go:92: Expected: 2262-04-11 23:47:16 +0000 UTC, got: 1990-01-27 10:50:44 +0000 UTC
--- FAIL: TestChtimes (0.00s)

The problem explained

And the relevant parts of the code, for reference:

func init() {
        // chtimes initialization
        if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
                // This is a 64 bit timespec
                // os.Chtimes limits time to the following
                maxTime = time.Unix(0, 1<<63-1)
        } else {
                // This is a 32 bit timespec
                maxTime = time.Unix(1<<31-1, 0)
        }
}

func TestChtimesLinux(t *testing.T) {

        [...]

        // Test both aTime and mTime set to Unix max time
        Chtimes(file, unixMaxTime, unixMaxTime)

        f, err = os.Stat(file)
        if err != nil {
                t.Fatal(err)
        }

        stat = f.Sys().(*syscall.Stat_t)
        aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) // nolint: unconvert
        if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
                t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
        }

After some investigation, I can explain the issue. On mips64, the size for Timespec.Nsec and Timespec.Sec is 64 bits. However, and that's the weird thing, the stat struct defines the variables st_atime, st_mtime and st_ctime as unsigned int, ie. 32 bits, in the kernel. See https://github.com/torvalds/linux/blob/master/arch/mips/include/uapi/asm/stat.h#L92

So what happens is that, while it's possible to set the access and modified times to something higher than UINT32_MAX, when one retrieves these values with f.Sys().(*syscall.Stat_t), this value is limited to 32 bit.

In other words, this test will never work on mips64, and that's expected

The workarounds

One can simply skip this test on mips64. This is what I did in this patch: https://salsa.debian.org/docker-team/docker/-/blob/master/debian/patches/test--skip-pkg-system-chtimes-mips64.patch.

Maybe a better way would be to split this test in different tests or subtests, so that we can skip the last part properly with t.Skip.

What approach do you prefer? I can submit a PR.

Thanks

@thaJeztah
Copy link
Member

@kolyshkin @tonistiigi wdyt?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants