atomic_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package osutil
  7. import (
  8. "bytes"
  9. "os"
  10. "path/filepath"
  11. "testing"
  12. )
  13. func TestCreateAtomicCreate(t *testing.T) {
  14. os.RemoveAll("testdata")
  15. defer os.RemoveAll("testdata")
  16. if err := os.Mkdir("testdata", 0o755); err != nil {
  17. t.Fatal(err)
  18. }
  19. w, err := CreateAtomic("testdata/file")
  20. if err != nil {
  21. t.Fatal(err)
  22. }
  23. n, err := w.Write([]byte("hello"))
  24. if err != nil {
  25. t.Fatal(err)
  26. }
  27. if n != 5 {
  28. t.Fatal("written bytes", n, "!= 5")
  29. }
  30. if _, err := os.ReadFile("testdata/file"); err == nil {
  31. t.Fatal("file should not exist")
  32. }
  33. if err := w.Close(); err != nil {
  34. t.Fatal(err)
  35. }
  36. bs, err := os.ReadFile("testdata/file")
  37. if err != nil {
  38. t.Fatal(err)
  39. }
  40. if !bytes.Equal(bs, []byte("hello")) {
  41. t.Error("incorrect data")
  42. }
  43. }
  44. func TestCreateAtomicReplace(t *testing.T) {
  45. testCreateAtomicReplace(t, 0o666)
  46. }
  47. func TestCreateAtomicReplaceReadOnly(t *testing.T) {
  48. testCreateAtomicReplace(t, 0o444) // windows compatible read-only bits
  49. }
  50. func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
  51. t.Helper()
  52. testdir := t.TempDir()
  53. testfile := filepath.Join(testdir, "testfile")
  54. os.RemoveAll(testdir)
  55. if err := os.Mkdir(testdir, 0o755); err != nil {
  56. t.Fatal(err)
  57. }
  58. if err := os.WriteFile(testfile, []byte("some old data"), oldPerms); err != nil {
  59. t.Fatal(err)
  60. }
  61. // Go < 1.14 has a bug in WriteFile where it does not use the requested
  62. // permissions on Windows. Chmod to make sure.
  63. if err := os.Chmod(testfile, oldPerms); err != nil {
  64. t.Fatal(err)
  65. }
  66. // Trust, but verify.
  67. if info, err := os.Stat(testfile); err != nil {
  68. t.Fatal(err)
  69. } else if info.Mode() != oldPerms {
  70. t.Fatalf("Wrong perms 0%o", info.Mode())
  71. }
  72. w, err := CreateAtomic(testfile)
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. if _, err := w.Write([]byte("hello")); err != nil {
  77. t.Fatal(err)
  78. }
  79. if err := w.Close(); err != nil {
  80. t.Fatal(err)
  81. }
  82. bs, err := os.ReadFile(testfile)
  83. if err != nil {
  84. t.Fatal(err)
  85. }
  86. if !bytes.Equal(bs, []byte("hello")) {
  87. t.Error("incorrect data")
  88. }
  89. if info, err := os.Stat(testfile); err != nil {
  90. t.Fatal(err)
  91. } else if info.Mode() != oldPerms {
  92. t.Fatalf("Perms changed during atomic write: 0%o", info.Mode())
  93. }
  94. }