github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchtransport/connection_integration_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // 3 // The OpenSearch Contributors require contributions made to 4 // this file be licensed under the Apache-2.0 license or a 5 // compatible open source license. 6 // 7 // Modifications Copyright OpenSearch Contributors. See 8 // GitHub history for details. 9 10 // Licensed to Elasticsearch B.V. under one or more contributor 11 // license agreements. See the NOTICE file distributed with 12 // this work for additional information regarding copyright 13 // ownership. Elasticsearch B.V. licenses this file to you under 14 // the Apache License, Version 2.0 (the "License"); you may 15 // not use this file except in compliance with the License. 16 // You may obtain a copy of the License at 17 // 18 // http://www.apache.org/licenses/LICENSE-2.0 19 // 20 // Unless required by applicable law or agreed to in writing, 21 // software distributed under the License is distributed on an 22 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 23 // KIND, either express or implied. See the License for the 24 // specific language governing permissions and limitations 25 // under the License. 26 27 // +build integration 28 29 package opensearchtransport 30 31 import ( 32 "fmt" 33 "net/http" 34 "net/url" 35 "os" 36 "testing" 37 "time" 38 ) 39 40 func NewServer(addr string, handler http.Handler) *http.Server { 41 return &http.Server{Addr: addr, Handler: handler} 42 } 43 44 func TestStatusConnectionPool(t *testing.T) { 45 defaultResurrectTimeoutInitial = time.Second 46 defer func() { defaultResurrectTimeoutInitial = 60 * time.Second }() 47 48 var ( 49 server *http.Server 50 servers []*http.Server 51 serverURLs []*url.URL 52 serverHosts []string 53 numServers = 3 54 55 defaultHandler = func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "OK") } 56 ) 57 58 for i := 1; i <= numServers; i++ { 59 s := NewServer(fmt.Sprintf("localhost:1000%d", i), http.HandlerFunc(defaultHandler)) 60 61 go func(s *http.Server) { 62 if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { 63 t.Fatalf("Unable to start server: %s", err) 64 } 65 }(s) 66 67 defer func(s *http.Server) { s.Close() }(s) 68 69 servers = append(servers, s) 70 time.Sleep(time.Millisecond) 71 } 72 73 for _, s := range servers { 74 u, _ := url.Parse("http://" + s.Addr) 75 serverURLs = append(serverURLs, u) 76 serverHosts = append(serverHosts, u.String()) 77 } 78 79 fmt.Printf("==> Started %d servers on %s\n", numServers, serverHosts) 80 81 cfg := Config{URLs: serverURLs} 82 83 if _, ok := os.LookupEnv("GITHUB_ACTIONS"); !ok { 84 cfg.Logger = &TextLogger{Output: os.Stdout} 85 cfg.EnableDebugLogger = true 86 } 87 88 transport, _ := New(cfg) 89 90 pool := transport.pool.(*statusConnectionPool) 91 92 for i := 1; i <= 9; i++ { 93 req, _ := http.NewRequest("GET", "/", nil) 94 res, err := transport.Perform(req) 95 if err != nil { 96 t.Errorf("Unexpected error: %v", err) 97 } 98 if res.StatusCode != 200 { 99 t.Errorf("Unexpected status code, want=200, got=%d", res.StatusCode) 100 } 101 } 102 103 pool.Lock() 104 if len(pool.live) != 3 { 105 t.Errorf("Unexpected number of live connections, want=3, got=%d", len(pool.live)) 106 } 107 pool.Unlock() 108 109 server = servers[1] 110 fmt.Printf("==> Closing server: %s\n", server.Addr) 111 if err := server.Close(); err != nil { 112 t.Fatalf("Unable to close server: %s", err) 113 } 114 115 for i := 1; i <= 9; i++ { 116 req, _ := http.NewRequest("GET", "/", nil) 117 res, err := transport.Perform(req) 118 if err != nil { 119 t.Errorf("Unexpected error: %v", err) 120 } 121 if res.StatusCode != 200 { 122 t.Errorf("Unexpected status code, want=200, got=%d", res.StatusCode) 123 } 124 } 125 126 pool.Lock() 127 if len(pool.live) != 2 { 128 t.Errorf("Unexpected number of live connections, want=2, got=%d", len(pool.live)) 129 } 130 pool.Unlock() 131 132 pool.Lock() 133 if len(pool.dead) != 1 { 134 t.Errorf("Unexpected number of dead connections, want=1, got=%d", len(pool.dead)) 135 } 136 pool.Unlock() 137 138 server = NewServer("localhost:10002", http.HandlerFunc(defaultHandler)) 139 servers[1] = server 140 fmt.Printf("==> Starting server: %s\n", server.Addr) 141 go func() { 142 if err := server.ListenAndServe(); err != nil { 143 t.Fatalf("Unable to start server: %s", err) 144 } 145 }() 146 147 fmt.Println("==> Waiting 1.25s for resurrection...") 148 time.Sleep(1250 * time.Millisecond) 149 150 for i := 1; i <= 9; i++ { 151 req, _ := http.NewRequest("GET", "/", nil) 152 res, err := transport.Perform(req) 153 if err != nil { 154 t.Errorf("Unexpected error: %v", err) 155 } 156 if res.StatusCode != 200 { 157 t.Errorf("Unexpected status code, want=200, got=%d", res.StatusCode) 158 } 159 } 160 161 pool.Lock() 162 if len(pool.live) != 3 { 163 t.Errorf("Unexpected number of live connections, want=3, got=%d", len(pool.live)) 164 } 165 pool.Unlock() 166 167 pool.Lock() 168 if len(pool.dead) != 0 { 169 t.Errorf("Unexpected number of dead connections, want=0, got=%d", len(pool.dead)) 170 } 171 pool.Unlock() 172 }