github.com/sercand/please@v13.4.0+incompatible/src/cache/rpc_cache_test.go (about) 1 package cache 2 3 import ( 4 "os" 5 "path" 6 "runtime" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/assert" 12 "google.golang.org/grpc" 13 14 "github.com/thought-machine/please/src/core" 15 "github.com/thought-machine/please/tools/cache/server" 16 ) 17 18 var ( 19 label core.BuildLabel 20 rpccache *rpcCache 21 ) 22 23 func init() { 24 runtime.GOMAXPROCS(1) // Don't allow tests to run in parallel, they should work but makes debugging tricky 25 label = core.NewBuildLabel("pkg/name", "label_name") 26 27 // Move this directory from test_data to somewhere local. 28 // This is easier than changing our working dir & a better test of some things too. 29 if err := os.Rename("src/cache/test_data/plz-out", "plz-out"); err != nil { 30 log.Fatalf("Failed to prepare test directory: %s\n", err) 31 } 32 33 _, addr := startServer("", "", "") 34 rpccache = buildClient(addr, "") 35 } 36 37 func startServer(keyFile, certFile, caCertFile string) (*grpc.Server, string) { 38 // Arbitrary large numbers so the cleaner never needs to run. 39 cache := server.NewCache("src/cache/test_data", 20*time.Hour, 100000, 100000000, 1000000000) 40 s, lis := server.BuildGrpcServer(0, cache, nil, keyFile, certFile, caCertFile, "", "") 41 go s.Serve(lis) 42 return s, lis.Addr().String() 43 } 44 45 func buildClient(addr, ca string) *rpcCache { 46 config := core.DefaultConfiguration() 47 if err := config.Cache.RPCURL.UnmarshalFlag(strings.Replace(addr, "[::]", "localhost", 1)); err != nil { 48 log.Fatalf("%s", err) 49 } 50 config.Cache.RPCWriteable = true 51 config.Cache.RPCCACert = ca 52 53 cache, err := newRPCCache(config) 54 if err != nil { 55 log.Fatalf("Failed to create RPC cache: %s", err) 56 } 57 58 // Busy-wait sucks but this isn't supposed to be visible from outside. 59 for i := 0; i < 10 && !cache.Connected && cache.Connecting; i++ { 60 time.Sleep(100 * time.Millisecond) 61 } 62 return cache 63 } 64 65 func TestStore(t *testing.T) { 66 target := core.NewBuildTarget(label) 67 target.AddOutput("testfile2") 68 rpccache.Store(target, []byte("test_key")) 69 expectedPath := path.Join("src/cache/test_data", core.OsArch, "pkg/name", "label_name", "dGVzdF9rZXk", target.Outputs()[0]) 70 if !core.PathExists(expectedPath) { 71 t.Errorf("Test file %s was not stored in cache.", expectedPath) 72 } 73 } 74 75 func TestRetrieve(t *testing.T) { 76 target := core.NewBuildTarget(label) 77 target.AddOutput("testfile") 78 if !rpccache.Retrieve(target, []byte("test_key")) { 79 t.Error("Artifact expected and not found.") 80 } 81 } 82 83 func TestStoreAndRetrieve(t *testing.T) { 84 target := core.NewBuildTarget(label) 85 target.AddOutput("testfile3") 86 rpccache.Store(target, []byte("test_key")) 87 // Remove the file so we can test retrieval correctly 88 outPath := path.Join(target.OutDir(), target.Outputs()[0]) 89 if err := os.Remove(outPath); err != nil { 90 t.Errorf("Failed to remove artifact: %s", err) 91 } 92 if !rpccache.Retrieve(target, []byte("test_key")) { 93 t.Error("Artifact expected and not found.") 94 } else if !core.PathExists(outPath) { 95 t.Errorf("Artifact %s doesn't exist after alleged cache retrieval", outPath) 96 } 97 } 98 99 func TestClean(t *testing.T) { 100 target := core.NewBuildTarget(label) 101 rpccache.Clean(target) 102 filename := path.Join("src/cache/test_data", core.OsArch, "pkg/name/label_name") 103 if core.PathExists(filename) { 104 t.Errorf("File %s was not removed from cache.", filename) 105 } 106 } 107 108 func TestDisconnectAfterEnoughErrors(t *testing.T) { 109 // Need a separate cache for this so we don't interfere with the other tests. 110 s, addr := startServer("", "", "") 111 c := buildClient(addr, "") 112 113 target := core.NewBuildTarget(label) 114 target.AddOutput("testfile4") 115 key := []byte("test_key") 116 c.Store(target, []byte("test_key")) 117 assert.True(t, c.Retrieve(target, key)) 118 s.Stop() 119 // Now after we hit the max number of errors it should disconnect. 120 for i := 0; i < maxErrors; i++ { 121 assert.True(t, c.Connected) 122 assert.False(t, c.Retrieve(target, key)) 123 } 124 assert.False(t, c.Connected) 125 } 126 127 func TestLoadCertificates(t *testing.T) { 128 _, err := loadAuth("", "src/cache/test_data/cert.pem", "src/cache/test_data/key.pem") 129 assert.NoError(t, err, "Trivial case with PEM files already") 130 _, err = loadAuth("", "id_rsa.pub", "id_rsa") 131 assert.Error(t, err, "Fails because files don't exist") 132 } 133 134 func TestRetrieveSSL(t *testing.T) { 135 // Need a separate cache for this so we don't interfere with the other tests. 136 s, addr := startServer("src/cache/test_data/key.pem", "src/cache/test_data/cert_signed.pem", "src/cache/test_data/ca.pem") 137 defer s.Stop() 138 c := buildClient(addr, "") 139 assert.False(t, c.Connected, "Should fail to connect without giving the client a CA cert") 140 c = buildClient(addr, "src/cache/test_data/ca.pem") 141 assert.True(t, c.Connected, "Connects OK this time") 142 }