Home | History | Annotate | Download | only in logger
      1 // Copyright 2017 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package logger
     16 
     17 import (
     18 	"bytes"
     19 	"fmt"
     20 	"io"
     21 	"io/ioutil"
     22 	"os"
     23 	"os/exec"
     24 	"path/filepath"
     25 	"reflect"
     26 	"sort"
     27 	"syscall"
     28 	"testing"
     29 )
     30 
     31 func TestCreateFileWithRotation(t *testing.T) {
     32 	dir, err := ioutil.TempDir("", "test-rotation")
     33 	if err != nil {
     34 		t.Fatalf("Failed to get TempDir: %v", err)
     35 	}
     36 	defer os.RemoveAll(dir)
     37 
     38 	file := filepath.Join(dir, "build.log")
     39 
     40 	writeFile := func(name string, data string) {
     41 		f, err := CreateFileWithRotation(name, 3)
     42 		if err != nil {
     43 			t.Fatalf("Failed to create file: %v", err)
     44 		}
     45 		if n, err := io.WriteString(f, data); err == nil && n < len(data) {
     46 			t.Fatalf("Short write")
     47 		} else if err != nil {
     48 			t.Fatalf("Failed to write: %v", err)
     49 		}
     50 		if err := f.Close(); err != nil {
     51 			t.Fatalf("Failed to close: %v", err)
     52 		}
     53 	}
     54 
     55 	writeFile(file, "a")
     56 	writeFile(file, "b")
     57 	writeFile(file, "c")
     58 	writeFile(file, "d")
     59 	writeFile(file, "e")
     60 
     61 	d, err := os.Open(dir)
     62 	if err != nil {
     63 		t.Fatalf("Failed to open dir: %v", err)
     64 	}
     65 	names, err := d.Readdirnames(0)
     66 	if err != nil {
     67 		t.Fatalf("Failed to read dir: %v", err)
     68 	}
     69 	sort.Strings(names)
     70 	expected := []string{".lock_build.log", "build.1.log", "build.2.log", "build.3.log", "build.log"}
     71 	if !reflect.DeepEqual(names, expected) {
     72 		t.Errorf("File list does not match.")
     73 		t.Errorf("     got: %v", names)
     74 		t.Errorf("expected: %v", expected)
     75 		t.FailNow()
     76 	}
     77 
     78 	expectFileContents := func(name, expected string) {
     79 		data, err := ioutil.ReadFile(filepath.Join(dir, name))
     80 		if err != nil {
     81 			t.Errorf("Error reading file: %v", err)
     82 			return
     83 		}
     84 		str := string(data)
     85 		if str != expected {
     86 			t.Errorf("Contents of %v does not match.", name)
     87 			t.Errorf("     got: %v", data)
     88 			t.Errorf("expected: %v", expected)
     89 		}
     90 	}
     91 
     92 	expectFileContents("build.log", "e")
     93 	expectFileContents("build.1.log", "d")
     94 	expectFileContents("build.2.log", "c")
     95 	expectFileContents("build.3.log", "b")
     96 }
     97 
     98 func TestPanic(t *testing.T) {
     99 	if os.Getenv("ACTUALLY_PANIC") == "1" {
    100 		panicValue := "foo"
    101 		log := New(&bytes.Buffer{})
    102 
    103 		defer func() {
    104 			p := recover()
    105 
    106 			if p == panicValue {
    107 				os.Exit(42)
    108 			} else {
    109 				fmt.Fprintf(os.Stderr, "Expected %q, got %v\n", panicValue, p)
    110 				os.Exit(3)
    111 			}
    112 		}()
    113 		defer log.Cleanup()
    114 
    115 		log.Panic(panicValue)
    116 		os.Exit(2)
    117 		return
    118 	}
    119 
    120 	// Run this in an external process so that we don't pollute stderr
    121 	cmd := exec.Command(os.Args[0], "-test.run=TestPanic")
    122 	cmd.Env = append(os.Environ(), "ACTUALLY_PANIC=1")
    123 	err := cmd.Run()
    124 	if e, ok := err.(*exec.ExitError); ok && e.Sys().(syscall.WaitStatus).ExitStatus() == 42 {
    125 		return
    126 	}
    127 	t.Errorf("Expected process to exit with status 42, got %v", err)
    128 }
    129 
    130 func TestFatal(t *testing.T) {
    131 	if os.Getenv("ACTUALLY_FATAL") == "1" {
    132 		log := New(&bytes.Buffer{})
    133 		defer func() {
    134 			// Shouldn't get here
    135 			os.Exit(3)
    136 		}()
    137 		defer log.Cleanup()
    138 		log.Fatal("Test")
    139 		os.Exit(0)
    140 		return
    141 	}
    142 
    143 	cmd := exec.Command(os.Args[0], "-test.run=TestFatal")
    144 	cmd.Env = append(os.Environ(), "ACTUALLY_FATAL=1")
    145 	err := cmd.Run()
    146 	if e, ok := err.(*exec.ExitError); ok && e.Sys().(syscall.WaitStatus).ExitStatus() == 1 {
    147 		return
    148 	}
    149 	t.Errorf("Expected process to exit with status 1, got %v", err)
    150 }
    151 
    152 func TestNonFatal(t *testing.T) {
    153 	if os.Getenv("ACTUAL_TEST") == "1" {
    154 		log := New(&bytes.Buffer{})
    155 		defer log.Cleanup()
    156 		log.Println("Test")
    157 		return
    158 	}
    159 
    160 	cmd := exec.Command(os.Args[0], "-test.run=TestNonFatal")
    161 	cmd.Env = append(os.Environ(), "ACTUAL_TEST=1")
    162 	err := cmd.Run()
    163 	if e, ok := err.(*exec.ExitError); ok || (ok && !e.Success()) {
    164 		t.Errorf("Expected process to exit cleanly, got %v", err)
    165 	}
    166 }
    167 
    168 func TestRecoverFatal(t *testing.T) {
    169 	log := New(&bytes.Buffer{})
    170 	defer func() {
    171 		if p := recover(); p != nil {
    172 			t.Errorf("Unexpected panic: %#v", p)
    173 		}
    174 	}()
    175 	defer Recover(func(err error) {
    176 		if err.Error() != "Test" {
    177 			t.Errorf("Expected %q, but got %q", "Test", err.Error())
    178 		}
    179 	})
    180 	log.Fatal("Test")
    181 	t.Errorf("Should not get here")
    182 }
    183 
    184 func TestRecoverNonFatal(t *testing.T) {
    185 	log := New(&bytes.Buffer{})
    186 	defer func() {
    187 		if p := recover(); p == nil {
    188 			t.Errorf("Panic not thrown")
    189 		} else if p != "Test" {
    190 			t.Errorf("Expected %q, but got %#v", "Test", p)
    191 		}
    192 	}()
    193 	defer Recover(func(err error) {
    194 		t.Errorf("Recover function should not be called")
    195 	})
    196 	log.Panic("Test")
    197 	t.Errorf("Should not get here")
    198 }
    199 
    200 func TestRuntimePanic(t *testing.T) {
    201 	defer func() {
    202 		if p := recover(); p == nil {
    203 			t.Errorf("Panic not thrown")
    204 		}
    205 	}()
    206 	defer Recover(func(err error) {
    207 		t.Errorf("Recover function should not be called")
    208 	})
    209 	var i *int
    210 	*i = 0
    211 	t.Errorf("Should not get here")
    212 }
    213