diff --git a/test/fuse_integration/POSIX_COMPLIANCE.md b/test/fuse_integration/POSIX_COMPLIANCE.md index b623ebae9..b166870e7 100644 --- a/test/fuse_integration/POSIX_COMPLIANCE.md +++ b/test/fuse_integration/POSIX_COMPLIANCE.md @@ -415,7 +415,7 @@ jobs: make -f posix_Makefile ci-posix-tests - name: Upload Test Results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: name: posix-test-results diff --git a/test/fuse_integration/atime_linux.go b/test/fuse_integration/atime_linux.go new file mode 100644 index 000000000..9d8e9579a --- /dev/null +++ b/test/fuse_integration/atime_linux.go @@ -0,0 +1,12 @@ +//go:build linux + +package fuse + +import ( + "syscall" +) + +// getAtimeNano returns the access time in nanoseconds for Linux systems +func getAtimeNano(stat *syscall.Stat_t) int64 { + return stat.Atim.Sec*1e9 + stat.Atim.Nsec +} diff --git a/test/fuse_integration/atime_nonlinux.go b/test/fuse_integration/atime_nonlinux.go new file mode 100644 index 000000000..6bafa4cd4 --- /dev/null +++ b/test/fuse_integration/atime_nonlinux.go @@ -0,0 +1,12 @@ +//go:build !linux + +package fuse + +import ( + "syscall" +) + +// getAtimeNano returns the access time in nanoseconds for non-Linux systems (macOS, BSD, etc.) +func getAtimeNano(stat *syscall.Stat_t) int64 { + return stat.Atimespec.Sec*1e9 + stat.Atimespec.Nsec +} diff --git a/test/fuse_integration/posix_Makefile b/test/fuse_integration/posix_Makefile index 0d959bace..95e815edf 100644 --- a/test/fuse_integration/posix_Makefile +++ b/test/fuse_integration/posix_Makefile @@ -263,9 +263,9 @@ create-fio-configs: setup-reports # Reporting and analysis generate-report: setup-reports @echo "$(BLUE)[REPORT] Generating comprehensive POSIX compliance report...$(RESET)" - @$(MAKE) -f posix_Makefile generate-html-report - @$(MAKE) -f posix_Makefile generate-text-report - @$(MAKE) -f posix_Makefile generate-json-report + @$(MAKE) generate-html-report + @$(MAKE) generate-text-report + @$(MAKE) generate-json-report generate-html-report: @echo "$(BLUE)[REPORT] Generating HTML report...$(RESET)" diff --git a/test/fuse_integration/posix_compliance_test.go b/test/fuse_integration/posix_compliance_test.go index b26bb815e..5cb782d26 100644 --- a/test/fuse_integration/posix_compliance_test.go +++ b/test/fuse_integration/posix_compliance_test.go @@ -326,33 +326,10 @@ func (s *POSIXComplianceTestSuite) TestTimestamps(t *testing.T) { require.NoError(t, err) // Access time should have been updated, and modification time should be unchanged. - // Note: Some filesystems may not update atime on read due to noatime mount options - // We'll focus on ensuring modification time is not affected by reads - require.Equal(t, stat1.ModTime(), stat2.ModTime(), "modification time should not change on read") - - // For access time, we use a cross-platform approach stat1Sys := stat1.Sys().(*syscall.Stat_t) stat2Sys := stat2.Sys().(*syscall.Stat_t) - - // Get access time in nanoseconds - handle different field names across platforms - var atime1, atime2 int64 - - // Try different field names based on platform - if hasAtimespec(stat1Sys) { - // macOS and some other systems use Atimespec - atime1 = getAtimespecNano(stat1Sys) - atime2 = getAtimespecNano(stat2Sys) - } else { - // Linux and others may use different field names - // For now, we'll skip detailed atime testing on unsupported platforms - atime1 = 0 - atime2 = 0 - } - - // Access time should be >= original (or filesystem may not update it due to noatime) - if atime1 > 0 && atime2 > 0 { - require.True(t, atime2 >= atime1, "access time should be updated or stay the same") - } + require.True(t, getAtimeNano(stat2Sys) >= getAtimeNano(stat1Sys), "access time should be updated or stay the same") + require.Equal(t, stat1.ModTime(), stat2.ModTime(), "modification time should not change on read") }) t.Run("ModificationTime", func(t *testing.T) { @@ -472,6 +449,36 @@ func (s *POSIXComplianceTestSuite) TestIOOperations(t *testing.T) { require.Equal(t, 1, n) require.Equal(t, []byte("A"), buffer) + // Test positioned I/O operations (pread/pwrite) + syscall.Close(fd) + + // Open for read/write to test pwrite + fd, err = syscall.Open(testFile, syscall.O_RDWR, 0) + require.NoError(t, err) + defer syscall.Close(fd) + + // Positioned write test + writeData := []byte("XYZ") + n, err = syscall.Pwrite(fd, writeData, 5) // pwrite at offset 5 + require.NoError(t, err) + require.Equal(t, len(writeData), n) + + // Verify file position is unchanged by pwrite + currentPos, err := syscall.Seek(fd, 0, 1) // SEEK_CUR + require.NoError(t, err) + require.Equal(t, int64(0), currentPos, "file offset should not be changed by pwrite") + + // Read back with pread + readBuffer := make([]byte, len(writeData)) + n, err = syscall.Pread(fd, readBuffer, 5) // pread at offset 5 + require.NoError(t, err) + require.Equal(t, len(writeData), n) + require.Equal(t, writeData, readBuffer) + + // Verify file position is still unchanged by pread + currentPos, err = syscall.Seek(fd, 0, 1) // SEEK_CUR + require.NoError(t, err) + require.Equal(t, int64(0), currentPos, "file offset should not be changed by pread") }) t.Run("AppendMode", func(t *testing.T) { @@ -626,7 +633,7 @@ func (s *POSIXComplianceTestSuite) TestConcurrentAccess(t *testing.T) { } }) - t.Run("ConcurrentFileCreations", func(t *testing.T) { + t.Run("ConcurrentWrites", func(t *testing.T) { testFile := filepath.Join(mountPoint, "concurrent_write.txt") // Launch multiple concurrent writers @@ -699,14 +706,3 @@ func (s *POSIXComplianceTestSuite) TestErrorHandling(t *testing.T) { require.True(t, os.IsPermission(err)) }) } - -// Cross-platform helper functions for access time handling -func hasAtimespec(stat *syscall.Stat_t) bool { - // Always return true for now - we'll handle platform differences in getAtimespecNano - return true -} - -func getAtimespecNano(stat *syscall.Stat_t) int64 { - // Use the field that exists on this platform - return stat.Atimespec.Sec*1e9 + stat.Atimespec.Nsec -}