github.com/vlifesystems/rulehunter@v0.0.0-20180501090014-673078aa4a83/watcher/watcher_test.go (about) 1 package watcher 2 3 import ( 4 "fmt" 5 "github.com/vlifesystems/rulehunter/fileinfo" 6 "github.com/vlifesystems/rulehunter/internal/testhelpers" 7 "github.com/vlifesystems/rulehunter/quitter" 8 "os" 9 "path/filepath" 10 "reflect" 11 "sort" 12 "testing" 13 "time" 14 ) 15 16 // Test initial filenames 17 func TestWatch_1(t *testing.T) { 18 tmpDir := testhelpers.TempDir(t) 19 defer os.RemoveAll(tmpDir) 20 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir) 21 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir) 22 testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir) 23 24 files := make(chan fileinfo.FileInfo, 100) 25 logger := testhelpers.NewLogger() 26 quit := quitter.New() 27 period := 50 * time.Millisecond 28 go logger.Run(quit) 29 go Watch(tmpDir, period, logger, quit, files) 30 time.Sleep(200 * time.Millisecond) 31 quit.Quit() 32 33 wantNewFiles := map[string]int{ 34 "debt.json": 1, 35 "debt.yaml": 1, 36 "flow.yaml": 1, 37 } 38 wantNonNewFiles := map[string]int{ 39 "debt.json": 2, 40 "debt.yaml": 2, 41 "flow.yaml": 2, 42 } 43 err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files) 44 if err != nil { 45 t.Error("Watch:", err) 46 } 47 48 if logEntries := logger.GetEntries(); len(logEntries) != 0 { 49 t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries) 50 } 51 } 52 53 // Test adding a filename to directory 54 func TestWatch_2(t *testing.T) { 55 tmpDir := testhelpers.TempDir(t) 56 defer os.RemoveAll(tmpDir) 57 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir) 58 testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir) 59 60 files := make(chan fileinfo.FileInfo, 100) 61 logger := testhelpers.NewLogger() 62 quit := quitter.New() 63 period := 50 * time.Millisecond 64 go logger.Run(quit) 65 go Watch(tmpDir, period, logger, quit, files) 66 time.Sleep(100 * time.Millisecond) 67 68 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir) 69 time.Sleep(60 * time.Millisecond) 70 quit.Quit() 71 72 wantNewFiles := map[string]int{ 73 "debt.json": 1, 74 "debt.yaml": 1, 75 "flow.yaml": 1, 76 } 77 wantNonNewFiles := map[string]int{ 78 "debt.json": 2, 79 "flow.yaml": 2, 80 "debt.yaml": 0, 81 } 82 err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files) 83 if err != nil { 84 t.Error("Watch:", err) 85 } 86 if logEntries := logger.GetEntries(); len(logEntries) != 0 { 87 t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries) 88 } 89 } 90 91 // Test changing a file 92 func TestWatch_3(t *testing.T) { 93 tmpDir := testhelpers.TempDir(t) 94 defer os.RemoveAll(tmpDir) 95 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir) 96 testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir) 97 98 files := make(chan fileinfo.FileInfo, 100) 99 logger := testhelpers.NewLogger() 100 quit := quitter.New() 101 period := 50 * time.Millisecond 102 go logger.Run(quit) 103 go Watch(tmpDir, period, logger, quit, files) 104 time.Sleep(100 * time.Millisecond) 105 106 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir) 107 time.Sleep(100 * time.Millisecond) 108 quit.Quit() 109 110 wantNewFiles := map[string]int{ 111 "debt.json": 2, 112 "flow.yaml": 1, 113 } 114 wantNonNewFiles := map[string]int{ 115 "debt.json": 1, 116 "flow.yaml": 2, 117 } 118 err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files) 119 if err != nil { 120 t.Error("Watch:", err) 121 } 122 if logEntries := logger.GetEntries(); len(logEntries) != 0 { 123 t.Errorf("Watch: gotLogEntries: %v, wanted: []", logEntries) 124 } 125 } 126 127 func TestWatch_errors(t *testing.T) { 128 tmpDir := testhelpers.TempDir(t) 129 os.RemoveAll(tmpDir) 130 dir := filepath.Join(tmpDir, "non") 131 files := make(chan fileinfo.FileInfo, 100) 132 logger := testhelpers.NewLogger() 133 quit := quitter.New() 134 period := 50 * time.Millisecond 135 go logger.Run(quit) 136 go Watch(dir, period, logger, quit, files) 137 time.Sleep(100 * time.Millisecond) 138 quit.Quit() 139 140 wantNewFiles := map[string]int{} 141 wantNonNewFiles := map[string]int{} 142 wantLogEntries := []testhelpers.Entry{ 143 testhelpers.Entry{ 144 Level: testhelpers.Error, 145 Msg: DirError(dir).Error(), 146 }, 147 } 148 149 err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files) 150 if err != nil { 151 t.Error("Watch:", err) 152 } 153 if !reflect.DeepEqual(wantLogEntries, logger.GetEntries()) { 154 t.Errorf("Watch: gotLogEntries: %v, want: %v", 155 logger.GetEntries(), wantLogEntries) 156 } 157 } 158 159 // Test a directory being removed part way through watching 160 func TestWatch_errors2(t *testing.T) { 161 tmpDir := testhelpers.TempDir(t) 162 files := make(chan fileinfo.FileInfo, 100) 163 logger := testhelpers.NewLogger() 164 quit := quitter.New() 165 period := 50 * time.Millisecond 166 go logger.Run(quit) 167 go Watch(tmpDir, period, logger, quit, files) 168 time.Sleep(100 * time.Millisecond) 169 170 os.RemoveAll(tmpDir) 171 time.Sleep(100 * time.Millisecond) 172 quit.Quit() 173 174 wantNewFiles := map[string]int{} 175 wantNonNewFiles := map[string]int{} 176 wantLogEntries := []testhelpers.Entry{ 177 testhelpers.Entry{ 178 Level: testhelpers.Error, 179 Msg: DirError(tmpDir).Error(), 180 }, 181 } 182 183 err := checkCorrectFileChan(wantNewFiles, wantNonNewFiles, files) 184 if err != nil { 185 t.Error("Watch:", err) 186 } 187 if !reflect.DeepEqual(wantLogEntries, logger.GetEntries()) { 188 t.Errorf("Watch: gotLogEntries: %v, want: %v", 189 logger.GetEntries(), wantLogEntries) 190 } 191 } 192 193 func TestGetExperimentFilenames(t *testing.T) { 194 tmpDir := testhelpers.TempDir(t) 195 defer os.RemoveAll(tmpDir) 196 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.json"), tmpDir) 197 testhelpers.CopyFile(t, filepath.Join("fixtures", "debt.yaml"), tmpDir) 198 testhelpers.CopyFile(t, filepath.Join("fixtures", "flow.yaml"), tmpDir) 199 testhelpers.CopyFile( 200 t, 201 filepath.Join("fixtures", "flow.yaml"), 202 tmpDir, 203 "flow.txt", 204 ) 205 206 wantFiles := []string{"debt.json", "debt.yaml", "flow.yaml"} 207 gotFiles, err := GetExperimentFiles(tmpDir) 208 if err != nil { 209 t.Fatalf("GetExperimentFilenames: %v", err) 210 } 211 if err := checkCorrectFiles(gotFiles, wantFiles); err != nil { 212 t.Error("GetExperimentFiles:", err) 213 } 214 } 215 216 func TestGetExperimentFilenames_errors(t *testing.T) { 217 tmpDir := testhelpers.TempDir(t) 218 defer os.RemoveAll(tmpDir) 219 dir := filepath.Join(tmpDir, "non") 220 wantFiles := []string{} 221 wantErr := DirError(dir) 222 gotFiles, err := GetExperimentFiles(dir) 223 if err == nil || err.Error() != wantErr.Error() { 224 t.Fatalf("GetExperimentFilenames: gotErr: %v, wantErr: %v", err, wantErr) 225 } 226 227 if err := checkCorrectFiles(gotFiles, wantFiles); err != nil { 228 t.Error("GetExperimentFiles:", err) 229 } 230 } 231 232 func TestDirErrorError(t *testing.T) { 233 dir := "/tmp/someplace" 234 want := "can not watch directory: /tmp/someplace" 235 got := DirError(dir).Error() 236 if got != want { 237 t.Errorf("Error: got: %s, want: %s", got, want) 238 } 239 } 240 241 /********************************* 242 * Helper functions 243 *********************************/ 244 func checkCorrectFiles( 245 gotFiles []fileinfo.FileInfo, 246 wantFilenames []string, 247 ) error { 248 allFilenames := []string{} 249 for _, file := range gotFiles { 250 allFilenames = append(allFilenames, file.Name()) 251 } 252 if len(allFilenames) != len(wantFilenames) { 253 return fmt.Errorf("gotFiles: %v, wantFilenames: %v", 254 allFilenames, wantFilenames) 255 } 256 sort.Strings(allFilenames) 257 sort.Strings(wantFilenames) 258 if !reflect.DeepEqual(allFilenames, wantFilenames) { 259 return fmt.Errorf("gotFiles: %v, wantFilenames: %v", 260 allFilenames, wantFilenames) 261 } 262 return nil 263 } 264 265 // The int in the maps below indicates that has been seen at least x times 266 func checkCorrectFileChan( 267 wantNewFiles map[string]int, 268 wantNonNewFiles map[string]int, 269 files <-chan fileinfo.FileInfo, 270 ) error { 271 allFiles := []fileinfo.FileInfo{} 272 gotNewFiles := map[string]int{} 273 gotNonNewFiles := map[string]int{} 274 for file := range files { 275 isNew := true 276 for _, f := range allFiles { 277 if fileinfo.IsEqual(file, f) { 278 isNew = false 279 break 280 } 281 } 282 if isNew { 283 gotNewFiles[file.Name()]++ 284 } else { 285 gotNonNewFiles[file.Name()]++ 286 } 287 allFiles = append(allFiles, file) 288 } 289 if len(gotNewFiles) != len(wantNewFiles) { 290 return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v", 291 gotNewFiles, wantNewFiles) 292 } 293 if len(gotNewFiles) > len(wantNewFiles) { 294 return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v", 295 gotNewFiles, wantNewFiles) 296 } 297 for name, n := range wantNewFiles { 298 if n > gotNewFiles[name] { 299 return fmt.Errorf("gotNewFiles: %v, wantNewFiles: %v", 300 gotNewFiles, wantNewFiles) 301 } 302 } 303 if len(gotNonNewFiles) > len(wantNonNewFiles) { 304 return fmt.Errorf("gotNonNewFiles: %v, wantNonNewFiles: %v", 305 gotNonNewFiles, wantNonNewFiles) 306 } 307 for name, n := range wantNonNewFiles { 308 if n > gotNonNewFiles[name] { 309 return fmt.Errorf("gotNonNewFiles: %v, wantNonNewFiles: %v", 310 gotNonNewFiles, wantNonNewFiles) 311 } 312 } 313 return nil 314 }