WIP
This commit is contained in:
parent
96e877b0c2
commit
6806a81588
|
@ -94,13 +94,13 @@ func (lf *LogFile) truncate() error {
|
|||
|
||||
func prettyByteSize(b int64) string {
|
||||
bf := float64(b)
|
||||
for _, unit := range []string{"", "K", "M", "G", "T", "P", "E", "Z"} {
|
||||
for _, unit := range []string{"", "K", "M", "G", "T", "P"} {
|
||||
if math.Abs(bf) < 1024.0 {
|
||||
return fmt.Sprintf("%3.1f%sB", bf, unit)
|
||||
}
|
||||
bf /= 1024.0
|
||||
}
|
||||
return fmt.Sprintf("%.1fYB", bf)
|
||||
return fmt.Sprintf("%.1fEB", bf)
|
||||
}
|
||||
|
||||
func compressOldFile(fname string) error {
|
||||
|
|
120
logger_test.go
120
logger_test.go
|
@ -2,7 +2,10 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTruncate(t *testing.T) {
|
||||
|
@ -11,14 +14,123 @@ func TestTruncate(t *testing.T) {
|
|||
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||
rulesJsonFp := "testData/app_over_size.log"
|
||||
|
||||
expected := fmt.Sprintf("%s/tmp/app.log", tmpDir)
|
||||
tmpLf := fmt.Sprintf("%s/tmp/app.log", tmpDir)
|
||||
|
||||
cpFileForTest(t, rulesJsonFp, expected)
|
||||
cpFileForTest(t, rulesJsonFp, tmpLf)
|
||||
|
||||
cfg := &LogFile{
|
||||
path: expected,
|
||||
lf := &LogFile{
|
||||
path: tmpLf,
|
||||
}
|
||||
|
||||
lf.path = tmpLf
|
||||
// Continue from here
|
||||
isEmpty := isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, false)
|
||||
|
||||
err := lf.truncate()
|
||||
assert.Equal(t, err, nil)
|
||||
isEmpty = isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, true)
|
||||
}
|
||||
|
||||
func TestMakeCopyTo(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||
rulesJsonFp := "testData/app_over_size.log"
|
||||
|
||||
tmpLf := fmt.Sprintf("%s/tmp/app.log", tmpDir)
|
||||
|
||||
cpFileForTest(t, rulesJsonFp, tmpLf)
|
||||
|
||||
newLocation := fmt.Sprintf("%s/tmp/app.1.log", tmpDir)
|
||||
|
||||
lf := &LogFile{
|
||||
path: tmpLf,
|
||||
}
|
||||
|
||||
lf.path = tmpLf
|
||||
|
||||
isEmpty := isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, false)
|
||||
|
||||
err := lf.makeCopyTo(newLocation)
|
||||
assert.Equal(t, err, nil)
|
||||
isEmpty = isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, false)
|
||||
ok := areFilesTheSame(t, lf.path, newLocation)
|
||||
assert.Equal(t, ok, true)
|
||||
}
|
||||
|
||||
func TestPrettyByteSize(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
input int
|
||||
want string
|
||||
}{
|
||||
"KB": {input: 5675, want: "5.5KB"},
|
||||
"MB": {input: 7060600, want: "6.7MB"},
|
||||
"GB": {input: 8000000000, want: "7.5GB"},
|
||||
"TB": {input: 1300007000000, want: "1.2TB"},
|
||||
"EB": {input: 1300007000000000000, want: "1.1EB"},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got := prettyByteSize(int64(tc.input))
|
||||
assert.Equal(t, got, tc.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressFile(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||
rulesJsonFp := "testData/app_over_size.log"
|
||||
|
||||
tmpLf := fmt.Sprintf("%s/tmp/app.log", tmpDir)
|
||||
|
||||
cpFileForTest(t, rulesJsonFp, tmpLf)
|
||||
|
||||
expected := fmt.Sprintf("%s/tmp/app.log.gz", tmpDir)
|
||||
|
||||
err := compressOldFile(tmpLf)
|
||||
assert.Equal(t, err, nil)
|
||||
exists := doesFileExist(tmpLf)
|
||||
assert.Equal(t, exists, false)
|
||||
exists = doesFileExist(expected)
|
||||
assert.Equal(t, exists, true)
|
||||
}
|
||||
|
||||
func TestRotate(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
mkDirForTest(t, fmt.Sprintf("%s/tmp", tmpDir))
|
||||
rulesJsonFp := "testData/app_over_size.log"
|
||||
|
||||
tmpLf := fmt.Sprintf("%s/tmp/app.log", tmpDir)
|
||||
|
||||
cpFileForTest(t, rulesJsonFp, tmpLf)
|
||||
|
||||
lf := &LogFile{
|
||||
path: tmpLf,
|
||||
}
|
||||
|
||||
fd, _ := os.Open(tmpLf)
|
||||
lf.handle = fd
|
||||
|
||||
isEmpty := isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, false)
|
||||
err := lf.rotate(true)
|
||||
assert.Equal(t, err, nil)
|
||||
exists := doesFileExist(tmpLf)
|
||||
assert.Equal(t, exists, true)
|
||||
isEmpty = isFileEmpty(t, tmpLf)
|
||||
assert.Equal(t, isEmpty, true)
|
||||
|
||||
expected := walkMatch(t, tmpDir, "*.gz")
|
||||
assert.NotEmpty(t, expected)
|
||||
t.Logf("%+v", expected)
|
||||
|
||||
assert.NotEqual(t, lf.handle, fd)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -81,6 +83,29 @@ func doesFileExist(name string) bool {
|
|||
return err == nil
|
||||
}
|
||||
|
||||
// Derived from here (https://stackoverflow.com/a/55300382)
|
||||
func walkMatch(t *testing.T, root, pattern string) []string {
|
||||
var matches []string
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
|
||||
return err
|
||||
} else if matched {
|
||||
matches = append(matches, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
// func doesFileExist(name string) bool {
|
||||
// _, err := os.Stat(name)
|
||||
// return !errors.Is(err, fs.ErrNotExist)
|
||||
|
@ -113,3 +138,72 @@ func isFileEmpty(t *testing.T, name string) bool {
|
|||
}
|
||||
return finfo.Size() < 1
|
||||
}
|
||||
|
||||
// Derived from here (https://stackoverflow.com/a/73411967)
|
||||
func areFilesTheSame(t *testing.T, fp_1 string, fp_2 string) bool {
|
||||
chunkSize := 4 * 1024
|
||||
|
||||
// shortcuts: check file metadata
|
||||
finfo_1, err := os.Stat(fp_1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
finfo_2, err := os.Stat(fp_2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// are inputs are literally the same file?
|
||||
if os.SameFile(finfo_1, finfo_2) {
|
||||
return true
|
||||
}
|
||||
|
||||
// do inputs at least have the same size?
|
||||
if finfo_1.Size() != finfo_2.Size() {
|
||||
return false
|
||||
}
|
||||
|
||||
// long way: compare contents
|
||||
fd_1, err := os.Open(fp_1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer fd_1.Close()
|
||||
|
||||
fd_2, err := os.Open(fp_2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer fd_2.Close()
|
||||
|
||||
bfd_1 := make([]byte, chunkSize)
|
||||
bfd_2 := make([]byte, chunkSize)
|
||||
for {
|
||||
n1, err1 := io.ReadFull(fd_1, bfd_1)
|
||||
n2, err2 := io.ReadFull(fd_2, bfd_2)
|
||||
|
||||
// https://pkg.go.dev/io#Reader
|
||||
// > Callers should always process the n > 0 bytes returned
|
||||
// > before considering the error err. Doing so correctly
|
||||
// > handles I/O errors that happen after reading some bytes
|
||||
// > and also both of the allowed EOF behaviors.
|
||||
|
||||
if !bytes.Equal(bfd_1[:n1], bfd_2[:n2]) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (err1 == io.EOF && err2 == io.EOF) || (err1 == io.ErrUnexpectedEOF && err2 == io.ErrUnexpectedEOF) {
|
||||
return true
|
||||
}
|
||||
|
||||
// some other error, like a dropped network connection or a bad transfer
|
||||
if err1 != nil {
|
||||
t.Fatal(err1)
|
||||
}
|
||||
if err2 != nil {
|
||||
t.Fatal(err2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue