<commit_before>package pcf_pipelines_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	yaml "gopkg.in/yaml.v2"

	"github.com/concourse/atc"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var placeholderRegexp = regexp.MustCompile("{{([a-zA-Z0-9-_]+)}}")

var _ = Describe("pcf-pipelines", func() {
	cwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("failed to get working dir: %s", err)
	}

	baseDir := filepath.Base(cwd)

	var pipelinePaths []string
	err = filepath.Walk(cwd, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if filepath.Base(path) == "pipeline.yml" {
			relPipelinePath, err := filepath.Rel(cwd, path)
			if err != nil {
				return err
			}
			pipelinePaths = append(pipelinePaths, relPipelinePath)
		}

		return nil
	})
	if err != nil {
		log.Fatalf("failed to walk: %s", err)
	}

	for _, path := range pipelinePaths {
		pipelinePath := path

		Context(fmt.Sprintf("pipeline at %s", pipelinePath), func() {
			var configBytes []byte

			BeforeEach(func() {
				var readErr error
				configBytes, readErr = ioutil.ReadFile(pipelinePath)
				Expect(readErr).NotTo(HaveOccurred())
			})

			It("specifies all and only the params that the pipeline's tasks expect", func() {
				cleanConfigBytes := placeholderRegexp.ReplaceAll(configBytes, []byte("true"))

				var config atc.Config
				err = yaml.Unmarshal(cleanConfigBytes, &config)
				Expect(err).NotTo(HaveOccurred())

				for _, job := range config.Jobs {
					for _, task := range allTasksInPlan(&job.Plan, nil) {
						failMessage := fmt.Sprintf("Found error in the following pipeline:\n    %s\n\nin the following task's params:\n    %s/%s\n", pipelinePath, job.Name, task.Name())

						var configParams []string
						for k := range task.Params {
							configParams = append(configParams, k)
						}

						if strings.HasPrefix(task.TaskConfigPath, baseDir) {
							taskPath := strings.TrimPrefix(task.TaskConfigPath, baseDir+"/")
							relpath, err := filepath.Rel(cwd, filepath.Join(cwd, taskPath))
							Expect(err).NotTo(HaveOccurred())

							bs, err := ioutil.ReadFile(relpath)
							Expect(err).NotTo(HaveOccurred())

							taskConfig := atc.TaskConfig{}
							err = yaml.Unmarshal(bs, &taskConfig)
							Expect(err).NotTo(HaveOccurred())

							var taskParams []string
							for k := range taskConfig.Params {
								taskParams = append(taskParams, k)
							}

							assertUnorderedEqual(taskParams, configParams, failMessage)
						}
					}
				}
			})

			It("has a params file with all and only the params that the pipeline specifies", func() {
				paramsPath := filepath.Join(filepath.Dir(pipelinePath), "params.yml")
				_, err := os.Lstat(paramsPath)
				Expect(err).NotTo(HaveOccurred())

				bs, err := ioutil.ReadFile(paramsPath)
				Expect(err).NotTo(HaveOccurred())

				paramsMap := map[string]interface{}{}
				err = yaml.Unmarshal(bs, paramsMap)
				Expect(err).NotTo(HaveOccurred())

				var params []string
				for k := range paramsMap {
					params = append(params, k)
				}

				matches := placeholderRegexp.FindAllStringSubmatch(string(configBytes), -1)

				uniqueMatches := map[string]struct{}{}
				for _, match := range matches {
					uniqueMatches[match[1]] = struct{}{}
				}

				var placeholders []string
				for match := range uniqueMatches {
					placeholders = append(placeholders, match)
				}

				failMessage := fmt.Sprintf(`
Found error with the following pipeline:
%s

in the following params template:
%s
`, pipelinePath, paramsPath)

				assertUnorderedEqual(placeholders, params, failMessage)
			})
		})
	}
})

func allTasksInPlan(seq *atc.PlanSequence, tasks []atc.PlanConfig) []atc.PlanConfig {
	for _, planConfig := range *seq {
		if planConfig.Aggregate != nil {
			tasks = append(tasks, allTasksInPlan(planConfig.Aggregate, tasks)...)
		}
		if planConfig.Do != nil {
			tasks = append(tasks, allTasksInPlan(planConfig.Do, tasks)...)
		}
		if planConfig.Task != "" {
			tasks = append(tasks, planConfig)
		}
	}

	return tasks
}

func assertUnorderedEqual(left, right []string, failMessage string) {
	for _, l := range left {
		Expect(right).To(ContainElement(l), failMessage)
	}

	for _, r := range right {
		var found bool

		for _, l := range left {
			if r == l {
				found = true
				break
			}
		}

		if !found {
			Expect(right).NotTo(ContainElement(r), failMessage)
		}
	}
}
<commit_msg>Add pipeline inputs test<commit_after>package pcf_pipelines_test

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	yaml "gopkg.in/yaml.v2"

	"github.com/concourse/atc"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var placeholderRegexp = regexp.MustCompile("{{([a-zA-Z0-9-_]+)}}")

var _ = Describe("pcf-pipelines", func() {
	cwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("failed to get working dir: %s", err)
	}

	root := filepath.Dir(cwd)
	baseDir := filepath.Base(cwd)

	var pipelinePaths []string
	err = filepath.Walk(cwd, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if filepath.Base(path) == "pipeline.yml" {
			relPipelinePath, err := filepath.Rel(cwd, path)
			if err != nil {
				return err
			}
			pipelinePaths = append(pipelinePaths, relPipelinePath)
		}

		return nil
	})
	if err != nil {
		log.Fatalf("failed to walk: %s", err)
	}

	for _, path := range pipelinePaths {
		pipelinePath := path

		Context(fmt.Sprintf("pipeline at %s", pipelinePath), func() {
			var configBytes []byte

			BeforeEach(func() {
				var err error
				configBytes, err = ioutil.ReadFile(pipelinePath)
				Expect(err).NotTo(HaveOccurred())
			})

			It("specifies all and only the params that the pipeline's tasks expect", func() {
				var config atc.Config
				cleanConfigBytes := placeholderRegexp.ReplaceAll(configBytes, []byte("true"))
				err := yaml.Unmarshal(cleanConfigBytes, &config)
				Expect(err).NotTo(HaveOccurred())

				for _, job := range config.Jobs {
					for _, task := range allTasksInPlan(&job.Plan, nil) {
						failMessage := fmt.Sprintf("Found error in the following pipeline:\n    %s\n\nin the following task's params:\n    %s/%s\n", pipelinePath, job.Name, task.Name())

						var configParams []string
						for k := range task.Params {
							configParams = append(configParams, k)
						}

						if strings.HasPrefix(task.TaskConfigPath, baseDir) {
							taskPath := strings.TrimPrefix(task.TaskConfigPath, baseDir+"/")
							relpath, err := filepath.Rel(cwd, filepath.Join(cwd, taskPath))
							Expect(err).NotTo(HaveOccurred())

							bs, err := ioutil.ReadFile(relpath)
							Expect(err).NotTo(HaveOccurred())

							taskConfig := atc.TaskConfig{}
							err = yaml.Unmarshal(bs, &taskConfig)
							Expect(err).NotTo(HaveOccurred())

							var taskParams []string
							for k := range taskConfig.Params {
								taskParams = append(taskParams, k)
							}

							assertUnorderedEqual(taskParams, configParams, failMessage)
						}
					}
				}
			})

			It("has a params file with all and only the params that the pipeline specifies", func() {
				paramsPath := filepath.Join(filepath.Dir(pipelinePath), "params.yml")
				_, err := os.Lstat(paramsPath)
				Expect(err).NotTo(HaveOccurred())

				bs, err := ioutil.ReadFile(paramsPath)
				Expect(err).NotTo(HaveOccurred())

				paramsMap := map[string]interface{}{}
				err = yaml.Unmarshal(bs, paramsMap)
				Expect(err).NotTo(HaveOccurred())

				var params []string
				for k := range paramsMap {
					params = append(params, k)
				}

				matches := placeholderRegexp.FindAllStringSubmatch(string(configBytes), -1)

				uniqueMatches := map[string]struct{}{}
				for _, match := range matches {
					uniqueMatches[match[1]] = struct{}{}
				}

				var placeholders []string
				for match := range uniqueMatches {
					placeholders = append(placeholders, match)
				}

				failMessage := fmt.Sprintf(`
Found error with the following pipeline:
%s

in the following params template:
%s
`, pipelinePath, paramsPath)

				assertUnorderedEqual(placeholders, params, failMessage)
			})

			It("provides all of the resources that the tasks it defines require", func() {
				var config atc.Config
				cleanConfigBytes := placeholderRegexp.ReplaceAll(configBytes, []byte("true"))
				err := yaml.Unmarshal(cleanConfigBytes, &config)
				Expect(err).NotTo(HaveOccurred())

				for _, job := range config.Jobs {
					tasks := allTasksInPlan(&job.Plan, nil)
					for i, task := range tasks {
						var inputs []atc.TaskInputConfig
						if task.TaskConfigPath != "" {
							var taskConfig atc.TaskConfig
							bs, err := ioutil.ReadFile(filepath.Join(root, task.TaskConfigPath))
							Expect(err).NotTo(HaveOccurred())

							err = yaml.Unmarshal(bs, &taskConfig)
							Expect(err).NotTo(HaveOccurred())

							inputs = taskConfig.Inputs
						}

						if task.TaskConfig != nil {
							inputs = task.TaskConfig.Inputs
						}

						for k := range task.InputMapping {
							var validInputMapping bool
							for _, input := range inputs {
								if input.Name == k {
									validInputMapping = true
									break
								}
							}
							if !validInputMapping {
								Fail(fmt.Sprintf("invalid input mapping; task does specify an input named '%s'", k))
							}
						}

						actuals := availableResources(&job.Plan, nil)

						for j := 0; j < i; j++ {
							upstreamTask := tasks[j]

							if upstreamTask.TaskConfig != nil {
								for _, output := range upstreamTask.TaskConfig.Outputs {
									actuals = append(actuals, output.Name)
								}
							}

							if upstreamTask.TaskConfigPath != "" {
								var upstreamTaskConfig atc.TaskConfig
								bs, err := ioutil.ReadFile(filepath.Join(root, upstreamTask.TaskConfigPath))
								Expect(err).NotTo(HaveOccurred())

								err = yaml.Unmarshal(bs, &upstreamTaskConfig)
								Expect(err).NotTo(HaveOccurred())

								for _, output := range upstreamTaskConfig.Outputs {
									actuals = append(actuals, output.Name)
								}
							}

							for _, v := range upstreamTask.OutputMapping {
								actuals = append(actuals, v)
							}
						}

					OUTER:
						for _, input := range inputs {
							for _, actual := range actuals {
								if input.Name == actual {
									continue OUTER
								}

								for k, v := range task.InputMapping {
									if k == input.Name && v == actual {
										continue OUTER
									}
								}
							}

							Fail(fmt.Sprintf("did not find matching get, put, output or input_mapping of '%s', which is required by task '%s'", input.Name, task.Name()))
						}
					}
				}
			})
		})
	}
})

func allTasksInPlan(seq *atc.PlanSequence, tasks []atc.PlanConfig) []atc.PlanConfig {
	for _, planConfig := range *seq {
		if planConfig.Aggregate != nil {
			tasks = append(tasks, allTasksInPlan(planConfig.Aggregate, tasks)...)
		}
		if planConfig.Do != nil {
			tasks = append(tasks, allTasksInPlan(planConfig.Do, tasks)...)
		}
		if planConfig.Task != "" {
			tasks = append(tasks, planConfig)
		}
	}

	return tasks
}

func availableResources(seq *atc.PlanSequence, resources []string) []string {
	for _, planConfig := range *seq {
		if planConfig.Aggregate != nil {
			resources = append(resources, availableResources(planConfig.Aggregate, resources)...)
		}
		if planConfig.Do != nil {
			resources = append(resources, availableResources(planConfig.Do, resources)...)
		}
		if planConfig.Get != "" {
			resources = append(resources, planConfig.Get)
		}
		if planConfig.Put != "" {
			resources = append(resources, planConfig.Put)
		}
	}

	return resources
}

func assertUnorderedEqual(left, right []string, failMessage string) {
	for _, l := range left {
		Expect(right).To(ContainElement(l), failMessage)
	}

	for _, r := range right {
		var found bool

		for _, l := range left {
			if r == l {
				found = true
				break
			}
		}

		if !found {
			Expect(right).NotTo(ContainElement(r), failMessage)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2017 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

                 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package test

import (
	"os"
	"path/filepath"

	"github.com/hyperledger/fabric/common/configtx"
	configtxapplication "github.com/hyperledger/fabric/common/configtx/handlers/application"
	configtxmsp "github.com/hyperledger/fabric/common/configtx/handlers/msp"
	configtxorderer "github.com/hyperledger/fabric/common/configtx/handlers/orderer"
	genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
	"github.com/hyperledger/fabric/common/genesis"
	"github.com/hyperledger/fabric/msp"
	cb "github.com/hyperledger/fabric/protos/common"

	logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("common/configtx/test")

const (
	// AcceptAllPolicyKey is the key of the AcceptAllPolicy.
	AcceptAllPolicyKey = "AcceptAllPolicy"
)

var sampleMSPPath string

func dirExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func init() {
	mspSampleConfig := "/msp/sampleconfig"
	peerPath := filepath.Join(os.Getenv("PEER_CFG_PATH"), mspSampleConfig)
	ordererPath := filepath.Join(os.Getenv("ORDERER_CFG_PATH"), mspSampleConfig)
	switch {
	case dirExists(peerPath):
		sampleMSPPath = peerPath
		return
	case dirExists(ordererPath):
		sampleMSPPath = ordererPath
		return
	}

	gopath := os.Getenv("GOPATH")
	for _, p := range filepath.SplitList(gopath) {
		samplePath := filepath.Join(p, "src/github.com/hyperledger/fabric", mspSampleConfig)
		if !dirExists(samplePath) {
			continue
		}
		sampleMSPPath = samplePath
	}

	if sampleMSPPath == "" {
		logger.Panicf("Could not find genesis.yaml, try setting PEER_CFG_PATH, ORDERER_CFG_PATH, or GOPATH correctly")
	}
}

// MakeGenesisBlock creates a genesis block using the test templates for the given chainID
func MakeGenesisBlock(chainID string) (*cb.Block, error) {
	return genesis.NewFactoryImpl(CompositeTemplate()).Block(chainID)
}

// OrderererTemplate returns the test orderer template
func OrdererTemplate() configtx.Template {
	genConf := genesisconfig.Load()
	return provisional.New(genConf).ChannelTemplate()
}

const sampleOrgID = "SAMPLE"

// ApplicationOrgTemplate returns the SAMPLE org with MSP template
func ApplicationOrgTemplate() configtx.Template {
	mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
	if err != nil {
		logger.Panicf("Could not load sample MSP config: %s", err)
	}
	return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{configtxapplication.GroupKey, sampleOrgID}, mspConf))
}

// OrdererOrgTemplate returns the SAMPLE org with MSP template
func OrdererOrgTemplate() configtx.Template {
	mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
	if err != nil {
		logger.Panicf("Could not load sample MSP config: %s", err)
	}
	return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{configtxorderer.GroupKey, sampleOrgID}, mspConf))
}

// CompositeTemplate returns the composite template of peer, orderer, and MSP
func CompositeTemplate() configtx.Template {
	return configtx.NewCompositeTemplate(OrdererTemplate(), ApplicationOrgTemplate(), OrdererOrgTemplate())
}
<commit_msg>[FAB-2232] Rename test MSP to DEFAULT<commit_after>/*
Copyright IBM Corp. 2017 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

                 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package test

import (
	"os"
	"path/filepath"

	"github.com/hyperledger/fabric/common/configtx"
	configtxapplication "github.com/hyperledger/fabric/common/configtx/handlers/application"
	configtxmsp "github.com/hyperledger/fabric/common/configtx/handlers/msp"
	configtxorderer "github.com/hyperledger/fabric/common/configtx/handlers/orderer"
	genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
	"github.com/hyperledger/fabric/common/configtx/tool/provisional"
	"github.com/hyperledger/fabric/common/genesis"
	"github.com/hyperledger/fabric/msp"
	cb "github.com/hyperledger/fabric/protos/common"

	logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("common/configtx/test")

const (
	// AcceptAllPolicyKey is the key of the AcceptAllPolicy.
	AcceptAllPolicyKey = "AcceptAllPolicy"
)

var sampleMSPPath string

func dirExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func init() {
	mspSampleConfig := "/msp/sampleconfig"
	peerPath := filepath.Join(os.Getenv("PEER_CFG_PATH"), mspSampleConfig)
	ordererPath := filepath.Join(os.Getenv("ORDERER_CFG_PATH"), mspSampleConfig)
	switch {
	case dirExists(peerPath):
		sampleMSPPath = peerPath
		return
	case dirExists(ordererPath):
		sampleMSPPath = ordererPath
		return
	}

	gopath := os.Getenv("GOPATH")
	for _, p := range filepath.SplitList(gopath) {
		samplePath := filepath.Join(p, "src/github.com/hyperledger/fabric", mspSampleConfig)
		if !dirExists(samplePath) {
			continue
		}
		sampleMSPPath = samplePath
	}

	if sampleMSPPath == "" {
		logger.Panicf("Could not find genesis.yaml, try setting PEER_CFG_PATH, ORDERER_CFG_PATH, or GOPATH correctly")
	}
}

// MakeGenesisBlock creates a genesis block using the test templates for the given chainID
func MakeGenesisBlock(chainID string) (*cb.Block, error) {
	return genesis.NewFactoryImpl(CompositeTemplate()).Block(chainID)
}

// OrderererTemplate returns the test orderer template
func OrdererTemplate() configtx.Template {
	genConf := genesisconfig.Load()
	return provisional.New(genConf).ChannelTemplate()
}

// sampleOrgID apparently _must_ be set to DEFAULT or things break
// Beware when changing!
const sampleOrgID = "DEFAULT"

// ApplicationOrgTemplate returns the SAMPLE org with MSP template
func ApplicationOrgTemplate() configtx.Template {
	mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
	if err != nil {
		logger.Panicf("Could not load sample MSP config: %s", err)
	}
	return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{configtxapplication.GroupKey, sampleOrgID}, mspConf))
}

// OrdererOrgTemplate returns the SAMPLE org with MSP template
func OrdererOrgTemplate() configtx.Template {
	mspConf, err := msp.GetLocalMspConfig(sampleMSPPath, sampleOrgID)
	if err != nil {
		logger.Panicf("Could not load sample MSP config: %s", err)
	}
	return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{configtxorderer.GroupKey, sampleOrgID}, mspConf))
}

// CompositeTemplate returns the composite template of peer, orderer, and MSP
func CompositeTemplate() configtx.Template {
	return configtx.NewCompositeTemplate(OrdererTemplate(), ApplicationOrgTemplate(), OrdererOrgTemplate())
}
<|endoftext|>


<commit_before>package wallet

import (
	"github.com/bitgoin/address"
)

type CoinType string
type Test bool

const (
	BTC CoinType = "BTC"
	LTC CoinType = "LTC"
)

var CoinMap = map[CoinType]uint32{
	BTC: 0,
	LTC: 2,
}

var CoinFee = map[CoinType]uint64{
	BTC: 20000,
	LTC: 100000,
}

var (
	//BitcoinMain is params for main net.
	BitcoinMain = &address.Params{
		DumpedPrivateKeyHeader: []byte{128},
		AddressHeader:          0,
		P2SHHeader:             5,
		HDPrivateKeyID:         []byte{0x04, 0x88, 0xad, 0xe4},
		HDPublicKeyID:          []byte{0x04, 0x88, 0xb2, 0x1e},
	}
	//BitcoinTest is params for test net.
	BitcoinTest = &address.Params{
		DumpedPrivateKeyHeader: []byte{239},
		AddressHeader:          111,
		P2SHHeader:             196,
		HDPrivateKeyID:         []byte{0x04, 0x35, 0x83, 0x94},
		HDPublicKeyID:          []byte{0x04, 0x35, 0x87, 0xcf},
	}
	//LitecoinMain is params for litecoin main net.
	LitecoinMain = &address.Params{
		DumpedPrivateKeyHeader: []byte{176},
		AddressHeader:          48,
		P2SHHeader:             50,
		HDPrivateKeyID:         []byte{0x04, 0x88, 0xad, 0xe4},
		HDPublicKeyID:          []byte{0x04, 0x88, 0xb2, 0x1e},
	}
	//LitecoinTest is params for litecoin test net.
	LitecoinTest = &address.Params{
		DumpedPrivateKeyHeader: []byte{239},
		AddressHeader:          111,
		P2SHHeader:             196,
		HDPrivateKeyID:         []byte{0x04, 0x35, 0x83, 0x94},
		HDPublicKeyID:          []byte{0x04, 0x35, 0x87, 0xcf},
	}
	//MonacoinMain is params for monacoin main net.
	MonacoinMain = &address.Params{
		DumpedPrivateKeyHeader: []byte{178, 176},
		AddressHeader:          50,
		P2SHHeader:             5,
		HDPrivateKeyID:         []byte{0x04, 0x88, 0xad, 0xe4},
		HDPublicKeyID:          []byte{0x04, 0x88, 0xb2, 0x1e},
	}
)

var CoinParams = map[CoinType]map[Test]*address.Params{
	BTC: {
		true:  BitcoinTest,
		false: BitcoinMain,
	},
	LTC: {
		true:  LitecoinTest,
		false: LitecoinMain,
	},
}
<commit_msg>Use bytes as the type of an address header and a script header<commit_after>package wallet

import (
	"github.com/bitgoin/address"
)

type CoinType string
type Test bool

const (
	BTC CoinType = "BTC"
	LTC CoinType = "LTC"
)

var CoinMap = map[CoinType]uint32{
	BTC: 0,
	LTC: 2,
}

var CoinFee = map[CoinType]uint64{
	BTC: 20000,
	LTC: 100000,
}

var (
	//BitcoinMain is params for main net.
	BitcoinMain = &address.Params{
		DumpedPrivateKeyHeader: []byte{128},
		AddressHeader:          []byte{0},
		P2SHHeader:             []byte{5},
		HDPrivateKeyID:         []byte{0x04, 0x88, 0xad, 0xe4},
		HDPublicKeyID:          []byte{0x04, 0x88, 0xb2, 0x1e},
	}
	//BitcoinTest is params for test net.
	BitcoinTest = &address.Params{
		DumpedPrivateKeyHeader: []byte{239},
		AddressHeader:          []byte{111},
		P2SHHeader:             []byte{196},
		HDPrivateKeyID:         []byte{0x04, 0x35, 0x83, 0x94},
		HDPublicKeyID:          []byte{0x04, 0x35, 0x87, 0xcf},
	}
	//LitecoinMain is params for litecoin main net.
	LitecoinMain = &address.Params{
		DumpedPrivateKeyHeader: []byte{176},
		AddressHeader:          []byte{48},
		P2SHHeader:             []byte{50},
		HDPrivateKeyID:         []byte{0x04, 0x88, 0xad, 0xe4},
		HDPublicKeyID:          []byte{0x04, 0x88, 0xb2, 0x1e},
	}
	//LitecoinTest is params for litecoin test net.
	LitecoinTest = &address.Params{
		DumpedPrivateKeyHeader: []byte{239},
		AddressHeader:          []byte{111},
		P2SHHeader:             []byte{196},
		HDPrivateKeyID:         []byte{0x04, 0x35, 0x83, 0x94},
		HDPublicKeyID:          []byte{0x04, 0x35, 0x87, 0xcf},
	}
)

var CoinParams = map[CoinType]map[Test]*address.Params{
	BTC: {
		true:  BitcoinTest,
		false: BitcoinMain,
	},
	LTC: {
		true:  LitecoinTest,
		false: LitecoinMain,
	},
}
<|endoftext|>


<commit_before>package topotools

import (
	"fmt"
	"net"
	"sort"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/net/context"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/netutil"
	"github.com/youtube/vitess/go/vt/concurrency"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/topo/topoproto"

	pb "github.com/youtube/vitess/go/vt/proto/topodata"
)

// TabletNode is the representation of a tablet in the db topology.
// It can be constructed from a Tablet object, or from an EndPoint.
type TabletNode struct {
	Host  string
	Alias *pb.TabletAlias
	Port  int32
}

// ShortName returns a displayable representation of the host name.
// If the host is an IP address instead of a name, it is not shortened.
func (tn *TabletNode) ShortName() string {
	if net.ParseIP(tn.Host) != nil {
		return netutil.JoinHostPort(tn.Host, tn.Port)
	}

	hostPart := strings.SplitN(tn.Host, ".", 2)[0]
	if tn.Port == 0 {
		return hostPart
	}
	return netutil.JoinHostPort(hostPart, tn.Port)
}

func newTabletNodeFromTabletInfo(ti *topo.TabletInfo) *TabletNode {
	if err := topo.TabletValidatePortMap(ti.Tablet); err != nil {
		log.Errorf("ValidatePortmap(%v): %v", ti.Alias, err)
	}
	return &TabletNode{
		Host:  ti.Hostname,
		Port:  ti.PortMap["vt"],
		Alias: ti.Alias,
	}
}

func newTabletNodeFromEndPoint(ep *pb.EndPoint, cell string) *TabletNode {
	return &TabletNode{
		Host: ep.Host,
		Alias: &pb.TabletAlias{
			Uid:  ep.Uid,
			Cell: cell,
		},
		Port: ep.PortMap[topo.DefaultPortName],
	}
}

// TabletNodesByType maps tablet types to slices of tablet nodes.
type TabletNodesByType struct {
	TabletType pb.TabletType
	Nodes      []*TabletNode
}

// ShardNodes represents all tablet nodes for a shard, indexed by tablet type.
type ShardNodes struct {
	Name        string
	TabletNodes []*TabletNodesByType
	ServedTypes []pb.TabletType
	Tag         interface{} // Tag is an arbitrary value manageable by a plugin.
}

type numericShardNodesList []*ShardNodes

// Len is part of sort.Interface
func (nsnl numericShardNodesList) Len() int {
	return len(nsnl)
}

// Less is part of sort.Interface
func (nsnl numericShardNodesList) Less(i, j int) bool {
	// This panics, so it shouldn't be called unless all shard
	// names can be converted to integers.
	ii, err := strconv.Atoi(nsnl[i].Name)
	if err != nil {
		panic("bad numeric shard: " + nsnl[i].Name)
	}

	jj, err := strconv.Atoi(nsnl[j].Name)
	if err != nil {
		panic("bad numeric shard" + nsnl[j].Name)
	}
	return ii < jj

}

// Swap is part of sort.Interface
func (nsnl numericShardNodesList) Swap(i, j int) {
	nsnl[i], nsnl[j] = nsnl[j], nsnl[i]
}

type rangeShardNodesList []*ShardNodes

// Len is part of sort.Interface
func (rsnl rangeShardNodesList) Len() int {
	return len(rsnl)
}

// Less is part of sort.Interface
func (rsnl rangeShardNodesList) Less(i, j int) bool {
	return rsnl[i].Name < rsnl[j].Name
}

// Swap is part of sort.Interface
func (rsnl rangeShardNodesList) Swap(i, j int) {
	rsnl[i], rsnl[j] = rsnl[j], rsnl[i]
}

// KeyspaceNodes represents all tablet nodes in a keyspace.
type KeyspaceNodes struct {
	ShardNodes []*ShardNodes // sorted by shard name
	ServedFrom map[topo.TabletType]string
}

func newKeyspaceNodes() *KeyspaceNodes {
	return &KeyspaceNodes{
		ServedFrom: make(map[topo.TabletType]string),
	}
}

func (ks *KeyspaceNodes) hasOnlyNumericShardNames() bool {
	for _, shardNodes := range ks.ShardNodes {
		if _, err := strconv.Atoi(shardNodes.Name); err != nil {
			return false
		}
	}
	return true
}

// TabletTypes returns a slice of tablet type names this ks
// contains.
func (ks KeyspaceNodes) TabletTypes() []pb.TabletType {
	var contained []pb.TabletType
	for _, t := range topoproto.AllTabletTypes {
		if ks.HasType(t) {
			contained = append(contained, t)
		}
	}
	return contained
}

// HasType returns true if ks has any tablets with the named type.
func (ks KeyspaceNodes) HasType(tabletType pb.TabletType) bool {
	for _, shardNodes := range ks.ShardNodes {
		for _, tabletNodes := range shardNodes.TabletNodes {
			if tabletNodes.TabletType == tabletType {
				return true
			}
		}
	}
	return false
}

// Topology is the entire set of tablets in the topology.
type Topology struct {
	Assigned map[string]*KeyspaceNodes // indexed by keyspace name
	Idle     []*TabletNode
	Scrap    []*TabletNode
	Partial  bool
}

// DbTopology returns the Topology for the topo server.
func DbTopology(ctx context.Context, ts topo.Server) (*Topology, error) {
	topology := &Topology{
		Assigned: make(map[string]*KeyspaceNodes),
		Idle:     make([]*TabletNode, 0),
		Scrap:    make([]*TabletNode, 0),
		Partial:  false,
	}

	tabletInfos, err := GetAllTabletsAcrossCells(ctx, ts)
	switch err {
	case nil:
		// we're good, no error
	case topo.ErrPartialResult:
		// we got a partial result
		topology.Partial = true
	default:
		// we got no result at all
		return nil, err
	}

	assigned := make(map[string]map[string][]*TabletNodesByType)
	for _, ti := range tabletInfos {
		tablet := newTabletNodeFromTabletInfo(ti)
		switch ti.Type {
		case pb.TabletType_IDLE:
			topology.Idle = append(topology.Idle, tablet)
		case pb.TabletType_SCRAP:
			topology.Scrap = append(topology.Scrap, tablet)
		default:
			if _, ok := assigned[ti.Keyspace]; !ok {
				assigned[ti.Keyspace] = make(map[string][]*TabletNodesByType)
			}
			var tabletNode *TabletNodesByType
			for _, tabletNodes := range assigned[ti.Keyspace][ti.Shard] {
				if tabletNodes.TabletType == ti.Type {
					tabletNode = tabletNodes
					break
				}
			}
			if tabletNode == nil {
				tabletNode = &TabletNodesByType{
					TabletType: ti.Type,
				}
				assigned[ti.Keyspace][ti.Shard] = append(assigned[ti.Keyspace][ti.Shard], tabletNode)
			}
			tabletNode.Nodes = append(tabletNode.Nodes, tablet)
		}
	}

	for keyspace, shardMap := range assigned {
		kn := newKeyspaceNodes()
		for shard, nodes := range shardMap {
			kn.ShardNodes = append(kn.ShardNodes, &ShardNodes{
				Name:        shard,
				TabletNodes: nodes,
			})
		}
		if kn.hasOnlyNumericShardNames() {
			sort.Sort(numericShardNodesList(kn.ShardNodes))
		} else {
			sort.Sort(rangeShardNodesList(kn.ShardNodes))
		}
		topology.Assigned[keyspace] = kn
	}
	return topology, nil
}

// ServingGraph contains the representation of the serving graph
// for a given cell.
type ServingGraph struct {
	Cell      string
	Keyspaces map[string]*KeyspaceNodes // indexed by keyspace name
	Errors    []string                  // collected during creation
}

// DbServingGraph returns the ServingGraph for the given cell.
func DbServingGraph(ctx context.Context, ts topo.Server, cell string) (servingGraph *ServingGraph) {
	servingGraph = &ServingGraph{
		Cell:      cell,
		Keyspaces: make(map[string]*KeyspaceNodes),
	}
	rec := concurrency.AllErrorRecorder{}

	keyspaces, err := ts.GetSrvKeyspaceNames(ctx, cell)
	if err != nil {
		servingGraph.Errors = append(servingGraph.Errors, fmt.Sprintf("GetSrvKeyspaceNames failed: %v", err))
		return
	}
	wg := sync.WaitGroup{}
	servingTypes := []topo.TabletType{topo.TYPE_MASTER, topo.TYPE_REPLICA, topo.TYPE_RDONLY}
	for _, keyspace := range keyspaces {
		kn := newKeyspaceNodes()
		servingGraph.Keyspaces[keyspace] = kn
		wg.Add(1)
		go func(keyspace string, kn *KeyspaceNodes) {
			defer wg.Done()

			ks, err := ts.GetSrvKeyspace(ctx, cell, keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetSrvKeyspace(%v, %v) failed: %v", cell, keyspace, err))
				return
			}
			if len(ks.ServedFrom) > 0 {
				kn.ServedFrom = make(map[topo.TabletType]string)
				for _, sf := range ks.ServedFrom {
					kn.ServedFrom[topo.ProtoToTabletType(sf.TabletType)] = sf.Keyspace
				}
			}

			displayedShards := make(map[string]bool)
			for _, partitionTabletType := range servingTypes {
				kp := topoproto.SrvKeyspaceGetPartition(ks, topo.TabletTypeToProto(partitionTabletType))
				if kp == nil {
					continue
				}
				for _, srvShard := range kp.ShardReferences {
					shard := srvShard.Name
					if displayedShards[shard] {
						continue
					}
					displayedShards[shard] = true

					sn := &ShardNodes{
						Name: shard,
					}
					kn.ShardNodes = append(kn.ShardNodes, sn)
					wg.Add(1)
					go func(shard string, sn *ShardNodes) {
						defer wg.Done()
						tabletTypes, err := ts.GetSrvTabletTypesPerShard(ctx, cell, keyspace, shard)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetSrvTabletTypesPerShard(%v, %v, %v) failed: %v", cell, keyspace, shard, err))
							return
						}
						for _, tabletType := range tabletTypes {
							endPoints, _, err := ts.GetEndPoints(ctx, cell, keyspace, shard, tabletType)
							if err != nil {
								rec.RecordError(fmt.Errorf("GetEndPoints(%v, %v, %v, %v) failed: %v", cell, keyspace, shard, tabletType, err))
								continue
							}
							for _, endPoint := range endPoints.Entries {
								var tabletNode *TabletNodesByType
								for _, t := range sn.TabletNodes {
									if t.TabletType == tabletType {
										tabletNode = t
										break
									}
								}
								if tabletNode == nil {
									tabletNode = &TabletNodesByType{
										TabletType: tabletType,
									}
									sn.TabletNodes = append(sn.TabletNodes, tabletNode)
								}
								tabletNode.Nodes = append(tabletNode.Nodes, newTabletNodeFromEndPoint(endPoint, cell))
							}
						}
					}(shard, sn)
				}
			}
		}(keyspace, kn)
	}
	wg.Wait()
	servingGraph.Errors = rec.ErrorStrings()
	return
}
<commit_msg>Removing a couple usages of old topo.TabletType.<commit_after>package topotools

import (
	"fmt"
	"net"
	"sort"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/net/context"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/netutil"
	"github.com/youtube/vitess/go/vt/concurrency"
	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/topo/topoproto"

	pb "github.com/youtube/vitess/go/vt/proto/topodata"
)

// TabletNode is the representation of a tablet in the db topology.
// It can be constructed from a Tablet object, or from an EndPoint.
type TabletNode struct {
	Host  string
	Alias *pb.TabletAlias
	Port  int32
}

// ShortName returns a displayable representation of the host name.
// If the host is an IP address instead of a name, it is not shortened.
func (tn *TabletNode) ShortName() string {
	if net.ParseIP(tn.Host) != nil {
		return netutil.JoinHostPort(tn.Host, tn.Port)
	}

	hostPart := strings.SplitN(tn.Host, ".", 2)[0]
	if tn.Port == 0 {
		return hostPart
	}
	return netutil.JoinHostPort(hostPart, tn.Port)
}

func newTabletNodeFromTabletInfo(ti *topo.TabletInfo) *TabletNode {
	if err := topo.TabletValidatePortMap(ti.Tablet); err != nil {
		log.Errorf("ValidatePortmap(%v): %v", ti.Alias, err)
	}
	return &TabletNode{
		Host:  ti.Hostname,
		Port:  ti.PortMap["vt"],
		Alias: ti.Alias,
	}
}

func newTabletNodeFromEndPoint(ep *pb.EndPoint, cell string) *TabletNode {
	return &TabletNode{
		Host: ep.Host,
		Alias: &pb.TabletAlias{
			Uid:  ep.Uid,
			Cell: cell,
		},
		Port: ep.PortMap[topo.DefaultPortName],
	}
}

// TabletNodesByType maps tablet types to slices of tablet nodes.
type TabletNodesByType struct {
	TabletType pb.TabletType
	Nodes      []*TabletNode
}

// ShardNodes represents all tablet nodes for a shard, indexed by tablet type.
type ShardNodes struct {
	Name        string
	TabletNodes []*TabletNodesByType
	ServedTypes []pb.TabletType
	Tag         interface{} // Tag is an arbitrary value manageable by a plugin.
}

type numericShardNodesList []*ShardNodes

// Len is part of sort.Interface
func (nsnl numericShardNodesList) Len() int {
	return len(nsnl)
}

// Less is part of sort.Interface
func (nsnl numericShardNodesList) Less(i, j int) bool {
	// This panics, so it shouldn't be called unless all shard
	// names can be converted to integers.
	ii, err := strconv.Atoi(nsnl[i].Name)
	if err != nil {
		panic("bad numeric shard: " + nsnl[i].Name)
	}

	jj, err := strconv.Atoi(nsnl[j].Name)
	if err != nil {
		panic("bad numeric shard" + nsnl[j].Name)
	}
	return ii < jj

}

// Swap is part of sort.Interface
func (nsnl numericShardNodesList) Swap(i, j int) {
	nsnl[i], nsnl[j] = nsnl[j], nsnl[i]
}

type rangeShardNodesList []*ShardNodes

// Len is part of sort.Interface
func (rsnl rangeShardNodesList) Len() int {
	return len(rsnl)
}

// Less is part of sort.Interface
func (rsnl rangeShardNodesList) Less(i, j int) bool {
	return rsnl[i].Name < rsnl[j].Name
}

// Swap is part of sort.Interface
func (rsnl rangeShardNodesList) Swap(i, j int) {
	rsnl[i], rsnl[j] = rsnl[j], rsnl[i]
}

// KeyspaceNodes represents all tablet nodes in a keyspace.
type KeyspaceNodes struct {
	ShardNodes []*ShardNodes // sorted by shard name
	ServedFrom map[string]string
}

func newKeyspaceNodes() *KeyspaceNodes {
	return &KeyspaceNodes{
		ServedFrom: make(map[string]string),
	}
}

func (ks *KeyspaceNodes) hasOnlyNumericShardNames() bool {
	for _, shardNodes := range ks.ShardNodes {
		if _, err := strconv.Atoi(shardNodes.Name); err != nil {
			return false
		}
	}
	return true
}

// TabletTypes returns a slice of tablet type names this ks
// contains.
func (ks KeyspaceNodes) TabletTypes() []pb.TabletType {
	var contained []pb.TabletType
	for _, t := range topoproto.AllTabletTypes {
		if ks.HasType(t) {
			contained = append(contained, t)
		}
	}
	return contained
}

// HasType returns true if ks has any tablets with the named type.
func (ks KeyspaceNodes) HasType(tabletType pb.TabletType) bool {
	for _, shardNodes := range ks.ShardNodes {
		for _, tabletNodes := range shardNodes.TabletNodes {
			if tabletNodes.TabletType == tabletType {
				return true
			}
		}
	}
	return false
}

// Topology is the entire set of tablets in the topology.
type Topology struct {
	Assigned map[string]*KeyspaceNodes // indexed by keyspace name
	Idle     []*TabletNode
	Scrap    []*TabletNode
	Partial  bool
}

// DbTopology returns the Topology for the topo server.
func DbTopology(ctx context.Context, ts topo.Server) (*Topology, error) {
	topology := &Topology{
		Assigned: make(map[string]*KeyspaceNodes),
		Idle:     make([]*TabletNode, 0),
		Scrap:    make([]*TabletNode, 0),
		Partial:  false,
	}

	tabletInfos, err := GetAllTabletsAcrossCells(ctx, ts)
	switch err {
	case nil:
		// we're good, no error
	case topo.ErrPartialResult:
		// we got a partial result
		topology.Partial = true
	default:
		// we got no result at all
		return nil, err
	}

	assigned := make(map[string]map[string][]*TabletNodesByType)
	for _, ti := range tabletInfos {
		tablet := newTabletNodeFromTabletInfo(ti)
		switch ti.Type {
		case pb.TabletType_IDLE:
			topology.Idle = append(topology.Idle, tablet)
		case pb.TabletType_SCRAP:
			topology.Scrap = append(topology.Scrap, tablet)
		default:
			if _, ok := assigned[ti.Keyspace]; !ok {
				assigned[ti.Keyspace] = make(map[string][]*TabletNodesByType)
			}
			var tabletNode *TabletNodesByType
			for _, tabletNodes := range assigned[ti.Keyspace][ti.Shard] {
				if tabletNodes.TabletType == ti.Type {
					tabletNode = tabletNodes
					break
				}
			}
			if tabletNode == nil {
				tabletNode = &TabletNodesByType{
					TabletType: ti.Type,
				}
				assigned[ti.Keyspace][ti.Shard] = append(assigned[ti.Keyspace][ti.Shard], tabletNode)
			}
			tabletNode.Nodes = append(tabletNode.Nodes, tablet)
		}
	}

	for keyspace, shardMap := range assigned {
		kn := newKeyspaceNodes()
		for shard, nodes := range shardMap {
			kn.ShardNodes = append(kn.ShardNodes, &ShardNodes{
				Name:        shard,
				TabletNodes: nodes,
			})
		}
		if kn.hasOnlyNumericShardNames() {
			sort.Sort(numericShardNodesList(kn.ShardNodes))
		} else {
			sort.Sort(rangeShardNodesList(kn.ShardNodes))
		}
		topology.Assigned[keyspace] = kn
	}
	return topology, nil
}

// ServingGraph contains the representation of the serving graph
// for a given cell.
type ServingGraph struct {
	Cell      string
	Keyspaces map[string]*KeyspaceNodes // indexed by keyspace name
	Errors    []string                  // collected during creation
}

// DbServingGraph returns the ServingGraph for the given cell.
func DbServingGraph(ctx context.Context, ts topo.Server, cell string) (servingGraph *ServingGraph) {
	servingGraph = &ServingGraph{
		Cell:      cell,
		Keyspaces: make(map[string]*KeyspaceNodes),
	}
	rec := concurrency.AllErrorRecorder{}

	keyspaces, err := ts.GetSrvKeyspaceNames(ctx, cell)
	if err != nil {
		servingGraph.Errors = append(servingGraph.Errors, fmt.Sprintf("GetSrvKeyspaceNames failed: %v", err))
		return
	}
	wg := sync.WaitGroup{}
	servingTypes := []pb.TabletType{pb.TabletType_MASTER, pb.TabletType_REPLICA, pb.TabletType_RDONLY}
	for _, keyspace := range keyspaces {
		kn := newKeyspaceNodes()
		servingGraph.Keyspaces[keyspace] = kn
		wg.Add(1)
		go func(keyspace string, kn *KeyspaceNodes) {
			defer wg.Done()

			ks, err := ts.GetSrvKeyspace(ctx, cell, keyspace)
			if err != nil {
				rec.RecordError(fmt.Errorf("GetSrvKeyspace(%v, %v) failed: %v", cell, keyspace, err))
				return
			}
			for _, sf := range ks.ServedFrom {
				kn.ServedFrom[strings.ToLower(sf.TabletType.String())] = sf.Keyspace
			}

			displayedShards := make(map[string]bool)
			for _, partitionTabletType := range servingTypes {
				kp := topoproto.SrvKeyspaceGetPartition(ks, partitionTabletType)
				if kp == nil {
					continue
				}
				for _, srvShard := range kp.ShardReferences {
					shard := srvShard.Name
					if displayedShards[shard] {
						continue
					}
					displayedShards[shard] = true

					sn := &ShardNodes{
						Name: shard,
					}
					kn.ShardNodes = append(kn.ShardNodes, sn)
					wg.Add(1)
					go func(shard string, sn *ShardNodes) {
						defer wg.Done()
						tabletTypes, err := ts.GetSrvTabletTypesPerShard(ctx, cell, keyspace, shard)
						if err != nil {
							rec.RecordError(fmt.Errorf("GetSrvTabletTypesPerShard(%v, %v, %v) failed: %v", cell, keyspace, shard, err))
							return
						}
						for _, tabletType := range tabletTypes {
							endPoints, _, err := ts.GetEndPoints(ctx, cell, keyspace, shard, tabletType)
							if err != nil {
								rec.RecordError(fmt.Errorf("GetEndPoints(%v, %v, %v, %v) failed: %v", cell, keyspace, shard, tabletType, err))
								continue
							}
							for _, endPoint := range endPoints.Entries {
								var tabletNode *TabletNodesByType
								for _, t := range sn.TabletNodes {
									if t.TabletType == tabletType {
										tabletNode = t
										break
									}
								}
								if tabletNode == nil {
									tabletNode = &TabletNodesByType{
										TabletType: tabletType,
									}
									sn.TabletNodes = append(sn.TabletNodes, tabletNode)
								}
								tabletNode.Nodes = append(tabletNode.Nodes, newTabletNodeFromEndPoint(endPoint, cell))
							}
						}
					}(shard, sn)
				}
			}
		}(keyspace, kn)
	}
	wg.Wait()
	servingGraph.Errors = rec.ErrorStrings()
	return
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package symtab

import (
	"bytes"
	"debug/dwarf"
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"fmt"
	"io/ioutil"
)

// SymbolTable allows for mapping between symbols and their addresses.
type SymbolTable struct {
	data *dwarf.Data
}

// New creates a new symbol table based on the debug info
// read from the specified file.
func New(filename string) (*SymbolTable, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	r := bytes.NewReader(b)

	// First try ELF
	ef, err := elf.NewFile(r)
	if err == nil {
		d, err := ef.DWARF()
		if err != nil {
			return nil, err
		}
		return &SymbolTable{d}, nil
	}

	// then Mach-O
	mf, err := macho.NewFile(r)
	if err == nil {
		d, err := mf.DWARF()
		if err != nil {
			return nil, fmt.Errorf("No working DWARF: %v", err)
		}
		return &SymbolTable{d}, nil
	}

	// finally try Windows PE format
	pf, err := pe.NewFile(r)
	if err == nil {
		d, err := pf.DWARF()
		if err != nil {
			return nil, err
		}
		return &SymbolTable{d}, nil
	}

	// Give up, we don't recognize it
	return nil, fmt.Errorf("Unknown file format")
}

// Addr2Sym returns the symbol name for the provided address.
func (s *SymbolTable) Addr2Sym(addr uintptr) (string, error) {
	reader := s.data.Reader()
	for {
		e, err := reader.Next()
		if err != nil {
			return "", err
		}

		if e == nil {
			break
		}

		if e.Tag == dwarf.TagSubprogram {
			nf := e.Field[1]
			if nf.Val.(uint64) == uint64(addr) {
				return e.Field[0].Val.(string), nil
			}
		}
	}
	return "", fmt.Errorf("no symbol found at address %x", addr)
}

// Sym2Addr returns the address of the provided symbol name.
func (s *SymbolTable) Sym2Addr(symbol string) (uintptr, error) {
	reader := s.data.Reader()
	for {
		e, err := reader.Next()
		if err != nil {
			return 0, err
		}

		if e == nil {
			break
		}

		if e.Tag == dwarf.TagSubprogram {
			nf := e.Field[0]
			if nf.Attr.String() == "Name" && nf.Val.(string) == symbol {
				addr := e.Field[1].Val.(uint64)
				return uintptr(addr), nil
			}
		}
	}
	return 0, fmt.Errorf("no symbol %q", symbol)
}
<commit_msg>BEAM-3324 improve symtab memory usage<commit_after>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package symtab

import (
	"debug/dwarf"
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"fmt"
	"os"
)

// SymbolTable allows for mapping between symbols and their addresses.
type SymbolTable struct {
	data *dwarf.Data
}

// New creates a new symbol table based on the debug info
// read from the specified file.
func New(filename string) (*SymbolTable, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	// First try ELF
	ef, err := elf.NewFile(f)
	if err == nil {
		d, err := ef.DWARF()
		if err != nil {
			return nil, err
		}
		return &SymbolTable{d}, nil
	}

	// then Mach-O
	mf, err := macho.NewFile(f)
	if err == nil {
		d, err := mf.DWARF()
		if err != nil {
			return nil, fmt.Errorf("No working DWARF: %v", err)
		}
		return &SymbolTable{d}, nil
	}

	// finally try Windows PE format
	pf, err := pe.NewFile(f)
	if err == nil {
		d, err := pf.DWARF()
		if err != nil {
			return nil, err
		}
		return &SymbolTable{d}, nil
	}

	// Give up, we don't recognize it
	return nil, fmt.Errorf("Unknown file format")
}

// Addr2Sym returns the symbol name for the provided address.
func (s *SymbolTable) Addr2Sym(addr uintptr) (string, error) {
	reader := s.data.Reader()
	for {
		e, err := reader.Next()
		if err != nil {
			return "", err
		}

		if e == nil {
			break
		}

		if e.Tag == dwarf.TagSubprogram {
			nf := e.Field[1]
			if nf.Val.(uint64) == uint64(addr) {
				return e.Field[0].Val.(string), nil
			}
		}
	}
	return "", fmt.Errorf("no symbol found at address %x", addr)
}

// Sym2Addr returns the address of the provided symbol name.
func (s *SymbolTable) Sym2Addr(symbol string) (uintptr, error) {
	reader := s.data.Reader()
	for {
		e, err := reader.Next()
		if err != nil {
			return 0, err
		}

		if e == nil {
			break
		}

		if e.Tag == dwarf.TagSubprogram {
			nf := e.Field[0]
			if nf.Attr.String() == "Name" && nf.Val.(string) == symbol {
				addr := e.Field[1].Val.(uint64)
				return uintptr(addr), nil
			}
		}
	}
	return 0, fmt.Errorf("no symbol %q", symbol)
}
<|endoftext|>


<commit_before>package ecs

import "github.com/denverdino/aliyungo/common"

type DescribeInstanceTypesArgs struct {
	InstanceTypeFamily string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancetypeitemtype
type InstanceTypeItemType struct {
	InstanceTypeId     string
	CpuCoreCount       int
	MemorySize         float64
	InstanceTypeFamily string
}

type DescribeInstanceTypesResponse struct {
	common.Response
	InstanceTypes struct {
		InstanceType []InstanceTypeItemType
	}
}

// DescribeInstanceTypes describes all instance types
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/other&describeinstancetypes
func (client *Client) DescribeInstanceTypes() (instanceTypes []InstanceTypeItemType, err error) {
	response := DescribeInstanceTypesResponse{}

	err = client.Invoke("DescribeInstanceTypes", &DescribeInstanceTypesArgs{}, &response)

	if err != nil {
		return []InstanceTypeItemType{}, err
	}
	return response.InstanceTypes.InstanceType, nil

}

// support user args
func (client *Client) DescribeInstanceTypesNew(args *DescribeInstanceTypesArgs) (instanceTypes []InstanceTypeItemType, err error) {
	response := DescribeInstanceTypesResponse{}

	err = client.Invoke("DescribeInstanceTypes", args, &response)

	if err != nil {
		return []InstanceTypeItemType{}, err
	}
	return response.InstanceTypes.InstanceType, nil

}
<commit_msg>add api DescribeInstanceTypeFamilies<commit_after>package ecs

import "github.com/denverdino/aliyungo/common"

type DescribeInstanceTypesArgs struct {
	InstanceTypeFamily string
}

//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancetypeitemtype
type InstanceTypeItemType struct {
	InstanceTypeId     string
	CpuCoreCount       int
	MemorySize         float64
	InstanceTypeFamily string
}

type DescribeInstanceTypesResponse struct {
	common.Response
	InstanceTypes struct {
		InstanceType []InstanceTypeItemType
	}
}

// DescribeInstanceTypes describes all instance types
//
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/other&describeinstancetypes
func (client *Client) DescribeInstanceTypes() (instanceTypes []InstanceTypeItemType, err error) {
	response := DescribeInstanceTypesResponse{}

	err = client.Invoke("DescribeInstanceTypes", &DescribeInstanceTypesArgs{}, &response)

	if err != nil {
		return []InstanceTypeItemType{}, err
	}
	return response.InstanceTypes.InstanceType, nil

}

// support user args
func (client *Client) DescribeInstanceTypesNew(args *DescribeInstanceTypesArgs) (instanceTypes []InstanceTypeItemType, err error) {
	response := DescribeInstanceTypesResponse{}

	err = client.Invoke("DescribeInstanceTypes", args, &response)

	if err != nil {
		return []InstanceTypeItemType{}, err
	}
	return response.InstanceTypes.InstanceType, nil

}

type DescribeInstanceTypeFamiliesArgs struct {
	RegionId   common.Region
	Generation string
}

type InstanceTypeFamilies struct {
	InstanceTypeFamily []InstanceTypeFamily
}

type InstanceTypeFamily struct {
	InstanceTypeFamilyId string
	Generation           string
}

type DescribeInstanceTypeFamiliesResponse struct {
	common.Response

	InstanceTypeFamilies InstanceTypeFamilies
}

func (client *Client) DescribeInstanceTypeFamilies(args *DescribeInstanceTypeFamiliesArgs) (*DescribeInstanceTypeFamiliesResponse, error) {
	response := &DescribeInstanceTypeFamiliesResponse{}

	err := client.Invoke("DescribeInstanceTypeFamilies", args, response)
	if err != nil {
		return nil, err
	}

	return response, nil
}
<|endoftext|>


<commit_before>package etcd

import (
	"errors"
	"strings"
	"time"

	goetcd "github.com/coreos/go-etcd/etcd"
)

// Client is a wrapper around the etcd client
type Client struct {
	client *goetcd.Client
}

// NewEtcdClient returns an *etcd.Client with a connection to named machines.
// It returns an error if a connection to the cluster cannot be made.
func NewEtcdClient(machines []string, cert, key string, caCert string) (*Client, error) {
	var c *goetcd.Client
	var err error
	if cert != "" && key != "" {
		c, err = goetcd.NewTLSClient(machines, cert, key, caCert)
		if err != nil {
			return &Client{c}, err
		}
	} else {
		c = goetcd.NewClient(machines)
	}
	// Configure the DialTimeout, since 1 second is often too short
	c.SetDialTimeout(time.Duration(3) * time.Second)
	success := c.SetCluster(machines)
	if !success {
		return &Client{c}, errors.New("cannot connect to etcd cluster: " + strings.Join(machines, ","))
	}
	return &Client{c}, nil
}

// GetValues queries etcd for keys prefixed by prefix.
func (c *Client) GetValues(keys []string) (map[string]string, error) {
	vars := make(map[string]string)
	for _, key := range keys {
		resp, err := c.client.Get(key, true, true)
		if err != nil {
			return vars, err
		}
		err = nodeWalk(resp.Node, vars)
		if err != nil {
			return vars, err
		}
	}
	return vars, nil
}

// nodeWalk recursively descends nodes, updating vars.
func nodeWalk(node *goetcd.Node, vars map[string]string) error {
	if node != nil {
		key := node.Key
		if !node.Dir {
			vars[key] = node.Value
		} else {
			for _, node := range node.Nodes {
				nodeWalk(node, vars)
			}
		}
	}
	return nil
}

func (c *Client) WatchPrefix(prefix string, waitIndex uint64, stopChan chan bool) (uint64, error) {
	if waitIndex == 0 {
		resp, err := c.client.Get(prefix, false, true)
		if err != nil {
			return 0, err
		}
		return resp.EtcdIndex, nil
	}
	resp, err := c.client.Watch(prefix, waitIndex+1, true, nil, stopChan)
	return resp.Node.ModifiedIndex, err
}
<commit_msg>backend etcd: avoid nil response by checking etcd error<commit_after>package etcd

import (
	"errors"
	"strings"
	"time"

	goetcd "github.com/coreos/go-etcd/etcd"
)

// Client is a wrapper around the etcd client
type Client struct {
	client *goetcd.Client
}

// NewEtcdClient returns an *etcd.Client with a connection to named machines.
// It returns an error if a connection to the cluster cannot be made.
func NewEtcdClient(machines []string, cert, key string, caCert string) (*Client, error) {
	var c *goetcd.Client
	var err error
	if cert != "" && key != "" {
		c, err = goetcd.NewTLSClient(machines, cert, key, caCert)
		if err != nil {
			return &Client{c}, err
		}
	} else {
		c = goetcd.NewClient(machines)
	}
	// Configure the DialTimeout, since 1 second is often too short
	c.SetDialTimeout(time.Duration(3) * time.Second)
	success := c.SetCluster(machines)
	if !success {
		return &Client{c}, errors.New("cannot connect to etcd cluster: " + strings.Join(machines, ","))
	}
	return &Client{c}, nil
}

// GetValues queries etcd for keys prefixed by prefix.
func (c *Client) GetValues(keys []string) (map[string]string, error) {
	vars := make(map[string]string)
	for _, key := range keys {
		resp, err := c.client.Get(key, true, true)
		if err != nil {
			return vars, err
		}
		err = nodeWalk(resp.Node, vars)
		if err != nil {
			return vars, err
		}
	}
	return vars, nil
}

// nodeWalk recursively descends nodes, updating vars.
func nodeWalk(node *goetcd.Node, vars map[string]string) error {
	if node != nil {
		key := node.Key
		if !node.Dir {
			vars[key] = node.Value
		} else {
			for _, node := range node.Nodes {
				nodeWalk(node, vars)
			}
		}
	}
	return nil
}

func (c *Client) WatchPrefix(prefix string, waitIndex uint64, stopChan chan bool) (uint64, error) {
	if waitIndex == 0 {
		resp, err := c.client.Get(prefix, false, true)
		if err != nil {
			return 0, err
		}
		return resp.EtcdIndex, nil
	}
	resp, err := c.client.Watch(prefix, waitIndex+1, true, nil, stopChan)
	if err != nil {
		return waitIndex, err
	}
	return resp.Node.ModifiedIndex, err
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

func appDirExists(application *Application, etcd *Etcd) bool {
	return etcd.HasKey("/paus/users/" + application.Username + "/apps/" + application.AppName)
}

func deploy(dockerHost string, application *Application, composeFilePath string) (string, error) {
	var err error

	compose := NewCompose(dockerHost, composeFilePath, application.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to build application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to pull application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to start application. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to web container ID. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	return webContainerId, nil
}

func getSubmodules(repositoryPath string) error {
	dir := filepath.Join(repositoryPath, ".git")

	stat, err := os.Stat(dir)

	if err == nil && stat.IsDir() {
		if e := os.RemoveAll(dir); e != nil {
			return errors.Wrap(e, fmt.Sprintf("Failed to remove %s.", dir))
		}
	}

	cmd := exec.Command("/usr/local/bin/get-submodules")

	if err = RunCommand(cmd); err != nil {
		return errors.Wrap(err, "Failed to get submodules.")
	}

	return nil
}

func injectBuildArgs(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	buildArgsKey := appDirectoryKey + "/build-args/"

	if !etcd.HasKey(buildArgsKey) {
		return nil
	}

	buildArgKeys, err := etcd.List(buildArgsKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get build arg keys.")
	}

	buildArgs := map[string]string{}

	for _, key := range buildArgKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get build arg value. key: %s", key))
		}

		buildArgs[strings.Replace(key, buildArgsKey, "", 1)] = value
	}

	composeFile.InjectBuildArgs(buildArgs)

	return nil
}

func injectEnvironmentVariables(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	envDirectoryKey := appDirectoryKey + "/envs/"

	if !etcd.HasKey(envDirectoryKey) {
		return nil
	}

	envKeys, err := etcd.List(envDirectoryKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get environment variable keys.")
	}

	environmentVariables := map[string]string{}

	for _, key := range envKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get environment variable value. key: %s", key))
		}

		environmentVariables[strings.Replace(key, envDirectoryKey, "", 1)] = value
	}

	composeFile.InjectEnvironmentVariables(environmentVariables)

	return nil
}

func registerApplicationMetadata(application *Application, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+application.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return errors.Wrap(err, "Failed to set revisdion.")
	}

	return nil
}

func registerVulcandInformation(application *Application, baseDomain string, webContainer *Container, etcd *Etcd) error {
	vulcand := NewVulcand(etcd)

	if err := vulcand.SetBackend(application, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	for _, identifier := range []string{application.ProjectName, fmt.Sprintf("%s-%s", application.Username, application.AppName)} {
		if err := vulcand.SetFrontend(application, identifier, baseDomain); err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to set vulcand frontend. identifier: %s", identifier))
		}
	}

	if err := vulcand.SetServer(application, webContainer, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	return nil
}

func removeUnpackedFiles(repositoryPath, newComposeFilePath string) error {
	files, err := ioutil.ReadDir(repositoryPath)

	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("Failed to open %s.", repositoryPath))
	}

	for _, file := range files {
		if filepath.Join(repositoryPath, file.Name()) != newComposeFilePath {
			path := filepath.Join(repositoryPath, file.Name())

			if err = os.RemoveAll(path); err != nil {
				return errors.Wrap(err, fmt.Sprintf("Failed to remove files in %s.", path))
			}
		}
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s.", repositoryPath))
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", errors.Wrap(err, "Failed to iterate tarball.")
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				if err = os.MkdirAll(outPath, 0755); err != nil {
					return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s from tarball.", outPath))
				}
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to copy file contents in %s from tarball.", outPath))
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to create file %s from tarball.", outPath))
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	config, err := LoadConfig()

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	etcd, err := NewEtcd(config.EtcdEndpoint)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	application := ApplicationFromArgs(os.Args[1:])

	if !appDirExists(application, etcd) {
		fmt.Fprintln(os.Stderr, "=====> Application not found: "+application.AppName)
		os.Exit(1)
	}

	repositoryPath, err := unpackReceivedFiles(config.RepositoryDir, application.Username, application.ProjectName, os.Stdin)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = os.Chdir(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to chdir to %s.", repositoryPath)))
		os.Exit(1)
	}

	fmt.Println("=====> Getting submodules ...")

	if err = getSubmodules(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to get submodules. path: %s", repositoryPath)))
		os.Exit(1)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	composeFile, err := NewComposeFile(composeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectBuildArgs(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectEnvironmentVariables(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	composeFile.RewritePortBindings()
	newComposeFilePath := filepath.Join(repositoryPath, "docker-compose-"+strconv.FormatInt(time.Now().Unix(), 10)+".yml")

	if err = composeFile.SaveAs(newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	webContainerId, err := deploy(config.DockerHost, application, newComposeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Application container is launched.")

	webContainer, err := ContainerFromID(config.DockerHost, webContainerId)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Registering metadata ...")

	if err = registerApplicationMetadata(application, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerVulcandInformation(application, config.BaseDomain, webContainer, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	uriScheme, err := etcd.Get("/paus/uri-scheme")

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	urlList := []string{
		fmt.Sprintf("%s://%s.%s", uriScheme, application.ProjectName, config.BaseDomain),                      // http://dtan4-docker-service-rails-a7f955b4.pausapp.com
		fmt.Sprintf("%s://%s-%s.%s", uriScheme, application.Username, application.AppName, config.BaseDomain), // http://dtan4-docker-service-rails.pausapp.com
	}

	fmt.Println("=====> " + application.Repository + " was successfully deployed at:")

	for _, url := range urlList {
		fmt.Println("         " + url)
	}

	if err = removeUnpackedFiles(repositoryPath, newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Use string concatenation<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

func appDirExists(application *Application, etcd *Etcd) bool {
	return etcd.HasKey("/paus/users/" + application.Username + "/apps/" + application.AppName)
}

func deploy(dockerHost string, application *Application, composeFilePath string) (string, error) {
	var err error

	compose := NewCompose(dockerHost, composeFilePath, application.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to build application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to pull application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to start application. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to web container ID. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	return webContainerId, nil
}

func getSubmodules(repositoryPath string) error {
	dir := filepath.Join(repositoryPath, ".git")

	stat, err := os.Stat(dir)

	if err == nil && stat.IsDir() {
		if e := os.RemoveAll(dir); e != nil {
			return errors.Wrap(e, fmt.Sprintf("Failed to remove %s.", dir))
		}
	}

	cmd := exec.Command("/usr/local/bin/get-submodules")

	if err = RunCommand(cmd); err != nil {
		return errors.Wrap(err, "Failed to get submodules.")
	}

	return nil
}

func injectBuildArgs(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	buildArgsKey := appDirectoryKey + "/build-args/"

	if !etcd.HasKey(buildArgsKey) {
		return nil
	}

	buildArgKeys, err := etcd.List(buildArgsKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get build arg keys.")
	}

	buildArgs := map[string]string{}

	for _, key := range buildArgKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get build arg value. key: %s", key))
		}

		buildArgs[strings.Replace(key, buildArgsKey, "", 1)] = value
	}

	composeFile.InjectBuildArgs(buildArgs)

	return nil
}

func injectEnvironmentVariables(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	envDirectoryKey := appDirectoryKey + "/envs/"

	if !etcd.HasKey(envDirectoryKey) {
		return nil
	}

	envKeys, err := etcd.List(envDirectoryKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get environment variable keys.")
	}

	environmentVariables := map[string]string{}

	for _, key := range envKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get environment variable value. key: %s", key))
		}

		environmentVariables[strings.Replace(key, envDirectoryKey, "", 1)] = value
	}

	composeFile.InjectEnvironmentVariables(environmentVariables)

	return nil
}

func registerApplicationMetadata(application *Application, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+application.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return errors.Wrap(err, "Failed to set revisdion.")
	}

	return nil
}

func registerVulcandInformation(application *Application, baseDomain string, webContainer *Container, etcd *Etcd) error {
	vulcand := NewVulcand(etcd)

	if err := vulcand.SetBackend(application, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	for _, identifier := range []string{application.ProjectName, fmt.Sprintf("%s-%s", application.Username, application.AppName)} {
		if err := vulcand.SetFrontend(application, identifier, baseDomain); err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to set vulcand frontend. identifier: %s", identifier))
		}
	}

	if err := vulcand.SetServer(application, webContainer, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	return nil
}

func removeUnpackedFiles(repositoryPath, newComposeFilePath string) error {
	files, err := ioutil.ReadDir(repositoryPath)

	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("Failed to open %s.", repositoryPath))
	}

	for _, file := range files {
		if filepath.Join(repositoryPath, file.Name()) != newComposeFilePath {
			path := filepath.Join(repositoryPath, file.Name())

			if err = os.RemoveAll(path); err != nil {
				return errors.Wrap(err, fmt.Sprintf("Failed to remove files in %s.", path))
			}
		}
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s.", repositoryPath))
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", errors.Wrap(err, "Failed to iterate tarball.")
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				if err = os.MkdirAll(outPath, 0755); err != nil {
					return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s from tarball.", outPath))
				}
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to copy file contents in %s from tarball.", outPath))
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to create file %s from tarball.", outPath))
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	config, err := LoadConfig()

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	etcd, err := NewEtcd(config.EtcdEndpoint)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	application := ApplicationFromArgs(os.Args[1:])

	if !appDirExists(application, etcd) {
		fmt.Fprintln(os.Stderr, "=====> Application not found: "+application.AppName)
		os.Exit(1)
	}

	repositoryPath, err := unpackReceivedFiles(config.RepositoryDir, application.Username, application.ProjectName, os.Stdin)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = os.Chdir(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to chdir to %s.", repositoryPath)))
		os.Exit(1)
	}

	fmt.Println("=====> Getting submodules ...")

	if err = getSubmodules(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to get submodules. path: %s", repositoryPath)))
		os.Exit(1)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	composeFile, err := NewComposeFile(composeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectBuildArgs(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectEnvironmentVariables(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	composeFile.RewritePortBindings()
	newComposeFilePath := filepath.Join(repositoryPath, "docker-compose-"+strconv.FormatInt(time.Now().Unix(), 10)+".yml")

	if err = composeFile.SaveAs(newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	webContainerId, err := deploy(config.DockerHost, application, newComposeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Application container is launched.")

	webContainer, err := ContainerFromID(config.DockerHost, webContainerId)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Registering metadata ...")

	if err = registerApplicationMetadata(application, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerVulcandInformation(application, config.BaseDomain, webContainer, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	uriScheme, err := etcd.Get("/paus/uri-scheme")

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	urlList := []string{
		uriScheme + "://" + application.ProjectName + "." + config.BaseDomain,
		uriScheme + "://" + application.Username + "." + application.AppName + "." + config.BaseDomain,
	}

	fmt.Println("=====> " + application.Repository + " was successfully deployed at:")

	for _, url := range urlList {
		fmt.Println("         " + url)
	}

	if err = removeUnpackedFiles(repositoryPath, newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package models

import (
	"sync"
	"time"

	"github.com/eaciit/orm"
)

type FunctionalLocation struct {
	sync.RWMutex
	orm.ModelBase          `bson:"-" json:"-"`
	FunctionalLocationCode string `bson:"FunctionalLocationCode" json:"FunctionalLocationCode"`
	Str                    string `bson:"FLDescription" json:"Description"`
	CostCtr                string `bson:"CostCtr" json:"CostCtr"`
	Location               string `bson:"Location" json:"Location"`
	// PIPI                   string `bson:"FLDescription" json:"PIPI"`
	// PInt                   string `bson:"PInt" json:"PInt"`
	// MainWorkCtr            string `bson:"MainWorkCtr" json:"MainWorkCtr"`
	// CatProf                string `bson:"CatProf" json:"CatProf"`
	// SortField              string `bson:"SortField" json:"SortField"`
	// ModelNo                string `bson:"ModelNo" json:"ModelNo"`
	// SerNo                  string `bson:"SerNo" json:"SerNo"`
	// UserStatus             string    `bson:"UserStatus" json:"UserStatus"`
	// A                      string    `bson:"A" json:"A"`
	// ObjectType             string    `bson:"ObjectType" json:"ObjectType"`
	// PG                     string    `bson:"PG" json:"PG"`
	// ManParNo               string    `bson:"ManParNo" json:"ManParNo"`
	// Asset                  string    `bson:"Asset" json:"Asset"`
	// Date                   time.Time `bson:"Date" json:"Date"`
	// AcqValue               string    `bson:"AcqValue" json:"AcqValue"`
	// InvNo                  string    `bson:"InvNo" json:"InvNo"`
	// ConstType              string    `bson:"ConstType" json:"ConstType"`
	// StartFrom              time.Time `bson:"StartFrom" json:"StartFrom"`
	// CreatedOn              time.Time `bson:"CreatedOn" json:"CreatedOn"`
	// SupFunctionalLocation  string    `bson:"SupFunctionalLocation" json:"SupFunctionalLocation"`
}

func (m *FunctionalLocation) TableName() string {
	return "FunctionalLocation"
}

type AnomaliesFunctionalLocation struct {
	sync.RWMutex
	orm.ModelBase          `bson:"-" json:"-"`
	FunctionalLocationCode string    `bson:"FunctionalLocationCode" json:"FunctionalLocationCode"`
	Str                    string    `bson:"FLDescription" json:"Description"`
	CostCtr                string    `bson:"CostCtr" json:"CostCtr"`
	Location               string    `bson:"Location" json:"Location"`
	PIPI                   string    `bson:"FLDescription" json:"PIPI"`
	PInt                   string    `bson:"PInt" json:"PInt"`
	MainWorkCtr            string    `bson:"MainWorkCtr" json:"MainWorkCtr"`
	CatProf                string    `bson:"CatProf" json:"CatProf"`
	SortField              string    `bson:"SortField" json:"SortField"`
	ModelNo                string    `bson:"ModelNo" json:"ModelNo"`
	SerNo                  string    `bson:"SerNo" json:"SerNo"`
	UserStatus             string    `bson:"UserStatus" json:"UserStatus"`
	A                      string    `bson:"A" json:"A"`
	ObjectType             string    `bson:"ObjectType" json:"ObjectType"`
	PG                     string    `bson:"PG" json:"PG"`
	ManParNo               string    `bson:"ManParNo" json:"ManParNo"`
	Asset                  string    `bson:"Asset" json:"Asset"`
	Date                   time.Time `bson:"Date" json:"Date"`
	AcqValue               string    `bson:"AcqValue" json:"AcqValue"`
	InvNo                  string    `bson:"InvNo" json:"InvNo"`
	ConstType              string    `bson:"ConstType" json:"ConstType"`
	StartFrom              time.Time `bson:"StartFrom" json:"StartFrom"`
	CreatedOn              time.Time `bson:"CreatedOn" json:"CreatedOn"`
	SupFunctionalLocation  string    `bson:"SupFunctionalLocation" json:"SupFunctionalLocation"`
}

func (m *AnomaliesFunctionalLocation) TableName() string {
	return "Anomalies_FunctionalLocation"
}
<commit_msg>Fixing functionallocation struct<commit_after>package models

import (
	"sync"
	"time"

	"github.com/eaciit/orm"
)

type FunctionalLocation struct {
	sync.RWMutex
	orm.ModelBase          `bson:"-" json:"-"`
	FunctionalLocationCode string    `bson:"FunctionalLocationCode" json:"FunctionalLocationCode"`
	Str                    string    `bson:"FLDescription" json:"Description"`
	CostCtr                string    `bson:"CostCtr" json:"CostCtr"`
	Location               string    `bson:"Location" json:"Location"`
	PIPI                   string    `bson:"PIPI" json:"PIPI"`
	PInt                   string    `bson:"PInt" json:"PInt"`
	MainWorkCtr            string    `bson:"MainWorkCtr" json:"MainWorkCtr"`
	CatProf                string    `bson:"CatProf" json:"CatProf"`
	SortField              string    `bson:"SortField" json:"SortField"`
	ModelNo                string    `bson:"ModelNo" json:"ModelNo"`
	SerNo                  string    `bson:"SerNo" json:"SerNo"`
	UserStatus             string    `bson:"UserStatus" json:"UserStatus"`
	A                      string    `bson:"A" json:"A"`
	ObjectType             string    `bson:"ObjectType" json:"ObjectType"`
	PG                     string    `bson:"PG" json:"PG"`
	ManParNo               string    `bson:"ManParNo" json:"ManParNo"`
	Asset                  string    `bson:"Asset" json:"Asset"`
	Date                   time.Time `bson:"Date" json:"Date"`
	AcqValue               string    `bson:"AcqValue" json:"AcqValue"`
	InvNo                  string    `bson:"InvNo" json:"InvNo"`
	ConstType              string    `bson:"ConstType" json:"ConstType"`
	StartFrom              time.Time `bson:"StartFrom" json:"StartFrom"`
	CreatedOn              time.Time `bson:"CreatedOn" json:"CreatedOn"`
	SupFunctionalLocation  string    `bson:"SupFunctionalLocation" json:"SupFunctionalLocation"`
}

func (m *FunctionalLocation) TableName() string {
	return "FunctionalLocation"
}

type AnomaliesFunctionalLocation struct {
	sync.RWMutex
	orm.ModelBase          `bson:"-" json:"-"`
	FunctionalLocationCode string    `bson:"FunctionalLocationCode" json:"FunctionalLocationCode"`
	Str                    string    `bson:"FLDescription" json:"Description"`
	CostCtr                string    `bson:"CostCtr" json:"CostCtr"`
	Location               string    `bson:"Location" json:"Location"`
	PIPI                   string    `bson:"FLDescription" json:"PIPI"`
	PInt                   string    `bson:"PInt" json:"PInt"`
	MainWorkCtr            string    `bson:"MainWorkCtr" json:"MainWorkCtr"`
	CatProf                string    `bson:"CatProf" json:"CatProf"`
	SortField              string    `bson:"SortField" json:"SortField"`
	ModelNo                string    `bson:"ModelNo" json:"ModelNo"`
	SerNo                  string    `bson:"SerNo" json:"SerNo"`
	UserStatus             string    `bson:"UserStatus" json:"UserStatus"`
	A                      string    `bson:"A" json:"A"`
	ObjectType             string    `bson:"ObjectType" json:"ObjectType"`
	PG                     string    `bson:"PG" json:"PG"`
	ManParNo               string    `bson:"ManParNo" json:"ManParNo"`
	Asset                  string    `bson:"Asset" json:"Asset"`
	Date                   time.Time `bson:"Date" json:"Date"`
	AcqValue               string    `bson:"AcqValue" json:"AcqValue"`
	InvNo                  string    `bson:"InvNo" json:"InvNo"`
	ConstType              string    `bson:"ConstType" json:"ConstType"`
	StartFrom              time.Time `bson:"StartFrom" json:"StartFrom"`
	CreatedOn              time.Time `bson:"CreatedOn" json:"CreatedOn"`
	SupFunctionalLocation  string    `bson:"SupFunctionalLocation" json:"SupFunctionalLocation"`
}

func (m *AnomaliesFunctionalLocation) TableName() string {
	return "Anomalies_FunctionalLocation"
}
<|endoftext|>


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

package main_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/alecthomas/kingpin.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/petergtz/pegomock/pegomock"

	"testing"
)

func TestPegomock(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pegomock CLI Suite")
}

var _ = Describe("Testing pegomock CLI", func() {

	var (
		packageDir, subPackageDir string
		app                       *kingpin.Application
		origWorkingDir            string
		done                      chan bool = make(chan bool)
	)

	BeforeEach(func() {
		packageDir = filepath.Join(os.Getenv("GOPATH"), "src", "pegomocktest")
		Expect(os.MkdirAll(packageDir, 0755)).To(Succeed())
		subPackageDir = filepath.Join(packageDir, "subpackage")
		Expect(os.MkdirAll(subPackageDir, 0755)).To(Succeed())

		var e error
		origWorkingDir, e = os.Getwd()
		Expect(e).NotTo(HaveOccurred())
		os.Chdir(packageDir)

		Expect(ioutil.WriteFile(
			filepath.Join(packageDir, "mydisplay.go"),
			[]byte("package pegomocktest; type MyDisplay interface {  Show() }"),
			0644)).
			To(Succeed())
		Expect(ioutil.WriteFile(
			filepath.Join(subPackageDir, "subdisplay.go"),
			[]byte("package pegomocktest; type SubDisplay interface {  ShowMe() }"),
			0644)).
			To(Succeed())
		app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
		app.Terminate(func(int) { panic("Unexpected terminate") })
	})

	AfterEach(func() {
		Expect(os.RemoveAll(packageDir)).To(Succeed())
		os.Chdir(origWorkingDir)
	})

	Describe(`"generate" command`, func() {

		Context(`with args "MyDisplay"`, func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				// The rationale behind this is:
				// mocks should always be part of test packages, because we don't
				// want them to be part of the production code.
				// But to be useful, they must still reside in the package, where
				// they are actually used.

				main.Run(cmd("pegomock generate MyDisplay"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context(`with args "pegomocktest/subpackage SubDisplay"`, func() {

			It(`generates a file mock_subdisplay_test.go in "pegomocktest" that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate pegomocktest/subpackage SubDisplay"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_subdisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("with args mydisplay.go", func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate mydisplay.go"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("with args -d mydisplay.go", func() {

			It(`prints out debug information on stdout`, func() {
				var buf bytes.Buffer
				main.Run(cmd("pegomock generate -d mydisplay.go"), &buf, app, done)
				Expect(buf.String()).To(ContainSubstring("- method Show"))
			})
		})

		Context("with too many args", func() {

			It(`reports an error and the usage`, func() {
				var buf bytes.Buffer
				Expect(func() {
					main.Run(cmd("pegomock generate with too many args"), &buf, app, done)
				}).To(Panic())

				Expect(buf.String()).To(ContainSubstring("Please provide exactly 1 interface or 1 package + 1 interface"))
				Expect(buf.String()).To(ContainSubstring("usage"))
			})
		})

	})

	Describe(`"watch" command`, func() {

		AfterEach(func(testDone Done) { done <- true; close(testDone) }, 2)

		Context("with no further action", func() {
			It(`Creates a template file interfaces_to_mock in the current directory`, func() {
				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(func() string { return "interfaces_to_mock" }, "3s").Should(BeAnExistingFile())
			})
		})

		Context("after populating interfaces_to_mock with an actual interface", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				Expect(ioutil.WriteFile(
					filepath.Join(packageDir, "interfaces_to_mock"),
					[]byte("MyDisplay"), 0644)).
					To(Succeed())

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Eventually(func() string { return mockFile }, "3s").Should(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("after populating interfaces_to_mock with a Go file", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				Expect(ioutil.WriteFile(
					filepath.Join(packageDir, "interfaces_to_mock"),
					[]byte("mydisplay.go"), 0644)).
					To(Succeed())

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Eventually(func() string { return mockFile }, "3s").Should(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})
	})

	Context("with some unknown command", func() {
		It(`reports an error and the usage`, func() {
			var buf bytes.Buffer
			kingpin.CommandLine.Terminate(nil)
			kingpin.CommandLine.Writer(&buf)

			main.Run(cmd("pegomock some unknown command"), &buf, app, done)
			Expect(buf.String()).To(ContainSubstring("error"))
		})
	})

})

func cmd(line string) []string {
	return strings.Split(line, " ")
}
<commit_msg>Increase test timeout for app teardown<commit_after>// Copyright 2016 Peter Goetz
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/alecthomas/kingpin.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/petergtz/pegomock/pegomock"

	"testing"
)

func TestPegomock(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Pegomock CLI Suite")
}

var _ = Describe("Testing pegomock CLI", func() {

	var (
		packageDir, subPackageDir string
		app                       *kingpin.Application
		origWorkingDir            string
		done                      chan bool = make(chan bool)
	)

	BeforeEach(func() {
		packageDir = filepath.Join(os.Getenv("GOPATH"), "src", "pegomocktest")
		Expect(os.MkdirAll(packageDir, 0755)).To(Succeed())
		subPackageDir = filepath.Join(packageDir, "subpackage")
		Expect(os.MkdirAll(subPackageDir, 0755)).To(Succeed())

		var e error
		origWorkingDir, e = os.Getwd()
		Expect(e).NotTo(HaveOccurred())
		os.Chdir(packageDir)

		Expect(ioutil.WriteFile(
			filepath.Join(packageDir, "mydisplay.go"),
			[]byte("package pegomocktest; type MyDisplay interface {  Show() }"),
			0644)).
			To(Succeed())
		Expect(ioutil.WriteFile(
			filepath.Join(subPackageDir, "subdisplay.go"),
			[]byte("package pegomocktest; type SubDisplay interface {  ShowMe() }"),
			0644)).
			To(Succeed())
		app = kingpin.New("pegomock", "Generates mocks based on interfaces.")
		app.Terminate(func(int) { panic("Unexpected terminate") })
	})

	AfterEach(func() {
		Expect(os.RemoveAll(packageDir)).To(Succeed())
		os.Chdir(origWorkingDir)
	})

	Describe(`"generate" command`, func() {

		Context(`with args "MyDisplay"`, func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				// The rationale behind this is:
				// mocks should always be part of test packages, because we don't
				// want them to be part of the production code.
				// But to be useful, they must still reside in the package, where
				// they are actually used.

				main.Run(cmd("pegomock generate MyDisplay"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context(`with args "pegomocktest/subpackage SubDisplay"`, func() {

			It(`generates a file mock_subdisplay_test.go in "pegomocktest" that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate pegomocktest/subpackage SubDisplay"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_subdisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("with args mydisplay.go", func() {

			It(`generates a file mock_mydisplay_test.go that contains "package pegomocktest_test"`, func() {
				main.Run(cmd("pegomock generate mydisplay.go"), os.Stdout, app, done)

				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Expect(mockFile).To(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("with args -d mydisplay.go", func() {

			It(`prints out debug information on stdout`, func() {
				var buf bytes.Buffer
				main.Run(cmd("pegomock generate -d mydisplay.go"), &buf, app, done)
				Expect(buf.String()).To(ContainSubstring("- method Show"))
			})
		})

		Context("with too many args", func() {

			It(`reports an error and the usage`, func() {
				var buf bytes.Buffer
				Expect(func() {
					main.Run(cmd("pegomock generate with too many args"), &buf, app, done)
				}).To(Panic())

				Expect(buf.String()).To(ContainSubstring("Please provide exactly 1 interface or 1 package + 1 interface"))
				Expect(buf.String()).To(ContainSubstring("usage"))
			})
		})

	})

	Describe(`"watch" command`, func() {

		AfterEach(func(testDone Done) { done <- true; close(testDone) }, 3)

		Context("with no further action", func() {
			It(`Creates a template file interfaces_to_mock in the current directory`, func() {
				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				Eventually(func() string { return "interfaces_to_mock" }, "3s").Should(BeAnExistingFile())
			})
		})

		Context("after populating interfaces_to_mock with an actual interface", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				Expect(ioutil.WriteFile(
					filepath.Join(packageDir, "interfaces_to_mock"),
					[]byte("MyDisplay"), 0644)).
					To(Succeed())

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Eventually(func() string { return mockFile }, "3s").Should(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})

		Context("after populating interfaces_to_mock with a Go file", func() {
			It(`Eventually creates a file mock_mydisplay_test.go starting with "package pegomocktest_test"`, func() {
				Expect(ioutil.WriteFile(
					filepath.Join(packageDir, "interfaces_to_mock"),
					[]byte("mydisplay.go"), 0644)).
					To(Succeed())

				go main.Run(cmd("pegomock watch"), os.Stdout, app, done)
				mockFile := filepath.Join(packageDir, "mock_mydisplay_test.go")
				Eventually(func() string { return mockFile }, "3s").Should(BeAnExistingFile())
				Expect(ioutil.ReadFile(mockFile)).To(ContainSubstring("package pegomocktest_test"))
			})
		})
	})

	Context("with some unknown command", func() {
		It(`reports an error and the usage`, func() {
			var buf bytes.Buffer
			kingpin.CommandLine.Terminate(nil)
			kingpin.CommandLine.Writer(&buf)

			main.Run(cmd("pegomock some unknown command"), &buf, app, done)
			Expect(buf.String()).To(ContainSubstring("error"))
		})
	})

})

func cmd(line string) []string {
	return strings.Split(line, " ")
}
<|endoftext|>