syncthing/lib/osutil/atomic_test.go
Jakob Borg 59b1b0e1dc
lib/osutil: Fix "atomic" rename on Windows (ref #6495, ref #6493) (#6510)
So, in a funny plot twist, it turns out that WriteFile in Go 1.13
doesn't actually set the read only bit on Windows when called with
permissions 0444 so my test was broken. With an improved test it turns
out that Rename does not, in fact, overwrite a read-only file on
Windows. This adds a fix for that.

(Rename might get improved in Go 1.15...)
2020-04-07 15:38:55 +02:00

114 lines
2.3 KiB
Go

// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package osutil
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestCreateAtomicCreate(t *testing.T) {
os.RemoveAll("testdata")
defer os.RemoveAll("testdata")
if err := os.Mkdir("testdata", 0755); err != nil {
t.Fatal(err)
}
w, err := CreateAtomic("testdata/file")
if err != nil {
t.Fatal(err)
}
n, err := w.Write([]byte("hello"))
if err != nil {
t.Fatal(err)
}
if n != 5 {
t.Fatal("written bytes", n, "!= 5")
}
if _, err := ioutil.ReadFile("testdata/file"); err == nil {
t.Fatal("file should not exist")
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
bs, err := ioutil.ReadFile("testdata/file")
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(bs, []byte("hello")) {
t.Error("incorrect data")
}
}
func TestCreateAtomicReplace(t *testing.T) {
testCreateAtomicReplace(t, 0666)
}
func TestCreateAtomicReplaceReadOnly(t *testing.T) {
testCreateAtomicReplace(t, 0444) // windows compatible read-only bits
}
func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
t.Helper()
testdir, err := ioutil.TempDir("", "syncthing")
if err != nil {
t.Fatal(err)
}
testfile := filepath.Join(testdir, "testfile")
os.RemoveAll(testdir)
defer os.RemoveAll(testdir)
if err := os.Mkdir(testdir, 0755); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(testfile, []byte("some old data"), oldPerms); err != nil {
t.Fatal(err)
}
// Go < 1.14 has a bug in WriteFile where it does not use the requested
// permissions on Windows. Chmod to make sure.
if err := os.Chmod(testfile, oldPerms); err != nil {
t.Fatal(err)
}
// Trust, but verify.
if info, err := os.Stat(testfile); err != nil {
t.Fatal(err)
} else if info.Mode() != oldPerms {
t.Fatalf("Wrong perms 0%o", info.Mode())
}
w, err := CreateAtomic(testfile)
if err != nil {
t.Fatal(err)
}
if _, err := w.Write([]byte("hello")); err != nil {
t.Fatal(err)
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
bs, err := ioutil.ReadFile(testfile)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(bs, []byte("hello")) {
t.Error("incorrect data")
}
}