github.com/weaviate/weaviate@v1.24.6/modules/text2vec-transformers/clients/startup_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package clients 13 14 import ( 15 "context" 16 "net/http" 17 "net/http/httptest" 18 "regexp" 19 "strings" 20 "testing" 21 "time" 22 23 "github.com/sirupsen/logrus" 24 "github.com/sirupsen/logrus/hooks/test" 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func TestWaitForStartup(t *testing.T) { 30 t.Run("when common server is immediately ready", func(t *testing.T) { 31 server := httptest.NewServer(&testReadyHandler{t: t}) 32 defer server.Close() 33 v := New(server.URL, server.URL, 0, nullLogger()) 34 err := v.WaitForStartup(context.Background(), 150*time.Millisecond) 35 36 assert.Nil(t, err) 37 }) 38 39 t.Run("when passage and query servers are immediately ready", func(t *testing.T) { 40 serverPassage := httptest.NewServer(&testReadyHandler{t: t}) 41 serverQuery := httptest.NewServer(&testReadyHandler{t: t}) 42 defer serverPassage.Close() 43 defer serverQuery.Close() 44 v := New(serverPassage.URL, serverQuery.URL, 0, nullLogger()) 45 err := v.WaitForStartup(context.Background(), 150*time.Millisecond) 46 47 assert.Nil(t, err) 48 }) 49 50 t.Run("when common server is down", func(t *testing.T) { 51 url := "http://nothing-running-at-this-url" 52 v := New(url, url, 0, nullLogger()) 53 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 54 defer cancel() 55 err := v.WaitForStartup(ctx, 50*time.Millisecond) 56 57 require.NotNil(t, err, nullLogger()) 58 assert.Contains(t, err.Error(), "init context expired before remote was ready: send check ready request") 59 assertContainsEither(t, err.Error(), "dial tcp", "context deadline exceeded") 60 assert.NotContains(t, err.Error(), "[passage]") 61 assert.NotContains(t, err.Error(), "[query]") 62 }) 63 64 t.Run("when passage and query servers are down", func(t *testing.T) { 65 urlPassage := "http://nothing-running-at-this-url" 66 urlQuery := "http://nothing-running-at-this-url-either" 67 v := New(urlPassage, urlQuery, 0, nullLogger()) 68 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 69 defer cancel() 70 err := v.WaitForStartup(ctx, 50*time.Millisecond) 71 72 require.NotNil(t, err, nullLogger()) 73 assert.Contains(t, err.Error(), "[passage] init context expired before remote was ready: send check ready request") 74 assert.Contains(t, err.Error(), "[query] init context expired before remote was ready: send check ready request") 75 assertContainsEither(t, err.Error(), "dial tcp", "context deadline exceeded") 76 }) 77 78 t.Run("when common server is alive, but not ready", func(t *testing.T) { 79 server := httptest.NewServer(&testReadyHandler{ 80 t: t, 81 readyTime: time.Now().Add(time.Hour), 82 }) 83 defer server.Close() 84 v := New(server.URL, server.URL, 0, nullLogger()) 85 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 86 defer cancel() 87 err := v.WaitForStartup(ctx, 50*time.Millisecond) 88 89 require.NotNil(t, err) 90 assert.Contains(t, err.Error(), "init context expired before remote was ready") 91 assertContainsEither(t, err.Error(), "not ready: status 503", "context deadline exceeded") 92 assert.NotContains(t, err.Error(), "[passage]") 93 assert.NotContains(t, err.Error(), "[query]") 94 }) 95 96 t.Run("when passage and query servers are alive, but not ready", func(t *testing.T) { 97 rt := time.Now().Add(time.Hour) 98 serverPassage := httptest.NewServer(&testReadyHandler{ 99 t: t, 100 readyTime: rt, 101 }) 102 serverQuery := httptest.NewServer(&testReadyHandler{ 103 t: t, 104 readyTime: rt, 105 }) 106 defer serverPassage.Close() 107 defer serverQuery.Close() 108 v := New(serverPassage.URL, serverQuery.URL, 0, nullLogger()) 109 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 110 defer cancel() 111 err := v.WaitForStartup(ctx, 50*time.Millisecond) 112 113 require.NotNil(t, err) 114 assert.Contains(t, err.Error(), "[passage] init context expired before remote was ready") 115 assert.Contains(t, err.Error(), "[query] init context expired before remote was ready") 116 assertContainsEither(t, err.Error(), "not ready: status 503", "context deadline exceeded") 117 }) 118 119 t.Run("when passage and query servers are alive, but query one is not ready", func(t *testing.T) { 120 serverPassage := httptest.NewServer(&testReadyHandler{t: t}) 121 serverQuery := httptest.NewServer(&testReadyHandler{ 122 t: t, 123 readyTime: time.Now().Add(1 * time.Minute), 124 }) 125 defer serverPassage.Close() 126 defer serverQuery.Close() 127 v := New(serverPassage.URL, serverQuery.URL, 0, nullLogger()) 128 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 129 defer cancel() 130 err := v.WaitForStartup(ctx, 50*time.Millisecond) 131 132 require.NotNil(t, err) 133 assert.Contains(t, err.Error(), "[query] init context expired before remote was ready") 134 assertContainsEither(t, err.Error(), "not ready: status 503", "context deadline exceeded") 135 assert.NotContains(t, err.Error(), "[passage]") 136 }) 137 138 t.Run("when common server is initially not ready, but then becomes ready", func(t *testing.T) { 139 server := httptest.NewServer(&testReadyHandler{ 140 t: t, 141 readyTime: time.Now().Add(100 * time.Millisecond), 142 }) 143 v := New(server.URL, server.URL, 0, nullLogger()) 144 defer server.Close() 145 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 146 defer cancel() 147 err := v.WaitForStartup(ctx, 50*time.Millisecond) 148 149 require.Nil(t, err) 150 }) 151 152 t.Run("when passage and query servers are initially not ready, but then become ready", func(t *testing.T) { 153 serverPassage := httptest.NewServer(&testReadyHandler{ 154 t: t, 155 readyTime: time.Now().Add(100 * time.Millisecond), 156 }) 157 serverQuery := httptest.NewServer(&testReadyHandler{ 158 t: t, 159 readyTime: time.Now().Add(150 * time.Millisecond), 160 }) 161 defer serverPassage.Close() 162 defer serverQuery.Close() 163 v := New(serverPassage.URL, serverQuery.URL, 0, nullLogger()) 164 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 165 defer cancel() 166 err := v.WaitForStartup(ctx, 50*time.Millisecond) 167 168 require.Nil(t, err) 169 }) 170 } 171 172 type testReadyHandler struct { 173 t *testing.T 174 // the test handler will report as not ready before the time has passed 175 readyTime time.Time 176 } 177 178 func (f *testReadyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 179 assert.Equal(f.t, "/.well-known/ready", r.URL.String()) 180 assert.Equal(f.t, http.MethodGet, r.Method) 181 182 if time.Since(f.readyTime) < 0 { 183 w.WriteHeader(http.StatusServiceUnavailable) 184 } else { 185 w.WriteHeader(http.StatusNoContent) 186 } 187 } 188 189 func nullLogger() logrus.FieldLogger { 190 l, _ := test.NewNullLogger() 191 return l 192 } 193 194 func assertContainsEither(t *testing.T, str string, contains ...string) { 195 reg := regexp.MustCompile(strings.Join(contains, "|")) 196 assert.Regexp(t, reg, str) 197 }