github.com/phuslu/log@v1.0.100/file_test.go (about)

     1  package log
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestFileWriter(t *testing.T) {
    12  	filename := "file-output.log"
    13  	text := "hello file writer!\n"
    14  
    15  	w := &FileWriter{
    16  		Filename: filename,
    17  	}
    18  	_, err := wlprintf(w, InfoLevel, text)
    19  	if err != nil {
    20  		t.Fatalf("file writer error: %+v", err)
    21  	}
    22  
    23  	// _ = w.Rotate()
    24  	w.Close()
    25  
    26  	matches, err := filepath.Glob("file-output.*.log")
    27  	if err != nil {
    28  		t.Fatalf("filepath glob error: %+v", err)
    29  	}
    30  	if len(matches) == 0 {
    31  		t.Fatal("filepath glob return empty")
    32  	}
    33  
    34  	data, err := os.ReadFile(matches[0])
    35  	if err != nil {
    36  		t.Fatalf("read file error: %+v", err)
    37  	}
    38  
    39  	if string(data) != text {
    40  		t.Fatalf("read file content mismath: data=[%s], text=[%s]", data, text)
    41  	}
    42  
    43  	err = os.Remove(matches[0])
    44  	if err != nil {
    45  		t.Fatalf("os remove %s error: %+v", matches[0], err)
    46  	}
    47  
    48  	os.Remove(filename)
    49  }
    50  
    51  func TestFileWriterStderr(t *testing.T) {
    52  	text1 := "hello file writer!\n"
    53  
    54  	w := &FileWriter{}
    55  
    56  	_, err := wlprintf(w, InfoLevel, text1)
    57  	if err != nil {
    58  		t.Fatalf("file writer error: %+v", err)
    59  	}
    60  }
    61  
    62  func TestFileWriterCreate(t *testing.T) {
    63  	text1 := "hello file writer!\n"
    64  
    65  	w := &FileWriter{
    66  		Filename: "/nonexists/output.log",
    67  	}
    68  
    69  	_, err := wlprintf(w, InfoLevel, text1)
    70  	if err == nil {
    71  		t.Fatalf("file writer should not write")
    72  	}
    73  
    74  	t.Logf("file writer return error: %+v", err)
    75  }
    76  
    77  func TestFileWriterEnsureFolder(t *testing.T) {
    78  	var remove = func(dirname string) {
    79  		matches, _ := filepath.Glob(dirname + "/*")
    80  		for i := range matches {
    81  			os.Remove(matches[i])
    82  		}
    83  		os.Remove(dirname)
    84  	}
    85  
    86  	filename := "logs/file-hostname.log"
    87  	text1 := "1. hello file writer!\n"
    88  	text2 := "2. hello file writer!\n"
    89  	w := &FileWriter{
    90  		Filename:     filename,
    91  		EnsureFolder: true,
    92  	}
    93  
    94  	remove(filepath.Dir(filename))
    95  
    96  	_, err := fmt.Fprint(w, text1)
    97  	if err != nil {
    98  		t.Logf("file writer return error: %+v", err)
    99  	}
   100  
   101  	_, err = fmt.Fprint(w, text2)
   102  	if err != nil {
   103  		t.Logf("file writer return error: %+v", err)
   104  	}
   105  
   106  	err = w.Close()
   107  	if err != nil {
   108  		t.Logf("file writer return error: %+v", err)
   109  	}
   110  
   111  	remove(filepath.Dir(filename))
   112  }
   113  
   114  func TestFileWriterHostname(t *testing.T) {
   115  	filename := "file-hostname.log"
   116  	text1 := "1. hello file writer!\n"
   117  	text2 := "2. hello file writer!\n"
   118  
   119  	for _, hostname := range []bool{false, true} {
   120  		for _, pid := range []bool{false, true} {
   121  			w := &FileWriter{
   122  				Filename:  filename,
   123  				HostName:  hostname,
   124  				ProcessID: pid,
   125  			}
   126  
   127  			_, err := wlprintf(w, InfoLevel, text1)
   128  			if err != nil {
   129  				t.Logf("file writer return error: %+v", err)
   130  			}
   131  
   132  			time.Sleep(time.Second)
   133  			os.Setenv("USER", "root")
   134  			_ = w.Rotate()
   135  			w.Close()
   136  
   137  			_, err = wlprintf(w, InfoLevel, text2)
   138  			if err != nil {
   139  				t.Logf("file writer return error: %+v", err)
   140  			}
   141  
   142  			w.Close()
   143  
   144  			matches, _ := filepath.Glob("file-hostname.*.log")
   145  			for i := range matches {
   146  				os.Remove(matches[i])
   147  			}
   148  
   149  			os.Remove(filename)
   150  		}
   151  	}
   152  }
   153  
   154  func TestFileWriterRotate(t *testing.T) {
   155  	filename := "file-rotate.log"
   156  	header := "# I AM A FILEWRITER HEADER\n"
   157  	text1 := "hello file writer!\n"
   158  	text2 := "hello rotated file writer!\n"
   159  
   160  	// trigger chown
   161  	os.Setenv("USER", "root")
   162  
   163  	w := &FileWriter{
   164  		Filename:   filename,
   165  		MaxBackups: 2,
   166  		Header: func(_ os.FileInfo) []byte {
   167  			return []byte(header)
   168  		},
   169  	}
   170  
   171  	// text 1
   172  	_, err := wlprintf(w, InfoLevel, text1)
   173  	if err != nil {
   174  		t.Fatalf("file writer error: %+v", err)
   175  	}
   176  
   177  	time.Sleep(time.Second)
   178  	_ = w.Rotate()
   179  
   180  	// text 2
   181  	_, err = wlprintf(w, InfoLevel, text2)
   182  	if err != nil {
   183  		t.Fatalf("file writer error: %+v", err)
   184  	}
   185  
   186  	w.Close()
   187  
   188  	matches, err := filepath.Glob("file-rotate.*.log")
   189  	if err != nil {
   190  		t.Fatalf("filepath glob error: %+v", err)
   191  	}
   192  	if len(matches) != 2 {
   193  		t.Fatalf("filepath glob return %+v number mismath", matches)
   194  	}
   195  
   196  	data, err := os.ReadFile(matches[0])
   197  	if err != nil {
   198  		t.Fatalf("read file error: %+v", err)
   199  	}
   200  
   201  	if string(data) != header+text1 {
   202  		t.Fatalf("read file content mismath: data=[%s], text1=[%s]", data, text1)
   203  	}
   204  
   205  	data, err = os.ReadFile(matches[1])
   206  	if err != nil {
   207  		t.Fatalf("read file error: %+v", err)
   208  	}
   209  
   210  	if string(data) != header+text2 {
   211  		t.Fatalf("read file content mismath: data=[%s], text2=[%s]", data, text2)
   212  	}
   213  
   214  	for i := range matches {
   215  		err = os.Remove(matches[i])
   216  		if err != nil {
   217  			t.Fatalf("os remove %s error: %+v", matches[i], err)
   218  		}
   219  	}
   220  
   221  	os.Remove(filename)
   222  }
   223  
   224  func TestFileWriterRotateBySize(t *testing.T) {
   225  	filename := "file-rotate-by-size.log"
   226  	text := "hello file writer!\n"
   227  
   228  	w := &FileWriter{
   229  		Filename:   filename,
   230  		MaxSize:    int64(len(text)) + 2,
   231  		MaxBackups: 2,
   232  	}
   233  
   234  	// text 1
   235  	_, err := wlprintf(w, InfoLevel, text)
   236  	if err != nil {
   237  		t.Fatalf("file writer error: %+v", err)
   238  	}
   239  
   240  	matches, err := filepath.Glob("file-rotate-by-size.*.log")
   241  	if err != nil {
   242  		t.Fatalf("filepath glob error: %+v", err)
   243  	}
   244  	if len(matches) != 1 {
   245  		t.Fatalf("filepath glob return %+v number mismath", matches)
   246  	}
   247  
   248  	time.Sleep(time.Second)
   249  
   250  	// text 2
   251  	_, err = wlprintf(w, InfoLevel, text)
   252  	if err != nil {
   253  		t.Fatalf("file writer error: %+v", err)
   254  	}
   255  
   256  	matches, err = filepath.Glob("file-rotate-by-size.*.log")
   257  	if err != nil {
   258  		t.Fatalf("filepath glob error: %+v", err)
   259  	}
   260  	if len(matches) != 2 {
   261  		t.Fatalf("filepath glob return %+v number mismath", matches)
   262  	}
   263  
   264  	// mock
   265  	os.Setenv("SUDO_UID", "1000")
   266  	os.Setenv("SUDO_GID", "1000")
   267  
   268  	// text 3 ~ 6
   269  	for i := 3; i <= 6; i++ {
   270  		_, err = wlprintf(w, InfoLevel, text)
   271  		time.Sleep(time.Second)
   272  		if err != nil {
   273  			t.Fatalf("file writer error: %+v", err)
   274  		}
   275  	}
   276  
   277  	matches, err = filepath.Glob("file-rotate-by-size.*.log")
   278  	if err != nil {
   279  		t.Fatalf("filepath glob error: %+v", err)
   280  	}
   281  	if len(matches) > w.MaxBackups+1 {
   282  		t.Fatalf("filepath glob return %+v number mismath", matches)
   283  	}
   284  
   285  	w.Close()
   286  
   287  	for i := range matches {
   288  		err = os.Remove(matches[i])
   289  		if err != nil {
   290  			t.Fatalf("os remove %s error: %+v", matches[i], err)
   291  		}
   292  	}
   293  
   294  	os.Remove(filename)
   295  }
   296  
   297  func TestFileWriterBackups(t *testing.T) {
   298  	filename := "file-backup.log"
   299  
   300  	w := &FileWriter{
   301  		Filename:   filename,
   302  		MaxBackups: 1,
   303  	}
   304  
   305  	time.Sleep(time.Second)
   306  	_ = w.Rotate()
   307  
   308  	time.Sleep(time.Second)
   309  	_ = w.Rotate()
   310  	w.Close()
   311  
   312  	matches, err := filepath.Glob("file-backup.*.log")
   313  	if err != nil {
   314  		t.Fatalf("filepath glob error: %+v", err)
   315  	}
   316  	if len(matches) != 2 {
   317  		t.Fatalf("filepath glob return %+v number mismath", matches)
   318  	}
   319  
   320  	matches, _ = filepath.Glob("file-backup.*.log")
   321  	for i := range matches {
   322  		err = os.Remove(matches[i])
   323  		if err != nil {
   324  			t.Fatalf("os remove %s error: %+v", matches[i], err)
   325  		}
   326  	}
   327  
   328  	os.Remove(filename)
   329  }
   330  
   331  func TestFileWriterFileargs(t *testing.T) {
   332  	filename := "file-output.log"
   333  	d := time.Date(2020, 8, 12, 16, 7, 0, 0, time.UTC)
   334  
   335  	t.Run("neither hostname nor pid appears", func(t *testing.T) {
   336  		w := &FileWriter{Filename: filename}
   337  		expected := "file-output.2020-08-12T16-07-00.log"
   338  		if name, _, _ := w.fileargs(d); name != expected {
   339  			t.Fatalf("expected: %q, actual: %q", expected, name)
   340  		}
   341  	})
   342  	t.Run("hostname or pid appears", func(t *testing.T) {
   343  		origHost := hostname
   344  		hostname = "shire"
   345  		defer func() { hostname = origHost }()
   346  		origPid := pid
   347  		pid = 198400
   348  		defer func() { pid = origPid }()
   349  
   350  		w := &FileWriter{Filename: filename, HostName: true}
   351  
   352  		cases := []struct {
   353  			hostName  bool
   354  			processID bool
   355  			expected  string
   356  		}{
   357  			{hostName: true, expected: "file-output.2020-08-12T16-07-00.shire.log"},
   358  			{processID: true, expected: "file-output.2020-08-12T16-07-00.198400.log"},
   359  			{hostName: true, processID: true, expected: "file-output.2020-08-12T16-07-00.shire-198400.log"},
   360  		}
   361  		for _, c := range cases {
   362  			w.HostName = c.hostName
   363  			w.ProcessID = c.processID
   364  			if name, _, _ := w.fileargs(d); name != c.expected {
   365  				t.Fatalf("expected: %q, actual: %q", c.expected, name)
   366  			}
   367  		}
   368  	})
   369  }