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  }