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 }