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