github.com/anuvu/nomad@v0.8.7-atom1/client/driver/logging/rotator_test.go (about)

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