Skip to content

Commit e7fc9c7

Browse files
author
Aaron Schlesinger
committed
fix(pkg/sshd/server_test.go): improve tests for the server
1 parent 5ba3741 commit e7fc9c7

1 file changed

Lines changed: 78 additions & 59 deletions

File tree

pkg/sshd/server_test.go

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1818
const (
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

2522
func 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.
4340
func 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

10497
func 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.
229249
func 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

Comments
 (0)