<commit_before>package docker

import (
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"sync"
	"testing"
)

// FIXME: this is no longer needed
const testLayerPath string = "/var/lib/docker/docker-ut.tar"
const unitTestImageName string = "docker-ut"

var unitTestStoreBase string
var srv *Server

func nuke(runtime *Runtime) error {
	var wg sync.WaitGroup
	for _, container := range runtime.List() {
		wg.Add(1)
		go func() {
			container.Kill()
			wg.Add(-1)
		}()
	}
	wg.Wait()
	return os.RemoveAll(runtime.root)
}

func CopyDirectory(source, dest string) error {
	if _, err := exec.Command("cp", "-ra", source, dest).Output(); err != nil {
		return err
	}
	return nil
}

func layerArchive(tarfile string) (io.Reader, error) {
	// FIXME: need to close f somewhere
	f, err := os.Open(tarfile)
	if err != nil {
		return nil, err
	}
	return f, nil
}

func init() {
	// Hack to run sys init during unit testing
	if SelfPath() == "/sbin/init" {
		SysInit()
		return
	}

	if usr, err := user.Current(); err != nil {
		panic(err)
	} else if usr.Uid != "0" {
		panic("docker tests needs to be run as root")
	}

	// Create a temp directory
	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		panic(err)
	}
	unitTestStoreBase = root

	// Make it our Store root
	runtime, err := NewRuntimeFromDirectory(root)
	if err != nil {
		panic(err)
	}
	// Create the "Server"
	srv := &Server{
		runtime: runtime,
	}
	// Retrieve the Image
	if err := srv.CmdPull(os.Stdin, os.Stdout, unitTestImageName); err != nil {
		panic(err)
	}
}

func newTestRuntime() (*Runtime, error) {
	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		return nil, err
	}
	if err := os.Remove(root); err != nil {
		return nil, err
	}
	if err := CopyDirectory(unitTestStoreBase, root); err != nil {
		panic(err)
		return nil, err
	}

	runtime, err := NewRuntimeFromDirectory(root)
	if err != nil {
		return nil, err
	}

	return runtime, nil
}

func GetTestImage(runtime *Runtime) *Image {
	imgs, err := runtime.graph.All()
	if err != nil {
		panic(err)
	} else if len(imgs) < 1 {
		panic("GASP")
	}
	return imgs[0]
}

func TestRuntimeCreate(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)

	// Make sure we start we 0 containers
	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
	}
	container, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}

	defer func() {
		if err := runtime.Destroy(container); err != nil {
			t.Error(err)
		}
	}()

	// Make sure we can find the newly created container with List()
	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	// Make sure the container List() returns is the right one
	if runtime.List()[0].Id != container.Id {
		t.Errorf("Unexpected container %v returned by List", runtime.List()[0])
	}

	// Make sure we can get the container with Get()
	if runtime.Get(container.Id) == nil {
		t.Errorf("Unable to get newly created container")
	}

	// Make sure it is the right container
	if runtime.Get(container.Id) != container {
		t.Errorf("Get() returned the wrong container")
	}

	// Make sure Exists returns it as existing
	if !runtime.Exists(container.Id) {
		t.Errorf("Exists() returned false for a newly created container")
	}
}

func TestDestroy(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)
	container, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	// Destroy
	if err := runtime.Destroy(container); err != nil {
		t.Error(err)
	}

	// Make sure runtime.Exists() behaves correctly
	if runtime.Exists("test_destroy") {
		t.Errorf("Exists() returned true")
	}

	// Make sure runtime.List() doesn't list the destroyed container
	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

	// Make sure runtime.Get() refuses to return the unexisting container
	if runtime.Get(container.Id) != nil {
		t.Errorf("Unable to get newly created container")
	}

	// Make sure the container root directory does not exist anymore
	_, err = os.Stat(container.root)
	if err == nil || !os.IsNotExist(err) {
		t.Errorf("Container root directory still exists after destroy")
	}

	// Test double destroy
	if err := runtime.Destroy(container); err == nil {
		// It should have failed
		t.Errorf("Double destroy did not fail")
	}
}

func TestGet(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)
	container1, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container1)

	container2, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container2)

	container3, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container3)

	if runtime.Get(container1.Id) != container1 {
		t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.Id), container1)
	}

	if runtime.Get(container2.Id) != container2 {
		t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.Id), container2)
	}

	if runtime.Get(container3.Id) != container3 {
		t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.Id), container3)
	}

}

func TestRestore(t *testing.T) {

	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Remove(root); err != nil {
		t.Fatal(err)
	}
	if err := CopyDirectory(unitTestStoreBase, root); err != nil {
		t.Fatal(err)
	}

	runtime1, err := NewRuntimeFromDirectory(root)
	if err != nil {
		t.Fatal(err)
	}

	// Create a container with one instance of docker
	container1, err := runtime1.Create(&Config{
		Image: GetTestImage(runtime1).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime1.Destroy(container1)
	if len(runtime1.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime1.List()))
	}
	if err := container1.Run(); err != nil {
		t.Fatal(err)
	}

	// Here are are simulating a docker restart - that is, reloading all containers
	// from scratch
	runtime2, err := NewRuntimeFromDirectory(root)
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime2)
	if len(runtime2.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime2.List()))
	}
	container2 := runtime2.Get(container1.Id)
	if container2 == nil {
		t.Fatal("Unable to Get container")
	}
	if err := container2.Run(); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>kill the right containers in runtime_test<commit_after>package docker

import (
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"sync"
	"testing"
)

// FIXME: this is no longer needed
const testLayerPath string = "/var/lib/docker/docker-ut.tar"
const unitTestImageName string = "docker-ut"

var unitTestStoreBase string
var srv *Server

func nuke(runtime *Runtime) error {
	var wg sync.WaitGroup
	for _, container := range runtime.List() {
		wg.Add(1)
		go func(c *Container) {
			c.Kill()
			wg.Add(-1)
		}(container)
	}
	wg.Wait()
	return os.RemoveAll(runtime.root)
}

func CopyDirectory(source, dest string) error {
	if _, err := exec.Command("cp", "-ra", source, dest).Output(); err != nil {
		return err
	}
	return nil
}

func layerArchive(tarfile string) (io.Reader, error) {
	// FIXME: need to close f somewhere
	f, err := os.Open(tarfile)
	if err != nil {
		return nil, err
	}
	return f, nil
}

func init() {
	// Hack to run sys init during unit testing
	if SelfPath() == "/sbin/init" {
		SysInit()
		return
	}

	if usr, err := user.Current(); err != nil {
		panic(err)
	} else if usr.Uid != "0" {
		panic("docker tests needs to be run as root")
	}

	// Create a temp directory
	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		panic(err)
	}
	unitTestStoreBase = root

	// Make it our Store root
	runtime, err := NewRuntimeFromDirectory(root)
	if err != nil {
		panic(err)
	}
	// Create the "Server"
	srv := &Server{
		runtime: runtime,
	}
	// Retrieve the Image
	if err := srv.CmdPull(os.Stdin, os.Stdout, unitTestImageName); err != nil {
		panic(err)
	}
}

func newTestRuntime() (*Runtime, error) {
	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		return nil, err
	}
	if err := os.Remove(root); err != nil {
		return nil, err
	}
	if err := CopyDirectory(unitTestStoreBase, root); err != nil {
		panic(err)
		return nil, err
	}

	runtime, err := NewRuntimeFromDirectory(root)
	if err != nil {
		return nil, err
	}

	return runtime, nil
}

func GetTestImage(runtime *Runtime) *Image {
	imgs, err := runtime.graph.All()
	if err != nil {
		panic(err)
	} else if len(imgs) < 1 {
		panic("GASP")
	}
	return imgs[0]
}

func TestRuntimeCreate(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)

	// Make sure we start we 0 containers
	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
	}
	container, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}

	defer func() {
		if err := runtime.Destroy(container); err != nil {
			t.Error(err)
		}
	}()

	// Make sure we can find the newly created container with List()
	if len(runtime.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime.List()))
	}

	// Make sure the container List() returns is the right one
	if runtime.List()[0].Id != container.Id {
		t.Errorf("Unexpected container %v returned by List", runtime.List()[0])
	}

	// Make sure we can get the container with Get()
	if runtime.Get(container.Id) == nil {
		t.Errorf("Unable to get newly created container")
	}

	// Make sure it is the right container
	if runtime.Get(container.Id) != container {
		t.Errorf("Get() returned the wrong container")
	}

	// Make sure Exists returns it as existing
	if !runtime.Exists(container.Id) {
		t.Errorf("Exists() returned false for a newly created container")
	}
}

func TestDestroy(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)
	container, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	// Destroy
	if err := runtime.Destroy(container); err != nil {
		t.Error(err)
	}

	// Make sure runtime.Exists() behaves correctly
	if runtime.Exists("test_destroy") {
		t.Errorf("Exists() returned true")
	}

	// Make sure runtime.List() doesn't list the destroyed container
	if len(runtime.List()) != 0 {
		t.Errorf("Expected 0 container, %v found", len(runtime.List()))
	}

	// Make sure runtime.Get() refuses to return the unexisting container
	if runtime.Get(container.Id) != nil {
		t.Errorf("Unable to get newly created container")
	}

	// Make sure the container root directory does not exist anymore
	_, err = os.Stat(container.root)
	if err == nil || !os.IsNotExist(err) {
		t.Errorf("Container root directory still exists after destroy")
	}

	// Test double destroy
	if err := runtime.Destroy(container); err == nil {
		// It should have failed
		t.Errorf("Double destroy did not fail")
	}
}

func TestGet(t *testing.T) {
	runtime, err := newTestRuntime()
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime)
	container1, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container1)

	container2, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container2)

	container3, err := runtime.Create(&Config{
		Image: GetTestImage(runtime).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime.Destroy(container3)

	if runtime.Get(container1.Id) != container1 {
		t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.Id), container1)
	}

	if runtime.Get(container2.Id) != container2 {
		t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.Id), container2)
	}

	if runtime.Get(container3.Id) != container3 {
		t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.Id), container3)
	}

}

func TestRestore(t *testing.T) {

	root, err := ioutil.TempDir("", "docker-test")
	if err != nil {
		t.Fatal(err)
	}
	if err := os.Remove(root); err != nil {
		t.Fatal(err)
	}
	if err := CopyDirectory(unitTestStoreBase, root); err != nil {
		t.Fatal(err)
	}

	runtime1, err := NewRuntimeFromDirectory(root)
	if err != nil {
		t.Fatal(err)
	}

	// Create a container with one instance of docker
	container1, err := runtime1.Create(&Config{
		Image: GetTestImage(runtime1).Id,
		Cmd:   []string{"ls", "-al"},
	},
	)
	if err != nil {
		t.Fatal(err)
	}
	defer runtime1.Destroy(container1)
	if len(runtime1.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime1.List()))
	}
	if err := container1.Run(); err != nil {
		t.Fatal(err)
	}

	// Here are are simulating a docker restart - that is, reloading all containers
	// from scratch
	runtime2, err := NewRuntimeFromDirectory(root)
	if err != nil {
		t.Fatal(err)
	}
	defer nuke(runtime2)
	if len(runtime2.List()) != 1 {
		t.Errorf("Expected 1 container, %v found", len(runtime2.List()))
	}
	container2 := runtime2.Get(container1.Id)
	if container2 == nil {
		t.Fatal("Unable to Get container")
	}
	if err := container2.Run(); err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage
 * Copyright 2015-2017 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package minio

// awsS3EndpointMap Amazon S3 endpoint map.
var awsS3EndpointMap = map[string]string{
	"us-east-1":      "s3.dualstack.us-east-1.amazonaws.com",
	"us-east-2":      "s3.dualstack.us-east-2.amazonaws.com",
	"us-west-2":      "s3.dualstack.us-west-2.amazonaws.com",
	"us-west-1":      "s3.dualstack.us-west-1.amazonaws.com",
	"ca-central-1":   "s3.dualstack.ca-central-1.amazonaws.com",
	"eu-west-1":      "s3.dualstack.eu-west-1.amazonaws.com",
	"eu-west-2":      "s3.dualstack.eu-west-2.amazonaws.com",
	"eu-west-3":      "s3.dualstack.eu-west-3.amazonaws.com",
	"eu-central-1":   "s3.dualstack.eu-central-1.amazonaws.com",
	"ap-south-1":     "s3.dualstack.ap-south-1.amazonaws.com",
	"ap-southeast-1": "s3.dualstack.ap-southeast-1.amazonaws.com",
	"ap-southeast-2": "s3.dualstack.ap-southeast-2.amazonaws.com",
	"ap-northeast-1": "s3.dualstack.ap-northeast-1.amazonaws.com",
	"ap-northeast-2": "s3.dualstack.ap-northeast-2.amazonaws.com",
	"sa-east-1":      "s3.dualstack.sa-east-1.amazonaws.com",
	"us-gov-west-1":  "s3.dualstack.us-gov-west-1.amazonaws.com",
	"cn-north-1":     "s3.cn-north-1.amazonaws.com.cn",
	"cn-northwest-1": "s3.cn-northwest-1.amazonaws.com.cn",
}

// getS3Endpoint get Amazon S3 endpoint based on the bucket location.
func getS3Endpoint(bucketLocation string) (s3Endpoint string) {
	s3Endpoint, ok := awsS3EndpointMap[bucketLocation]
	if !ok {
		// Default to 's3.dualstack.us-east-1.amazonaws.com' endpoint.
		s3Endpoint = "s3.dualstack.us-east-1.amazonaws.com"
	}
	return s3Endpoint
}
<commit_msg>Support new AWS regions: eu-north-1 and us-gov-east-1 (#1060)<commit_after>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage
 * Copyright 2015-2017 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package minio

// awsS3EndpointMap Amazon S3 endpoint map.
var awsS3EndpointMap = map[string]string{
	"us-east-1":      "s3.dualstack.us-east-1.amazonaws.com",
	"us-east-2":      "s3.dualstack.us-east-2.amazonaws.com",
	"us-west-2":      "s3.dualstack.us-west-2.amazonaws.com",
	"us-west-1":      "s3.dualstack.us-west-1.amazonaws.com",
	"ca-central-1":   "s3.dualstack.ca-central-1.amazonaws.com",
	"eu-west-1":      "s3.dualstack.eu-west-1.amazonaws.com",
	"eu-west-2":      "s3.dualstack.eu-west-2.amazonaws.com",
	"eu-west-3":      "s3.dualstack.eu-west-3.amazonaws.com",
	"eu-central-1":   "s3.dualstack.eu-central-1.amazonaws.com",
	"eu-north-1":     "s3.dualstack.eu-north-1.amazonaws.com",
	"ap-south-1":     "s3.dualstack.ap-south-1.amazonaws.com",
	"ap-southeast-1": "s3.dualstack.ap-southeast-1.amazonaws.com",
	"ap-southeast-2": "s3.dualstack.ap-southeast-2.amazonaws.com",
	"ap-northeast-1": "s3.dualstack.ap-northeast-1.amazonaws.com",
	"ap-northeast-2": "s3.dualstack.ap-northeast-2.amazonaws.com",
	"sa-east-1":      "s3.dualstack.sa-east-1.amazonaws.com",
	"us-gov-west-1":  "s3.dualstack.us-gov-west-1.amazonaws.com",
	"us-gov-east-1":  "s3.dualstack.us-gov-east-1.amazonaws.com",
	"cn-north-1":     "s3.cn-north-1.amazonaws.com.cn",
	"cn-northwest-1": "s3.cn-northwest-1.amazonaws.com.cn",
}

// getS3Endpoint get Amazon S3 endpoint based on the bucket location.
func getS3Endpoint(bucketLocation string) (s3Endpoint string) {
	s3Endpoint, ok := awsS3EndpointMap[bucketLocation]
	if !ok {
		// Default to 's3.dualstack.us-east-1.amazonaws.com' endpoint.
		s3Endpoint = "s3.dualstack.us-east-1.amazonaws.com"
	}
	return s3Endpoint
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safehttp

import (
	"net/http"
)

// TODO: add the missing methods
const (
	// HTTP GET request
	MethodGet = "GET"
	// HTTP Post request
	MethodPost = "POST"
)

// ServeMux is an HTTP request multiplexer. It matches the URL of each incoming
// request against a list of registered patterns and calls the handler for
// the pattern that most closely matches the URL.
//
// Patterns name are fixed, rooted paths, like "/favicon.ico", or rooted
// subtrees like "/images/" (note the trailing slash). Longer patterns take
// precedence over shorter ones, so that if there are handlers registered for
// both "/images/" and "/images/thumbnails/", the latter handler will be called
// for paths beginning "/images/thumbnails/" and the former will receive
// requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted subtree, the
// pattern "/" matches all paths not matched by other registered patterns,
// not just the URL with Path == "/".
//
// If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to
// the subtree root (adding the trailing slash). This behavior can be overridden
// with a separate registration for the path without the trailing slash. For
// example, registering "/images/" causes ServeMux to redirect a request for
// "/images" to "/images/", unless "/images" has been registered separately.
//
// Patterns may optionally begin with a host name, restricting matches to URLs
// on that host only. Host-specific patterns take precedence over general
// patterns, so that a handler might register for the two patterns "/codesearch"
// and "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// ServeMux also takes care of sanitizing the URL request path and the Host
// header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL.
//
// Multiple HTTP methods can be served for one pattern and the user is expected
// to register a handler for each method supported. These will be combined
// into one handler per pattern. The framework will then match each
// incoming request to its underlying handler according to its HTTP method.
type ServeMux struct {
	mux     *http.ServeMux
	domains map[string]bool
	disp    Dispatcher

	// Maps user-provided patterns to combined handlers which encapsulate
	// multiple handlers, each one associated with an HTTP method.
	handlers map[string]methodHandler
}

// NewServeMux allocates and returns a new ServeMux
// TODO(@mattiasgrenfeldt, @mihalimara22): make domains a variadic of string ..//**literals**.
func NewServeMux(dispatcher Dispatcher, domains ...string) *ServeMux {
	d := map[string]bool{}
	for _, host := range domains {
		d[host] = true
	}
	return &ServeMux{
		mux:      http.NewServeMux(),
		domains:  d,
		disp:     dispatcher,
		handlers: map[string]methodHandler{},
	}
}

// Handle registers a handler for the given pattern and method. If another
// handler is already registered for the same pattern and method, Handle panics.
func (m *ServeMux) Handle(pattern string, method string, h Handler) {
	ch, ok := m.handlers[pattern]
	if !ok {
		ch := methodHandler{
			methodMap: map[string]Handler{method: h},
			domains:   m.domains,
			disp:      m.disp,
		}

		m.handlers[pattern] = ch
		m.mux.Handle(pattern, ch)
		return
	}

	if _, ok := ch.methodMap[method]; ok {
		panic("method already registered")
	}
	ch.methodMap[method] = h
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// methodHandler is collection of handlers based on the request method.
type methodHandler struct {
	// Maps an HTTP method to its handler
	methodMap map[string]Handler
	domains   map[string]bool
	disp      Dispatcher
}

// ServeHTTP dispatches the request to the handler associated with
// the incoming request's method.
func (m methodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !m.domains[r.Host] {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	h, ok := m.methodMap[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(newResponseWriter(m.disp, w), newIncomingRequest(r))
}
<commit_msg>Rename method to handler map in methodHandler<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safehttp

import (
	"net/http"
)

// TODO: add the missing methods
const (
	// HTTP GET request
	MethodGet = "GET"
	// HTTP Post request
	MethodPost = "POST"
)

// ServeMux is an HTTP request multiplexer. It matches the URL of each incoming
// request against a list of registered patterns and calls the handler for
// the pattern that most closely matches the URL.
//
// Patterns name are fixed, rooted paths, like "/favicon.ico", or rooted
// subtrees like "/images/" (note the trailing slash). Longer patterns take
// precedence over shorter ones, so that if there are handlers registered for
// both "/images/" and "/images/thumbnails/", the latter handler will be called
// for paths beginning "/images/thumbnails/" and the former will receive
// requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted subtree, the
// pattern "/" matches all paths not matched by other registered patterns,
// not just the URL with Path == "/".
//
// If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to
// the subtree root (adding the trailing slash). This behavior can be overridden
// with a separate registration for the path without the trailing slash. For
// example, registering "/images/" causes ServeMux to redirect a request for
// "/images" to "/images/", unless "/images" has been registered separately.
//
// Patterns may optionally begin with a host name, restricting matches to URLs
// on that host only. Host-specific patterns take precedence over general
// patterns, so that a handler might register for the two patterns "/codesearch"
// and "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// ServeMux also takes care of sanitizing the URL request path and the Host
// header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL.
//
// Multiple HTTP methods can be served for one pattern and the user is expected
// to register a handler for each method supported. These will be combined
// into one handler per pattern. The framework will then match each
// incoming request to its underlying handler according to its HTTP method.
type ServeMux struct {
	mux     *http.ServeMux
	domains map[string]bool
	disp    Dispatcher

	// Maps user-provided patterns to combined handlers which encapsulate
	// multiple handlers, each one associated with an HTTP method.
	handlers map[string]methodHandler
}

// NewServeMux allocates and returns a new ServeMux
// TODO(@mattiasgrenfeldt, @mihalimara22): make domains a variadic of string ..//**literals**.
func NewServeMux(dispatcher Dispatcher, domains ...string) *ServeMux {
	d := map[string]bool{}
	for _, host := range domains {
		d[host] = true
	}
	return &ServeMux{
		mux:      http.NewServeMux(),
		domains:  d,
		disp:     dispatcher,
		handlers: map[string]methodHandler{},
	}
}

// Handle registers a handler for the given pattern and method. If another
// handler is already registered for the same pattern and method, Handle panics.
func (m *ServeMux) Handle(pattern string, method string, h Handler) {
	ch, ok := m.handlers[pattern]
	if !ok {
		ch := methodHandler{
			handlers: map[string]Handler{method: h},
			domains:  m.domains,
			disp:     m.disp,
		}

		m.handlers[pattern] = ch
		m.mux.Handle(pattern, ch)
		return
	}

	if _, ok := ch.handlers[method]; ok {
		panic("method already registered")
	}
	ch.handlers[method] = h
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// methodHandler is collection of handlers based on the request method.
type methodHandler struct {
	// Maps an HTTP method to its handler
	handlers map[string]Handler
	domains  map[string]bool
	disp     Dispatcher
}

// ServeHTTP dispatches the request to the handler associated with
// the incoming request's method.
func (m methodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !m.domains[r.Host] {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	h, ok := m.handlers[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(newResponseWriter(m.disp, w), newIncomingRequest(r))
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// An integration test that uses a real S3 account. Run as follows:
//
//     go run integration_test/*.go \
//         -key_id <key ID> \
//         -bucket <bucket> \
//         -region s3-ap-northeast-1.amazonaws.com
//

package main

import (
	"bytes"
	"flag"
	"fmt"
	. "github.com/jacobsa/ogletest"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/s3"
	"os"
	"regexp"
	"strings"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

var keyId = flag.String("key_id", "", "Access key ID.")
var bucketName = flag.String("bucket", "", "Bucket name.")
var region = flag.String("region", "", "Region endpoint server.")
var accessKey aws.AccessKey

type integrationTest struct {
}

////////////////////////////////////////////////////////////////////////
// Bucket
////////////////////////////////////////////////////////////////////////

type BucketTest struct {
	integrationTest
	bucket s3.Bucket
}

func init() { RegisterTestSuite(&BucketTest{}) }

func (t *BucketTest) SetUp(i *TestInfo) {
	var err error

	// Open a bucket.
	t.bucket, err = s3.OpenBucket(*bucketName, s3.Region(*region), accessKey)
	AssertEq(nil, err)
}

func (t *BucketTest) TodoRefactorMe() {
	// Attempt to create an object.
	objectName := "타코&burrito?enchilada"
	data := []byte("taco")
	data = append(data, 0x00)
	data = append(data, []byte("burrito")...)

	if err := t.bucket.StoreObject(objectName, data); err != nil {
		fmt.Println("StoreObject:", err)
		os.Exit(1)
	}

	// TODO(jacobsa): Test ListKeys.

	// Read the object back.
	dataRead, err := t.bucket.GetObject(objectName)
	if err != nil {
		fmt.Println("GetObject:", err)
		os.Exit(1)
	}

	// Make sure the result is identical.
	if !bytes.Equal(data, dataRead) {
		fmt.Printf("Mismatch; %x vs. %x\n", data, dataRead)
		os.Exit(1)
	}

	// Attempt to load a non-existent object. We should get a 404 back.
	_, err = t.bucket.GetObject("other_name")
	if err == nil || strings.Count(err.Error(), "404") != 1 {
		fmt.Println("Unexpected 404 error:", err)
		os.Exit(1)
	}
}

////////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////////

func main() {
	flag.Parse()

	if *keyId == "" {
		fmt.Println("You must set the -key_id flag.")
		fmt.Println("Find a key ID here:")
		fmt.Println("    https://portal.aws.amazon.com/gp/aws/securityCredentials")
		os.Exit(1)
	}

	if *bucketName == "" {
		fmt.Println("You must set the -bucket flag.")
		fmt.Println("Manage your buckets here:")
		fmt.Println("    http://aws.amazon.com/console/")
		os.Exit(1)
	}

	if *region == "" {
		fmt.Println("You must set the -region flag. See region.go.")
		os.Exit(1)
	}

	// Read in the access key.
	accessKey.Id = *keyId
	accessKey.Secret = readPassword("Access key secret: ")

	// Run the tests.
	matchString := func (pat, str string) (bool, error) {
		re, err := regexp.Compile(pat)
		if err != nil {
			return false, err
		}

		return re.MatchString(str), nil
	}

	testing.Main(
		matchString,
		[]testing.InternalTest{
			testing.InternalTest{
				Name: "IntegrationTest",
				F: func (t *testing.T) { RunTests(t) },
			},
		},
		[]testing.InternalBenchmark{},
		[]testing.InternalExample{},
	)
}
<commit_msg>Added another comment.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// An integration test that uses a real S3 account. Run as follows:
//
//     go run integration_test/*.go \
//         -key_id <key ID> \
//         -bucket <bucket> \
//         -region s3-ap-northeast-1.amazonaws.com
//
// Before doing this, create an empty bucket (or delete the contents of an
// existing bucket) using the S3 management console.

package main

import (
	"bytes"
	"flag"
	"fmt"
	. "github.com/jacobsa/ogletest"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/s3"
	"os"
	"regexp"
	"strings"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

var keyId = flag.String("key_id", "", "Access key ID.")
var bucketName = flag.String("bucket", "", "Bucket name.")
var region = flag.String("region", "", "Region endpoint server.")
var accessKey aws.AccessKey

type integrationTest struct {
}

////////////////////////////////////////////////////////////////////////
// Bucket
////////////////////////////////////////////////////////////////////////

type BucketTest struct {
	integrationTest
	bucket s3.Bucket
}

func init() { RegisterTestSuite(&BucketTest{}) }

func (t *BucketTest) SetUp(i *TestInfo) {
	var err error

	// Open a bucket.
	t.bucket, err = s3.OpenBucket(*bucketName, s3.Region(*region), accessKey)
	AssertEq(nil, err)
}

func (t *BucketTest) TodoRefactorMe() {
	// Attempt to create an object.
	objectName := "타코&burrito?enchilada"
	data := []byte("taco")
	data = append(data, 0x00)
	data = append(data, []byte("burrito")...)

	if err := t.bucket.StoreObject(objectName, data); err != nil {
		fmt.Println("StoreObject:", err)
		os.Exit(1)
	}

	// TODO(jacobsa): Test ListKeys.

	// Read the object back.
	dataRead, err := t.bucket.GetObject(objectName)
	if err != nil {
		fmt.Println("GetObject:", err)
		os.Exit(1)
	}

	// Make sure the result is identical.
	if !bytes.Equal(data, dataRead) {
		fmt.Printf("Mismatch; %x vs. %x\n", data, dataRead)
		os.Exit(1)
	}

	// Attempt to load a non-existent object. We should get a 404 back.
	_, err = t.bucket.GetObject("other_name")
	if err == nil || strings.Count(err.Error(), "404") != 1 {
		fmt.Println("Unexpected 404 error:", err)
		os.Exit(1)
	}
}

////////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////////

func main() {
	flag.Parse()

	if *keyId == "" {
		fmt.Println("You must set the -key_id flag.")
		fmt.Println("Find a key ID here:")
		fmt.Println("    https://portal.aws.amazon.com/gp/aws/securityCredentials")
		os.Exit(1)
	}

	if *bucketName == "" {
		fmt.Println("You must set the -bucket flag.")
		fmt.Println("Manage your buckets here:")
		fmt.Println("    http://aws.amazon.com/console/")
		os.Exit(1)
	}

	if *region == "" {
		fmt.Println("You must set the -region flag. See region.go.")
		os.Exit(1)
	}

	// Read in the access key.
	accessKey.Id = *keyId
	accessKey.Secret = readPassword("Access key secret: ")

	// Run the tests.
	matchString := func (pat, str string) (bool, error) {
		re, err := regexp.Compile(pat)
		if err != nil {
			return false, err
		}

		return re.MatchString(str), nil
	}

	testing.Main(
		matchString,
		[]testing.InternalTest{
			testing.InternalTest{
				Name: "IntegrationTest",
				F: func (t *testing.T) { RunTests(t) },
			},
		},
		[]testing.InternalBenchmark{},
		[]testing.InternalExample{},
	)
}
<|endoftext|>


<commit_before>package ui

import (
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"text/tabwriter"

	"github.com/adamdecaf/cert-manage/tools/_x509"
	"github.com/adamdecaf/cert-manage/tools/file"
	"github.com/adamdecaf/cert-manage/tools/pem"
)

const (
	fingerprintPreviewLength = 16
)

var (
	outputFormats = map[string]printer{
		"openssl":       printCertsOpenSSL,
		DefaultFormat(): printCertsTable,
		"raw":           printCertsRaw,
	}
)

// showCertsOnCli outputs the slice of certificates in `cfg.Format` to stdout
func showCertsOnCli(certs []*x509.Certificate, cfg *Config) error {
	fn, ok := outputFormats[strings.ToLower(cfg.Format)]
	if !ok {
		return fmt.Errorf("Unknown format %s specified", cfg.Format)
	}
	fn(certs)
	return nil
}

type printer func([]*x509.Certificate)

// printCertsTable outputs a nicely formatted table of the certs found. This uses golang's
// native text/tabwriter package to align based on the rows given to it.
func printCertsTable(certs []*x509.Certificate) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	fmt.Fprintln(w, "Subject\tIssuer\tPublic Key Algorithm\tSHA256 Fingerprint\tNot Before\tNot After")
	defer func() {
		err := w.Flush()
		if err != nil {
			fmt.Printf("error flushing output table - %s\n", err)
		}
	}()

	rows := make([]string, len(certs))
	for i := range certs {
		fingerprint := _x509.GetHexSHA256Fingerprint(*certs[i])

		c1 := _x509.StringifyPKIXName(certs[i].Subject)
		c2 := _x509.StringifyPKIXName(certs[i].Issuer)
		c3 := _x509.StringifyPubKeyAlgo(certs[i].PublicKeyAlgorithm)
		c4 := fingerprint[:fingerprintPreviewLength]

		c5 := certs[i].NotBefore.Format("2006-01-02")
		c6 := certs[i].NotAfter.Format("2006-01-02")

		rows[i] = fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s", c1, c2, c3, c4, c5, c6)
	}

	file.SortNames(rows)
	for i := range rows {
		fmt.Fprintln(w, rows[i])
	}
}

type openssl struct{}

func (o *openssl) installed() bool {
	err := exec.Command("openssl", "version").Run()
	return err == nil
}
func (o *openssl) printCertificate(path string) error {
	out, err := exec.Command("openssl", "x509", "-in", path, "-noout", "-text").CombinedOutput()
	if err != nil {
		return err
	}
	fmt.Println(string(out))
	return nil
}

// printCertsOpenSSL shells out to openssl (if available) to print out each certificate
func printCertsOpenSSL(certs []*x509.Certificate) {
	ossl := openssl{}

	// fail if we can't find openssl
	if !ossl.installed() {
		fmt.Println("Unable to find openssl")
		return
	}

	tmp, err := ioutil.TempFile("", "cert-mange-print-cert")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer os.Remove(tmp.Name())

	wrapper := make([]*x509.Certificate, 1)
	for i := range certs {
		// render each cert to temp file, then `openssl x509 -in tmp.Name() -outform pem`
		wrapper[0] = certs[i]
		err = pem.ToFile(tmp.Name(), wrapper)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = ossl.printCertificate(tmp.Name())
		if err != nil {
			fmt.Println(err)
			return
		}
	}
	return
}

// printCertsRaw very verbosly prints out the ecah certificate's information
// to stdout. This isn't very useful for machine parsing or small screen displays.
func printCertsRaw(certs []*x509.Certificate) {
	for i := range certs {
		fmt.Printf("Certificate\n")
		fmt.Printf("  SHA1 Fingerprint - %s\n", _x509.GetHexSHA1Fingerprint(*certs[i]))
		fmt.Printf("  SHA256 Fingerprint - %s\n", _x509.GetHexSHA256Fingerprint(*certs[i]))
		fmt.Printf("  SerialNumber: %d\n", certs[i].SerialNumber)
		fmt.Printf("  Subject: %s\n", _x509.StringifyPKIXName(certs[i].Subject))
		fmt.Printf("  Issuer: %s\n", _x509.StringifyPKIXName(certs[i].Issuer))
		fmt.Printf("  NotBefore - %s, NotAfter - %s\n", certs[i].NotBefore, certs[i].NotAfter)
		fmt.Printf("  IsCA - %t\n", certs[i].IsCA)

		if len(certs[i].DNSNames) > 0 {
			fmt.Printf("  DNSNames\n")
			for j := range certs[i].DNSNames {
				fmt.Printf("    %s\n", certs[i].DNSNames[j])
			}
		}

		if len(certs[i].EmailAddresses) > 0 {
			fmt.Printf("  EmailAddresses\n")
			for j := range certs[i].EmailAddresses {
				fmt.Printf("    %s\n", certs[i].EmailAddresses[j])
			}
		}

		if len(certs[i].IPAddresses) > 0 {
			fmt.Printf("  IPAddresses\n")
			for j := range certs[i].IPAddresses {
				fmt.Printf("    %s\n", certs[i].IPAddresses[j])
			}
		}

		if len(certs[i].PermittedDNSDomains) > 0 {
			fmt.Printf("  PermittedDNSDomains\n")
			for j := range certs[i].PermittedDNSDomains {
				fmt.Printf("    %s\n", certs[i].PermittedDNSDomains[j])
			}
		}

		if len(certs[i].CRLDistributionPoints) > 0 {
			fmt.Printf("  CRLDistributionPoints\n")
			for j := range certs[i].CRLDistributionPoints {
				fmt.Printf("    %s\n", certs[i].CRLDistributionPoints[j])
			}
		}
	}
}
<commit_msg>ui/cli: accept another writer, but keep os.Stdout<commit_after>package ui

import (
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"text/tabwriter"

	"github.com/adamdecaf/cert-manage/tools/_x509"
	"github.com/adamdecaf/cert-manage/tools/file"
	"github.com/adamdecaf/cert-manage/tools/pem"
)

const (
	fingerprintPreviewLength = 16
)

var (
	outputFormats = map[string]printer{
		"openssl":       printCertsOpenSSL,
		DefaultFormat(): printCertsTable,
		"raw":           printCertsRaw,
	}
)

// showCertsOnCli outputs the slice of certificates in `cfg.Format` to stdout
func showCertsOnCli(certs []*x509.Certificate, cfg *Config) error {
	fn, ok := outputFormats[strings.ToLower(cfg.Format)]
	if !ok {
		return fmt.Errorf("Unknown format %s specified", cfg.Format)
	}
	fn(os.Stdout, certs)
	return nil
}

// printer accepts a writer (*os.File) and the certificates to write
type printer func(*os.File, []*x509.Certificate)

// printCertsTable outputs a nicely formatted table of the certs found. This uses golang's
// native text/tabwriter package to align based on the rows given to it.
func printCertsTable(fd *os.File, certs []*x509.Certificate) {
	w := tabwriter.NewWriter(fd, 0, 0, 1, ' ', 0)
	fmt.Fprintln(w, "Subject\tIssuer\tPublic Key Algorithm\tSHA256 Fingerprint\tNot Before\tNot After")
	defer func() {
		err := w.Flush()
		if err != nil {
			fmt.Printf("error flushing output table - %s\n", err)
		}
	}()

	rows := make([]string, len(certs))
	for i := range certs {
		fingerprint := _x509.GetHexSHA256Fingerprint(*certs[i])

		c1 := _x509.StringifyPKIXName(certs[i].Subject)
		c2 := _x509.StringifyPKIXName(certs[i].Issuer)
		c3 := _x509.StringifyPubKeyAlgo(certs[i].PublicKeyAlgorithm)
		c4 := fingerprint[:fingerprintPreviewLength]

		c5 := certs[i].NotBefore.Format("2006-01-02")
		c6 := certs[i].NotAfter.Format("2006-01-02")

		rows[i] = fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s", c1, c2, c3, c4, c5, c6)
	}

	file.SortNames(rows)
	for i := range rows {
		fmt.Fprintln(w, rows[i])
	}
}

type openssl struct {
	writer *os.File
}

func (o *openssl) installed() bool {
	err := exec.Command("openssl", "version").Run()
	return err == nil
}
func (o *openssl) printCertificate(path string) error {
	out, err := exec.Command("openssl", "x509", "-in", path, "-noout", "-text").CombinedOutput()
	if err != nil {
		return err
	}
	fmt.Fprintln(o.writer, string(out))
	return nil
}

// printCertsOpenSSL shells out to openssl (if available) to print out each certificate
func printCertsOpenSSL(w *os.File, certs []*x509.Certificate) {
	ossl := openssl{writer: w}

	// fail if we can't find openssl
	if !ossl.installed() {
		fmt.Println("Unable to find openssl")
		return
	}

	tmp, err := ioutil.TempFile("", "cert-mange-print-cert")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer os.Remove(tmp.Name())

	wrapper := make([]*x509.Certificate, 1)
	for i := range certs {
		// render each cert to temp file, then `openssl x509 -in tmp.Name() -outform pem`
		wrapper[0] = certs[i]
		err = pem.ToFile(tmp.Name(), wrapper)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = ossl.printCertificate(tmp.Name())
		if err != nil {
			fmt.Println(err)
			return
		}
	}
	return
}

// printCertsRaw very verbosly prints out the ecah certificate's information
// to stdout. This isn't very useful for machine parsing or small screen displays.
func printCertsRaw(w *os.File, certs []*x509.Certificate) {
	for i := range certs {
		fmt.Fprintf(w, "Certificate\n")
		fmt.Fprintf(w, "  SHA1 Fingerprint - %s\n", _x509.GetHexSHA1Fingerprint(*certs[i]))
		fmt.Fprintf(w, "  SHA256 Fingerprint - %s\n", _x509.GetHexSHA256Fingerprint(*certs[i]))
		fmt.Fprintf(w, "  SerialNumber: %d\n", certs[i].SerialNumber)
		fmt.Fprintf(w, "  Subject: %s\n", _x509.StringifyPKIXName(certs[i].Subject))
		fmt.Fprintf(w, "  Issuer: %s\n", _x509.StringifyPKIXName(certs[i].Issuer))
		fmt.Fprintf(w, "  NotBefore - %s, NotAfter - %s\n", certs[i].NotBefore, certs[i].NotAfter)
		fmt.Fprintf(w, "  IsCA - %t\n", certs[i].IsCA)

		if len(certs[i].DNSNames) > 0 {
			fmt.Fprintf(w, "  DNSNames\n")
			for j := range certs[i].DNSNames {
				fmt.Fprintf(w, "    %s\n", certs[i].DNSNames[j])
			}
		}

		if len(certs[i].EmailAddresses) > 0 {
			fmt.Fprintf(w, "  EmailAddresses\n")
			for j := range certs[i].EmailAddresses {
				fmt.Fprintf(w, "    %s\n", certs[i].EmailAddresses[j])
			}
		}

		if len(certs[i].IPAddresses) > 0 {
			fmt.Fprintf(w, "  IPAddresses\n")
			for j := range certs[i].IPAddresses {
				fmt.Fprintf(w, "    %s\n", certs[i].IPAddresses[j])
			}
		}

		if len(certs[i].PermittedDNSDomains) > 0 {
			fmt.Fprintf(w, "  PermittedDNSDomains\n")
			for j := range certs[i].PermittedDNSDomains {
				fmt.Fprintf(w, "    %s\n", certs[i].PermittedDNSDomains[j])
			}
		}

		if len(certs[i].CRLDistributionPoints) > 0 {
			fmt.Fprintf(w, "  CRLDistributionPoints\n")
			for j := range certs[i].CRLDistributionPoints {
				fmt.Fprintf(w, "    %s\n", certs[i].CRLDistributionPoints[j])
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package environs

import (
	. "launchpad.net/gocheck"

	"launchpad.net/juju-core/cert"
	"launchpad.net/juju-core/testing"
)

// EnvironsCertSuite tests the internal functions defined in environs/cert.go
type EnvironsCertSuite struct {
	testing.LoggingSuite
}

var _ = Suite(&EnvironsCertSuite{})

type testCerts struct {
	cert []byte
	key  []byte
}

func (*EnvironsCertSuite) TestGenerateCertificate(c *C) {
	defer testing.MakeSampleHome(c).Restore()
	env, err := NewFromName(testing.SampleEnvName)
	c.Assert(err, IsNil)

	var savedCerts testCerts
	writeFunc := func(name string, cert, key []byte) error {
		savedCerts.cert = cert
		savedCerts.key = key
		return nil
	}
	generateCertificate(env, writeFunc)

	// Check that the cert and key have been set correctly in the configuration
	cfgCertPEM, cfgCertOK := env.Config().CACert()
	cfgKeyPEM, cfgKeyOK := env.Config().CAPrivateKey()
	c.Assert(cfgCertOK, Equals, true)
	c.Assert(cfgKeyOK, Equals, true)
	c.Assert(cfgCertPEM, DeepEquals, savedCerts.cert)
	c.Assert(cfgKeyPEM, DeepEquals, savedCerts.key)

	// Check the common name of the generated cert
	caCert, _, err := cert.ParseCertAndKey(cfgCertPEM, cfgKeyPEM)
	c.Assert(err, IsNil)
	c.Assert(caCert.Subject.CommonName, Equals, `juju-generated CA for environment `+testing.SampleEnvName)
}
<commit_msg>environs: fix for cert name fix<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package environs

import (
	. "launchpad.net/gocheck"

	"launchpad.net/juju-core/cert"
	"launchpad.net/juju-core/testing"
)

// EnvironsCertSuite tests the internal functions defined in environs/cert.go
type EnvironsCertSuite struct {
	testing.LoggingSuite
}

var _ = Suite(&EnvironsCertSuite{})

type testCerts struct {
	cert []byte
	key  []byte
}

func (*EnvironsCertSuite) TestGenerateCertificate(c *C) {
	defer testing.MakeSampleHome(c).Restore()
	env, err := NewFromName(testing.SampleEnvName)
	c.Assert(err, IsNil)

	var savedCerts testCerts
	writeFunc := func(name string, cert, key []byte) error {
		savedCerts.cert = cert
		savedCerts.key = key
		return nil
	}
	generateCertificate(env, writeFunc)

	// Check that the cert and key have been set correctly in the configuration
	cfgCertPEM, cfgCertOK := env.Config().CACert()
	cfgKeyPEM, cfgKeyOK := env.Config().CAPrivateKey()
	c.Assert(cfgCertOK, Equals, true)
	c.Assert(cfgKeyOK, Equals, true)
	c.Assert(cfgCertPEM, DeepEquals, savedCerts.cert)
	c.Assert(cfgKeyPEM, DeepEquals, savedCerts.key)

	// Check the common name of the generated cert
	caCert, _, err := cert.ParseCertAndKey(cfgCertPEM, cfgKeyPEM)
	c.Assert(err, IsNil)
	c.Assert(caCert.Subject.CommonName, Equals, `juju-generated CA for environment "`+testing.SampleEnvName+`"`)
}
<|endoftext|>


<commit_before>package jujutest

import (
	"fmt"
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/juju"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/version"
	"time"
)

// TestStartStop is similar to Tests.TestStartStop except
// that it does not assume a pristine environment.
func (t *LiveTests) TestStartStop(c *C) {
	insts, err := t.Env.Instances(nil)
	c.Assert(err, IsNil)
	c.Check(insts, HasLen, 0)

	inst, err := t.Env.StartInstance(0, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst, NotNil)
	id0 := inst.Id()

	insts, err = t.Env.Instances([]string{id0, id0})
	c.Assert(err, IsNil)
	c.Assert(insts, HasLen, 2)
	c.Assert(insts[0].Id(), Equals, id0)
	c.Assert(insts[1].Id(), Equals, id0)

	insts, err = t.Env.AllInstances()
	c.Assert(err, IsNil)
	// differs from the check above because AllInstances returns
	// a set (without duplicates) containing only one instance.
	c.Assert(insts, HasLen, 1)
	c.Assert(insts[0].Id(), Equals, id0)

	dns, err := inst.WaitDNSName()
	c.Assert(err, IsNil)
	c.Assert(dns, Not(Equals), "")

	insts, err = t.Env.Instances([]string{id0, ""})
	c.Assert(err, Equals, environs.ErrPartialInstances)
	c.Assert(insts, HasLen, 2)
	c.Check(insts[0].Id(), Equals, id0)
	c.Check(insts[1], IsNil)

	err = t.Env.StopInstances([]environs.Instance{inst})
	c.Assert(err, IsNil)

	// Stopping may not be noticed at first due to eventual
	// consistency. Repeat a few times to ensure we get the error.
	for i := 0; i < 20; i++ {
		insts, err = t.Env.Instances([]string{id0})
		if err != nil {
			break
		}
		time.Sleep(0.25e9)
	}
	c.Assert(err, Equals, environs.ErrNoInstances)
	c.Assert(insts, HasLen, 0)
}

func (t *LiveTests) TestPorts(c *C) {
	inst1, err := t.Env.StartInstance(1, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst1, NotNil)
	defer t.Env.StopInstances([]environs.Instance{inst1})

	ports, err := inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)

	inst2, err := t.Env.StartInstance(2, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst2, NotNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)
	defer t.Env.StopInstances([]environs.Instance{inst2})

	// Open some ports and check they're there.
	err = inst1.OpenPorts(1, []state.Port{{"udp", 67}, {"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)

	// Check there's no crosstalk to another machine
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 89}, {"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}})
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})

	// Check that opening the same port again is ok.
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}})

	// Check that opening the same port again and another port is ok.
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 45}, {"tcp", 99}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}, {"tcp", 99}})

	// Check that we can close ports and that there's no crosstalk.
	err = inst2.ClosePorts(2, []state.Port{{"tcp", 45}, {"tcp", 99}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 89}})
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})

	// Check that we can close multiple ports.
	err = inst1.ClosePorts(1, []state.Port{{"tcp", 45}, {"udp", 67}})
	c.Assert(err, IsNil)
	ports, err = inst1.Ports(1)
	c.Assert(ports, HasLen, 0)

	// Check that we can close ports that aren't there.
	err = inst2.ClosePorts(2, []state.Port{{"tcp", 111}, {"udp", 222}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 89}})
}

func (t *LiveTests) TestBootstrapMultiple(c *C) {
	t.BootstrapOnce(c)

	// Wait for a while to let eventual consistency catch up, hopefully.
	time.Sleep(t.ConsistencyDelay)
	err := t.Env.Bootstrap(false)
	c.Assert(err, ErrorMatches, "environment is already bootstrapped")

	c.Logf("destroy env")
	t.Destroy(c)

	// check that we can bootstrap after destroy
	t.BootstrapOnce(c)
}

func (t *LiveTests) TestBootstrapProvisioner(c *C) {
	if !t.CanOpenState || !t.HasProvisioner {
		c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner))
	}
	t.BootstrapOnce(c)

	// TODO(dfc) constructing a juju.Conn by hand is a code smell.
	conn, err := juju.NewConnFromAttrs(t.Env.Config().AllAttrs())
	c.Assert(err, IsNil)

	st, err := conn.State()
	c.Assert(err, IsNil)

	// Check that we can upgrade the machine agent on the bootstrap machine.
	m, err := st.Machine(0)
	c.Assert(err, IsNil)

	t.checkUpgradeMachineAgent(c, m)

	// place a new machine into the state
	m, err = st.AddMachine()
	c.Assert(err, IsNil)

	t.assertStartInstance(c, m)

	// now remove it
	c.Assert(st.RemoveMachine(m.Id()), IsNil)

	// watch the PA remove it
	t.assertStopInstance(c, m)
	assertInstanceId(c, m, nil)

	err = st.Close()
	c.Assert(err, IsNil)
}

func (t *LiveTests) checkUpgradeMachineAgent(c *C, m *state.Machine) {
	// First watch the machine agent's current tools to make sure
	// that it sets them appropriately.
	w := m.WatchAgentTools()

	var gotTools *state.Tools
	for tools := range w.Changes() {
		if tools.URL == "" {
			// Machine agent hasn't started yet.
			continue
		}
		gotTools = tools
		break
	}
	c.Assert(gotTools, NotNil, Commentf("tools watcher died: %v", w.Err()))
	c.Assert(gotTools.Binary, Equals, version.Current)

	c.Logf("putting testing version of juju tools")
	upgradeTools, err := environs.PutTools(t.Env.Storage(), "bumpversion")
	c.Assert(err, IsNil)

	// Check that the put version really is the version we expect.
	newVersion := version.Current
	newVersion.Patch++
	c.Assert(upgradeTools.Binary, Equals, newVersion)
	err = m.ProposeAgentTools(upgradeTools)

	c.Logf("waiting for upgrade")
	tools, ok := <-w.Changes()
	if !ok {
		c.Fatalf("watcher died: %v", w.Err())
	}
	c.Assert(tools, DeepEquals, upgradeTools)
	c.Logf("upgrade successful!")
}

var waitAgent = environs.AttemptStrategy{
	Total: 30 * time.Second,
	Delay: 1 * time.Second,
}

func (t *LiveTests) assertStartInstance(c *C, m *state.Machine) {
	// Wait for machine to get an instance id.
	for a := waitAgent.Start(); a.Next(); {
		instId, err := m.InstanceId()
		if _, ok := err.(*state.NotFoundError); ok {
			continue
		}
		c.Assert(err, IsNil)
		_, err = t.Env.Instances([]string{instId})
		c.Assert(err, IsNil)
		return
	}
	c.Fatalf("provisioner failed to start machine after %v", waitAgent.Total)
}

func (t *LiveTests) assertStopInstance(c *C, m *state.Machine) {
	// Wait for machine id to be cleared.
	for a := waitAgent.Start(); a.Next(); {
		if instId, err := m.InstanceId(); instId == "" {
			c.Assert(err, FitsTypeOf, &state.NotFoundError{})
			return
		}
	}
	c.Fatalf("provisioner failed to stop machine after %v", waitAgent.Total)
}

// assertInstanceId asserts that the machine has an instance id
// that matches that of the given instance. If the instance is nil,
// It asserts that the instance id is unset.
func assertInstanceId(c *C, m *state.Machine, inst environs.Instance) {
	// TODO(dfc) add machine.WatchConfig() to avoid having to poll.
	var instId, id string
	var err error
	if inst != nil {
		instId = inst.Id()
	}
	for a := waitAgent.Start(); a.Next(); {
		id, err = m.InstanceId()
		_, notset := err.(*state.NotFoundError)
		if notset {
			if inst == nil {
				return
			}
			continue
		}
		c.Assert(err, IsNil)
		break
	}
	c.Assert(err, IsNil)
	c.Assert(id, Equals, instId)
}

// TODO check that binary data works ok?
var contents = []byte("hello\n")
var contents2 = []byte("goodbye\n\n")

func (t *LiveTests) TestFile(c *C) {
	name := fmt.Sprint("testfile", time.Now().UnixNano())
	storage := t.Env.Storage()

	checkFileDoesNotExist(c, storage, name)
	checkPutFile(c, storage, name, contents)
	checkFileHasContents(c, storage, name, contents)
	checkPutFile(c, storage, name, contents2) // check that we can overwrite the file
	checkFileHasContents(c, storage, name, contents2)

	// check that the listed contents include the
	// expected name.
	names, err := storage.List("")
	c.Assert(err, IsNil)
	found := false
	for _, lname := range names {
		if lname == name {
			found = true
			break
		}
	}
	if !found {
		c.Errorf("file name %q not found in file list %q", name, names)
	}

	err = storage.Remove(name)
	c.Check(err, IsNil)
	checkFileDoesNotExist(c, storage, name)
	// removing a file that does not exist should not be an error.
	err = storage.Remove(name)
	c.Check(err, IsNil)
}

// Check that we can't start an instance running tools
// that correspond with no available platform.
func (t *LiveTests) TestStartInstanceOnUnknownPlatform(c *C) {
	vers := version.Current
	// Note that we want this test to function correctly in the
	// dummy environment, so to avoid enumerating all possible
	// platforms in the dummy provider, it treats only series and/or
	// architectures with the "unknown" prefix as invalid.
	vers.Series = "unknownseries"
	vers.Arch = "unknownarch"
	name := environs.ToolsStoragePath(vers)
	storage := t.Env.Storage()
	checkPutFile(c, storage, name, []byte("fake tools on invalid series"))
	defer storage.Remove(name)

	url, err := storage.URL(name)
	c.Assert(err, IsNil)
	tools := &state.Tools{
		Binary: vers,
		URL:    url,
	}

	inst, err := t.Env.StartInstance(4, InvalidStateInfo, tools)
	if inst != nil {
		err := t.Env.StopInstances([]environs.Instance{inst})
		c.Check(err, IsNil)
	}
	c.Assert(inst, IsNil)
	c.Assert(err, ErrorMatches, "cannot find image.*")
}
<commit_msg>environs/jujutest: use new PutTools interface<commit_after>package jujutest

import (
	"fmt"
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/juju"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/version"
	"time"
)

// TestStartStop is similar to Tests.TestStartStop except
// that it does not assume a pristine environment.
func (t *LiveTests) TestStartStop(c *C) {
	insts, err := t.Env.Instances(nil)
	c.Assert(err, IsNil)
	c.Check(insts, HasLen, 0)

	inst, err := t.Env.StartInstance(0, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst, NotNil)
	id0 := inst.Id()

	insts, err = t.Env.Instances([]string{id0, id0})
	c.Assert(err, IsNil)
	c.Assert(insts, HasLen, 2)
	c.Assert(insts[0].Id(), Equals, id0)
	c.Assert(insts[1].Id(), Equals, id0)

	insts, err = t.Env.AllInstances()
	c.Assert(err, IsNil)
	// differs from the check above because AllInstances returns
	// a set (without duplicates) containing only one instance.
	c.Assert(insts, HasLen, 1)
	c.Assert(insts[0].Id(), Equals, id0)

	dns, err := inst.WaitDNSName()
	c.Assert(err, IsNil)
	c.Assert(dns, Not(Equals), "")

	insts, err = t.Env.Instances([]string{id0, ""})
	c.Assert(err, Equals, environs.ErrPartialInstances)
	c.Assert(insts, HasLen, 2)
	c.Check(insts[0].Id(), Equals, id0)
	c.Check(insts[1], IsNil)

	err = t.Env.StopInstances([]environs.Instance{inst})
	c.Assert(err, IsNil)

	// Stopping may not be noticed at first due to eventual
	// consistency. Repeat a few times to ensure we get the error.
	for i := 0; i < 20; i++ {
		insts, err = t.Env.Instances([]string{id0})
		if err != nil {
			break
		}
		time.Sleep(0.25e9)
	}
	c.Assert(err, Equals, environs.ErrNoInstances)
	c.Assert(insts, HasLen, 0)
}

func (t *LiveTests) TestPorts(c *C) {
	inst1, err := t.Env.StartInstance(1, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst1, NotNil)
	defer t.Env.StopInstances([]environs.Instance{inst1})

	ports, err := inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)

	inst2, err := t.Env.StartInstance(2, InvalidStateInfo, nil)
	c.Assert(err, IsNil)
	c.Assert(inst2, NotNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)
	defer t.Env.StopInstances([]environs.Instance{inst2})

	// Open some ports and check they're there.
	err = inst1.OpenPorts(1, []state.Port{{"udp", 67}, {"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, HasLen, 0)

	// Check there's no crosstalk to another machine
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 89}, {"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}})
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})

	// Check that opening the same port again is ok.
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 45}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}})

	// Check that opening the same port again and another port is ok.
	err = inst2.OpenPorts(2, []state.Port{{"tcp", 45}, {"tcp", 99}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"tcp", 89}, {"tcp", 99}})

	// Check that we can close ports and that there's no crosstalk.
	err = inst2.ClosePorts(2, []state.Port{{"tcp", 45}, {"tcp", 99}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 89}})
	ports, err = inst1.Ports(1)
	c.Assert(err, IsNil)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 45}, {"udp", 67}})

	// Check that we can close multiple ports.
	err = inst1.ClosePorts(1, []state.Port{{"tcp", 45}, {"udp", 67}})
	c.Assert(err, IsNil)
	ports, err = inst1.Ports(1)
	c.Assert(ports, HasLen, 0)

	// Check that we can close ports that aren't there.
	err = inst2.ClosePorts(2, []state.Port{{"tcp", 111}, {"udp", 222}})
	c.Assert(err, IsNil)
	ports, err = inst2.Ports(2)
	c.Assert(ports, DeepEquals, []state.Port{{"tcp", 89}})
}

func (t *LiveTests) TestBootstrapMultiple(c *C) {
	t.BootstrapOnce(c)

	// Wait for a while to let eventual consistency catch up, hopefully.
	time.Sleep(t.ConsistencyDelay)
	err := t.Env.Bootstrap(false)
	c.Assert(err, ErrorMatches, "environment is already bootstrapped")

	c.Logf("destroy env")
	t.Destroy(c)

	// check that we can bootstrap after destroy
	t.BootstrapOnce(c)
}

func (t *LiveTests) TestBootstrapProvisioner(c *C) {
	if !t.CanOpenState || !t.HasProvisioner {
		c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner))
	}
	t.BootstrapOnce(c)

	// TODO(dfc) constructing a juju.Conn by hand is a code smell.
	conn, err := juju.NewConnFromAttrs(t.Env.Config().AllAttrs())
	c.Assert(err, IsNil)

	st, err := conn.State()
	c.Assert(err, IsNil)

	// Check that we can upgrade the machine agent on the bootstrap machine.
	m, err := st.Machine(0)
	c.Assert(err, IsNil)

	t.checkUpgradeMachineAgent(c, m)

	// place a new machine into the state
	m, err = st.AddMachine()
	c.Assert(err, IsNil)

	t.assertStartInstance(c, m)

	// now remove it
	c.Assert(st.RemoveMachine(m.Id()), IsNil)

	// watch the PA remove it
	t.assertStopInstance(c, m)
	assertInstanceId(c, m, nil)

	err = st.Close()
	c.Assert(err, IsNil)
}

func (t *LiveTests) checkUpgradeMachineAgent(c *C, m *state.Machine) {
	// First watch the machine agent's current tools to make sure
	// that it sets them appropriately.
	w := m.WatchAgentTools()

	var gotTools *state.Tools
	for tools := range w.Changes() {
		if tools.URL == "" {
			// Machine agent hasn't started yet.
			continue
		}
		gotTools = tools
		break
	}
	c.Assert(gotTools, NotNil, Commentf("tools watcher died: %v", w.Err()))
	c.Assert(gotTools.Binary, Equals, version.Current)

	c.Logf("putting testing version of juju tools")

	newVersion := version.Current
	newVersion.Patch++
	upgradeTools, err := environs.PutTools(t.Env.Storage(), &newVersion)
	c.Assert(err, IsNil)

	// Check that the put version really is the version we expect.
	c.Assert(upgradeTools.Binary, Equals, newVersion)
	err = m.ProposeAgentTools(upgradeTools)

	c.Logf("waiting for upgrade")
	tools, ok := <-w.Changes()
	if !ok {
		c.Fatalf("watcher died: %v", w.Err())
	}
	c.Assert(tools, DeepEquals, upgradeTools)
	c.Logf("upgrade successful!")
}

var waitAgent = environs.AttemptStrategy{
	Total: 30 * time.Second,
	Delay: 1 * time.Second,
}

func (t *LiveTests) assertStartInstance(c *C, m *state.Machine) {
	// Wait for machine to get an instance id.
	for a := waitAgent.Start(); a.Next(); {
		instId, err := m.InstanceId()
		if _, ok := err.(*state.NotFoundError); ok {
			continue
		}
		c.Assert(err, IsNil)
		_, err = t.Env.Instances([]string{instId})
		c.Assert(err, IsNil)
		return
	}
	c.Fatalf("provisioner failed to start machine after %v", waitAgent.Total)
}

func (t *LiveTests) assertStopInstance(c *C, m *state.Machine) {
	// Wait for machine id to be cleared.
	for a := waitAgent.Start(); a.Next(); {
		if instId, err := m.InstanceId(); instId == "" {
			c.Assert(err, FitsTypeOf, &state.NotFoundError{})
			return
		}
	}
	c.Fatalf("provisioner failed to stop machine after %v", waitAgent.Total)
}

// assertInstanceId asserts that the machine has an instance id
// that matches that of the given instance. If the instance is nil,
// It asserts that the instance id is unset.
func assertInstanceId(c *C, m *state.Machine, inst environs.Instance) {
	// TODO(dfc) add machine.WatchConfig() to avoid having to poll.
	var instId, id string
	var err error
	if inst != nil {
		instId = inst.Id()
	}
	for a := waitAgent.Start(); a.Next(); {
		id, err = m.InstanceId()
		_, notset := err.(*state.NotFoundError)
		if notset {
			if inst == nil {
				return
			}
			continue
		}
		c.Assert(err, IsNil)
		break
	}
	c.Assert(err, IsNil)
	c.Assert(id, Equals, instId)
}

// TODO check that binary data works ok?
var contents = []byte("hello\n")
var contents2 = []byte("goodbye\n\n")

func (t *LiveTests) TestFile(c *C) {
	name := fmt.Sprint("testfile", time.Now().UnixNano())
	storage := t.Env.Storage()

	checkFileDoesNotExist(c, storage, name)
	checkPutFile(c, storage, name, contents)
	checkFileHasContents(c, storage, name, contents)
	checkPutFile(c, storage, name, contents2) // check that we can overwrite the file
	checkFileHasContents(c, storage, name, contents2)

	// check that the listed contents include the
	// expected name.
	names, err := storage.List("")
	c.Assert(err, IsNil)
	found := false
	for _, lname := range names {
		if lname == name {
			found = true
			break
		}
	}
	if !found {
		c.Errorf("file name %q not found in file list %q", name, names)
	}

	err = storage.Remove(name)
	c.Check(err, IsNil)
	checkFileDoesNotExist(c, storage, name)
	// removing a file that does not exist should not be an error.
	err = storage.Remove(name)
	c.Check(err, IsNil)
}

// Check that we can't start an instance running tools
// that correspond with no available platform.
func (t *LiveTests) TestStartInstanceOnUnknownPlatform(c *C) {
	vers := version.Current
	// Note that we want this test to function correctly in the
	// dummy environment, so to avoid enumerating all possible
	// platforms in the dummy provider, it treats only series and/or
	// architectures with the "unknown" prefix as invalid.
	vers.Series = "unknownseries"
	vers.Arch = "unknownarch"
	name := environs.ToolsStoragePath(vers)
	storage := t.Env.Storage()
	checkPutFile(c, storage, name, []byte("fake tools on invalid series"))
	defer storage.Remove(name)

	url, err := storage.URL(name)
	c.Assert(err, IsNil)
	tools := &state.Tools{
		Binary: vers,
		URL:    url,
	}

	inst, err := t.Env.StartInstance(4, InvalidStateInfo, tools)
	if inst != nil {
		err := t.Env.StopInstances([]environs.Instance{inst})
		c.Check(err, IsNil)
	}
	c.Assert(inst, IsNil)
	c.Assert(err, ErrorMatches, "cannot find image.*")
}
<|endoftext|>


<commit_before>package local_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"testing"

	"launchpad.net/juju-core/environs/local"
)

func TestLocal(t *testing.T) {
	TestingT(t)
}

type backendSuite struct{}

var _ = Suite(&backendSuite{})

const environName = "test-environ"

var testSetMu sync.Mutex

// nextTestSet returns a new port number, listener and data directory.
func nextTestSet(c *C) (int, net.Listener, string) {
	testSetMu.Lock()
	defer testSetMu.Unlock()

	dataDir := c.MkDir()
	listener, err := local.Listen(dataDir, environName, "127.0.0.1", 0)
	c.Assert(err, IsNil)
	_, ports, err := net.SplitHostPort(listener.Addr().String())
	c.Assert(err, IsNil)
	port, err := strconv.Atoi(ports)
	c.Assert(err, IsNil)

	return port, listener, dataDir
}

type testCase struct {
	name    string
	content string
	found   []string
	status  int
}

var getTests = []testCase{
	{
		// Get existing file.
		name:    "foo",
		content: "this is file 'foo'",
	},
	{
		// Get existing file.
		name:    "bar",
		content: "this is file 'bar'",
	},
	{
		// Get existing file.
		name:    "baz",
		content: "this is file 'baz'",
	},
	{
		// Get existing file.
		name:    "yadda",
		content: "this is file 'yadda'",
	},
	{
		// Get existing file from nested directory.
		name:    "inner/fooin",
		content: "this is inner file 'fooin'",
	},
	{
		// Get existing file from nested directory.
		name:    "inner/barin",
		content: "this is inner file 'barin'",
	},
	{
		// Get non-existing file.
		name:   "dummy",
		status: 404,
	},
	{
		// Get non-existing file from nested directory.
		name:   "inner/dummy",
		status: 404,
	},
	{
		// Get with a relative path ".." based on the
		// root is passed without invoking the handler
		// function.
		name:   "../dummy",
		status: 404,
	},
	{
		// Get with a relative path ".." based on the
		// root is passed without invoking the handler
		// function.
		name:    "../foo",
		content: "this is file 'foo'",
	},
	{
		// Get on a directory returns a 404 as it is
		// not a file.
		name:   "inner",
		status: 404,
	},
}

func (s *backendSuite) TestGet(c *C) {
	// Test retrieving a file from a storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		resp, err := http.Get(url)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		defer resp.Body.Close()
		var buf bytes.Buffer
		_, err = buf.ReadFrom(resp.Body)
		c.Assert(err, IsNil)
		c.Assert(buf.String(), Equals, tc.content)
	}
	for _, tc := range getTests {
		check(tc)
	}
}

var listTests = []testCase{
	{
		// List with a full filename.
		name:  "foo",
		found: []string{"foo"},
	},
	{
		// List with a name matching two files.
		name:  "ba",
		found: []string{"bar", "baz"},
	},
	{
		// List the contents of a directory.
		name:  "inner/",
		found: []string{"inner/barin", "inner/bazin", "inner/fooin"},
	},
	{
		// List with a name matching two files in
		// a directory.
		name:  "inner/ba",
		found: []string{"inner/barin", "inner/bazin"},
	},
	{
		// List with no name also lists the contents of all
		// directories.
		name:  "",
		found: []string{"bar", "baz", "foo", "inner/barin", "inner/bazin", "inner/fooin", "yadda"},
	},
	{
		// List with a non-matching name returns an empty
		// body which is evaluated to a slice with an empty
		// string in the test (simplification).
		name:  "zzz",
		found: []string{""},
	},
	{
		// List with a relative path ".." based on the
		// root is passed without invoking the handler
		// function. So returns the contents of all
		// directories.
		name:  "../",
		found: []string{"bar", "baz", "foo", "inner/barin", "inner/bazin", "inner/fooin", "yadda"},
	},
}

func (s *backendSuite) TestList(c *C) {
	// Test listing file of a storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s*", portNo, tc.name)
		resp, err := http.Get(url)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		defer resp.Body.Close()
		var buf bytes.Buffer
		_, err = buf.ReadFrom(resp.Body)
		c.Assert(err, IsNil)
		names := strings.Split(buf.String(), "\n")
		c.Assert(names, DeepEquals, tc.found)
	}
	for _, tc := range listTests {
		check(tc)
	}
}

var putTests = []testCase{
	{
		// Put a file in the root directory.
		name:    "porterhouse",
		content: "this is the sent file 'porterhouse'",
	},
	{
		// Put a file with a relative path ".." is resolved
		// a redirect 301 by the Go HTTP daemon. The handler
		// isn't aware of it.
		name:   "../no-way",
		status: 301,
	},
	{
		// Put a file in a nested directory.
		name:    "deep/cambridge",
		content: "this is the sent file 'deep/cambridge'",
	},
}

func (s *backendSuite) TestPut(c *C) {
	// Test sending a file to the storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		req, err := http.NewRequest("PUT", url, bytes.NewBufferString(tc.content))
		c.Assert(err, IsNil)
		req.Header.Set("Content-Type", "application/octet-stream")
		resp, err := http.DefaultClient.Do(req)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		c.Assert(resp.StatusCode, Equals, 201)

		fp := filepath.Join(dataDir, environName, tc.name)
		b, err := ioutil.ReadFile(fp)
		c.Assert(err, IsNil)
		c.Assert(string(b), Equals, tc.content)
	}
	for _, tc := range putTests {
		check(tc)
	}
}

var removeTests = []testCase{
	{
		// Delete a file in the root directory.
		name:    "fox",
		content: "the quick brown fox jumps over the lazy dog",
	},
	{
		// Delete a file in a nested directory.
		name:    "quick/brown/fox",
		content: "the quick brown fox jumps over the lazy dog",
	},
	{
		// Delete a non-existing file leads to no error.
		name: "dog",
	},
	{
		// Delete a file with a relative path ".." is resolved
		// a redirect 301 by the Go HTTP daemon. The handler
		// doesn't get aware of it.
		name:   "../something",
		status: 301,
	},
}

func (s *backendSuite) TestRemove(c *C) {
	// Test removing a file in the storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		fp := filepath.Join(dataDir, environName, tc.name)
		dir, _ := filepath.Split(fp)
		err := os.MkdirAll(dir, 0777)
		c.Assert(err, IsNil)
		err = ioutil.WriteFile(fp, []byte(tc.content), 0644)
		c.Assert(err, IsNil)

		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		req, err := http.NewRequest("DELETE", url, nil)
		c.Assert(err, IsNil)
		resp, err := http.DefaultClient.Do(req)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		c.Assert(resp.StatusCode, Equals, 200)

		_, err = os.Stat(fp)
		c.Assert(err, ErrorMatches, ".*: no such file or directory")
	}
	for _, tc := range removeTests {
		check(tc)
	}
}

func createTestData(c *C, dataDir string) {
	writeData := func(dir, name, data string) {
		fn := filepath.Join(dir, name)
		err := ioutil.WriteFile(fn, []byte(data), 0644)
		c.Assert(err, IsNil)
	}

	dir := filepath.Join(dataDir, environName)

	writeData(dir, "foo", "this is file 'foo'")
	writeData(dir, "bar", "this is file 'bar'")
	writeData(dir, "baz", "this is file 'baz'")
	writeData(dir, "yadda", "this is file 'yadda'")

	dir = filepath.Join(dataDir, environName, "inner")
	err := os.MkdirAll(dir, 0777)
	c.Assert(err, IsNil)

	writeData(dir, "fooin", "this is inner file 'fooin'")
	writeData(dir, "barin", "this is inner file 'barin'")
	writeData(dir, "bazin", "this is inner file 'bazin'")
}
<commit_msg>environs/local: small port gathering change after review<commit_after>package local_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"testing"

	"launchpad.net/juju-core/environs/local"
)

func TestLocal(t *testing.T) {
	TestingT(t)
}

type backendSuite struct{}

var _ = Suite(&backendSuite{})

const environName = "test-environ"

var testSetMu sync.Mutex

// nextTestSet returns a new port number, listener and data directory.
func nextTestSet(c *C) (int, net.Listener, string) {
	testSetMu.Lock()
	defer testSetMu.Unlock()

	dataDir := c.MkDir()
	listener, err := local.Listen(dataDir, environName, "127.0.0.1", 0)
	c.Assert(err, IsNil)
	port := listener.Addr().(*net.TCPAddr).Port

	return port, listener, dataDir
}

type testCase struct {
	name    string
	content string
	found   []string
	status  int
}

var getTests = []testCase{
	{
		// Get existing file.
		name:    "foo",
		content: "this is file 'foo'",
	},
	{
		// Get existing file.
		name:    "bar",
		content: "this is file 'bar'",
	},
	{
		// Get existing file.
		name:    "baz",
		content: "this is file 'baz'",
	},
	{
		// Get existing file.
		name:    "yadda",
		content: "this is file 'yadda'",
	},
	{
		// Get existing file from nested directory.
		name:    "inner/fooin",
		content: "this is inner file 'fooin'",
	},
	{
		// Get existing file from nested directory.
		name:    "inner/barin",
		content: "this is inner file 'barin'",
	},
	{
		// Get non-existing file.
		name:   "dummy",
		status: 404,
	},
	{
		// Get non-existing file from nested directory.
		name:   "inner/dummy",
		status: 404,
	},
	{
		// Get with a relative path ".." based on the
		// root is passed without invoking the handler
		// function.
		name:   "../dummy",
		status: 404,
	},
	{
		// Get with a relative path ".." based on the
		// root is passed without invoking the handler
		// function.
		name:    "../foo",
		content: "this is file 'foo'",
	},
	{
		// Get on a directory returns a 404 as it is
		// not a file.
		name:   "inner",
		status: 404,
	},
}

func (s *backendSuite) TestGet(c *C) {
	// Test retrieving a file from a storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		resp, err := http.Get(url)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		defer resp.Body.Close()
		var buf bytes.Buffer
		_, err = buf.ReadFrom(resp.Body)
		c.Assert(err, IsNil)
		c.Assert(buf.String(), Equals, tc.content)
	}
	for _, tc := range getTests {
		check(tc)
	}
}

var listTests = []testCase{
	{
		// List with a full filename.
		name:  "foo",
		found: []string{"foo"},
	},
	{
		// List with a name matching two files.
		name:  "ba",
		found: []string{"bar", "baz"},
	},
	{
		// List the contents of a directory.
		name:  "inner/",
		found: []string{"inner/barin", "inner/bazin", "inner/fooin"},
	},
	{
		// List with a name matching two files in
		// a directory.
		name:  "inner/ba",
		found: []string{"inner/barin", "inner/bazin"},
	},
	{
		// List with no name also lists the contents of all
		// directories.
		name:  "",
		found: []string{"bar", "baz", "foo", "inner/barin", "inner/bazin", "inner/fooin", "yadda"},
	},
	{
		// List with a non-matching name returns an empty
		// body which is evaluated to a slice with an empty
		// string in the test (simplification).
		name:  "zzz",
		found: []string{""},
	},
	{
		// List with a relative path ".." based on the
		// root is passed without invoking the handler
		// function. So returns the contents of all
		// directories.
		name:  "../",
		found: []string{"bar", "baz", "foo", "inner/barin", "inner/bazin", "inner/fooin", "yadda"},
	},
}

func (s *backendSuite) TestList(c *C) {
	// Test listing file of a storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s*", portNo, tc.name)
		resp, err := http.Get(url)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		defer resp.Body.Close()
		var buf bytes.Buffer
		_, err = buf.ReadFrom(resp.Body)
		c.Assert(err, IsNil)
		names := strings.Split(buf.String(), "\n")
		c.Assert(names, DeepEquals, tc.found)
	}
	for _, tc := range listTests {
		check(tc)
	}
}

var putTests = []testCase{
	{
		// Put a file in the root directory.
		name:    "porterhouse",
		content: "this is the sent file 'porterhouse'",
	},
	{
		// Put a file with a relative path ".." is resolved
		// a redirect 301 by the Go HTTP daemon. The handler
		// isn't aware of it.
		name:   "../no-way",
		status: 301,
	},
	{
		// Put a file in a nested directory.
		name:    "deep/cambridge",
		content: "this is the sent file 'deep/cambridge'",
	},
}

func (s *backendSuite) TestPut(c *C) {
	// Test sending a file to the storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		req, err := http.NewRequest("PUT", url, bytes.NewBufferString(tc.content))
		c.Assert(err, IsNil)
		req.Header.Set("Content-Type", "application/octet-stream")
		resp, err := http.DefaultClient.Do(req)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		c.Assert(resp.StatusCode, Equals, 201)

		fp := filepath.Join(dataDir, environName, tc.name)
		b, err := ioutil.ReadFile(fp)
		c.Assert(err, IsNil)
		c.Assert(string(b), Equals, tc.content)
	}
	for _, tc := range putTests {
		check(tc)
	}
}

var removeTests = []testCase{
	{
		// Delete a file in the root directory.
		name:    "fox",
		content: "the quick brown fox jumps over the lazy dog",
	},
	{
		// Delete a file in a nested directory.
		name:    "quick/brown/fox",
		content: "the quick brown fox jumps over the lazy dog",
	},
	{
		// Delete a non-existing file leads to no error.
		name: "dog",
	},
	{
		// Delete a file with a relative path ".." is resolved
		// a redirect 301 by the Go HTTP daemon. The handler
		// doesn't get aware of it.
		name:   "../something",
		status: 301,
	},
}

func (s *backendSuite) TestRemove(c *C) {
	// Test removing a file in the storage.
	portNo, listener, dataDir := nextTestSet(c)
	defer listener.Close()

	createTestData(c, dataDir)

	check := func(tc testCase) {
		fp := filepath.Join(dataDir, environName, tc.name)
		dir, _ := filepath.Split(fp)
		err := os.MkdirAll(dir, 0777)
		c.Assert(err, IsNil)
		err = ioutil.WriteFile(fp, []byte(tc.content), 0644)
		c.Assert(err, IsNil)

		url := fmt.Sprintf("http://localhost:%d/%s", portNo, tc.name)
		req, err := http.NewRequest("DELETE", url, nil)
		c.Assert(err, IsNil)
		resp, err := http.DefaultClient.Do(req)
		c.Assert(err, IsNil)
		if tc.status != 0 {
			c.Assert(resp.StatusCode, Equals, tc.status)
			return
		}
		c.Assert(resp.StatusCode, Equals, 200)

		_, err = os.Stat(fp)
		c.Assert(err, ErrorMatches, ".*: no such file or directory")
	}
	for _, tc := range removeTests {
		check(tc)
	}
}

func createTestData(c *C, dataDir string) {
	writeData := func(dir, name, data string) {
		fn := filepath.Join(dir, name)
		err := ioutil.WriteFile(fn, []byte(data), 0644)
		c.Assert(err, IsNil)
	}

	dir := filepath.Join(dataDir, environName)

	writeData(dir, "foo", "this is file 'foo'")
	writeData(dir, "bar", "this is file 'bar'")
	writeData(dir, "baz", "this is file 'baz'")
	writeData(dir, "yadda", "this is file 'yadda'")

	dir = filepath.Join(dataDir, environName, "inner")
	err := os.MkdirAll(dir, 0777)
	c.Assert(err, IsNil)

	writeData(dir, "fooin", "this is inner file 'fooin'")
	writeData(dir, "barin", "this is inner file 'barin'")
	writeData(dir, "bazin", "this is inner file 'bazin'")
}
<|endoftext|>