Skip to content

Commit 7c2435e

Browse files
darkowlzzPaulo Gomes
authored andcommitted
Fix race condition in git proxy tests
The variable used to store the information about proxied request was being written to in the proxy server request handler and read for assertion at the end of the test. Replace the boolean variable with an atomic counter to count the number of requests proxied, preventing the race condition. Signed-off-by: Sunny <[email protected]>
1 parent a22c017 commit 7c2435e

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

pkg/git/strategy/proxy/strategy_proxy_test.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"net/url"
2525
"os"
2626
"strings"
27+
"sync/atomic"
2728
"testing"
2829
"time"
2930

@@ -59,7 +60,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
5960
gitImpl git.Implementation
6061
url string
6162
branch string
62-
setupGitProxy func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc)
63+
setupGitProxy func(g *WithT, proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) (*git.AuthOptions, cleanupFunc)
6364
shortTimeout bool
6465
wantUsedProxy bool
6566
wantError bool
@@ -176,7 +177,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
176177
gitImpl: libgit2.Implementation,
177178
url: "https://example.com/bar/test-reponame",
178179
branch: "main",
179-
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) {
180+
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) (*git.AuthOptions, cleanupFunc) {
180181
// Create the git server.
181182
gitServer, err := gittestserver.NewTempGitServer()
182183
g.Expect(err).ToNot(HaveOccurred())
@@ -211,7 +212,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
211212
// Check if the host matches with the git server address and the user-agent is the expected git client.
212213
userAgent := ctx.Req.Header.Get("User-Agent")
213214
if strings.Contains(host, "example.com") && strings.Contains(userAgent, "libgit2") {
214-
*proxyGotRequest = true
215+
atomic.AddInt32(proxiedRequests, 1)
215216
return goproxy.OkConnect, u.Host
216217
}
217218
// Reject if it isn't our request.
@@ -239,7 +240,7 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
239240
gitImpl: libgit2.Implementation,
240241
url: "http://example.com/bar/test-reponame",
241242
branch: "main",
242-
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) {
243+
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) (*git.AuthOptions, cleanupFunc) {
243244
// Create the git server.
244245
gitServer, err := gittestserver.NewTempGitServer()
245246
g.Expect(err).ToNot(HaveOccurred())
@@ -259,8 +260,8 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
259260
// The certificate used here is valid for both example.com and localhost.
260261
var proxyHandler goproxy.FuncReqHandler = func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
261262
userAgent := req.Header.Get("User-Agent")
262-
if strings.Contains(req.Host, "example.com") && strings.Contains(userAgent, "libgit2") {
263-
*proxyGotRequest = true
263+
if strings.Contains(req.Host, "example.com") && strings.Contains(userAgent, "git") {
264+
atomic.AddInt32(proxiedRequests, 1)
264265
req.Host = u.Host
265266
req.URL.Host = req.Host
266267
return req, nil
@@ -283,14 +284,41 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
283284
wantError: false,
284285
},
285286
{
286-
name: "libgit2_NO_PROXY",
287-
gitImpl: libgit2.Implementation,
287+
name: "gogit_HTTPS_PROXY",
288+
gitImpl: gogit.Implementation,
289+
url: "https://github.com/git-fixtures/basic",
290+
branch: "master",
291+
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) (*git.AuthOptions, cleanupFunc) {
292+
var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
293+
// We don't check for user agent as this handler is only going to process CONNECT requests, and because Go's net/http
294+
// is the one making such a request on behalf of go-git, adding a check for the go net/http user agent (Go-http-client)
295+
// would only allow false positives from any request originating from Go's net/http.
296+
if strings.Contains(host, "github.com") {
297+
atomic.AddInt32(proxiedRequests, 1)
298+
return goproxy.OkConnect, host
299+
}
300+
// Reject if it isnt our request.
301+
return goproxy.RejectConnect, host
302+
}
303+
proxy.OnRequest().HandleConnect(proxyHandler)
304+
305+
// go-git does not allow to use an HTTPS proxy and a custom root CA at the same time.
306+
// See https://github.com/fluxcd/source-controller/pull/524#issuecomment-1006673163.
307+
return nil, func() {}
308+
},
309+
shortTimeout: false,
310+
wantUsedProxy: true,
311+
wantError: false,
312+
},
313+
{
314+
name: "gogit_NO_PROXY",
315+
gitImpl: gogit.Implementation,
288316
url: "https://192.0.2.1/bar/test-reponame",
289317
branch: "main",
290-
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxyGotRequest *bool) (*git.AuthOptions, cleanupFunc) {
318+
setupGitProxy: func(g *WithT, proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) (*git.AuthOptions, cleanupFunc) {
291319
var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
292320
// We shouldn't hit the proxy so we just want to check for any interaction, then reject.
293-
*proxyGotRequest = true
321+
atomic.AddInt32(proxiedRequests, 1)
294322
return goproxy.RejectConnect, host
295323
}
296324
proxy.OnRequest().HandleConnect(proxyHandler)
@@ -311,8 +339,8 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
311339
proxy := goproxy.NewProxyHttpServer()
312340
proxy.Verbose = true
313341

314-
proxyGotRequest := false
315-
authOpts, cleanup := tt.setupGitProxy(g, proxy, &proxyGotRequest)
342+
proxiedRequests := int32(0)
343+
authOpts, cleanup := tt.setupGitProxy(g, proxy, &proxiedRequests)
316344
defer cleanup()
317345

318346
proxyServer := http.Server{
@@ -357,7 +385,8 @@ func TestCheckoutStrategyForImplementation_Proxied(t *testing.T) {
357385
g.Expect(err).ToNot(HaveOccurred())
358386
}
359387

360-
g.Expect(proxyGotRequest).To(Equal(tt.wantUsedProxy))
388+
g.Expect(atomic.LoadInt32(&proxiedRequests) > 0).To(Equal(tt.wantUsedProxy))
389+
361390
})
362391
}
363392
}

0 commit comments

Comments
 (0)