github.phpd.cn/thought-machine/please@v12.2.0+incompatible/tools/cache/server/cache_stress_test.go (about) 1 // Small stress test for the cache to help flush out concurrency bugs. 2 package server 3 4 import ( 5 "crypto/sha1" 6 "fmt" 7 "math/rand" 8 "os" 9 "strconv" 10 "sync" 11 "testing" 12 13 "github.com/stretchr/testify/assert" 14 "gopkg.in/op/go-logging.v1" 15 ) 16 17 var cache *Cache 18 19 const size = 1000 20 21 func init() { 22 logging.SetLevel(logging.NOTICE, "server") 23 cache = newCache("cache") 24 } 25 26 func TestStoreFiles(t *testing.T) { 27 // Store 1000 files in parallel 28 var wg sync.WaitGroup 29 wg.Add(size) 30 for _, i := range rand.Perm(size) { 31 go func(i int) { 32 path, contents := artifact(i) 33 assert.NoError(t, cache.StoreArtifact(path, contents, "")) 34 wg.Done() 35 }(i) 36 } 37 wg.Wait() 38 } 39 40 func TestRetrieveFiles(t *testing.T) { 41 // Store 1000 files in parallel 42 var wg sync.WaitGroup 43 wg.Add(size) 44 for _, i := range rand.Perm(size) { 45 go func(i int) { 46 path, contents := artifact(i) 47 arts, err := cache.RetrieveArtifact(path) 48 if os.IsNotExist(err) { // It's allowed not to exist. 49 wg.Done() 50 return 51 } 52 assert.NoError(t, err) 53 assert.Equal(t, 1, len(arts)) 54 assert.Equal(t, contents, arts[0].Body) 55 wg.Done() 56 }(i) 57 } 58 wg.Wait() 59 } 60 61 func TestDeleteFiles(t *testing.T) { 62 // Delete 1000 files in parallel 63 var wg sync.WaitGroup 64 wg.Add(size) 65 for _, i := range rand.Perm(size) { 66 go func(i int) { 67 path, _ := artifact(i) 68 assert.NoError(t, cache.DeleteArtifact(path)) 69 wg.Done() 70 }(i) 71 } 72 wg.Wait() 73 } 74 75 func TestInParallel(t *testing.T) { 76 // Run all above tests in parallel. 77 var wg sync.WaitGroup 78 wg.Add(3) 79 go func() { 80 TestStoreFiles(t) 81 wg.Done() 82 }() 83 go func() { 84 TestRetrieveFiles(t) 85 wg.Done() 86 }() 87 go func() { 88 TestDeleteFiles(t) 89 wg.Done() 90 }() 91 wg.Wait() 92 } 93 94 func TestInParallelWithCleaning(t *testing.T) { 95 // Run store & retrieve tests in parallel & cleaning at the same time. 96 // It's too awkward to write a reliable test with deleting too and actually 97 // guarantee that the cleaner does anything. 98 var wg sync.WaitGroup 99 wg.Add(3) 100 go func() { 101 TestStoreFiles(t) 102 wg.Done() 103 }() 104 go func() { 105 TestRetrieveFiles(t) 106 wg.Done() 107 }() 108 go func() { 109 // Each artifact is sha1.Size bytes long, so this should guarantee it runs once. 110 for !cache.singleClean(sha1.Size*size/10, sha1.Size*size/2) { 111 } 112 // Now run it a bunch more times. 113 for i := 0; i < 100; i++ { 114 cache.singleClean(sha1.Size*size/10, sha1.Size*size/2) 115 } 116 wg.Done() 117 }() 118 wg.Wait() 119 } 120 121 func artifact(i int) (string, []byte) { 122 path := fmt.Sprintf("src/%d/%d/%d.dat", i/100, i/10, i) 123 contents := sha1.Sum([]byte(strconv.Itoa(i))) 124 return path, contents[:] 125 }