github.com/anuvu/nomad@v0.8.7-atom1/client/driver/logging/rotator_test.go (about) 1 package logging 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "log" 7 "math/rand" 8 "os" 9 "path/filepath" 10 "testing" 11 12 "github.com/hashicorp/nomad/testutil" 13 ) 14 15 var ( 16 logger = log.New(os.Stdout, "", log.LstdFlags) 17 pathPrefix = "logrotator" 18 baseFileName = "redis.stdout" 19 ) 20 21 func TestFileRotator_IncorrectPath(t *testing.T) { 22 t.Parallel() 23 if _, err := NewFileRotator("/foo", baseFileName, 10, 10, logger); err == nil { 24 t.Fatalf("expected error") 25 } 26 } 27 28 func TestFileRotator_CreateNewFile(t *testing.T) { 29 t.Parallel() 30 var path string 31 var err error 32 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 33 t.Fatalf("test setup err: %v", err) 34 } 35 defer os.RemoveAll(path) 36 37 _, err = NewFileRotator(path, baseFileName, 10, 10, logger) 38 if err != nil { 39 t.Fatalf("test setup err: %v", err) 40 } 41 42 if _, err := os.Stat(filepath.Join(path, "redis.stdout.0")); err != nil { 43 t.Fatalf("expected file") 44 } 45 } 46 47 func TestFileRotator_OpenLastFile(t *testing.T) { 48 t.Parallel() 49 var path string 50 var err error 51 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 52 t.Fatalf("test setup err: %v", err) 53 } 54 defer os.RemoveAll(path) 55 56 fname1 := filepath.Join(path, "redis.stdout.0") 57 fname2 := filepath.Join(path, "redis.stdout.2") 58 if _, err := os.Create(fname1); err != nil { 59 t.Fatalf("test setup failure: %v", err) 60 } 61 if _, err := os.Create(fname2); err != nil { 62 t.Fatalf("test setup failure: %v", err) 63 } 64 65 fr, err := NewFileRotator(path, baseFileName, 10, 10, logger) 66 if err != nil { 67 t.Fatalf("test setup err: %v", err) 68 } 69 70 if fr.currentFile.Name() != fname2 { 71 t.Fatalf("expected current file: %v, got: %v", fname2, fr.currentFile.Name()) 72 } 73 } 74 75 func TestFileRotator_WriteToCurrentFile(t *testing.T) { 76 t.Parallel() 77 var path string 78 var err error 79 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 80 t.Fatalf("test setup err: %v", err) 81 } 82 defer os.RemoveAll(path) 83 84 fname1 := filepath.Join(path, "redis.stdout.0") 85 if _, err := os.Create(fname1); err != nil { 86 t.Fatalf("test setup failure: %v", err) 87 } 88 89 fr, err := NewFileRotator(path, baseFileName, 10, 5, logger) 90 if err != nil { 91 t.Fatalf("test setup err: %v", err) 92 } 93 94 fr.Write([]byte("abcde")) 95 96 var actual int64 97 testutil.WaitForResult(func() (bool, error) { 98 fi, err := os.Stat(fname1) 99 if err != nil { 100 return false, err 101 } 102 actual = fi.Size() 103 if actual != 5 { 104 return false, nil 105 } 106 107 return true, nil 108 }, func(err error) { 109 t.Fatalf("expected size: %v, actual: %v", 5, actual) 110 }) 111 } 112 113 func TestFileRotator_RotateFiles(t *testing.T) { 114 t.Parallel() 115 var path string 116 var err error 117 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 118 t.Fatalf("test setup err: %v", err) 119 } 120 defer os.RemoveAll(path) 121 122 fr, err := NewFileRotator(path, baseFileName, 10, 5, logger) 123 if err != nil { 124 t.Fatalf("test setup err: %v", err) 125 } 126 127 str := "abcdefgh" 128 nw, err := fr.Write([]byte(str)) 129 if err != nil { 130 t.Fatalf("got error while writing: %v", err) 131 } 132 133 if nw != len(str) { 134 t.Fatalf("expected %v, got %v", len(str), nw) 135 } 136 137 var lastErr error 138 testutil.WaitForResult(func() (bool, error) { 139 fname1 := filepath.Join(path, "redis.stdout.0") 140 fi, err := os.Stat(fname1) 141 if err != nil { 142 lastErr = err 143 return false, nil 144 } 145 if fi.Size() != 5 { 146 lastErr = fmt.Errorf("expected size: %v, actual: %v", 5, fi.Size()) 147 return false, nil 148 } 149 150 fname2 := filepath.Join(path, "redis.stdout.1") 151 if _, err := os.Stat(fname2); err != nil { 152 lastErr = fmt.Errorf("expected file %v to exist", fname2) 153 return false, nil 154 } 155 156 if fi2, err := os.Stat(fname2); err == nil { 157 if fi2.Size() != 3 { 158 lastErr = fmt.Errorf("expected size: %v, actual: %v", 3, fi2.Size()) 159 return false, nil 160 } 161 } else { 162 lastErr = fmt.Errorf("error getting the file info: %v", err) 163 return false, nil 164 } 165 166 return true, nil 167 }, func(err error) { 168 t.Fatalf("%v", lastErr) 169 }) 170 } 171 172 func TestFileRotator_RotateFiles_Boundary(t *testing.T) { 173 t.Parallel() 174 var path string 175 var err error 176 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 177 t.Fatalf("test setup err: %v", err) 178 } 179 defer os.RemoveAll(path) 180 181 fr, err := NewFileRotator(path, baseFileName, 10, 5, logger) 182 if err != nil { 183 t.Fatalf("test setup err: %v", err) 184 } 185 186 // We will write three times: 187 // 1st: Write with new lines spanning two files 188 // 2nd: Write long string with no new lines 189 // 3rd: Write a single new line 190 expectations := [][]byte{ 191 []byte("ab\n"), 192 []byte("cdef\n"), 193 []byte("12345"), 194 []byte("67890"), 195 []byte("\n"), 196 } 197 198 for _, str := range []string{"ab\ncdef\n", "1234567890", "\n"} { 199 nw, err := fr.Write([]byte(str)) 200 if err != nil { 201 t.Fatalf("got error while writing: %v", err) 202 } 203 204 if nw != len(str) { 205 t.Fatalf("expected %v, got %v", len(str), nw) 206 } 207 } 208 209 var lastErr error 210 testutil.WaitForResult(func() (bool, error) { 211 212 for i, exp := range expectations { 213 fname := filepath.Join(path, fmt.Sprintf("redis.stdout.%d", i)) 214 fi, err := os.Stat(fname) 215 if err != nil { 216 lastErr = err 217 return false, nil 218 } 219 if int(fi.Size()) != len(exp) { 220 lastErr = fmt.Errorf("expected size: %v, actual: %v", len(exp), fi.Size()) 221 return false, nil 222 } 223 } 224 225 return true, nil 226 }, func(err error) { 227 t.Fatalf("%v", lastErr) 228 }) 229 } 230 231 func TestFileRotator_WriteRemaining(t *testing.T) { 232 t.Parallel() 233 var path string 234 var err error 235 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 236 t.Fatalf("test setup err: %v", err) 237 } 238 defer os.RemoveAll(path) 239 240 fname1 := filepath.Join(path, "redis.stdout.0") 241 if f, err := os.Create(fname1); err == nil { 242 f.Write([]byte("abcd")) 243 } else { 244 t.Fatalf("test setup failure: %v", err) 245 } 246 247 fr, err := NewFileRotator(path, baseFileName, 10, 5, logger) 248 if err != nil { 249 t.Fatalf("test setup err: %v", err) 250 } 251 252 str := "efghijkl" 253 nw, err := fr.Write([]byte(str)) 254 if err != nil { 255 t.Fatalf("got error while writing: %v", err) 256 } 257 if nw != len(str) { 258 t.Fatalf("expected %v, got %v", len(str), nw) 259 } 260 var lastErr error 261 testutil.WaitForResult(func() (bool, error) { 262 fi, err := os.Stat(fname1) 263 if err != nil { 264 lastErr = fmt.Errorf("error getting the file info: %v", err) 265 return false, nil 266 } 267 if fi.Size() != 5 { 268 lastErr = fmt.Errorf("expected size: %v, actual: %v", 5, fi.Size()) 269 return false, nil 270 } 271 272 fname2 := filepath.Join(path, "redis.stdout.1") 273 if _, err := os.Stat(fname2); err != nil { 274 lastErr = fmt.Errorf("expected file %v to exist", fname2) 275 return false, nil 276 } 277 278 if fi2, err := os.Stat(fname2); err == nil { 279 if fi2.Size() != 5 { 280 lastErr = fmt.Errorf("expected size: %v, actual: %v", 5, fi2.Size()) 281 return false, nil 282 } 283 } else { 284 lastErr = fmt.Errorf("error getting the file info: %v", err) 285 return false, nil 286 } 287 288 fname3 := filepath.Join(path, "redis.stdout.2") 289 if _, err := os.Stat(fname3); err != nil { 290 lastErr = fmt.Errorf("expected file %v to exist", fname3) 291 return false, nil 292 } 293 294 if fi3, err := os.Stat(fname3); err == nil { 295 if fi3.Size() != 2 { 296 lastErr = fmt.Errorf("expected size: %v, actual: %v", 2, fi3.Size()) 297 return false, nil 298 } 299 } else { 300 lastErr = fmt.Errorf("error getting the file info: %v", err) 301 return false, nil 302 } 303 304 return true, nil 305 }, func(err error) { 306 t.Fatalf("%v", lastErr) 307 }) 308 309 } 310 311 func TestFileRotator_PurgeOldFiles(t *testing.T) { 312 t.Parallel() 313 var path string 314 var err error 315 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 316 t.Fatalf("test setup err: %v", err) 317 } 318 defer os.RemoveAll(path) 319 320 fr, err := NewFileRotator(path, baseFileName, 2, 2, logger) 321 if err != nil { 322 t.Fatalf("test setup err: %v", err) 323 } 324 325 str := "abcdeghijklmn" 326 nw, err := fr.Write([]byte(str)) 327 if err != nil { 328 t.Fatalf("got error while writing: %v", err) 329 } 330 if nw != len(str) { 331 t.Fatalf("expected %v, got %v", len(str), nw) 332 } 333 334 var lastErr error 335 testutil.WaitForResult(func() (bool, error) { 336 f, err := ioutil.ReadDir(path) 337 if err != nil { 338 lastErr = fmt.Errorf("test error: %v", err) 339 return false, nil 340 } 341 342 if len(f) != 2 { 343 lastErr = fmt.Errorf("expected number of files: %v, got: %v", 2, len(f)) 344 return false, nil 345 } 346 347 return true, nil 348 }, func(err error) { 349 t.Fatalf("%v", lastErr) 350 }) 351 } 352 353 func BenchmarkRotator(b *testing.B) { 354 kb := 1024 355 for _, inputSize := range []int{kb, 2 * kb, 4 * kb, 8 * kb, 16 * kb, 32 * kb, 64 * kb, 128 * kb, 256 * kb} { 356 b.Run(fmt.Sprintf("%dKB", inputSize/kb), func(b *testing.B) { 357 benchmarkRotatorWithInputSize(inputSize, b) 358 }) 359 } 360 } 361 362 func benchmarkRotatorWithInputSize(size int, b *testing.B) { 363 var path string 364 var err error 365 if path, err = ioutil.TempDir("", pathPrefix); err != nil { 366 b.Fatalf("test setup err: %v", err) 367 } 368 defer os.RemoveAll(path) 369 370 fr, err := NewFileRotator(path, baseFileName, 5, 1024*1024, logger) 371 if err != nil { 372 b.Fatalf("test setup err: %v", err) 373 } 374 b.ResetTimer() 375 376 // run the Fib function b.N times 377 for n := 0; n < b.N; n++ { 378 // Generate some input 379 data := make([]byte, size) 380 _, err := rand.Read(data) 381 if err != nil { 382 b.Fatalf("Error generating date: %v", err) 383 } 384 385 // Insert random new lines 386 for i := 0; i < 100; i++ { 387 index := rand.Intn(size) 388 data[index] = '\n' 389 } 390 391 // Write the data 392 if _, err := fr.Write(data); err != nil { 393 b.Fatalf("Failed to write data: %v", err) 394 } 395 } 396 }