Files
Roger 92053b85b0 chore: update golangci-lint config and fix lint issues (#542)
* chore: update golangci-lint config and fix lint issues
2026-04-04 16:26:07 +08:00

165 lines
4.6 KiB
Go

//go:build windows
package filemanager
import (
"bytes"
"os"
"path/filepath"
"syscall"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCopyLocked_ExclusiveLock(t *testing.T) {
dir := t.TempDir()
src := filepath.Join(dir, "locked.db")
testData := []byte("this is locked file content")
require.NoError(t, os.WriteFile(src, testData, 0o644))
handle := openExclusive(t, src)
defer syscall.CloseHandle(handle)
// Normal copy should fail
err := copyFile(src, filepath.Join(dir, "normal_copy.db"))
require.Error(t, err, "normal copy should fail on exclusively locked file")
// copyLocked should succeed via DuplicateHandle + FileMapping
lockedDst := filepath.Join(dir, "locked_copy.db")
err = copyLocked(src, lockedDst)
require.NoError(t, err, "copyLocked should bypass exclusive lock")
copied, err := os.ReadFile(lockedDst)
require.NoError(t, err)
assert.Equal(t, testData, copied, "copied content should match original")
}
func TestCopyLocked_WriteThenRead(t *testing.T) {
dir := t.TempDir()
src := filepath.Join(dir, "modified.db")
// Write initial data
require.NoError(t, os.WriteFile(src, []byte("initial"), 0o644))
// Open exclusively and write more data through the handle
handle := openExclusive(t, src)
defer syscall.CloseHandle(handle)
// Seek to end and write additional data
_, seekErr := syscall.Seek(handle, 0, 2) // SEEK_END
require.NoError(t, seekErr)
additional := []byte(" + appended data")
var written uint32
writeErr := syscall.WriteFile(handle, additional, &written, nil)
require.NoError(t, writeErr)
require.Equal(t, uint32(len(additional)), written)
flushErr := syscall.FlushFileBuffers(handle)
require.NoError(t, flushErr)
// copyLocked should read the full content including appended data
lockedDst := filepath.Join(dir, "modified_copy.db")
copyErr := copyLocked(src, lockedDst)
require.NoError(t, copyErr)
copied, err := os.ReadFile(lockedDst)
require.NoError(t, err)
assert.Equal(t, "initial + appended data", string(copied),
"should read complete content including data written after lock")
}
func TestCopyLocked_LargeFile(t *testing.T) {
dir := t.TempDir()
src := filepath.Join(dir, "large.db")
// Create a file similar in size to a real Cookies database (~64KB)
data := make([]byte, 65536)
for i := range data {
data[i] = byte(i % 256)
}
require.NoError(t, os.WriteFile(src, data, 0o644))
handle := openExclusive(t, src)
defer syscall.CloseHandle(handle)
lockedDst := filepath.Join(dir, "large_copy.db")
err := copyLocked(src, lockedDst)
require.NoError(t, err)
copied, err := os.ReadFile(lockedDst)
require.NoError(t, err)
assert.Len(t, copied, len(data), "file sizes should match")
assert.True(t, bytes.Equal(data, copied), "file content should match byte-for-byte")
}
func TestCopyLocked_FileNotFound(t *testing.T) {
err := copyLocked("/nonexistent/file.db", filepath.Join(t.TempDir(), "dst.db"))
require.Error(t, err)
}
func TestAcquire_FallbackToLocked(t *testing.T) {
dir := t.TempDir()
src := filepath.Join(dir, "cookies.db")
testData := []byte("cookie data")
require.NoError(t, os.WriteFile(src, testData, 0o644))
handle := openExclusive(t, src)
defer syscall.CloseHandle(handle)
session, err := NewSession()
require.NoError(t, err)
defer session.Cleanup()
dst := filepath.Join(session.TempDir(), "cookies.db")
err = session.Acquire(src, dst, false)
require.NoError(t, err, "Acquire should succeed via locked fallback")
copied, err := os.ReadFile(dst)
require.NoError(t, err)
assert.Equal(t, testData, copied)
}
func TestAcquire_NormalCopyWhenNotLocked(t *testing.T) {
dir := t.TempDir()
src := filepath.Join(dir, "unlocked.db")
testData := []byte("unlocked data")
require.NoError(t, os.WriteFile(src, testData, 0o644))
// No exclusive lock — normal copy should work without needing copyLocked
session, err := NewSession()
require.NoError(t, err)
defer session.Cleanup()
dst := filepath.Join(session.TempDir(), "unlocked.db")
err = session.Acquire(src, dst, false)
require.NoError(t, err)
copied, err := os.ReadFile(dst)
require.NoError(t, err)
assert.Equal(t, testData, copied)
}
// openExclusive opens a file with exclusive lock (dwShareMode=0),
// simulating Chrome's PRAGMA locking_mode=EXCLUSIVE behavior.
func openExclusive(t *testing.T, path string) syscall.Handle {
t.Helper()
srcPtr, err := syscall.UTF16PtrFromString(path)
require.NoError(t, err)
handle, err := syscall.CreateFile(
srcPtr,
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
0, // exclusive: no sharing
nil,
syscall.OPEN_EXISTING,
syscall.FILE_ATTRIBUTE_NORMAL,
0,
)
require.NoError(t, err)
return handle
}