@@ -4,22 +4,19 @@ import (
44 "bytes"
55 "fmt"
66 "net"
7+ "sync"
78 "testing"
89 "time"
910
10- "github.com/deis/builder/pkg/controller"
11-
1211 "github.com/Masterminds/cookoo"
1312 "github.com/arschles/assert"
1413 "github.com/deis/builder/pkg/cleaner"
14+ "github.com/deis/builder/pkg/controller"
1515 "golang.org/x/crypto/ssh"
1616)
1717
1818const (
19- testingServerAddr = "127.0.0.1:2244"
20- testingServerAddr2 = "127.0.0.1:2245"
21- testingServerAddr3 = "127.0.0.1:2246"
22- gitHome = "/git"
19+ gitHome = "/git"
2320)
2421
2522func TestGitPktLine (t * testing.T ) {
@@ -41,10 +38,9 @@ func TestGitPktLine(t *testing.T) {
4138// the same port (at a later time) or else you will have key issues that you
4239// must manually resolve.
4340func TestReceive (t * testing.T ) {
41+ const testingServerAddr = "127.0.0.1:2244"
4442 key , err := sshTestingHostKey ()
45- if err != nil {
46- t .Fatal (err )
47- }
43+ assert .NoErr (t , err )
4844
4945 cfg := ssh.ServerConfig {
5046 NoClientAuth : true ,
@@ -53,15 +49,12 @@ func TestReceive(t *testing.T) {
5349
5450 c := NewCircuit ()
5551 pushLock := NewInMemoryRepositoryLock ()
56- deleteLock := NewInMemoryRepositoryLock ()
57- cxt := runServer (& cfg , c , pushLock , deleteLock , testingServerAddr , t )
52+ cleanerRef := cleaner . NewRef ()
53+ cxt := runServer (& cfg , c , pushLock , cleanerRef , testingServerAddr , t )
5854
5955 // Give server time to initialize.
6056 time .Sleep (200 * time .Millisecond )
61-
62- if c .State () != ClosedState {
63- t .Fatalf ("circuit was not in closed state" )
64- }
57+ assert .Equal (t , c .State (), ClosedState , "circuit state" )
6558
6659 // Connect to the server and issue env var set. This should return true.
6760 client , err := ssh .Dial ("tcp" , testingServerAddr , & ssh.ClientConfig {})
@@ -102,10 +95,9 @@ func TestReceive(t *testing.T) {
10295}
10396
10497func TestPush (t * testing.T ) {
98+ const testingServerAddr = "127.0.0.1:2245"
10599 key , err := sshTestingHostKey ()
106- if err != nil {
107- t .Fatal (err )
108- }
100+ assert .NoErr (t , err )
109101
110102 cfg := ssh.ServerConfig {
111103 NoClientAuth : true ,
@@ -114,8 +106,8 @@ func TestPush(t *testing.T) {
114106
115107 c := NewCircuit ()
116108 pushLock := NewInMemoryRepositoryLock ()
117- deleteLock := NewInMemoryRepositoryLock ()
118- runServer (& cfg , c , pushLock , deleteLock , testingServerAddr2 , t )
109+ cleanerRef := cleaner . NewRef ()
110+ runServer (& cfg , c , pushLock , cleanerRef , testingServerAddr , t )
119111
120112 // Give server time to initialize.
121113 time .Sleep (200 * time .Millisecond )
@@ -125,7 +117,7 @@ func TestPush(t *testing.T) {
125117 }
126118
127119 // Connect to the server and issue env var set. This should return true.
128- client , err := ssh .Dial ("tcp" , testingServerAddr2 , & ssh.ClientConfig {})
120+ client , err := ssh .Dial ("tcp" , testingServerAddr , & ssh.ClientConfig {})
129121 if err != nil {
130122 t .Fatalf ("Failed to connect client to local server: %s" , err )
131123 }
@@ -167,70 +159,98 @@ func TestPush(t *testing.T) {
167159 sess .Close ()
168160}
169161
170- func TestDelete (t * testing.T ) {
162+ func TestManyConcurrentPushes (t * testing.T ) {
163+ const testingServerAddr = "127.0.0.1:2247"
171164 key , err := sshTestingHostKey ()
172165 if err != nil {
173166 t .Fatal (err )
174167 }
168+ cfg := ssh.ServerConfig {NoClientAuth : true }
169+ cfg .AddHostKey (key )
170+ c := NewCircuit ()
171+ pushLock := NewInMemoryRepositoryLock ()
172+ cleanerRef := cleaner .NewRef ()
173+ runServer (& cfg , c , pushLock , cleanerRef , testingServerAddr , t )
174+ time .Sleep (200 * time .Millisecond )
175+ assert .Equal (t , c .State (), ClosedState , "circuit state" )
175176
176- cfg := ssh.ServerConfig {
177- NoClientAuth : true ,
177+ // Connect to the server and issue env var set. This should return true.
178+ client , err := ssh .Dial ("tcp" , testingServerAddr , & ssh.ClientConfig {})
179+ assert .NoErr (t , err )
180+ sess , err := client .NewSession ()
181+ assert .NoErr (t , err )
182+
183+ const numRepos = 20
184+ repoNames := make ([]string , numRepos )
185+ for i := 0 ; i < numRepos ; i ++ {
186+ repoNames [i ] = fmt .Sprintf ("repo%d" , i )
187+ }
188+ var wg sync.WaitGroup
189+ for _ , repoName := range repoNames {
190+ wg .Add (1 )
191+ go func (repoName string ) {
192+ defer wg .Done ()
193+ sess , err = client .NewSession ()
194+ assert .NoErr (t , err )
195+ out , err := sess .Output ("git-upload-pack /" + repoName + ".git" )
196+ assert .NoErr (t , err )
197+ assert .Equal (t , string (out ), "OK" , "output" )
198+ }(repoName )
178199 }
200+ wg .Wait ()
201+ }
202+
203+ func TestDelete (t * testing.T ) {
204+ const testingServerAddr = "127.0.0.1:2246"
205+ key , err := sshTestingHostKey ()
206+ assert .NoErr (t , err )
207+
208+ cfg := ssh.ServerConfig {NoClientAuth : true }
179209 cfg .AddHostKey (key )
180210
181211 c := NewCircuit ()
182212 pushLock := NewInMemoryRepositoryLock ()
183- deleteLock := NewInMemoryRepositoryLock ()
184- runServer (& cfg , c , pushLock , deleteLock , testingServerAddr3 , t )
213+ cleanerRef := cleaner . NewRef ()
214+ runServer (& cfg , c , pushLock , cleanerRef , testingServerAddr , t )
185215
186216 // Give server time to initialize.
187217 time .Sleep (200 * time .Millisecond )
188-
189- if c .State () != ClosedState {
190- t .Fatalf ("circuit was not in closed state" )
191- }
218+ assert .Equal (t , c .State (), ClosedState , "circuit state" )
192219
193220 // Connect to the server and issue env var set. This should return true.
194- client , err := ssh .Dial ("tcp" , testingServerAddr2 , & ssh.ClientConfig {})
195- if err != nil {
196- t .Fatalf ("Failed to connect client to local server: %s" , err )
197- }
221+ client , err := ssh .Dial ("tcp" , testingServerAddr , & ssh.ClientConfig {})
222+ assert .NoErr (t , err )
198223 sess , err := client .NewSession ()
199- if err != nil {
200- t .Fatalf ("Failed to create client session: %s" , err )
201- }
202-
203- // check for invalid length of arguments
204- if out , err := sess .Output ("git-upload-pack" ); err == nil {
205- t .Errorf ("Expected an error but '%s' was received" , out )
206- } else if string (out ) != "" {
207- t .Errorf ("Expected , got '%s'" , out )
208- }
209- sess .Close ()
224+ assert .NoErr (t , err )
210225
211226 repoName := "demo"
212- if err := deleteLock .Lock (repoName , time .Duration (0 )); err != nil {
213- t .Fatalf ("Error locking the delete lock (%s)" , err )
214- }
227+ cleanerRef .Lock ()
215228
216- sess , err = client .NewSession ()
217- if err != nil {
218- t .Fatalf ("Failed to create client session: %s" , err )
219- }
220- if out , err := sess .Output ("git-upload-pack /" + repoName + ".git" ); err != nil {
221- t .Errorf ("expected no error, got %s" , err )
222- } else if string (out ) != "OK" {
223- t .Errorf ("Expected 'OK' output, got %s" , string (out ))
229+ doneCh := make (chan struct {})
230+ go func () {
231+ defer close (doneCh )
232+ sess , err = client .NewSession ()
233+ assert .NoErr (t , err )
234+ // this is expected to hang because cleanerRef is locked
235+ out , err := sess .Output ("git-upload-pack /" + repoName + ".git" )
236+ assert .NoErr (t , err )
237+ assert .Equal (t , string (out ), "OK" , "output" )
238+ sess .Close ()
239+ }()
240+
241+ select {
242+ case <- doneCh :
243+ t .Fatalf ("push succeeded while cleaner was locked" )
244+ case <- time .After (100 * time .Millisecond ):
224245 }
225- sess .Close ()
226246}
227247
228248// sshTestingHostKey loads the testing key.
229249func sshTestingHostKey () (ssh.Signer , error ) {
230250 return ssh .ParsePrivateKey ([]byte (testingHostKey ))
231251}
232252
233- func runServer (config * ssh.ServerConfig , c * Circuit , pushLock RepositoryLock , deleteLock RepositoryLock , testAddr string , t * testing.T ) cookoo.Context {
253+ func runServer (config * ssh.ServerConfig , c * Circuit , pushLock RepositoryLock , cleanerRef cleaner. Ref , testAddr string , t * testing.T ) cookoo.Context {
234254 reg , router , cxt := cookoo .Cookoo ()
235255 cxt .Put (ServerConfig , config )
236256 cxt .Put (Address , testAddr )
@@ -284,7 +304,6 @@ func runServer(config *ssh.ServerConfig, c *Circuit, pushLock RepositoryLock, de
284304 },
285305 })
286306
287- cleanerRef := cleaner .NewRef ()
288307 go func () {
289308 if err := Serve (reg , router , c , gitHome , pushLock , cleanerRef , cxt ); err != nil {
290309 t .Fatalf ("Failed serving with %s" , err )
0 commit comments