purge_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2015 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package fileutil
  15. import (
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "path/filepath"
  20. "reflect"
  21. "testing"
  22. "time"
  23. "go.uber.org/zap"
  24. )
  25. func TestPurgeFile(t *testing.T) {
  26. dir, err := ioutil.TempDir("", "purgefile")
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. defer os.RemoveAll(dir)
  31. // minimal file set
  32. for i := 0; i < 3; i++ {
  33. f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i)))
  34. if ferr != nil {
  35. t.Fatal(err)
  36. }
  37. f.Close()
  38. }
  39. stop, purgec := make(chan struct{}), make(chan string, 10)
  40. // keep 3 most recent files
  41. errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec)
  42. select {
  43. case f := <-purgec:
  44. t.Errorf("unexpected purge on %q", f)
  45. case <-time.After(10 * time.Millisecond):
  46. }
  47. // rest of the files
  48. for i := 4; i < 10; i++ {
  49. go func(n int) {
  50. f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", n)))
  51. if ferr != nil {
  52. t.Error(err)
  53. }
  54. f.Close()
  55. }(i)
  56. }
  57. // watch files purge away
  58. for i := 4; i < 10; i++ {
  59. select {
  60. case <-purgec:
  61. case <-time.After(time.Second):
  62. t.Errorf("purge took too long")
  63. }
  64. }
  65. fnames, rerr := ReadDir(dir)
  66. if rerr != nil {
  67. t.Fatal(rerr)
  68. }
  69. wnames := []string{"7.test", "8.test", "9.test"}
  70. if !reflect.DeepEqual(fnames, wnames) {
  71. t.Errorf("filenames = %v, want %v", fnames, wnames)
  72. }
  73. // no error should be reported from purge routine
  74. select {
  75. case f := <-purgec:
  76. t.Errorf("unexpected purge on %q", f)
  77. case err := <-errch:
  78. t.Errorf("unexpected purge error %v", err)
  79. case <-time.After(10 * time.Millisecond):
  80. }
  81. close(stop)
  82. }
  83. func TestPurgeFileHoldingLockFile(t *testing.T) {
  84. dir, err := ioutil.TempDir("", "purgefile")
  85. if err != nil {
  86. t.Fatal(err)
  87. }
  88. defer os.RemoveAll(dir)
  89. for i := 0; i < 10; i++ {
  90. var f *os.File
  91. f, err = os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i)))
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. f.Close()
  96. }
  97. // create a purge barrier at 5
  98. p := filepath.Join(dir, fmt.Sprintf("%d.test", 5))
  99. l, err := LockFile(p, os.O_WRONLY, PrivateFileMode)
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. stop, purgec := make(chan struct{}), make(chan string, 10)
  104. errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec)
  105. for i := 0; i < 5; i++ {
  106. select {
  107. case <-purgec:
  108. case <-time.After(time.Second):
  109. t.Fatalf("purge took too long")
  110. }
  111. }
  112. fnames, rerr := ReadDir(dir)
  113. if rerr != nil {
  114. t.Fatal(rerr)
  115. }
  116. wnames := []string{"5.test", "6.test", "7.test", "8.test", "9.test"}
  117. if !reflect.DeepEqual(fnames, wnames) {
  118. t.Errorf("filenames = %v, want %v", fnames, wnames)
  119. }
  120. select {
  121. case s := <-purgec:
  122. t.Errorf("unexpected purge %q", s)
  123. case err = <-errch:
  124. t.Errorf("unexpected purge error %v", err)
  125. case <-time.After(10 * time.Millisecond):
  126. }
  127. // remove the purge barrier
  128. if err = l.Close(); err != nil {
  129. t.Fatal(err)
  130. }
  131. // wait for rest of purges (5, 6)
  132. for i := 0; i < 2; i++ {
  133. select {
  134. case <-purgec:
  135. case <-time.After(time.Second):
  136. t.Fatalf("purge took too long")
  137. }
  138. }
  139. fnames, rerr = ReadDir(dir)
  140. if rerr != nil {
  141. t.Fatal(rerr)
  142. }
  143. wnames = []string{"7.test", "8.test", "9.test"}
  144. if !reflect.DeepEqual(fnames, wnames) {
  145. t.Errorf("filenames = %v, want %v", fnames, wnames)
  146. }
  147. select {
  148. case f := <-purgec:
  149. t.Errorf("unexpected purge on %q", f)
  150. case err := <-errch:
  151. t.Errorf("unexpected purge error %v", err)
  152. case <-time.After(10 * time.Millisecond):
  153. }
  154. close(stop)
  155. }