github.com/wtsi-ssg/wrstat/v3@v3.2.3/stat/stat_test.go (about)

     1  /*******************************************************************************
     2   * Copyright (c) 2021 Genome Research Ltd.
     3   *
     4   * Author: Sendu Bala <sb10@sanger.ac.uk>
     5   *
     6   * Permission is hereby granted, free of charge, to any person obtaining
     7   * a copy of this software and associated documentation files (the
     8   * "Software"), to deal in the Software without restriction, including
     9   * without limitation the rights to use, copy, modify, merge, publish,
    10   * distribute, sublicense, and/or sell copies of the Software, and to
    11   * permit persons to whom the Software is furnished to do so, subject to
    12   * the following conditions:
    13   *
    14   * The above copyright notice and this permission notice shall be included
    15   * in all copies or substantial portions of the Software.
    16   *
    17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    18   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    19   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    20   * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    21   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    22   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    23   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    24   ******************************************************************************/
    25  
    26  package stat
    27  
    28  import (
    29  	"bytes"
    30  	"os"
    31  	"path/filepath"
    32  	"testing"
    33  	"time"
    34  
    35  	"github.com/inconshreveable/log15"
    36  	. "github.com/smartystreets/goconvey/convey"
    37  )
    38  
    39  func TestLstat(t *testing.T) {
    40  	timeout := 50 * time.Millisecond
    41  	attempts := 2
    42  
    43  	Convey("Given a Statter with large timeout", t, func() {
    44  		buff, l := newLogger()
    45  
    46  		s := WithTimeout(timeout, attempts, l)
    47  		So(s, ShouldNotBeNil)
    48  
    49  		Convey("you can call Lstat on it", func() {
    50  			info, err := s.Lstat("/foo/bar")
    51  			So(err, ShouldNotBeNil)
    52  			So(info, ShouldBeNil)
    53  
    54  			pathEmpty, pathContent := createTestFiles(t)
    55  
    56  			info, err = s.Lstat(pathEmpty)
    57  			So(err, ShouldBeNil)
    58  			So(info, ShouldNotBeNil)
    59  			So(info.Size(), ShouldEqual, 0)
    60  
    61  			info, err = s.Lstat(pathContent)
    62  			So(err, ShouldBeNil)
    63  			So(info.Size(), ShouldEqual, 1)
    64  			So(buff.String(), ShouldBeBlank)
    65  
    66  			Convey("but that fails with a tiny timeout", func() {
    67  				s = WithTimeout(1*time.Nanosecond, attempts, l)
    68  				So(s, ShouldNotBeNil)
    69  
    70  				defer func() { os.Unsetenv("WRSTAT_TEST_LSTAT") }()
    71  				os.Setenv("WRSTAT_TEST_LSTAT", "long")
    72  
    73  				info, err = s.Lstat(pathContent)
    74  				So(err, ShouldNotBeNil)
    75  				So(info, ShouldBeNil)
    76  				logStr := buff.String()
    77  				So(logStr, ShouldContainSubstring, `lvl=warn msg="an lstat call exceeded timeout, will retry"`)
    78  				So(logStr, ShouldContainSubstring, `lvl=warn msg="an lstat call exceeded timeout, giving up"`)
    79  				So(logStr, ShouldContainSubstring, `attempts=1`)
    80  				So(logStr, ShouldContainSubstring, `attempts=2`)
    81  				So(logStr, ShouldContainSubstring, `attempts=3`)
    82  				So(logStr, ShouldNotContainSubstring, `attempts=4`)
    83  
    84  				buff.Reset()
    85  				info, err = s.Lstat("/foo")
    86  				So(err, ShouldNotBeNil)
    87  				So(info, ShouldBeNil)
    88  				logStr = buff.String()
    89  				So(logStr, ShouldContainSubstring, `lvl=warn msg="an lstat call exceeded timeout, will retry"`)
    90  				So(logStr, ShouldContainSubstring, `lvl=warn msg="an lstat call exceeded timeout, giving up"`)
    91  				So(logStr, ShouldContainSubstring, `attempts=1`)
    92  				So(logStr, ShouldContainSubstring, `attempts=2`)
    93  				So(logStr, ShouldContainSubstring, `attempts=3`)
    94  				So(logStr, ShouldNotContainSubstring, `attempts=4`)
    95  			})
    96  		})
    97  	})
    98  }
    99  
   100  // newLogger returns a logger that logs to the returned buffer.
   101  func newLogger() (*bytes.Buffer, log15.Logger) {
   102  	buff := new(bytes.Buffer)
   103  	l := log15.New()
   104  	l.SetHandler(log15.StreamHandler(buff, log15.LogfmtFormat()))
   105  
   106  	return buff, l
   107  }
   108  
   109  // createTestFiles creates 2 temp files, the first empty, the second 1 byte
   110  // long, and returns their paths.
   111  func createTestFiles(t *testing.T) (string, string) {
   112  	t.Helper()
   113  
   114  	dir := t.TempDir()
   115  	pathEmpty := filepath.Join(dir, "empty")
   116  
   117  	f, err := os.Create(pathEmpty)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	f.Close()
   123  
   124  	pathContent := filepath.Join(dir, "content")
   125  
   126  	f, err = os.Create(pathContent)
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  
   131  	_, err = f.WriteString("1")
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	f.Close()
   137  
   138  	return pathEmpty, pathContent
   139  }