github.phpd.cn/thought-machine/please@v12.2.0+incompatible/src/cache/dir_cache_test.go (about) 1 package cache 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "io/ioutil" 7 "os" 8 "path" 9 "runtime" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 14 "core" 15 ) 16 17 var hash = []byte("12345678901234567890") 18 var b64Hash = base64.URLEncoding.EncodeToString(hash) 19 20 func writeFile(filename string, size int) { 21 contents := bytes.Repeat([]byte{'p', 'l', 'z'}, size) // so this is three times the size... 22 if err := os.MkdirAll(path.Dir(filename), core.DirPermissions); err != nil { 23 panic(err) 24 } 25 if err := ioutil.WriteFile(filename, contents, 0644); err != nil { 26 panic(err) 27 } 28 } 29 30 func cachePath(target *core.BuildTarget) string { 31 return path.Join(".plz-cache-"+target.Label.PackageName, target.Label.PackageName, target.Label.Name, b64Hash, target.Outputs()[0]) 32 } 33 34 func inCache(target *core.BuildTarget) bool { 35 dest := cachePath(target) 36 log.Debug("Checking for %s", dest) 37 return core.PathExists(dest) 38 } 39 40 func TestStoreAndRetrieve(t *testing.T) { 41 cache := makeCache(".plz-cache-test1") 42 target := makeTarget("//test1:target1", 20) 43 cache.Store(target, hash) 44 // Should now exist in cache at this path 45 assert.True(t, inCache(target)) 46 assert.True(t, cache.Retrieve(target, hash)) 47 // Should be able to store it again without problems 48 cache.Store(target, hash) 49 assert.True(t, inCache(target)) 50 assert.True(t, cache.Retrieve(target, hash)) 51 } 52 53 func TestCleanNoop(t *testing.T) { 54 cache := makeCache(".plz-cache-test2") 55 target1 := makeTarget("//test2:target1", 2000) 56 cache.Store(target1, hash) 57 assert.True(t, inCache(target1)) 58 target2 := makeTarget("//test2:target2", 2000) 59 cache.Store(target2, hash) 60 assert.True(t, inCache(target2)) 61 // Doesn't clean anything this time because the high water mark is sufficiently high 62 totalSize := cache.clean(20000, 1000) 63 assert.EqualValues(t, 12000, totalSize) 64 assert.True(t, inCache(target1)) 65 assert.True(t, inCache(target2)) 66 } 67 68 func TestCleanNoop2(t *testing.T) { 69 cache := makeCache(".plz-cache-test3") 70 target1 := makeTarget("//test3:target1", 2000) 71 cache.Store(target1, hash) 72 assert.True(t, inCache(target1)) 73 target2 := makeTarget("//test3:target2", 2000) 74 cache.Store(target2, hash) 75 assert.True(t, inCache(target2)) 76 // Doesn't clean anything this time, the high water mark is lower but both targets have 77 // just been built. 78 totalSize := cache.clean(10000, 1000) 79 assert.EqualValues(t, 12000, totalSize) 80 assert.True(t, inCache(target1)) 81 assert.True(t, inCache(target2)) 82 } 83 84 func TestCleanForReal(t *testing.T) { 85 cache := makeCache(".plz-cache-test4") 86 target1 := makeTarget("//test4:target1", 2000) 87 cache.Store(target1, hash) 88 assert.True(t, inCache(target1)) 89 target2 := makeTarget("//test4:target2", 2000) 90 writeFile(cachePath(target2), 2000) 91 assert.True(t, inCache(target2)) 92 // This time it should clean target2, because target1 has just been stored 93 totalSize := cache.clean(10000, 1000) 94 assert.EqualValues(t, 6000, totalSize) 95 assert.True(t, inCache(target1)) 96 assert.False(t, inCache(target2)) 97 } 98 99 func TestCleanForReal2(t *testing.T) { 100 cache := makeCache(".plz-cache-test5") 101 target1 := makeTarget("//test5:target1", 2000) 102 writeFile(cachePath(target1), 2000) 103 assert.True(t, inCache(target1)) 104 target2 := makeTarget("//test5:target2", 2000) 105 cache.Store(target2, hash) 106 assert.True(t, inCache(target2)) 107 // This time it should clean target1, because target2 has just been stored 108 totalSize := cache.clean(10000, 1000) 109 assert.EqualValues(t, 6000, totalSize) 110 assert.False(t, inCache(target1)) 111 assert.True(t, inCache(target2)) 112 } 113 114 func TestCleanForReal3(t *testing.T) { 115 t.Skip("Failing on CI, not sure why") 116 if runtime.GOOS != "linux" { 117 // The various sizes that follow assume specific things about Linux's filesystem 118 // (specifically that directories will cost 4k - which might also be ext4 specific?). 119 t.Skip("assumes things about Linux's filesystem") 120 } 121 cache := makeCache(".plz-cache-test6") 122 target1 := makeTarget("//test6:target1", 2000) 123 writeFile(cachePath(target1), 2000) 124 assert.True(t, inCache(target1)) 125 target2 := makeTarget("//test6:target2", 2000) 126 writeFile(cachePath(target2), 2000) 127 assert.True(t, inCache(target2)) 128 // This time it should clean one of the two targets, but it is indeterminate which one. 129 // N.B. We allow a bit over the 6k you'd expect - each directory costs 4k as well. 130 totalSize := cache.clean(12000, 11000) 131 assert.EqualValues(t, 10096, totalSize) // again +4k for a directory 132 assert.True(t, inCache(target1) != inCache(target2)) 133 } 134 135 func makeCache(dir string) *dirCache { 136 config := core.DefaultConfiguration() 137 config.Cache.Dir = dir 138 config.Cache.DirClean = false // We will do this explicitly 139 return newDirCache(config) 140 } 141 142 func makeTarget(label string, size int) *core.BuildTarget { 143 target := core.NewBuildTarget(core.ParseBuildLabel(label, "")) 144 target.AddOutput("test.go") 145 writeFile(path.Join("plz-out/gen", target.Label.PackageName, "test.go"), size) 146 return target 147 }