<commit_before>package utils

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Jeffail/gabs"
	log "github.com/cihub/seelog"
	"github.com/fsouza/go-dockerclient"
	"io/ioutil"
	"net"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	countFile = "/tmp/logspout/logspout.json"
)

var UUID string
var M1 map[string]string
var IP string
var Hostname string
var UserId string
var ClusterId string
var counter map[string]int64
var counterlock sync.Mutex
var mesoslock sync.Mutex

func getPort(ports string) string {
	reg := regexp.MustCompile("\\[|\\]")
	strs := strings.Split(reg.ReplaceAllString(ports, ""), "-")
	startPort, serr := strconv.Atoi(strs[0])
	endPort, eerr := strconv.Atoi(strs[1])
	if serr != nil || eerr != nil {
		return "[]"
	}
	var port []string
	for i := startPort; i <= endPort; i++ {
		port = append(port, strconv.Itoa(i))
	}
	return "[" + strings.Join(port, ",") + "]"

}

type Message struct {
	FrameWorks []struct {
		Executors []struct {
			Container string `json:"container"`
			Tasks     []struct {
				SlaveId   string `json:"slave_id"`
				State     string `json:"state"`
				Name      string `json:"name"`
				Id        string `json:"id"`
				Resources struct {
					Ports string `json:"ports"`
				} `json:"resources"`
			} `json:"tasks"`
		} `json:"executors"`
	} `json:"frameworks"`
	HostName string `json:"hostname"`
}

func init() {
	counterlock = sync.Mutex{}
	mesoslock = sync.Mutex{}
	loadCounter()
	UUID = os.Getenv("HOST_ID")
	if UUID == "" {
		log.Error("cat't found uuid")
		os.Exit(0)
	}
	UserId = os.Getenv("USER_ID")
	if UserId == "" {
		log.Error("cat't found userid")
		os.Exit(0)
	}
	ClusterId = os.Getenv("CLUSTER_ID")
	if ClusterId == "" {
		log.Error("cat't found clusterid")
		os.Exit(0)
	}
	Hostname, _ = os.Hostname()
	IP, _ = GetIp()
	M1 = getCnames()
}

func Run() {
	timer := time.NewTicker(5 * time.Second)
	for {
		select {
		case <-timer.C:
			//getMesosInfo(mesoslock)
			persistenCounter()
		}
	}
}

func getMesosInfo(lock *sync.Mutex) {
	data, err := HttpGet("http://" + IP + ":5051/slave(1)/state.json")
	if err == nil {
		mg := getCnames()
		var m Message
		json.Unmarshal([]byte(data), &m)
		if len(m.FrameWorks) > 0 {
			for _, fw := range m.FrameWorks {
				if len(fw.Executors) > 0 {
					for _, ex := range fw.Executors {
						if len(ex.Tasks) > 0 {
							for _, ts := range ex.Tasks {
								mcn := "/mesos-" + ts.SlaveId + "." + ex.Container
								mg[mcn] = ts.Name + " " +
									ts.Id + " " +
									getPort(ts.Resources.Ports)
							}
						}
					}
				}
			}
		}
		lock.Lock()
		M1 = mg
		lock.Unlock()
	}
	//log.Debug("get mesos json: ", err, M1)
}

func GetIp() (ip string, err error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

func ConnTCP(address string) (net.Conn, error) {
	raddr, err := net.ResolveTCPAddr("tcp", address)
	if err != nil {
		return nil, err
	}
	conn, err := net.DialTCP("tcp", nil, raddr)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func ConnTLS(address string) (net.Conn, error) {
	cert, err := tls.LoadX509KeyPair("/root/ssl/client.pem", "/root/ssl/client.key")
	if err != nil {
		return nil, err
	}
	config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
	conn, err := tls.Dial("tcp", address, &config)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func getCnames() map[string]string {
	cnames := os.Getenv("CNAMES")
	if cnames != "" {
		cmap := make(map[string]string)
		ca := strings.Split(cnames, ",")
		for _, cname := range ca {
			rname := strings.Replace(cname, "/", "", 1)
			cmap[cname] = rname + " " + rname + " " + "[]"
		}
		return cmap
	}
	return make(map[string]string)
}

func SendMessage(cn, msg string, d *docker.Container) string {
	counter[d.ID]++
	t := time.Now()
	timestr := t.Format("2006-01-02T15:04:05.895+08:00")
	logmsg := timestr + " " +
		UserId + " " +
		fmt.Sprint(counter[d.ID]) + " " +
		ClusterId + " " +
		UUID + " " +
		IP + " " +
		Hostname + " " +
		cn + " " +
		msg
	return logmsg
}

func loadCounter() {
	counter = make(map[string]int64)
	buf, err := ioutil.ReadFile(countFile)
	if err == nil {
		json, err := gabs.ParseJSON(buf)
		if err == nil {
			m, err := json.ChildrenMap()
			if err == nil {
				for k, v := range m {
					if reflect.TypeOf(v.Data()).String() == "float64" {
						counter[k] = int64(v.Data().(float64))
					}
				}
				log.Debug("load container counter: ", json)
			} else {
				log.Error("counter childrenmap err: ", err)
			}
		} else {
			log.Error("counter str to json err: ", err)
		}
	} else {
		log.Debug("not found counter file: ", err)
	}
}

func persistenCounter() {
	if len(counter) > 0 {
		json := gabs.New()
		counterlock.Lock()
		for k, v := range counter {
			json.Set(v, k)
		}
		counterlock.Unlock()
		err := ioutil.WriteFile(countFile, json.Bytes(), 0x644)
		if err != nil {
			log.Error("persisten counter failed: ", err)
		}
	}
}

func DeleteCounter(client *docker.Client) {
	containers, err := client.ListContainers(docker.ListContainersOptions{})
	if err == nil {
		copycounter := counter
		for _, container := range containers {
			_, ok := copycounter[container.ID]
			if ok {
				delete(copycounter, container.ID)
			}
		}

		counterlock.Lock()
		for k, _ := range copycounter {
			delete(counter, k)
		}
		counterlock.Unlock()
	}
}

func DeleteM1(cname string) {
	if _, ok := getCnames()[cname]; !ok {
		mesoslock.Lock()
		delete(M1, cname)
		mesoslock.Unlock()
	}
}

func ReceiveContainer(container *docker.Container) {
	env := container.Config.Env
	appName := ""
	taskId := ""
	ports := ""
	if len(env) > 0 {
		for _, e := range env {
			if strings.Contains(e, "MARATHON_APP_ID=/") {
				appName = strings.Split(e, "=/")[1]
			} else if strings.Contains(e, "MESOS_TASK_ID=") {
				taskId = strings.Split(e, "=")[1]
			} else if strings.Contains(e, "PORTS=") {
				ports = strings.Split(e, "=")[1]
			}
		}
		if appName != "" && taskId != "" && ports != "" {
			mesoslock.Lock()
			M1[container.Name] = appName + " " + taskId + " " + "[" + ports + "]"
			mesoslock.Unlock()
		}
	}
}
<commit_msg>ge shi<commit_after>package utils

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Jeffail/gabs"
	log "github.com/cihub/seelog"
	"github.com/fsouza/go-dockerclient"
	"io/ioutil"
	"net"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	countFile = "/tmp/logspout/logspout.json"
)

var (
	UUID        string
	M1          map[string]string
	IP          string
	Hostname    string
	UserId      string
	ClusterId   string
	counter     map[string]int64
	counterlock sync.Mutex
	mesoslock   sync.Mutex
)

func getPort(ports string) string {
	reg := regexp.MustCompile("\\[|\\]")
	strs := strings.Split(reg.ReplaceAllString(ports, ""), "-")
	startPort, serr := strconv.Atoi(strs[0])
	endPort, eerr := strconv.Atoi(strs[1])
	if serr != nil || eerr != nil {
		return "[]"
	}
	var port []string
	for i := startPort; i <= endPort; i++ {
		port = append(port, strconv.Itoa(i))
	}
	return "[" + strings.Join(port, ",") + "]"

}

type Message struct {
	FrameWorks []struct {
		Executors []struct {
			Container string `json:"container"`
			Tasks     []struct {
				SlaveId   string `json:"slave_id"`
				State     string `json:"state"`
				Name      string `json:"name"`
				Id        string `json:"id"`
				Resources struct {
					Ports string `json:"ports"`
				} `json:"resources"`
			} `json:"tasks"`
		} `json:"executors"`
	} `json:"frameworks"`
	HostName string `json:"hostname"`
}

func init() {
	counterlock, mesoslock = sync.Mutex{}, sync.Mutex{}
	M1 = make(map[string]string)
	loadCounter()
	UUID = os.Getenv("HOST_ID")
	if UUID == "" {
		log.Error("cat't found uuid")
		os.Exit(0)
	}
	UserId = os.Getenv("USER_ID")
	if UserId == "" {
		log.Error("cat't found userid")
		os.Exit(0)
	}
	ClusterId = os.Getenv("CLUSTER_ID")
	if ClusterId == "" {
		log.Error("cat't found clusterid")
		os.Exit(0)
	}
	Hostname, _ = os.Hostname()
	IP, _ = GetIp()
	M1 = getCnames()
}

func Run() {
	timer := time.NewTicker(5 * time.Second)
	for {
		select {
		case <-timer.C:
			//getMesosInfo(mesoslock)
			persistenCounter()
		}
	}
}

func getMesosInfo(lock *sync.Mutex) {
	data, err := HttpGet("http://" + IP + ":5051/slave(1)/state.json")
	if err == nil {
		mg := getCnames()
		var m Message
		json.Unmarshal([]byte(data), &m)
		if len(m.FrameWorks) > 0 {
			for _, fw := range m.FrameWorks {
				if len(fw.Executors) > 0 {
					for _, ex := range fw.Executors {
						if len(ex.Tasks) > 0 {
							for _, ts := range ex.Tasks {
								mcn := "/mesos-" + ts.SlaveId + "." + ex.Container
								mg[mcn] = ts.Name + " " +
									ts.Id + " " +
									getPort(ts.Resources.Ports)
							}
						}
					}
				}
			}
		}
		lock.Lock()
		M1 = mg
		lock.Unlock()
	}
	//log.Debug("get mesos json: ", err, M1)
}

func GetIp() (ip string, err error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

func ConnTCP(address string) (net.Conn, error) {
	raddr, err := net.ResolveTCPAddr("tcp", address)
	if err != nil {
		return nil, err
	}
	conn, err := net.DialTCP("tcp", nil, raddr)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func ConnTLS(address string) (net.Conn, error) {
	cert, err := tls.LoadX509KeyPair("/root/ssl/client.pem", "/root/ssl/client.key")
	if err != nil {
		return nil, err
	}
	config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
	conn, err := tls.Dial("tcp", address, &config)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func getCnames() map[string]string {
	cnames := os.Getenv("CNAMES")
	if cnames != "" {
		cmap := make(map[string]string)
		ca := strings.Split(cnames, ",")
		for _, cname := range ca {
			rname := strings.Replace(cname, "/", "", 1)
			cmap[cname] = rname + " " + rname + " " + "[]"
		}
		return cmap
	}
	return make(map[string]string)
}

func SendMessage(cn, msg string, d *docker.Container) string {
	counter[d.ID]++
	t := time.Now()
	timestr := t.Format("2006-01-02T15:04:05.895+08:00")
	logmsg := timestr + " " +
		UserId + " " +
		fmt.Sprint(counter[d.ID]) + " " +
		ClusterId + " " +
		UUID + " " +
		IP + " " +
		Hostname + " " +
		cn + " " +
		msg
	return logmsg
}

func loadCounter() {
	counter = make(map[string]int64)
	buf, err := ioutil.ReadFile(countFile)
	if err == nil {
		json, err := gabs.ParseJSON(buf)
		if err == nil {
			m, err := json.ChildrenMap()
			if err == nil {
				for k, v := range m {
					if reflect.TypeOf(v.Data()).String() == "float64" {
						counter[k] = int64(v.Data().(float64))
					}
				}
				log.Debug("load container counter: ", json)
			} else {
				log.Error("counter childrenmap err: ", err)
			}
		} else {
			log.Error("counter str to json err: ", err)
		}
	} else {
		log.Debug("not found counter file: ", err)
	}
}

func persistenCounter() {
	if len(counter) > 0 {
		json := gabs.New()
		counterlock.Lock()
		for k, v := range counter {
			json.Set(v, k)
		}
		counterlock.Unlock()
		err := ioutil.WriteFile(countFile, json.Bytes(), 0x644)
		if err != nil {
			log.Error("persisten counter failed: ", err)
		}
	}
}

func DeleteCounter(client *docker.Client) {
	containers, err := client.ListContainers(docker.ListContainersOptions{})
	if err == nil {
		copycounter := counter
		for _, container := range containers {
			_, ok := copycounter[container.ID]
			if ok {
				delete(copycounter, container.ID)
			}
		}

		counterlock.Lock()
		for k, _ := range copycounter {
			delete(counter, k)
		}
		counterlock.Unlock()
	}
}

func DeleteM1(cname string) {
	if _, ok := getCnames()[cname]; !ok {
		mesoslock.Lock()
		delete(M1, cname)
		mesoslock.Unlock()
	}
}

func ReceiveContainer(container *docker.Container) {
	env := container.Config.Env
	appName := ""
	taskId := ""
	ports := ""
	if len(env) > 0 {
		for _, e := range env {
			if strings.Contains(e, "MARATHON_APP_ID=/") {
				appName = strings.Split(e, "=/")[1]
			} else if strings.Contains(e, "MESOS_TASK_ID=") {
				taskId = strings.Split(e, "=")[1]
			} else if strings.Contains(e, "PORTS=") {
				ports = strings.Split(e, "=")[1]
			}
		}
		if appName != "" && taskId != "" && ports != "" {
			mesoslock.Lock()
			M1[container.Name] = appName + " " + taskId + " " + "[" + ports + "]"
			mesoslock.Unlock()
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016-2020 The Libsacloud Authors
//
// 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 libsacloud

// Version バージョン
const Version = "2.6.1"
<commit_msg>Bump to v2.6.2<commit_after>// Copyright 2016-2020 The Libsacloud Authors
//
// 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 libsacloud

// Version バージョン
const Version = "2.6.2"
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "log"
    "os"
    "image/png"
    "errors"
    "functorama.com/demo/libgodelbrot"
)

type commandLine struct {
    iterateLimit uint
    divergeLimit float64
    width uint
    height uint
    filename string
    xOffset float64
    yOffset float64
    zoom float64
    mode string
}

func parseArguments(args *commandLine) {
    flag.UintVar(&args.iterateLimit, "iterateLimit", 255, "Maximum number of iterations")
    flag.Float64Var(&args.divergeLimit, "divergeLimit", 4.0, "Limit where function is said to diverge to infinity")
    flag.UintVar(&args.width, "imageWidth", 800, "Width of output PNG")
    flag.UintVar(&args.height, "imageHeight", 600, "Height of output PNG")
    flag.StringVar(&args.filename, "filename", "mandelbrot.png", "Name of output PNG")
    flag.Float64Var(&args.xOffset, "xOffset", -1.5, "Leftmost position of complex plane projected onto PNG image")
    flag.Float64Var(&args.yOffset, "yOffset", 1.0, "Topmost position of complex plane projected onto PNG image")
    flag.Float64Var(&args.zoom, "zoom", 1.0, "Look into the eyeball")
    flag.StringVar(&args.mode, "mode", "sequential", "Render mode")
}

func extractRenderParameters(args commandLine) (*libgodelbrot.RenderParameters, error) {
    if args.iterateLimit > 255 {
        return nil, errors.New("iterateLimit out of bounds (uint8)")
    }

    if args.divergeLimit <= 0.0 {
        return nil, errors.New("divergeLimit out of bounds (positive float64)")
    }

    if args.zoom <= 0.0 {
        return nil, errors.New("zoom out of bounds (positive float64)")
    }

    parameters := &libgodelbrot.RenderParameters{
        IterateLimit: uint8(args.iterateLimit),
        DivergeLimit: args.divergeLimit,
        Width: args.width,
        Height: args.height,
        XOffset: args.xOffset,
        YOffset: args.yOffset,
        Zoom: args.zoom,
    }
    return parameters, nil
}

func main() {
    args := commandLine{}
    parseArguments(&args)

    var renderer *libgodelbrot.SequentialRenderer
    switch args.mode {
    case "sequential":
        renderer = libgodelbrot.NewSequentialRenderer()
    default:
        log.Fatal("Unknown renderer")
    }

    renderParameters, validationError := extractRenderParameters(args)
    if validationError != nil {
        log.Fatal(validationError)
    }

    image, renderError := renderer.Render(renderParameters)
    if renderError != nil {
        log.Fatal(renderError)
    }

    file, fileError := os.Create(args.filename)

    if fileError != nil {
        log.Fatal(fileError)
    }
    defer file.Close()

    writeError := png.Encode(file, image)

    if writeError != nil {
        log.Fatal(writeError)
    }
}<commit_msg>Actually parse arguments<commit_after>package main

import (
    "flag"
    "log"
    "os"
    "image/png"
    "errors"
    "functorama.com/demo/libgodelbrot"
)

type commandLine struct {
    iterateLimit uint
    divergeLimit float64
    width uint
    height uint
    filename string
    xOffset float64
    yOffset float64
    zoom float64
    mode string
}

func parseArguments(args *commandLine) {
    flag.UintVar(&args.iterateLimit, "iterateLimit", 255, "Maximum number of iterations")
    flag.Float64Var(&args.divergeLimit, "divergeLimit", 4.0, "Limit where function is said to diverge to infinity")
    flag.UintVar(&args.width, "imageWidth", 800, "Width of output PNG")
    flag.UintVar(&args.height, "imageHeight", 600, "Height of output PNG")
    flag.StringVar(&args.filename, "filename", "mandelbrot.png", "Name of output PNG")
    flag.Float64Var(&args.xOffset, "xOffset", -1.5, "Leftmost position of complex plane projected onto PNG image")
    flag.Float64Var(&args.yOffset, "yOffset", 1.0, "Topmost position of complex plane projected onto PNG image")
    flag.Float64Var(&args.zoom, "zoom", 1.0, "Look into the eyeball")
    flag.StringVar(&args.mode, "mode", "sequential", "Render mode")
    flag.Parse()
}

func extractRenderParameters(args commandLine) (*libgodelbrot.RenderParameters, error) {
    if args.iterateLimit > 255 {
        return nil, errors.New("iterateLimit out of bounds (uint8)")
    }

    if args.divergeLimit <= 0.0 {
        return nil, errors.New("divergeLimit out of bounds (positive float64)")
    }

    if args.zoom <= 0.0 {
        return nil, errors.New("zoom out of bounds (positive float64)")
    }

    parameters := &libgodelbrot.RenderParameters{
        IterateLimit: uint8(args.iterateLimit),
        DivergeLimit: args.divergeLimit,
        Width: args.width,
        Height: args.height,
        XOffset: args.xOffset,
        YOffset: args.yOffset,
        Zoom: args.zoom,
    }
    return parameters, nil
}

func main() {
    args := commandLine{}
    parseArguments(&args)

    var renderer *libgodelbrot.SequentialRenderer
    switch args.mode {
    case "sequential":
        renderer = libgodelbrot.NewSequentialRenderer()
    default:
        log.Fatal("Unknown renderer")
    }

    renderParameters, validationError := extractRenderParameters(args)
    if validationError != nil {
        log.Fatal(validationError)
    }

    image, renderError := renderer.Render(renderParameters)
    if renderError != nil {
        log.Fatal(renderError)
    }

    file, fileError := os.Create(args.filename)

    if fileError != nil {
        log.Fatal(fileError)
    }
    defer file.Close()

    writeError := png.Encode(file, image)

    if writeError != nil {
        log.Fatal(writeError)
    }
}<|endoftext|>


<commit_before>package revel

import (
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"runtime"
)

type ValidationError struct {
	Message, Key string
}

// Returns the Message.
func (e *ValidationError) String() string {
	if e == nil {
		return ""
	}
	return e.Message
}

// A Validation context manages data validation and error messages.
type Validation struct {
	Errors []*ValidationError
	keep   bool
}

func (v *Validation) Keep() {
	v.keep = true
}

func (v *Validation) Clear() {
	v.Errors = []*ValidationError{}
}

func (v *Validation) HasErrors() bool {
	return len(v.Errors) > 0
}

// Return the errors mapped by key.
// If there are multiple validation errors associated with a single key, the
// first one "wins".  (Typically the first validation will be the more basic).
func (v *Validation) ErrorMap() map[string]*ValidationError {
	m := map[string]*ValidationError{}
	for _, e := range v.Errors {
		if _, ok := m[e.Key]; !ok {
			m[e.Key] = e
		}
	}
	return m
}

// Add an error to the validation context.
func (v *Validation) Error(message string, args ...interface{}) *ValidationResult {
	result := (&ValidationResult{
		Ok:    false,
		Error: &ValidationError{},
	}).Message(message, args)
	v.Errors = append(v.Errors, result.Error)
	return result
}

// A ValidationResult is returned from every validation method.
// It provides an indication of success, and a pointer to the Error (if any).
type ValidationResult struct {
	Error *ValidationError
	Ok    bool
}

func (r *ValidationResult) Key(key string) *ValidationResult {
	if r.Error != nil {
		r.Error.Key = key
	}
	return r
}

func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
	if r.Error != nil {
		if len(args) == 0 {
			r.Error.Message = message
		} else {
			r.Error.Message = fmt.Sprintf(message, args)
		}
	}
	return r
}

// Test that the argument is non-nil and non-empty (if string or list)
func (v *Validation) Required(obj interface{}) *ValidationResult {
	return v.apply(Required{}, obj)
}

func (v *Validation) Min(n int, min int) *ValidationResult {
	return v.apply(Min{min}, n)
}

func (v *Validation) Max(n int, max int) *ValidationResult {
	return v.apply(Max{max}, n)
}

func (v *Validation) Range(n, min, max int) *ValidationResult {
	return v.apply(Range{Min{min}, Max{max}}, n)
}

func (v *Validation) MinSize(obj interface{}, min int) *ValidationResult {
	return v.apply(MinSize{min}, obj)
}

func (v *Validation) MaxSize(obj interface{}, max int) *ValidationResult {
	return v.apply(MaxSize{max}, obj)
}

func (v *Validation) Length(obj interface{}, n int) *ValidationResult {
	return v.apply(Length{n}, obj)
}

func (v *Validation) Match(str string, regex *regexp.Regexp) *ValidationResult {
	return v.apply(Match{regex}, str)
}

func (v *Validation) Email(str string) *ValidationResult {
	return v.apply(Email{Match{emailPattern}}, str)
}

func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
	if chk.IsSatisfied(obj) {
		return &ValidationResult{Ok: true}
	}

	// Get the default key.
	var key string
	if pc, _, line, ok := runtime.Caller(2); ok {
		f := runtime.FuncForPC(pc)
		if defaultKeys, ok := DefaultValidationKeys[f.Name()]; ok {
			key = defaultKeys[line]
		}
	} else {
		INFO.Println("Failed to get Caller information to look up Validation key")
	}

	// Add the error to the validation context.
	err := &ValidationError{
		Message: chk.DefaultMessage(),
		Key:     key,
	}
	v.Errors = append(v.Errors, err)

	// Also return it in the result.
	return &ValidationResult{
		Ok:    false,
		Error: err,
	}
}

// Apply a group of validators to a field, in order, and return the
// ValidationResult from the first one that fails, or the last one that
// succeeds.
func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResult {
	var result *ValidationResult
	for _, check := range checks {
		result = v.apply(check, obj)
		if !result.Ok {
			return result
		}
	}
	return result
}

func ValidationFilter(c *Controller, fc []Filter) {
	c.Validation = &Validation{
		Errors: restoreValidationErrors(c.Request.Request),
		keep:   false,
	}

	fc[0](c, fc[1:])

	// Add Validation errors to RenderArgs.
	c.RenderArgs["errors"] = c.Validation.ErrorMap()

	// Store the Validation errors
	var errorsValue string
	if c.Validation.keep {
		for _, error := range c.Validation.Errors {
			if error.Message != "" {
				errorsValue += "\x00" + error.Key + ":" + error.Message + "\x00"
			}
		}
	}
	c.SetCookie(&http.Cookie{
		Name:  CookiePrefix + "_ERRORS",
		Value: url.QueryEscape(errorsValue),
		Path:  "/",
	})
}

// Restore Validation.Errors from a request.
func restoreValidationErrors(req *http.Request) []*ValidationError {
	errors := make([]*ValidationError, 0, 5)
	if cookie, err := req.Cookie(CookiePrefix + "_ERRORS"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			errors = append(errors, &ValidationError{
				Key:     key,
				Message: val,
			})
		})
	}
	return errors
}

// Register default validation keys for all calls to Controller.Validation.Func().
// Map from (package).func => (line => name of first arg to Validation func)
// E.g. "myapp/controllers.helper" or "myapp/controllers.(*Application).Action"
// This is set on initialization in the generated main.go file.
var DefaultValidationKeys map[string]map[int]string
<commit_msg>Fix call to Message() in Validation.Error()<commit_after>package revel

import (
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"runtime"
)

type ValidationError struct {
	Message, Key string
}

// Returns the Message.
func (e *ValidationError) String() string {
	if e == nil {
		return ""
	}
	return e.Message
}

// A Validation context manages data validation and error messages.
type Validation struct {
	Errors []*ValidationError
	keep   bool
}

func (v *Validation) Keep() {
	v.keep = true
}

func (v *Validation) Clear() {
	v.Errors = []*ValidationError{}
}

func (v *Validation) HasErrors() bool {
	return len(v.Errors) > 0
}

// Return the errors mapped by key.
// If there are multiple validation errors associated with a single key, the
// first one "wins".  (Typically the first validation will be the more basic).
func (v *Validation) ErrorMap() map[string]*ValidationError {
	m := map[string]*ValidationError{}
	for _, e := range v.Errors {
		if _, ok := m[e.Key]; !ok {
			m[e.Key] = e
		}
	}
	return m
}

// Add an error to the validation context.
func (v *Validation) Error(message string, args ...interface{}) *ValidationResult {
	result := (&ValidationResult{
		Ok:    false,
		Error: &ValidationError{},
	}).Message(message, args...)
	v.Errors = append(v.Errors, result.Error)
	return result
}

// A ValidationResult is returned from every validation method.
// It provides an indication of success, and a pointer to the Error (if any).
type ValidationResult struct {
	Error *ValidationError
	Ok    bool
}

func (r *ValidationResult) Key(key string) *ValidationResult {
	if r.Error != nil {
		r.Error.Key = key
	}
	return r
}

func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
	if r.Error != nil {
		if len(args) == 0 {
			r.Error.Message = message
		} else {
			r.Error.Message = fmt.Sprintf(message, args)
		}
	}
	return r
}

// Test that the argument is non-nil and non-empty (if string or list)
func (v *Validation) Required(obj interface{}) *ValidationResult {
	return v.apply(Required{}, obj)
}

func (v *Validation) Min(n int, min int) *ValidationResult {
	return v.apply(Min{min}, n)
}

func (v *Validation) Max(n int, max int) *ValidationResult {
	return v.apply(Max{max}, n)
}

func (v *Validation) Range(n, min, max int) *ValidationResult {
	return v.apply(Range{Min{min}, Max{max}}, n)
}

func (v *Validation) MinSize(obj interface{}, min int) *ValidationResult {
	return v.apply(MinSize{min}, obj)
}

func (v *Validation) MaxSize(obj interface{}, max int) *ValidationResult {
	return v.apply(MaxSize{max}, obj)
}

func (v *Validation) Length(obj interface{}, n int) *ValidationResult {
	return v.apply(Length{n}, obj)
}

func (v *Validation) Match(str string, regex *regexp.Regexp) *ValidationResult {
	return v.apply(Match{regex}, str)
}

func (v *Validation) Email(str string) *ValidationResult {
	return v.apply(Email{Match{emailPattern}}, str)
}

func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
	if chk.IsSatisfied(obj) {
		return &ValidationResult{Ok: true}
	}

	// Get the default key.
	var key string
	if pc, _, line, ok := runtime.Caller(2); ok {
		f := runtime.FuncForPC(pc)
		if defaultKeys, ok := DefaultValidationKeys[f.Name()]; ok {
			key = defaultKeys[line]
		}
	} else {
		INFO.Println("Failed to get Caller information to look up Validation key")
	}

	// Add the error to the validation context.
	err := &ValidationError{
		Message: chk.DefaultMessage(),
		Key:     key,
	}
	v.Errors = append(v.Errors, err)

	// Also return it in the result.
	return &ValidationResult{
		Ok:    false,
		Error: err,
	}
}

// Apply a group of validators to a field, in order, and return the
// ValidationResult from the first one that fails, or the last one that
// succeeds.
func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResult {
	var result *ValidationResult
	for _, check := range checks {
		result = v.apply(check, obj)
		if !result.Ok {
			return result
		}
	}
	return result
}

func ValidationFilter(c *Controller, fc []Filter) {
	c.Validation = &Validation{
		Errors: restoreValidationErrors(c.Request.Request),
		keep:   false,
	}

	fc[0](c, fc[1:])

	// Add Validation errors to RenderArgs.
	c.RenderArgs["errors"] = c.Validation.ErrorMap()

	// Store the Validation errors
	var errorsValue string
	if c.Validation.keep {
		for _, error := range c.Validation.Errors {
			if error.Message != "" {
				errorsValue += "\x00" + error.Key + ":" + error.Message + "\x00"
			}
		}
	}
	c.SetCookie(&http.Cookie{
		Name:  CookiePrefix + "_ERRORS",
		Value: url.QueryEscape(errorsValue),
		Path:  "/",
	})
}

// Restore Validation.Errors from a request.
func restoreValidationErrors(req *http.Request) []*ValidationError {
	errors := make([]*ValidationError, 0, 5)
	if cookie, err := req.Cookie(CookiePrefix + "_ERRORS"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			errors = append(errors, &ValidationError{
				Key:     key,
				Message: val,
			})
		})
	}
	return errors
}

// Register default validation keys for all calls to Controller.Validation.Func().
// Map from (package).func => (line => name of first arg to Validation func)
// E.g. "myapp/controllers.helper" or "myapp/controllers.(*Application).Action"
// This is set on initialization in the generated main.go file.
var DefaultValidationKeys map[string]map[int]string
<|endoftext|>


<commit_before>// Copyright 2021 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 noder_test

import (
	"encoding/json"
	"flag"
	exec "internal/execabs"
	"os"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

var (
	flagPkgs     = flag.String("pkgs", "std", "list of packages to compare (ignored in -short mode)")
	flagAll      = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets")
	flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel")
)

// TestUnifiedCompare implements a test similar to running:
//
//	$ go build -toolexec="toolstash -cmp" std
//
// The -pkgs flag controls the list of packages tested.
//
// By default, only the native GOOS/GOARCH target is enabled. The -all
// flag enables testing of non-native targets. The -parallel flag
// additionally enables testing of targets in parallel.
//
// Caution: Testing all targets is very resource intensive! On an IBM
// P920 (dual Intel Xeon Gold 6154 CPUs; 36 cores, 192GB RAM), testing
// all targets in parallel takes about 5 minutes. Using the 'go test'
// command's -run flag for subtest matching is recommended for less
// powerful machines.
func TestUnifiedCompare(t *testing.T) {
	targets, err := exec.Command("go", "tool", "dist", "list").Output()
	if err != nil {
		t.Fatal(err)
	}

	for _, target := range strings.Fields(string(targets)) {
		t.Run(target, func(t *testing.T) {
			parts := strings.Split(target, "/")
			goos, goarch := parts[0], parts[1]

			if !(*flagAll || goos == runtime.GOOS && goarch == runtime.GOARCH) {
				t.Skip("skipping non-native target (use -all to enable)")
			}
			if *flagParallel {
				t.Parallel()
			}

			pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0")
			pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0")

			if len(pkgs1) != len(pkgs2) {
				t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2))
			}

			for i := range pkgs1 {
				pkg1 := pkgs1[i]
				pkg2 := pkgs2[i]

				path := pkg1.ImportPath
				if path != pkg2.ImportPath {
					t.Fatalf("mismatched paths: %q != %q", path, pkg2.ImportPath)
				}

				// Packages that don't have any source files (e.g., packages
				// unsafe, embed/internal/embedtest, and cmd/internal/moddeps).
				if pkg1.Export == "" && pkg2.Export == "" {
					continue
				}

				if pkg1.BuildID == pkg2.BuildID {
					t.Errorf("package %q: build IDs unexpectedly matched", path)
				}

				// Unlike toolstash -cmp, we're comparing the same compiler
				// binary against itself, just with different flags. So we
				// don't need to worry about skipping over mismatched version
				// strings, but we do need to account for differing build IDs.
				//
				// Fortunately, build IDs are cryptographic 256-bit hashes,
				// and cmd/go provides us with them up front. So we can just
				// use them as delimeters to split the files, and then check
				// that the substrings are all equal.
				file1 := strings.Split(readFile(t, pkg1.Export), pkg1.BuildID)
				file2 := strings.Split(readFile(t, pkg2.Export), pkg2.BuildID)
				if !reflect.DeepEqual(file1, file2) {
					t.Errorf("package %q: compile output differs", path)
				}
			}
		})
	}
}

type pkg struct {
	ImportPath string
	Export     string
	BuildID    string
	Incomplete bool
}

func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg {
	args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"}
	if testing.Short() {
		t.Log("short testing mode; only testing package runtime")
		args = append(args, "runtime")
	} else {
		args = append(args, strings.Fields(*flagPkgs)...)
	}

	cmd := exec.Command("go", args...)
	cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch)
	cmd.Stderr = os.Stderr
	t.Logf("running %v", cmd)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		t.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	var res []pkg
	for dec := json.NewDecoder(stdout); dec.More(); {
		var pkg pkg
		if err := dec.Decode(&pkg); err != nil {
			t.Fatal(err)
		}
		if pkg.Incomplete {
			t.Fatalf("incomplete package: %q", pkg.ImportPath)
		}
		res = append(res, pkg)
	}
	if err := cmd.Wait(); err != nil {
		t.Fatal(err)
	}
	return res
}

func readFile(t *testing.T, name string) string {
	buf, err := os.ReadFile(name)
	if err != nil {
		t.Fatal(err)
	}
	return string(buf)
}
<commit_msg>cmd/compile/internal/noder: hide TestUnifiedCompare behind -cmp flag<commit_after>// Copyright 2021 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 noder_test

import (
	"encoding/json"
	"flag"
	exec "internal/execabs"
	"os"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

var (
	flagCmp      = flag.Bool("cmp", false, "enable TestUnifiedCompare")
	flagPkgs     = flag.String("pkgs", "std", "list of packages to compare (ignored in -short mode)")
	flagAll      = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets")
	flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel")
)

// TestUnifiedCompare implements a test similar to running:
//
//	$ go build -toolexec="toolstash -cmp" std
//
// The -pkgs flag controls the list of packages tested.
//
// By default, only the native GOOS/GOARCH target is enabled. The -all
// flag enables testing of non-native targets. The -parallel flag
// additionally enables testing of targets in parallel.
//
// Caution: Testing all targets is very resource intensive! On an IBM
// P920 (dual Intel Xeon Gold 6154 CPUs; 36 cores, 192GB RAM), testing
// all targets in parallel takes about 5 minutes. Using the 'go test'
// command's -run flag for subtest matching is recommended for less
// powerful machines.
func TestUnifiedCompare(t *testing.T) {
	// TODO(mdempsky): Either re-enable or delete. Disabled for now to
	// avoid impeding others' forward progress.
	if !*flagCmp {
		t.Skip("skipping TestUnifiedCompare (use -cmp to enable)")
	}

	targets, err := exec.Command("go", "tool", "dist", "list").Output()
	if err != nil {
		t.Fatal(err)
	}

	for _, target := range strings.Fields(string(targets)) {
		t.Run(target, func(t *testing.T) {
			parts := strings.Split(target, "/")
			goos, goarch := parts[0], parts[1]

			if !(*flagAll || goos == runtime.GOOS && goarch == runtime.GOARCH) {
				t.Skip("skipping non-native target (use -all to enable)")
			}
			if *flagParallel {
				t.Parallel()
			}

			pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0")
			pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0")

			if len(pkgs1) != len(pkgs2) {
				t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2))
			}

			for i := range pkgs1 {
				pkg1 := pkgs1[i]
				pkg2 := pkgs2[i]

				path := pkg1.ImportPath
				if path != pkg2.ImportPath {
					t.Fatalf("mismatched paths: %q != %q", path, pkg2.ImportPath)
				}

				// Packages that don't have any source files (e.g., packages
				// unsafe, embed/internal/embedtest, and cmd/internal/moddeps).
				if pkg1.Export == "" && pkg2.Export == "" {
					continue
				}

				if pkg1.BuildID == pkg2.BuildID {
					t.Errorf("package %q: build IDs unexpectedly matched", path)
				}

				// Unlike toolstash -cmp, we're comparing the same compiler
				// binary against itself, just with different flags. So we
				// don't need to worry about skipping over mismatched version
				// strings, but we do need to account for differing build IDs.
				//
				// Fortunately, build IDs are cryptographic 256-bit hashes,
				// and cmd/go provides us with them up front. So we can just
				// use them as delimeters to split the files, and then check
				// that the substrings are all equal.
				file1 := strings.Split(readFile(t, pkg1.Export), pkg1.BuildID)
				file2 := strings.Split(readFile(t, pkg2.Export), pkg2.BuildID)
				if !reflect.DeepEqual(file1, file2) {
					t.Errorf("package %q: compile output differs", path)
				}
			}
		})
	}
}

type pkg struct {
	ImportPath string
	Export     string
	BuildID    string
	Incomplete bool
}

func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg {
	args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"}
	if testing.Short() {
		t.Log("short testing mode; only testing package runtime")
		args = append(args, "runtime")
	} else {
		args = append(args, strings.Fields(*flagPkgs)...)
	}

	cmd := exec.Command("go", args...)
	cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch)
	cmd.Stderr = os.Stderr
	t.Logf("running %v", cmd)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		t.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}

	var res []pkg
	for dec := json.NewDecoder(stdout); dec.More(); {
		var pkg pkg
		if err := dec.Decode(&pkg); err != nil {
			t.Fatal(err)
		}
		if pkg.Incomplete {
			t.Fatalf("incomplete package: %q", pkg.ImportPath)
		}
		res = append(res, pkg)
	}
	if err := cmd.Wait(); err != nil {
		t.Fatal(err)
	}
	return res
}

func readFile(t *testing.T, name string) string {
	buf, err := os.ReadFile(name)
	if err != nil {
		t.Fatal(err)
	}
	return string(buf)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"

	"github.com/docker/hyperkit/go"

	"github.com/docker/infrakit/pkg/spi/instance"
	"github.com/docker/infrakit/pkg/types"
)

// NewHyperKitPlugin creates an instance plugin for hyperkit.
func NewHyperKitPlugin(vmDir, hyperkit, vpnkitSock string) instance.Plugin {
	return &hyperkitPlugin{VMDir: vmDir,
		HyperKit:   hyperkit,
		VPNKitSock: vpnkitSock,
	}
}

type hyperkitPlugin struct {
	// VMDir is the path to a directory where per VM state is kept
	VMDir string

	// Hyperkit is the path to the hyperkit executable
	HyperKit string

	// VPNKitSock is the path to the VPNKit Unix domain socket.
	VPNKitSock string
}

// Validate performs local validation on a provision request.
func (p hyperkitPlugin) Validate(req *types.Any) error {
	return nil
}

// Provision creates a new instance.
func (p hyperkitPlugin) Provision(spec instance.Spec) (*instance.ID, error) {

	var properties map[string]interface{}

	if spec.Properties != nil {
		if err := spec.Properties.Decode(&properties); err != nil {
			return nil, fmt.Errorf("Invalid instance properties: %s", err)
		}
	}

	if properties["Moby"] == nil {
		return nil, errors.New("Property 'Moby' must be set")
	}
	if properties["CPUs"] == nil {
		properties["CPUs"] = 1
	}
	if properties["Memory"] == nil {
		properties["Memory"] = 512
	}
	if properties["Disk"] == nil {
		properties["Disk"] = 256
	}

	instanceDir, err := ioutil.TempDir(p.VMDir, "infrakit-")
	if err != nil {
		return nil, err
	}
	id := instance.ID(path.Base(instanceDir))

	// Start a HyperKit instance
	h, err := hyperkit.New(p.HyperKit, instanceDir, p.VPNKitSock, "")
	if err != nil {
		return nil, err
	}
	h.Kernel = properties["Moby"].(string) + "-bzImage"
	h.Initrd = properties["Moby"].(string) + "-initrd.img"
	h.CPUs = int(properties["CPUs"].(float64))
	h.Memory = int(properties["Memory"].(float64))
	h.DiskSize = int(properties["Disk"].(float64))
	h.UserData = spec.Init
	h.Console = hyperkit.ConsoleFile
	err = h.Start("console=ttyS0")
	if err != nil {
		return nil, err
	}
	log.Info("Started new VM: ", id)

	tagData, err := types.AnyValue(spec.Tags)
	if err != nil {
		return nil, err
	}

	if err := ioutil.WriteFile(path.Join(instanceDir, "tags"), tagData.Bytes(), 0644); err != nil {
		return nil, err
	}

	return &id, nil
}

// Label labels the instance
func (p hyperkitPlugin) Label(instance instance.ID, labels map[string]string) error {
	instanceDir := path.Join(p.VMDir, string(instance))
	tagFile := path.Join(instanceDir, "tags")
	buff, err := ioutil.ReadFile(tagFile)
	if err != nil {
		return err
	}

	tags := map[string]string{}
	err = types.AnyBytes(buff).Decode(&tags)
	if err != nil {
		return err
	}

	for k, v := range labels {
		tags[k] = v
	}

	encoded, err := types.AnyValue(tags)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(tagFile, encoded.Bytes(), 0644)
}

// Destroy terminates an existing instance.
func (p hyperkitPlugin) Destroy(id instance.ID) error {
	log.Info("Destroying VM: ", id)

	instanceDir := path.Join(p.VMDir, string(id))
	_, err := os.Stat(instanceDir)
	if err != nil {
		if os.IsNotExist(err) {
			return errors.New("Instance does not exist")
		}
	}

	h, err := hyperkit.FromState(instanceDir)
	if err != nil {
		return err
	}
	err = h.Stop()
	if err != nil {
		return err
	}
	err = h.Remove(false)
	if err != nil {
		return err
	}
	return nil
}

// DescribeInstances returns descriptions of all instances matching all of the provided tags.
func (p hyperkitPlugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
	files, err := ioutil.ReadDir(p.VMDir)
	if err != nil {
		return nil, err
	}

	descriptions := []instance.Description{}

	for _, file := range files {
		if !file.IsDir() {
			continue
		}

		instanceDir := path.Join(p.VMDir, file.Name())

		tagData, err := ioutil.ReadFile(path.Join(instanceDir, "tags"))
		if err != nil {
			if os.IsNotExist(err) {
				continue
			}

			return nil, err
		}

		instanceTags := map[string]string{}
		if err := types.AnyBytes(tagData).Decode(&instanceTags); err != nil {
			return nil, err
		}

		allMatched := true
		for k, v := range tags {
			value, exists := instanceTags[k]
			if !exists || v != value {
				allMatched = false
				break
			}
		}

		if allMatched {
			var logicalID *instance.LogicalID
			id := instance.ID(file.Name())

			h, err := hyperkit.FromState(instanceDir)
			if err != nil {
				log.Warningln("Could not get instance data. Id: ", id)
				p.Destroy(id)
				continue
			}
			if !h.IsRunning() {
				log.Warningln("Instance is not running. Id: ", id)
				p.Destroy(id)
				continue
			}
			lid := instance.LogicalID(h.Pid)
			logicalID = &lid

			descriptions = append(descriptions, instance.Description{
				ID:        id,
				LogicalID: logicalID,
				Tags:      instanceTags,
			})
		}
	}

	return descriptions, nil
}
<commit_msg>infrakit: Update HyperKit plugin to new API<commit_after>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"

	"github.com/docker/hyperkit/go"

	"github.com/docker/infrakit/pkg/spi/instance"
	"github.com/docker/infrakit/pkg/types"
)

// NewHyperKitPlugin creates an instance plugin for hyperkit.
func NewHyperKitPlugin(vmDir, hyperkit, vpnkitSock string) instance.Plugin {
	return &hyperkitPlugin{VMDir: vmDir,
		HyperKit:   hyperkit,
		VPNKitSock: vpnkitSock,
	}
}

type hyperkitPlugin struct {
	// VMDir is the path to a directory where per VM state is kept
	VMDir string

	// Hyperkit is the path to the hyperkit executable
	HyperKit string

	// VPNKitSock is the path to the VPNKit Unix domain socket.
	VPNKitSock string
}

// Validate performs local validation on a provision request.
func (p hyperkitPlugin) Validate(req *types.Any) error {
	return nil
}

// Provision creates a new instance.
func (p hyperkitPlugin) Provision(spec instance.Spec) (*instance.ID, error) {

	var properties map[string]interface{}

	if spec.Properties != nil {
		if err := spec.Properties.Decode(&properties); err != nil {
			return nil, fmt.Errorf("Invalid instance properties: %s", err)
		}
	}

	if properties["Moby"] == nil {
		return nil, errors.New("Property 'Moby' must be set")
	}
	if properties["CPUs"] == nil {
		properties["CPUs"] = 1
	}
	if properties["Memory"] == nil {
		properties["Memory"] = 512
	}
	if properties["Disk"] == nil {
		properties["Disk"] = 256
	}

	instanceDir, err := ioutil.TempDir(p.VMDir, "infrakit-")
	if err != nil {
		return nil, err
	}
	id := instance.ID(path.Base(instanceDir))

	// Start a HyperKit instance
	h, err := hyperkit.New(p.HyperKit, instanceDir, p.VPNKitSock, "")
	if err != nil {
		return nil, err
	}
	h.Kernel = properties["Moby"].(string) + "-bzImage"
	h.Initrd = properties["Moby"].(string) + "-initrd.img"
	h.CPUs = int(properties["CPUs"].(float64))
	h.Memory = int(properties["Memory"].(float64))
	h.DiskSize = int(properties["Disk"].(float64))
	h.UserData = spec.Init
	h.Console = hyperkit.ConsoleFile
	err = h.Start("console=ttyS0")
	if err != nil {
		return nil, err
	}
	log.Info("Started new VM: ", id)

	tagData, err := types.AnyValue(spec.Tags)
	if err != nil {
		return nil, err
	}

	if err := ioutil.WriteFile(path.Join(instanceDir, "tags"), tagData.Bytes(), 0644); err != nil {
		return nil, err
	}

	return &id, nil
}

// Label labels the instance
func (p hyperkitPlugin) Label(instance instance.ID, labels map[string]string) error {
	instanceDir := path.Join(p.VMDir, string(instance))
	tagFile := path.Join(instanceDir, "tags")
	buff, err := ioutil.ReadFile(tagFile)
	if err != nil {
		return err
	}

	tags := map[string]string{}
	err = types.AnyBytes(buff).Decode(&tags)
	if err != nil {
		return err
	}

	for k, v := range labels {
		tags[k] = v
	}

	encoded, err := types.AnyValue(tags)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(tagFile, encoded.Bytes(), 0644)
}

// Destroy terminates an existing instance.
func (p hyperkitPlugin) Destroy(id instance.ID) error {
	log.Info("Destroying VM: ", id)

	instanceDir := path.Join(p.VMDir, string(id))
	_, err := os.Stat(instanceDir)
	if err != nil {
		if os.IsNotExist(err) {
			return errors.New("Instance does not exist")
		}
	}

	h, err := hyperkit.FromState(instanceDir)
	if err != nil {
		return err
	}
	err = h.Stop()
	if err != nil {
		return err
	}
	err = h.Remove(false)
	if err != nil {
		return err
	}
	return nil
}

// DescribeInstances returns descriptions of all instances matching all of the provided tags.
func (p hyperkitPlugin) DescribeInstances(tags map[string]string, properties bool) ([]instance.Description, error) {
	files, err := ioutil.ReadDir(p.VMDir)
	if err != nil {
		return nil, err
	}

	descriptions := []instance.Description{}

	for _, file := range files {
		if !file.IsDir() {
			continue
		}

		instanceDir := path.Join(p.VMDir, file.Name())

		tagData, err := ioutil.ReadFile(path.Join(instanceDir, "tags"))
		if err != nil {
			if os.IsNotExist(err) {
				continue
			}

			return nil, err
		}

		instanceTags := map[string]string{}
		if err := types.AnyBytes(tagData).Decode(&instanceTags); err != nil {
			return nil, err
		}

		allMatched := true
		for k, v := range tags {
			value, exists := instanceTags[k]
			if !exists || v != value {
				allMatched = false
				break
			}
		}

		if allMatched {
			var logicalID *instance.LogicalID
			id := instance.ID(file.Name())

			h, err := hyperkit.FromState(instanceDir)
			if err != nil {
				log.Warningln("Could not get instance data. Id: ", id)
				p.Destroy(id)
				continue
			}
			if !h.IsRunning() {
				log.Warningln("Instance is not running. Id: ", id)
				p.Destroy(id)
				continue
			}
			lid := instance.LogicalID(h.Pid)
			logicalID = &lid

			descriptions = append(descriptions, instance.Description{
				ID:        id,
				LogicalID: logicalID,
				Tags:      instanceTags,
			})
		}
	}

	return descriptions, nil
}
<|endoftext|>


<commit_before>package jsonschema

import (
	"encoding/json"
	"fmt"
	"regexp"
	"strings"
	"unicode/utf8"
)

type maximum struct {
	json.Number
	exclusive bool
}

func (m maximum) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	var isLarger bool
	switch n := normalized.(type) {
	case int64:
		isLarger, err = m.isLargerThanInt(n)
	case float64:
		isLarger, err = m.isLargerThanFloat(n)
	default:
		return nil
	}
	if err != nil {
		return nil
	}
	if !isLarger {
		maxErr := fmt.Sprintf("Value must be smaller than %s.", m)
		return []ValidationError{ValidationError{maxErr}}
	}
	return nil
}

func (m maximum) isLargerThanInt(n int64) (bool, error) {
	if !strings.Contains(m.String(), ".") {
		max, err := m.Int64()
		if err != nil {
			return false, err
		}
		return max > n || !m.exclusive && max == n, nil
	} else {
		return m.isLargerThanFloat(float64(n))
	}
}

func (m maximum) isLargerThanFloat(n float64) (isLarger bool, err error) {
	max, err := m.Float64()
	if err != nil {
		return
	}
	return max > n || !m.exclusive && max == n, nil
}

func (m *maximum) SetSchema(v map[string]json.RawMessage) {
	value, ok := v["exclusiveMaximum"]
	if ok {
		// Ignore errors from Unmarshal. If exclusiveMaximum is a non boolean JSON
		// value we leave it as false.
		json.Unmarshal(value, &m.exclusive)
	}
	return
}

func (m *maximum) UnmarshalJSON(b []byte) error {
	return json.Unmarshal(b, &m.Number)
}

type minimum struct {
	json.Number
	exclusive bool
}

func (m minimum) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	var isLarger bool
	switch n := normalized.(type) {
	case int64:
		isLarger, err = m.isLargerThanInt(n)
	case float64:
		isLarger, err = m.isLargerThanFloat(n)
	default:
		return nil
	}
	if err != nil {
		return nil
	}
	if isLarger {
		minErr := fmt.Sprintf("Value must be smaller than %s.", m)
		return []ValidationError{ValidationError{minErr}}
	}
	return nil
}

func (m minimum) isLargerThanInt(n int64) (bool, error) {
	if !strings.Contains(m.String(), ".") {
		min, err := m.Int64()
		if err != nil {
			return false, nil
		}
		return min > n || !m.exclusive && min == n, nil
	} else {
		return m.isLargerThanFloat(float64(n))
	}
}

func (m minimum) isLargerThanFloat(n float64) (isLarger bool, err error) {
	min, err := m.Float64()
	if err != nil {
		return
	}
	return min > n || !m.exclusive && min == n, nil
}

func (m *minimum) SetSchema(v map[string]json.RawMessage) {
	value, ok := v["exclusiveminimum"]
	if ok {
		// Ignore errors from Unmarshal. If exclusiveminimum is a non boolean JSON
		// value we leave it as false.
		json.Unmarshal(value, &m.exclusive)
	}
	return
}

func (m *minimum) UnmarshalJSON(b []byte) error {
	return json.Unmarshal(b, &m.Number)
}

type multipleOf int64

// Contrary to the spec, validation doesn't support floats in the schema
// or the data being validated. This is because of issues with math.Mod,
// e.g. math.Mod(0.0075, 0.0001) != 0.
func (m multipleOf) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	n, ok := normalized.(int64)
	if !ok {
		return nil
	}
	if n%int64(m) != 0 {
		mulErr := ValidationError{fmt.Sprintf("Value must be a multiple of %d.", m)}
		return []ValidationError{mulErr}
	}
	return nil
}

func (m *multipleOf) UnmarshalJSON(b []byte) error {
	var n int64
	if err := json.Unmarshal(b, &n); err != nil {
		return err
	}
	*m = multipleOf(n)
	return nil
}

type maxLength int

func (m maxLength) Validate(v interface{}) []ValidationError {
	l, ok := v.(string)
	if !ok {
		return nil
	}
	if utf8.RuneCountInString(l) > int(m) {
		lenErr := ValidationError{fmt.Sprintf("String length must be shorter than %d characters.", m)}
		return []ValidationError{lenErr}
	}
	return nil
}

type minLength int

func (m minLength) Validate(v interface{}) []ValidationError {
	l, ok := v.(string)
	if !ok {
		return nil
	}
	if utf8.RuneCountInString(l) < int(m) {
		lenErr := ValidationError{fmt.Sprintf("String length must be shorter than %d characters.", m)}
		return []ValidationError{lenErr}
	}
	return nil
}

type pattern struct {
	regexp.Regexp
}

func (p pattern) Validate(v interface{}) []ValidationError {
	s, ok := v.(string)
	if !ok {
		return nil
	}
	if !p.MatchString(s) {
		patErr := ValidationError{fmt.Sprintf("String must match the pattern: \"%s\".", p.String())}
		return []ValidationError{patErr}
	}
	return nil
}

func (p *pattern) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	r, err := regexp.Compile(s)
	if err != nil {
		return err
	}
	p.Regexp = *r
	return nil
}

type maxItems int

func (m maxItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) > int(m) {
		maxErr := ValidationError{fmt.Sprintf("Array must have fewer than %d items.", m)}
		return []ValidationError{maxErr}
	}
	return nil
}

type minItems int

func (m minItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) < int(m) {
		minErr := ValidationError{fmt.Sprintf("Array must have more than %d items.", m)}
		return []ValidationError{minErr}
	}
	return nil
}

// The spec[0] is useless for this keyword. The implemention here is based on the tests and this[1] guide.
//
// [0] http://json-schema.org/latest/json-schema-validation.html#anchor37
// [1] http://spacetelescope.github.io/understanding-json-schema/reference/array.html
type items struct {
	schema            *Schema
	schemaSlice       []*Schema
	additionalAllowed bool
	additionalItems   *Schema
}

func (i items) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	instances, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if i.schema != nil {
		for _, value := range instances {
			valErrs = append(valErrs, i.schema.Validate(value)...)
		}
	} else if i.schemaSlice != nil {
		for pos, value := range instances {
			if pos <= len(i.schemaSlice)-1 {
				schema := i.schemaSlice[pos]
				valErrs = append(valErrs, schema.Validate(value)...)
			} else if i.additionalAllowed {
				if i.additionalItems == nil {
					continue
				}
				valErrs = append(valErrs, i.additionalItems.Validate(value)...)
			} else if !i.additionalAllowed {
				return []ValidationError{ValidationError{"Additional items aren't allowed."}}
			}
		}
	}
	return valErrs
}

func (i *items) SetSchema(v map[string]json.RawMessage) {
	i.additionalAllowed = true
	value, ok := v["additionalItems"]
	if !ok {
		return
	}
	json.Unmarshal(value, &i.additionalAllowed)
	json.Unmarshal(value, &i.additionalItems)
	return
}

func (i *items) UnmarshalJSON(b []byte) error {
	if err1 := json.Unmarshal(b, &i.schema); err1 != nil {
		i.schema = nil
	}
	if err := json.Unmarshal(b, &i.schemaSlice); err != nil {
		i.schemaSlice = nil
		return err
	}
	return nil
}

type properties map[string]json.RawMessage

func (p properties) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	for schemaKey, schemaValue := range p {
		dataMap, ok := v.(map[string]interface{})
		if !ok {
			continue
		}
		if dataValue, ok := dataMap[schemaKey]; ok {
			var schema Schema
			err := json.Unmarshal(schemaValue, &schema)
			if err != nil {
				break
			}
			valErrs = append(valErrs, schema.Validate(dataValue)...)
		}
	}
	return valErrs
}

type allOf []Schema

func (a allOf) Validate(v interface{}) (valErrs []ValidationError) {
	for _, schema := range a {
		valErrs = append(valErrs, schema.Validate(v)...)
	}
	return
}

type anyOf []Schema

func (a anyOf) Validate(v interface{}) []ValidationError {
	for _, schema := range a {
		if schema.Validate(v) == nil {
			return nil
		}
	}
	return []ValidationError{
		ValidationError{"Validation failed for each schema in 'anyOf'."}}
}

type enum []interface{}

func (a enum) Validate(v interface{}) []ValidationError {
	for _, b := range a {
		if isEqual(v, b) {
			return nil
		}
	}
	return []ValidationError{
		ValidationError{"enum failed."}}
}

type not Schema

func (n not) Validate(v interface{}) []ValidationError {
	schema := Schema{n.vals}
	if schema.Validate(v) == nil {
		return []ValidationError{ValidationError{"The 'not' schema didn't raise an error."}}
	}
	return nil
}

func (n *not) UnmarshalJSON(b []byte) error {
	var s Schema
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	*n = not(s)
	return nil
}

type oneOf []Schema

func (a oneOf) Validate(v interface{}) []ValidationError {
	var succeeded int
	for _, schema := range a {
		if schema.Validate(v) == nil {
			succeeded += 1
		}
	}
	if succeeded != 1 {
		return []ValidationError{ValidationError{
			fmt.Sprintf("Validation passed for %d schemas in 'oneOf'.", succeeded)}}
	}
	return nil
}

type typeValidator map[string]bool

func (t typeValidator) Validate(v interface{}) []ValidationError {
	var s string

	switch x := v.(type) {

	case string:
		s = "string"
	case bool:
		s = "boolean"
	case nil:
		s = "null"
	case []interface{}:
		s = "array"
	case map[string]interface{}:
		s = "object"

	case json.Number:
		if strings.Contains(x.String(), ".") {
			s = "number"
		} else {
			s = "integer"
		}
	case float64:
		s = "number"
	}

	_, ok := t[s]

	// The "number" type includes the "integer" type.
	if !ok && s == "integer" {
		_, ok = t["number"]
	}

	if !ok {
		types := make([]string, 0, len(t))
		for key, _ := range t {
			types = append(types, key)
		}
		return []ValidationError{ValidationError{
			fmt.Sprintf("Value must be one of these types: %s.", types)}}
	}
	return nil
}

func (t *typeValidator) UnmarshalJSON(b []byte) error {
	*t = make(typeValidator)
	var s string
	var l []string

	// The value of the "type" keyword can be a string or an array.
	if err := json.Unmarshal(b, &s); err != nil {
		err = json.Unmarshal(b, &l)
		if err != nil {
			return err
		}
	} else {
		l = []string{s}
	}

	for _, val := range l {
		(*t)[val] = true
	}
	return nil
}
<commit_msg>Add a real error message for the enum validator.<commit_after>package jsonschema

import (
	"encoding/json"
	"fmt"
	"regexp"
	"strings"
	"unicode/utf8"
)

type maximum struct {
	json.Number
	exclusive bool
}

func (m maximum) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	var isLarger bool
	switch n := normalized.(type) {
	case int64:
		isLarger, err = m.isLargerThanInt(n)
	case float64:
		isLarger, err = m.isLargerThanFloat(n)
	default:
		return nil
	}
	if err != nil {
		return nil
	}
	if !isLarger {
		maxErr := fmt.Sprintf("Value must be smaller than %s.", m)
		return []ValidationError{ValidationError{maxErr}}
	}
	return nil
}

func (m maximum) isLargerThanInt(n int64) (bool, error) {
	if !strings.Contains(m.String(), ".") {
		max, err := m.Int64()
		if err != nil {
			return false, err
		}
		return max > n || !m.exclusive && max == n, nil
	} else {
		return m.isLargerThanFloat(float64(n))
	}
}

func (m maximum) isLargerThanFloat(n float64) (isLarger bool, err error) {
	max, err := m.Float64()
	if err != nil {
		return
	}
	return max > n || !m.exclusive && max == n, nil
}

func (m *maximum) SetSchema(v map[string]json.RawMessage) {
	value, ok := v["exclusiveMaximum"]
	if ok {
		// Ignore errors from Unmarshal. If exclusiveMaximum is a non boolean JSON
		// value we leave it as false.
		json.Unmarshal(value, &m.exclusive)
	}
	return
}

func (m *maximum) UnmarshalJSON(b []byte) error {
	return json.Unmarshal(b, &m.Number)
}

type minimum struct {
	json.Number
	exclusive bool
}

func (m minimum) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	var isLarger bool
	switch n := normalized.(type) {
	case int64:
		isLarger, err = m.isLargerThanInt(n)
	case float64:
		isLarger, err = m.isLargerThanFloat(n)
	default:
		return nil
	}
	if err != nil {
		return nil
	}
	if isLarger {
		minErr := fmt.Sprintf("Value must be smaller than %s.", m)
		return []ValidationError{ValidationError{minErr}}
	}
	return nil
}

func (m minimum) isLargerThanInt(n int64) (bool, error) {
	if !strings.Contains(m.String(), ".") {
		min, err := m.Int64()
		if err != nil {
			return false, nil
		}
		return min > n || !m.exclusive && min == n, nil
	} else {
		return m.isLargerThanFloat(float64(n))
	}
}

func (m minimum) isLargerThanFloat(n float64) (isLarger bool, err error) {
	min, err := m.Float64()
	if err != nil {
		return
	}
	return min > n || !m.exclusive && min == n, nil
}

func (m *minimum) SetSchema(v map[string]json.RawMessage) {
	value, ok := v["exclusiveminimum"]
	if ok {
		// Ignore errors from Unmarshal. If exclusiveminimum is a non boolean JSON
		// value we leave it as false.
		json.Unmarshal(value, &m.exclusive)
	}
	return
}

func (m *minimum) UnmarshalJSON(b []byte) error {
	return json.Unmarshal(b, &m.Number)
}

type multipleOf int64

// Contrary to the spec, validation doesn't support floats in the schema
// or the data being validated. This is because of issues with math.Mod,
// e.g. math.Mod(0.0075, 0.0001) != 0.
func (m multipleOf) Validate(v interface{}) []ValidationError {
	normalized, err := normalizeNumber(v)
	if err != nil {
		return []ValidationError{ValidationError{err.Error()}}
	}
	n, ok := normalized.(int64)
	if !ok {
		return nil
	}
	if n%int64(m) != 0 {
		mulErr := ValidationError{fmt.Sprintf("Value must be a multiple of %d.", m)}
		return []ValidationError{mulErr}
	}
	return nil
}

func (m *multipleOf) UnmarshalJSON(b []byte) error {
	var n int64
	if err := json.Unmarshal(b, &n); err != nil {
		return err
	}
	*m = multipleOf(n)
	return nil
}

type maxLength int

func (m maxLength) Validate(v interface{}) []ValidationError {
	l, ok := v.(string)
	if !ok {
		return nil
	}
	if utf8.RuneCountInString(l) > int(m) {
		lenErr := ValidationError{fmt.Sprintf("String length must be shorter than %d characters.", m)}
		return []ValidationError{lenErr}
	}
	return nil
}

type minLength int

func (m minLength) Validate(v interface{}) []ValidationError {
	l, ok := v.(string)
	if !ok {
		return nil
	}
	if utf8.RuneCountInString(l) < int(m) {
		lenErr := ValidationError{fmt.Sprintf("String length must be shorter than %d characters.", m)}
		return []ValidationError{lenErr}
	}
	return nil
}

type pattern struct {
	regexp.Regexp
}

func (p pattern) Validate(v interface{}) []ValidationError {
	s, ok := v.(string)
	if !ok {
		return nil
	}
	if !p.MatchString(s) {
		patErr := ValidationError{fmt.Sprintf("String must match the pattern: \"%s\".", p.String())}
		return []ValidationError{patErr}
	}
	return nil
}

func (p *pattern) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	r, err := regexp.Compile(s)
	if err != nil {
		return err
	}
	p.Regexp = *r
	return nil
}

type maxItems int

func (m maxItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) > int(m) {
		maxErr := ValidationError{fmt.Sprintf("Array must have fewer than %d items.", m)}
		return []ValidationError{maxErr}
	}
	return nil
}

type minItems int

func (m minItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) < int(m) {
		minErr := ValidationError{fmt.Sprintf("Array must have more than %d items.", m)}
		return []ValidationError{minErr}
	}
	return nil
}

// The spec[0] is useless for this keyword. The implemention here is based on the tests and this[1] guide.
//
// [0] http://json-schema.org/latest/json-schema-validation.html#anchor37
// [1] http://spacetelescope.github.io/understanding-json-schema/reference/array.html
type items struct {
	schema            *Schema
	schemaSlice       []*Schema
	additionalAllowed bool
	additionalItems   *Schema
}

func (i items) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	instances, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if i.schema != nil {
		for _, value := range instances {
			valErrs = append(valErrs, i.schema.Validate(value)...)
		}
	} else if i.schemaSlice != nil {
		for pos, value := range instances {
			if pos <= len(i.schemaSlice)-1 {
				schema := i.schemaSlice[pos]
				valErrs = append(valErrs, schema.Validate(value)...)
			} else if i.additionalAllowed {
				if i.additionalItems == nil {
					continue
				}
				valErrs = append(valErrs, i.additionalItems.Validate(value)...)
			} else if !i.additionalAllowed {
				return []ValidationError{ValidationError{"Additional items aren't allowed."}}
			}
		}
	}
	return valErrs
}

func (i *items) SetSchema(v map[string]json.RawMessage) {
	i.additionalAllowed = true
	value, ok := v["additionalItems"]
	if !ok {
		return
	}
	json.Unmarshal(value, &i.additionalAllowed)
	json.Unmarshal(value, &i.additionalItems)
	return
}

func (i *items) UnmarshalJSON(b []byte) error {
	if err1 := json.Unmarshal(b, &i.schema); err1 != nil {
		i.schema = nil
	}
	if err := json.Unmarshal(b, &i.schemaSlice); err != nil {
		i.schemaSlice = nil
		return err
	}
	return nil
}

type properties map[string]json.RawMessage

func (p properties) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	for schemaKey, schemaValue := range p {
		dataMap, ok := v.(map[string]interface{})
		if !ok {
			continue
		}
		if dataValue, ok := dataMap[schemaKey]; ok {
			var schema Schema
			err := json.Unmarshal(schemaValue, &schema)
			if err != nil {
				break
			}
			valErrs = append(valErrs, schema.Validate(dataValue)...)
		}
	}
	return valErrs
}

type allOf []Schema

func (a allOf) Validate(v interface{}) (valErrs []ValidationError) {
	for _, schema := range a {
		valErrs = append(valErrs, schema.Validate(v)...)
	}
	return
}

type anyOf []Schema

func (a anyOf) Validate(v interface{}) []ValidationError {
	for _, schema := range a {
		if schema.Validate(v) == nil {
			return nil
		}
	}
	return []ValidationError{
		ValidationError{"Validation failed for each schema in 'anyOf'."}}
}

type enum []interface{}

func (a enum) Validate(v interface{}) []ValidationError {
	for _, b := range a {
		if isEqual(v, b) {
			return nil
		}
	}
	return []ValidationError{
		ValidationError{fmt.Sprintf("Enum error. The data must be equal to one of these values %v.", a)}}
}

type not Schema

func (n not) Validate(v interface{}) []ValidationError {
	schema := Schema{n.vals}
	if schema.Validate(v) == nil {
		return []ValidationError{ValidationError{"The 'not' schema didn't raise an error."}}
	}
	return nil
}

func (n *not) UnmarshalJSON(b []byte) error {
	var s Schema
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	*n = not(s)
	return nil
}

type oneOf []Schema

func (a oneOf) Validate(v interface{}) []ValidationError {
	var succeeded int
	for _, schema := range a {
		if schema.Validate(v) == nil {
			succeeded += 1
		}
	}
	if succeeded != 1 {
		return []ValidationError{ValidationError{
			fmt.Sprintf("Validation passed for %d schemas in 'oneOf'.", succeeded)}}
	}
	return nil
}

type typeValidator map[string]bool

func (t typeValidator) Validate(v interface{}) []ValidationError {
	var s string

	switch x := v.(type) {

	case string:
		s = "string"
	case bool:
		s = "boolean"
	case nil:
		s = "null"
	case []interface{}:
		s = "array"
	case map[string]interface{}:
		s = "object"

	case json.Number:
		if strings.Contains(x.String(), ".") {
			s = "number"
		} else {
			s = "integer"
		}
	case float64:
		s = "number"
	}

	_, ok := t[s]

	// The "number" type includes the "integer" type.
	if !ok && s == "integer" {
		_, ok = t["number"]
	}

	if !ok {
		types := make([]string, 0, len(t))
		for key, _ := range t {
			types = append(types, key)
		}
		return []ValidationError{ValidationError{
			fmt.Sprintf("Value must be one of these types: %s.", types)}}
	}
	return nil
}

func (t *typeValidator) UnmarshalJSON(b []byte) error {
	*t = make(typeValidator)
	var s string
	var l []string

	// The value of the "type" keyword can be a string or an array.
	if err := json.Unmarshal(b, &s); err != nil {
		err = json.Unmarshal(b, &l)
		if err != nil {
			return err
		}
	} else {
		l = []string{s}
	}

	for _, val := range l {
		(*t)[val] = true
	}
	return nil
}
<|endoftext|>


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

package py

// #include "utils.h"
import "C"

import "unsafe"

type String struct {
	AbstractObject
	o C.PyStringObject
}

// StringType is the Type object that represents the String type.
var StringType = (*Type)(unsafe.Pointer(&C.PyString_Type))

func stringCheck(obj Object) bool {
	return C.stringCheck(c(obj)) != 0
}

func newString(obj *C.PyObject) *String {
	return (*String)(unsafe.Pointer(obj))
}

func NewString(s string) (*String, error) {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	ret := C.PyString_FromString(cs)
	if ret == nil {
		return nil, exception()
	}
	return newString(ret), nil
}

func (s *String) String() string {
	if s == nil {
		return "<nil>"
	}
	ret := C.PyString_AsString(c(s))
	if ret == nil {
		panic(exception())
	}
	return C.GoString(ret)
}

func (s *String) Format(args *Tuple) (*String, error) {
	ret := C.PyString_Format(c(s), c(args))
	if ret == nil {
		return nil, exception()
	}
	return newString(ret), nil
}
<commit_msg>Add a few more String methods<commit_after>// Copyright 2011 Julian Phillips.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package py

// #include "utils.h"
import "C"

import "unsafe"

type String struct {
	AbstractObject
	o C.PyStringObject
}

// StringType is the Type object that represents the String type.
var StringType = (*Type)(unsafe.Pointer(&C.PyString_Type))

func stringCheck(obj Object) bool {
	return C.stringCheck(c(obj)) != 0
}

func newString(obj *C.PyObject) *String {
	return (*String)(unsafe.Pointer(obj))
}

func NewString(s string) (*String, error) {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	ret := C.PyString_FromString(cs)
	if ret == nil {
		return nil, exception()
	}
	return newString(ret), nil
}

func (s *String) String() string {
	if s == nil {
		return "<nil>"
	}
	ret := C.PyString_AsString(c(s))
	if ret == nil {
		panic(exception())
	}
	return C.GoString(ret)
}

func (s *String) Format(args *Tuple) (*String, error) {
	ret := C.PyString_Format(c(s), c(args))
	if ret == nil {
		return nil, exception()
	}
	return newString(ret), nil
}

func (s *String) Size() int64 {
	ret := C.PyString_Size(c(s))
	return int64(ret)
}

func (s *String) Decode(encoding, errors string) (Object, error) {
	var cEncoding, cErrors *C.char
	if encoding == "" {
		cEncoding = C.CString(encoding)
		defer C.free(unsafe.Pointer(cEncoding))
	}
	if errors != "" {
		cErrors = C.CString(errors)
		defer C.free(unsafe.Pointer(cErrors))
	}
	ret := C.PyString_AsDecodedObject(c(s), cEncoding, cErrors)
	return obj2ObjErr(ret)
}

func (s *String) Encode(encoding, errors string) (Object, error) {
	var cEncoding, cErrors *C.char
	if encoding == "" {
		cEncoding = C.CString(encoding)
		defer C.free(unsafe.Pointer(cEncoding))
	}
	if errors != "" {
		cErrors = C.CString(errors)
		defer C.free(unsafe.Pointer(cErrors))
	}
	ret := C.PyString_AsEncodedObject(c(s), cEncoding, cErrors)
	return obj2ObjErr(ret)
}
<|endoftext|>


<commit_before>package stm

const (
	// MaxSitemapFiles defines max sitemap links per index file
	MaxSitemapFiles = 50000
	// MaxSitemapLinks defines max links per sitemap
	MaxSitemapLinks = 50000
	// MaxSitemapImages defines max images per url
	MaxSitemapImages = 1000
	// MaxSitemapNews defines max news sitemap per index_file
	MaxSitemapNews = 1000
	// MaxSitemapFilesize defines file size for sitemap.
	MaxSitemapFilesize = 31457280 // bytes
)

const (
	// SchemaGeo exists for geo sitemap
	SchemaGeo = "http://www.google.com/geo/schemas/sitemap/1.0"
	// SchemaImage exists for image sitemap
	SchemaImage = "http://www.google.com/schemas/sitemap-image/1.1"
	// SchemaMobile exists for mobile sitemap
	SchemaMobile = "http://www.google.com/schemas/sitemap-mobile/1.0"
	// SchemaNews exists for news sitemap
	SchemaNews = "http://www.google.com/schemas/sitemap-news/0.9"
	// SchemaPagemap exists for pagemap sitemap
	SchemaPagemap = "http://www.google.com/schemas/sitemap-pagemap/1.0"
	// SchemaVideo exists for video sitemap
	SchemaVideo = "http://www.google.com/schemas/sitemap-video/1.1"
)

var (
	// IndexXMLHeader exists for create sitemap xml as a specific sitemap document.
	IndexXMLHeader = []byte(`<?xml version="1.0" encoding="UTF-8"?>
      <sitemapindex
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
        http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd"
      xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    >`)
	// IndexXMLFooter and IndexXMLHeader will used from user together .
	IndexXMLFooter = []byte("</sitemapindex>")
)

var (
	// XMLHeader exists for create sitemap xml as a specific sitemap document.
	XMLHeader = []byte(`<?xml version="1.0" encoding="UTF-8"?>
      <urlset
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
          http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
        xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:image="` + SchemaImage + `"
        xmlns:video="` + SchemaVideo + `"
        xmlns:geo="` + SchemaGeo + `"
        xmlns:news="` + SchemaNews + `"
        xmlns:mobile="` + SchemaMobile + `"
        xmlns:pagemap="` + SchemaPagemap + `"
        xmlns:xhtml="http://www.w3.org/1999/xhtml"
    >`)
	// XMLFooter and XMLHeader will used from user together .
	XMLFooter = []byte("</urlset>")
)
<commit_msg>closes #6<commit_after>package stm

const (
	// MaxSitemapFiles defines max sitemap links per index file
	MaxSitemapFiles = 50000
	// MaxSitemapLinks defines max links per sitemap
	MaxSitemapLinks = 50000
	// MaxSitemapImages defines max images per url
	MaxSitemapImages = 1000
	// MaxSitemapNews defines max news sitemap per index_file
	MaxSitemapNews = 1000
	// MaxSitemapFilesize defines file size for sitemap.
	MaxSitemapFilesize = 10000000 // bytes
)

const (
	// SchemaGeo exists for geo sitemap
	SchemaGeo = "http://www.google.com/geo/schemas/sitemap/1.0"
	// SchemaImage exists for image sitemap
	SchemaImage = "http://www.google.com/schemas/sitemap-image/1.1"
	// SchemaMobile exists for mobile sitemap
	SchemaMobile = "http://www.google.com/schemas/sitemap-mobile/1.0"
	// SchemaNews exists for news sitemap
	SchemaNews = "http://www.google.com/schemas/sitemap-news/0.9"
	// SchemaPagemap exists for pagemap sitemap
	SchemaPagemap = "http://www.google.com/schemas/sitemap-pagemap/1.0"
	// SchemaVideo exists for video sitemap
	SchemaVideo = "http://www.google.com/schemas/sitemap-video/1.1"
)

var (
	// IndexXMLHeader exists for create sitemap xml as a specific sitemap document.
	IndexXMLHeader = []byte(`<?xml version="1.0" encoding="UTF-8"?>
      <sitemapindex
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
        http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd"
      xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    >`)
	// IndexXMLFooter and IndexXMLHeader will used from user together .
	IndexXMLFooter = []byte("</sitemapindex>")
)

var (
	// XMLHeader exists for create sitemap xml as a specific sitemap document.
	XMLHeader = []byte(`<?xml version="1.0" encoding="UTF-8"?>
      <urlset
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
          http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
        xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:image="` + SchemaImage + `"
        xmlns:video="` + SchemaVideo + `"
        xmlns:geo="` + SchemaGeo + `"
        xmlns:news="` + SchemaNews + `"
        xmlns:mobile="` + SchemaMobile + `"
        xmlns:pagemap="` + SchemaPagemap + `"
        xmlns:xhtml="http://www.w3.org/1999/xhtml"
    >`)
	// XMLFooter and XMLHeader will used from user together .
	XMLFooter = []byte("</urlset>")
)
<|endoftext|>


<commit_before>package webhook

import (
	"cred-alert/git"
	"cred-alert/logging"
	"net/http"

	"github.com/google/go-github/github"
	"github.com/pivotal-golang/lager"

	gh "cred-alert/github"
)

//go:generate counterfeiter . Scanner

type Scanner interface {
	ScanPushEvent(lager.Logger, github.PushEvent)
}

type PushEventScanner struct {
	fetchDiff func(lager.Logger, github.PushEvent) (string, error)
	scan      func(lager.Logger, string) []git.Line
	emitter   logging.Emitter
}

func NewPushEventScanner(fetchDiff func(lager.Logger, github.PushEvent) (string, error), scan func(lager.Logger, string) []git.Line, emitter logging.Emitter) *PushEventScanner {
	return &PushEventScanner{
		fetchDiff: fetchDiff,
		scan:      scan,
		emitter:   emitter,
	}
}

func (s PushEventScanner) ScanPushEvent(logger lager.Logger, event github.PushEvent) {
	logger = logger.Session("scan-event")

	diff, err := s.fetchDiff(logger, event)
	if err != nil {
		return
	}

	lines := s.scan(logger, diff)

	for _, line := range lines {
		logger.Info("found-credential", lager.Data{
			"path":        line.Path,
			"line-number": line.LineNumber,
		})

		s.emitter.CountViolation(logger, len(lines))
	}
}

func FetchDiff(logger lager.Logger, event github.PushEvent) (string, error) {
	httpClient := &http.Client{}
	githubClient := gh.NewClient("https://api.github.com/", httpClient)

	return githubClient.CompareRefs(logger, *event.Repo.Owner.Name, *event.Repo.Name, *event.Before, *event.After)
}
<commit_msg>Fix CountViolation line length<commit_after>package webhook

import (
	"cred-alert/git"
	"cred-alert/logging"
	"net/http"

	"github.com/google/go-github/github"
	"github.com/pivotal-golang/lager"

	gh "cred-alert/github"
)

//go:generate counterfeiter . Scanner

type Scanner interface {
	ScanPushEvent(lager.Logger, github.PushEvent)
}

type PushEventScanner struct {
	fetchDiff func(lager.Logger, github.PushEvent) (string, error)
	scan      func(lager.Logger, string) []git.Line
	emitter   logging.Emitter
}

func NewPushEventScanner(fetchDiff func(lager.Logger, github.PushEvent) (string, error), scan func(lager.Logger, string) []git.Line, emitter logging.Emitter) *PushEventScanner {
	return &PushEventScanner{
		fetchDiff: fetchDiff,
		scan:      scan,
		emitter:   emitter,
	}
}

func (s PushEventScanner) ScanPushEvent(logger lager.Logger, event github.PushEvent) {
	logger = logger.Session("scan-event")

	diff, err := s.fetchDiff(logger, event)
	if err != nil {
		return
	}

	lines := s.scan(logger, diff)

	for _, line := range lines {
		logger.Info("found-credential", lager.Data{
			"path":        line.Path,
			"line-number": line.LineNumber,
		})

	}

	s.emitter.CountViolation(logger, len(lines))
}

func FetchDiff(logger lager.Logger, event github.PushEvent) (string, error) {
	httpClient := &http.Client{}
	githubClient := gh.NewClient("https://api.github.com/", httpClient)

	return githubClient.CompareRefs(logger, *event.Repo.Owner.Name, *event.Repo.Name, *event.Before, *event.After)
}
<|endoftext|>


<commit_before>package solve

import (
	"container/heap"
	"fmt"
	"strings"
	"sort"
)

type Algorithm int

const (
	Astar Algorithm = iota
	DepthFirst Algorithm = iota
	BreadthFirst Algorithm = iota
	IDAstar Algorithm = iota
)

func (a Algorithm) String() string {
	switch a {
	case Astar: return "A*"
	case IDAstar: return "IDA*"
	case BreadthFirst: return "BreadthFirst"
	case DepthFirst: return "DepthFirst"
	}
	return "<unknown>"
}

type strategy interface {
	Take() *node
	Add(node *node)
}

// A* strategy, based on a priority queue
type priorityQueue []*node

func (pq priorityQueue) Len() int {
	return len(pq)
}

func compare(a, b float64) int {
	if a < b {
		return -1
	}
	if a > b {
		return 1
	}
	return 0
}

func (pq priorityQueue) Less(i, j int) bool {
	diff := compare(pq[i].value, pq[j].value)
	if diff == 0 {
		diff = compare(pq[j].state.Cost(), pq[i].state.Cost())
	}
	return diff < 0
}

func (pq priorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}

func (pq *priorityQueue) Push(x interface{}) {
	item := x.(*node)
	*pq = append(*pq, item)
}

func (pq *priorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n - 1]
	*pq = old[0 : n - 1]
	return item
}

func (pq *priorityQueue) Take() *node {
	if len(*pq) == 0 {
		return nil
	}
	return heap.Pop(pq).(*node)
}

func (pq *priorityQueue) Add(node *node) {
	heap.Push(pq, node)
}

func (pq priorityQueue) String() string {
	copy := pq
	sort.Sort(copy)
	var ss []string
	for _, item := range copy {
		ss = append(ss, fmt.Sprintf("%v (%v)", item.state, item.value))
	}
	return strings.Join(ss, ", ")
}

// Depth-first strategy, based on a lifo queue
type lifo []*node

func (dfq *lifo) Take() *node {
	if len(*dfq) == 0 {
		return nil
	}
	old := *dfq
	n := len(old)
	item := old[n - 1]
	*dfq = old[0 : n - 1]
	return item
}

func (dfq *lifo) Add(node *node) {
	*dfq = append(*dfq, node)
}

// Inspired by github.com/phf/go-queue/queue, but we implement our own
// because we only need part of the functionality and can make a sligtly
// more efficient implementation without the need for an external dependency
type ringbuffer struct {
	buffer []*node
	start  int
	end    int
}

func inc(b *ringbuffer, i int) int {
	return (i + 1) & (len(b.buffer) - 1) // requires l = 2^n
}

func (b *ringbuffer) Take() *node {
	if b.start == b.end {
		return nil
	}
	item := b.buffer[b.start]
	b.start = inc(b, b.start)
	return item
}

func (b *ringbuffer) Add(node *node) {
	b.buffer[b.end] = node
	b.end = inc(b, b.end)
	if b.start == b.end {
		grow(b)
	}
}

func grow(b *ringbuffer) {
	oldsize := len(b.buffer)
	size := oldsize * 2
	adjusted := make([]*node, size)
	if b.start < b.end {
		// not "wrapped" around, one copy suffices
		copy(adjusted, b.buffer[b.start:b.end])
	} else {
		// "wrapped" around, need two copies
		n := copy(adjusted, b.buffer[b.start:])
		copy(adjusted[n:], b.buffer[:b.end])
	}
	b.buffer = adjusted
	b.start = 0
	b.end = oldsize
}

func aStar() strategy {
	pq := make(priorityQueue, 0, 64)
	heap.Init(&pq)
	return &pq
}

func depthFirst() strategy {
	queue := make(lifo, 0, 64)
	return &queue
}

func breadthFirst() strategy {
	var b ringbuffer
	b.buffer = make([]*node, 64)
	return &b
}
<commit_msg>Removed debugging code<commit_after>package solve

import (
	"container/heap"
	"fmt"
	"strings"
	"sort"
)

type Algorithm int

const (
	Astar Algorithm = iota
	DepthFirst Algorithm = iota
	BreadthFirst Algorithm = iota
	IDAstar Algorithm = iota
)

func (a Algorithm) String() string {
	switch a {
	case Astar: return "A*"
	case IDAstar: return "IDA*"
	case BreadthFirst: return "BreadthFirst"
	case DepthFirst: return "DepthFirst"
	}
	return "<unknown>"
}

type strategy interface {
	Take() *node
	Add(node *node)
}

// A* strategy, based on a priority queue
type priorityQueue []*node

func (pq priorityQueue) Len() int {
	return len(pq)
}

func compare(a, b float64) int {
	if a < b {
		return -1
	}
	if a > b {
		return 1
	}
	return 0
}

func (pq priorityQueue) Less(i, j int) bool {
	diff := compare(pq[i].value, pq[j].value)
	if diff == 0 {
		diff = compare(pq[j].state.Cost(), pq[i].state.Cost())
	}
	return diff < 0
}

func (pq priorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}

func (pq *priorityQueue) Push(x interface{}) {
	item := x.(*node)
	*pq = append(*pq, item)
}

func (pq *priorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n - 1]
	*pq = old[0 : n - 1]
	return item
}

func (pq *priorityQueue) Take() *node {
	if len(*pq) == 0 {
		return nil
	}
	return heap.Pop(pq).(*node)
}

func (pq *priorityQueue) Add(node *node) {
	heap.Push(pq, node)
}

// Depth-first strategy, based on a lifo queue
type lifo []*node

func (dfq *lifo) Take() *node {
	if len(*dfq) == 0 {
		return nil
	}
	old := *dfq
	n := len(old)
	item := old[n - 1]
	*dfq = old[0 : n - 1]
	return item
}

func (dfq *lifo) Add(node *node) {
	*dfq = append(*dfq, node)
}

// Inspired by github.com/phf/go-queue/queue, but we implement our own
// because we only need part of the functionality and can make a sligtly
// more efficient implementation without the need for an external dependency
type ringbuffer struct {
	buffer []*node
	start  int
	end    int
}

func inc(b *ringbuffer, i int) int {
	return (i + 1) & (len(b.buffer) - 1) // requires l = 2^n
}

func (b *ringbuffer) Take() *node {
	if b.start == b.end {
		return nil
	}
	item := b.buffer[b.start]
	b.start = inc(b, b.start)
	return item
}

func (b *ringbuffer) Add(node *node) {
	b.buffer[b.end] = node
	b.end = inc(b, b.end)
	if b.start == b.end {
		grow(b)
	}
}

func grow(b *ringbuffer) {
	oldsize := len(b.buffer)
	size := oldsize * 2
	adjusted := make([]*node, size)
	if b.start < b.end {
		// not "wrapped" around, one copy suffices
		copy(adjusted, b.buffer[b.start:b.end])
	} else {
		// "wrapped" around, need two copies
		n := copy(adjusted, b.buffer[b.start:])
		copy(adjusted[n:], b.buffer[:b.end])
	}
	b.buffer = adjusted
	b.start = 0
	b.end = oldsize
}

func aStar() strategy {
	pq := make(priorityQueue, 0, 64)
	heap.Init(&pq)
	return &pq
}

func depthFirst() strategy {
	queue := make(lifo, 0, 64)
	return &queue
}

func breadthFirst() strategy {
	var b ringbuffer
	b.buffer = make([]*node, 64)
	return &b
}
<|endoftext|>


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

package time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = int64(100e6)
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Nanoseconds()
	Sleep(delay)
	duration := Nanoseconds() - start
	if duration < delay {
		t.Fatalf("Sleep(%d) slept for only %d ns", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1e9)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
		}
	}()
	c := Tick(1)
	for i := 0; i < 100; i++ {
		<-c
	}
	atomic.StoreUint32(&stop, 1)
}

func BenchmarkAfterFunc(b *testing.B) {
	i := b.N
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func BenchmarkAfter(b *testing.B) {
	for i := 0; i < b.N; i++ {
		<-After(1)
	}
}

func BenchmarkStop(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewTimer(1e9).Stop()
	}
}

func TestAfter(t *testing.T) {
	const delay = int64(100e6)
	start := Nanoseconds()
	end := <-After(delay)
	if duration := Nanoseconds() - start; duration < delay {
		t.Fatalf("After(%d) slept for only %d ns", delay, duration)
	}
	if min := start + delay; end < min {
		t.Fatalf("After(%d) expect >= %d, got %d", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const (
		Delta = 100 * 1e6
		Count = 10
	)
	t0 := Nanoseconds()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Nanoseconds()
	ns := t1 - t0
	target := int64(Delta * Count)
	slop := target * 2 / 10
	if ns < target-slop || ns > target+slop {
		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
	}
}

func TestAfterStop(t *testing.T) {
	const msec = 1e6
	AfterFunc(100*msec, func() {})
	t0 := NewTimer(50 * msec)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*msec, func() { c1 <- true })
	c2 := After(200 * msec)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    int64
}

func await(slot int, result chan<- afterResult, ac <-chan int64) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	const (
		Delta = 100 * 1e6
	)
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Nanoseconds()
	for _, slot := range slots {
		go await(slot, result, After(int64(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after queue got slot %d, expected %d", r.slot, slot)
		}
		ns := r.t - t0
		target := int64(slot * Delta)
		slop := int64(Delta) / 4
		if ns < target-slop || ns > target+slop {
			return fmt.Errorf("after queue slot %d arrived at %g, expected [%g,%g]", slot, float64(ns), float64(target-slop), float64(target+slop))
		}
	}
	return nil
}
<commit_msg>time: fix test hang<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time_test

import (
	"errors"
	"fmt"
	"runtime"
	"sort"
	"sync/atomic"
	"testing"
	. "time"
)

func TestSleep(t *testing.T) {
	const delay = int64(100e6)
	go func() {
		Sleep(delay / 2)
		Interrupt()
	}()
	start := Nanoseconds()
	Sleep(delay)
	duration := Nanoseconds() - start
	if duration < delay {
		t.Fatalf("Sleep(%d) slept for only %d ns", delay, duration)
	}
}

// Test the basic function calling behavior. Correct queueing
// behavior is tested elsewhere, since After and AfterFunc share
// the same code.
func TestAfterFunc(t *testing.T) {
	i := 10
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
			Sleep(1e9)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func TestAfterStress(t *testing.T) {
	stop := uint32(0)
	go func() {
		for atomic.LoadUint32(&stop) == 0 {
			runtime.GC()
			// Need to yield, because otherwise
			// the main goroutine will never set the stop flag.
			runtime.Gosched()
		}
	}()
	c := Tick(1)
	for i := 0; i < 100; i++ {
		<-c
	}
	atomic.StoreUint32(&stop, 1)
}

func BenchmarkAfterFunc(b *testing.B) {
	i := b.N
	c := make(chan bool)
	var f func()
	f = func() {
		i--
		if i >= 0 {
			AfterFunc(0, f)
		} else {
			c <- true
		}
	}

	AfterFunc(0, f)
	<-c
}

func BenchmarkAfter(b *testing.B) {
	for i := 0; i < b.N; i++ {
		<-After(1)
	}
}

func BenchmarkStop(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewTimer(1e9).Stop()
	}
}

func TestAfter(t *testing.T) {
	const delay = int64(100e6)
	start := Nanoseconds()
	end := <-After(delay)
	if duration := Nanoseconds() - start; duration < delay {
		t.Fatalf("After(%d) slept for only %d ns", delay, duration)
	}
	if min := start + delay; end < min {
		t.Fatalf("After(%d) expect >= %d, got %d", delay, min, end)
	}
}

func TestAfterTick(t *testing.T) {
	const (
		Delta = 100 * 1e6
		Count = 10
	)
	t0 := Nanoseconds()
	for i := 0; i < Count; i++ {
		<-After(Delta)
	}
	t1 := Nanoseconds()
	ns := t1 - t0
	target := int64(Delta * Count)
	slop := target * 2 / 10
	if ns < target-slop || ns > target+slop {
		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
	}
}

func TestAfterStop(t *testing.T) {
	const msec = 1e6
	AfterFunc(100*msec, func() {})
	t0 := NewTimer(50 * msec)
	c1 := make(chan bool, 1)
	t1 := AfterFunc(150*msec, func() { c1 <- true })
	c2 := After(200 * msec)
	if !t0.Stop() {
		t.Fatalf("failed to stop event 0")
	}
	if !t1.Stop() {
		t.Fatalf("failed to stop event 1")
	}
	<-c2
	select {
	case <-t0.C:
		t.Fatalf("event 0 was not stopped")
	case <-c1:
		t.Fatalf("event 1 was not stopped")
	default:
	}
	if t1.Stop() {
		t.Fatalf("Stop returned true twice")
	}
}

func TestAfterQueuing(t *testing.T) {
	// This test flakes out on some systems,
	// so we'll try it a few times before declaring it a failure.
	const attempts = 3
	err := errors.New("!=nil")
	for i := 0; i < attempts && err != nil; i++ {
		if err = testAfterQueuing(t); err != nil {
			t.Logf("attempt %v failed: %v", i, err)
		}
	}
	if err != nil {
		t.Fatal(err)
	}
}

var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}

type afterResult struct {
	slot int
	t    int64
}

func await(slot int, result chan<- afterResult, ac <-chan int64) {
	result <- afterResult{slot, <-ac}
}

func testAfterQueuing(t *testing.T) error {
	const (
		Delta = 100 * 1e6
	)
	// make the result channel buffered because we don't want
	// to depend on channel queueing semantics that might
	// possibly change in the future.
	result := make(chan afterResult, len(slots))

	t0 := Nanoseconds()
	for _, slot := range slots {
		go await(slot, result, After(int64(slot)*Delta))
	}
	sort.Ints(slots)
	for _, slot := range slots {
		r := <-result
		if r.slot != slot {
			return fmt.Errorf("after queue got slot %d, expected %d", r.slot, slot)
		}
		ns := r.t - t0
		target := int64(slot * Delta)
		slop := int64(Delta) / 4
		if ns < target-slop || ns > target+slop {
			return fmt.Errorf("after queue slot %d arrived at %g, expected [%g,%g]", slot, float64(ns), float64(target-slop), float64(target+slop))
		}
	}
	return nil
}
<|endoftext|>