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

package uniter_test

import (
	"github.com/juju/errors"
	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/api/base/testing"
	"github.com/juju/juju/api/uniter"
	"github.com/juju/juju/apiserver/params"
	coretesting "github.com/juju/juju/testing"
)

var _ = gc.Suite(&storageSuite{})

type storageSuite struct {
	coretesting.BaseSuite
}

func (s *storageSuite) TestStorageAttachments(c *gc.C) {
	storageAttachments := []params.StorageAttachment{{
		StorageTag: "storage-whatever-0",
		OwnerTag:   "service-mysql",
		UnitTag:    "unit-mysql-0",
		Kind:       params.StorageKindBlock,
		Location:   "/dev/sda",
	}}

	var called bool
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		c.Check(objType, gc.Equals, "Uniter")
		c.Check(version, gc.Equals, 2)
		c.Check(id, gc.Equals, "")
		c.Check(request, gc.Equals, "StorageAttachments")
		c.Check(arg, gc.DeepEquals, params.Entities{
			Entities: []params.Entity{{Tag: "unit-mysql-0"}},
		})
		c.Assert(result, gc.FitsTypeOf, &params.StorageAttachmentsResults{})
		*(result.(*params.StorageAttachmentsResults)) = params.StorageAttachmentsResults{
			Results: []params.StorageAttachmentsResult{{
				Result: storageAttachments,
			}},
		}
		called = true
		return nil
	})

	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	attachments, err := st.StorageAttachments(names.NewUnitTag("mysql/0"))
	c.Check(err, jc.ErrorIsNil)
	c.Check(called, jc.IsTrue)
	c.Assert(attachments, gc.DeepEquals, storageAttachments)
}

func (s *storageSuite) TestStorageAttachmentResultCountMismatch(c *gc.C) {
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		*(result.(*params.StorageAttachmentsResults)) = params.StorageAttachmentsResults{
			[]params.StorageAttachmentsResult{{}, {}},
		}
		return nil
	})
	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	c.Assert(func() { st.StorageAttachments(names.NewUnitTag("mysql/0")) }, gc.PanicMatches, "expected 1 result, got 2")
}

func (s *storageSuite) TestAPIErrors(c *gc.C) {
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		return errors.New("bad")
	})
	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	_, err := st.StorageAttachments(names.NewUnitTag("mysql/0"))
	c.Check(err, gc.ErrorMatches, "bad")
}
<commit_msg>api/uniter: add test for WatchStorageAttachments<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package uniter_test

import (
	"github.com/juju/errors"
	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/api/base/testing"
	"github.com/juju/juju/api/uniter"
	"github.com/juju/juju/apiserver/params"
	coretesting "github.com/juju/juju/testing"
)

var _ = gc.Suite(&storageSuite{})

type storageSuite struct {
	coretesting.BaseSuite
}

func (s *storageSuite) TestStorageAttachments(c *gc.C) {
	storageAttachments := []params.StorageAttachment{{
		StorageTag: "storage-whatever-0",
		OwnerTag:   "service-mysql",
		UnitTag:    "unit-mysql-0",
		Kind:       params.StorageKindBlock,
		Location:   "/dev/sda",
	}}

	var called bool
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		c.Check(objType, gc.Equals, "Uniter")
		c.Check(version, gc.Equals, 2)
		c.Check(id, gc.Equals, "")
		c.Check(request, gc.Equals, "StorageAttachments")
		c.Check(arg, gc.DeepEquals, params.Entities{
			Entities: []params.Entity{{Tag: "unit-mysql-0"}},
		})
		c.Assert(result, gc.FitsTypeOf, &params.StorageAttachmentsResults{})
		*(result.(*params.StorageAttachmentsResults)) = params.StorageAttachmentsResults{
			Results: []params.StorageAttachmentsResult{{
				Result: storageAttachments,
			}},
		}
		called = true
		return nil
	})

	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	attachments, err := st.StorageAttachments(names.NewUnitTag("mysql/0"))
	c.Check(err, jc.ErrorIsNil)
	c.Check(called, jc.IsTrue)
	c.Assert(attachments, gc.DeepEquals, storageAttachments)
}

func (s *storageSuite) TestStorageAttachmentResultCountMismatch(c *gc.C) {
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		*(result.(*params.StorageAttachmentsResults)) = params.StorageAttachmentsResults{
			[]params.StorageAttachmentsResult{{}, {}},
		}
		return nil
	})
	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	c.Assert(func() { st.StorageAttachments(names.NewUnitTag("mysql/0")) }, gc.PanicMatches, "expected 1 result, got 2")
}

func (s *storageSuite) TestAPIErrors(c *gc.C) {
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		return errors.New("bad")
	})
	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	_, err := st.StorageAttachments(names.NewUnitTag("mysql/0"))
	c.Check(err, gc.ErrorMatches, "bad")
}

func (s *storageSuite) TestWatchStorageAttachments(c *gc.C) {
	var called bool
	apiCaller := testing.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
		c.Check(objType, gc.Equals, "Uniter")
		c.Check(version, gc.Equals, 2)
		c.Check(id, gc.Equals, "")
		c.Check(request, gc.Equals, "WatchStorageAttachments")
		c.Check(arg, gc.DeepEquals, params.Entities{
			Entities: []params.Entity{{Tag: "unit-mysql-0"}},
		})
		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResults{})
		*(result.(*params.StringsWatchResults)) = params.StringsWatchResults{
			Results: []params.StringsWatchResult{{
				Error: &params.Error{Message: "FAIL"},
			}},
		}
		called = true
		return nil
	})

	st := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
	_, err := st.WatchStorageAttachments(names.NewUnitTag("mysql/0"))
	c.Check(err, gc.ErrorMatches, "FAIL")
	c.Check(called, jc.IsTrue)
}
<|endoftext|>


<commit_before>// Copyright 2022 NetApp, Inc. All Rights Reserved.

package controllerAPI

import (
	"io/ioutil"
	"os"
	"testing"

	log "github.com/sirupsen/logrus"
)

func TestMain(m *testing.M) {
	// Disable any standard log output
	log.SetOutput(ioutil.Discard)
	os.Exit(m.Run())
}
<commit_msg>CSI controller API Rest unit test changes<commit_after>// Copyright 2022 NetApp, Inc. All Rights Reserved.

package controllerAPI

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"strings"
	"testing"

	log "github.com/sirupsen/logrus"
	"github.com/stretchr/testify/assert"

	"github.com/netapp/trident/config"
	"github.com/netapp/trident/utils"
)

var (
	ctx              = context.Background()
	tridentNodeTable = make(map[string]string)
	chap             = GetCHAPResponse{}
)

func TestMain(m *testing.M) {
	log.SetOutput(ioutil.Discard)
	os.Exit(m.Run())
}

func getHttpServer(url string, mockFunction func(w http.ResponseWriter, r *http.Request)) *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == url {
			mockFunction(w, r)
		} else {
			sc := http.StatusBadRequest
			createResponse(w, "", sc)
		}
	}))
}

func mockCreateNode(w http.ResponseWriter, r *http.Request) {
	s := strings.TrimSpace(r.URL.Path)
	str := strings.Split(s, "/")
	name := str[4]
	sc := http.StatusCreated
	if name == "" {
		sc = http.StatusBadRequest
	}
	if name == "invalidResponse" {
		msg := "invalidResponse"
		createResponse(w, msg, sc)
	} else {
		indexNumber := len(tridentNodeTable) + 1
		nodeId := strconv.Itoa(indexNumber)
		tridentNodeTable[nodeId] = name
		msg := ListNodesResponse{}
		nodes := append(msg.Nodes, name)
		msg.Nodes = nodes
		createResponse(w, msg, sc)
	}
}

func mockGetNodeResponse(w http.ResponseWriter, r *http.Request) {
	ids, ok := r.URL.Query()["id"]
	sc := http.StatusOK

	msg := ListNodesResponse{}
	if !ok || len(ids[0]) == 0 {
		values := make([]string, 0, len(tridentNodeTable))
		for _, v := range tridentNodeTable {
			updatedNodes := append(msg.Nodes, v)
			msg.Nodes = updatedNodes
			values = append(values, v)
		}
	} else {
		for i := 0; i < len(ids); i++ {
			updatedNodes := append(msg.Nodes, tridentNodeTable[ids[i]])
			msg.Nodes = updatedNodes
		}
	}

	createResponse(w, msg, sc)
}

func mockResourceNotFound(w http.ResponseWriter, r *http.Request) {
	sc := http.StatusNotFound
	createResponse(w, "", sc)
}

func mockDeleteNode(w http.ResponseWriter, r *http.Request) {
	str := strings.Split(strings.TrimSpace(r.URL.Path), "/")
	name := str[4]

	if name == "StatusUnprocessableEntity" {
		createResponse(w, "", http.StatusUnprocessableEntity)
	} else if name == "StatusNotFound" {
		createResponse(w, "", http.StatusNotFound)
	} else if name == "StatusGone" {
		createResponse(w, "", http.StatusGone)
	} else if name == "StatusBadRequest" {
		createResponse(w, "", http.StatusBadRequest)
	} else {
		for k, v := range tridentNodeTable {
			if v == name {
				delete(tridentNodeTable, k)
				msg := ListNodesResponse{}
				x := append(msg.Nodes, name)
				msg.Nodes = x
				createResponse(w, msg, http.StatusOK)
			}
		}
	}
}

func createResponse(w http.ResponseWriter, msg any, sc int) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(sc)
	json.NewEncoder(w).Encode(msg)
}

func mockGetChap(w http.ResponseWriter, r *http.Request) {
	str := strings.Split(r.URL.Path, "/")
	sc := http.StatusCreated

	if str[5] == "node1" {
		chapInfo := utils.IscsiChapInfo{}
		chapInfo.UseCHAP = true
		chap.CHAP = &chapInfo
		sc = http.StatusOK
		createResponse(w, chap, sc)
	} else if str[5] == "invalidResponse" {
		sc = http.StatusBadRequest
		msg := "invalidResponse"
		createResponse(w, msg, sc)
	} else {
		msg := GetCHAPResponse{}
		createResponse(w, msg, sc)
	}
}

func TestInvokeAPI(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	s := "{\"id\":\" uuid\"}"
	ctx = context.Background()
	server := getHttpServer(config.NodeURL, mockGetNodeResponse)
	controllerRestClient.url = server.URL
	response, _, err := controllerRestClient.InvokeAPI(ctx, []byte(s), "GET", "/trident/v1/node?id=1", true, true)
	server.Close()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, response.StatusCode)
}

func TestInvokeAPIResponseResourceNotFound(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	s := "{\"id\":\" uuid\"}"
	ctx = context.Background()
	server := getHttpServer("/trident/v1/notFound", mockResourceNotFound)
	controllerRestClient.url = server.URL
	response, _, err := controllerRestClient.InvokeAPI(ctx, []byte(s), "GET", "/trident/v1/notFound", true, true)
	server.Close()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusNotFound, response.StatusCode)
}

func TestCreateNode(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	tridentNodeTable["1"] = "tridentNode1"
	tridentNodeTable["2"] = "tridentNode2"

	tridentNodeTableLength := len(tridentNodeTable)

	ctx = context.Background()

	tests := []struct {
		nodeName        string
		mockFunction    func(w http.ResponseWriter, r *http.Request)
		isErrorExpected bool
	}{
		{nodeName: "VSM1", mockFunction: mockCreateNode, isErrorExpected: false},
		{nodeName: "", mockFunction: mockCreateNode, isErrorExpected: true},
		{nodeName: "invalidResponse", mockFunction: mockCreateNode, isErrorExpected: true},
	}

	for i, test := range tests {
		node := utils.Node{}
		node.Name = test.nodeName
		t.Run(fmt.Sprintf("CreateNode: %d", i), func(t *testing.T) {
			server := getHttpServer(config.NodeURL+"/"+test.nodeName, test.mockFunction)
			controllerRestClient.url = server.URL
			_, result := controllerRestClient.CreateNode(ctx, &node)
			if !test.isErrorExpected {
				assert.NoError(t, result)
				assert.Equal(t, tridentNodeTableLength+1, len(tridentNodeTable))
			} else {
				assert.Error(t, result)
			}
			server.Close()
		})
	}
}

func TestCreateNodeFailedInvokeAPICall(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	ctx = context.Background()
	controllerRestClient.url = ""
	controllerRestClient.httpClient = *http.DefaultClient
	node := utils.Node{}
	node.Name = "VSM1"
	_, err := controllerRestClient.CreateNode(ctx, &node)

	assert.Error(t, err)
}

func TestGetNode(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	ctx = context.Background()
	tests := []struct {
		mockFunction    func(w http.ResponseWriter, r *http.Request)
		isErrorExpected bool
	}{
		{mockFunction: mockGetNodeResponse, isErrorExpected: false},
		{mockFunction: mockResourceNotFound, isErrorExpected: true},
	}
	for i, test := range tests {
		t.Run(fmt.Sprintf("GetNode: %d", i), func(t *testing.T) {
			server := getHttpServer(config.NodeURL, test.mockFunction)
			controllerRestClient.url = server.URL
			response, result := controllerRestClient.GetNodes(ctx)
			if !test.isErrorExpected {
				assert.NoError(t, result)
				assert.Equal(t, len(response), len(tridentNodeTable))
			} else {
				assert.Error(t, result)
			}
			server.Close()
		})
	}
}

func TestGetNodesInvokeAPIError(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	ctx = context.Background()
	controllerRestClient.url = ""

	_, err := controllerRestClient.GetNodes(ctx)
	assert.Error(t, err)
}

func TestDeleteNode(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	tridentNodeTable["1"] = "tridentNode1"
	tridentNodeTable["2"] = "tridentNode2"
	ctx = context.Background()
	tridentNodeTableLength := len(tridentNodeTable)

	tests := []struct {
		nodeName        string
		mockFunction    func(w http.ResponseWriter, r *http.Request)
		isErrorExpected bool
	}{
		{nodeName: "tridentNode1", mockFunction: mockDeleteNode, isErrorExpected: false},
		{nodeName: "StatusUnprocessableEntity", mockFunction: mockDeleteNode, isErrorExpected: false},
		{nodeName: "StatusNotFound", mockFunction: mockDeleteNode, isErrorExpected: false},
		{nodeName: "StatusGone", mockFunction: mockDeleteNode, isErrorExpected: false},
		{nodeName: "StatusBadRequest", mockFunction: mockDeleteNode, isErrorExpected: true},
	}

	for i, test := range tests {
		t.Run(fmt.Sprintf("GetNode: %d", i), func(t *testing.T) {
			server := getHttpServer(config.NodeURL+"/"+test.nodeName, test.mockFunction)
			controllerRestClient.url = server.URL
			result := controllerRestClient.DeleteNode(ctx, test.nodeName)
			if !test.isErrorExpected {
				assert.NoError(t, result)
				assert.Equal(t, tridentNodeTableLength-1, len(tridentNodeTable))
			} else {
				assert.Error(t, result)
			}
			server.Close()
		})
	}
}

func TestDeleteNodeInvokeAPICallFailed(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	controllerRestClient.url = ""
	err := controllerRestClient.DeleteNode(ctx, "VSM1")
	assert.Error(t, err)
}

func TestGetChap(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	ctx = context.Background()

	tests := []struct {
		nodeName        string
		volumeName      string
		mockFunction    func(w http.ResponseWriter, r *http.Request)
		isErrorExpected bool
	}{
		{nodeName: "node1", volumeName: "volume", mockFunction: mockGetChap, isErrorExpected: false},
		{nodeName: "invalidResponse", volumeName: "volume", mockFunction: mockGetChap, isErrorExpected: true},
		{nodeName: "nodeNotPresent", volumeName: "volume", mockFunction: mockGetChap, isErrorExpected: true},
	}

	for i, test := range tests {
		t.Run(fmt.Sprintf("GetNode: %d", i), func(t *testing.T) {
			server := getHttpServer(config.ChapURL+"/"+test.volumeName+"/"+test.nodeName, test.mockFunction)
			controllerRestClient.url = server.URL
			response, result := controllerRestClient.GetChap(ctx, test.volumeName, test.nodeName)
			if !test.isErrorExpected {
				assert.NoError(t, result)
				assert.Equal(t, chap.CHAP, response)
			} else {
				assert.Error(t, result)
			}
			server.Close()
		})
	}
}

func TestGetChapInvokeAPICallFailed(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	controllerRestClient.url = ""
	_, err := controllerRestClient.GetChap(ctx, "volume", "xyz1")
	assert.Error(t, err)
}

func TestCreateTLSRestClient(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	certFile := os.Getenv("CERT")
	keyFile := os.Getenv("KEY")

	fileHandler, e := os.Create("data.txt")
	assert.NoError(t, e)

	server := getHttpServer("/trident/v1/chap/volume/xyz", mockGetChap)
	controllerRestClient.url = server.URL
	_, err := CreateTLSRestClient(controllerRestClient.url, fileHandler.Name(), certFile, keyFile)
	server.Close()
	assert.NoError(t, err)
	fileHandler.Close()
	e = os.Remove("data.txt")
	assert.NoError(t, e)
}

func TestCreateTLSRestClientEmptyFile(t *testing.T) {
	controllerRestClient := ControllerRestClient{}
	certFile := os.Getenv("CERT")
	keyFile := os.Getenv("KEY")

	server := getHttpServer("/trident/v1/chap/volume/xyz", mockGetChap)
	controllerRestClient.url = server.URL
	_, err := CreateTLSRestClient(controllerRestClient.url, "", certFile, keyFile)
	server.Close()
	assert.NoError(t, err)
}
<|endoftext|>


<commit_before>// Copyright 2010  The "goconfig" Authors
//
// Use of this source code is governed by the BSD-2 Clause license
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package config

// AddSection adds a new section to the configuration.
//
// If the section is nil then uses the section by default which it's already
// created.
//
// It returns true if the new section was inserted, and false if the section
// already existed.
func (self *Config) AddSection(section string) bool {
	// _DEFAULT_SECTION
	if section == "" {
		return false
	}

	if _, ok := self.data[section]; ok {
		return false
	}

	self.data[section] = make(map[string]*tValue)

	// Section order
	self.idSection[section] = self.lastIdSection
	self.lastIdSection++

	return true
}

// RemoveSection removes a section from the configuration.
// It returns true if the section was removed, and false if section did not exist.
func (self *Config) RemoveSection(section string) bool {
	_, ok := self.data[section]

	// Default section cannot be removed.
	if !ok || section == _DEFAULT_SECTION {
		return false
	}

	for o, _ := range self.data[section] {
		self.data[section][o] = nil, false // *value
	}
	self.data[section] = nil, false

	self.lastIdOption[section] = 0, false
	self.idSection[section] = 0, false

	return true
}

// HasSection checks if the configuration has the given section.
// (The default section always exists.)
func (self *Config) HasSection(section string) bool {
	_, ok := self.data[section]

	return ok
}

// Sections returns the list of sections in the configuration.
// (The default section always exists.)
func (self *Config) Sections() (sections []string) {
	sections = make([]string, len(self.idSection))
	pos := 0 // Position in sections

	for i := 0; i < self.lastIdSection; i++ {
		for section, id := range self.idSection {
			if id == i {
				sections[pos] = section
				pos++
			}
		}
	}

	return sections
}
<commit_msg>Use new sintaxis to delete in map<commit_after>// Copyright 2010  The "goconfig" Authors
//
// Use of this source code is governed by the BSD-2 Clause license
// that can be found in the LICENSE file.
//
// This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for more details.

package config

// AddSection adds a new section to the configuration.
//
// If the section is nil then uses the section by default which it's already
// created.
//
// It returns true if the new section was inserted, and false if the section
// already existed.
func (self *Config) AddSection(section string) bool {
	// _DEFAULT_SECTION
	if section == "" {
		return false
	}

	if _, ok := self.data[section]; ok {
		return false
	}

	self.data[section] = make(map[string]*tValue)

	// Section order
	self.idSection[section] = self.lastIdSection
	self.lastIdSection++

	return true
}

// RemoveSection removes a section from the configuration.
// It returns true if the section was removed, and false if section did not exist.
func (self *Config) RemoveSection(section string) bool {
	_, ok := self.data[section]

	// Default section cannot be removed.
	if !ok || section == _DEFAULT_SECTION {
		return false
	}

	for o, _ := range self.data[section] {
		self.data[section][o] = nil, false // *value
	}
	self.data[section] = nil, false

	delete(self.lastIdOption, section)
	delete(self.idSection, section)

	return true
}

// HasSection checks if the configuration has the given section.
// (The default section always exists.)
func (self *Config) HasSection(section string) bool {
	_, ok := self.data[section]

	return ok
}

// Sections returns the list of sections in the configuration.
// (The default section always exists.)
func (self *Config) Sections() (sections []string) {
	sections = make([]string, len(self.idSection))
	pos := 0 // Position in sections

	for i := 0; i < self.lastIdSection; i++ {
		for section, id := range self.idSection {
			if id == i {
				sections[pos] = section
				pos++
			}
		}
	}

	return sections
}
<|endoftext|>


<commit_before>package functionHandlers

import (
	. "github.com/apoydence/hydra/types"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("FunctionInvoker", func() {

	Context("when given multiple functions", func() {
		fakeSetupChan := make(chan SetupFunction)
		fakeSetupChanResult := make(chan bool)

		var (
			fakeSetupBuilder SetupFunctionBuilder
			fakeSetup        SetupFunction
			functionInvoker	 FunctionInvoker
		)

		fakeSetupComparer := func(s SetupFunction) bool {
			fakeSetupChan <- s.(SetupFunction)
			return <-fakeSetupChanResult
		}

		BeforeEach(func() {

			functionInvoker = NewFunctionInvoker()
			fakeSetupBuilder = func(name string, f func(SetupFunction), c chan FunctionInfo) SetupFunction {
				return fakeSetup
			}
			fakeSetup = &fakeSetupFunction{}

			go func() {
				for sf := range fakeSetupChan {
					fakeSetupChanResult <- sf == fakeSetup
				}
			}()
		})

		It("invokes each function once initially", func(done Done) {
			defer close(done)

			countChan := make(chan interface{})
			fake := func(sf SetupFunction) {
				countChan <- nil
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
			for i := 0; i < 3; i++ {
				<-countChan
			}

			Expect(tryRead(countChan)).ToNot(BeTrue())
		}, 1)

		It("invokes each function on their own go routine", func(done Done) {
			defer close(done)
			fake := func(sf SetupFunction) {
				x := make(chan struct{})
				<-x
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
		}, 1)

		It("passes the SetupFunction to each function", func(done Done) {
			defer close(done)

			fake := func(sf SetupFunction) {
				defer GinkgoRecover()
				Expect(fakeSetupComparer(sf)).To(Equal(true))
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
		}, 1)

		It("returns the same channel (non-nil) as the functions receive", func(done Done) {
			defer close(done)
			resultChan := make(chan chan FunctionInfo, 1)
			fsb := func(name string, f func(SetupFunction), c chan FunctionInfo) SetupFunction {
				resultChan <- c
				return fakeSetup
			}
			fake := func(sf SetupFunction) {}

			result := functionInvoker(fsb, fake)
			c := <-resultChan
			Expect(c).ToNot(BeNil())
			Expect(c).To(BeEquivalentTo(result))
		}, 1)
	})
})

func tryRead(c chan interface{}) bool {
	select {
	case <-c:
		return true
	default:
		return false
	}
}

type fakeSetupFunction struct{
}

func (f *fakeSetupFunction) AsProducer(instances int) WriteOnlyChannel{
	panic("Not intended to be called")
}

func (f *fakeSetupFunction) AsFilter(parent string, instances int) (ReadOnlyChannel, WriteOnlyChannel){
	panic("Not intended to be called")
}

func (f *fakeSetupFunction) AsConsumer(parent string, instances int) ReadOnlyChannel{
	panic("Not intended to be called")
}
<commit_msg>Fixes data race in test.<commit_after>package functionHandlers

import (
	. "github.com/apoydence/hydra/types"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("FunctionInvoker", func() {

	Context("when given multiple functions", func() {
		fakeSetupChan := make(chan SetupFunction)
		fakeSetupChanResult := make(chan bool)

		var (
			fakeSetupBuilder SetupFunctionBuilder
			fakeSetup        SetupFunction
			functionInvoker	 FunctionInvoker
		)

		fakeSetupComparer := func(s SetupFunction) bool {
			fakeSetupChan <- s.(SetupFunction)
			return <-fakeSetupChanResult
		}

		BeforeEach(func() {

			functionInvoker = NewFunctionInvoker()
			fakeSetupBuilder = func(name string, f func(SetupFunction), c chan FunctionInfo) SetupFunction {
				return fakeSetup
			}
			fakeSetup = &fakeSetupFunction{}

			go func(fakeSetup SetupFunction) {
				for sf := range fakeSetupChan {
					fakeSetupChanResult <- sf == fakeSetup
				}
			}(fakeSetup)
		})

		It("invokes each function once initially", func(done Done) {
			defer close(done)

			countChan := make(chan interface{})
			fake := func(sf SetupFunction) {
				countChan <- nil
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
			for i := 0; i < 3; i++ {
				<-countChan
			}

			Expect(tryRead(countChan)).ToNot(BeTrue())
		}, 1)

		It("invokes each function on their own go routine", func(done Done) {
			defer close(done)
			fake := func(sf SetupFunction) {
				x := make(chan struct{})
				<-x
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
		}, 1)

		It("passes the SetupFunction to each function", func(done Done) {
			defer close(done)

			fake := func(sf SetupFunction) {
				defer GinkgoRecover()
				Expect(fakeSetupComparer(sf)).To(Equal(true))
			}

			functionInvoker(fakeSetupBuilder, fake, fake, fake)
		}, 1)

		It("returns the same channel (non-nil) as the functions receive", func(done Done) {
			defer close(done)
			resultChan := make(chan chan FunctionInfo, 1)
			fsb := func(name string, f func(SetupFunction), c chan FunctionInfo) SetupFunction {
				resultChan <- c
				return fakeSetup
			}
			fake := func(sf SetupFunction) {}

			result := functionInvoker(fsb, fake)
			c := <-resultChan
			Expect(c).ToNot(BeNil())
			Expect(c).To(BeEquivalentTo(result))
		}, 1)
	})
})

func tryRead(c chan interface{}) bool {
	select {
	case <-c:
		return true
	default:
		return false
	}
}

type fakeSetupFunction struct{
}

func (f *fakeSetupFunction) AsProducer(instances int) WriteOnlyChannel{
	panic("Not intended to be called")
}

func (f *fakeSetupFunction) AsFilter(parent string, instances int) (ReadOnlyChannel, WriteOnlyChannel){
	panic("Not intended to be called")
}

func (f *fakeSetupFunction) AsConsumer(parent string, instances int) ReadOnlyChannel{
	panic("Not intended to be called")
}
<|endoftext|>


<commit_before>/*
Copyright 2012, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package relog

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"runtime"
)

var (
	dunno     = []byte("???")
	centerDot = []byte("·")
	dot       = []byte(".")
)

type ErrorTrace interface {
	Error() string
	String() string
	StackTrace() string
}

type errorTrace struct {
	err        error
	stackTrace string
}

func (e errorTrace) Error() string {
	return e.err.Error()
}

func (e errorTrace) StackTrace() string {
	return e.stackTrace
}

func (e errorTrace) String() string {
	return fmt.Sprintf("%v\n%v", e.err, e.stackTrace)
}

func NewErrorTrace(err error) ErrorTrace {
	return errorTrace{err.(error), string(Stack(5))}
}

// Taken from runtime/debug.
func Stack(calldepth int) []byte {
	return stack(calldepth)
}

func stack(calldepth int) []byte {
	buf := new(bytes.Buffer) // the returned data
	// As we loop, we open files and read them. These variables record the currently
	// loaded file.
	var lines [][]byte
	var lastFile string
	for i := calldepth; ; i++ { // Caller we care about is the user, 2 frames up
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		// Print this much at least.  If we can't find the source, it won't show.
		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
		if file != lastFile {
			data, err := ioutil.ReadFile(file)
			if err != nil {
				continue
			}
			lines = bytes.Split(data, []byte{'\n'})
			lastFile = file
		}
		line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
	}
	return buf.Bytes()
}

// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
	if n < 0 || n >= len(lines) {
		return dunno
	}
	return bytes.Trim(lines[n], " \t")
}

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
	fn := runtime.FuncForPC(pc)
	if fn == nil {
		return dunno
	}
	name := []byte(fn.Name())
	// The name includes the path name to the package, which is unnecessary
	// since the file name is already included.  Plus, it has center dots.
	// That is, we see
	//	runtime/debug.*T·ptrmethod
	// and want
	//	*T.ptrmethod
	if period := bytes.Index(name, dot); period >= 0 {
		name = name[period+1:]
	}
	name = bytes.Replace(name, centerDot, dot, -1)
	return name
}
<commit_msg>rename to clarify the purpose of this code<commit_after>/*
Copyright 2012, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package relog

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"runtime"
)

var (
	dunno     = []byte("???")
	centerDot = []byte("·")
	dot       = []byte(".")
)

type PanicError interface {
	Error() string
	String() string
	StackTrace() string
}

type panicError struct {
	err        error
	stackTrace string
}

func (e panicError) Error() string {
	return e.err.Error()
}

func (e panicError) StackTrace() string {
	return e.stackTrace
}

func (e panicError) String() string {
	return fmt.Sprintf("%v\n%v", e.err, e.stackTrace)
}

func NewPanicError(err error) PanicError {
	// magic 5 trims off just enough stack data to be clear
	return panicError{err.(error), string(Stack(5))}
}

// Taken from runtime/debug.go
func Stack(calldepth int) []byte {
	return stack(calldepth)
}

func stack(calldepth int) []byte {
	buf := new(bytes.Buffer) // the returned data
	// As we loop, we open files and read them. These variables record the currently
	// loaded file.
	var lines [][]byte
	var lastFile string
	for i := calldepth; ; i++ { // Caller we care about is the user, 2 frames up
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		// Print this much at least.  If we can't find the source, it won't show.
		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
		if file != lastFile {
			data, err := ioutil.ReadFile(file)
			if err != nil {
				continue
			}
			lines = bytes.Split(data, []byte{'\n'})
			lastFile = file
		}
		line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
	}
	return buf.Bytes()
}

// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
	if n < 0 || n >= len(lines) {
		return dunno
	}
	return bytes.Trim(lines[n], " \t")
}

// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
	fn := runtime.FuncForPC(pc)
	if fn == nil {
		return dunno
	}
	name := []byte(fn.Name())
	// The name includes the path name to the package, which is unnecessary
	// since the file name is already included.  Plus, it has center dots.
	// That is, we see
	//	runtime/debug.*T·ptrmethod
	// and want
	//	*T.ptrmethod
	if period := bytes.Index(name, dot); period >= 0 {
		name = name[period+1:]
	}
	name = bytes.Replace(name, centerDot, dot, -1)
	return name
}
<|endoftext|>


<commit_before>// errchk $G -e $D/$F.go

// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test that basic operations on named types are valid
// and preserve the type.

package main

type Bool bool

type Map map[int]int
func (Map) M() {}

func asBool(Bool) {}

func main() {
	var (
		b Bool = true;
		i, j int;
		c = make(chan int);
		m = make(Map);
	)

	asBool(b);
	asBool(!b);
	asBool(true);
	asBool(*&b);
	asBool(Bool(true));
	asBool(1!=2);	// ERROR "cannot use.*type bool.*as type Bool"
	asBool(i < j);	// ERROR "cannot use.*type bool.*as type Bool"

	_, b = m[2];	// ERROR "cannot assign bool.*type Bool"
	m[2] = 1, b;	// ERROR "cannot use.*type Bool.*as type bool"

	b = c<-1;	// ERROR "cannot use.*type bool.*type Bool"
	_ = b;
	asBool(c<-1);	// ERROR "cannot use.*type bool.*as type Bool"

	_, b = <-c;	// ERROR "cannot assign bool.*type Bool"
	_ = b;

	var inter interface{};
	_, b = inter.(Map);	// ERROR "cannot assign bool.*type Bool"
	_ = b;

	var minter interface{M()};
	_, b = minter.(Map);	// ERROR "cannot assign bool.*type Bool"
	_ = b;

	asBool(closed(c));	// ERROR "cannot use.*type bool.*as type Bool"
	b = closed(c);		// ERROR "cannot use.*type bool.*type Bool"
	_ = b;
}

<commit_msg>gccgo does not distinguish "use" and "assign" in these error messages.  Match gccgo output.<commit_after>// errchk $G -e $D/$F.go

// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test that basic operations on named types are valid
// and preserve the type.

package main

type Bool bool

type Map map[int]int
func (Map) M() {}

func asBool(Bool) {}

func main() {
	var (
		b Bool = true;
		i, j int;
		c = make(chan int);
		m = make(Map);
	)

	asBool(b);
	asBool(!b);
	asBool(true);
	asBool(*&b);
	asBool(Bool(true));
	asBool(1!=2);	// ERROR "cannot use.*type bool.*as type Bool"
	asBool(i < j);	// ERROR "cannot use.*type bool.*as type Bool"

	_, b = m[2];	// ERROR "cannot .* bool.*type Bool"
	m[2] = 1, b;	// ERROR "cannot use.*type Bool.*as type bool"

	b = c<-1;	// ERROR "cannot use.*type bool.*type Bool"
	_ = b;
	asBool(c<-1);	// ERROR "cannot use.*type bool.*as type Bool"

	_, b = <-c;	// ERROR "cannot .* bool.*type Bool"
	_ = b;

	var inter interface{};
	_, b = inter.(Map);	// ERROR "cannot .* bool.*type Bool"
	_ = b;

	var minter interface{M()};
	_, b = minter.(Map);	// ERROR "cannot .* bool.*type Bool"
	_ = b;

	asBool(closed(c));	// ERROR "cannot use.*type bool.*as type Bool"
	b = closed(c);		// ERROR "cannot use.*type bool.*type Bool"
	_ = b;
}

<|endoftext|>


<commit_before>// run

// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test that the implementation catches nil ptr indirection
// in a large address space.

package main

import "unsafe"

// Having a big address space means that indexing
// at a 256 MB offset from a nil pointer might not
// cause a memory access fault. This test checks
// that Go is doing the correct explicit checks to catch
// these nil pointer accesses, not just relying on the hardware.
var dummy [256 << 20]byte // give us a big address space

func main() {
	// the test only tests what we intend to test
	// if dummy starts in the first 256 MB of memory.
	// otherwise there might not be anything mapped
	// at the address that might be accidentally
	// dereferenced below.
	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
		panic("dummy too far out")
	}

	shouldPanic(p1)
	shouldPanic(p2)
	shouldPanic(p3)
	shouldPanic(p4)
	shouldPanic(p5)
	shouldPanic(p6)
	shouldPanic(p7)
	shouldPanic(p8)
	shouldPanic(p9)
	shouldPanic(p10)
	shouldPanic(p11)
	shouldPanic(p12)
}

func shouldPanic(f func()) {
	defer func() {
		if recover() == nil {
			panic("memory reference did not panic")
		}
	}()
	f()
}

func p1() {
	// Array index.
	var p *[1 << 30]byte = nil
	println(p[256<<20]) // very likely to be inside dummy, but should panic
}

var xb byte

func p2() {
	var p *[1 << 30]byte = nil
	xb = 123

	// Array index.
	println(p[uintptr(unsafe.Pointer(&xb))]) // should panic
}

func p3() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	var x []byte = p[0:] // should panic
	_ = x
}

var q *[1 << 30]byte

func p4() {
	// Array to slice.
	var x []byte
	var y = &x
	*y = q[0:] // should crash (uses arraytoslice runtime routine)
}

func fb([]byte) {
	panic("unreachable")
}

func p5() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	fb(p[0:]) // should crash
}

func p6() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	var _ []byte = p[10 : len(p)-10] // should crash
}

type T struct {
	x [256 << 20]byte
	i int
}

func f() *T {
	return nil
}

var y *T
var x = &y

func p7() {
	// Struct field access with large offset.
	println(f().i) // should crash
}

func p8() {
	// Struct field access with large offset.
	println((*x).i) // should crash
}

func p9() {
	// Struct field access with large offset.
	var t *T
	println(&t.i) // should crash
}

func p10() {
	// Struct field access with large offset.
	var t *T
	println(t.i) // should crash
}

type T1 struct {
	T
}

type T2 struct {
	*T1
}

func p11() {
	t := &T2{}
	p := &t.i
	println(*p)
}

// ADDR(DOT(IND(p))) needs a check also
func p12() {
	var p *T = nil
	println(*(&((*p).i)))
}
<commit_msg>test/nilptr: add more tests<commit_after>// run

// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test that the implementation catches nil ptr indirection
// in a large address space.

package main

import "unsafe"

// Having a big address space means that indexing
// at a 256 MB offset from a nil pointer might not
// cause a memory access fault. This test checks
// that Go is doing the correct explicit checks to catch
// these nil pointer accesses, not just relying on the hardware.
var dummy [256 << 20]byte // give us a big address space

func main() {
	// the test only tests what we intend to test
	// if dummy starts in the first 256 MB of memory.
	// otherwise there might not be anything mapped
	// at the address that might be accidentally
	// dereferenced below.
	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
		panic("dummy too far out")
	}

	shouldPanic(p1)
	shouldPanic(p2)
	shouldPanic(p3)
	shouldPanic(p4)
	shouldPanic(p5)
	shouldPanic(p6)
	shouldPanic(p7)
	shouldPanic(p8)
	shouldPanic(p9)
	shouldPanic(p10)
	shouldPanic(p11)
	shouldPanic(p12)
	shouldPanic(p13)
	shouldPanic(p14)
	shouldPanic(p15)
	shouldPanic(p16)
}

func shouldPanic(f func()) {
	defer func() {
		if recover() == nil {
			panic("memory reference did not panic")
		}
	}()
	f()
}

func p1() {
	// Array index.
	var p *[1 << 30]byte = nil
	println(p[256<<20]) // very likely to be inside dummy, but should panic
}

var xb byte

func p2() {
	var p *[1 << 30]byte = nil
	xb = 123

	// Array index.
	println(p[uintptr(unsafe.Pointer(&xb))]) // should panic
}

func p3() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	var x []byte = p[0:] // should panic
	_ = x
}

var q *[1 << 30]byte

func p4() {
	// Array to slice.
	var x []byte
	var y = &x
	*y = q[0:] // should crash (uses arraytoslice runtime routine)
}

func fb([]byte) {
	panic("unreachable")
}

func p5() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	fb(p[0:]) // should crash
}

func p6() {
	// Array to slice.
	var p *[1 << 30]byte = nil
	var _ []byte = p[10 : len(p)-10] // should crash
}

type T struct {
	x [256 << 20]byte
	i int
}

func f() *T {
	return nil
}

var y *T
var x = &y

func p7() {
	// Struct field access with large offset.
	println(f().i) // should crash
}

func p8() {
	// Struct field access with large offset.
	println((*x).i) // should crash
}

func p9() {
	// Struct field access with large offset.
	var t *T
	println(&t.i) // should crash
}

func p10() {
	// Struct field access with large offset.
	var t *T
	println(t.i) // should crash
}

type T1 struct {
	T
}

type T2 struct {
	*T1
}

func p11() {
	t := &T2{}
	p := &t.i
	println(*p)
}

// ADDR(DOT(IND(p))) needs a check also
func p12() {
	var p *T = nil
	println(*(&((*p).i)))
}

// Tests suggested in golang.org/issue/6080.

func p13() {
	var x *[10]int
	y := x[:]
	_ = y
}

func p14() {
	println((*[1]int)(nil)[:])
}

func p15() {
	for i := range (*[1]int)(nil)[:] {
		_ = i
	}
}

func p16() {
	for i, v := range (*[1]int)(nil)[:] {
		_ = i + v
	}
}
<|endoftext|>


<commit_before>// errorcheck

// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test illegal shifts.
// Issue 1708, illegal cases.
// Does not compile.

package p

func f(x int) int         { return 0 }
func g(x interface{}) int { return 0 }
func h(x float64) int     { return 0 }

// from the spec
var (
	s uint    = 33
	u         = 1.0 << s // ERROR "invalid operation|shift of non-integer operand"
	v float32 = 1 << s   // ERROR "invalid" "as type float32"
)

// non-constant shift expressions
var (
	e1       = g(2.0 << s) // ERROR "invalid" "as type interface"
	f1       = h(2 << s)   // ERROR "invalid" "as type float64"
	g1 int64 = 1.1 << s    // ERROR "truncated"
)

// constant shift expressions
const c uint = 65

var (
	a2 int = 1.0 << c    // ERROR "overflow"
	b2     = 1.0 << c    // ERROR "overflow"
	d2     = f(1.0 << c) // ERROR "overflow"
)

var (
	// issues 4882, 4936.
	a3 = 1.0<<s + 0 // ERROR "invalid operation|shift of non-integer operand"
	// issue 4937
	b3 = 1<<s + 1 + 1.0 // ERROR "invalid operation|shift of non-integer operand"
	// issue 5014
	c3     = complex(1<<s, 0) // ERROR "shift of type float64"
	d3 int = complex(1<<s, 3) // ERROR "cannot use.*as type int" "shift of type float64"
	e3     = real(1 << s)     // ERROR "invalid"
	f3     = imag(1 << s)     // ERROR "invalid"
)

var (
	a4 float64
	b4 int
	c4 = complex(1<<s, a4) // ERROR "shift of type float64"
	d4 = complex(1<<s, b4) // ERROR "invalid"
)
<commit_msg>test: more systematic shift tests<commit_after>// errorcheck

// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test illegal shifts.
// Issue 1708, illegal cases.
// Does not compile.

package p

func f(x int) int         { return 0 }
func g(x interface{}) int { return 0 }
func h(x float64) int     { return 0 }

// from the spec
var (
	s uint    = 33
	u         = 1.0 << s // ERROR "invalid operation|shift of non-integer operand"
	v float32 = 1 << s   // ERROR "invalid" "as type float32"
)

// non-constant shift expressions
var (
	e1       = g(2.0 << s) // ERROR "invalid" "as type interface"
	f1       = h(2 << s)   // ERROR "invalid" "as type float64"
	g1 int64 = 1.1 << s    // ERROR "truncated"
)

// constant shift expressions
const c uint = 65

var (
	a2 int = 1.0 << c    // ERROR "overflow"
	b2     = 1.0 << c    // ERROR "overflow"
	d2     = f(1.0 << c) // ERROR "overflow"
)

var (
	// issues 4882, 4936.
	a3 = 1.0<<s + 0 // ERROR "invalid operation|shift of non-integer operand"
	// issue 4937
	b3 = 1<<s + 1 + 1.0 // ERROR "invalid operation|shift of non-integer operand"
	// issue 5014
	c3     = complex(1<<s, 0) // ERROR "shift of type float64"
	d3 int = complex(1<<s, 3) // ERROR "cannot use.*as type int" "shift of type float64"
	e3     = real(1 << s)     // ERROR "invalid"
	f3     = imag(1 << s)     // ERROR "invalid"
)

// from the spec
func _() {
	var (
		s uint  = 33
		i       = 1 << s         // 1 has type int
		j int32 = 1 << s         // 1 has type int32; j == 0
		k       = uint64(1 << s) // 1 has type uint64; k == 1<<33
		m int   = 1.0 << s       // 1.0 has type int
		n       = 1.0<<s != i    // 1.0 has type int; n == false if ints are 32bits in size
		o       = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
		// next test only fails on 32bit systems
		// p = 1<<s == 1<<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
		u          = 1.0 << s    // ERROR "float64"
		u1         = 1.0<<s != 0 // ERROR "float64"
		u2         = 1<<s != 1.0 // ERROR "float64"
		v  float32 = 1 << s      // ERROR "float32"
		w  int64   = 1.0 << 33   // 1.0<<33 is a constant shift expression
	)
}

// shifts in comparisons w/ untyped operands
var (
	_ = 1<<s == 1
	_ = 1<<s == 1.  // ERROR "shift of type float64"
	_ = 1.<<s == 1  // ERROR "shift of type float64"
	_ = 1.<<s == 1. // ERROR "shift of type float64"

	_ = 1<<s+1 == 1
	_ = 1<<s+1 == 1.   // ERROR "shift of type float64"
	_ = 1<<s+1. == 1   // ERROR "shift of type float64"
	_ = 1<<s+1. == 1.  // ERROR "shift of type float64"
	_ = 1.<<s+1 == 1   // ERROR "shift of type float64"
	_ = 1.<<s+1 == 1.  // ERROR "shift of type float64"
	_ = 1.<<s+1. == 1  // ERROR "shift of type float64"
	_ = 1.<<s+1. == 1. // ERROR "shift of type float64"

	_ = 1<<s == 1<<s
	_ = 1<<s == 1.<<s  // ERROR "shift of type float64"
	_ = 1.<<s == 1<<s  // ERROR "shift of type float64"
	_ = 1.<<s == 1.<<s // ERROR "shift of type float64"

	_ = 1<<s+1<<s == 1
	_ = 1<<s+1<<s == 1.   // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1   // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1.  // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1   // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1.  // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1  // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1. // ERROR "shift of type float64"

	_ = 1<<s+1<<s == 1<<s+1<<s
	_ = 1<<s+1<<s == 1<<s+1.<<s    // ERROR "shift of type float64"
	_ = 1<<s+1<<s == 1.<<s+1<<s    // ERROR "shift of type float64"
	_ = 1<<s+1<<s == 1.<<s+1.<<s   // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1<<s+1<<s    // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1<<s+1.<<s   // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1.<<s+1<<s   // ERROR "shift of type float64"
	_ = 1<<s+1.<<s == 1.<<s+1.<<s  // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1<<s+1<<s    // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1<<s+1.<<s   // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1.<<s+1<<s   // ERROR "shift of type float64"
	_ = 1.<<s+1<<s == 1.<<s+1.<<s  // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1<<s+1<<s   // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1<<s+1.<<s  // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1.<<s+1<<s  // ERROR "shift of type float64"
	_ = 1.<<s+1.<<s == 1.<<s+1.<<s // ERROR "shift of type float64"
)

// shifts in comparisons w/ typed operands
var (
	x int
	_ = 1<<s == x
	_ = 1.<<s == x
	_ = 1.1<<s == x // ERROR "1.1 truncated"

	_ = 1<<s+x == 1
	_ = 1<<s+x == 1.
	_ = 1<<s+x == 1.1 // ERROR "1.1 truncated"
	_ = 1.<<s+x == 1
	_ = 1.<<s+x == 1.
	_ = 1.<<s+x == 1.1  // ERROR "1.1 truncated"
	_ = 1.1<<s+x == 1   // ERROR "1.1 truncated"
	_ = 1.1<<s+x == 1.  // ERROR "1.1 truncated"
	_ = 1.1<<s+x == 1.1 // ERROR "1.1 truncated"

	_ = 1<<s == x<<s
	_ = 1.<<s == x<<s
	_ = 1.1<<s == x<<s // ERROR "1.1 truncated"
)

// shifts as operands in non-arithmetic operations and as arguments
func _() {
	var s uint
	var a []int
	_ = a[1<<s]
	_ = a[1.]
	// For now, the spec disallows these. We may revisit past Go 1.1.
	_ = a[1.<<s]  // ERROR "shift of type float64"
	_ = a[1.1<<s] // ERROR "shift of type float64"

	_ = make([]int, 1)
	_ = make([]int, 1.)
	_ = make([]int, 1.<<s)
	_ = make([]int, 1.1<<s) // ERROR "1.1 truncated"

	_ = float32(1)
	_ = float32(1 << s) // ERROR "shift of type float32"
	_ = float32(1.)
	_ = float32(1. << s)  // ERROR "shift of type float32"
	_ = float32(1.1 << s) // ERROR "shift of type float32"

	_ = append(a, 1<<s)
	_ = append(a, 1.<<s)
	_ = append(a, 1.1<<s) // ERROR "1.1 truncated"

	var b []float32
	_ = append(b, 1<<s)   // ERROR "type float32"
	_ = append(b, 1.<<s)  // ERROR "type float32"
	_ = append(b, 1.1<<s) // ERROR "type float32"

	_ = complex(1.<<s, 0)  // ERROR "shift of type float64"
	_ = complex(1.1<<s, 0) // ERROR "shift of type float64"
	_ = complex(0, 1.<<s)  // ERROR "shift of type float64"
	_ = complex(0, 1.1<<s) // ERROR "shift of type float64"

	var a4 float64
	var b4 int
	_ = complex(1<<s, a4) // ERROR "shift of type float64"
	_ = complex(1<<s, b4) // ERROR "invalid"

	var m1 map[int]string
	delete(m1, 1<<s)
	delete(m1, 1.<<s)
	delete(m1, 1.1<<s) // ERROR "1.1 truncated|shift of type float64"

	var m2 map[float32]string
	delete(m2, 1<<s)   // ERROR "invalid|cannot use 1 << s as type float32"
	delete(m2, 1.<<s)  // ERROR "invalid|cannot use 1 << s as type float32"
	delete(m2, 1.1<<s) // ERROR "invalid|cannot use 1.1 << s as type float32"
}

// shifts of shifts
func _() {
	var s uint
	_ = 1 << (1 << s)
	_ = 1 << (1. << s)
	_ = 1 << (1.1 << s)   // ERROR "1.1 truncated"
	_ = 1. << (1 << s)    // ERROR "shift of type float64"
	_ = 1. << (1. << s)   // ERROR "shift of type float64"
	_ = 1.1 << (1.1 << s) // ERROR "invalid|1.1 truncated"

	_ = (1 << s) << (1 << s)
	_ = (1 << s) << (1. << s)
	_ = (1 << s) << (1.1 << s)   // ERROR "1.1 truncated"
	_ = (1. << s) << (1 << s)    // ERROR "shift of type float64"
	_ = (1. << s) << (1. << s)   // ERROR "shift of type float64"
	_ = (1.1 << s) << (1.1 << s) // ERROR "invalid|1.1 truncated"

	var x int
	x = 1 << (1 << s)
	x = 1 << (1. << s)
	x = 1 << (1.1 << s) // ERROR "1.1 truncated"
	x = 1. << (1 << s)
	x = 1. << (1. << s)
	x = 1.1 << (1.1 << s) // ERROR "1.1 truncated"

	x = (1 << s) << (1 << s)
	x = (1 << s) << (1. << s)
	x = (1 << s) << (1.1 << s) // ERROR "1.1 truncated"
	x = (1. << s) << (1 << s)
	x = (1. << s) << (1. << s)
	x = (1.1 << s) << (1.1 << s) // ERROR "1.1 truncated"

	var y float32
	y = 1 << (1 << s)     // ERROR "type float32"
	y = 1 << (1. << s)    // ERROR "type float32"
	y = 1 << (1.1 << s)   // ERROR "invalid|1.1 truncated|float32"
	y = 1. << (1 << s)    // ERROR "type float32"
	y = 1. << (1. << s)   // ERROR "type float32"
	y = 1.1 << (1.1 << s) // ERROR "invalid|1.1 truncated|float32"

	var z complex128
	z = (1 << s) << (1 << s)     // ERROR "type complex128"
	z = (1 << s) << (1. << s)    // ERROR "type complex128"
	z = (1 << s) << (1.1 << s)   // ERROR "invalid|1.1 truncated|complex128"
	z = (1. << s) << (1 << s)    // ERROR "type complex128"
	z = (1. << s) << (1. << s)   // ERROR "type complex128"
	z = (1.1 << s) << (1.1 << s) // ERROR "invalid|1.1 truncated|complex128"
}
<|endoftext|>


<commit_before>package ca

import (
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"net"
	"path/filepath"

	"github.com/cloudflare/cfssl/api/client"
	"github.com/cloudflare/cfssl/auth"
	"github.com/cloudflare/cfssl/config"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/info"
	"github.com/cloudflare/cfssl/signer"
	"github.com/cloudflare/cfssl/transport/core"
)

type authError struct {
	authType string
}

func (err *authError) Error() string {
	return fmt.Sprintf("transport: unsupported CFSSL authentication method %s", err.authType)
}

// This approach allows us to quickly add other providers later, such
// as the TPM.
var authTypes = map[string]func(config.AuthKey, []byte) (auth.Provider, error){
	"standard": newStandardProvider,
}

// Create a standard provider without providing any additional data.
func newStandardProvider(ak config.AuthKey, ad []byte) (auth.Provider, error) {
	return auth.New(ak.Key, ad)
}

// Create a new provider from an authentication key and possibly
// additional data.
func newProvider(ak config.AuthKey, ad []byte) (auth.Provider, error) {
	// If no auth key was provided, use unauthenticated
	// requests. This is useful when a local CFSSL is being used.
	if ak.Type == "" && ak.Key == "" {
		return nil, nil
	}

	f, ok := authTypes[ak.Type]
	if !ok {
		return nil, &authError{authType: ak.Type}
	}

	return f(ak, ad)
}

// ErrNoAuth is returned when a client is talking to a CFSSL remote
// that is not on a loopback address and doesn't have an
// authentication provider set.
var ErrNoAuth = errors.New("transport: authentication is required for non-local remotes")

var v4Loopback = net.IPNet{
	IP:   net.IP{127, 0, 0, 0},
	Mask: net.IPv4Mask(255, 0, 0, 0),
}

func ipIsLocal(ip net.IP) bool {
	if ip.To4() == nil {
		return ip.Equal(net.IPv6loopback)
	}

	return v4Loopback.Contains(ip)
}

// The only time a client should be doing unauthenticated requests is
// when a local CFSSL is being used.
func (cap *CFSSL) validateAuth() error {
	// The client is using some form of authentication, and the best way
	// to figure out that the auth is invalid is when it's used. Therefore,
	// we'll delay checking the credentials until that time.
	if cap.provider != nil {
		return nil
	}

	hosts := cap.remote.Hosts()
	for i := range hosts {
		ips, err := net.LookupIP(hosts[i])
		if err != nil {
			return err
		}

		for _, ip := range ips {
			if !ipIsLocal(ip) {
				return ErrNoAuth
			}
		}
	}

	return nil
}

var cfsslConfigDirs = []string{
	"/usr/local/cfssl",
	"/etc/cfssl",
	"/state/etc/cfssl",
}

// The CFSSL standard is to have a configuration file for a label as
// <config>.json.
func findLabel(label string) *config.Config {
	for _, dir := range cfsslConfigDirs {
		cfgFile := filepath.Join(dir, label+".json")
		cfg, err := config.LoadFile(cfgFile)
		if err == nil {
			return cfg
		}
	}

	return nil
}

func getProfile(cfg *config.Config, profileName string) (*config.SigningProfile, bool) {
	if cfg == nil || cfg.Signing == nil || cfg.Signing.Default == nil {
		return nil, false
	}

	var ok bool
	profile := cfg.Signing.Default
	if profileName != "" {
		if cfg.Signing.Profiles == nil {
			return nil, false
		}

		profile, ok = cfg.Signing.Profiles[profileName]
		if !ok {
			return nil, false
		}
	}

	return profile, true
}

// loadAuth loads an authentication provider from the client config's
// explicitly set auth key.
func (cap *CFSSL) loadAuth() error {
	var err error
	cap.provider, err = newProvider(cap.DefaultAuth, nil)
	return err
}

func getRemote(cfg *config.Config, profile *config.SigningProfile) (string, bool) {
	// NB: Loading the config will validate that the remote is
	// present in the config's remote section.
	if profile.RemoteServer != "" {
		return profile.RemoteServer, true
	}

	return "", false
}

func (cap *CFSSL) setRemoteAndAuth() error {
	if cap.Label != "" {
		cfsslConfig := findLabel(cap.Label)
		profile, ok := getProfile(cfsslConfig, cap.Profile)
		if ok {
			remote, ok := getRemote(cfsslConfig, profile)
			if ok {
				cap.remote = client.NewServerTLS(remote, helpers.CreateTLSConfig(profile.RemoteCAs, profile.ClientCert))
				cap.provider = profile.Provider
				return nil
			}

			// The profile may not have a remote set, but
			// it may have an authentication provider.
			cap.provider = profile.Provider
		}
	}

	cap.remote = cap.DefaultRemote
	if cap.provider != nil {
		return nil
	}
	return cap.loadAuth()
}

// CFSSL provides support for signing certificates via
// CFSSL.
type CFSSL struct {
	remote        client.Remote
	provider      auth.Provider
	Profile       string
	Label         string
	DefaultRemote client.Remote
	DefaultAuth   config.AuthKey
}

// SignCSR requests a certificate from a CFSSL signer.
func (cap *CFSSL) SignCSR(csrPEM []byte) (cert []byte, err error) {
	p, _ := pem.Decode(csrPEM)
	if p == nil || p.Type != "CERTIFICATE REQUEST" {
		return nil, errors.New("transport: invalid PEM-encoded certificate signing request")
	}

	csr, err := x509.ParseCertificateRequest(p.Bytes)
	if err != nil {
		return nil, err
	}

	hosts := make([]string, len(csr.DNSNames), len(csr.DNSNames)+len(csr.IPAddresses))
	copy(hosts, csr.DNSNames)

	for i := range csr.IPAddresses {
		hosts = append(hosts, csr.IPAddresses[i].String())
	}

	sreq := &signer.SignRequest{
		Hosts:   hosts,
		Request: string(csrPEM),
		Profile: cap.Profile,
		Label:   cap.Label,
	}

	out, err := json.Marshal(sreq)
	if err != nil {
		return nil, err
	}

	if cap.provider != nil {
		return cap.remote.AuthSign(out, nil, cap.provider)
	}

	return cap.remote.Sign(out)
}

// CACertificate returns the certificate for a CFSSL CA.
func (cap *CFSSL) CACertificate() ([]byte, error) {
	req := &info.Req{
		Label:   cap.Label,
		Profile: cap.Profile,
	}
	out, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}

	resp, err := cap.remote.Info(out)
	if err != nil {
		return nil, err
	}

	return []byte(resp.Certificate), nil
}

// NewCFSSLProvider takes the configuration information from an
// Identity (and an optional default remote), returning a CFSSL
// instance. There should be a profile in id called "cfssl", which
// should contain label and profile fields as needed.
func NewCFSSLProvider(id *core.Identity, defaultRemote client.Remote) (*CFSSL, error) {
	if id == nil {
		return nil, errors.New("transport: the identity hasn't been initialised. Has it been loaded from disk?")
	}

	cap := &CFSSL{
		DefaultRemote: defaultRemote,
	}

	cfssl := id.Profiles["cfssl"]
	if cfssl != nil {
		cap.Label = cfssl["label"]
		cap.Profile = cfssl["profile"]

		if cap.DefaultRemote == nil {
			cert, err := helpers.LoadClientCertificate(cfssl["mutual-tls-cert"], cfssl["mutual-tls-key"])
			if err != nil {
				return nil, err
			}
			remoteCAs, err := helpers.LoadPEMCertPool(cfssl["tls-remote-ca"])
			if err != nil {
				return nil, err
			}
			cap.DefaultRemote = client.NewServerTLS(cfssl["remote"], helpers.CreateTLSConfig(remoteCAs, cert))
		}

		cap.DefaultAuth.Type = cfssl["auth-type"]
		cap.DefaultAuth.Key = cfssl["auth-key"]
	}

	err := cap.setRemoteAndAuth()
	if err != nil {
		return nil, err
	}

	return cap, nil
}
<commit_msg>fix: cfssl provider support SAN URI<commit_after>package ca

import (
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"net"
	"path/filepath"

	"github.com/cloudflare/cfssl/api/client"
	"github.com/cloudflare/cfssl/auth"
	"github.com/cloudflare/cfssl/config"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/info"
	"github.com/cloudflare/cfssl/signer"
	"github.com/cloudflare/cfssl/transport/core"
)

type authError struct {
	authType string
}

func (err *authError) Error() string {
	return fmt.Sprintf("transport: unsupported CFSSL authentication method %s", err.authType)
}

// This approach allows us to quickly add other providers later, such
// as the TPM.
var authTypes = map[string]func(config.AuthKey, []byte) (auth.Provider, error){
	"standard": newStandardProvider,
}

// Create a standard provider without providing any additional data.
func newStandardProvider(ak config.AuthKey, ad []byte) (auth.Provider, error) {
	return auth.New(ak.Key, ad)
}

// Create a new provider from an authentication key and possibly
// additional data.
func newProvider(ak config.AuthKey, ad []byte) (auth.Provider, error) {
	// If no auth key was provided, use unauthenticated
	// requests. This is useful when a local CFSSL is being used.
	if ak.Type == "" && ak.Key == "" {
		return nil, nil
	}

	f, ok := authTypes[ak.Type]
	if !ok {
		return nil, &authError{authType: ak.Type}
	}

	return f(ak, ad)
}

// ErrNoAuth is returned when a client is talking to a CFSSL remote
// that is not on a loopback address and doesn't have an
// authentication provider set.
var ErrNoAuth = errors.New("transport: authentication is required for non-local remotes")

var v4Loopback = net.IPNet{
	IP:   net.IP{127, 0, 0, 0},
	Mask: net.IPv4Mask(255, 0, 0, 0),
}

func ipIsLocal(ip net.IP) bool {
	if ip.To4() == nil {
		return ip.Equal(net.IPv6loopback)
	}

	return v4Loopback.Contains(ip)
}

// The only time a client should be doing unauthenticated requests is
// when a local CFSSL is being used.
func (cap *CFSSL) validateAuth() error {
	// The client is using some form of authentication, and the best way
	// to figure out that the auth is invalid is when it's used. Therefore,
	// we'll delay checking the credentials until that time.
	if cap.provider != nil {
		return nil
	}

	hosts := cap.remote.Hosts()
	for i := range hosts {
		ips, err := net.LookupIP(hosts[i])
		if err != nil {
			return err
		}

		for _, ip := range ips {
			if !ipIsLocal(ip) {
				return ErrNoAuth
			}
		}
	}

	return nil
}

var cfsslConfigDirs = []string{
	"/usr/local/cfssl",
	"/etc/cfssl",
	"/state/etc/cfssl",
}

// The CFSSL standard is to have a configuration file for a label as
// <config>.json.
func findLabel(label string) *config.Config {
	for _, dir := range cfsslConfigDirs {
		cfgFile := filepath.Join(dir, label+".json")
		cfg, err := config.LoadFile(cfgFile)
		if err == nil {
			return cfg
		}
	}

	return nil
}

func getProfile(cfg *config.Config, profileName string) (*config.SigningProfile, bool) {
	if cfg == nil || cfg.Signing == nil || cfg.Signing.Default == nil {
		return nil, false
	}

	var ok bool
	profile := cfg.Signing.Default
	if profileName != "" {
		if cfg.Signing.Profiles == nil {
			return nil, false
		}

		profile, ok = cfg.Signing.Profiles[profileName]
		if !ok {
			return nil, false
		}
	}

	return profile, true
}

// loadAuth loads an authentication provider from the client config's
// explicitly set auth key.
func (cap *CFSSL) loadAuth() error {
	var err error
	cap.provider, err = newProvider(cap.DefaultAuth, nil)
	return err
}

func getRemote(cfg *config.Config, profile *config.SigningProfile) (string, bool) {
	// NB: Loading the config will validate that the remote is
	// present in the config's remote section.
	if profile.RemoteServer != "" {
		return profile.RemoteServer, true
	}

	return "", false
}

func (cap *CFSSL) setRemoteAndAuth() error {
	if cap.Label != "" {
		cfsslConfig := findLabel(cap.Label)
		profile, ok := getProfile(cfsslConfig, cap.Profile)
		if ok {
			remote, ok := getRemote(cfsslConfig, profile)
			if ok {
				cap.remote = client.NewServerTLS(remote, helpers.CreateTLSConfig(profile.RemoteCAs, profile.ClientCert))
				cap.provider = profile.Provider
				return nil
			}

			// The profile may not have a remote set, but
			// it may have an authentication provider.
			cap.provider = profile.Provider
		}
	}

	cap.remote = cap.DefaultRemote
	if cap.provider != nil {
		return nil
	}
	return cap.loadAuth()
}

// CFSSL provides support for signing certificates via
// CFSSL.
type CFSSL struct {
	remote        client.Remote
	provider      auth.Provider
	Profile       string
	Label         string
	DefaultRemote client.Remote
	DefaultAuth   config.AuthKey
}

// SignCSR requests a certificate from a CFSSL signer.
func (cap *CFSSL) SignCSR(csrPEM []byte) (cert []byte, err error) {
	p, _ := pem.Decode(csrPEM)
	if p == nil || p.Type != "CERTIFICATE REQUEST" {
		return nil, errors.New("transport: invalid PEM-encoded certificate signing request")
	}

	csr, err := x509.ParseCertificateRequest(p.Bytes)
	if err != nil {
		return nil, err
	}

	hosts := make([]string, len(csr.DNSNames), len(csr.DNSNames)+len(csr.IPAddresses)+len(csr.URIs))
	copy(hosts, csr.DNSNames)

	for i := range csr.IPAddresses {
		hosts = append(hosts, csr.IPAddresses[i].String())
	}

	for i := range csr.URIs {
		hosts = append(hosts, csr.URIs[i].String())
	}

	sreq := &signer.SignRequest{
		Hosts:   hosts,
		Request: string(csrPEM),
		Profile: cap.Profile,
		Label:   cap.Label,
	}

	out, err := json.Marshal(sreq)
	if err != nil {
		return nil, err
	}

	if cap.provider != nil {
		return cap.remote.AuthSign(out, nil, cap.provider)
	}

	return cap.remote.Sign(out)
}

// CACertificate returns the certificate for a CFSSL CA.
func (cap *CFSSL) CACertificate() ([]byte, error) {
	req := &info.Req{
		Label:   cap.Label,
		Profile: cap.Profile,
	}
	out, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}

	resp, err := cap.remote.Info(out)
	if err != nil {
		return nil, err
	}

	return []byte(resp.Certificate), nil
}

// NewCFSSLProvider takes the configuration information from an
// Identity (and an optional default remote), returning a CFSSL
// instance. There should be a profile in id called "cfssl", which
// should contain label and profile fields as needed.
func NewCFSSLProvider(id *core.Identity, defaultRemote client.Remote) (*CFSSL, error) {
	if id == nil {
		return nil, errors.New("transport: the identity hasn't been initialised. Has it been loaded from disk?")
	}

	cap := &CFSSL{
		DefaultRemote: defaultRemote,
	}

	cfssl := id.Profiles["cfssl"]
	if cfssl != nil {
		cap.Label = cfssl["label"]
		cap.Profile = cfssl["profile"]

		if cap.DefaultRemote == nil {
			cert, err := helpers.LoadClientCertificate(cfssl["mutual-tls-cert"], cfssl["mutual-tls-key"])
			if err != nil {
				return nil, err
			}
			remoteCAs, err := helpers.LoadPEMCertPool(cfssl["tls-remote-ca"])
			if err != nil {
				return nil, err
			}
			cap.DefaultRemote = client.NewServerTLS(cfssl["remote"], helpers.CreateTLSConfig(remoteCAs, cert))
		}

		cap.DefaultAuth.Type = cfssl["auth-type"]
		cap.DefaultAuth.Key = cfssl["auth-key"]
	}

	err := cap.setRemoteAndAuth()
	if err != nil {
		return nil, err
	}

	return cap, nil
}
<|endoftext|>


<commit_before>package lib_test

import (
	"os"
	"testing"

	"github.com/masutaka/github-nippou/lib"
)

func TestInit(t *testing.T) {
	t.Skip("This test is pending.")
}

func TestGetUser(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_USER", "taro")

	actual, _ := lib.GetUser()
	const expected = "taro"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_USER", "")
}

func TestGetAccessToken(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_ACCESS_TOKEN", "1234abcd")

	actual, _ := lib.GetAccessToken()
	const expected = "1234abcd"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_ACCESS_TOKEN", "")
}

func TestGetGistID(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_SETTINGS_GIST_ID", "0123456789")

	actual := lib.GetGistID()
	const expected = "0123456789"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_SETTINGS_GIST_ID", "")
}

func TestGetParallelNum(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_THREAD_NUM", "10")

	actual, _ := lib.GetParallelNum()
	const expected = 10
	if actual != expected {
		t.Errorf("expected %d but got %d", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_THREAD_NUM", "")
}

func TestGetDefaultSettingsURL(t *testing.T) {
	actual := lib.GetDefaultSettingsURL()
	const expected = "https://github.com/masutaka/github-nippou/blob/v" + lib.Version + "/config/settings.yml"
	if actual != expected {
		t.Errorf("expected %d but got %d", expected, actual)
	}
}

func TestGetDefaultSettingsYml(t *testing.T) {
	t.Skip("This test is pending.")
}
<commit_msg>Fix failrue of `$ make vet`<commit_after>package lib_test

import (
	"os"
	"testing"

	"github.com/masutaka/github-nippou/lib"
)

func TestInit(t *testing.T) {
	t.Skip("This test is pending.")
}

func TestGetUser(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_USER", "taro")

	actual, _ := lib.GetUser()
	const expected = "taro"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_USER", "")
}

func TestGetAccessToken(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_ACCESS_TOKEN", "1234abcd")

	actual, _ := lib.GetAccessToken()
	const expected = "1234abcd"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_ACCESS_TOKEN", "")
}

func TestGetGistID(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_SETTINGS_GIST_ID", "0123456789")

	actual := lib.GetGistID()
	const expected = "0123456789"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_SETTINGS_GIST_ID", "")
}

func TestGetParallelNum(t *testing.T) {
	os.Setenv("GITHUB_NIPPOU_THREAD_NUM", "10")

	actual, _ := lib.GetParallelNum()
	const expected = 10
	if actual != expected {
		t.Errorf("expected %d but got %d", expected, actual)
	}

	os.Setenv("GITHUB_NIPPOU_THREAD_NUM", "")
}

func TestGetDefaultSettingsURL(t *testing.T) {
	actual := lib.GetDefaultSettingsURL()
	const expected = "https://github.com/masutaka/github-nippou/blob/v" + lib.Version + "/config/settings.yml"
	if actual != expected {
		t.Errorf("expected %s but got %s", expected, actual)
	}
}

func TestGetDefaultSettingsYml(t *testing.T) {
	t.Skip("This test is pending.")
}
<|endoftext|>


<commit_before>package container

import (
	"strings"

	"github.com/docker/engine-api/types/blkiodev"
	"github.com/docker/engine-api/types/strslice"
	"github.com/docker/go-connections/nat"
	"github.com/docker/go-units"
)

// NetworkMode represents the container network stack.
type NetworkMode string

// Isolation represents the isolation technology of a container. The supported
// values are platform specific
type Isolation string

// IsDefault indicates the default isolation technology of a container. On Linux this
// is the native driver. On Windows, this is a Windows Server Container.
func (i Isolation) IsDefault() bool {
	return strings.ToLower(string(i)) == "default" || string(i) == ""
}

// IpcMode represents the container ipc stack.
type IpcMode string

// IsPrivate indicates whether the container uses its private ipc stack.
func (n IpcMode) IsPrivate() bool {
	return !(n.IsHost() || n.IsContainer())
}

// IsHost indicates whether the container uses the host's ipc stack.
func (n IpcMode) IsHost() bool {
	return n == "host"
}

// IsContainer indicates whether the container uses a container's ipc stack.
func (n IpcMode) IsContainer() bool {
	parts := strings.SplitN(string(n), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the ipc stack is valid.
func (n IpcMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	case "container":
		if len(parts) != 2 || parts[1] == "" {
			return false
		}
	default:
		return false
	}
	return true
}

// Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string {
	parts := strings.SplitN(string(n), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// UsernsMode represents userns mode in the container.
type UsernsMode string

// IsHost indicates whether the container uses the host's userns.
func (n UsernsMode) IsHost() bool {
	return n == "host"
}

// IsPrivate indicates whether the container uses the a private userns.
func (n UsernsMode) IsPrivate() bool {
	return !(n.IsHost())
}

// Valid indicates whether the userns is valid.
func (n UsernsMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	default:
		return false
	}
	return true
}

// CgroupSpec represents the cgroup to use for the container.
type CgroupSpec string

// IsContainer indicates whether the container is using another container cgroup
func (c CgroupSpec) IsContainer() bool {
	parts := strings.SplitN(string(c), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the cgroup spec is valid.
func (c CgroupSpec) Valid() bool {
	return c.IsContainer() || c == ""
}

// Container returns the name of the container whose cgroup will be used.
func (c CgroupSpec) Container() string {
	parts := strings.SplitN(string(c), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// UTSMode represents the UTS namespace of the container.
type UTSMode string

// IsPrivate indicates whether the container uses its private UTS namespace.
func (n UTSMode) IsPrivate() bool {
	return !(n.IsHost())
}

// IsHost indicates whether the container uses the host's UTS namespace.
func (n UTSMode) IsHost() bool {
	return n == "host"
}

// Valid indicates whether the UTS namespace is valid.
func (n UTSMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	default:
		return false
	}
	return true
}

// PidMode represents the pid namespace of the container.
type PidMode string

// IsPrivate indicates whether the container uses its own new pid namespace.
func (n PidMode) IsPrivate() bool {
	return !(n.IsHost() || n.IsContainer())
}

// IsHost indicates whether the container uses the host's pid namespace.
func (n PidMode) IsHost() bool {
	return n == "host"
}

// IsContainer indicates whether the container uses a container's pid namespace.
func (n PidMode) IsContainer() bool {
	parts := strings.SplitN(string(n), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the pid namespace is valid.
func (n PidMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	case "container":
		if len(parts) != 2 || parts[1] == "" {
			return false
		}
	default:
		return false
	}
	return true
}

// Container returns the name of the container whose pid namespace is going to be used.
func (n PidMode) Container() string {
	parts := strings.SplitN(string(n), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct {
	PathOnHost        string
	PathInContainer   string
	CgroupPermissions string
}

// RestartPolicy represents the restart policies of the container.
type RestartPolicy struct {
	Name              string
	MaximumRetryCount int
}

// IsNone indicates whether the container has the "no" restart policy.
// This means the container will not automatically restart when exiting.
func (rp *RestartPolicy) IsNone() bool {
	return rp.Name == "no" || rp.Name == ""
}

// IsAlways indicates whether the container has the "always" restart policy.
// This means the container will automatically restart regardless of the exit status.
func (rp *RestartPolicy) IsAlways() bool {
	return rp.Name == "always"
}

// IsOnFailure indicates whether the container has the "on-failure" restart policy.
// This means the container will automatically restart of exiting with a non-zero exit status.
func (rp *RestartPolicy) IsOnFailure() bool {
	return rp.Name == "on-failure"
}

// IsUnlessStopped indicates whether the container has the
// "unless-stopped" restart policy. This means the container will
// automatically restart unless user has put it to stopped state.
func (rp *RestartPolicy) IsUnlessStopped() bool {
	return rp.Name == "unless-stopped"
}

// IsSame compares two RestartPolicy to see if they are the same
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
	return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
}

// LogConfig represents the logging configuration of the container.
type LogConfig struct {
	Type   string
	Config map[string]string
}

// Resources contains container's resources (cgroups config, ulimits...)
type Resources struct {
	// Applicable to all platforms
	CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
	Memory    int64 // Memory limit (in bytes)

	// Applicable to UNIX platforms
	CgroupParent         string // Parent cgroup.
	BlkioWeight          uint16 // Block IO weight (relative weight vs. other containers)
	BlkioWeightDevice    []*blkiodev.WeightDevice
	BlkioDeviceReadBps   []*blkiodev.ThrottleDevice
	BlkioDeviceWriteBps  []*blkiodev.ThrottleDevice
	BlkioDeviceReadIOps  []*blkiodev.ThrottleDevice
	BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
	CPUPeriod            int64           `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
	CPUQuota             int64           `json:"CpuQuota"`  // CPU CFS (Completely Fair Scheduler) quota
	CpusetCpus           string          // CpusetCpus 0-2, 0,1
	CpusetMems           string          // CpusetMems 0-2, 0,1
	Devices              []DeviceMapping // List of devices to map inside the container
	DiskQuota            int64           // Disk limit (in bytes)
	KernelMemory         int64           // Kernel memory limit (in bytes)
	MemoryReservation    int64           // Memory soft limit (in bytes)
	MemorySwap           int64           // Total memory usage (memory + swap); set `-1` to enable unlimited swap
	MemorySwappiness     *int64          // Tuning container memory swappiness behaviour
	OomKillDisable       *bool           // Whether to disable OOM Killer or not
	PidsLimit            int64           // Setting pids limit for a container
	Ulimits              []*units.Ulimit // List of ulimits to be set in the container

	// Applicable to Windows
	CPUCount                int64  `json:"CpuCount"`   // CPU count
	CPUPercent              int64  `json:"CpuPercent"` // CPU percent
	IOMaximumIOps           uint64 // Maximum IOps for the container system drive
	IOMaximumBandwidth      uint64 // Maximum IO in bytes per second for the container system drive
	NetworkMaximumBandwidth uint64 // Maximum bandwidth of the network endpoint in bytes per second
}

// UpdateConfig holds the mutable attributes of a Container.
// Those attributes can be updated at runtime.
type UpdateConfig struct {
	// Contains container's resources (cgroups, ulimits)
	Resources
	RestartPolicy RestartPolicy
}

// HostConfig the non-portable Config structure of a container.
// Here, "non-portable" means "dependent of the host we are running on".
// Portable information *should* appear in Config.
type HostConfig struct {
	// Applicable to all platforms
	Binds           []string      // List of volume bindings for this container
	ContainerIDFile string        // File (path) where the containerId is written
	LogConfig       LogConfig     // Configuration of the logs for this container
	NetworkMode     NetworkMode   // Network mode to use for the container
	PortBindings    nat.PortMap   // Port mapping between the exposed port (container) and the host
	RestartPolicy   RestartPolicy // Restart policy to be used for the container
	AutoRemove      bool          // Automatically remove container when it exits
	VolumeDriver    string        // Name of the volume driver used to mount volumes
	VolumesFrom     []string      // List of volumes to take from other container

	// Applicable to UNIX platforms
	CapAdd          strslice.StrSlice // List of kernel capabilities to add to the container
	CapDrop         strslice.StrSlice // List of kernel capabilities to remove from the container
	DNS             []string          `json:"Dns"`        // List of DNS server to lookup
	DNSOptions      []string          `json:"DnsOptions"` // List of DNSOption to look for
	DNSSearch       []string          `json:"DnsSearch"`  // List of DNSSearch to look for
	ExtraHosts      []string          // List of extra hosts
	GroupAdd        []string          // List of additional groups that the container process will run as
	IpcMode         IpcMode           // IPC namespace to use for the container
	Cgroup          CgroupSpec        // Cgroup to use for the container
	Links           []string          // List of links (in the name:alias form)
	OomScoreAdj     int               // Container preference for OOM-killing
	PidMode         PidMode           // PID namespace to use for the container
	Privileged      bool              // Is the container in privileged mode
	PublishAllPorts bool              // Should docker publish all exposed port for the container
	ReadonlyRootfs  bool              // Is the container root filesystem in read-only
	SecurityOpt     []string          // List of string values to customize labels for MLS systems, such as SELinux.
	StorageOpt      map[string]string // Storage driver options per container.
	Tmpfs           map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
	UTSMode         UTSMode           // UTS namespace to use for the container
	UsernsMode      UsernsMode        // The user namespace to use for the container
	ShmSize         int64             // Total shm memory usage
	Sysctls         map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container

	// Applicable to Windows
	ConsoleSize [2]int    // Initial console size
	Isolation   Isolation // Isolation technology of the container (eg default, hyperv)

	// Contains container's resources (cgroups, ulimits)
	Resources
}
<commit_msg>Revert "Added network max bandwidth to container host config"<commit_after>package container

import (
	"strings"

	"github.com/docker/engine-api/types/blkiodev"
	"github.com/docker/engine-api/types/strslice"
	"github.com/docker/go-connections/nat"
	"github.com/docker/go-units"
)

// NetworkMode represents the container network stack.
type NetworkMode string

// Isolation represents the isolation technology of a container. The supported
// values are platform specific
type Isolation string

// IsDefault indicates the default isolation technology of a container. On Linux this
// is the native driver. On Windows, this is a Windows Server Container.
func (i Isolation) IsDefault() bool {
	return strings.ToLower(string(i)) == "default" || string(i) == ""
}

// IpcMode represents the container ipc stack.
type IpcMode string

// IsPrivate indicates whether the container uses its private ipc stack.
func (n IpcMode) IsPrivate() bool {
	return !(n.IsHost() || n.IsContainer())
}

// IsHost indicates whether the container uses the host's ipc stack.
func (n IpcMode) IsHost() bool {
	return n == "host"
}

// IsContainer indicates whether the container uses a container's ipc stack.
func (n IpcMode) IsContainer() bool {
	parts := strings.SplitN(string(n), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the ipc stack is valid.
func (n IpcMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	case "container":
		if len(parts) != 2 || parts[1] == "" {
			return false
		}
	default:
		return false
	}
	return true
}

// Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string {
	parts := strings.SplitN(string(n), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// UsernsMode represents userns mode in the container.
type UsernsMode string

// IsHost indicates whether the container uses the host's userns.
func (n UsernsMode) IsHost() bool {
	return n == "host"
}

// IsPrivate indicates whether the container uses the a private userns.
func (n UsernsMode) IsPrivate() bool {
	return !(n.IsHost())
}

// Valid indicates whether the userns is valid.
func (n UsernsMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	default:
		return false
	}
	return true
}

// CgroupSpec represents the cgroup to use for the container.
type CgroupSpec string

// IsContainer indicates whether the container is using another container cgroup
func (c CgroupSpec) IsContainer() bool {
	parts := strings.SplitN(string(c), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the cgroup spec is valid.
func (c CgroupSpec) Valid() bool {
	return c.IsContainer() || c == ""
}

// Container returns the name of the container whose cgroup will be used.
func (c CgroupSpec) Container() string {
	parts := strings.SplitN(string(c), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// UTSMode represents the UTS namespace of the container.
type UTSMode string

// IsPrivate indicates whether the container uses its private UTS namespace.
func (n UTSMode) IsPrivate() bool {
	return !(n.IsHost())
}

// IsHost indicates whether the container uses the host's UTS namespace.
func (n UTSMode) IsHost() bool {
	return n == "host"
}

// Valid indicates whether the UTS namespace is valid.
func (n UTSMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	default:
		return false
	}
	return true
}

// PidMode represents the pid namespace of the container.
type PidMode string

// IsPrivate indicates whether the container uses its own new pid namespace.
func (n PidMode) IsPrivate() bool {
	return !(n.IsHost() || n.IsContainer())
}

// IsHost indicates whether the container uses the host's pid namespace.
func (n PidMode) IsHost() bool {
	return n == "host"
}

// IsContainer indicates whether the container uses a container's pid namespace.
func (n PidMode) IsContainer() bool {
	parts := strings.SplitN(string(n), ":", 2)
	return len(parts) > 1 && parts[0] == "container"
}

// Valid indicates whether the pid namespace is valid.
func (n PidMode) Valid() bool {
	parts := strings.Split(string(n), ":")
	switch mode := parts[0]; mode {
	case "", "host":
	case "container":
		if len(parts) != 2 || parts[1] == "" {
			return false
		}
	default:
		return false
	}
	return true
}

// Container returns the name of the container whose pid namespace is going to be used.
func (n PidMode) Container() string {
	parts := strings.SplitN(string(n), ":", 2)
	if len(parts) > 1 {
		return parts[1]
	}
	return ""
}

// DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct {
	PathOnHost        string
	PathInContainer   string
	CgroupPermissions string
}

// RestartPolicy represents the restart policies of the container.
type RestartPolicy struct {
	Name              string
	MaximumRetryCount int
}

// IsNone indicates whether the container has the "no" restart policy.
// This means the container will not automatically restart when exiting.
func (rp *RestartPolicy) IsNone() bool {
	return rp.Name == "no" || rp.Name == ""
}

// IsAlways indicates whether the container has the "always" restart policy.
// This means the container will automatically restart regardless of the exit status.
func (rp *RestartPolicy) IsAlways() bool {
	return rp.Name == "always"
}

// IsOnFailure indicates whether the container has the "on-failure" restart policy.
// This means the container will automatically restart of exiting with a non-zero exit status.
func (rp *RestartPolicy) IsOnFailure() bool {
	return rp.Name == "on-failure"
}

// IsUnlessStopped indicates whether the container has the
// "unless-stopped" restart policy. This means the container will
// automatically restart unless user has put it to stopped state.
func (rp *RestartPolicy) IsUnlessStopped() bool {
	return rp.Name == "unless-stopped"
}

// IsSame compares two RestartPolicy to see if they are the same
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
	return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
}

// LogConfig represents the logging configuration of the container.
type LogConfig struct {
	Type   string
	Config map[string]string
}

// Resources contains container's resources (cgroups config, ulimits...)
type Resources struct {
	// Applicable to all platforms
	CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
	Memory    int64 // Memory limit (in bytes)

	// Applicable to UNIX platforms
	CgroupParent         string // Parent cgroup.
	BlkioWeight          uint16 // Block IO weight (relative weight vs. other containers)
	BlkioWeightDevice    []*blkiodev.WeightDevice
	BlkioDeviceReadBps   []*blkiodev.ThrottleDevice
	BlkioDeviceWriteBps  []*blkiodev.ThrottleDevice
	BlkioDeviceReadIOps  []*blkiodev.ThrottleDevice
	BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
	CPUPeriod            int64           `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
	CPUQuota             int64           `json:"CpuQuota"`  // CPU CFS (Completely Fair Scheduler) quota
	CpusetCpus           string          // CpusetCpus 0-2, 0,1
	CpusetMems           string          // CpusetMems 0-2, 0,1
	Devices              []DeviceMapping // List of devices to map inside the container
	DiskQuota            int64           // Disk limit (in bytes)
	KernelMemory         int64           // Kernel memory limit (in bytes)
	MemoryReservation    int64           // Memory soft limit (in bytes)
	MemorySwap           int64           // Total memory usage (memory + swap); set `-1` to enable unlimited swap
	MemorySwappiness     *int64          // Tuning container memory swappiness behaviour
	OomKillDisable       *bool           // Whether to disable OOM Killer or not
	PidsLimit            int64           // Setting pids limit for a container
	Ulimits              []*units.Ulimit // List of ulimits to be set in the container

	// Applicable to Windows
	CPUCount           int64  `json:"CpuCount"`   // CPU count
	CPUPercent         int64  `json:"CpuPercent"` // CPU percent
	IOMaximumIOps      uint64 // Maximum IOps for the container system drive
	IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive
}

// UpdateConfig holds the mutable attributes of a Container.
// Those attributes can be updated at runtime.
type UpdateConfig struct {
	// Contains container's resources (cgroups, ulimits)
	Resources
	RestartPolicy RestartPolicy
}

// HostConfig the non-portable Config structure of a container.
// Here, "non-portable" means "dependent of the host we are running on".
// Portable information *should* appear in Config.
type HostConfig struct {
	// Applicable to all platforms
	Binds           []string      // List of volume bindings for this container
	ContainerIDFile string        // File (path) where the containerId is written
	LogConfig       LogConfig     // Configuration of the logs for this container
	NetworkMode     NetworkMode   // Network mode to use for the container
	PortBindings    nat.PortMap   // Port mapping between the exposed port (container) and the host
	RestartPolicy   RestartPolicy // Restart policy to be used for the container
	AutoRemove      bool          // Automatically remove container when it exits
	VolumeDriver    string        // Name of the volume driver used to mount volumes
	VolumesFrom     []string      // List of volumes to take from other container

	// Applicable to UNIX platforms
	CapAdd          strslice.StrSlice // List of kernel capabilities to add to the container
	CapDrop         strslice.StrSlice // List of kernel capabilities to remove from the container
	DNS             []string          `json:"Dns"`        // List of DNS server to lookup
	DNSOptions      []string          `json:"DnsOptions"` // List of DNSOption to look for
	DNSSearch       []string          `json:"DnsSearch"`  // List of DNSSearch to look for
	ExtraHosts      []string          // List of extra hosts
	GroupAdd        []string          // List of additional groups that the container process will run as
	IpcMode         IpcMode           // IPC namespace to use for the container
	Cgroup          CgroupSpec        // Cgroup to use for the container
	Links           []string          // List of links (in the name:alias form)
	OomScoreAdj     int               // Container preference for OOM-killing
	PidMode         PidMode           // PID namespace to use for the container
	Privileged      bool              // Is the container in privileged mode
	PublishAllPorts bool              // Should docker publish all exposed port for the container
	ReadonlyRootfs  bool              // Is the container root filesystem in read-only
	SecurityOpt     []string          // List of string values to customize labels for MLS systems, such as SELinux.
	StorageOpt      map[string]string // Storage driver options per container.
	Tmpfs           map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
	UTSMode         UTSMode           // UTS namespace to use for the container
	UsernsMode      UsernsMode        // The user namespace to use for the container
	ShmSize         int64             // Total shm memory usage
	Sysctls         map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container

	// Applicable to Windows
	ConsoleSize [2]int    // Initial console size
	Isolation   Isolation // Isolation technology of the container (eg default, hyperv)

	// Contains container's resources (cgroups, ulimits)
	Resources
}
<|endoftext|>


<commit_before>package environs

import (
	"time"
)

// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully.
type AttemptStrategy struct {
	Total time.Duration // total duration of attempt.
	Delay time.Duration // interval between each try in the burst.
}

type attempt struct {
	AttemptStrategy
	end time.Time
}

func (a AttemptStrategy) Start() *attempt {
	return &attempt{
		AttemptStrategy: a,
	}
}

func (a *attempt) Next() bool {
	now := time.Now()
	// we always make at least one attempt.
	if a.end.IsZero() {
		a.end = now.Add(a.Total)
		return true
	}

	if !now.Add(a.Delay).Before(a.end) {
		return false
	}
	time.Sleep(a.Delay)
	return true
}
<commit_msg>responding to review feedback<commit_after>package environs

import (
	"time"
)

// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully.
type AttemptStrategy struct {
	Total time.Duration // total duration of attempt.
	Delay time.Duration // interval between each try in the burst.
}

type attempt struct {
	AttemptStrategy
	end time.Time
}

// Start begins a new sequence of attempts with the given strategy.
func (a AttemptStrategy) Start() *attempt {
	return &attempt{
		AttemptStrategy: a,
	}
}

// Next waits until it is time to perform the next attempt or returns
// false if not attempts remain.
func (a *attempt) Next() bool {
	now := time.Now()
	// we always make at least one attempt.
	if a.end.IsZero() {
		a.end = now.Add(a.Total)
		return true
	}

	if !now.Add(a.Delay).Before(a.end) {
		return false
	}
	time.Sleep(a.Delay)
	return true
}
<|endoftext|>


<commit_before>package environs

import (
	"time"
)

// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully.
type AttemptStrategy struct {
	Total time.Duration // total duration of attempt.
	Delay time.Duration // interval between each try in the burst.
}

type Attempt struct {
	strategy AttemptStrategy
	end      time.Time
}

// Start begins a new sequence of attempts with the given strategy.
func (a AttemptStrategy) Start() *Attempt {
	return &Attempt{
		strategy: a,
	}
}

// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
	now := time.Now()
	// we always make at least one attempt.
	if a.end.IsZero() {
		a.end = now.Add(a.strategy.Total)
		return true
	}

	if !now.Add(a.strategy.Delay).Before(a.end) {
		return false
	}
	time.Sleep(a.strategy.Delay)
	return true
}
<commit_msg>final polish<commit_after>package environs

import (
	"time"
)

// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully.
type AttemptStrategy struct {
	Total time.Duration // total duration of attempt.
	Delay time.Duration // interval between each try in the burst.
}

type Attempt struct {
	strategy AttemptStrategy
	end      time.Time
}

// Start begins a new sequence of attempts for the given strategy.
func (a AttemptStrategy) Start() *Attempt {
	return &Attempt{
		strategy: a,
	}
}

// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
	now := time.Now()
	// we always make at least one attempt.
	if a.end.IsZero() {
		a.end = now.Add(a.strategy.Total)
		return true
	}

	if !now.Add(a.strategy.Delay).Before(a.end) {
		return false
	}
	time.Sleep(a.strategy.Delay)
	return true
}
<|endoftext|>