| ... | ... |
@@ -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, |