<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/drone/drone-go/drone"
	"github.com/joho/godotenv"
	"golang.org/x/oauth2"
)

// Plugin defines the Downstream plugin parameters.
type Plugin struct {
	Repos          []string
	Server         string
	Host           string
	Proto          string
	Token          string
	Wait           bool
	Timeout        time.Duration
	LastSuccessful bool
	Params         []string
	ParamsEnv      []string
	Deploy         string
}

// Exec runs the plugin
func (p *Plugin) Exec() error {
	if len(p.Token) == 0 {
		return fmt.Errorf("Error: you must provide your Drone access token.")
	}

	p.Server = getServerWithDefaults(p.Server, p.Host, p.Proto)
	if len(p.Server) == 0 {
		return fmt.Errorf("Error: you must provide your Drone server.")
	}

	if p.Wait && p.LastSuccessful {
		return fmt.Errorf("Error: only one of wait and last_successful can be true; choose one")
	}

	params, err := parseParams(p.Params)
	if err != nil {
		return fmt.Errorf("Error: unable to parse params: %s.\n", err)
	}

	for _, k := range p.ParamsEnv {
		v, exists := os.LookupEnv(k)
		if !exists {
			return fmt.Errorf("Error: param_from_env %s is not set.\n", k)
		}

		params[k] = v
	}

	config := new(oauth2.Config)

	auther := config.Client(
		oauth2.NoContext,
		&oauth2.Token{
			AccessToken: p.Token,
		},
	)

	client := drone.NewClient(p.Server, auther)

	for _, entry := range p.Repos {

		// parses the repository name in owner/name@branch format
		owner, name, branch := parseRepoBranch(entry)
		if len(owner) == 0 || len(name) == 0 {
			return fmt.Errorf("Error: unable to parse repository name %s.\n", entry)
		}

		// check for mandatory build no during deploy trigger
		if len(p.Deploy) != 0 {
			if branch == "" {
				return fmt.Errorf("Error: build no or branch must be mentioned for deploy, format repository@build/branch")
			}
			if _, err := strconv.Atoi(branch); err != nil && !p.LastSuccessful {
				return fmt.Errorf("Error: for deploy build no must be numeric only " +
					" or for branch deploy last_successful should be true," +
					" format repository@build/branch")
			}
		}

		waiting := false

		timeout := time.After(p.Timeout)
		tick := time.Tick(1 * time.Second)

		// Keep trying until we're timed out, successful or got an error
		// Tagged with "I" due to break nested in select
	I:
		for {
			select {
			// Got a timeout! fail with a timeout error
			case <-timeout:
				return fmt.Errorf("Error: timed out waiting on a build for %s.\n", entry)
			// Got a tick, we should check on the build status
			case <-tick:
				// first handle the deploy trigger
				if len(p.Deploy) != 0 {
					var build *drone.Build
					if p.LastSuccessful {
						// Get the last successful build of branch
						builds, err := client.BuildList(owner, name, drone.ListOptions{})
						if err != nil {
							return fmt.Errorf("Error: unable to get build list for %s", entry)
						}

						for _, b := range builds {
							if b.Source == branch && b.Status == drone.StatusPassing {
								build = b
								break
							}
						}
						if build == nil {
							return fmt.Errorf("Error: unable to get last successful build for %s", entry)
						}
					} else {
						// Get build by number
						buildNumber, _ := strconv.Atoi(branch)
						build, err = client.Build(owner, name, buildNumber)
						if err != nil {
							return fmt.Errorf("Error: unable to get requested build %v for deploy for %s", buildNumber, entry)
						}
					}
					if p.Wait && !waiting && (build.Status == drone.StatusRunning || build.Status == drone.StatusPending) {
						fmt.Printf("BuildLast for repository: %s, returned build number: %v with a status of %s. Will retry for %v.\n", entry, build.Number, build.Status, p.Timeout)
						waiting = true
						continue
					}
					if (build.Status != drone.StatusRunning && build.Status != drone.StatusPending) || !p.Wait {
						// start a new deploy
						_, err = client.Promote(owner, name, int(build.Number), p.Deploy, params)
						if err != nil {
							if waiting {
								continue
							}
							return fmt.Errorf("Error: unable to trigger deploy for %s - err %v", entry, err)
						}
						fmt.Printf("Starting deploy for %s/%s env - %s build - %d.\n", owner, name, p.Deploy, build.Number)
						logParams(params, p.ParamsEnv)
						break I
					}
				}

				// get the latest build for the specified repository
				build, err := client.BuildLast(owner, name, branch)
				if err != nil {
					if waiting {
						continue
					}
					return fmt.Errorf("Error: unable to get latest build for %s.\n", entry)
				}
				if p.Wait && !waiting && (build.Status == drone.StatusRunning || build.Status == drone.StatusPending) {
					fmt.Printf("BuildLast for repository: %s, returned build number: %v with a status of %s. Will retry for %v.\n", entry, build.Number, build.Status, p.Timeout)
					waiting = true
					continue
				} else if p.LastSuccessful && build.Status != drone.StatusPassing {
					builds, err := client.BuildList(owner, name, drone.ListOptions{})
					if err != nil {
						return fmt.Errorf("Error: unable to get build list for %s.\n", entry)
					}

					build = nil
					for _, b := range builds {
						if b.Source == branch && b.Status == drone.StatusPassing {
							build = b
							break
						}
					}
					if build == nil {
						return fmt.Errorf("Error: unable to get last successful build for %s.\n", entry)
					}
				}

				if (build.Status != drone.StatusRunning && build.Status != drone.StatusPending) || !p.Wait {
					// rebuild the latest build
					_, err = client.BuildRestart(owner, name, int(build.Number), params)
					if err != nil {
						if waiting {
							continue
						}
						return fmt.Errorf("Error: unable to trigger build for %s.\n", entry)
					}
					fmt.Printf("Restarting build %d for %s\n", build.Number, entry)
					logParams(params, p.ParamsEnv)

					break I
				}
			}
		}
	}
	return nil
}

func parseRepoBranch(repo string) (string, string, string) {
	var (
		owner  string
		name   string
		branch string
	)

	parts := strings.Split(repo, "@")
	if len(parts) == 2 {
		branch = parts[1]
		repo = parts[0]
	}

	parts = strings.Split(repo, "/")
	if len(parts) == 2 {
		owner = parts[0]
		name = parts[1]
	}
	return owner, name, branch
}

func parseParams(paramList []string) (map[string]string, error) {
	params := make(map[string]string)
	for _, p := range paramList {
		parts := strings.SplitN(p, "=", 2)
		if len(parts) == 2 {
			params[parts[0]] = parts[1]
		} else if _, err := os.Stat(parts[0]); os.IsNotExist(err) {
			return nil, fmt.Errorf(
				"invalid param '%s'; must be KEY=VALUE or file path",
				parts[0],
			)
		} else {
			fileParams, err := godotenv.Read(parts[0])
			if err != nil {
				return nil, err
			}

			for k, v := range fileParams {
				params[k] = v
			}
		}
	}

	return params, nil
}

func logParams(params map[string]string, paramsEnv []string) {
	if len(params) > 0 {
		fmt.Println("  with params:")
		for k, v := range params {
			fromEnv := false
			for _, e := range paramsEnv {
				if k == e {
					fromEnv = true
					break
				}
			}
			if fromEnv {
				v = "[from-environment]"
			}
			fmt.Printf("  - %s: %s\n", k, v)
		}
	}
}

func getServerWithDefaults(server string, host string, protocol string) string {
	if len(server) != 0 {
		return server
	}

	if len(host) == 0 || len(protocol) == 0 {
		return ""
	}

	return fmt.Sprintf("%s://%s", protocol, host)
}
<commit_msg>Improve the logging when triggering builds<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/drone/drone-go/drone"
	"github.com/joho/godotenv"
	"golang.org/x/oauth2"
)

// Plugin defines the Downstream plugin parameters.
type Plugin struct {
	Repos          []string
	Server         string
	Host           string
	Proto          string
	Token          string
	Wait           bool
	Timeout        time.Duration
	LastSuccessful bool
	Params         []string
	ParamsEnv      []string
	Deploy         string
}

// Exec runs the plugin
func (p *Plugin) Exec() error {
	if len(p.Token) == 0 {
		return fmt.Errorf("Error: you must provide your Drone access token.")
	}

	p.Server = getServerWithDefaults(p.Server, p.Host, p.Proto)
	if len(p.Server) == 0 {
		return fmt.Errorf("Error: you must provide your Drone server.")
	}

	if p.Wait && p.LastSuccessful {
		return fmt.Errorf("Error: only one of wait and last_successful can be true; choose one")
	}

	params, err := parseParams(p.Params)
	if err != nil {
		return fmt.Errorf("Error: unable to parse params: %s.\n", err)
	}

	for _, k := range p.ParamsEnv {
		v, exists := os.LookupEnv(k)
		if !exists {
			return fmt.Errorf("Error: param_from_env %s is not set.\n", k)
		}

		params[k] = v
	}

	config := new(oauth2.Config)

	auther := config.Client(
		oauth2.NoContext,
		&oauth2.Token{
			AccessToken: p.Token,
		},
	)

	client := drone.NewClient(p.Server, auther)

	for _, entry := range p.Repos {

		// parses the repository name in owner/name@branch format
		owner, name, branch := parseRepoBranch(entry)
		if len(owner) == 0 || len(name) == 0 {
			return fmt.Errorf("Error: unable to parse repository name %s.\n", entry)
		}

		// check for mandatory build no during deploy trigger
		if len(p.Deploy) != 0 {
			if branch == "" {
				return fmt.Errorf("Error: build no or branch must be mentioned for deploy, format repository@build/branch")
			}
			if _, err := strconv.Atoi(branch); err != nil && !p.LastSuccessful {
				return fmt.Errorf("Error: for deploy build no must be numeric only " +
					" or for branch deploy last_successful should be true," +
					" format repository@build/branch")
			}
		}

		waiting := false

		timeout := time.After(p.Timeout)
		tick := time.Tick(1 * time.Second)

		// Keep trying until we're timed out, successful or got an error
		// Tagged with "I" due to break nested in select
	I:
		for {
			select {
			// Got a timeout! fail with a timeout error
			case <-timeout:
				return fmt.Errorf("Error: timed out waiting on a build for %s.\n", entry)
			// Got a tick, we should check on the build status
			case <-tick:
				// first handle the deploy trigger
				if len(p.Deploy) != 0 {
					var build *drone.Build
					if p.LastSuccessful {
						// Get the last successful build of branch
						builds, err := client.BuildList(owner, name, drone.ListOptions{})
						if err != nil {
							return fmt.Errorf("Error: unable to get build list for %s", entry)
						}

						for _, b := range builds {
							if b.Source == branch && b.Status == drone.StatusPassing {
								build = b
								break
							}
						}
						if build == nil {
							return fmt.Errorf("Error: unable to get last successful build for %s", entry)
						}
					} else {
						// Get build by number
						buildNumber, _ := strconv.Atoi(branch)
						build, err = client.Build(owner, name, buildNumber)
						if err != nil {
							return fmt.Errorf("Error: unable to get requested build %v for deploy for %s", buildNumber, entry)
						}
					}
					if p.Wait && !waiting && (build.Status == drone.StatusRunning || build.Status == drone.StatusPending) {
						fmt.Printf("BuildLast for repository: %s, returned build number: %v with a status of %s. Will retry for %v.\n", entry, build.Number, build.Status, p.Timeout)
						waiting = true
						continue
					}
					if (build.Status != drone.StatusRunning && build.Status != drone.StatusPending) || !p.Wait {
						// start a new deploy
						_, err = client.Promote(owner, name, int(build.Number), p.Deploy, params)
						if err != nil {
							if waiting {
								continue
							}
							return fmt.Errorf("Error: unable to trigger deploy for %s - err %v", entry, err)
						}
						fmt.Printf("Starting deploy for %s/%s env - %s build - %d.\n", owner, name, p.Deploy, build.Number)
						logParams(params, p.ParamsEnv)
						break I
					}
				}

				// get the latest build for the specified repository
				build, err := client.BuildLast(owner, name, branch)
				if err != nil {
					if waiting {
						continue
					}
					return fmt.Errorf("Error: unable to get latest build for %s: %s.\n", entry, err)
				}
				if p.Wait && !waiting && (build.Status == drone.StatusRunning || build.Status == drone.StatusPending) {
					fmt.Printf("BuildLast for repository: %s, returned build number: %v with a status of %s. Will retry for %v.\n", entry, build.Number, build.Status, p.Timeout)
					waiting = true
					continue
				} else if p.LastSuccessful && build.Status != drone.StatusPassing {
					builds, err := client.BuildList(owner, name, drone.ListOptions{})
					if err != nil {
						return fmt.Errorf("Error: unable to get build list for %s.\n", entry)
					}

					build = nil
					for _, b := range builds {
						if b.Source == branch && b.Status == drone.StatusPassing {
							build = b
							break
						}
					}
					if build == nil {
						return fmt.Errorf("Error: unable to get last successful build for %s.\n", entry)
					}
				}

				if (build.Status != drone.StatusRunning && build.Status != drone.StatusPending) || !p.Wait {
					// rebuild the latest build
					_, err = client.BuildRestart(owner, name, int(build.Number), params)
					if err != nil {
						if waiting {
							continue
						}
						return fmt.Errorf("Error: unable to trigger build for %s.\n", entry)
					}
					fmt.Printf("Restarting build %d for %s\n", build.Number, entry)
					logParams(params, p.ParamsEnv)

					break I
				}
			}
		}
	}
	return nil
}

func parseRepoBranch(repo string) (string, string, string) {
	var (
		owner  string
		name   string
		branch string
	)

	parts := strings.Split(repo, "@")
	if len(parts) == 2 {
		branch = parts[1]
		repo = parts[0]
	}

	parts = strings.Split(repo, "/")
	if len(parts) == 2 {
		owner = parts[0]
		name = parts[1]
	}
	return owner, name, branch
}

func parseParams(paramList []string) (map[string]string, error) {
	params := make(map[string]string)
	for _, p := range paramList {
		parts := strings.SplitN(p, "=", 2)
		if len(parts) == 2 {
			params[parts[0]] = parts[1]
		} else if _, err := os.Stat(parts[0]); os.IsNotExist(err) {
			return nil, fmt.Errorf(
				"invalid param '%s'; must be KEY=VALUE or file path",
				parts[0],
			)
		} else {
			fileParams, err := godotenv.Read(parts[0])
			if err != nil {
				return nil, err
			}

			for k, v := range fileParams {
				params[k] = v
			}
		}
	}

	return params, nil
}

func logParams(params map[string]string, paramsEnv []string) {
	if len(params) > 0 {
		fmt.Println("  with params:")
		for k, v := range params {
			fromEnv := false
			for _, e := range paramsEnv {
				if k == e {
					fromEnv = true
					break
				}
			}
			if fromEnv {
				v = "[from-environment]"
			}
			fmt.Printf("  - %s: %s\n", k, v)
		}
	}
}

func getServerWithDefaults(server string, host string, protocol string) string {
	if len(server) != 0 {
		return server
	}

	if len(host) == 0 || len(protocol) == 0 {
		return ""
	}

	return fmt.Sprintf("%s://%s", protocol, host)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
	"time"

	"golang.org/x/crypto/ssh"
)

const (
	missingHostOrUser    = "Error: missing server host or user"
	missingPasswordOrKey = "Error: can't connect without a private SSH key or password"
	unableConnectServer  = "Error: Failed to start a SSH session"
	failParsePrivateKey  = "Error: Failed to parse private key"
	sshKeyNotFound       = "ssh: no key found"
)

type (
	// Config for the plugin.
	Config struct {
		Key      string
		KeyPath  string
		User     string
		Password string
		Host     []string
		Port     int
		Sleep    int
		Timeout  time.Duration
		Script   []string
	}

	// Plugin structure
	Plugin struct {
		Config Config
	}
)

// returns ssh.Signer from user you running app home path + cutted key path.
// (ex. pubkey,err := getKeyFile("/.ssh/id_rsa") )
func getKeyFile(keypath string) (ssh.Signer, error) {
	buf, err := ioutil.ReadFile(keypath)
	if err != nil {
		return nil, err
	}

	pubkey, err := ssh.ParsePrivateKey(buf)
	if err != nil {
		return nil, err
	}

	return pubkey, nil
}

// Exec executes the plugin.
func (p Plugin) Exec() error {
	if len(p.Config.Host) == 0 && p.Config.User == "" {
		return fmt.Errorf(missingHostOrUser)
	}

	if p.Config.Key == "" && p.Config.Password == "" && p.Config.KeyPath == "" {
		return fmt.Errorf(missingPasswordOrKey)
	}

	for i, host := range p.Config.Host {
		addr := net.JoinHostPort(
			host,
			strconv.Itoa(p.Config.Port),
		)

		// auths holds the detected ssh auth methods
		auths := []ssh.AuthMethod{}

		if p.Config.KeyPath != "" {
			pubkey, err := getKeyFile(p.Config.KeyPath)

			if err != nil {
				return err
			}

			auths = append(auths, ssh.PublicKeys(pubkey))
		}

		if p.Config.Key != "" {
			signer, err := ssh.ParsePrivateKey([]byte(p.Config.Key))

			if err != nil {
				return fmt.Errorf(failParsePrivateKey)
			}

			auths = append(auths, ssh.PublicKeys(signer))
		}

		// figure out what auths are requested, what is supported
		if p.Config.Password != "" {
			auths = append(auths, ssh.Password(p.Config.Password))
		}

		config := &ssh.ClientConfig{
			Timeout: p.Config.Timeout,
			User:    p.Config.User,
			Auth:    auths,
		}

		log.Printf("+ ssh %s@%s -p %d\n", p.Config.User, addr, p.Config.Port)
		client, err := ssh.Dial("tcp", addr, config)

		if err != nil {
			return fmt.Errorf(unableConnectServer)
		}

		session, _ := client.NewSession()
		defer session.Close()

		session.Stdout = os.Stdout
		session.Stderr = os.Stderr

		if err := session.Run(strings.Join(p.Config.Script, "\n")); err != nil {
			return err
		}

		if p.Config.Sleep != 0 && i != len(p.Config.Host)-1 {
			log.Printf("+ sleep %d\n", p.Config.Sleep)
			time.Sleep(time.Duration(p.Config.Sleep) * time.Second)
		}
	}

	return nil
}
<commit_msg>docs: remove duplicated of port config. (#36)<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strconv"
	"strings"
	"time"

	"golang.org/x/crypto/ssh"
)

const (
	missingHostOrUser    = "Error: missing server host or user"
	missingPasswordOrKey = "Error: can't connect without a private SSH key or password"
	unableConnectServer  = "Error: Failed to start a SSH session"
	failParsePrivateKey  = "Error: Failed to parse private key"
	sshKeyNotFound       = "ssh: no key found"
)

type (
	// Config for the plugin.
	Config struct {
		Key      string
		KeyPath  string
		User     string
		Password string
		Host     []string
		Port     int
		Sleep    int
		Timeout  time.Duration
		Script   []string
	}

	// Plugin structure
	Plugin struct {
		Config Config
	}
)

// returns ssh.Signer from user you running app home path + cutted key path.
// (ex. pubkey,err := getKeyFile("/.ssh/id_rsa") )
func getKeyFile(keypath string) (ssh.Signer, error) {
	buf, err := ioutil.ReadFile(keypath)
	if err != nil {
		return nil, err
	}

	pubkey, err := ssh.ParsePrivateKey(buf)
	if err != nil {
		return nil, err
	}

	return pubkey, nil
}

// Exec executes the plugin.
func (p Plugin) Exec() error {
	if len(p.Config.Host) == 0 && p.Config.User == "" {
		return fmt.Errorf(missingHostOrUser)
	}

	if p.Config.Key == "" && p.Config.Password == "" && p.Config.KeyPath == "" {
		return fmt.Errorf(missingPasswordOrKey)
	}

	for i, host := range p.Config.Host {
		addr := net.JoinHostPort(
			host,
			strconv.Itoa(p.Config.Port),
		)

		// auths holds the detected ssh auth methods
		auths := []ssh.AuthMethod{}

		if p.Config.KeyPath != "" {
			pubkey, err := getKeyFile(p.Config.KeyPath)

			if err != nil {
				return err
			}

			auths = append(auths, ssh.PublicKeys(pubkey))
		}

		if p.Config.Key != "" {
			signer, err := ssh.ParsePrivateKey([]byte(p.Config.Key))

			if err != nil {
				return fmt.Errorf(failParsePrivateKey)
			}

			auths = append(auths, ssh.PublicKeys(signer))
		}

		// figure out what auths are requested, what is supported
		if p.Config.Password != "" {
			auths = append(auths, ssh.Password(p.Config.Password))
		}

		config := &ssh.ClientConfig{
			Timeout: p.Config.Timeout,
			User:    p.Config.User,
			Auth:    auths,
		}

		log.Printf("+ ssh %s@%s \n", p.Config.User, addr)
		client, err := ssh.Dial("tcp", addr, config)

		if err != nil {
			return fmt.Errorf(unableConnectServer)
		}

		session, _ := client.NewSession()
		defer session.Close()

		session.Stdout = os.Stdout
		session.Stderr = os.Stderr

		if err := session.Run(strings.Join(p.Config.Script, "\n")); err != nil {
			return err
		}

		if p.Config.Sleep != 0 && i != len(p.Config.Host)-1 {
			log.Printf("+ sleep %d\n", p.Config.Sleep)
			time.Sleep(time.Duration(p.Config.Sleep) * time.Second)
		}
	}

	return nil
}
<|endoftext|>


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

package imports

import (
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"code.google.com/p/go.tools/astutil"
)

// importToGroup is a list of functions which map from an import path to
// a group number.
var importToGroup = []func(importPath string) (num int, ok bool){
	func(importPath string) (num int, ok bool) {
		if strings.HasPrefix(importPath, "appengine") {
			return 2, true
		}
		return
	},
	func(importPath string) (num int, ok bool) {
		if strings.Contains(importPath, ".") {
			return 1, true
		}
		return
	},
}

func importGroup(importPath string) int {
	for _, fn := range importToGroup {
		if n, ok := fn(importPath); ok {
			return n
		}
	}
	return 0
}

func fixImports(fset *token.FileSet, f *ast.File) (added []string, err error) {
	// refs are a set of possible package references currently unsatisified by imports.
	// first key: either base package (e.g. "fmt") or renamed package
	// second key: referenced package symbol (e.g. "Println")
	refs := make(map[string]map[string]bool)

	// decls are the current package imports. key is base package or renamed package.
	decls := make(map[string]*ast.ImportSpec)

	// collect potential uses of packages.
	var visitor visitFn
	visitor = visitFn(func(node ast.Node) ast.Visitor {
		if node == nil {
			return visitor
		}
		switch v := node.(type) {
		case *ast.ImportSpec:
			if v.Name != nil {
				decls[v.Name.Name] = v
			} else {
				local := importPathToName(strings.Trim(v.Path.Value, `\"`))
				decls[local] = v
			}
		case *ast.SelectorExpr:
			xident, ok := v.X.(*ast.Ident)
			if !ok {
				break
			}
			if xident.Obj != nil {
				// if the parser can resolve it, it's not a package ref
				break
			}
			pkgName := xident.Name
			if refs[pkgName] == nil {
				refs[pkgName] = make(map[string]bool)
			}
			if decls[pkgName] == nil {
				refs[pkgName][v.Sel.Name] = true
			}
		}
		return visitor
	})
	ast.Walk(visitor, f)

	// Search for imports matching potential package references.
	searches := 0
	type result struct {
		ipath string
		name  string
		err   error
	}
	results := make(chan result)
	for pkgName, symbols := range refs {
		if len(symbols) == 0 {
			continue // skip over packages already imported
		}
		go func(pkgName string, symbols map[string]bool) {
			ipath, rename, err := findImport(pkgName, symbols)
			r := result{ipath: ipath, err: err}
			if rename {
				r.name = pkgName
			}
			results <- r
		}(pkgName, symbols)
		searches++
	}
	for i := 0; i < searches; i++ {
		result := <-results
		if result.err != nil {
			return nil, result.err
		}
		if result.ipath != "" {
			if result.name != "" {
				astutil.AddNamedImport(fset, f, result.name, result.ipath)
			} else {
				astutil.AddImport(fset, f, result.ipath)
			}
			added = append(added, result.ipath)
		}
	}

	// Nil out any unused ImportSpecs, to be removed in following passes
	unusedImport := map[string]bool{}
	for pkg, is := range decls {
		if refs[pkg] == nil && pkg != "_" && pkg != "." {
			unusedImport[strings.Trim(is.Path.Value, `"`)] = true
		}
	}
	for ipath := range unusedImport {
		if ipath == "C" {
			// Don't remove cgo stuff.
			continue
		}
		astutil.DeleteImport(fset, f, ipath)
	}

	return added, nil
}

// importPathToName returns the package name for the given import path.
var importPathToName = importPathToNameGoPath

// importPathToNameBasic assumes the package name is the base of import path.
func importPathToNameBasic(importPath string) (packageName string) {
	return path.Base(importPath)
}

// importPathToNameGoPath finds out the actual package name, as declared in its .go files.
// If there's a problem, it falls back to using importPathToNameBasic.
func importPathToNameGoPath(importPath string) (packageName string) {
	if buildPkg, err := build.Import(importPath, "", 0); err == nil {
		return buildPkg.Name
	} else {
		return importPathToNameBasic(importPath)
	}
}

type pkg struct {
	importpath string // full pkg import path, e.g. "net/http"
	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
}

var pkgIndexOnce sync.Once

var pkgIndex struct {
	sync.Mutex
	m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http"
}

func loadPkgIndex() {
	pkgIndex.Lock()
	pkgIndex.m = make(map[string][]pkg)
	pkgIndex.Unlock()

	var wg sync.WaitGroup
	for _, path := range build.Default.SrcDirs() {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprint(os.Stderr, err)
			continue
		}
		children, err := f.Readdir(-1)
		f.Close()
		if err != nil {
			fmt.Fprint(os.Stderr, err)
			continue
		}
		for _, child := range children {
			if child.IsDir() {
				wg.Add(1)
				go func(path, name string) {
					defer wg.Done()
					loadPkg(&wg, path, name)
				}(path, child.Name())
			}
		}
	}
	wg.Wait()
}

func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) {
	importpath := filepath.ToSlash(pkgrelpath)
	shortName := importPathToName(importpath)

	dir := filepath.Join(root, importpath)
	pkgIndex.Lock()
	pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{
		importpath: importpath,
		dir:        dir,
	})
	pkgIndex.Unlock()

	pkgDir, err := os.Open(dir)
	if err != nil {
		return
	}
	children, err := pkgDir.Readdir(-1)
	pkgDir.Close()
	if err != nil {
		return
	}
	for _, child := range children {
		name := child.Name()
		if name == "" {
			continue
		}
		if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
			continue
		}
		if child.IsDir() {
			wg.Add(1)
			go func(root, name string) {
				defer wg.Done()
				loadPkg(wg, root, name)
			}(root, filepath.Join(importpath, name))
		}
	}
}

// loadExports returns a list exports for a package.
var loadExports = loadExportsGoPath

func loadExportsGoPath(dir string) map[string]bool {
	exports := make(map[string]bool)
	buildPkg, err := build.ImportDir(dir, 0)
	if err != nil {
		if strings.Contains(err.Error(), "no buildable Go source files in") {
			return nil
		}
		fmt.Fprintf(os.Stderr, "could not import %q: %v", dir, err)
		return nil
	}
	fset := token.NewFileSet()
	for _, file := range buildPkg.GoFiles {
		f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
		if err != nil {
			fmt.Fprintf(os.Stderr, "could not parse %q: %v", file, err)
			continue
		}
		for name := range f.Scope.Objects {
			if ast.IsExported(name) {
				exports[name] = true
			}
		}
	}
	return exports
}

// findImport searches for a package with the given symbols.
// If no package is found, findImport returns "".
// Declared as a variable rather than a function so goimports can be easily
// extended by adding a file with an init function.
var findImport = findImportGoPath

func findImportGoPath(pkgName string, symbols map[string]bool) (string, bool, error) {
	// Fast path for the standard library.
	// In the common case we hopefully never have to scan the GOPATH, which can
	// be slow with moving disks.
	if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok {
		return pkg, rename, nil
	}

	// TODO(sameer): look at the import lines for other Go files in the
	// local directory, since the user is likely to import the same packages
	// in the current Go file.  Return rename=true when the other Go files
	// use a renamed package that's also used in the current file.

	pkgIndexOnce.Do(loadPkgIndex)

	// Collect exports for packages with matching names.
	var wg sync.WaitGroup
	var pkgsMu sync.Mutex // guards pkgs
	// full importpath => exported symbol => True
	// e.g. "net/http" => "Client" => True
	pkgs := make(map[string]map[string]bool)
	pkgIndex.Lock()
	for _, pkg := range pkgIndex.m[pkgName] {
		wg.Add(1)
		go func(importpath, dir string) {
			defer wg.Done()
			exports := loadExports(dir)
			if exports != nil {
				pkgsMu.Lock()
				pkgs[importpath] = exports
				pkgsMu.Unlock()
			}
		}(pkg.importpath, pkg.dir)
	}
	pkgIndex.Unlock()
	wg.Wait()

	// Filter out packages missing required exported symbols.
	for symbol := range symbols {
		for importpath, exports := range pkgs {
			if !exports[symbol] {
				delete(pkgs, importpath)
			}
		}
	}
	if len(pkgs) == 0 {
		return "", false, nil
	}

	// If there are multiple candidate packages, the shortest one wins.
	// This is a heuristic to prefer the standard library (e.g. "bytes")
	// over e.g. "github.com/foo/bar/bytes".
	shortest := ""
	for importPath := range pkgs {
		if shortest == "" || len(importPath) < len(shortest) {
			shortest = importPath
		}
	}
	return shortest, false, nil
}

type visitFn func(node ast.Node) ast.Visitor

func (fn visitFn) Visit(node ast.Node) ast.Visitor {
	return fn(node)
}

func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) {
	for symbol := range symbols {
		path := stdlib[shortPkg+"."+symbol]
		if path == "" {
			return "", false, false
		}
		if importPath != "" && importPath != path {
			// Ambiguous. Symbols pointed to different things.
			return "", false, false
		}
		importPath = path
	}
	return importPath, false, importPath != ""
}
<commit_msg>imports: limit local disk concurrency, avoid reads in non-Go directories<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package imports

import (
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"code.google.com/p/go.tools/astutil"
)

// importToGroup is a list of functions which map from an import path to
// a group number.
var importToGroup = []func(importPath string) (num int, ok bool){
	func(importPath string) (num int, ok bool) {
		if strings.HasPrefix(importPath, "appengine") {
			return 2, true
		}
		return
	},
	func(importPath string) (num int, ok bool) {
		if strings.Contains(importPath, ".") {
			return 1, true
		}
		return
	},
}

func importGroup(importPath string) int {
	for _, fn := range importToGroup {
		if n, ok := fn(importPath); ok {
			return n
		}
	}
	return 0
}

func fixImports(fset *token.FileSet, f *ast.File) (added []string, err error) {
	// refs are a set of possible package references currently unsatisified by imports.
	// first key: either base package (e.g. "fmt") or renamed package
	// second key: referenced package symbol (e.g. "Println")
	refs := make(map[string]map[string]bool)

	// decls are the current package imports. key is base package or renamed package.
	decls := make(map[string]*ast.ImportSpec)

	// collect potential uses of packages.
	var visitor visitFn
	visitor = visitFn(func(node ast.Node) ast.Visitor {
		if node == nil {
			return visitor
		}
		switch v := node.(type) {
		case *ast.ImportSpec:
			if v.Name != nil {
				decls[v.Name.Name] = v
			} else {
				local := importPathToName(strings.Trim(v.Path.Value, `\"`))
				decls[local] = v
			}
		case *ast.SelectorExpr:
			xident, ok := v.X.(*ast.Ident)
			if !ok {
				break
			}
			if xident.Obj != nil {
				// if the parser can resolve it, it's not a package ref
				break
			}
			pkgName := xident.Name
			if refs[pkgName] == nil {
				refs[pkgName] = make(map[string]bool)
			}
			if decls[pkgName] == nil {
				refs[pkgName][v.Sel.Name] = true
			}
		}
		return visitor
	})
	ast.Walk(visitor, f)

	// Search for imports matching potential package references.
	searches := 0
	type result struct {
		ipath string
		name  string
		err   error
	}
	results := make(chan result)
	for pkgName, symbols := range refs {
		if len(symbols) == 0 {
			continue // skip over packages already imported
		}
		go func(pkgName string, symbols map[string]bool) {
			ipath, rename, err := findImport(pkgName, symbols)
			r := result{ipath: ipath, err: err}
			if rename {
				r.name = pkgName
			}
			results <- r
		}(pkgName, symbols)
		searches++
	}
	for i := 0; i < searches; i++ {
		result := <-results
		if result.err != nil {
			return nil, result.err
		}
		if result.ipath != "" {
			if result.name != "" {
				astutil.AddNamedImport(fset, f, result.name, result.ipath)
			} else {
				astutil.AddImport(fset, f, result.ipath)
			}
			added = append(added, result.ipath)
		}
	}

	// Nil out any unused ImportSpecs, to be removed in following passes
	unusedImport := map[string]bool{}
	for pkg, is := range decls {
		if refs[pkg] == nil && pkg != "_" && pkg != "." {
			unusedImport[strings.Trim(is.Path.Value, `"`)] = true
		}
	}
	for ipath := range unusedImport {
		if ipath == "C" {
			// Don't remove cgo stuff.
			continue
		}
		astutil.DeleteImport(fset, f, ipath)
	}

	return added, nil
}

// importPathToName returns the package name for the given import path.
var importPathToName = importPathToNameGoPath

// importPathToNameBasic assumes the package name is the base of import path.
func importPathToNameBasic(importPath string) (packageName string) {
	return path.Base(importPath)
}

// importPathToNameGoPath finds out the actual package name, as declared in its .go files.
// If there's a problem, it falls back to using importPathToNameBasic.
func importPathToNameGoPath(importPath string) (packageName string) {
	if buildPkg, err := build.Import(importPath, "", 0); err == nil {
		return buildPkg.Name
	} else {
		return importPathToNameBasic(importPath)
	}
}

type pkg struct {
	importpath string // full pkg import path, e.g. "net/http"
	dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
}

var pkgIndexOnce sync.Once

var pkgIndex struct {
	sync.Mutex
	m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http"
}

// gate is a semaphore for limiting concurrency.
type gate chan bool

func (g gate) enter() { g <- true }
func (g gate) leave() { <-g }

// fsgate protects the OS & filesystem from too much concurrency.
// Too much disk I/O -> too many threads -> swapping and bad scheduling.
var fsgate = make(gate, 8)

func loadPkgIndex() {
	pkgIndex.Lock()
	pkgIndex.m = make(map[string][]pkg)
	pkgIndex.Unlock()

	var wg sync.WaitGroup
	for _, path := range build.Default.SrcDirs() {
		fsgate.enter()
		f, err := os.Open(path)
		if err != nil {
			fsgate.leave()
			fmt.Fprint(os.Stderr, err)
			continue
		}
		children, err := f.Readdir(-1)
		f.Close()
		fsgate.leave()
		if err != nil {
			fmt.Fprint(os.Stderr, err)
			continue
		}
		for _, child := range children {
			if child.IsDir() {
				wg.Add(1)
				go func(path, name string) {
					defer wg.Done()
					loadPkg(&wg, path, name)
				}(path, child.Name())
			}
		}
	}
	wg.Wait()
}

func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) {
	importpath := filepath.ToSlash(pkgrelpath)
	dir := filepath.Join(root, importpath)

	fsgate.enter()
	defer fsgate.leave()
	pkgDir, err := os.Open(dir)
	if err != nil {
		return
	}
	children, err := pkgDir.Readdir(-1)
	pkgDir.Close()
	if err != nil {
		return
	}
	// hasGo tracks whether a directory actually appears to be a
	// Go source code directory. If $GOPATH == $HOME, and
	// $HOME/src has lots of other large non-Go projects in it,
	// then the calls to importPathToName below can be expensive.
	hasGo := false
	for _, child := range children {
		name := child.Name()
		if name == "" {
			continue
		}
		if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
			continue
		}
		if strings.HasSuffix(name, ".go") {
			hasGo = true
		}
		if child.IsDir() {
			wg.Add(1)
			go func(root, name string) {
				defer wg.Done()
				loadPkg(wg, root, name)
			}(root, filepath.Join(importpath, name))
		}
	}
	if hasGo {
		shortName := importPathToName(importpath)
		pkgIndex.Lock()
		pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{
			importpath: importpath,
			dir:        dir,
		})
		pkgIndex.Unlock()
	}

}

// loadExports returns a list exports for a package.
var loadExports = loadExportsGoPath

func loadExportsGoPath(dir string) map[string]bool {
	exports := make(map[string]bool)
	buildPkg, err := build.ImportDir(dir, 0)
	if err != nil {
		if strings.Contains(err.Error(), "no buildable Go source files in") {
			return nil
		}
		fmt.Fprintf(os.Stderr, "could not import %q: %v", dir, err)
		return nil
	}
	fset := token.NewFileSet()
	for _, file := range buildPkg.GoFiles {
		f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
		if err != nil {
			fmt.Fprintf(os.Stderr, "could not parse %q: %v", file, err)
			continue
		}
		for name := range f.Scope.Objects {
			if ast.IsExported(name) {
				exports[name] = true
			}
		}
	}
	return exports
}

// findImport searches for a package with the given symbols.
// If no package is found, findImport returns "".
// Declared as a variable rather than a function so goimports can be easily
// extended by adding a file with an init function.
var findImport = findImportGoPath

func findImportGoPath(pkgName string, symbols map[string]bool) (string, bool, error) {
	// Fast path for the standard library.
	// In the common case we hopefully never have to scan the GOPATH, which can
	// be slow with moving disks.
	if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok {
		return pkg, rename, nil
	}

	// TODO(sameer): look at the import lines for other Go files in the
	// local directory, since the user is likely to import the same packages
	// in the current Go file.  Return rename=true when the other Go files
	// use a renamed package that's also used in the current file.

	pkgIndexOnce.Do(loadPkgIndex)

	// Collect exports for packages with matching names.
	var wg sync.WaitGroup
	var pkgsMu sync.Mutex // guards pkgs
	// full importpath => exported symbol => True
	// e.g. "net/http" => "Client" => True
	pkgs := make(map[string]map[string]bool)
	pkgIndex.Lock()
	for _, pkg := range pkgIndex.m[pkgName] {
		wg.Add(1)
		go func(importpath, dir string) {
			defer wg.Done()
			exports := loadExports(dir)
			if exports != nil {
				pkgsMu.Lock()
				pkgs[importpath] = exports
				pkgsMu.Unlock()
			}
		}(pkg.importpath, pkg.dir)
	}
	pkgIndex.Unlock()
	wg.Wait()

	// Filter out packages missing required exported symbols.
	for symbol := range symbols {
		for importpath, exports := range pkgs {
			if !exports[symbol] {
				delete(pkgs, importpath)
			}
		}
	}
	if len(pkgs) == 0 {
		return "", false, nil
	}

	// If there are multiple candidate packages, the shortest one wins.
	// This is a heuristic to prefer the standard library (e.g. "bytes")
	// over e.g. "github.com/foo/bar/bytes".
	shortest := ""
	for importPath := range pkgs {
		if shortest == "" || len(importPath) < len(shortest) {
			shortest = importPath
		}
	}
	return shortest, false, nil
}

type visitFn func(node ast.Node) ast.Visitor

func (fn visitFn) Visit(node ast.Node) ast.Visitor {
	return fn(node)
}

func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) {
	for symbol := range symbols {
		path := stdlib[shortPkg+"."+symbol]
		if path == "" {
			return "", false, false
		}
		if importPath != "" && importPath != path {
			// Ambiguous. Symbols pointed to different things.
			return "", false, false
		}
		importPath = path
	}
	return importPath, false, importPath != ""
}
<|endoftext|>


<commit_before><commit_msg>Add missing return in error case<commit_after><|endoftext|>


<commit_before>package gin

import (
	"log"
	"net/http"
)

type (
	ResponseWriter interface {
		http.ResponseWriter
		Status() int
		Written() bool
		WriteHeaderNow()
	}

	responseWriter struct {
		http.ResponseWriter
		status  int
		written bool
	}
)

func (w *responseWriter) reset(writer http.ResponseWriter) {
	w.ResponseWriter = writer
	w.status = 200
	w.written = false
}

func (w *responseWriter) WriteHeader(code int) {
	if code != 0 {
		w.status = code
		if w.written {
			log.Println("[GIN] WARNING. Headers were already written!")
		}
	}
}

func (w *responseWriter) WriteHeaderNow() {
	if !w.written {
		w.written = true
		w.ResponseWriter.WriteHeader(w.status)
	}
}

func (w *responseWriter) Write(data []byte) (n int, err error) {
	w.WriteHeaderNow()
	return w.ResponseWriter.Write(data)
}

func (w *responseWriter) Status() int {
	return w.status
}

func (w *responseWriter) Written() bool {
	return w.written
}
<commit_msg>Fixes bug when status code is negative<commit_after>package gin

import (
	"log"
	"net/http"
)

type (
	ResponseWriter interface {
		http.ResponseWriter
		Status() int
		Written() bool
		WriteHeaderNow()
	}

	responseWriter struct {
		http.ResponseWriter
		status  int
		written bool
	}
)

func (w *responseWriter) reset(writer http.ResponseWriter) {
	w.ResponseWriter = writer
	w.status = 200
	w.written = false
}

func (w *responseWriter) WriteHeader(code int) {
	if code > 0 {
		w.status = code
		if w.written {
			log.Println("[GIN] WARNING. Headers were already written!")
		}
	}
}

func (w *responseWriter) WriteHeaderNow() {
	if !w.written {
		w.written = true
		w.ResponseWriter.WriteHeader(w.status)
	}
}

func (w *responseWriter) Write(data []byte) (n int, err error) {
	w.WriteHeaderNow()
	return w.ResponseWriter.Write(data)
}

func (w *responseWriter) Status() int {
	return w.status
}

func (w *responseWriter) Written() bool {
	return w.written
}
<|endoftext|>


<commit_before>package leetcode

import (
    "bytes"
    "strconv"
)

func reverse(x int) int {
    negative := false
    if x < 0 {
        negative = true
        x = -x
    }

    s := strconv.Itoa(x)
    size := len(s)

    var buffer bytes.Buffer
    if negative {
        buffer.WriteByte(45)
    }

    for i := size - 1; i >= 0; i-- {
        buffer.WriteByte(s[i])
    }

    num, err := strconv.ParseInt(buffer.String(), 10, 32)
    if err != nil {
        return 0
    }

    return int(num)
}

// uint8       the set of all unsigned  8-bit integers (0 to 255)
// uint16      the set of all unsigned 16-bit integers (0 to 65535)
// uint32      the set of all unsigned 32-bit integers (0 to 4294967295)
// uint64      the set of all unsigned 64-bit integers (0 to 18446744073709551615)

// int8        the set of all signed  8-bit integers (-128 to 127)
// int16       the set of all signed 16-bit integers (-32768 to 32767)
// int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
// int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)<commit_msg>remove comment lines<commit_after>package leetcode

import (
    "bytes"
    "strconv"
)

func reverse(x int) int {
    negative := false
    if x < 0 {
        negative = true
        x = -x
    }

    s := strconv.Itoa(x)
    size := len(s)

    var buffer bytes.Buffer
    if negative {
        buffer.WriteByte(45)
    }

    for i := size - 1; i >= 0; i-- {
        buffer.WriteByte(s[i])
    }

    num, err := strconv.ParseInt(buffer.String(), 10, 32)
    if err != nil {
        return 0
    }

    return int(num)
}<|endoftext|>


<commit_before>package template

import (
	"testing"
)

func TestIsSet(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}
	ok := funcs.isSet("test")
	if !ok {
		t.Error("expected true but got false")
	}
	ok = funcs.isSet("testFalse")
	if ok {
		t.Error("expected false but got true")
	}
}

func TestDefaultOrValue(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}
	value := funcs.defaultOrValue("test", "testDefault")
	if value != "testValue" {
		t.Errorf("expected 'testValue' but got %s", value)
	}
	value = funcs.defaultOrValue("testDefaultValue", "testDefault")
	if value != "testDefault" {
		t.Errorf("expected 'testDefault' but got %s", value)
	}
}

func TestInFormat(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = []string{"test1", "test2"}
	funcs := &FuncRegistry{TemplateData: data}
	query := funcs.inFormat("test")
	if query != "('test1', 'test2')" {
		t.Errorf("expected ('test1', 'test2'), but got %s", query)
	}
}

func TestRegistryAllFuncs(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}

	fmap := funcs.RegistryAllFuncs()
	_, ok := fmap["isSet"]
	if !ok {
		t.Error("func isSet is not registred")
	}
	_, ok = fmap["defaultOrValue"]
	if !ok {
		t.Error("func defaultOrValue is not registred")
	}
	_, ok = fmap["in"]
	if !ok {
		t.Error("func in is not registred")
	}
}
<commit_msg>fix typo<commit_after>package template

import (
	"testing"
)

func TestIsSet(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}
	ok := funcs.isSet("test")
	if !ok {
		t.Error("expected true but got false")
	}
	ok = funcs.isSet("testFalse")
	if ok {
		t.Error("expected false but got true")
	}
}

func TestDefaultOrValue(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}
	value := funcs.defaultOrValue("test", "testDefault")
	if value != "testValue" {
		t.Errorf("expected 'testValue' but got %s", value)
	}
	value = funcs.defaultOrValue("testDefaultValue", "testDefault")
	if value != "testDefault" {
		t.Errorf("expected 'testDefault' but got %s", value)
	}
}

func TestInFormat(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = []string{"test1", "test2"}
	funcs := &FuncRegistry{TemplateData: data}
	query := funcs.inFormat("test")
	if query != "('test1', 'test2')" {
		t.Errorf("expected ('test1', 'test2'), but got %s", query)
	}
}

func TestRegistryAllFuncs(t *testing.T) {
	data := make(map[string]interface{})
	data["test"] = "testValue"
	funcs := &FuncRegistry{TemplateData: data}

	fmap := funcs.RegistryAllFuncs()
	_, ok := fmap["isSet"]
	if !ok {
		t.Error("func isSet is not registred")
	}
	_, ok = fmap["defaultOrValue"]
	if !ok {
		t.Error("func defaultOrValue is not registred")
	}
	_, ok = fmap["inFormat"]
	if !ok {
		t.Error("func in is not registred")
	}
}
<|endoftext|>


<commit_before>// +build fvtests

// Copyright (c) 2017-2018 Tigera, Inc. 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 fv_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	log "github.com/sirupsen/logrus"

	"github.com/projectcalico/felix/fv/infrastructure"
	"github.com/projectcalico/felix/fv/metrics"
	"github.com/projectcalico/felix/fv/utils"
	"github.com/projectcalico/felix/fv/workload"
	"github.com/projectcalico/libcalico-go/lib/apiconfig"
	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/numorstring"
)

func MetricsPortReachable(felix *infrastructure.Felix) bool {
	// Delete existing conntrack state for the metrics port.
	felix.Exec("conntrack", "-L")
	felix.Exec("conntrack", "-L", "-p", "tcp", "--dport", metrics.PortString())
	felix.ExecMayFail("conntrack", "-D", "-p", "tcp", "--orig-port-dst", metrics.PortString())

	// Now try to get a metric.
	m, err := metrics.GetFelixMetric(felix.IP, "felix_active_local_endpoints")
	if err != nil {
		log.WithError(err).Info("Metrics port not reachable")
		return false
	}
	log.WithField("felix_active_local_endpoints", m).Info("Metrics port reachable")
	return true
}

// Here we test reachability to a port number running on a Calico host itself, specifically Felix's
// metrics port 9091, and how that is affected by policy, host endpoint and workload endpoint
// configuration.
//
// - When there is no policy or endpoint configuration, the port should be reachable.
//
// - When there is a local workload endpoint, the port should be reachable.  (Existence of workload
//   endpoints should make no difference to reachability to ports on the host itself.)
//
// - When a host endpoint is configured for the host's interface (eth0), but not yet any policy, the
//   port should be unreachable.
//
//   - When pre-DNAT policy is then configured, to allow ingress to that port, it should be
//     reachable again.

var _ = infrastructure.DatastoreDescribe("with initialized Felix", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) {
	var (
		infra                infrastructure.DatastoreInfra
		felix                *infrastructure.Felix
		client               client.Interface
		metricsPortReachable func() bool
	)

	BeforeEach(func() {
		var err error
		infra, err = getInfra()
		Expect(err).NotTo(HaveOccurred())

		felix, client = infrastructure.StartSingleNodeTopology(infrastructure.DefaultTopologyOptions(), infra)

		metricsPortReachable = func() bool {
			return MetricsPortReachable(felix)
		}
	})

	AfterEach(func() {

		if CurrentGinkgoTestDescription().Failed {
			infra.DumpErrorData()
			felix.Exec("iptables-save", "-c")
			felix.Exec("ip", "r")
			felix.Exec("ip", "a")
		}
		felix.Stop()
		infra.Stop()
	})

	It("with no endpoints or policy, port should be reachable", func() {
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue())
	})

	It("with a local workload, port should be reachable", func() {
		w := workload.Run(felix, "w", "default", "10.65.0.2", "8055", "tcp")
		w.ConfigureInDatastore(infra)
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue(), "Not reachable with workload running")
		w.Stop()
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue(), "With workload stopped, not reachable")
	})

	Context("with host endpoint defined", func() {

		BeforeEach(func() {
			hostEp := api.NewHostEndpoint()
			hostEp.Name = "host-endpoint-1"
			hostEp.Labels = map[string]string{"host-endpoint": "true"}
			hostEp.Spec.Node = felix.Hostname
			hostEp.Spec.InterfaceName = "eth0"
			_, err := client.HostEndpoints().Create(utils.Ctx, hostEp, utils.NoOptions)
			Expect(err).NotTo(HaveOccurred())
		})

		It("port should not be reachable", func() {
			Eventually(metricsPortReachable, "10s", "1s").Should(BeFalse())
		})

		Context("with pre-DNAT policy defined", func() {

			BeforeEach(func() {
				// Ensure the HostEndpoint has taken effect and is blocking traffic
				Eventually(metricsPortReachable, "10s", "1s").Should(BeFalse())
				policy := api.NewGlobalNetworkPolicy()
				policy.Name = "pre-dnat-policy-1"
				policy.Spec.PreDNAT = true
				policy.Spec.ApplyOnForward = true
				protocol := numorstring.ProtocolFromString("tcp")
				allowMetricsPortRule := api.Rule{
					Action:   api.Allow,
					Protocol: &protocol,
					Destination: api.EntityRule{
						Ports: []numorstring.Port{numorstring.SinglePort(uint16(metrics.Port))},
					},
				}
				policy.Spec.Ingress = []api.Rule{allowMetricsPortRule}
				policy.Spec.Selector = "host-endpoint=='true'"
				_, err := client.GlobalNetworkPolicies().Create(utils.Ctx, policy, utils.NoOptions)
				Expect(err).NotTo(HaveOccurred())
			})

			It("port should be reachable", func() {
				Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue())
			})
		})
	})
})
<commit_msg>FV: Trying to get info on HEP flake<commit_after>// +build fvtests

// Copyright (c) 2017-2018 Tigera, Inc. 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 fv_test

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	log "github.com/sirupsen/logrus"

	"github.com/projectcalico/felix/fv/infrastructure"
	"github.com/projectcalico/felix/fv/metrics"
	"github.com/projectcalico/felix/fv/utils"
	"github.com/projectcalico/felix/fv/workload"
	"github.com/projectcalico/libcalico-go/lib/apiconfig"
	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/numorstring"
)

func MetricsPortReachable(felix *infrastructure.Felix) bool {
	// Delete existing conntrack state for the metrics port.
	felix.Exec("conntrack", "-L")
	felix.Exec("conntrack", "-L", "-p", "tcp", "--dport", metrics.PortString())
	felix.ExecMayFail("conntrack", "-D", "-p", "tcp", "--orig-port-dst", metrics.PortString())

	// Now try to get a metric.
	m, err := metrics.GetFelixMetric(felix.IP, "felix_active_local_endpoints")
	if err != nil {
		log.WithError(err).Info("Metrics port not reachable")
		return false
	}
	log.WithField("felix_active_local_endpoints", m).Info("Metrics port reachable")
	return true
}

// Here we test reachability to a port number running on a Calico host itself, specifically Felix's
// metrics port 9091, and how that is affected by policy, host endpoint and workload endpoint
// configuration.
//
// - When there is no policy or endpoint configuration, the port should be reachable.
//
// - When there is a local workload endpoint, the port should be reachable.  (Existence of workload
//   endpoints should make no difference to reachability to ports on the host itself.)
//
// - When a host endpoint is configured for the host's interface (eth0), but not yet any policy, the
//   port should be unreachable.
//
//   - When pre-DNAT policy is then configured, to allow ingress to that port, it should be
//     reachable again.

var _ = infrastructure.DatastoreDescribe("with initialized Felix", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) {
	var (
		infra                infrastructure.DatastoreInfra
		felix                *infrastructure.Felix
		client               client.Interface
		metricsPortReachable func() bool
	)

	BeforeEach(func() {
		var err error
		infra, err = getInfra()
		Expect(err).NotTo(HaveOccurred())

		felix, client = infrastructure.StartSingleNodeTopology(infrastructure.DefaultTopologyOptions(), infra)

		metricsPortReachable = func() bool {
			return MetricsPortReachable(felix)
		}
	})

	AfterEach(func() {

		if CurrentGinkgoTestDescription().Failed {
			infra.DumpErrorData()
			felix.Exec("iptables-save", "-c")
			felix.Exec("ip", "r")
			felix.Exec("ip", "a")
		}
		felix.Stop()
		infra.Stop()
	})

	It("with no endpoints or policy, port should be reachable", func() {
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue())
	})

	It("with a local workload, port should be reachable", func() {
		w := workload.Run(felix, "w", "default", "10.65.0.2", "8055", "tcp")
		w.ConfigureInDatastore(infra)
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue(), "Not reachable with workload running")
		w.Stop()
		Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue(), "With workload stopped, not reachable")
	})

	Context("with host endpoint defined", func() {

		BeforeEach(func() {
			hostEp := api.NewHostEndpoint()
			hostEp.Name = "host-endpoint-1"
			hostEp.Labels = map[string]string{"host-endpoint": "true"}
			hostEp.Spec.Node = felix.Hostname
			hostEp.Spec.InterfaceName = "eth0"
			_, err := client.HostEndpoints().Create(utils.Ctx, hostEp, utils.NoOptions)
			Expect(err).NotTo(HaveOccurred())
		})

		It("port should not be reachable", func() {
			Eventually(metricsPortReachable, "10s", "1s").Should(BeFalse())
		})

		Context("with pre-DNAT policy defined", func() {

			BeforeEach(func() {
				// Ensure the HostEndpoint has taken effect and is blocking traffic
				Eventually(metricsPortReachable, "10s", "1s").Should(BeFalse())
				policy := api.NewGlobalNetworkPolicy()
				policy.Name = "pre-dnat-policy-1"
				policy.Spec.PreDNAT = true
				policy.Spec.ApplyOnForward = true
				protocol := numorstring.ProtocolFromString("tcp")
				allowMetricsPortRule := api.Rule{
					Action:   api.Allow,
					Protocol: &protocol,
					Destination: api.EntityRule{
						Ports: []numorstring.Port{numorstring.SinglePort(uint16(metrics.Port))},
					},
				}
				policy.Spec.Ingress = []api.Rule{allowMetricsPortRule}
				policy.Spec.Selector = "host-endpoint=='true'"
				_, err := client.GlobalNetworkPolicies().Create(utils.Ctx, policy, utils.NoOptions)
				Expect(err).NotTo(HaveOccurred())
			})

			It("port should be reachable", func() {
				//Eventually(metricsPortReachable, "10s", "1s").Should(BeTrue())
				// Switching to the loop below, *seems* to have fixed a flake
				// that was happening here with the Eventually check above.
				// The loop is purposefully high vs what is being checked so
				// if another failure occurs we can see if the timeout is just
				// a little too low or it is something more.
				start := time.Now()
				for time.Since(start).Seconds() < 50 {
					metricsStartTime := time.Now()
					reachable := metricsPortReachable()
					log.WithField("time", time.Since(metricsStartTime)).Info("Checked metrics port")
					if reachable {
						break
					}
					time.Sleep(time.Second)
				}
				Expect(time.Since(start).Seconds()).To(BeNumerically("<", 10))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"sync"
)

// Our "Database" file!
const itemsFile = "../db/items.json"

// Item is what we get from our .json file
// and which we handle as "Store Items" so
// to say. All of our operations should be "GET"
// types, we don't really delete Items at any point
type Item struct {
  id int
  name string
  price int
}

// This, is a "Mutural exclusion lock" which allows us to
// lock our files so that we don't access it twice at the same time
// and do some bad stuff!
var itemsMutex = new(sync.Mutex)

// GetByID returns the item bound to the id passed
// to the function
func (item *Item) GetByID(id int) (Item, error) {
  return nil, nil
}

// GetAll returns every item in our shop in an array,
// and an error if something went horribly wrong
func (item *Item) GetAll() ([]Item, error) {
  return nil, nil
}
<commit_msg>go fmt<commit_after>package main

import (
	"sync"
)

// Our "Database" file
const itemsFile = "../db/items.json"

// Item is what we get from our .json file
// and which we handle as "Store Items" so
// to say. All of our operations should be "GET"
// types, we don't really delete Items at any point
type Item struct {
	id    int
	name  string
	price int
}

// This, is a "Mutural exclusion lock" which allows us to
// lock our files so that we don't access it twice at the same time
// and do some bad stuff!
var itemsMutex = new(sync.Mutex)

// GetByID returns the item bound to the id passed
// to the function
func (item *Item) GetByID(id int) (Item, error) {
	return nil, nil
}

// GetAll returns every item in our shop in an array,
// and an error if something went horribly wrong
func (item *Item) GetAll() ([]Item, error) {
	return nil, nil
}
<|endoftext|>


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

package index

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"
	"time"

	"github.com/coreos/mantle/Godeps/_workspace/src/google.golang.org/api/googleapi"
	"github.com/coreos/mantle/Godeps/_workspace/src/google.golang.org/api/storage/v1"
)

var (
	// Retry write requests up to 6 times.
	maxTries int = 6
	// Wait no less than a second before retrying.
	minBackoff time.Duration = time.Second
	// Do not wait more than 8 seconds between tries.
	maxBackoff time.Duration = time.Second * 8

	indexTemplate *template.Template
)

const (
	// TODO: The version will be used to regenerate existing indexes.
	INDEX_VERSION = `2014-08-12`
	INDEX_TEXT    = `

	<title>{{.Bucket}}/{{.Prefix}}</title>
	<meta http-equiv="X-Clacks-Overhead" content="GNU Terry Pratchett" />

{{.Bucket}}/{{.Prefix}}

    {{range $name, $sub := .SubDirs}}
	[dir] {{$name}}

    {{end}}
    {{range $name, $obj := .Objects}}
	{{if ne $name "index.html"}}
	    [file] {{$name}}

	{{end}}
    {{end}}

`
)

func init() {
	indexTemplate = template.Must(template.New("index").Parse(INDEX_TEXT))
}

func expBackoff(interval time.Duration) time.Duration {
	interval = interval * 2
	if interval > maxBackoff {
		interval = maxBackoff
	}
	return interval
}

func serverError(err error) bool {
	if apierr, ok := err.(*googleapi.Error); ok {
		if apierr.Code == 500 || apierr.Code == 503 {
			return true
		}
	}

	return false
}

func (d *Directory) WriteIndex(client *http.Client) error {
	service, err := storage.New(client)
	if err != nil {
		return err
	}

	buf := bytes.Buffer{}
	err = indexTemplate.Execute(&buf, d)
	if err != nil {
		return err
	}

	writeObj := storage.Object{
		Name:         d.Prefix + "index.html",
		ContentType:  "text/html",
		CacheControl: "public, max-age=60",
	}
	writeReq := service.Objects.Insert(d.Bucket, &writeObj)
	writeReq.Media(&buf)

	fmt.Printf("Writing gs://%s/%s\n", d.Bucket, writeObj.Name)

	// Retry write, sometimes transient 500 errors are reported.
	retryDelay := minBackoff
	for try := 1; try <= maxTries; try++ {
		_, err = writeReq.Do()
		if err != nil && serverError(err) {
			time.Sleep(retryDelay)
			retryDelay = expBackoff(retryDelay)
		} else {
			break
		}
	}
	return err
}
<commit_msg>index: remove obsolete retry code<commit_after>// Copyright 2014 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package index

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"

	"github.com/coreos/mantle/Godeps/_workspace/src/google.golang.org/api/storage/v1"
)

var (
	indexTemplate *template.Template
)

const (
	// TODO: The version will be used to regenerate existing indexes.
	INDEX_VERSION = `2014-08-12`
	INDEX_TEXT    = `

	<title>{{.Bucket}}/{{.Prefix}}</title>
	<meta http-equiv="X-Clacks-Overhead" content="GNU Terry Pratchett" />

{{.Bucket}}/{{.Prefix}}

    {{range $name, $sub := .SubDirs}}
	[dir] {{$name}}

    {{end}}
    {{range $name, $obj := .Objects}}
	{{if ne $name "index.html"}}
	    [file] {{$name}}

	{{end}}
    {{end}}

`
)

func init() {
	indexTemplate = template.Must(template.New("index").Parse(INDEX_TEXT))
}

func (d *Directory) WriteIndex(client *http.Client) error {
	service, err := storage.New(client)
	if err != nil {
		return err
	}

	buf := bytes.Buffer{}
	err = indexTemplate.Execute(&buf, d)
	if err != nil {
		return err
	}

	writeObj := storage.Object{
		Name:         d.Prefix + "index.html",
		ContentType:  "text/html",
		CacheControl: "public, max-age=60",
	}
	writeReq := service.Objects.Insert(d.Bucket, &writeObj)
	writeReq.Media(&buf)

	fmt.Printf("Writing gs://%s/%s\n", d.Bucket, writeObj.Name)
	_, err = writeReq.Do()
	return err
}
<|endoftext|>


<commit_before>package assertions

import (
	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			It("When Actual is float64 and Instance is nil", func() {
				actualValue := float64(1.1)
				var instanceValue struct{}

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			It("When Actual is int and Instance is nil", func() {
				actualValue := 1
				var instanceValue struct{}

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			It("When Actual is string-number and Instance is nil", func() {
				actualValue := "1"
				var instanceValue struct{}

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			It("When Actual is string and Instance is nil", func() {
				actualValue := "a"
				var instanceValue struct{}

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			It("When Actual is float64 and Instance is float64", func() {
				actualValue := float64(5)
				instanceValue := float64(1)

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			It("When Actual is int and Instance is float64", func() {
				actualValue := 5
				instanceValue := float64(1)

				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<commit_msg>Refactored the tests to use test cases with a single function which is easier to manage and less duplication<commit_after>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type ATC struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewATC(actual interface{}, instance interface{}) (newInstance ATC) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			assertTrueResult := func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			}

			var nilValue interface{}
			var successfulAssertionTestCases = []ATC{
				NewATC(float64(1.1), nilValue),
				NewATC(int(1), nilValue),
				NewATC("1", nilValue),
				NewATC("a", nilValue),
				NewATC(float64(5), float64(1)),
				NewATC(int(5), float64(1)),
			}

			for _, successCase := range successfulAssertionTestCases {
				actualValue := successCase.Actual
				instanceValue := successCase.Instance
				testName := fmt.Sprintf("ACTUAL > INSTANCE when Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
				if successCase.ActualStringNumber {
					testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER", testName)
				}
				if successCase.InstanceStringNumber {
					testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER", testName)
				}
				It(testName, func() {
					assertTrueResult(actualValue, instanceValue)
				})
			}

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<|endoftext|>


<commit_before>package flags

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type iniValue struct {
	Name  string
	Value string
}

type iniSection []iniValue
type ini map[string]iniSection

func readFullLine(reader *bufio.Reader) (string, error) {
	var line []byte

	for {
		l, more, err := reader.ReadLine()

		if err != nil {
			return "", err
		}

		if line == nil && !more {
			return string(l), nil
		}

		line = append(line, l...)

		if !more {
			break
		}
	}

	return string(line), nil
}

func optionIniName(option *Option) string {
	name := option.tag.Get("_read-ini-name")

	if len(name) != 0 {
		return name
	}

	name = option.tag.Get("ini-name")

	if len(name) != 0 {
		return name
	}

	return option.field.Name
}

func writeGroupIni(group *Group, namespace string, writer io.Writer, options IniOptions) {
	var sname string

	if len(namespace) != 0 {
		sname = namespace + "." + group.ShortDescription
	} else {
		sname = group.ShortDescription
	}

	sectionwritten := false
	comments := (options & IniIncludeComments) != IniNone

	for _, option := range group.options {
		if option.isFunc() {
			continue
		}

		if len(option.tag.Get("no-ini")) != 0 {
			continue
		}

		val := option.value

		if (options&IniIncludeDefaults) == IniNone &&
			reflect.DeepEqual(val, option.defaultValue) {
			continue
		}

		if !sectionwritten {
			fmt.Fprintf(writer, "[%s]\n", sname)
			sectionwritten = true
		}

		if comments {
			fmt.Fprintf(writer, "; %s\n", option.Description)
		}

		oname := optionIniName(option)

		switch val.Type().Kind() {
		case reflect.Slice:
			for idx := 0; idx < val.Len(); idx++ {
				v, _ := convertToString(val.Index(idx), option.tag)
				fmt.Fprintf(writer, "%s = %s\n", oname, v)
			}

			if val.Len() == 0 {
				fmt.Fprintf(writer, "; %s =\n", oname)
			}
		case reflect.Map:
			for _, key := range val.MapKeys() {
				k, _ := convertToString(key, option.tag)
				v, _ := convertToString(val.MapIndex(key), option.tag)

				fmt.Fprintf(writer, "%s = %s:%s\n", oname, k, v)
			}

			if val.Len() == 0 {
				fmt.Fprintf(writer, "; %s =\n", oname)
			}
		default:
			v, _ := convertToString(val, option.tag)
			fmt.Fprintf(writer, "%s = %s\n", oname, v)
		}
	}

	fmt.Fprintln(writer)
}

func writeCommandIni(command *Command, namespace string, writer io.Writer, options IniOptions) {
	command.eachGroup(func(group *Group) {
		writeGroupIni(group, namespace, writer, options)
	})

	for _, c := range command.commands {
		var nns string

		if len(namespace) != 0 {
			nns = c.Name + "." + nns
		} else {
			nns = c.Name
		}

		writeCommandIni(c, nns, writer, options)
	}
}

func writeIni(parser *IniParser, writer io.Writer, options IniOptions) {
	writeCommandIni(parser.parser.Command, "", writer, options)
}

func readIniFromFile(filename string) (ini, error) {
	file, err := os.Open(filename)

	if err != nil {
		return nil, err
	}

	defer file.Close()

	return readIni(file, filename)
}

func readIni(contents io.Reader, filename string) (ini, error) {
	ret := make(ini)

	reader := bufio.NewReader(contents)

	var section iniSection
	var sectionname string

	var lineno uint

	for {
		line, err := readFullLine(reader)

		if err == io.EOF {
			break
		}

		if err != nil {
			return nil, err
		}

		lineno++
		line = strings.TrimSpace(line)

		// Skip empty lines and lines starting with ; (comments)
		if len(line) == 0 || line[0] == ';' {
			continue
		}

		if section == nil {
			if line[0] != '[' || line[len(line)-1] != ']' {
				return nil, &IniError{
					Message:    "malformed section header",
					File:       filename,
					LineNumber: lineno,
				}
			}

			name := strings.TrimSpace(line[1 : len(line)-1])

			if len(name) == 0 {
				return nil, &IniError{
					Message:    "empty section name",
					File:       filename,
					LineNumber: lineno,
				}
			}

			sectionname = name
			section = ret[name]

			if section == nil {
				section = make(iniSection, 0, 10)
				ret[name] = section
			}

			continue
		}

		// Parse option here
		keyval := strings.SplitN(line, "=", 2)

		if len(keyval) != 2 {
			return nil, &IniError{
				Message:    "malformed key=value",
				File:       filename,
				LineNumber: lineno,
			}
		}

		name := strings.TrimSpace(keyval[0])
		value := strings.TrimSpace(keyval[1])

		section = append(section, iniValue{
			Name:  name,
			Value: value,
		})

		ret[sectionname] = section
	}

	return ret, nil
}

func (i *IniParser) parse(ini ini) error {
	p := i.parser

	for name, section := range ini {
		group := p.groupByName(name)

		if group == nil {
			return newError(ErrUnknownGroup,
				fmt.Sprintf("could not find option group `%s'", name))
		}

		for _, inival := range section {
			opt := group.optionByName(inival.Name, func(o *Option, n string) bool {
				return strings.ToLower(o.tag.Get("ini-name")) == strings.ToLower(n)
			})

			if opt == nil {
				if (p.Options & IgnoreUnknown) == None {
					return newError(ErrUnknownFlag,
						fmt.Sprintf("unknown option: %s", inival.Name))
				}

				continue
			}

			if opt.tag.Get("no-ini") != "" {
				continue
			}

			pval := &inival.Value

			if !opt.canArgument() && len(inival.Value) == 0 {
				pval = nil
			}

			if err := opt.set(pval); err != nil {
				return wrapError(err)
			}

			opt.tag.Set("_read-ini-name", inival.Name)
		}
	}

	return nil
}
<commit_msg>Cleanup writing newlines<commit_after>package flags

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type iniValue struct {
	Name  string
	Value string
}

type iniSection []iniValue
type ini map[string]iniSection

func readFullLine(reader *bufio.Reader) (string, error) {
	var line []byte

	for {
		l, more, err := reader.ReadLine()

		if err != nil {
			return "", err
		}

		if line == nil && !more {
			return string(l), nil
		}

		line = append(line, l...)

		if !more {
			break
		}
	}

	return string(line), nil
}

func optionIniName(option *Option) string {
	name := option.tag.Get("_read-ini-name")

	if len(name) != 0 {
		return name
	}

	name = option.tag.Get("ini-name")

	if len(name) != 0 {
		return name
	}

	return option.field.Name
}

func writeGroupIni(group *Group, namespace string, writer io.Writer, options IniOptions) {
	var sname string

	if len(namespace) != 0 {
		sname = namespace + "." + group.ShortDescription
	} else {
		sname = group.ShortDescription
	}

	sectionwritten := false
	comments := (options & IniIncludeComments) != IniNone

	for _, option := range group.options {
		if option.isFunc() {
			continue
		}

		if len(option.tag.Get("no-ini")) != 0 {
			continue
		}

		val := option.value

		if (options&IniIncludeDefaults) == IniNone &&
			reflect.DeepEqual(val, option.defaultValue) {
			continue
		}

		if !sectionwritten {
			fmt.Fprintf(writer, "[%s]\n", sname)
			sectionwritten = true
		}

		if comments {
			fmt.Fprintf(writer, "; %s\n", option.Description)
		}

		oname := optionIniName(option)

		switch val.Type().Kind() {
		case reflect.Slice:
			for idx := 0; idx < val.Len(); idx++ {
				v, _ := convertToString(val.Index(idx), option.tag)
				fmt.Fprintf(writer, "%s = %s\n", oname, v)
			}

			if val.Len() == 0 {
				fmt.Fprintf(writer, "; %s =\n", oname)
			}
		case reflect.Map:
			for _, key := range val.MapKeys() {
				k, _ := convertToString(key, option.tag)
				v, _ := convertToString(val.MapIndex(key), option.tag)

				fmt.Fprintf(writer, "%s = %s:%s\n", oname, k, v)
			}

			if val.Len() == 0 {
				fmt.Fprintf(writer, "; %s =\n", oname)
			}
		default:
			v, _ := convertToString(val, option.tag)
			fmt.Fprintf(writer, "%s = %s\n", oname, v)
		}

		if comments {
			fmt.Fprintln(writer)
		}
	}

	if sectionwritten && !comments {
		fmt.Fprintln(writer)
	}
}

func writeCommandIni(command *Command, namespace string, writer io.Writer, options IniOptions) {
	command.eachGroup(func(group *Group) {
		writeGroupIni(group, namespace, writer, options)
	})

	for _, c := range command.commands {
		var nns string

		if len(namespace) != 0 {
			nns = c.Name + "." + nns
		} else {
			nns = c.Name
		}

		writeCommandIni(c, nns, writer, options)
	}
}

func writeIni(parser *IniParser, writer io.Writer, options IniOptions) {
	writeCommandIni(parser.parser.Command, "", writer, options)
}

func readIniFromFile(filename string) (ini, error) {
	file, err := os.Open(filename)

	if err != nil {
		return nil, err
	}

	defer file.Close()

	return readIni(file, filename)
}

func readIni(contents io.Reader, filename string) (ini, error) {
	ret := make(ini)

	reader := bufio.NewReader(contents)

	var section iniSection
	var sectionname string

	var lineno uint

	for {
		line, err := readFullLine(reader)

		if err == io.EOF {
			break
		}

		if err != nil {
			return nil, err
		}

		lineno++
		line = strings.TrimSpace(line)

		// Skip empty lines and lines starting with ; (comments)
		if len(line) == 0 || line[0] == ';' {
			continue
		}

		if section == nil {
			if line[0] != '[' || line[len(line)-1] != ']' {
				return nil, &IniError{
					Message:    "malformed section header",
					File:       filename,
					LineNumber: lineno,
				}
			}

			name := strings.TrimSpace(line[1 : len(line)-1])

			if len(name) == 0 {
				return nil, &IniError{
					Message:    "empty section name",
					File:       filename,
					LineNumber: lineno,
				}
			}

			sectionname = name
			section = ret[name]

			if section == nil {
				section = make(iniSection, 0, 10)
				ret[name] = section
			}

			continue
		}

		// Parse option here
		keyval := strings.SplitN(line, "=", 2)

		if len(keyval) != 2 {
			return nil, &IniError{
				Message:    "malformed key=value",
				File:       filename,
				LineNumber: lineno,
			}
		}

		name := strings.TrimSpace(keyval[0])
		value := strings.TrimSpace(keyval[1])

		section = append(section, iniValue{
			Name:  name,
			Value: value,
		})

		ret[sectionname] = section
	}

	return ret, nil
}

func (i *IniParser) parse(ini ini) error {
	p := i.parser

	for name, section := range ini {
		group := p.groupByName(name)

		if group == nil {
			return newError(ErrUnknownGroup,
				fmt.Sprintf("could not find option group `%s'", name))
		}

		for _, inival := range section {
			opt := group.optionByName(inival.Name, func(o *Option, n string) bool {
				return strings.ToLower(o.tag.Get("ini-name")) == strings.ToLower(n)
			})

			if opt == nil {
				if (p.Options & IgnoreUnknown) == None {
					return newError(ErrUnknownFlag,
						fmt.Sprintf("unknown option: %s", inival.Name))
				}

				continue
			}

			if opt.tag.Get("no-ini") != "" {
				continue
			}

			pval := &inival.Value

			if !opt.canArgument() && len(inival.Value) == 0 {
				pval = nil
			}

			if err := opt.set(pval); err != nil {
				return wrapError(err)
			}

			opt.tag.Set("_read-ini-name", inival.Name)
		}
	}

	return nil
}
<|endoftext|>