github.com/Aoi-hosizora/ahlib-more@v1.5.1-0.20230404072844-256112befaf6/xrotation/xrotation_test.go (about) 1 package xrotation 2 3 import ( 4 "fmt" 5 "github.com/Aoi-hosizora/ahlib/xtesting" 6 "github.com/Aoi-hosizora/ahlib/xtime" 7 "io/ioutil" 8 "log" 9 "os" 10 "path/filepath" 11 "testing" 12 "time" 13 ) 14 15 func TestOptions(t *testing.T) { 16 t.Run("errors", func(t *testing.T) { 17 _, err := New("") 18 xtesting.NotNil(t, err) 19 _, err = New("test.log") 20 xtesting.Nil(t, err) 21 _, err = New("test.log%") 22 xtesting.NotNil(t, err) 23 _, err = New("[x-]", WithForceNewFile(true)) 24 xtesting.NotNil(t, err) 25 _, err = New("test.log", WithRotationMaxAge(1), WithRotationMaxCount(0)) 26 xtesting.Nil(t, err) 27 _, err = New("test.log", WithRotationMaxAge(0), WithRotationMaxCount(1)) 28 xtesting.Nil(t, err) 29 _, err = New("test.log", WithRotationMaxAge(1), WithRotationMaxCount(1)) 30 xtesting.NotNil(t, err) 31 }) 32 33 t.Run("values", func(t *testing.T) { 34 rl, err := New("test.log") 35 xtesting.Nil(t, err) 36 xtesting.Equal(t, rl.namePattern, "test.log") 37 xtesting.Equal(t, rl.globPattern, "test.log") 38 xtesting.Equal(t, rl.option.symlinkFilename, "") 39 xtesting.Equal(t, xtime.LocationDuration(rl.option.nowClock.Now().Location()), xtime.LocationDuration(time.Local)) 40 xtesting.Equal(t, rl.option.forceNewFile, false) 41 xtesting.Equal(t, rl.option.rotationTime, 24*time.Hour) 42 xtesting.Equal(t, rl.option.rotationSize, int64(0)) 43 xtesting.Equal(t, rl.option.rotationMaxAge, 7*24*time.Hour) 44 xtesting.Equal(t, rl.option.rotationMaxCount, int32(0)) 45 46 rl, err = New( 47 "x", WithSymlinkFilename(""), WithSymlinkFilename("test.curr.log"), WithClock(nil), 48 WithForceNewFile(false), WithRotationTime(-1), WithRotationSize(-1), WithRotationMaxAge(-1), WithRotationMaxCount(-1), 49 ) 50 xtesting.Nil(t, err) 51 xtesting.Equal(t, rl.namePattern, "x") 52 xtesting.Equal(t, rl.globPattern, "x") 53 xtesting.Equal(t, rl.option.symlinkFilename, "test.curr.log") 54 xtesting.Equal(t, xtime.LocationDuration(rl.option.nowClock.Now().Location()), xtime.LocationDuration(time.Local)) 55 xtesting.Equal(t, rl.option.forceNewFile, false) 56 xtesting.Equal(t, rl.option.rotationTime, 24*time.Hour) 57 xtesting.Equal(t, rl.option.rotationSize, int64(0)) 58 xtesting.Equal(t, rl.option.rotationMaxAge, 7*24*time.Hour) 59 xtesting.Equal(t, rl.option.rotationMaxCount, int32(0)) 60 61 rl, err = New( 62 "test-%Y%m%d.log", WithSymlinkFilename(""), WithClock(xtime.UTC), WithForceNewFile(true), 63 WithRotationTime(time.Hour), WithRotationSize(256), WithRotationMaxAge(time.Hour*15*24), WithRotationMaxCount(0), 64 ) 65 xtesting.Nil(t, err) 66 xtesting.Equal(t, rl.namePattern, "test-%Y%m%d.log") 67 xtesting.Equal(t, rl.globPattern, "test-*.log") 68 xtesting.Equal(t, rl.option.symlinkFilename, "") 69 xtesting.Equal(t, xtime.LocationDuration(rl.option.nowClock.Now().Location()), time.Duration(0)) 70 xtesting.Equal(t, rl.option.forceNewFile, true) 71 xtesting.Equal(t, rl.option.rotationTime, time.Hour) 72 xtesting.Equal(t, rl.option.rotationSize, int64(256)) 73 xtesting.Equal(t, rl.option.rotationMaxAge, 15*24*time.Hour) 74 xtesting.Equal(t, rl.option.rotationMaxCount, int32(0)) 75 }) 76 } 77 78 func removeLoggers() { 79 matches, _ := filepath.Glob("*.log*") 80 for _, match := range matches { 81 err := os.Remove(match) 82 if err != nil { 83 log.Printf("removeLoggers: os.Remove failed on `%s`", match) 84 } 85 } 86 err := os.RemoveAll("./_test") 87 if err != nil { 88 log.Printf("removeLoggers: os.Remove failed on `%s`", "./_test") 89 } 90 } 91 92 func testFileContent(t *testing.T, name, content string) { 93 xtesting.SetExtraSkip(1) 94 defer xtesting.SetExtraSkip(0) 95 bs, err := ioutil.ReadFile(name) 96 xtesting.Nil(t, err) 97 if err == nil { 98 xtesting.Equal(t, string(bs), content) 99 } 100 } 101 102 func testFileExistence(t *testing.T, name string, exist bool) { 103 xtesting.SetExtraSkip(1) 104 defer xtesting.SetExtraSkip(0) 105 _, err := os.Stat(name) 106 if exist { 107 xtesting.Nil(t, err) 108 } else { 109 xtesting.True(t, os.IsNotExist(err)) 110 } 111 } 112 113 func TestSimpleWrite(t *testing.T) { 114 t.Run("strftime", func(t *testing.T) { 115 removeLoggers() 116 defer removeLoggers() 117 118 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 119 pNow := &now 120 clock := xtime.CustomClock(pNow) 121 rl, _ := New("logger.%Y%m%d.log", WithRotationTime(time.Hour*24), WithClock(clock)) 122 xtesting.Nil(t, rl.Close()) // <- r.currFile == nil 123 124 rl, _ = New("logger.%Y%m%d.log", WithRotationTime(time.Hour*24), WithClock(clock)) 125 _, err := fmt.Fprintf(rl, "hello world 1") // <- create a new file, logger.01.log 126 xtesting.Nil(t, err) 127 testFileExistence(t, "logger.20010101.log", true) 128 testFileContent(t, "logger.20010101.log", "hello world 1") 129 130 *pNow = time.Date(2002, 2, 2, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 131 _, err = fmt.Fprintf(rl, "hello world 2") // <- create a new file, logger.02.log 132 xtesting.Nil(t, err) 133 testFileExistence(t, "logger.20010101.log", true) 134 testFileExistence(t, "logger.20020202.log", true) 135 testFileContent(t, "logger.20010101.log", "hello world 1") 136 testFileContent(t, "logger.20020202.log", "hello world 2") 137 138 _, err = fmt.Fprintf(rl, "hello world 3") // <- use logger.02.log 139 testFileContent(t, "logger.20020202.log", "hello world 2hello world 3") 140 xtesting.Nil(t, rl.Close()) // normal close 141 xtesting.Nil(t, rl.currFile) 142 xtesting.Zero(t, rl.currBasename) 143 xtesting.Zero(t, rl.currGeneration) 144 xtesting.Zero(t, rl.currFilename) 145 _, err = fmt.Fprintf(rl, "hello world 4") // <- normally use logger.02.log 146 testFileContent(t, "logger.20020202.log", "hello world 2hello world 3hello world 4") 147 xtesting.Nil(t, rl.Close()) // normal close 148 }) 149 150 t.Run("reopen and ForceNewFile", func(t *testing.T) { 151 removeLoggers() 152 defer removeLoggers() 153 154 rl, _ := New("logger.log", WithRotationTime(time.Hour*24), WithRotationSize(15), WithForceNewFile(false)) 155 _, err := fmt.Fprintf(rl, "hello world 1\n") // <- 14, create logger.log 156 xtesting.Nil(t, err) 157 testFileExistence(t, "logger.log", true) 158 testFileContent(t, "logger.log", "hello world 1\n") 159 xtesting.Nil(t, rl.Close()) 160 161 rl, _ = New("logger.log", WithRotationTime(time.Hour*24), WithRotationSize(15), WithForceNewFile(false)) 162 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use logger.log 163 xtesting.Nil(t, err) 164 testFileExistence(t, "logger.log", true) 165 testFileExistence(t, "logger.log_1", false) 166 testFileContent(t, "logger.log", "hello world 1\nhello world 2\n") 167 xtesting.Nil(t, rl.Close()) 168 169 rl, _ = New("logger.log", WithRotationTime(time.Hour*24), WithRotationSize(15), WithForceNewFile(false)) 170 _, err = fmt.Fprintf(rl, "hello world 3\n") // <- create logger.log_1 171 xtesting.Nil(t, err) 172 testFileExistence(t, "logger.log_1", true) 173 testFileExistence(t, "logger.log_2", false) 174 testFileContent(t, "logger.log", "hello world 1\nhello world 2\n") 175 testFileContent(t, "logger.log_1", "hello world 3\n") 176 xtesting.Nil(t, rl.Close()) 177 178 rl, _ = New("logger.log", WithRotationTime(time.Hour*24), WithRotationSize(15), WithForceNewFile(true)) 179 _, err = fmt.Fprintf(rl, "hello world 4\n") // <- create logger.log_2 180 xtesting.Nil(t, err) 181 testFileExistence(t, "logger.log_2", true) 182 testFileExistence(t, "logger.log_3", false) 183 testFileContent(t, "logger.log_1", "hello world 3\n") 184 testFileContent(t, "logger.log_2", "hello world 4\n") 185 xtesting.Nil(t, rl.Close()) 186 }) 187 } 188 189 func TestWrite(t *testing.T) { 190 t.Run("some write demos", func(t *testing.T) { 191 removeLoggers() 192 defer removeLoggers() 193 194 rl, _ := New("logger.log", WithRotationSize(15)) 195 xtesting.Equal(t, rl.CurrentFilename(), "") 196 _, err := fmt.Fprintf(rl, "hello world 1\n") // <- 14, create logger.log 197 xtesting.Nil(t, err) 198 testFileExistence(t, "logger.log", true) 199 testFileExistence(t, "logger.log_1", false) 200 testFileContent(t, "logger.log", "hello world 1\n") 201 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 202 203 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use logger.log 204 xtesting.Nil(t, err) 205 testFileExistence(t, "logger.log", true) 206 testFileExistence(t, "logger.log_1", false) 207 testFileContent(t, "logger.log", "hello world 1\nhello world 2\n") 208 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 209 210 _, err = fmt.Fprintf(rl, "hello world 3\n") // <- create: logger.log_1 211 xtesting.Nil(t, err) 212 testFileExistence(t, "logger.log_1", true) 213 testFileExistence(t, "logger.log_2", false) 214 testFileContent(t, "logger.log", "hello world 1\nhello world 2\n") 215 testFileContent(t, "logger.log_1", "hello world 3\n") 216 xtesting.Equal(t, rl.CurrentFilename(), "logger.log_1") 217 xtesting.Nil(t, rl.Close()) 218 219 rl, _ = New("logger.log", WithRotationSize(29)) 220 xtesting.Equal(t, rl.CurrentFilename(), "") 221 _, err = fmt.Fprintf(rl, "hello world 4\n") // <- use logger.log 222 xtesting.Nil(t, err) 223 testFileExistence(t, "logger.log", true) 224 testFileExistence(t, "logger.log_1", true) 225 testFileExistence(t, "logger.log_2", false) 226 testFileContent(t, "logger.log", "hello world 1\nhello world 2\nhello world 4\n") 227 testFileContent(t, "logger.log_1", "hello world 3\n") 228 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 229 230 _, err = fmt.Fprintf(rl, "hello world 5\n") // <- create: logger.log_2 231 xtesting.Nil(t, err) 232 testFileExistence(t, "logger.log_2", true) 233 testFileExistence(t, "logger.log_3", false) 234 testFileContent(t, "logger.log", "hello world 1\nhello world 2\nhello world 4\n") 235 testFileContent(t, "logger.log_1", "hello world 3\n") 236 testFileContent(t, "logger.log_2", "hello world 5\n") 237 xtesting.Equal(t, rl.CurrentFilename(), "logger.log_2") 238 xtesting.Nil(t, rl.Close()) 239 240 rl, _ = New("logger.log", WithRotationSize(29)) 241 xtesting.Equal(t, rl.CurrentFilename(), "") 242 _, err = fmt.Fprintf(rl, "hello world 6\n") // <- create: logger.log_3 243 xtesting.Nil(t, err) 244 testFileExistence(t, "logger.log_3", true) 245 testFileExistence(t, "logger.log_4", false) 246 testFileContent(t, "logger.log_2", "hello world 5\n") 247 testFileContent(t, "logger.log_3", "hello world 6\n") 248 xtesting.Equal(t, rl.CurrentFilename(), "logger.log_3") 249 xtesting.Nil(t, rl.Close()) 250 }) 251 252 t.Run("simple rotate", func(t *testing.T) { 253 removeLoggers() 254 defer removeLoggers() 255 256 rl, _ := New("logger.log", WithRotationSize(15)) 257 xtesting.Nil(t, rl.Rotate()) // <- create logger.log 258 testFileExistence(t, "logger.log", true) 259 testFileContent(t, "logger.log", "") 260 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 261 xtesting.Nil(t, rl.Rotate()) // <- use logger.log 262 testFileExistence(t, "logger.log", true) 263 testFileExistence(t, "logger.log_1", false) 264 testFileContent(t, "logger.log", "") 265 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 266 xtesting.Nil(t, rl.Close()) 267 268 rl, _ = New("logger.log", WithRotationSize(15)) 269 xtesting.Nil(t, rl.Rotate()) // <- use logger.log 270 testFileExistence(t, "logger.log", true) 271 testFileExistence(t, "logger.log_1", false) 272 testFileContent(t, "logger.log", "") 273 xtesting.Equal(t, rl.CurrentFilename(), "logger.log") 274 _, err := fmt.Fprintf(rl, "hello world 1\n") // <- write to logger.log 275 xtesting.Nil(t, err) 276 testFileContent(t, "logger.log", "hello world 1\n") 277 xtesting.Nil(t, rl.Rotate()) // <- use logger.log 278 testFileExistence(t, "logger.log", true) 279 testFileExistence(t, "logger.log_1", false) 280 testFileContent(t, "logger.log", "hello world 1\n") 281 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- write to logger.log 282 xtesting.Nil(t, err) 283 testFileContent(t, "logger.log", "hello world 1\nhello world 2\n") 284 xtesting.Nil(t, rl.Rotate()) // <- create logger_1.log 285 testFileExistence(t, "logger.log_1", true) 286 testFileExistence(t, "logger.log_2", false) 287 testFileContent(t, "logger.log_1", "") // <- empty logger.log_1 288 xtesting.Nil(t, rl.Close()) 289 290 rl, _ = New("logger.log", WithRotationSize(15)) 291 xtesting.Nil(t, rl.Rotate()) // <- create logger.log_2 292 testFileExistence(t, "logger.log_1", true) 293 testFileExistence(t, "logger.log_2", true) 294 testFileContent(t, "logger.log_2", "") 295 _, err = fmt.Fprintf(rl, "hello world 3\n") // <- write to logger.log_2 296 testFileContent(t, "logger.log_1", "") 297 testFileContent(t, "logger.log_2", "hello world 3\n") 298 xtesting.Nil(t, rl.Close()) 299 }) 300 } 301 302 func TestRotate(t *testing.T) { 303 t.Run("max age", func(t *testing.T) { 304 removeLoggers() 305 defer removeLoggers() 306 307 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 308 pNow := &now 309 clock := xtime.CustomClock(pNow) 310 rl, _ := New("logger.%Y%m%d.log", WithRotationSize(15), WithRotationTime(time.Hour*24), WithRotationMaxAge(3*24*time.Hour), WithClock(clock)) 311 312 *pNow = xtime.SetDay(now, 1) // 1d 313 _, _ = fmt.Fprintf(rl, "hello world 1\n") // <- logger.01.log 314 _, _ = fmt.Fprintf(rl, "hello world 2\n") 315 _, _ = fmt.Fprintf(rl, "hello world 3\n") // <- logger.01.log_1 316 _, _ = fmt.Fprintf(rl, "hello world 4\n") 317 _, _ = fmt.Fprintf(rl, "hello world 5\n") // <- logger.01.log_2 318 _ = os.Chtimes("logger.20010101.log", now, now) 319 _ = os.Chtimes("logger.20010101.log_1", now, now) 320 _ = os.Chtimes("logger.20010101.log_2", now, now) 321 *pNow = xtime.SetDay(now, 2) // 2d 322 _, _ = fmt.Fprintf(rl, "hello world 6\n") // <- logger.02.log 323 _, _ = fmt.Fprintf(rl, "hello world 7\n") 324 _, _ = fmt.Fprintf(rl, "hello world 8\n") // <- logger.02.log_1 325 _ = os.Chtimes("logger.20010102.log", now, now) 326 _ = os.Chtimes("logger.20010102.log_1", now, now) 327 *pNow = xtime.SetDay(now, 3) // 3d 328 _, _ = fmt.Fprintf(rl, "hello world 9\n") // <- logger.03.log 329 _ = os.Chtimes("logger.20010103.log", now, now) 330 testFileExistence(t, "logger.20010101.log", true) 331 testFileExistence(t, "logger.20010101.log_1", true) 332 testFileExistence(t, "logger.20010101.log_2", true) 333 testFileExistence(t, "logger.20010102.log", true) 334 testFileExistence(t, "logger.20010102.log_1", true) 335 testFileExistence(t, "logger.20010103.log", true) 336 337 *pNow = xtime.SetHour(now, 1) 338 *pNow = xtime.SetDay(now, 4) // 4d1h 339 xtesting.Nil(t, rl.Rotate()) // <- delete logger.01.log 340 testFileExistence(t, "logger.20010101.log", false) 341 testFileExistence(t, "logger.20010101.log_1", false) 342 testFileExistence(t, "logger.20010101.log_2", false) 343 testFileExistence(t, "logger.20010102.log", true) 344 testFileExistence(t, "logger.20010102.log_1", true) 345 testFileExistence(t, "logger.20010103.log", true) 346 *pNow = xtime.SetDay(now, 5) // 5d1h 347 _, _ = fmt.Fprintf(rl, "for rotate") // <- delete logger.02.log 348 testFileExistence(t, "logger.20010101.log", false) 349 testFileExistence(t, "logger.20010101.log_1", false) 350 testFileExistence(t, "logger.20010101.log_2", false) 351 testFileExistence(t, "logger.20010102.log", false) 352 testFileExistence(t, "logger.20010102.log_1", false) 353 testFileExistence(t, "logger.20010103.log", true) 354 *pNow = xtime.SetDay(now, 6) // 6d1h 355 xtesting.Nil(t, rl.Rotate()) // <- delete logger.03.log 356 testFileExistence(t, "logger.20010101.log", false) 357 testFileExistence(t, "logger.20010101.log_1", false) 358 testFileExistence(t, "logger.20010101.log_2", false) 359 testFileExistence(t, "logger.20010102.log", false) 360 testFileExistence(t, "logger.20010102.log_1", false) 361 testFileExistence(t, "logger.20010103.log", false) 362 _ = rl.Close() 363 }) 364 365 t.Run("max count", func(t *testing.T) { 366 removeLoggers() 367 defer removeLoggers() 368 369 now := time.Date(2001, 1, 1, 1, 1, 1, 0, time.FixedZone("", 8*60*60)) 370 pNow := &now 371 clock := xtime.CustomClock(pNow) 372 rl, _ := New("logger.%Y%m%d.log", WithRotationSize(15), WithRotationTime(time.Hour*24), WithRotationMaxCount(3), WithClock(clock)) 373 374 *pNow = xtime.SetDay(now, 1) // 1d 375 _, _ = fmt.Fprintf(rl, "hello world 1\n") // <- logger.01.log 376 _, _ = fmt.Fprintf(rl, "hello world 2\n") 377 _, _ = fmt.Fprintf(rl, "hello world 3\n") // <- logger.01.log_1 378 _, _ = fmt.Fprintf(rl, "hello world 4\n") 379 _, _ = fmt.Fprintf(rl, "hello world 5\n") // <- logger.01.log_2 380 *pNow = xtime.SetDay(now, 2) // 2d 381 _, _ = fmt.Fprintf(rl, "hello world 6\n") // <- logger.02.log 382 _, _ = fmt.Fprintf(rl, "hello world 7\n") 383 _, _ = fmt.Fprintf(rl, "hello world 8\n") // <- logger.02.log_1 384 *pNow = xtime.SetDay(now, 3) // 3d 385 _, _ = fmt.Fprintf(rl, "hello world 9\n") // <- logger.03.log 386 testFileExistence(t, "logger.20010101.log", true) 387 testFileExistence(t, "logger.20010101.log_1", true) 388 testFileExistence(t, "logger.20010101.log_2", true) 389 testFileExistence(t, "logger.20010102.log", true) 390 testFileExistence(t, "logger.20010102.log_1", true) 391 testFileExistence(t, "logger.20010103.log", true) 392 393 *pNow = xtime.SetHour(now, 1) 394 *pNow = xtime.SetDay(now, 4) // 4d1h 395 xtesting.Nil(t, rl.Rotate()) // <- delete logger.01.log 396 testFileExistence(t, "logger.20010101.log", false) 397 testFileExistence(t, "logger.20010101.log_1", false) 398 testFileExistence(t, "logger.20010101.log_2", false) 399 testFileExistence(t, "logger.20010102.log", true) 400 testFileExistence(t, "logger.20010102.log_1", true) 401 testFileExistence(t, "logger.20010103.log", true) 402 *pNow = xtime.SetDay(now, 5) // 5d1h 403 _, _ = fmt.Fprintf(rl, "for rotate") // <- delete logger.02.log 404 testFileExistence(t, "logger.20010101.log", false) 405 testFileExistence(t, "logger.20010101.log_1", false) 406 testFileExistence(t, "logger.20010101.log_2", false) 407 testFileExistence(t, "logger.20010102.log", false) 408 testFileExistence(t, "logger.20010102.log_1", false) 409 testFileExistence(t, "logger.20010103.log", true) 410 *pNow = xtime.SetDay(now, 6) // 6d1h 411 xtesting.Nil(t, rl.Rotate()) // <- delete logger.03.log 412 testFileExistence(t, "logger.20010101.log", false) 413 testFileExistence(t, "logger.20010101.log_1", false) 414 testFileExistence(t, "logger.20010101.log_2", false) 415 testFileExistence(t, "logger.20010102.log", false) 416 testFileExistence(t, "logger.20010102.log_1", false) 417 testFileExistence(t, "logger.20010103.log", false) 418 419 f1, err := os.OpenFile("logger.20010104.log", os.O_APPEND, 0644) 420 xtesting.Nil(t, err) 421 f2, err := os.OpenFile("logger.20010105.log", os.O_APPEND, 0644) 422 xtesting.Nil(t, err) 423 *pNow = xtime.SetDay(now, 7) // 7d1h 424 _, err = fmt.Fprintf(rl, "") 425 xtesting.Nil(t, err) // <- Warning: failed to remove logger.04.log 426 xtesting.NotNil(t, rl.Rotate()) // <- need to rotate, error: failed to remove logger.04.log 427 testFileExistence(t, "logger.20010104.log", true) 428 *pNow = xtime.SetDay(now, 8) // 8d1h 429 xtesting.NotNil(t, rl.Rotate()) // <- error: failed to remove logger.04.log, logger.05.log 430 testFileExistence(t, "logger.20010104.log", true) 431 testFileExistence(t, "logger.20010105.log", true) 432 xtesting.Nil(t, f1.Close()) 433 xtesting.Nil(t, f2.Close()) 434 *pNow = xtime.SetDay(now, 9) // 9d1h 435 xtesting.Nil(t, rl.Rotate()) // <- delete logger.04.log and logger.05.log 436 testFileExistence(t, "logger.20010104.log", false) 437 testFileExistence(t, "logger.20010105.log", false) 438 _ = rl.Close() 439 }) 440 } 441 442 func TestInDifferentDir(t *testing.T) { 443 t.Run("some write demos", func(t *testing.T) { 444 removeLoggers() 445 defer removeLoggers() 446 447 rl, _ := New("./_test/_test/logger.log", WithRotationSize(15)) 448 _, _ = fmt.Fprintf(rl, "hello world 1\n") // <- create logger.log 449 _, _ = fmt.Fprintf(rl, "hello world 2\n") // <- use logger.log 450 _, _ = fmt.Fprintf(rl, "hello world 3\n") // <- create: logger.log_1 451 testFileExistence(t, "./_test/_test/logger.log", true) 452 testFileExistence(t, "./_test/_test/logger.log_1", true) 453 testFileExistence(t, "./_test/_test/logger.log_2", false) 454 testFileContent(t, "./_test/_test/logger.log", "hello world 1\nhello world 2\n") 455 testFileContent(t, "./_test/_test/logger.log_1", "hello world 3\n") 456 xtesting.Equal(t, rl.CurrentFilename(), "./_test/_test/logger.log_1") 457 xtesting.Nil(t, rl.Close()) 458 459 rl, _ = New("./_test/_test/logger.log", WithRotationSize(29)) 460 _, _ = fmt.Fprintf(rl, "hello world 4\n") // <- use logger.log 461 _, _ = fmt.Fprintf(rl, "hello world 5\n") // <- create: logger.log_2 462 testFileExistence(t, "./_test/_test/logger.log", true) 463 testFileExistence(t, "./_test/_test/logger.log_1", true) 464 testFileExistence(t, "./_test/_test/logger.log_2", true) 465 testFileExistence(t, "./_test/_test/logger.log_3", false) 466 testFileContent(t, "./_test/_test/logger.log", "hello world 1\nhello world 2\nhello world 4\n") 467 testFileContent(t, "./_test/_test/logger.log_1", "hello world 3\n") 468 testFileContent(t, "./_test/_test/logger.log_2", "hello world 5\n") 469 xtesting.Equal(t, rl.CurrentFilename(), "./_test/_test/logger.log_2") 470 xtesting.Nil(t, rl.Close()) 471 }) 472 473 t.Run("max age", func(t *testing.T) { 474 removeLoggers() 475 defer removeLoggers() 476 477 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 478 pNow := &now 479 clock := xtime.CustomClock(pNow) 480 rl, _ := New("./_test/_test/logger.%Y%m%d.log", WithRotationSize(15), WithRotationTime(time.Hour*24), WithRotationMaxAge(2*24*time.Hour), WithClock(clock)) 481 482 *pNow = xtime.SetDay(now, 1) // 1d 483 _, _ = fmt.Fprintf(rl, "hello world 1\n") // <- logger.01.log 484 _, _ = fmt.Fprintf(rl, "hello world 2\n") 485 _, _ = fmt.Fprintf(rl, "hello world 3\n") // <- logger.01.log_1 486 _ = os.Chtimes("./_test/_test/logger.20010101.log", now, now) 487 _ = os.Chtimes("./_test/_test/logger.20010101.log_1", now, now) 488 *pNow = xtime.SetDay(now, 2) // 2d 489 _, _ = fmt.Fprintf(rl, "hello world 4\n") // <- logger.02.log 490 _ = os.Chtimes("./_test/_test/logger.20010102.log", now, now) 491 testFileExistence(t, "./_test/_test/logger.20010101.log", true) 492 testFileExistence(t, "./_test/_test/logger.20010101.log_1", true) 493 testFileExistence(t, "./_test/_test/logger.20010102.log", true) 494 495 *pNow = xtime.SetHour(now, 1) 496 *pNow = xtime.SetDay(now, 3) // 3d1h 497 xtesting.Nil(t, rl.Rotate()) // <- delete logger.01.log 498 testFileExistence(t, "./_test/_test/logger.20010101.log", false) 499 testFileExistence(t, "./_test/_test/logger.20010101.log_1", false) 500 testFileExistence(t, "./_test/_test/logger.20010102.log", true) 501 *pNow = xtime.SetDay(now, 4) // 4d1h 502 _, _ = fmt.Fprintf(rl, "for rotate") // <- delete logger.02.log 503 testFileExistence(t, "./_test/_test/logger.20010101.log", false) 504 testFileExistence(t, "./_test/_test/logger.20010101.log_1", false) 505 testFileExistence(t, "./_test/_test/logger.20010102.log", false) 506 _ = rl.Close() 507 }) 508 509 t.Run("max count", func(t *testing.T) { 510 removeLoggers() 511 defer removeLoggers() 512 513 now := time.Date(2001, 1, 1, 1, 1, 1, 0, time.FixedZone("", 8*60*60)) 514 pNow := &now 515 clock := xtime.CustomClock(pNow) 516 rl, _ := New("./_test/_test/logger.%Y%m%d.log", WithRotationSize(15), WithRotationTime(time.Hour*24), WithRotationMaxCount(2), WithClock(clock)) 517 518 *pNow = xtime.SetDay(now, 1) // 1d 519 _, _ = fmt.Fprintf(rl, "hello world 1\n") // <- logger.01.log 520 _, _ = fmt.Fprintf(rl, "hello world 2\n") 521 _, _ = fmt.Fprintf(rl, "hello world 3\n") // <- logger.01.log_1 522 *pNow = xtime.SetDay(now, 2) // 2d 523 _, _ = fmt.Fprintf(rl, "hello world 4\n") // <- logger.02.log 524 testFileExistence(t, "./_test/_test/logger.20010101.log", true) 525 testFileExistence(t, "./_test/_test/logger.20010101.log_1", true) 526 testFileExistence(t, "./_test/_test/logger.20010102.log", true) 527 528 *pNow = xtime.SetHour(now, 1) 529 *pNow = xtime.SetDay(now, 3) // 3d1h 530 xtesting.Nil(t, rl.Rotate()) // <- delete logger.01.log 531 testFileExistence(t, "./_test/_test/logger.20010101.log", false) 532 testFileExistence(t, "./_test/_test/logger.20010101.log_1", false) 533 testFileExistence(t, "./_test/_test/logger.20010102.log", true) 534 *pNow = xtime.SetDay(now, 4) // 4d1h 535 _, _ = fmt.Fprintf(rl, "for rotate") // <- delete logger.02.log 536 testFileExistence(t, "./_test/_test/logger.20010101.log", false) 537 testFileExistence(t, "./_test/_test/logger.20010101.log_1", false) 538 testFileExistence(t, "./_test/_test/logger.20010102.log", false) 539 _ = rl.Close() 540 }) 541 542 t.Run("cover errors", func(t *testing.T) { 543 removeLoggers() 544 now := time.Date(2001, 1, 1, 1, 1, 1, 0, time.FixedZone("", 8*60*60)) 545 pNow := &now 546 clock := xtime.CustomClock(pNow) 547 548 rl, _ := New("./_test/logger.%Y%m%d.log", WithRotationTime(time.Hour*24), WithClock(clock)) 549 *pNow = xtime.SetDay(now, 1) 550 _t_testHookMkdir = func() { 551 f, err := os.OpenFile("_test", os.O_CREATE, 0644) 552 xtesting.Nil(t, err) 553 xtesting.Nil(t, f.Close()) 554 } 555 xtesting.NotNil(t, rl.Rotate()) // Rotate: MkdirAll failed 556 removeLoggers() 557 _t_testHookMkdir = func() { 558 err := os.MkdirAll("./_test/logger.20010101.log", 0755) 559 xtesting.Nil(t, err) 560 } 561 _, err := fmt.Fprintf(rl, "test OpenFile") 562 xtesting.NotNil(t, err) // OpenFile failed 563 _ = rl.Close() 564 _t_testHookMkdir = nil 565 removeLoggers() 566 }) 567 } 568 569 func TestSymlink(t *testing.T) { 570 t.Run("same directory", func(t *testing.T) { 571 removeLoggers() 572 defer removeLoggers() 573 574 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 575 pNow := &now 576 clock := xtime.CustomClock(pNow) 577 rl, _ := New("logger.%Y%m%d.log", WithSymlinkFilename("logger.current.log"), WithRotationSize(15), WithRotationMaxCount(2), WithClock(clock)) 578 _, err := fmt.Fprintf(rl, "hello world 1\n") // <- create: logger.01.log 579 xtesting.Nil(t, err) 580 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use: logger.01.log 581 xtesting.Nil(t, err) 582 testFileContent(t, "logger.20010101.log", "hello world 1\nhello world 2\n") 583 testFileExistence(t, "logger.current.log", true) 584 fi, err := os.Lstat("logger.current.log") 585 xtesting.Nil(t, err) 586 xtesting.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink) 587 testFileContent(t, "logger.current.log", "hello world 1\nhello world 2\n") 588 589 _, err = fmt.Fprintf(rl, "hello world 3\n") // <- create: logger.01.log_1 590 xtesting.Nil(t, err) 591 testFileContent(t, "logger.20010101.log_1", "hello world 3\n") 592 testFileContent(t, "logger.current.log", "hello world 3\n") 593 *pNow = xtime.SetDay(now, 2) // 2d 594 _, err = fmt.Fprintf(rl, "hello world 4\n") // <- create: logger.02.log 595 testFileContent(t, "logger.20010102.log", "hello world 4\n") 596 testFileContent(t, "logger.current.log", "hello world 4\n") 597 *pNow = xtime.SetDay(now, 3) // 3d 598 _, err = fmt.Fprintf(rl, "hello world 5\n") // <- create: logger.03.log, need rotate 599 xtesting.Nil(t, err) 600 testFileExistence(t, "logger.20010101.log", false) 601 testFileExistence(t, "logger.20010101.log_1", false) 602 testFileExistence(t, "logger.20010102.log", true) 603 testFileContent(t, "logger.20010103.log", "hello world 5\n") 604 testFileContent(t, "logger.current.log", "hello world 5\n") 605 _ = rl.Close() 606 removeLoggers() 607 608 rl, _ = New("logger.%Y%m%d.log", WithSymlinkFilename("logger.current.log"), WithRotationSize(15), WithRotationMaxAge(time.Hour*24*2), WithClock(clock), WithForceNewFile(true)) 609 *pNow = xtime.SetDay(now, 1) // 1d 610 _, err = fmt.Fprintf(rl, "hello world 1\n") // <- create: logger.01.log 611 xtesting.Nil(t, err) 612 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use: logger.01.log 613 xtesting.Nil(t, err) 614 _ = os.Chtimes("logger.20010101.log", now, now) 615 testFileContent(t, "logger.20010101.log", "hello world 1\nhello world 2\n") 616 testFileContent(t, "logger.current.log", "hello world 1\nhello world 2\n") 617 618 _, err = fmt.Fprintf(rl, "hello world 3\n") // <- create: logger.01.log_1 619 xtesting.Nil(t, err) 620 _ = os.Chtimes("logger.20010101.log_1", now, now) 621 testFileContent(t, "logger.20010101.log_1", "hello world 3\n") 622 testFileContent(t, "logger.current.log", "hello world 3\n") 623 *pNow = xtime.SetDay(now, 2) // 2d 624 _, err = fmt.Fprintf(rl, "hello world 4\n") // <- create: logger.02.log 625 _ = os.Chtimes("logger.20010102.log", now, now) 626 testFileContent(t, "logger.20010102.log", "hello world 4\n") 627 testFileContent(t, "logger.current.log", "hello world 4\n") 628 *pNow = xtime.SetHour(now, 1) 629 *pNow = xtime.SetDay(now, 3) // 3d1h 630 f, err := os.OpenFile("logger.20010103.log_symlink", os.O_CREATE, 0644) 631 xtesting.Nil(t, err) // <- fake symlink, need to be deleted 632 xtesting.Nil(t, f.Close()) 633 _, err = fmt.Fprintf(rl, "hello world 5\n") // <- create: logger.03.log, need rotate 634 xtesting.Nil(t, err) 635 testFileExistence(t, "logger.20010101.log", false) 636 testFileExistence(t, "logger.20010101.log_1", false) 637 testFileExistence(t, "logger.20010102.log", true) 638 testFileContent(t, "logger.20010103.log", "hello world 5\n") 639 testFileContent(t, "logger.current.log", "hello world 5\n") 640 _ = rl.Close() 641 }) 642 643 t.Run("different directory", func(t *testing.T) { 644 removeLoggers() 645 defer removeLoggers() 646 647 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 648 pNow := &now 649 clock := xtime.CustomClock(pNow) 650 rl, _ := New("_test/logger.%Y%m%d.log", WithSymlinkFilename("_test/_test/logger.current.log"), WithRotationSize(15), WithClock(clock)) 651 _, err := fmt.Fprintf(rl, "hello world 1\n") // <- create: logger.01.log 652 xtesting.Nil(t, err) 653 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use: logger.01.log 654 xtesting.Nil(t, err) 655 testFileContent(t, "_test/logger.20010101.log", "hello world 1\nhello world 2\n") 656 testFileExistence(t, "_test/_test/logger.current.log", true) 657 testFileContent(t, "_test/_test/logger.current.log", "hello world 1\nhello world 2\n") 658 _ = rl.Close() 659 removeLoggers() 660 661 rl, _ = New("_test/_test/logger.%Y%m%d.log", WithSymlinkFilename("_test/logger.current.log"), WithRotationSize(15), WithClock(clock)) 662 _, err = fmt.Fprintf(rl, "hello world 1\n") // <- create: logger.01.log 663 xtesting.Nil(t, err) 664 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use: logger.01.log 665 xtesting.Nil(t, err) 666 testFileContent(t, "_test/_test/logger.20010101.log", "hello world 1\nhello world 2\n") 667 testFileExistence(t, "_test/logger.current.log", true) 668 testFileContent(t, "_test/logger.current.log", "hello world 1\nhello world 2\n") 669 _ = rl.Close() 670 removeLoggers() 671 672 rl, _ = New("_test/logger.%Y%m%d.log", WithSymlinkFilename("_test/logger.current.log"), WithRotationSize(15), WithClock(clock)) 673 _, err = fmt.Fprintf(rl, "hello world 1\n") // <- create: logger.01.log 674 xtesting.Nil(t, err) 675 _, err = fmt.Fprintf(rl, "hello world 2\n") // <- use: logger.01.log 676 xtesting.Nil(t, err) 677 testFileContent(t, "_test/logger.20010101.log", "hello world 1\nhello world 2\n") 678 testFileExistence(t, "_test/logger.current.log", true) 679 testFileContent(t, "_test/logger.current.log", "hello world 1\nhello world 2\n") 680 _ = rl.Close() 681 removeLoggers() 682 }) 683 684 t.Run("cover errors", func(t *testing.T) { 685 removeLoggers() 686 defer removeLoggers() 687 688 now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)) 689 pNow := &now 690 clock := xtime.CustomClock(pNow) 691 rl, _ := New("logger.%Y%m%d.log", WithSymlinkFilename("_test/logger.current.log"), WithRotationSize(15), WithClock(clock)) 692 *pNow = xtime.SetDay(now, 1) 693 _t_testHookSymlink[0] = func() string { 694 f, err := os.OpenFile("_test", os.O_CREATE, 0644) 695 xtesting.Nil(t, err) 696 xtesting.Nil(t, f.Close()) 697 return "" 698 } 699 xtesting.Nil(t, rl.Rotate()) // MkdirAll failed 700 _t_testHookSymlink[0] = nil 701 702 *pNow = xtime.SetDay(now, 2) 703 _t_testHookSymlink[1] = func() string { 704 return ".." // hack 705 } 706 xtesting.Nil(t, rl.Rotate()) // Rel failed 707 _t_testHookSymlink[1] = nil 708 709 *pNow = xtime.SetDay(now, 3) 710 _t_testHookSymlink[2] = func() string { 711 xtesting.Nil(t, os.MkdirAll("logger.20010103.log_symlink", 0755)) 712 return "" 713 } 714 xtesting.Nil(t, rl.Rotate()) // Symlink failed 715 716 _ = os.RemoveAll("_test") 717 *pNow = xtime.SetDay(now, 4) 718 _t_testHookSymlink[2] = func() string { 719 xtesting.Nil(t, os.MkdirAll("_test/logger.current.log", 0755)) 720 return "" 721 } 722 xtesting.Nil(t, rl.Rotate()) // Rename failed 723 _t_testHookSymlink[2] = nil 724 725 _ = rl.Close() 726 }) 727 }