Browse code

Hack: simplify the creation of test directories

Solomon Hykes authored on 2013/10/27 16:13:45
Showing 4 changed files
... ...
@@ -3,6 +3,7 @@ package docker
3 3
 import (
4 4
 	"bytes"
5 5
 	"fmt"
6
+	"github.com/dotcloud/docker/engine"
6 7
 	"github.com/dotcloud/docker/sysinit"
7 8
 	"github.com/dotcloud/docker/utils"
8 9
 	"io"
... ...
@@ -17,6 +18,7 @@ import (
17 17
 	"syscall"
18 18
 	"testing"
19 19
 	"time"
20
+	"net/url"
20 21
 )
21 22
 
22 23
 const (
... ...
@@ -118,22 +120,19 @@ func init() {
118 118
 }
119 119
 
120 120
 func setupBaseImage() {
121
-	config := &DaemonConfig{
122
-		Root:        unitTestStoreBase,
123
-		AutoRestart: false,
124
-		BridgeIface: unitTestNetworkBridge,
125
-	}
126
-	runtime, err := NewRuntimeFromDirectory(config)
121
+	eng, err := engine.New(unitTestStoreBase)
127 122
 	if err != nil {
128
-		log.Fatalf("Unable to create a runtime for tests:", err)
123
+		log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err)
129 124
 	}
130
-
131
-	// Create the "Server"
132
-	srv := &Server{
133
-		runtime:     runtime,
134
-		pullingPool: make(map[string]struct{}),
135
-		pushingPool: make(map[string]struct{}),
125
+	job := eng.Job("initapi")
126
+	job.Setenv("Root", unitTestStoreBase)
127
+	job.SetenvBool("Autorestart", false)
128
+	job.Setenv("BridgeIface", unitTestNetworkBridge)
129
+	if err := job.Run(); err != nil {
130
+		log.Fatalf("Unable to create a runtime for tests:", err)
136 131
 	}
132
+	srv := mkServerFromEngine(eng, log.New(os.Stderr, "", 0))
133
+	runtime := srv.runtime
137 134
 
138 135
 	// If the unit test is not found, try to download it.
139 136
 	if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
... ...
@@ -149,18 +148,22 @@ func spawnGlobalDaemon() {
149 149
 		utils.Debugf("Global runtime already exists. Skipping.")
150 150
 		return
151 151
 	}
152
-	globalRuntime = mkRuntime(log.New(os.Stderr, "", 0))
153
-	srv := &Server{
154
-		runtime:     globalRuntime,
155
-		pullingPool: make(map[string]struct{}),
156
-		pushingPool: make(map[string]struct{}),
157
-	}
152
+	t := log.New(os.Stderr, "", 0)
153
+	eng := NewTestEngine(t)
154
+	srv := mkServerFromEngine(eng, t)
155
+	globalRuntime = srv.runtime
158 156
 
159 157
 	// Spawn a Daemon
160 158
 	go func() {
161 159
 		utils.Debugf("Spawning global daemon for integration tests")
162
-		if err := ListenAndServe(testDaemonProto, testDaemonAddr, srv, os.Getenv("DEBUG") != ""); err != nil {
163
-			log.Fatalf("Unable to spawn the test daemon:", err)
160
+		listenURL := &url.URL{
161
+			Scheme:	testDaemonProto,
162
+			Host:	testDaemonAddr,
163
+		}
164
+		job := eng.Job("serveapi", listenURL.String())
165
+		job.SetenvBool("Logging", os.Getenv("DEBUG") != "")
166
+		if err := job.Run(); err != nil {
167
+			log.Fatalf("Unable to spawn the test daemon: %s", err)
164 168
 		}
165 169
 	}()
166 170
 	// Give some time to ListenAndServer to actually start
... ...
@@ -1,7 +1,6 @@
1 1
 package docker
2 2
 
3 3
 import (
4
-	"github.com/dotcloud/docker/engine"
5 4
 	"github.com/dotcloud/docker/utils"
6 5
 	"strings"
7 6
 	"testing"
... ...
@@ -110,7 +109,7 @@ func TestCreateRm(t *testing.T) {
110 110
 }
111 111
 
112 112
 func TestCreateRmVolumes(t *testing.T) {
113
-	eng := engine.NewTestEngine(t)
113
+	eng := NewTestEngine(t)
114 114
 
115 115
 	srv := mkServerFromEngine(eng, t)
116 116
 	runtime := srv.runtime
... ...
@@ -174,7 +173,7 @@ func TestCommit(t *testing.T) {
174 174
 }
175 175
 
176 176
 func TestCreateStartRestartStopStartKillRm(t *testing.T) {
177
-	eng := engine.NewTestEngine(t)
177
+	eng := NewTestEngine(t)
178 178
 	srv := mkServerFromEngine(eng, t)
179 179
 	runtime := srv.runtime
180 180
 	defer nuke(runtime)
... ...
@@ -397,7 +396,7 @@ func TestLogEvent(t *testing.T) {
397 397
 }
398 398
 
399 399
 func TestRmi(t *testing.T) {
400
-	eng := engine.NewTestEngine(t)
400
+	eng := NewTestEngine(t)
401 401
 	srv := mkServerFromEngine(eng, t)
402 402
 	runtime := srv.runtime
403 403
 	defer nuke(runtime)
... ...
@@ -27,6 +27,12 @@ var (
27 27
 	INITSHA1  string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary
28 28
 )
29 29
 
30
+// A common interface to access the Fatal method of
31
+// both testing.B and testing.T.
32
+type Fataler interface {
33
+	Fatal(args ...interface{})
34
+}
35
+
30 36
 // ListOpts type
31 37
 type ListOpts []string
32 38
 
... ...
@@ -21,27 +21,24 @@ var globalTestID string
21 21
 
22 22
 // Create a temporary runtime suitable for unit testing.
23 23
 // Call t.Fatal() at the first error.
24
-func mkRuntime(f Fataler) *Runtime {
25
-	// Use the caller function name as a prefix.
26
-	// This helps trace temp directories back to their test.
27
-	pc, _, _, _ := runtime.Caller(1)
28
-	callerLongName := runtime.FuncForPC(pc).Name()
29
-	parts := strings.Split(callerLongName, ".")
30
-	callerShortName := parts[len(parts)-1]
31
-	if globalTestID == "" {
32
-		globalTestID = GenerateID()[:4]
24
+func mkRuntime(f utils.Fataler) *Runtime {
25
+	root, err := newTestDirectory(unitTestStoreBase)
26
+	if err != nil {
27
+		f.Fatal(err)
33 28
 	}
34
-	prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, callerShortName)
35
-	utils.Debugf("prefix = '%s'", prefix)
36
-
37
-	runtime, err := newTestRuntime(prefix)
29
+	config := &DaemonConfig{
30
+		Root:   root,
31
+		AutoRestart: false,
32
+	}
33
+	r, err := NewRuntimeFromDirectory(config)
38 34
 	if err != nil {
39 35
 		f.Fatal(err)
40 36
 	}
41
-	return runtime
37
+	r.UpdateCapabilities(true)
38
+	return r
42 39
 }
43 40
 
44
-func mkServerFromEngine(eng *engine.Engine, t Fataler) *Server {
41
+func mkServerFromEngine(eng *engine.Engine, t utils.Fataler) *Server {
45 42
 	iSrv := eng.Hack_GetGlobalVar("httpapi.server")
46 43
 	if iSrv == nil {
47 44
 		t.Fatal("Legacy server field not set in engine")
... ...
@@ -53,42 +50,53 @@ func mkServerFromEngine(eng *engine.Engine, t Fataler) *Server {
53 53
 	return srv
54 54
 }
55 55
 
56
-// A common interface to access the Fatal method of
57
-// both testing.B and testing.T.
58
-type Fataler interface {
59
-	Fatal(args ...interface{})
60
-}
61 56
 
62
-func newTestRuntime(prefix string) (runtime *Runtime, err error) {
63
-	if prefix == "" {
64
-		prefix = "docker-test-"
65
-	}
66
-	utils.Debugf("prefix = %s", prefix)
67
-	utils.Debugf("newTestRuntime start")
68
-	root, err := ioutil.TempDir("", prefix)
69
-	defer func() {
70
-		utils.Debugf("newTestRuntime: %s", root)
71
-	}()
57
+func NewTestEngine(t utils.Fataler) *engine.Engine {
58
+	root, err := newTestDirectory(unitTestStoreBase)
72 59
 	if err != nil {
73
-		return nil, err
60
+		t.Fatal(err)
74 61
 	}
75
-	if err := os.Remove(root); err != nil {
76
-		return nil, err
62
+	eng, err := engine.New(root)
63
+	if err != nil {
64
+		t.Fatal(err)
77 65
 	}
78
-	if err := utils.CopyDirectory(unitTestStoreBase, root); err != nil {
79
-		return nil, err
66
+	// Load default plugins
67
+	// (This is manually copied and modified from main() until we have a more generic plugin system)
68
+	job := eng.Job("initapi")
69
+	job.Setenv("Root", root)
70
+	job.SetenvBool("AutoRestart", false)
71
+	if err := job.Run(); err != nil {
72
+		t.Fatal(err)
80 73
 	}
74
+	return eng
75
+}
81 76
 
82
-	config := &DaemonConfig{
83
-		Root:   root,
84
-		AutoRestart: false,
77
+func newTestDirectory(templateDir string) (dir string, err error) {
78
+	if globalTestID == "" {
79
+		globalTestID = GenerateID()[:4]
85 80
 	}
86
-	runtime, err = NewRuntimeFromDirectory(config)
87
-	if err != nil {
88
-		return nil, err
81
+	prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, getCallerName(2))
82
+	if prefix == "" {
83
+		prefix = "docker-test-"
84
+	}
85
+	dir, err = ioutil.TempDir("", prefix)
86
+	if err = os.Remove(dir); err != nil {
87
+		return
88
+	}
89
+	if err = utils.CopyDirectory(templateDir, dir); err != nil {
90
+		return
89 91
 	}
90
-	runtime.UpdateCapabilities(true)
91
-	return runtime, nil
92
+	return
93
+}
94
+
95
+func getCallerName(depth int) string {
96
+	// Use the caller function name as a prefix.
97
+	// This helps trace temp directories back to their test.
98
+	pc, _, _, _ := runtime.Caller(depth + 1)
99
+	callerLongName := runtime.FuncForPC(pc).Name()
100
+	parts := strings.Split(callerLongName, ".")
101
+	callerShortName := parts[len(parts)-1]
102
+	return callerShortName
92 103
 }
93 104
 
94 105
 // Write `content` to the file at path `dst`, creating it if necessary,