Hack: simplify the creation of test directories

This commit is contained in:
Solomon Hykes 2013-10-27 07:13:45 +00:00
parent 02ddaad5d9
commit 5a85456d48
4 changed files with 85 additions and 69 deletions

View file

@ -3,6 +3,7 @@ package docker
import (
"bytes"
"fmt"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/sysinit"
"github.com/dotcloud/docker/utils"
"io"
@ -17,6 +18,7 @@ import (
"syscall"
"testing"
"time"
"net/url"
)
const (
@ -118,22 +120,19 @@ func init() {
}
func setupBaseImage() {
config := &DaemonConfig{
Root: unitTestStoreBase,
AutoRestart: false,
BridgeIface: unitTestNetworkBridge,
}
runtime, err := NewRuntimeFromDirectory(config)
eng, err := engine.New(unitTestStoreBase)
if err != nil {
log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err)
}
job := eng.Job("initapi")
job.Setenv("Root", unitTestStoreBase)
job.SetenvBool("Autorestart", false)
job.Setenv("BridgeIface", unitTestNetworkBridge)
if err := job.Run(); err != nil {
log.Fatalf("Unable to create a runtime for tests:", err)
}
// Create the "Server"
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
srv := mkServerFromEngine(eng, log.New(os.Stderr, "", 0))
runtime := srv.runtime
// If the unit test is not found, try to download it.
if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
@ -149,18 +148,22 @@ func spawnGlobalDaemon() {
utils.Debugf("Global runtime already exists. Skipping.")
return
}
globalRuntime = mkRuntime(log.New(os.Stderr, "", 0))
srv := &Server{
runtime: globalRuntime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
t := log.New(os.Stderr, "", 0)
eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t)
globalRuntime = srv.runtime
// Spawn a Daemon
go func() {
utils.Debugf("Spawning global daemon for integration tests")
if err := ListenAndServe(testDaemonProto, testDaemonAddr, srv, os.Getenv("DEBUG") != ""); err != nil {
log.Fatalf("Unable to spawn the test daemon:", err)
listenURL := &url.URL{
Scheme: testDaemonProto,
Host: testDaemonAddr,
}
job := eng.Job("serveapi", listenURL.String())
job.SetenvBool("Logging", os.Getenv("DEBUG") != "")
if err := job.Run(); err != nil {
log.Fatalf("Unable to spawn the test daemon: %s", err)
}
}()
// Give some time to ListenAndServer to actually start

View file

@ -1,7 +1,6 @@
package docker
import (
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/utils"
"strings"
"testing"
@ -110,7 +109,7 @@ func TestCreateRm(t *testing.T) {
}
func TestCreateRmVolumes(t *testing.T) {
eng := engine.NewTestEngine(t)
eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t)
runtime := srv.runtime
@ -174,7 +173,7 @@ func TestCommit(t *testing.T) {
}
func TestCreateStartRestartStopStartKillRm(t *testing.T) {
eng := engine.NewTestEngine(t)
eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime)
@ -397,7 +396,7 @@ func TestLogEvent(t *testing.T) {
}
func TestRmi(t *testing.T) {
eng := engine.NewTestEngine(t)
eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime)

View file

@ -27,6 +27,12 @@ var (
INITSHA1 string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary
)
// A common interface to access the Fatal method of
// both testing.B and testing.T.
type Fataler interface {
Fatal(args ...interface{})
}
// ListOpts type
type ListOpts []string

View file

@ -21,27 +21,24 @@ var globalTestID string
// Create a temporary runtime suitable for unit testing.
// Call t.Fatal() at the first error.
func mkRuntime(f Fataler) *Runtime {
// Use the caller function name as a prefix.
// This helps trace temp directories back to their test.
pc, _, _, _ := runtime.Caller(1)
callerLongName := runtime.FuncForPC(pc).Name()
parts := strings.Split(callerLongName, ".")
callerShortName := parts[len(parts)-1]
if globalTestID == "" {
globalTestID = GenerateID()[:4]
}
prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, callerShortName)
utils.Debugf("prefix = '%s'", prefix)
runtime, err := newTestRuntime(prefix)
func mkRuntime(f utils.Fataler) *Runtime {
root, err := newTestDirectory(unitTestStoreBase)
if err != nil {
f.Fatal(err)
}
return runtime
config := &DaemonConfig{
Root: root,
AutoRestart: false,
}
r, err := NewRuntimeFromDirectory(config)
if err != nil {
f.Fatal(err)
}
r.UpdateCapabilities(true)
return r
}
func mkServerFromEngine(eng *engine.Engine, t Fataler) *Server {
func mkServerFromEngine(eng *engine.Engine, t utils.Fataler) *Server {
iSrv := eng.Hack_GetGlobalVar("httpapi.server")
if iSrv == nil {
t.Fatal("Legacy server field not set in engine")
@ -53,42 +50,53 @@ func mkServerFromEngine(eng *engine.Engine, t Fataler) *Server {
return srv
}
// A common interface to access the Fatal method of
// both testing.B and testing.T.
type Fataler interface {
Fatal(args ...interface{})
func NewTestEngine(t utils.Fataler) *engine.Engine {
root, err := newTestDirectory(unitTestStoreBase)
if err != nil {
t.Fatal(err)
}
eng, err := engine.New(root)
if err != nil {
t.Fatal(err)
}
// Load default plugins
// (This is manually copied and modified from main() until we have a more generic plugin system)
job := eng.Job("initapi")
job.Setenv("Root", root)
job.SetenvBool("AutoRestart", false)
if err := job.Run(); err != nil {
t.Fatal(err)
}
return eng
}
func newTestRuntime(prefix string) (runtime *Runtime, err error) {
func newTestDirectory(templateDir string) (dir string, err error) {
if globalTestID == "" {
globalTestID = GenerateID()[:4]
}
prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, getCallerName(2))
if prefix == "" {
prefix = "docker-test-"
}
utils.Debugf("prefix = %s", prefix)
utils.Debugf("newTestRuntime start")
root, err := ioutil.TempDir("", prefix)
defer func() {
utils.Debugf("newTestRuntime: %s", root)
}()
if err != nil {
return nil, err
dir, err = ioutil.TempDir("", prefix)
if err = os.Remove(dir); err != nil {
return
}
if err := os.Remove(root); err != nil {
return nil, err
if err = utils.CopyDirectory(templateDir, dir); err != nil {
return
}
if err := utils.CopyDirectory(unitTestStoreBase, root); err != nil {
return nil, err
return
}
config := &DaemonConfig{
Root: root,
AutoRestart: false,
}
runtime, err = NewRuntimeFromDirectory(config)
if err != nil {
return nil, err
}
runtime.UpdateCapabilities(true)
return runtime, nil
func getCallerName(depth int) string {
// Use the caller function name as a prefix.
// This helps trace temp directories back to their test.
pc, _, _, _ := runtime.Caller(depth + 1)
callerLongName := runtime.FuncForPC(pc).Name()
parts := strings.Split(callerLongName, ".")
callerShortName := parts[len(parts)-1]
return callerShortName
}
// Write `content` to the file at path `dst`, creating it if necessary,