<commit_before>package utils

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"runtime/debug"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"

	"strings"
)

// Humanize separates string based on capitalizd letters
// e.g. "OrderItem" -> "Order Item"
func HumanizeString(str string) string {
	var human []rune
	for i, l := range str {
		if i > 0 && isUppercase(byte(l)) {
			if i > 0 && !isUppercase(str[i-1]) || i+1 < len(str) && !isUppercase(str[i+1]) {
				human = append(human, rune(' '))
			}
		}
		human = append(human, l)
	}
	return strings.Title(string(human))
}

func isUppercase(char byte) bool {
	return 'A' <= char && char <= 'Z'
}

// ToParamString replaces spaces and separates words (by uppercase letters) with
// underscores in a string, also downcase it
// e.g. ToParamString -> to_param_string, To ParamString -> to_param_string

var upcaseRegexp = regexp.MustCompile("[A-Z]{3,}[a-z]")

func ToParamString(str string) string {
	if len(str) <= 1 {
		return strings.ToLower(str)
	}

	str = upcaseRegexp.ReplaceAllStringFunc(str, func(s string) string {
		return s[0:1] + strings.ToLower(s[1:len(s)-2]) + s[len(s)-2:]
	})

	result := []rune{rune(str[0])}
	for _, l := range str[1:] {
		if rune('A') <= l && l <= rune('Z') {
			if lr := len(result); lr == 0 || (result[lr-1] != '_' && !(rune('A') <= result[lr-1] && result[lr-1] <= rune('Z'))) {
				result = append(result, rune('_'), l)
				continue
			}
		}

		result = append(result, l)
	}

	return strings.ToLower(string(result))
}

// PatchURL updates the query part of the current request url. You can
// access it in template by `patch_url`.
//     patch_url "google.com" "key" "value"
func PatchURL(originalURL string, params ...interface{}) (patchedURL string, err error) {
	url, err := url.Parse(originalURL)
	if err != nil {
		return
	}

	query := url.Query()
	for i := 0; i < len(params)/2; i++ {
		// Check if params is key&value pair
		key := fmt.Sprintf("%v", params[i*2])
		value := fmt.Sprintf("%v", params[i*2+1])

		if value == "" {
			query.Del(key)
		} else {
			query.Set(key, value)
		}
	}

	url.RawQuery = query.Encode()
	patchedURL = url.String()
	return
}

func GetLocale(context *qor.Context) string {
	var locale = context.Request.URL.Query().Get("locale")

	if locale == "" {
		locale = context.Request.Form.Get("locale")
	}

	if locale != "" {
		if context.Writer != nil {
			cookie := http.Cookie{Name: "locale", Value: locale, Expires: time.Now().AddDate(1, 0, 0), Path: "/"}
			http.SetCookie(context.Writer, &cookie)
		}
		return locale
	}

	if locale, err := context.Request.Cookie("locale"); err == nil {
		return locale.Value
	}

	return ""
}

func Stringify(object interface{}) string {
	if obj, ok := object.(interface {
		Stringify() string
	}); ok {
		return obj.Stringify()
	}

	scope := gorm.Scope{Value: object}
	for _, column := range []string{"Name", "Title"} {
		if field, ok := scope.FieldByName(column); ok {
			return fmt.Sprintf("%v", field.Field.Interface())
		}
	}

	if scope.PrimaryKeyZero() {
		return ""
	} else {
		return fmt.Sprintf("%v#%v", scope.GetModelStruct().ModelType.Name(), scope.PrimaryKeyValue())
	}
}

func ParseTagOption(str string) map[string]string {
	tags := strings.Split(str, ";")
	setting := map[string]string{}
	for _, value := range tags {
		v := strings.Split(value, ":")
		k := strings.TrimSpace(strings.ToUpper(v[0]))
		if len(v) == 2 {
			setting[k] = v[1]
		} else {
			setting[k] = k
		}
	}
	return setting
}

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:len(results)]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}

func ExitWithMsg(str string, value ...interface{}) {
	fmt.Printf("\n"+filenameWithLineNum()+"\n"+str+"\n", value...)
	debug.PrintStack()
}
<commit_msg>Fix ToParam for downcase words<commit_after>package utils

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"runtime/debug"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/qor/qor"

	"strings"
)

// Humanize separates string based on capitalizd letters
// e.g. "OrderItem" -> "Order Item"
func HumanizeString(str string) string {
	var human []rune
	for i, l := range str {
		if i > 0 && isUppercase(byte(l)) {
			if i > 0 && !isUppercase(str[i-1]) || i+1 < len(str) && !isUppercase(str[i+1]) {
				human = append(human, rune(' '))
			}
		}
		human = append(human, l)
	}
	return strings.Title(string(human))
}

func isUppercase(char byte) bool {
	return 'A' <= char && char <= 'Z'
}

// ToParamString replaces spaces and separates words (by uppercase letters) with
// underscores in a string, also downcase it
// e.g. ToParamString -> to_param_string, To ParamString -> to_param_string

var upcaseRegexp = regexp.MustCompile("[A-Z]{3,}[a-z]")

func ToParamString(str string) string {
	if len(str) <= 1 {
		return strings.ToLower(str)
	}

	str = strings.Replace(str, " ", "_", -1)
	str = upcaseRegexp.ReplaceAllStringFunc(str, func(s string) string {
		return s[0:1] + strings.ToLower(s[1:len(s)-2]) + s[len(s)-2:]
	})

	result := []rune{rune(str[0])}
	for _, l := range str[1:] {
		if rune('A') <= l && l <= rune('Z') {
			if lr := len(result); lr == 0 || (result[lr-1] != '_' && !(rune('A') <= result[lr-1] && result[lr-1] <= rune('Z'))) {
				result = append(result, rune('_'), l)
				continue
			}
		}

		result = append(result, l)
	}

	return strings.ToLower(string(result))
}

// PatchURL updates the query part of the current request url. You can
// access it in template by `patch_url`.
//     patch_url "google.com" "key" "value"
func PatchURL(originalURL string, params ...interface{}) (patchedURL string, err error) {
	url, err := url.Parse(originalURL)
	if err != nil {
		return
	}

	query := url.Query()
	for i := 0; i < len(params)/2; i++ {
		// Check if params is key&value pair
		key := fmt.Sprintf("%v", params[i*2])
		value := fmt.Sprintf("%v", params[i*2+1])

		if value == "" {
			query.Del(key)
		} else {
			query.Set(key, value)
		}
	}

	url.RawQuery = query.Encode()
	patchedURL = url.String()
	return
}

func GetLocale(context *qor.Context) string {
	var locale = context.Request.URL.Query().Get("locale")

	if locale == "" {
		locale = context.Request.Form.Get("locale")
	}

	if locale != "" {
		if context.Writer != nil {
			cookie := http.Cookie{Name: "locale", Value: locale, Expires: time.Now().AddDate(1, 0, 0), Path: "/"}
			http.SetCookie(context.Writer, &cookie)
		}
		return locale
	}

	if locale, err := context.Request.Cookie("locale"); err == nil {
		return locale.Value
	}

	return ""
}

func Stringify(object interface{}) string {
	if obj, ok := object.(interface {
		Stringify() string
	}); ok {
		return obj.Stringify()
	}

	scope := gorm.Scope{Value: object}
	for _, column := range []string{"Name", "Title"} {
		if field, ok := scope.FieldByName(column); ok {
			return fmt.Sprintf("%v", field.Field.Interface())
		}
	}

	if scope.PrimaryKeyZero() {
		return ""
	} else {
		return fmt.Sprintf("%v#%v", scope.GetModelStruct().ModelType.Name(), scope.PrimaryKeyValue())
	}
}

func ParseTagOption(str string) map[string]string {
	tags := strings.Split(str, ";")
	setting := map[string]string{}
	for _, value := range tags {
		v := strings.Split(value, ":")
		k := strings.TrimSpace(strings.ToUpper(v[0]))
		if len(v) == 2 {
			setting[k] = v[1]
		} else {
			setting[k] = k
		}
	}
	return setting
}

func filenameWithLineNum() string {
	var total = 10
	var results []string
	for i := 2; i < 15; i++ {
		if _, file, line, ok := runtime.Caller(i); ok {
			total--
			results = append(results[:0],
				append(
					[]string{fmt.Sprintf("%v:%v", strings.TrimPrefix(file, os.Getenv("GOPATH")+"src/"), line)},
					results[0:len(results)]...)...)

			if total == 0 {
				return strings.Join(results, "\n")
			}
		}
	}
	return ""
}

func ExitWithMsg(str string, value ...interface{}) {
	fmt.Printf("\n"+filenameWithLineNum()+"\n"+str+"\n", value...)
	debug.PrintStack()
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	"os"
	"image"
	"image/png"
	"image/color"

	_ "image/jpeg"
	_ "image/gif"
)

// ReadStdin reads a png file from standard input.
func ReadStdin() image.Image {
	img, _, _ := image.Decode(os.Stdin)

	return img
}

// WriteStdout writes an Image to standard output.
func WriteStdout(img image.Image) {
	png.Encode(os.Stdout, img)
}

// Warn prints a message to standard error
func Warn(s interface{}) {
	fmt.Fprintln(os.Stderr, s)
}

// NormalisedRGBA returns the RGBA colour channel values of a Color in a
// normalised form.
func NormalisedRGBA(c color.Color) (rn, gn, bn, an uint32) {
	d := color.NRGBAModel.Convert(c).(color.NRGBA)
	r := d.R; g := d.G; b := d.B; a := d.A

	// Need to do some crazy type conversions first
	rn = uint32(uint8(r))
	gn = uint32(uint8(g))
	bn = uint32(uint8(b))
	an = uint32(uint8(a))

	return
}

// NormalisedRGBAf returns the RGBA colour channel values as floating point
// numbers with values from 0 to 255.
func NormalisedRGBAf(c color.Color) (rn, gn, bn, an float64) {
	r, g, b, a := NormalisedRGBA(c)

	rn = float64(r)
	gn = float64(g)
	bn = float64(b)
	an = float64(a)

	return
}

// RatioRGBA returns the RGBA colour channel values as floating point numbers
// with values from 0 to 1.
func RatioRGBA(c color.Color) (rn, gn, bn, an float64) {
	r, g, b, a := NormalisedRGBAf(c)

	rn = r / 255
	gn = g / 255
	bn = b / 255
	an = a / 255

	return
}

// Truncate takes a colour channel value and forces it into the range 0 to 255
// by setting any value below 0 to 0 and and any above 255 to 255.
func Truncate(n uint32) uint32 {
	if n < 0 { return 0 } else if n > 255 { return 255 }
	return n
}

// Truanctef is identical to Truncate but takes and returns a float64.
func Truncatef(n float64) float64 {
	if n < 0 { return 0 } else if n > 255 { return 255 }
	return n
}

// Closeness calculates the "closeness" of two colours by finding the sum of
// differences in each colour channel.
func Closeness(one, two color.Color) uint32 {
	a, b, c, d := NormalisedRGBA(one)
	w, x, y, z := NormalisedRGBA(two)

	return (a - w) + (b - x) + (c - y) + (d - z)
}

// Average takes a list of colours and returns the average.
func Average(cs... color.Color) color.Color {
	var red, green, blue, alpha uint32
	red = 0; green = 0; blue = 0; alpha = 0

	for i := 0; i < len(cs); i++ {
		r, g, b, a := NormalisedRGBA(cs[i])

		red += r; green += g; blue += b; alpha += a
	}

	return color.NRGBA{
		uint8(red   / uint32(len(cs))),
		uint8(green / uint32(len(cs))),
		uint8(blue  / uint32(len(cs))),
		uint8(alpha / uint32(len(cs))),
	}
}

// Min returns the smallest value in the list of uint32s given.
func Min(ns... uint32) (n uint32) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] < n {
			n = ns[i]
		}
	}
	return
}

// Minf returns the smallest value in the list of float64s given.
func Minf(ns... float64) (n float64) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] < n {
			n = ns[i]
		}
	}
	return
}

// Max returns the largest value in the list of uint32s given.
func Max(ns... uint32) (n uint32) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] > n {
			n = ns[i]
		}
	}
	return
}

// Maxf returns the largest value in the list of float64s given.
func Maxf(ns... float64) (n float64) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] > n {
			n = ns[i]
		}
	}
	return
}

// EachPixel iterates through each pixel of the Image applies the function given
// and draws the result to a new Image which is then returned.
func EachPixel(img image.Image, f func(c color.Color) color.Color) image.Image {
	b := img.Bounds()
	o := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))

	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			result := f(img.At(x, y))
			o.Set(x, y, result)
		}
	}

	return o
}
<commit_msg>Fix ReadStdin() docstring<commit_after>package utils

import (
	"fmt"
	"os"
	"image"
	"image/png"
	"image/color"

	_ "image/jpeg"
	_ "image/gif"
)

// ReadStdin reads an image file from standard input.
func ReadStdin() image.Image {
	img, _, _ := image.Decode(os.Stdin)

	return img
}

// WriteStdout writes an Image to standard output.
func WriteStdout(img image.Image) {
	png.Encode(os.Stdout, img)
}

// Warn prints a message to standard error
func Warn(s interface{}) {
	fmt.Fprintln(os.Stderr, s)
}

// NormalisedRGBA returns the RGBA colour channel values of a Color in a
// normalised form.
func NormalisedRGBA(c color.Color) (rn, gn, bn, an uint32) {
	d := color.NRGBAModel.Convert(c).(color.NRGBA)
	r := d.R; g := d.G; b := d.B; a := d.A

	// Need to do some crazy type conversions first
	rn = uint32(uint8(r))
	gn = uint32(uint8(g))
	bn = uint32(uint8(b))
	an = uint32(uint8(a))

	return
}

// NormalisedRGBAf returns the RGBA colour channel values as floating point
// numbers with values from 0 to 255.
func NormalisedRGBAf(c color.Color) (rn, gn, bn, an float64) {
	r, g, b, a := NormalisedRGBA(c)

	rn = float64(r)
	gn = float64(g)
	bn = float64(b)
	an = float64(a)

	return
}

// RatioRGBA returns the RGBA colour channel values as floating point numbers
// with values from 0 to 1.
func RatioRGBA(c color.Color) (rn, gn, bn, an float64) {
	r, g, b, a := NormalisedRGBAf(c)

	rn = r / 255
	gn = g / 255
	bn = b / 255
	an = a / 255

	return
}

// Truncate takes a colour channel value and forces it into the range 0 to 255
// by setting any value below 0 to 0 and and any above 255 to 255.
func Truncate(n uint32) uint32 {
	if n < 0 { return 0 } else if n > 255 { return 255 }
	return n
}

// Truanctef is identical to Truncate but takes and returns a float64.
func Truncatef(n float64) float64 {
	if n < 0 { return 0 } else if n > 255 { return 255 }
	return n
}

// Closeness calculates the "closeness" of two colours by finding the sum of
// differences in each colour channel.
func Closeness(one, two color.Color) uint32 {
	a, b, c, d := NormalisedRGBA(one)
	w, x, y, z := NormalisedRGBA(two)

	return (a - w) + (b - x) + (c - y) + (d - z)
}

// Average takes a list of colours and returns the average.
func Average(cs... color.Color) color.Color {
	var red, green, blue, alpha uint32
	red = 0; green = 0; blue = 0; alpha = 0

	for i := 0; i < len(cs); i++ {
		r, g, b, a := NormalisedRGBA(cs[i])

		red += r; green += g; blue += b; alpha += a
	}

	return color.NRGBA{
		uint8(red   / uint32(len(cs))),
		uint8(green / uint32(len(cs))),
		uint8(blue  / uint32(len(cs))),
		uint8(alpha / uint32(len(cs))),
	}
}

// Min returns the smallest value in the list of uint32s given.
func Min(ns... uint32) (n uint32) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] < n {
			n = ns[i]
		}
	}
	return
}

// Minf returns the smallest value in the list of float64s given.
func Minf(ns... float64) (n float64) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] < n {
			n = ns[i]
		}
	}
	return
}

// Max returns the largest value in the list of uint32s given.
func Max(ns... uint32) (n uint32) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] > n {
			n = ns[i]
		}
	}
	return
}

// Maxf returns the largest value in the list of float64s given.
func Maxf(ns... float64) (n float64) {
	if len(ns) > 0 {
		n = ns[0]
	}
	for i := 1; i < len(ns); i++ {
		if ns[i] > n {
			n = ns[i]
		}
	}
	return
}

// EachPixel iterates through each pixel of the Image applies the function given
// and draws the result to a new Image which is then returned.
func EachPixel(img image.Image, f func(c color.Color) color.Color) image.Image {
	b := img.Bounds()
	o := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))

	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			result := f(img.At(x, y))
			o.Set(x, y, result)
		}
	}

	return o
}
<|endoftext|>


<commit_before>package utils

import (
    "fmt"
    "crypto/sha1"
)

func Hash(s string) string {
    h := sha1.New()
    h.Write([]byte(s))

    hash := h.Sum(nil)

    return fmt.Sprintf("%x", hash)
}
<commit_msg>utils : add Map and Hex_val methods<commit_after>package utils

import (
    "fmt"
    "crypto/sha1"
    "strconv"
)

func Hash(s string) string {
    h := sha1.New()
    h.Write([]byte(s))

    hash := h.Sum(nil)

    return fmt.Sprintf("%x", hash)
}

func Map(value, a_min, a_max, b_min, b_max float64) int {
    a_range := a_max - a_min
    b_range := b_max - b_min

    return int(b_max - (a_max - value) * (b_range/a_range))
}

func Hex_val(str string, index, length int) int {
    hex_str := str[index:index+length]

    hex_val, err := strconv.ParseInt(hex_str, 16, 0)
    if err != nil {
        panic(err)
    }

    return int(hex_val)
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package vms

import (
	"fmt"
	"sync"

	"github.com/ava-labs/avalanchego/api/server"
	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow"
	"github.com/ava-labs/avalanchego/snow/engine/common"
	"github.com/ava-labs/avalanchego/utils/logging"
)

// A VMFactory creates new instances of a VM
type VMFactory interface {
	New(*snow.Context) (interface{}, error)
}

// Manager is a VM manager.
// It has the following functionality:
//   1) Register a VM factory. To register a VM is to associate its ID with a
//		 VMFactory which, when New() is called upon it, creates a new instance of that VM.
//	 2) Get a VM factory. Given the ID of a VM that has been
//      registered, return the factory that the ID is associated with.
//   3) Associate a VM with an alias
//   4) Get the ID of the VM by the VM's alias
//   5) Get the aliases of a VM
type Manager interface {
	// Returns a factory that can create new instances of the VM
	// with the given ID
	GetVMFactory(ids.ID) (VMFactory, error)

	// Associate an ID with the factory that creates new instances
	// of the VM with the given ID
	RegisterVMFactory(ids.ID, VMFactory) error

	// Given an alias, return the ID of the VM associated with that alias
	Lookup(string) (ids.ID, error)

	// Return the aliases associated with a VM
	Aliases(ids.ID) []string

	// Give an alias to a VM
	Alias(ids.ID, string) error
}

// Implements Manager
type manager struct {
	// Note: The string representation of a VM's ID is also considered to be an
	// alias of the VM. That is, [VM].String() is an alias for the VM, too.
	ids.Aliaser

	// Key: The key underlying a VM's ID
	// Value: A factory that creates new instances of that VM
	vmFactories map[ids.ID]VMFactory

	// The node's API server.
	// [manager] adds routes to this server to expose new API endpoints/services
	apiServer *server.Server

	log logging.Logger
}

// NewManager returns an instance of a VM manager
func NewManager(apiServer *server.Server, log logging.Logger) Manager {
	m := &manager{
		vmFactories: make(map[ids.ID]VMFactory),
		apiServer:   apiServer,
		log:         log,
	}
	m.Initialize()
	return m
}

// Return a factory that can create new instances of the vm whose
// ID is [vmID]
func (m *manager) GetVMFactory(vmID ids.ID) (VMFactory, error) {
	if factory, ok := m.vmFactories[vmID]; ok {
		return factory, nil
	}
	return nil, fmt.Errorf("no vm with ID '%v' has been registered", vmID)

}

// Map [vmID] to [factory]. [factory] creates new instances of the vm whose
// ID is [vmID]
func (m *manager) RegisterVMFactory(vmID ids.ID, factory VMFactory) error {
	if _, exists := m.vmFactories[vmID]; exists {
		return fmt.Errorf("a vm with ID '%v' has already been registered", vmID)
	}
	if err := m.Alias(vmID, vmID.String()); err != nil {
		return err
	}

	m.vmFactories[vmID] = factory

	// add the static API endpoints
	m.addStaticAPIEndpoints(vmID)
	return nil
}

// VMs can expose a static API (one that does not depend on the state of a particular chain.)
// This method adds to the node's API server the static API of the VM with ID [vmID].
// This allows clients to call the VM's static API methods.
func (m *manager) addStaticAPIEndpoints(vmID ids.ID) {
	vmFactory, err := m.GetVMFactory(vmID)
	m.log.AssertNoError(err)
	m.log.Debug("adding static API for VM with ID %s", vmID)
	vm, err := vmFactory.New(nil)
	if err != nil {
		return
	}

	staticVM, ok := vm.(common.StaticVM)
	if !ok {
		staticVM, ok := vm.(common.VM)
		if ok {
			if err := staticVM.Shutdown(); err != nil {
				m.log.Error("shutting down static API endpoints errored with: %s", err)
			}
		}
		return
	}

	handlers, err := staticVM.CreateStaticHandlers()
	if err != nil {
		m.log.Error("starting static API endpoints for %s errored with: %s", vmID, err)

		staticVM, ok := vm.(common.VM)
		if ok {
			if err := staticVM.Shutdown(); err != nil {
				m.log.Error("shutting down static API endpoints errored with: %s", err)
			}
		}
		return
	}

	// all static endpoints go to the vm endpoint, defaulting to the vm id
	defaultEndpoint := "vm/" + vmID.String()
	// use a single lock for this entire vm
	lock := new(sync.RWMutex)
	// register the static endpoints
	for extension, service := range handlers {
		m.log.Verbo("adding static API endpoint: %s", defaultEndpoint+extension)
		if err := m.apiServer.AddRoute(service, lock, defaultEndpoint, extension, m.log); err != nil {
			m.log.Warn("failed to add static API endpoint %s: %v", fmt.Sprintf("%s%s", defaultEndpoint, extension), err)
		}
	}
}
<commit_msg>ensuring the node startup ends when failing to connect to the EVM<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package vms

import (
	"fmt"
	"sync"

	"github.com/ava-labs/avalanchego/api/server"
	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow"
	"github.com/ava-labs/avalanchego/snow/engine/common"
	"github.com/ava-labs/avalanchego/utils/logging"
)

// A VMFactory creates new instances of a VM
type VMFactory interface {
	New(*snow.Context) (interface{}, error)
}

// Manager is a VM manager.
// It has the following functionality:
//   1) Register a VM factory. To register a VM is to associate its ID with a
//		 VMFactory which, when New() is called upon it, creates a new instance of that VM.
//	 2) Get a VM factory. Given the ID of a VM that has been
//      registered, return the factory that the ID is associated with.
//   3) Associate a VM with an alias
//   4) Get the ID of the VM by the VM's alias
//   5) Get the aliases of a VM
type Manager interface {
	// Returns a factory that can create new instances of the VM
	// with the given ID
	GetVMFactory(ids.ID) (VMFactory, error)

	// Associate an ID with the factory that creates new instances
	// of the VM with the given ID
	RegisterVMFactory(ids.ID, VMFactory) error

	// Given an alias, return the ID of the VM associated with that alias
	Lookup(string) (ids.ID, error)

	// Return the aliases associated with a VM
	Aliases(ids.ID) []string

	// Give an alias to a VM
	Alias(ids.ID, string) error
}

// Implements Manager
type manager struct {
	// Note: The string representation of a VM's ID is also considered to be an
	// alias of the VM. That is, [VM].String() is an alias for the VM, too.
	ids.Aliaser

	// Key: The key underlying a VM's ID
	// Value: A factory that creates new instances of that VM
	vmFactories map[ids.ID]VMFactory

	// The node's API server.
	// [manager] adds routes to this server to expose new API endpoints/services
	apiServer *server.Server

	log logging.Logger
}

// NewManager returns an instance of a VM manager
func NewManager(apiServer *server.Server, log logging.Logger) Manager {
	m := &manager{
		vmFactories: make(map[ids.ID]VMFactory),
		apiServer:   apiServer,
		log:         log,
	}
	m.Initialize()
	return m
}

// Return a factory that can create new instances of the vm whose
// ID is [vmID]
func (m *manager) GetVMFactory(vmID ids.ID) (VMFactory, error) {
	if factory, ok := m.vmFactories[vmID]; ok {
		return factory, nil
	}
	return nil, fmt.Errorf("no vm with ID '%v' has been registered", vmID)

}

// Map [vmID] to [factory]. [factory] creates new instances of the vm whose
// ID is [vmID]
func (m *manager) RegisterVMFactory(vmID ids.ID, factory VMFactory) error {
	if _, exists := m.vmFactories[vmID]; exists {
		return fmt.Errorf("a vm with ID '%v' has already been registered", vmID)
	}
	if err := m.Alias(vmID, vmID.String()); err != nil {
		return err
	}

	m.vmFactories[vmID] = factory

	// add the static API endpoints
	return m.addStaticAPIEndpoints(vmID)
}

// VMs can expose a static API (one that does not depend on the state of a particular chain.)
// This method adds to the node's API server the static API of the VM with ID [vmID].
// This allows clients to call the VM's static API methods.
func (m *manager) addStaticAPIEndpoints(vmID ids.ID) error {
	vmFactory, err := m.GetVMFactory(vmID)
	m.log.AssertNoError(err)
	m.log.Debug("adding static API for VM with ID %s", vmID)
	vm, err := vmFactory.New(nil)
	if err != nil {
		return err
	}

	staticVM, ok := vm.(common.StaticVM)
	if !ok {
		staticVM, ok := vm.(common.VM)
		if ok {
			if err := staticVM.Shutdown(); err != nil {
				m.log.Error("shutting down static API endpoints errored with: %s", err)
				return err
			}
		}
		return nil
	}

	handlers, err := staticVM.CreateStaticHandlers()
	if err != nil {
		m.log.Error("starting static API endpoints for %s errored with: %s", vmID, err)

		staticVM, ok := vm.(common.VM)
		if ok {
			if err := staticVM.Shutdown(); err != nil {
				m.log.Error("shutting down static API endpoints errored with: %s", err)
				return err
			}
		}
		return nil
	}

	// all static endpoints go to the vm endpoint, defaulting to the vm id
	defaultEndpoint := "vm/" + vmID.String()
	// use a single lock for this entire vm
	lock := new(sync.RWMutex)
	// register the static endpoints
	for extension, service := range handlers {
		m.log.Verbo("adding static API endpoint: %s", defaultEndpoint+extension)
		if err := m.apiServer.AddRoute(service, lock, defaultEndpoint, extension, m.log); err != nil {
			m.log.Warn("failed to add static API endpoint %s: %v", fmt.Sprintf("%s%s", defaultEndpoint, extension), err)
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package walker_test

import (
	"os"
	"sort"
	"testing"

	"github.com/minodisk/go-walker"
)

func TestWalkWithDirectory(t *testing.T) {
	expectedFiles := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	expectedDirs := []string{"fixtures", "fixtures/bar", "fixtures/bar/qux"}
	var actualFiles, actualDirs []string
	err := walker.Walk("fixtures", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkWithFile(t *testing.T) {
	expectedFiles := []string{"fixtures/foo"}
	expectedDirs := []string{}
	var actualFiles, actualDirs []string
	err := walker.Walk("fixtures/foo", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkUnderWithDirectory(t *testing.T) {
	expectedFiles := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	expectedDirs := []string{"fixtures/bar", "fixtures/bar/qux"}
	var actualFiles, actualDirs []string
	err := walker.WalkUnder("fixtures", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkUnderWithFile(t *testing.T) {
	expectedFiles := []string{}
	expectedDirs := []string{}
	var actualFiles, actualDirs []string
	err := walker.WalkUnder("fixtures/foo", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestFindDirs(t *testing.T) {
	expected := []string{"fixtures", "fixtures/bar", "fixtures/bar/qux"}
	actual := walker.FindDirs("fixtures")
	if !equalStrings(expected, actual) {
		t.Errorf("wrong files: expected %v, but actual %v", expected, actual)
	}
}

func TestFindFiles(t *testing.T) {
	expected := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	actual := walker.FindFiles("fixtures")
	if !equalStrings(expected, actual) {
		t.Errorf("wrong files: expected %v, but actual %v", expected, actual)
	}
}

func equalStrings(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	sort.Strings(a)
	sort.Strings(b)
	for i, va := range a {
		vb := b[i]
		if va != vb {
			return false
		}
	}
	return true
}

func in(arr []string, elem string) bool {
	for _, e := range arr {
		if e == elem {
			return true
		}
	}
	return false
}
<commit_msg>Skip a bug of `os.ReadDir` in go 1.4<commit_after>package walker_test

import (
	"os"
	"sort"
	"testing"

	"github.com/minodisk/go-walker"
)

func TestWalkWithDirectory(t *testing.T) {
	expectedFiles := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	expectedDirs := []string{"fixtures", "fixtures/bar", "fixtures/bar/qux"}
	var actualFiles, actualDirs []string
	err := walker.Walk("fixtures", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkWithFile(t *testing.T) {
	expectedFiles := []string{"fixtures/foo"}
	expectedDirs := []string{}
	var actualFiles, actualDirs []string
	err := walker.Walk("fixtures/foo", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkUnderWithDirectory(t *testing.T) {
	expectedFiles := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	expectedDirs := []string{"fixtures/bar", "fixtures/bar/qux"}
	var actualFiles, actualDirs []string
	err := walker.WalkUnder("fixtures", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	if err != nil {
		t.Errorf("should not return error: %v", err)
	}
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestWalkUnderWithFile(t *testing.T) {
	expectedFiles := []string{}
	expectedDirs := []string{}
	var actualFiles, actualDirs []string
	walker.WalkUnder("fixtures/foo", func(name string, fi os.FileInfo) (bool, error) {
		if fi.IsDir() {
			actualDirs = append(actualDirs, name)
		} else {
			actualFiles = append(actualFiles, name)
		}
		return true, nil
	})
	// Should return error in Linux, but doesn't in Mac OS X, in go 1.4.
	// See https://github.com/golang/go/issues/9789
	// if err == nil {
	// 	t.Errorf("should return error: %v", err)
	// }
	if !equalStrings(expectedFiles, actualFiles) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedFiles, actualFiles)
	}
	if !equalStrings(expectedDirs, actualDirs) {
		t.Errorf("wrong files: expected %v, but actual %v", expectedDirs, actualDirs)
	}
}

func TestFindDirs(t *testing.T) {
	expected := []string{"fixtures", "fixtures/bar", "fixtures/bar/qux"}
	actual := walker.FindDirs("fixtures")
	if !equalStrings(expected, actual) {
		t.Errorf("wrong files: expected %v, but actual %v", expected, actual)
	}
}

func TestFindFiles(t *testing.T) {
	expected := []string{"fixtures/bar/baz", "fixtures/bar/qux/quux", "fixtures/foo"}
	actual := walker.FindFiles("fixtures")
	if !equalStrings(expected, actual) {
		t.Errorf("wrong files: expected %v, but actual %v", expected, actual)
	}
}

func equalStrings(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	sort.Strings(a)
	sort.Strings(b)
	for i, va := range a {
		vb := b[i]
		if va != vb {
			return false
		}
	}
	return true
}

func in(arr []string, elem string) bool {
	for _, e := range arr {
		if e == elem {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package wallet

import (
	"bytes"
	"crypto/sha256"

	"github.com/FactomProject/btcutil/base58"
)

const (
	SeedLength = 64
	Version    = "0.2.2.0"
	ApiVersion = "2.0"
)

// seed address prefix
var seedPrefix = []byte{0x13, 0xdd}

// SeedString returnes the string representation of a raw Wallet Seed or Next
// Wallet Seed.
func SeedString(seed []byte) string {
	if len(seed) != SeedLength {
		return ""
	}

	buf := new(bytes.Buffer)

	// 2 byte Seed Address Prefix
	buf.Write(seedPrefix)

	// 64 byte Seed
	buf.Write(seed)

	// 4 byte Checksum
	check := shad(buf.Bytes())[:4]
	buf.Write(check)

	return base58.Encode(buf.Bytes())
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// newCounter is used to generate the ID field for the JSON2Request
func newCounter() func() int {
	count := 0
	return func() int {
		count += 1
		return count
	}
}

var APICounter = newCounter()
<commit_msg>bump version<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package wallet

import (
	"bytes"
	"crypto/sha256"

	"github.com/FactomProject/btcutil/base58"
)

const (
	SeedLength = 64
	Version    = "0.2.2.1"
	ApiVersion = "2.0"
)

// seed address prefix
var seedPrefix = []byte{0x13, 0xdd}

// SeedString returnes the string representation of a raw Wallet Seed or Next
// Wallet Seed.
func SeedString(seed []byte) string {
	if len(seed) != SeedLength {
		return ""
	}

	buf := new(bytes.Buffer)

	// 2 byte Seed Address Prefix
	buf.Write(seedPrefix)

	// 64 byte Seed
	buf.Write(seed)

	// 4 byte Checksum
	check := shad(buf.Bytes())[:4]
	buf.Write(check)

	return base58.Encode(buf.Bytes())
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// newCounter is used to generate the ID field for the JSON2Request
func newCounter() func() int {
	count := 0
	return func() int {
		count += 1
		return count
	}
}

var APICounter = newCounter()
<|endoftext|>


<commit_before>package watch

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/http/cookiejar"
	"strings"
	"time"

	"reflect"

	"github.com/foomo/petze/config"

	log "github.com/sirupsen/logrus"
)

var typeDNSConfigErr = reflect.TypeOf(&net.DNSConfigError{})
var typeDNSErr = reflect.TypeOf(&net.DNSError{})
var typeOpErr = reflect.TypeOf(&net.OpError{})
var typeX509CertificateInvalidError = reflect.TypeOf(x509.CertificateInvalidError{})
var typeX509HostnameError = reflect.TypeOf(x509.HostnameError{})
var typeX509SystemRootsError = reflect.TypeOf(x509.SystemRootsError{})
var typeX509UnknownAuthorityError = reflect.TypeOf(x509.UnknownAuthorityError{})

type ErrorType string

const (
	ErrorInvalidEndpoint           ErrorType = "endpointInvalid"
	ErrorTypeServerTooSlow                   = "serverTooSlow"
	ErrorTypeNotImplemented                  = "notImplemented"
	ErrorTypeUnknownError                    = "unknownError"
	ErrorTypeClientError                     = "clientError"
	ErrorTypeDNS                             = "dns"
	ErrorTypeDNSConfig                       = "dnsConfig"
	ErrorTypeTLSCertificateInvalid           = "tlsCertificateInvalid"
	ErrorTypeTLSHostNameError                = "tlsHostNameError"
	ErrorTypeTLSSystemRootsError             = "tlsSystemRootsError"
	ErrorTypeTLSUnknownAuthority             = "tlsUnknownAutority"
	ErrorTypeWrongHTTPStatusCode             = "wrongHTTPStatus"
	ErrorTypeCertificateIsExpiring           = "certificateIsExpiring"
	ErrorTypeUnexpectedContentType           = "unexpectedContentType"
	ErrorTypeSessionFail                     = "sessionFail"
	ErrorTypeGoQueryMismatch                 = "goqueryMismatch"
	ErrorTypeGoQuery                         = "goQueryGeneralError"
	ErrorTypeDataMismatch                    = "dataMismatch"
	ErrorJsonPath                            = "jsonPathError"
	ErrorRegex				 = "regexError"
	ErrorBadResponseBody			 = "badResponseBody"
)

type Error struct {
	Error   string    `json:"error"`
	Type    ErrorType `json:"type"`
	Comment string    `json:"comment,omitempty"`
}

type Result struct {
	ID        string        `json:"id"`
	Errors    []Error       `json:"errors"`
	Timeout   bool          `json:"timeout"`
	Timestamp time.Time     `json:"timestamp"`
	RunTime   time.Duration `json:"runtime"`
}

func NewResult(id string) *Result {
	return &Result{
		ID:        id,
		Errors:    []Error{},
		Timestamp: time.Now(),
	}
}

func (r *Result) addError(e error, t ErrorType, comment string) {
	r.Errors = addError(r.Errors, e, t, comment)
}

func addError(errors []Error, err error, t ErrorType, comment string) []Error {
	return append(errors, Error{
		Error:   err.Error(),
		Type:    t,
		Comment: comment,
	})
}

type dialerErrRecorder struct {
	errors                     []Error
	unknownErr                 error
	err                        net.Error
	dnsError                   net.Error
	dnsConfigError             net.Error
	tlsCertificateInvalidError *x509.CertificateInvalidError
	tlsHostnameError           *x509.HostnameError
	tlsSystemRootsError        *x509.SystemRootsError
	tlsUnknownAuthorityError   *x509.UnknownAuthorityError
}

type Watcher struct {
	active  bool
	service *config.Service
}

// Watch create a watcher and start watching
func Watch(service *config.Service, chanResult chan Result) *Watcher {
	w := &Watcher{
		active:  true,
		service: service,
	}
	go w.watchLoop(chanResult)
	return w
}

// Stop watching - beware this is async
func (w *Watcher) Stop() {
	w.active = false
}

func (w *Watcher) watchLoop(chanResult chan Result) {
	for w.active {
		r := watch(w.service)
		if w.active {
			chanResult <- *r
			time.Sleep(w.service.Interval)
		}
	}
}

func getClientAndDialErrRecorder() (client *http.Client, errRecorder *dialerErrRecorder) {
	errRecorder = &dialerErrRecorder{
		errors: []Error{},
	}
	tlsConfig := &tls.Config{}
	dialer := &net.Dialer{
		Timeout:   10 * time.Second,
		KeepAlive: 0 * time.Second,
	}
	dialTLS := func(network, address string) (conn net.Conn, err error) {
		tlsConn, tlsErr := tls.DialWithDialer(dialer, network, address, tlsConfig)
		if tlsErr == nil {
			//conn = tlsConn.(net.Conn)
			connectionState := tlsConn.ConnectionState()
			for _, cert := range connectionState.PeerCertificates {
				durationUntilExpiry := cert.NotAfter.Sub(time.Now())
				if durationUntilExpiry < time.Hour*7*24 {
					// well in less than 24 h is worth an error
					errRecorder.errors = addError(errRecorder.errors, errors.New(fmt.Sprint("cert CN=\"", cert.Subject.CommonName, "\" is expiring in less than 24h: ", cert.NotAfter, ", left: ", durationUntilExpiry)), ErrorTypeCertificateIsExpiring, "")
				}
			}
			conn = tlsConn
		} else {

			switch reflect.TypeOf(tlsErr) {
			case typeX509UnknownAuthorityError:
				unknownAuthorityError := tlsErr.(x509.UnknownAuthorityError)
				errRecorder.tlsUnknownAuthorityError = &unknownAuthorityError
			case typeX509HostnameError:
				hostnameErr := tlsErr.(x509.HostnameError)
				errRecorder.tlsHostnameError = &hostnameErr
			case typeX509CertificateInvalidError:
				tlsCertificateInvalidError := tlsErr.(x509.CertificateInvalidError)
				errRecorder.tlsCertificateInvalidError = &tlsCertificateInvalidError
			case typeX509SystemRootsError:
				systemRootsError := tlsErr.(x509.SystemRootsError)
				errRecorder.tlsSystemRootsError = &systemRootsError
			default:
				log.Error("unknown tls error", reflect.TypeOf(tlsErr), tlsErr)
			}
		}
		return conn, tlsErr
	}
	dial := func(network, address string) (conn net.Conn, err error) {
		conn, err = dialer.Dial(network, address)
		if err != nil {
			switch reflect.TypeOf(err) {
			case typeOpErr:
				opError := reflect.ValueOf(err).Elem().Interface().(net.OpError)
				switch reflect.TypeOf(opError.Err) {
				case typeDNSConfigErr:
					log.Error("dns config error")
					errRecorder.dnsConfigError = opError.Err.(net.Error)
				case typeDNSErr:
					log.Error("dns error")
					errRecorder.dnsError = opError.Err.(net.Error)
				default:
					errRecorder.unknownErr = opError.Err
				}
			default:
				log.Error("again some general bullshit", err)
				errRecorder.err = err.(net.Error)
			}
		}
		return
	}
	client = &http.Client{
		Transport: &http.Transport{
			Proxy:               http.ProxyFromEnvironment,
			Dial:                dial,
			DialTLS:             dialTLS,
			TLSHandshakeTimeout: 10 * time.Second,
			TLSClientConfig:     tlsConfig,
		},
	}
	return
}

// actual watch
func watch(service *config.Service) (r *Result) {
	r = NewResult(service.ID)
	// parsing, the endpoint
	request, err := http.NewRequest("GET", service.Endpoint, nil)
	if err != nil {
		r.addError(err, ErrorInvalidEndpoint, "")
		return r
	}
	// my personal dns error check
	if len(request.Host) > 0 {
		host := request.Host
		parts := strings.Split(host, ":")
		if len(parts) > 1 {
			host, _, err = net.SplitHostPort(request.Host)
			if err != nil {
				r.addError(err, ErrorInvalidEndpoint, "")
				return
			}
		}
		_, lookupErr := net.LookupIP(host)
		if lookupErr != nil {
			r.addError(lookupErr, ErrorTypeDNS, "")
			return
		}
	}

	// i am explicitly not calling http.Get, because it does 30x handling and i do not want that
	client, errRecorder := getClientAndDialErrRecorder()
	response, err := client.Do(request)
	r.Errors = append(r.Errors, errRecorder.errors...)

	if response != nil && response.Body != nil {
		// always close the body
		response.Body.Close()
	}

	if err != nil {
		// sth. went wrong
		r.addError(err, ErrorTypeClientError, "")
		var netErr net.Error
		switch true {
		case errRecorder.tlsHostnameError != nil:
			r.addError(errRecorder.tlsHostnameError, ErrorTypeTLSHostNameError, "")
		case errRecorder.tlsSystemRootsError != nil:
			r.addError(errRecorder.tlsSystemRootsError, ErrorTypeTLSSystemRootsError, "")
		case errRecorder.tlsUnknownAuthorityError != nil:
			r.addError(errRecorder.tlsUnknownAuthorityError, ErrorTypeTLSUnknownAuthority, "")
		case errRecorder.tlsCertificateInvalidError != nil:
			r.addError(errRecorder.tlsCertificateInvalidError, ErrorTypeTLSCertificateInvalid, "")
		case errRecorder.unknownErr != nil:
			r.addError(errRecorder.unknownErr, ErrorTypeUnknownError, "")
		case errRecorder.dnsConfigError != nil:
			netErr = errRecorder.dnsConfigError
			r.addError(errRecorder.dnsConfigError, ErrorTypeDNSConfig, "")
		case errRecorder.dnsError != nil:
			netErr = errRecorder.dnsError
			r.addError(errRecorder.dnsError, ErrorTypeDNS, "")
		case errRecorder.err != nil:
			netErr = errRecorder.err
			r.addError(errRecorder.err, ErrorTypeUnknownError, "")
		}
		if netErr != nil {
			r.Timeout = netErr.Timeout()
		}
		return
	}

	// prepare to run the session with cookies
	cookieJar, _ := cookiejar.New(nil)
	client.Jar = cookieJar
	errSession := runSession(service, r, client)
	if errSession != nil {
		log.Error("session error", errSession)
		r.addError(errSession, ErrorTypeSessionFail, "")
	}
	r.RunTime = time.Since(r.Timestamp)

	// r.addError(errors.New(fmt.Sprint("response time too slow:", runTimeMilliseconds, ", should not be more than:", maxRuntime)), ErrorTypeServerTooSlow)
	//r.StatusCode = response.StatusCode
	if response.StatusCode != http.StatusOK {
		r.addError(errors.New(fmt.Sprint("unexpected status code: ", response.StatusCode)), ErrorTypeWrongHTTPStatusCode, "")
	}
	return
}
<commit_msg>Fix goroutine leak on petze<commit_after>package watch

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/http/cookiejar"
	"strings"
	"time"

	"reflect"

	"github.com/foomo/petze/config"

	log "github.com/sirupsen/logrus"
)

var typeDNSConfigErr = reflect.TypeOf(&net.DNSConfigError{})
var typeDNSErr = reflect.TypeOf(&net.DNSError{})
var typeOpErr = reflect.TypeOf(&net.OpError{})
var typeX509CertificateInvalidError = reflect.TypeOf(x509.CertificateInvalidError{})
var typeX509HostnameError = reflect.TypeOf(x509.HostnameError{})
var typeX509SystemRootsError = reflect.TypeOf(x509.SystemRootsError{})
var typeX509UnknownAuthorityError = reflect.TypeOf(x509.UnknownAuthorityError{})

type ErrorType string

const (
	ErrorInvalidEndpoint           ErrorType = "endpointInvalid"
	ErrorTypeServerTooSlow                   = "serverTooSlow"
	ErrorTypeNotImplemented                  = "notImplemented"
	ErrorTypeUnknownError                    = "unknownError"
	ErrorTypeClientError                     = "clientError"
	ErrorTypeDNS                             = "dns"
	ErrorTypeDNSConfig                       = "dnsConfig"
	ErrorTypeTLSCertificateInvalid           = "tlsCertificateInvalid"
	ErrorTypeTLSHostNameError                = "tlsHostNameError"
	ErrorTypeTLSSystemRootsError             = "tlsSystemRootsError"
	ErrorTypeTLSUnknownAuthority             = "tlsUnknownAutority"
	ErrorTypeWrongHTTPStatusCode             = "wrongHTTPStatus"
	ErrorTypeCertificateIsExpiring           = "certificateIsExpiring"
	ErrorTypeUnexpectedContentType           = "unexpectedContentType"
	ErrorTypeSessionFail                     = "sessionFail"
	ErrorTypeGoQueryMismatch                 = "goqueryMismatch"
	ErrorTypeGoQuery                         = "goQueryGeneralError"
	ErrorTypeDataMismatch                    = "dataMismatch"
	ErrorJsonPath                            = "jsonPathError"
	ErrorRegex                               = "regexError"
	ErrorBadResponseBody                     = "badResponseBody"
)

type Error struct {
	Error   string    `json:"error"`
	Type    ErrorType `json:"type"`
	Comment string    `json:"comment,omitempty"`
}

type Result struct {
	ID        string        `json:"id"`
	Errors    []Error       `json:"errors"`
	Timeout   bool          `json:"timeout"`
	Timestamp time.Time     `json:"timestamp"`
	RunTime   time.Duration `json:"runtime"`
}

func NewResult(id string) *Result {
	return &Result{
		ID:        id,
		Errors:    []Error{},
		Timestamp: time.Now(),
	}
}

func (r *Result) addError(e error, t ErrorType, comment string) {
	r.Errors = addError(r.Errors, e, t, comment)
}

func addError(errors []Error, err error, t ErrorType, comment string) []Error {
	return append(errors, Error{
		Error:   err.Error(),
		Type:    t,
		Comment: comment,
	})
}

type dialerErrRecorder struct {
	errors                     []Error
	unknownErr                 error
	err                        net.Error
	dnsError                   net.Error
	dnsConfigError             net.Error
	tlsCertificateInvalidError *x509.CertificateInvalidError
	tlsHostnameError           *x509.HostnameError
	tlsSystemRootsError        *x509.SystemRootsError
	tlsUnknownAuthorityError   *x509.UnknownAuthorityError
}

type Watcher struct {
	active  bool
	service *config.Service
}

// Watch create a watcher and start watching
func Watch(service *config.Service, chanResult chan Result) *Watcher {

	w := &Watcher{
		active:  true,
		service: service,

	}
	go w.watchLoop(chanResult)
	return w
}

// Stop watching - beware this is async
func (w *Watcher) Stop() {
	w.active = false
}

func (w *Watcher) watchLoop(chanResult chan Result) {
	httpClient, errRecorder := getClientAndDialErrRecorder()

	for w.active {
		r := watch(w.service, httpClient, errRecorder)
		if w.active {
			chanResult <- *r
			time.Sleep(w.service.Interval)
		}
	}
}

func getClientAndDialErrRecorder() (client *http.Client, errRecorder *dialerErrRecorder) {
	errRecorder = &dialerErrRecorder{
		errors: []Error{},
	}
	tlsConfig := &tls.Config{}
	dialer := &net.Dialer{
		Timeout:   10 * time.Second,
		KeepAlive: 0 * time.Second,
	}
	dialTLS := func(network, address string) (conn net.Conn, err error) {
		tlsConn, tlsErr := tls.DialWithDialer(dialer, network, address, tlsConfig)
		if tlsErr == nil {
			//conn = tlsConn.(net.Conn)
			connectionState := tlsConn.ConnectionState()
			for _, cert := range connectionState.PeerCertificates {
				durationUntilExpiry := cert.NotAfter.Sub(time.Now())
				if durationUntilExpiry < time.Hour*7*24 {
					// well in less than 24 h is worth an error
					errRecorder.errors = addError(errRecorder.errors, errors.New(fmt.Sprint("cert CN=\"", cert.Subject.CommonName, "\" is expiring in less than 24h: ", cert.NotAfter, ", left: ", durationUntilExpiry)), ErrorTypeCertificateIsExpiring, "")
				}
			}
			conn = tlsConn
		} else {

			switch reflect.TypeOf(tlsErr) {
			case typeX509UnknownAuthorityError:
				unknownAuthorityError := tlsErr.(x509.UnknownAuthorityError)
				errRecorder.tlsUnknownAuthorityError = &unknownAuthorityError
			case typeX509HostnameError:
				hostnameErr := tlsErr.(x509.HostnameError)
				errRecorder.tlsHostnameError = &hostnameErr
			case typeX509CertificateInvalidError:
				tlsCertificateInvalidError := tlsErr.(x509.CertificateInvalidError)
				errRecorder.tlsCertificateInvalidError = &tlsCertificateInvalidError
			case typeX509SystemRootsError:
				systemRootsError := tlsErr.(x509.SystemRootsError)
				errRecorder.tlsSystemRootsError = &systemRootsError
			default:
				log.Error("unknown tls error", reflect.TypeOf(tlsErr), tlsErr)
			}
		}
		return conn, tlsErr
	}
	dial := func(network, address string) (conn net.Conn, err error) {
		conn, err = dialer.Dial(network, address)
		if err != nil {
			switch reflect.TypeOf(err) {
			case typeOpErr:
				opError := reflect.ValueOf(err).Elem().Interface().(net.OpError)
				switch reflect.TypeOf(opError.Err) {
				case typeDNSConfigErr:
					log.Error("dns config error")
					errRecorder.dnsConfigError = opError.Err.(net.Error)
				case typeDNSErr:
					log.Error("dns error")
					errRecorder.dnsError = opError.Err.(net.Error)
				default:
					errRecorder.unknownErr = opError.Err
				}
			default:
				log.Error("again some general bullshit", err)
				errRecorder.err = err.(net.Error)
			}
		}
		return
	}
	client = &http.Client{
		Transport: &http.Transport{
			Proxy:               http.ProxyFromEnvironment,
			Dial:                dial,
			DialTLS:             dialTLS,
			TLSHandshakeTimeout: 10 * time.Second,
			TLSClientConfig:     tlsConfig,
		},
	}
	return
}

// actual watch
func watch(service *config.Service, client *http.Client, errRecorder *dialerErrRecorder) (r *Result) {
	r = NewResult(service.ID)
	// parsing, the endpoint
	request, err := http.NewRequest("GET", service.Endpoint, nil)
	if err != nil {
		r.addError(err, ErrorInvalidEndpoint, "")
		return r
	}
	// my personal dns error check
	if len(request.Host) > 0 {
		host := request.Host
		parts := strings.Split(host, ":")
		if len(parts) > 1 {
			host, _, err = net.SplitHostPort(request.Host)
			if err != nil {
				r.addError(err, ErrorInvalidEndpoint, "")
				return
			}
		}
		_, lookupErr := net.LookupIP(host)
		if lookupErr != nil {
			r.addError(lookupErr, ErrorTypeDNS, "")
			return
		}
	}

	// i am explicitly not calling http.Get, because it does 30x handling and i do not want that
	response, err := client.Do(request)
	r.Errors = append(r.Errors, errRecorder.errors...)

	if response != nil && response.Body != nil {
		// always close the body
		response.Body.Close()
	}

	if err != nil {
		// sth. went wrong
		r.addError(err, ErrorTypeClientError, "")
		var netErr net.Error
		switch true {
		case errRecorder.tlsHostnameError != nil:
			r.addError(errRecorder.tlsHostnameError, ErrorTypeTLSHostNameError, "")
		case errRecorder.tlsSystemRootsError != nil:
			r.addError(errRecorder.tlsSystemRootsError, ErrorTypeTLSSystemRootsError, "")
		case errRecorder.tlsUnknownAuthorityError != nil:
			r.addError(errRecorder.tlsUnknownAuthorityError, ErrorTypeTLSUnknownAuthority, "")
		case errRecorder.tlsCertificateInvalidError != nil:
			r.addError(errRecorder.tlsCertificateInvalidError, ErrorTypeTLSCertificateInvalid, "")
		case errRecorder.unknownErr != nil:
			r.addError(errRecorder.unknownErr, ErrorTypeUnknownError, "")
		case errRecorder.dnsConfigError != nil:
			netErr = errRecorder.dnsConfigError
			r.addError(errRecorder.dnsConfigError, ErrorTypeDNSConfig, "")
		case errRecorder.dnsError != nil:
			netErr = errRecorder.dnsError
			r.addError(errRecorder.dnsError, ErrorTypeDNS, "")
		case errRecorder.err != nil:
			netErr = errRecorder.err
			r.addError(errRecorder.err, ErrorTypeUnknownError, "")
		}
		if netErr != nil {
			r.Timeout = netErr.Timeout()
		}
		return
	}

	// prepare to run the session with cookies
	cookieJar, _ := cookiejar.New(nil)
	client.Jar = cookieJar
	errSession := runSession(service, r, client)
	if errSession != nil {
		log.Error("session error", errSession)
		r.addError(errSession, ErrorTypeSessionFail, "")
	}
	r.RunTime = time.Since(r.Timestamp)

	// r.addError(errors.New(fmt.Sprint("response time too slow:", runTimeMilliseconds, ", should not be more than:", maxRuntime)), ErrorTypeServerTooSlow)
	//r.StatusCode = response.StatusCode
	if response.StatusCode != http.StatusOK {
		r.addError(errors.New(fmt.Sprint("unexpected status code: ", response.StatusCode)), ErrorTypeWrongHTTPStatusCode, "")
	}
	return
}
<|endoftext|>


<commit_before>package wav

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"

	"github.com/mattetti/audio"
	"github.com/mattetti/audio/riff"
)

// Encoder encodes LPCM data into a wav containter.
type Encoder struct {
	w              io.WriteSeeker
	SampleRate     int
	BitDepth       int
	NumChans       int
	Frames         [][]int
	WavAudioFormat int

	WrittenBytes int
}

// NewEncoder creates a new encoder to create a new wav file.
// Don't forget to add Frames to the encoder before writing.
func NewEncoder(w io.WriteSeeker, sampleRate, bitDepth, numChans, audioFormat int) *Encoder {
	return &Encoder{
		w:              w,
		SampleRate:     sampleRate,
		BitDepth:       bitDepth,
		NumChans:       numChans,
		WavAudioFormat: audioFormat,
	}
}

// Add serializes and adds the passed value using little endian
func (e *Encoder) Add(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.LittleEndian, src)
}

// AddLE serializes and adds the passed value using little endian
func (e *Encoder) AddLE(src interface{}) error {
	return e.Add(src)
}

// AddBE serializes and adds the passed value using big endian
func (e *Encoder) AddBE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.BigEndian, src)
}

func (e *Encoder) addFrame(frame []int) error {
	if frame == nil {
		return fmt.Errorf("can't add a nil frame")
	}
	for i := 0; i < e.NumChans; i++ {
		switch e.BitDepth {
		case 8:
			if err := e.Add(uint8(frame[i])); err != nil {
				return err
			}
		case 16:
			if err := e.Add(uint16(frame[i])); err != nil {
				return err
			}
		case 24:
			if err := e.Add(audio.Uint32toUint24Bytes(uint32(frame[i]))); err != nil {
				return err
			}
		case 32:
			if err := e.Add(uint32(frame[i])); err != nil {
				return err
			}
		default:
			return fmt.Errorf("can't add frames of bit size %d", e.BitDepth)
		}
	}

	return nil
}

func (e *Encoder) numSampleFrames() int {
	return len(e.Frames)
}

func (e *Encoder) Write() error {
	if e == nil {
		return fmt.Errorf("can't write a nil encoder")
	}
	if e.w == nil {
		return fmt.Errorf("can't write to a nil writer")
	}

	// HEADERS
	// riff ID
	if err := e.Add(riff.RiffID); err != nil {
		return err
	}
	// file size uint32, to update later on.
	if err := e.Add(uint32(42)); err != nil {
		return err
	}

	// wave headers
	if err := e.Add(riff.WavFormatID); err != nil {
		return err
	}
	// form
	if err := e.Add(riff.FmtID); err != nil {
		return err
	}
	// chunk size
	if err := e.AddLE(uint32(16)); err != nil {
		return err
	}
	// wave format
	if err := e.Add(uint16(e.WavAudioFormat)); err != nil {
		return err
	}
	// num channels
	if err := e.Add(uint16(e.NumChans)); err != nil {
		return fmt.Errorf("error encoding the number of channels - %v", err)
	}
	// samplerate
	if err := e.Add(uint32(e.SampleRate)); err != nil {
		return fmt.Errorf("error encoding the sample rate - %v", err)
	}
	// avg bytes per sec
	if err := e.Add(uint32(e.SampleRate * e.NumChans * e.BitDepth / 8)); err != nil {
		return fmt.Errorf("error encoding the avg bytes per sec - %v", err)
	}
	// block align
	if err := e.Add(uint16(2)); err != nil {
		return err
	}
	// bits per sample
	if err := e.Add(uint16(e.BitDepth)); err != nil {
		return fmt.Errorf("error encoding bits per sample - %v", err)
	}

	// sound header
	if err := e.Add(riff.DataFormatID); err != nil {
		return fmt.Errorf("error encoding sound header %v", err)
	}

	chunksize := uint32((int(e.BitDepth) / 8) * int(e.NumChans) * len(e.Frames))
	if err := e.Add(uint32(chunksize)); err != nil {
		return fmt.Errorf("%v when writing wav data chunk size header", err)
	}

	for i, frame := range e.Frames {
		if err := e.addFrame(frame); err != nil {
			return fmt.Errorf("%v when writing frame %d", err, i)
		}
	}

	// go back and write total size
	e.w.Seek(4, 0)
	if err := e.AddLE(uint32(e.WrittenBytes) - 8); err != nil {
		return fmt.Errorf("%v when writing the total written bytes", err)
	}
	// jump to the end of the file.
	e.w.Seek(0, 2)
	switch e.w.(type) {
	case *os.File:
		e.w.(*os.File).Sync()
	}
	return nil
}
<commit_msg>wav: refactoring the encoder API<commit_after>package wav

import (
	"encoding/binary"
	"fmt"
	"io"
	"os"

	"github.com/mattetti/audio"
	"github.com/mattetti/audio/riff"
)

// Encoder encodes LPCM data into a wav containter.
type Encoder struct {
	w              io.WriteSeeker
	SampleRate     int
	BitDepth       int
	NumChans       int
	Frames         [][]int
	WavAudioFormat int

	WrittenBytes int
}

// NewEncoder creates a new encoder to create a new wav file.
// Don't forget to add Frames to the encoder before writing.
func NewEncoder(w io.WriteSeeker, sampleRate, bitDepth, numChans, audioFormat int) *Encoder {
	return &Encoder{
		w:              w,
		SampleRate:     sampleRate,
		BitDepth:       bitDepth,
		NumChans:       numChans,
		WavAudioFormat: audioFormat,
	}
}

// AddLE serializes and adds the passed value using little endian
func (e *Encoder) AddLE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.LittleEndian, src)
}

// AddBE serializes and adds the passed value using big endian
func (e *Encoder) AddBE(src interface{}) error {
	e.WrittenBytes += binary.Size(src)
	return binary.Write(e.w, binary.BigEndian, src)
}

func (e *Encoder) addFrame(frame []int) error {
	if frame == nil {
		return fmt.Errorf("can't add a nil frame")
	}
	for i := 0; i < e.NumChans; i++ {
		switch e.BitDepth {
		case 8:
			if err := e.AddLE(uint8(frame[i])); err != nil {
				return err
			}
		case 16:
			if err := e.AddLE(uint16(frame[i])); err != nil {
				return err
			}
		case 24:
			if err := e.AddLE(audio.Uint32toUint24Bytes(uint32(frame[i]))); err != nil {
				return err
			}
		case 32:
			if err := e.AddLE(uint32(frame[i])); err != nil {
				return err
			}
		default:
			return fmt.Errorf("can't add frames of bit size %d", e.BitDepth)
		}
	}

	return nil
}

func (e *Encoder) numSampleFrames() int {
	return len(e.Frames)
}

func (e *Encoder) Write() error {
	if e == nil {
		return fmt.Errorf("can't write a nil encoder")
	}
	if e.w == nil {
		return fmt.Errorf("can't write to a nil writer")
	}

	// HEADERS
	// riff ID
	if err := e.AddLE(riff.RiffID); err != nil {
		return err
	}
	// file size uint32, to update later on.
	if err := e.AddLE(uint32(42)); err != nil {
		return err
	}

	// wave headers
	if err := e.AddLE(riff.WavFormatID); err != nil {
		return err
	}
	// form
	if err := e.AddLE(riff.FmtID); err != nil {
		return err
	}
	// chunk size
	if err := e.AddLE(uint32(16)); err != nil {
		return err
	}
	// wave format
	if err := e.AddLE(uint16(e.WavAudioFormat)); err != nil {
		return err
	}
	// num channels
	if err := e.AddLE(uint16(e.NumChans)); err != nil {
		return fmt.Errorf("error encoding the number of channels - %v", err)
	}
	// samplerate
	if err := e.AddLE(uint32(e.SampleRate)); err != nil {
		return fmt.Errorf("error encoding the sample rate - %v", err)
	}
	// avg bytes per sec
	if err := e.AddLE(uint32(e.SampleRate * e.NumChans * e.BitDepth / 8)); err != nil {
		return fmt.Errorf("error encoding the avg bytes per sec - %v", err)
	}
	// block align
	if err := e.AddLE(uint16(2)); err != nil {
		return err
	}
	// bits per sample
	if err := e.AddLE(uint16(e.BitDepth)); err != nil {
		return fmt.Errorf("error encoding bits per sample - %v", err)
	}

	// sound header
	if err := e.AddLE(riff.DataFormatID); err != nil {
		return fmt.Errorf("error encoding sound header %v", err)
	}

	chunksize := uint32((int(e.BitDepth) / 8) * int(e.NumChans) * len(e.Frames))
	if err := e.AddLE(uint32(chunksize)); err != nil {
		return fmt.Errorf("%v when writing wav data chunk size header", err)
	}

	for i, frame := range e.Frames {
		if err := e.addFrame(frame); err != nil {
			return fmt.Errorf("%v when writing frame %d", err, i)
		}
	}

	// go back and write total size
	e.w.Seek(4, 0)
	if err := e.AddLE(uint32(e.WrittenBytes) - 8); err != nil {
		return fmt.Errorf("%v when writing the total written bytes", err)
	}
	// jump to the end of the file.
	e.w.Seek(0, 2)
	switch e.w.(type) {
	case *os.File:
		e.w.(*os.File).Sync()
	}
	return nil
}
<|endoftext|>


<commit_before>//go:build !containers_image_openpgp
// +build !containers_image_openpgp

package main

/*
This is a pretty horrible workaround.  Due to a glibc bug
https://bugzilla.redhat.com/show_bug.cgi?id=1326903 , we must ensure we link
with -lgpgme before -lpthread.  Such arguments come from various packages
using cgo, and the ordering of these arguments is, with current (go tool link),
dependent on the order in which the cgo-using packages are found in a
breadth-first search following dependencies, starting from “main”.

Thus, if
   import "net"
is processed before
   import "…/skopeo/signature"
it will, in the next level of the BFS, pull in "runtime/cgo" (a dependency of
"net") before "mtrmac/gpgme" (a dependency of "…/skopeo/signature"), causing
-lpthread (used by "runtime/cgo") to be used before -lgpgme.

This might be possible to work around by careful import ordering, or by removing
a direct dependency on "net", but that would be very fragile.

So, until the above bug is fixed, add -lgpgme directly in the "main" package
to ensure the needed build order.

Unfortunately, this workaround needs to be applied at the top level of any user
of "…/skopeo/signature"; it cannot be added to "…/skopeo/signature" itself,
by that time this package is first processed by the linker, a -lpthread may
already be queued and it would be too late.
*/

// #cgo LDFLAGS: -lgpgme
import "C"
<commit_msg>Remove cgo_pthread_ordering_workaround.go<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package atomic

import (
	"runtime"
	"testing"
)

const _parallelism = 4
const _iterations = 1000

func TestStressInt32(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := &Int32{0}
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Add(1)
				atom.Sub(2)
				atom.Inc()
				atom.Dec()
				atom.CAS(1, 0)
				atom.Swap(5)
				atom.Store(1)
			}
		}()
	}
}

func TestStressInt64(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := &Int64{0}
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Add(1)
				atom.Sub(2)
				atom.Inc()
				atom.Dec()
				atom.CAS(1, 0)
				atom.Swap(5)
				atom.Store(1)
			}
		}()
	}
}

func TestStressUint32(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := &Uint32{0}
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Add(1)
				atom.Sub(2)
				atom.Inc()
				atom.Dec()
				atom.CAS(1, 0)
				atom.Swap(5)
				atom.Store(1)
			}
		}()
	}
}

func TestStressUint64(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := &Uint64{0}
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Add(1)
				atom.Sub(2)
				atom.Inc()
				atom.Dec()
				atom.CAS(1, 0)
				atom.Swap(5)
				atom.Store(1)
			}
		}()
	}
}

func TestStressBool(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := NewBool(false)
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Store(false)
				atom.Swap(true)
				atom.Load()
				atom.Toggle()
				atom.Toggle()
			}
		}()
	}
}

func TestStressString(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))
	atom := NewString("")
	for i := 0; i < _parallelism; i++ {
		go func() {
			for j := 0; j < _iterations; j++ {
				atom.Load()
				atom.Store("abc")
				atom.Load()
				atom.Store("def")
			}
		}()
	}
}
<commit_msg>Refactor stress tests and wait for the results<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package atomic

import (
	"runtime"
	"sync"
	"testing"
)

const (
	_parallelism = 4
	_iterations  = 1000
)

func runStress(f func()) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(_parallelism))

	var wg sync.WaitGroup
	wg.Add(_parallelism)
	for i := 0; i < _parallelism; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < _iterations; j++ {
				f()
			}
		}()
	}

	wg.Wait()
}

func TestStressInt32(t *testing.T) {
	var atom Int32
	runStress(func() {
		atom.Load()
		atom.Add(1)
		atom.Sub(2)
		atom.Inc()
		atom.Dec()
		atom.CAS(1, 0)
		atom.Swap(5)
		atom.Store(1)
	})
}

func TestStressInt64(t *testing.T) {
	var atom Int64
	runStress(func() {
		atom.Load()
		atom.Add(1)
		atom.Sub(2)
		atom.Inc()
		atom.Dec()
		atom.CAS(1, 0)
		atom.Swap(5)
		atom.Store(1)

	})
}

func TestStressUint32(t *testing.T) {
	var atom Uint32
	runStress(func() {
		atom.Load()
		atom.Add(1)
		atom.Sub(2)
		atom.Inc()
		atom.Dec()
		atom.CAS(1, 0)
		atom.Swap(5)
		atom.Store(1)
	})
}

func TestStressUint64(t *testing.T) {
	var atom Uint64
	runStress(func() {
		atom.Load()
		atom.Add(1)
		atom.Sub(2)
		atom.Inc()
		atom.Dec()
		atom.CAS(1, 0)
		atom.Swap(5)
		atom.Store(1)
	})
}

func TestStressBool(t *testing.T) {
	var atom Bool
	runStress(func() {
		atom.Load()
		atom.Store(false)
		atom.Swap(true)
		atom.Load()
		atom.Toggle()
		atom.Toggle()
	})
}

func TestStressString(t *testing.T) {
	var atom String
	runStress(func() {
		atom.Load()
		atom.Store("abc")
		atom.Load()
		atom.Store("def")

	})
}
<|endoftext|>


<commit_before>package slices

import (
	"fmt"
	"reflect"
	"testing"
)

// https://golang.org/cmd/go/#hdr-Description_of_testing_flags
// go test -v -bench string_test.go -benchtime 2s

var ()

func TestIsEmpty(t *testing.T) {

	if err := expect(IsEmpty([]string{}), true); err != nil {
		t.Error(err)
	}

	if err := expect(IsEmpty([]string{""}), true); err != nil {
		t.Error(err)
	}

	if err := expect(IsEmpty([]string{"a", "b", "c"}), false); err != nil {
		t.Error(err)
	}
}

func TestConcat(t *testing.T) {

	if err := expect(Concat([]string{}), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Concat([]string{""}), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Concat([]string{"a", "b", "c"}), "abc"); err != nil {
		t.Error(err)
	}
}

func TestJoin(t *testing.T) {

	if err := expect(Join([]string{}, "-"), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Join([]string{""}, "-"), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Join([]string{"a", "b", "c"}, "-"), "a-b-c"); err != nil {
		t.Error(err)
	}
}

func TestCut(t *testing.T) {

	if err := expect(Cut([]string{}, 0, -1), []string{}); err != nil {
		t.Error(err)
	}

	if err := expectNot(Cut([]string{}, 0, -1), []string{""}); err != nil {
		t.Error(err)
	}

	if err := expect(Cut([]string{""}, 0, -1), []string{""}); err != nil {
		t.Error(err)
	}
}

// func BenchmarkStringsReplaceAll(b *testing.B) {
// 	for i := 0; i < b.N; i++ {
// 		strings.Replace(TestFileContent, ToFind, ToReplace, -1)
// 	}
// }

func expect(args ...interface{}) error {
	switch len(args) {
	case 0, 1:
		return fmt.Errorf("Not enough arguments to expect. Args passed: %v", args)
	default:
		return _expect(true, args...)
	}
}

func expectNot(args ...interface{}) error {
	switch len(args) {
	case 0, 1:
		return fmt.Errorf("Not enough arguments to expect. Args passed: %v", args)
	default:
		return _expect(false, args...)
	}
}

func _expect(boolWanted bool, args ...interface{}) error {

	result := args[0]
	expected := args[1]

	if boolReceived := _areEqual(result, expected); boolReceived != boolWanted {
		return errExpected(boolWanted, args...)
	}
	return nil
}

func _areEqual(result interface{}, expected interface{}) bool {
	return reflect.DeepEqual(result, expected)
}

func errExpected(boolWanted bool, args ...interface{}) error {

	condition := "to equal"
	if boolWanted == false {
		condition = "not to equal"
	}

	result := args[0]
	expected := args[1]

	switch len(args) {
	case 2:
		return fmt.Errorf("Expected '%v' %v '%v'", result, condition, expected)
	default:
		return fmt.Errorf("%v: Expected '%v' %v '%v'", args[2], result, condition, expected)
	}
}
<commit_msg>IsSameArray() test<commit_after>package slices

import (
	"fmt"
	"reflect"
	"testing"
)

// https://golang.org/cmd/go/#hdr-Description_of_testing_flags
// go test -v -bench string_test.go -benchtime 2s

var ()

func TestIsEmpty(t *testing.T) {

	if err := expect(IsEmpty([]string{}), true); err != nil {
		t.Error(err)
	}

	if err := expect(IsEmpty([]string{""}), true); err != nil {
		t.Error(err)
	}

	if err := expect(IsEmpty([]string{"a", "b", "c"}), false); err != nil {
		t.Error(err)
	}
}

func TestConcat(t *testing.T) {

	if err := expect(Concat([]string{}), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Concat([]string{""}), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Concat([]string{"a", "b", "c"}), "abc"); err != nil {
		t.Error(err)
	}
}

func TestJoin(t *testing.T) {

	if err := expect(Join([]string{}, "-"), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Join([]string{""}, "-"), ""); err != nil {
		t.Error(err)
	}

	if err := expect(Join([]string{"a", "b", "c"}, "-"), "a-b-c"); err != nil {
		t.Error(err)
	}
}

func TestCut(t *testing.T) {

	if err := expect(Cut([]string{}, 0, -1), []string{}); err != nil {
		t.Error(err)
	}

	if err := expectNot(Cut([]string{}, 0, -1), []string{""}); err != nil {
		t.Error(err)
	}

	if err := expect(Cut([]string{""}, 0, -1), []string{""}); err != nil {
		t.Error(err)
	}
}

func TestIsSameArray(t *testing.T) {
	slc1 := []string{"same elements,", "different arrays"}
	if slc2 := Cut(slc1, 0, -1); IsSameArray(slc2, slc1) {
		t.Error(errExpected(false, slc2, slc1))
	}
}

// func BenchmarkStringsReplaceAll(b *testing.B) {
// 	for i := 0; i < b.N; i++ {
// 		strings.Replace(TestFileContent, ToFind, ToReplace, -1)
// 	}
// }

func expect(args ...interface{}) error {
	switch len(args) {
	case 0, 1:
		return fmt.Errorf("Not enough arguments to expect. Args passed: %v", args)
	default:
		return _expect(true, args...)
	}
}

func expectNot(args ...interface{}) error {
	switch len(args) {
	case 0, 1:
		return fmt.Errorf("Not enough arguments to expect. Args passed: %v", args)
	default:
		return _expect(false, args...)
	}
}

func _expect(boolWanted bool, args ...interface{}) error {

	result := args[0]
	expected := args[1]

	if boolReceived := _areEqual(result, expected); boolReceived != boolWanted {
		return errExpected(boolWanted, args...)
	}
	return nil
}

func _areEqual(result interface{}, expected interface{}) bool {
	return reflect.DeepEqual(result, expected)
}

func errExpected(boolWanted bool, args ...interface{}) error {

	condition := "to equal"
	if boolWanted == false {
		condition = "not to equal"
	}

	result := args[0]
	expected := args[1]

	switch len(args) {
	case 2:
		return fmt.Errorf("Expected '%v' %v '%v'", result, condition, expected)
	default:
		return fmt.Errorf("%v: Expected '%v' %v '%v'", args[2], result, condition, expected)
	}
}
<|endoftext|>


<commit_before>/* Copyright 2012 Marc-Antoine Ruel. 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 subcommands permits a Go application to implement subcommands support
// similar to what is supported by the 'go' tool.
//
// The library is designed so that the test cases can run concurrently.
// Using global flags variables is discouraged to keep your program testable
// conccurently.
package subcommands

import (
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"text/template"
)

// Application describes an application with subcommand support.
type Application interface {
	// GetName returns the 'name' of the application.
	GetName() string

	// GetTitle returns a one-line title explaining the purpose of the tool.
	GetTitle() string

	// GetCommands returns the list of the subcommands that are supported.
	GetCommands() []*Command

	// GetOut is used for testing to allow parallel test case execution, should
	// be normally os.Stdout.
	GetOut() io.Writer

	// GetOut is used for testing to allow parallel test case execution, should
	// be normally os.Stderr.
	GetErr() io.Writer
}

// DefaultApplication implements all of Application interface's methods. An
// application should usually have a global instance of DefaultApplication and
// route main() to command_support.Run(app).
type DefaultApplication struct {
	Name     string
	Title    string
	Commands []*Command
}

// GetName implements interface Application.
func (a *DefaultApplication) GetName() string {
	return a.Name
}

// GetTitle implements interface Application.
func (a *DefaultApplication) GetTitle() string {
	return a.Title
}

// GetNCommands implements interface Application.
func (a *DefaultApplication) GetCommands() []*Command {
	return a.Commands
}

// GetOut implements interface Application.
func (a *DefaultApplication) GetOut() io.Writer {
	return os.Stdout
}

// GetErr implements interface Application.
func (a *DefaultApplication) GetErr() io.Writer {
	return os.Stderr
}

// CommandRun is an initialized object representing a subcommand that is ready
// to be executed.
type CommandRun interface {
	// Run execute the actual command. When this function is called by
	// command_support.Run(), the flags have already been parsed.
	Run(a Application, args []string) int

	// GetFlags returns the flags for this specific command.
	GetFlags() *flag.FlagSet
}

// Command describes a subcommand. It has one generator to generate a command
// object which is executable. The purpose of this design is to enable safe
// parallel execution of test cases.
type Command struct {
	UsageLine  string
	ShortDesc  string
	LongDesc   string
	CommandRun func() CommandRun
}

// CommandRunBase implements GetFlags of CommandRun. It should be embedded in
// another struct that implements Run().
type CommandRunBase struct {
	Flags flag.FlagSet
}

// GetFlags implements CommandRun.
func (c *CommandRunBase) GetFlags() *flag.FlagSet {
	return &c.Flags
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// usage prints out the general application usage.
//
// TODO(maruel): Use termbox-go to enable coloring!
func usage(out io.Writer, a Application) {
	usageTemplate := `{{.GetTitle}}

Usage:  {{.GetName}} [command] [arguments]

Commands:{{range .GetCommands}}
  {{.Name | printf "%-11s"}} {{.ShortDesc}}{{end}}

Use "{{.GetName}} help [command]" for more information about a command.

`
	tmpl(out, usageTemplate, a)
}

func getCommandUsageHandler(out io.Writer, a Application, c *Command, r CommandRun, helpUsed *bool) func() {
	return func() {
		helpTemplate := "{{.Cmd.LongDesc | trim | wrapWithLines}}usage:  {{.App.GetName}} {{.Cmd.UsageLine}}\n"
		dict := struct {
			App Application
			Cmd *Command
		}{a, c}
		tmpl(out, helpTemplate, dict)
		r.GetFlags().PrintDefaults()
		*helpUsed = true
	}
}

// Initializes the flags for a specific CommandRun.
func initCommand(a Application, c *Command, r CommandRun, out io.Writer, helpUsed *bool) {
	r.GetFlags().Usage = getCommandUsageHandler(out, a, c, r, helpUsed)
	r.GetFlags().SetOutput(out)
	r.GetFlags().Init(c.Name(), flag.ContinueOnError)
}

// FindCommand finds a Command by name and returns it if found.
func FindCommand(a Application, name string) *Command {
	for _, c := range a.GetCommands() {
		if c.Name() == name {
			return c
		}
	}
	return nil
}

// Run runs the application, scheduling the subcommand. This is the main entry
// point of the library.
func Run(a Application, args []string) int {
	var helpUsed bool

	// Process general flags first, mainly for -help.
	flag.Usage = func() {
		usage(a.GetErr(), a)
		helpUsed = true
	}

	// Do not parse during unit tests because flag.commandLine.errorHandling == ExitOnError. :(
	// It is safer to use a base class embedding CommandRunBase that is then
	// embedded by each CommandRun implementation to define flags available for
	// all commands.
	if args == nil {
		flag.Parse()
		args = flag.Args()
	}

	if len(args) < 1 {
		// Need a command.
		usage(a.GetErr(), a)
		return 2
	}

	if c := FindCommand(a, args[0]); c != nil {
		// Initialize the flags.
		r := c.CommandRun()
		initCommand(a, c, r, a.GetErr(), &helpUsed)
		if err := r.GetFlags().Parse(args[1:]); err != nil {
			return 2
		}
		if helpUsed {
			return 0
		}
		return r.Run(a, r.GetFlags().Args())
	}

	fmt.Fprintf(a.GetErr(), "%s: unknown command %#q\n\nRun '%s help' for usage.\n", a.GetName(), args[0], a.GetName())
	return 2
}

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "wrapWithLines": wrapWithLines})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(fmt.Sprintf("Failed to execute templare: %s", err))
	}
}

func wrapWithLines(s string) string {
	if s == "" {
		return s
	}
	return s + "\n\n"
}

// Defines the help command. It should be included in your Commands list.
//
// It is not added automatically but it will be run automatically if added.
var CmdHelp = &Command{
	UsageLine:  "help <command>",
	ShortDesc:  "prints help about a command",
	LongDesc:   "Prints an overview of every commands or information about a specific command.",
	CommandRun: func() CommandRun { return &helpRun{} },
}

type helpRun struct {
	CommandRunBase
}

func (c *helpRun) Run(a Application, args []string) int {
	if len(args) == 0 {
		usage(a.GetOut(), a)
		return 0
	}
	if len(args) != 1 {
		fmt.Fprintf(a.GetErr(), "%s: Too many arguments given\n\nRun '%s help' for usage.\n", a.GetName(), a.GetName())
		return 2
	}
	// Redirects all output to Out.
	var helpUsed bool
	if cmd := FindCommand(a, args[0]); cmd != nil {
		// Initialize the flags.
		r := cmd.CommandRun()
		initCommand(a, cmd, r, a.GetErr(), &helpUsed)
		r.GetFlags().Usage()
		return 0
	}

	fmt.Fprintf(a.GetErr(), "%s: unknown command %#q\n\nRun '%s help' for usage.\n", a.GetName(), args[0], a.GetName())
	return 2
}
<commit_msg>Fix typo<commit_after>/* Copyright 2012 Marc-Antoine Ruel. 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 subcommands permits a Go application to implement subcommands support
// similar to what is supported by the 'go' tool.
//
// The library is designed so that the test cases can run concurrently.
// Using global flags variables is discouraged to keep your program testable
// conccurently.
package subcommands

import (
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
	"text/template"
)

// Application describes an application with subcommand support.
type Application interface {
	// GetName returns the 'name' of the application.
	GetName() string

	// GetTitle returns a one-line title explaining the purpose of the tool.
	GetTitle() string

	// GetCommands returns the list of the subcommands that are supported.
	GetCommands() []*Command

	// GetOut is used for testing to allow parallel test case execution, should
	// be normally os.Stdout.
	GetOut() io.Writer

	// GetOut is used for testing to allow parallel test case execution, should
	// be normally os.Stderr.
	GetErr() io.Writer
}

// DefaultApplication implements all of Application interface's methods. An
// application should usually have a global instance of DefaultApplication and
// route main() to command_support.Run(app).
type DefaultApplication struct {
	Name     string
	Title    string
	Commands []*Command
}

// GetName implements interface Application.
func (a *DefaultApplication) GetName() string {
	return a.Name
}

// GetTitle implements interface Application.
func (a *DefaultApplication) GetTitle() string {
	return a.Title
}

// GetCommands implements interface Application.
func (a *DefaultApplication) GetCommands() []*Command {
	return a.Commands
}

// GetOut implements interface Application.
func (a *DefaultApplication) GetOut() io.Writer {
	return os.Stdout
}

// GetErr implements interface Application.
func (a *DefaultApplication) GetErr() io.Writer {
	return os.Stderr
}

// CommandRun is an initialized object representing a subcommand that is ready
// to be executed.
type CommandRun interface {
	// Run execute the actual command. When this function is called by
	// command_support.Run(), the flags have already been parsed.
	Run(a Application, args []string) int

	// GetFlags returns the flags for this specific command.
	GetFlags() *flag.FlagSet
}

// Command describes a subcommand. It has one generator to generate a command
// object which is executable. The purpose of this design is to enable safe
// parallel execution of test cases.
type Command struct {
	UsageLine  string
	ShortDesc  string
	LongDesc   string
	CommandRun func() CommandRun
}

// CommandRunBase implements GetFlags of CommandRun. It should be embedded in
// another struct that implements Run().
type CommandRunBase struct {
	Flags flag.FlagSet
}

// GetFlags implements CommandRun.
func (c *CommandRunBase) GetFlags() *flag.FlagSet {
	return &c.Flags
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

// usage prints out the general application usage.
//
// TODO(maruel): Use termbox-go to enable coloring!
func usage(out io.Writer, a Application) {
	usageTemplate := `{{.GetTitle}}

Usage:  {{.GetName}} [command] [arguments]

Commands:{{range .GetCommands}}
  {{.Name | printf "%-11s"}} {{.ShortDesc}}{{end}}

Use "{{.GetName}} help [command]" for more information about a command.

`
	tmpl(out, usageTemplate, a)
}

func getCommandUsageHandler(out io.Writer, a Application, c *Command, r CommandRun, helpUsed *bool) func() {
	return func() {
		helpTemplate := "{{.Cmd.LongDesc | trim | wrapWithLines}}usage:  {{.App.GetName}} {{.Cmd.UsageLine}}\n"
		dict := struct {
			App Application
			Cmd *Command
		}{a, c}
		tmpl(out, helpTemplate, dict)
		r.GetFlags().PrintDefaults()
		*helpUsed = true
	}
}

// Initializes the flags for a specific CommandRun.
func initCommand(a Application, c *Command, r CommandRun, out io.Writer, helpUsed *bool) {
	r.GetFlags().Usage = getCommandUsageHandler(out, a, c, r, helpUsed)
	r.GetFlags().SetOutput(out)
	r.GetFlags().Init(c.Name(), flag.ContinueOnError)
}

// FindCommand finds a Command by name and returns it if found.
func FindCommand(a Application, name string) *Command {
	for _, c := range a.GetCommands() {
		if c.Name() == name {
			return c
		}
	}
	return nil
}

// Run runs the application, scheduling the subcommand. This is the main entry
// point of the library.
func Run(a Application, args []string) int {
	var helpUsed bool

	// Process general flags first, mainly for -help.
	flag.Usage = func() {
		usage(a.GetErr(), a)
		helpUsed = true
	}

	// Do not parse during unit tests because flag.commandLine.errorHandling == ExitOnError. :(
	// It is safer to use a base class embedding CommandRunBase that is then
	// embedded by each CommandRun implementation to define flags available for
	// all commands.
	if args == nil {
		flag.Parse()
		args = flag.Args()
	}

	if len(args) < 1 {
		// Need a command.
		usage(a.GetErr(), a)
		return 2
	}

	if c := FindCommand(a, args[0]); c != nil {
		// Initialize the flags.
		r := c.CommandRun()
		initCommand(a, c, r, a.GetErr(), &helpUsed)
		if err := r.GetFlags().Parse(args[1:]); err != nil {
			return 2
		}
		if helpUsed {
			return 0
		}
		return r.Run(a, r.GetFlags().Args())
	}

	fmt.Fprintf(a.GetErr(), "%s: unknown command %#q\n\nRun '%s help' for usage.\n", a.GetName(), args[0], a.GetName())
	return 2
}

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "wrapWithLines": wrapWithLines})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(fmt.Sprintf("Failed to execute templare: %s", err))
	}
}

func wrapWithLines(s string) string {
	if s == "" {
		return s
	}
	return s + "\n\n"
}

// Defines the help command. It should be included in your Commands list.
//
// It is not added automatically but it will be run automatically if added.
var CmdHelp = &Command{
	UsageLine:  "help <command>",
	ShortDesc:  "prints help about a command",
	LongDesc:   "Prints an overview of every commands or information about a specific command.",
	CommandRun: func() CommandRun { return &helpRun{} },
}

type helpRun struct {
	CommandRunBase
}

func (c *helpRun) Run(a Application, args []string) int {
	if len(args) == 0 {
		usage(a.GetOut(), a)
		return 0
	}
	if len(args) != 1 {
		fmt.Fprintf(a.GetErr(), "%s: Too many arguments given\n\nRun '%s help' for usage.\n", a.GetName(), a.GetName())
		return 2
	}
	// Redirects all output to Out.
	var helpUsed bool
	if cmd := FindCommand(a, args[0]); cmd != nil {
		// Initialize the flags.
		r := cmd.CommandRun()
		initCommand(a, cmd, r, a.GetErr(), &helpUsed)
		r.GetFlags().Usage()
		return 0
	}

	fmt.Fprintf(a.GetErr(), "%s: unknown command %#q\n\nRun '%s help' for usage.\n", a.GetName(), args[0], a.GetName())
	return 2
}
<|endoftext|>