atomic_test.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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", 0755); 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, 0666)
  46. }
  47. func TestCreateAtomicReplaceReadOnly(t *testing.T) {
  48. testCreateAtomicReplace(t, 0444) // windows compatible read-only bits
  49. }
  50. func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
  51. t.Helper()
  52. testdir, err := os.MkdirTemp("", "syncthing")
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. testfile := filepath.Join(testdir, "testfile")
  57. os.RemoveAll(testdir)
  58. defer os.RemoveAll(testdir)
  59. if err := os.Mkdir(testdir, 0755); err != nil {
  60. t.Fatal(err)
  61. }
  62. if err := os.WriteFile(testfile, []byte("some old data"), oldPerms); err != nil {
  63. t.Fatal(err)
  64. }
  65. // Go < 1.14 has a bug in WriteFile where it does not use the requested
  66. // permissions on Windows. Chmod to make sure.
  67. if err := os.Chmod(testfile, oldPerms); err != nil {
  68. t.Fatal(err)
  69. }
  70. // Trust, but verify.
  71. if info, err := os.Stat(testfile); err != nil {
  72. t.Fatal(err)
  73. } else if info.Mode() != oldPerms {
  74. t.Fatalf("Wrong perms 0%o", info.Mode())
  75. }
  76. w, err := CreateAtomic(testfile)
  77. if err != nil {
  78. t.Fatal(err)
  79. }
  80. if _, err := w.Write([]byte("hello")); err != nil {
  81. t.Fatal(err)
  82. }
  83. if err := w.Close(); err != nil {
  84. t.Fatal(err)
  85. }
  86. bs, err := os.ReadFile(testfile)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. if !bytes.Equal(bs, []byte("hello")) {
  91. t.Error("incorrect data")
  92. }
  93. if info, err := os.Stat(testfile); err != nil {
  94. t.Fatal(err)
  95. } else if info.Mode() != oldPerms {
  96. t.Fatalf("Perms changed during atomic write: 0%o", info.Mode())
  97. }
  98. }