github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/worker/container_sweeper_test.go (about) 1 package worker_test 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "os" 8 "time" 9 10 "code.cloudfoundry.org/lager/lagertest" 11 "github.com/pf-qiu/concourse/v6/atc/worker/gclient" 12 "github.com/pf-qiu/concourse/v6/worker" 13 "github.com/pf-qiu/concourse/v6/worker/workerfakes" 14 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 "github.com/onsi/gomega/gbytes" 18 "github.com/onsi/gomega/ghttp" 19 ) 20 21 var _ = Describe("Container Sweeper", func() { 22 const ( 23 sweepInterval = 1 * time.Second 24 maxInFlight = uint16(1) 25 gardenClientTimeoutRequest = 5 * time.Millisecond 26 ) 27 28 var ( 29 garden *ghttp.Server 30 31 testLogger = lagertest.NewTestLogger("container-sweeper") 32 33 fakeTSAClient workerfakes.FakeTSAClient 34 gardenClient gclient.Client 35 36 sweeper *worker.ContainerSweeper 37 38 osSignal chan os.Signal 39 exited chan struct{} 40 ) 41 42 BeforeEach(func() { 43 garden = ghttp.NewServer() 44 45 osSignal = make(chan os.Signal) 46 exited = make(chan struct{}) 47 48 gardenAddr := fmt.Sprintf("http://%s", garden.Addr()) 49 gardenClient = gclient.BasicGardenClientWithRequestTimeout(testLogger, gardenClientTimeoutRequest, gardenAddr) 50 51 fakeTSAClient = workerfakes.FakeTSAClient{} 52 fakeTSAClient.ReportContainersReturns(nil) 53 54 sweeper = worker.NewContainerSweeper(testLogger, sweepInterval, &fakeTSAClient, gardenClient, maxInFlight) 55 56 }) 57 58 JustBeforeEach(func() { 59 go func() { 60 _ = sweeper.Run(osSignal, make(chan struct{})) 61 close(exited) 62 }() 63 }) 64 65 AfterEach(func() { 66 close(osSignal) 67 <-exited 68 garden.Close() 69 }) 70 71 Context("when garden doesn't respond on DELETE", func() { 72 var ( 73 gardenContext context.Context 74 gardenCancel context.CancelFunc 75 ) 76 77 BeforeEach(func() { 78 gardenContext, gardenCancel = context.WithCancel(context.Background()) 79 garden.AppendHandlers( 80 ghttp.CombineHandlers( 81 ghttp.VerifyRequest("GET", "/containers"), 82 ghttp.RespondWithJSONEncoded(200, []map[string]string{}), 83 ), 84 ghttp.CombineHandlers( 85 ghttp.VerifyRequest("DELETE", "/containers/some-handle-1"), 86 func(w http.ResponseWriter, r *http.Request) { 87 <-gardenContext.Done() 88 }, 89 ), 90 ghttp.CombineHandlers( 91 ghttp.VerifyRequest("DELETE", "/containers/some-handle-2"), 92 func(w http.ResponseWriter, r *http.Request) { 93 <-gardenContext.Done() 94 }, 95 ), 96 ghttp.CombineHandlers( 97 ghttp.VerifyRequest("GET", "/containers"), 98 ghttp.RespondWithJSONEncoded(200, []map[string]string{}), 99 ), 100 ghttp.CombineHandlers( 101 ghttp.VerifyRequest("DELETE", "/containers/some-handle-3"), 102 func(w http.ResponseWriter, r *http.Request) { 103 <-gardenContext.Done() 104 }, 105 ), 106 ghttp.CombineHandlers( 107 ghttp.VerifyRequest("DELETE", "/containers/some-handle-4"), 108 func(w http.ResponseWriter, r *http.Request) { 109 <-gardenContext.Done() 110 }, 111 ), 112 ) 113 // First GC Tick 114 fakeTSAClient.ContainersToDestroyReturnsOnCall(0, []string{"some-handle-1", "some-handle-2"}, nil) 115 // Second GC Tick 116 fakeTSAClient.ContainersToDestroyReturnsOnCall(1, []string{"some-handle-3", "some-handle-4"}, nil) 117 118 garden.AllowUnhandledRequests = true 119 120 }) 121 AfterEach(func() { 122 gardenCancel() 123 }) 124 125 It("request to garden times out eventually", func() { 126 Eventually(testLogger.Buffer()).Should(gbytes.Say("failed-to-destroy-container\".*\\(Client.Timeout exceeded while awaiting headers\\)")) 127 }) 128 It("sweeper continues ticking and GC'ing", func() { 129 // ensure all 4 DELETEs are issues over 2 successive ticks 130 Eventually(func() []string { 131 // Gather all containers deleted 132 var deleteRequestPaths []string 133 for _, req := range garden.ReceivedRequests() { 134 if req.Method == http.MethodDelete { 135 deleteRequestPaths = append(deleteRequestPaths, req.RequestURI) 136 } 137 } 138 return deleteRequestPaths 139 }).Should(ConsistOf( 140 "/containers/some-handle-1", 141 "/containers/some-handle-2", 142 "/containers/some-handle-3", 143 "/containers/some-handle-4")) 144 145 // Check calls to TSA for containers to destroy > 1 146 Expect(fakeTSAClient.ContainersToDestroyCallCount()).To(BeNumerically(">=", 2)) 147 }) 148 }) 149 150 })