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

package release

import (
	"fmt"
	"os"
	"strings"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	"code.gitea.io/gitea/modules/process"
	"code.gitea.io/gitea/modules/timeutil"
)

func createTag(gitRepo *git.Repository, rel *models.Release) error {
	// Only actual create when publish.
	if !rel.IsDraft {
		if !gitRepo.IsTagExist(rel.TagName) {
			commit, err := gitRepo.GetCommit(rel.Target)
			if err != nil {
				return fmt.Errorf("GetCommit: %v", err)
			}

			// Trim '--' prefix to prevent command line argument vulnerability.
			rel.TagName = strings.TrimPrefix(rel.TagName, "--")
			if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
				if strings.Contains(err.Error(), "is not a valid tag name") {
					return models.ErrInvalidTagName{
						TagName: rel.TagName,
					}
				}
				return err
			}
			rel.LowerTagName = strings.ToLower(rel.TagName)
		}
		commit, err := gitRepo.GetTagCommit(rel.TagName)
		if err != nil {
			return fmt.Errorf("GetTagCommit: %v", err)
		}

		rel.Sha1 = commit.ID.String()
		rel.CreatedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
		rel.NumCommits, err = commit.CommitsCount()
		if err != nil {
			return fmt.Errorf("CommitsCount: %v", err)
		}
	} else {
		rel.CreatedUnix = timeutil.TimeStampNow()
	}
	return nil
}

// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error {
	isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName)
	if err != nil {
		return err
	} else if isExist {
		return models.ErrReleaseAlreadyExist{
			TagName: rel.TagName,
		}
	}

	if err = createTag(gitRepo, rel); err != nil {
		return err
	}

	rel.LowerTagName = strings.ToLower(rel.TagName)
	if err = models.InsertRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		return err
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return nil
}

// UpdateRelease updates information of a release.
func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) (err error) {
	if err = createTag(gitRepo, rel); err != nil {
		return err
	}
	rel.LowerTagName = strings.ToLower(rel.TagName)

	if err = models.UpdateRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		log.Error("AddReleaseAttachments: %v", err)
	}

	notification.NotifyUpdateRelease(doer, rel)

	return err
}

// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
	rel, err := models.GetReleaseByID(id)
	if err != nil {
		return fmt.Errorf("GetReleaseByID: %v", err)
	}

	repo, err := models.GetRepositoryByID(rel.RepoID)
	if err != nil {
		return fmt.Errorf("GetRepositoryByID: %v", err)
	}

	if delTag {
		_, stderr, err := process.GetManager().ExecDir(-1, repo.RepoPath(),
			fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
			git.GitExecutable, "tag", "-d", rel.TagName)
		if err != nil && !strings.Contains(stderr, "not found") {
			return fmt.Errorf("git tag -d: %v - %s", err, stderr)
		}

		if err := models.DeleteReleaseByID(id); err != nil {
			return fmt.Errorf("DeleteReleaseByID: %v", err)
		}
	} else {
		rel.IsTag = true
		rel.IsDraft = false
		rel.IsPrerelease = false
		rel.Title = ""
		rel.Note = ""

		if err = models.UpdateRelease(rel); err != nil {
			return fmt.Errorf("Update: %v", err)
		}
	}

	rel.Repo = repo
	if err = rel.LoadAttributes(); err != nil {
		return fmt.Errorf("LoadAttributes: %v", err)
	}

	if err := models.DeleteAttachmentsByRelease(rel.ID); err != nil {
		return fmt.Errorf("DeleteAttachments: %v", err)
	}

	for i := range rel.Attachments {
		attachment := rel.Attachments[i]
		if err := os.RemoveAll(attachment.LocalPath()); err != nil {
			log.Error("Delete attachment %s of release %s failed: %v", attachment.UUID, rel.ID, err)
		}
	}

	notification.NotifyDeleteRelease(doer, rel)

	return nil
}
<commit_msg>Send tag create and push webhook when release created on UI (#8671)<commit_after>// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package release

import (
	"fmt"
	"os"
	"strings"

	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	"code.gitea.io/gitea/modules/process"
	"code.gitea.io/gitea/modules/timeutil"
)

func createTag(gitRepo *git.Repository, rel *models.Release) error {
	// Only actual create when publish.
	if !rel.IsDraft {
		if !gitRepo.IsTagExist(rel.TagName) {
			commit, err := gitRepo.GetCommit(rel.Target)
			if err != nil {
				return fmt.Errorf("GetCommit: %v", err)
			}

			// Trim '--' prefix to prevent command line argument vulnerability.
			rel.TagName = strings.TrimPrefix(rel.TagName, "--")
			if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
				if strings.Contains(err.Error(), "is not a valid tag name") {
					return models.ErrInvalidTagName{
						TagName: rel.TagName,
					}
				}
				return err
			}
			rel.LowerTagName = strings.ToLower(rel.TagName)
			// Prepare Notify
			if err := rel.LoadAttributes(); err != nil {
				log.Error("LoadAttributes: %v", err)
				return err
			}
			notification.NotifyPushCommits(
				rel.Publisher, rel.Repo, git.TagPrefix+rel.TagName,
				git.EmptySHA, commit.ID.String(), models.NewPushCommits())
			notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName)
		}
		commit, err := gitRepo.GetTagCommit(rel.TagName)
		if err != nil {
			return fmt.Errorf("GetTagCommit: %v", err)
		}

		rel.Sha1 = commit.ID.String()
		rel.CreatedUnix = timeutil.TimeStamp(commit.Author.When.Unix())
		rel.NumCommits, err = commit.CommitsCount()
		if err != nil {
			return fmt.Errorf("CommitsCount: %v", err)
		}
	} else {
		rel.CreatedUnix = timeutil.TimeStampNow()
	}
	return nil
}

// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) error {
	isExist, err := models.IsReleaseExist(rel.RepoID, rel.TagName)
	if err != nil {
		return err
	} else if isExist {
		return models.ErrReleaseAlreadyExist{
			TagName: rel.TagName,
		}
	}

	if err = createTag(gitRepo, rel); err != nil {
		return err
	}

	rel.LowerTagName = strings.ToLower(rel.TagName)
	if err = models.InsertRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		return err
	}

	if !rel.IsDraft {
		notification.NotifyNewRelease(rel)
	}

	return nil
}

// UpdateRelease updates information of a release.
func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Release, attachmentUUIDs []string) (err error) {
	if err = createTag(gitRepo, rel); err != nil {
		return err
	}
	rel.LowerTagName = strings.ToLower(rel.TagName)

	if err = models.UpdateRelease(rel); err != nil {
		return err
	}

	if err = models.AddReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
		log.Error("AddReleaseAttachments: %v", err)
	}

	notification.NotifyUpdateRelease(doer, rel)

	return err
}

// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
	rel, err := models.GetReleaseByID(id)
	if err != nil {
		return fmt.Errorf("GetReleaseByID: %v", err)
	}

	repo, err := models.GetRepositoryByID(rel.RepoID)
	if err != nil {
		return fmt.Errorf("GetRepositoryByID: %v", err)
	}

	if delTag {
		_, stderr, err := process.GetManager().ExecDir(-1, repo.RepoPath(),
			fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
			git.GitExecutable, "tag", "-d", rel.TagName)
		if err != nil && !strings.Contains(stderr, "not found") {
			return fmt.Errorf("git tag -d: %v - %s", err, stderr)
		}

		if err := models.DeleteReleaseByID(id); err != nil {
			return fmt.Errorf("DeleteReleaseByID: %v", err)
		}
	} else {
		rel.IsTag = true
		rel.IsDraft = false
		rel.IsPrerelease = false
		rel.Title = ""
		rel.Note = ""

		if err = models.UpdateRelease(rel); err != nil {
			return fmt.Errorf("Update: %v", err)
		}
	}

	rel.Repo = repo
	if err = rel.LoadAttributes(); err != nil {
		return fmt.Errorf("LoadAttributes: %v", err)
	}

	if err := models.DeleteAttachmentsByRelease(rel.ID); err != nil {
		return fmt.Errorf("DeleteAttachments: %v", err)
	}

	for i := range rel.Attachments {
		attachment := rel.Attachments[i]
		if err := os.RemoveAll(attachment.LocalPath()); err != nil {
			log.Error("Delete attachment %s of release %s failed: %v", attachment.UUID, rel.ID, err)
		}
	}

	notification.NotifyDeleteRelease(doer, rel)

	return nil
}
<|endoftext|>


<commit_before>package fury

import (
	"math/rand"
	"net/http"
	"time"
)

const (
	CID_HEADER = "X-Request-CID"
)

func generateCID() string {
	alphabet := []rune("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ")
	alphabetLength := len(alphabet)

	cid := make([]rune, alphabetLength)

	for i := range cid {
		cid[i] = alphabet[rand.Intn(alphabetLength)]
	}
	return string(cid)
}

func RequestCIDMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(rw http.ResponseWriter, request *http.Request) {
		cid := generateCID()
		Logger().Debug(cid)
		request.Header.Set(CID_HEADER, cid)
		next(rw, request)
	}
}

func RequestStatsMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(rw http.ResponseWriter, request *http.Request) {
		url := request.URL
		path := url.Path
		qs := url.RawQuery

		Logger().Debug("---------***----------")
		Logger().Debug("REMOTE ADDR: %s", request.RemoteAddr)
		Logger().Debugf("URL: %s, Method: %s", url, request.Method)
		Logger().Debugf("PATH: %s", path)
		Logger().Debugf("QUERY: %s", qs)
		Logger().Debugf("User Agent: %s", request.UserAgent())
		Logger().Debug("---------***----------")

		next(rw, request)
	}
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<commit_msg>Formatting fix<commit_after>package fury

import (
	"math/rand"
	"net/http"
	"time"
)

const (
	CID_HEADER = "X-Request-CID"
)

func generateCID() string {
	alphabet := []rune("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ")
	alphabetLength := len(alphabet)

	cid := make([]rune, alphabetLength)

	for i := range cid {
		cid[i] = alphabet[rand.Intn(alphabetLength)]
	}
	return string(cid)
}

func RequestCIDMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(rw http.ResponseWriter, request *http.Request) {
		cid := generateCID()
		Logger().Debug(cid)
		request.Header.Set(CID_HEADER, cid)
		next(rw, request)
	}
}

func RequestStatsMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(rw http.ResponseWriter, request *http.Request) {
		url := request.URL
		path := url.Path
		qs := url.RawQuery

		Logger().Debug("---------***----------")
		Logger().Debugf("REMOTE ADDR: %s", request.RemoteAddr)
		Logger().Debugf("URL: %s, Method: %s", url, request.Method)
		Logger().Debugf("PATH: %s", path)
		Logger().Debugf("QUERY: %s", qs)
		Logger().Debugf("User Agent: %s", request.UserAgent())
		Logger().Debug("---------***----------")

		next(rw, request)
	}
}

func init() {
	rand.Seed(time.Now().UnixNano())
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/gtfierro/cs262-project/common"
	"github.com/tinylib/msgp/msgp"
	"io"
	"net"
	"time"
)

type Client struct {
	BrokerURL   string
	BrokerPort  int
	Query       string
	latencyChan chan int64
}

func (c *Client) subscribe() {
	conn, err := net.Dial("tcp", fmt.Sprintf("%v:%v", c.BrokerURL, c.BrokerPort))
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Fatalf("Error creating connection to %v:%v", c.BrokerURL, c.BrokerPort)
	}

	enc := msgp.NewWriter(conn)
	log.WithField("query", c.Query).Debug("Submitting query")
	qmsg := common.QueryMessage(c.Query)
	err = qmsg.Encode(enc)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Error marshalling query")
	}
	err = enc.Flush()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Error sending subscription query to broker")
	}

	dec := msgp.NewReader(conn)
	for {
		msg, err := common.MessageFromDecoderMsgp(dec)
		arrivalTime := time.Now().UnixNano()
		if err == io.EOF {
			return // connection is closed
		} else if err != nil {
			log.WithField("error", err).Fatal("Error while decoding message")
		}
		switch m := msg.(type) {
		case *common.PublishMessage:
			c.latencyChan <- arrivalTime - m.Value.(int64)
		case *common.SubscriptionDiffMessage:
			// Can safely ignore this
		}
	}
}
<commit_msg>update benchmark client<commit_after>package main

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/gtfierro/cs262-project/common"
	"github.com/tinylib/msgp/msgp"
	"io"
	"net"
	"time"
)

type Client struct {
	BrokerURL   string
	BrokerPort  int
	Query       string
	latencyChan chan int64
}

func (c *Client) subscribe() {
	conn, err := net.Dial("tcp", fmt.Sprintf("%v:%v", c.BrokerURL, c.BrokerPort))
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Fatalf("Error creating connection to %v:%v", c.BrokerURL, c.BrokerPort)
	}

	enc := msgp.NewWriter(conn)
	log.WithField("query", c.Query).Debug("Submitting query")
	qmsg := &common.QueryMessage{UUID: common.UUID("asdf"), Query: c.Query}
	err = qmsg.Encode(enc)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Error marshalling query")
	}
	err = enc.Flush()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Error sending subscription query to broker")
	}

	dec := msgp.NewReader(conn)
	for {
		msg, err := common.MessageFromDecoderMsgp(dec)
		arrivalTime := time.Now().UnixNano()
		if err == io.EOF {
			return // connection is closed
		} else if err != nil {
			log.WithField("error", err).Fatal("Error while decoding message")
		}
		switch m := msg.(type) {
		case *common.PublishMessage:
			c.latencyChan <- arrivalTime - m.Value.(int64)
		case *common.SubscriptionDiffMessage:
			// Can safely ignore this
		}
	}
}
<|endoftext|>


<commit_before>//+build windows

package file

import (
	"os"
	"syscall"
	"unsafe"

	"github.com/pkg/errors"
	"golang.org/x/sys/windows"
)

var (
	ntdll                        = windows.NewLazySystemDLL("ntdll.dll")
	ntQueryVolumeInformationFile = ntdll.NewProc("NtQueryVolumeInformationFile")
	ntSetInformationFile         = ntdll.NewProc("NtSetInformationFile")
)

type fileAllocationInformation struct {
	AllocationSize uint64
}

type fileFsSizeInformation struct {
	TotalAllocationUnits     uint64
	AvailableAllocationUnits uint64
	SectorsPerAllocationUnit uint32
	BytesPerSector           uint32
}

type ioStatusBlock struct {
	Status, Information uintptr
}

// PreallocateImplemented is a constant indicating whether the
// implementation of Preallocate actually does anything.
const PreallocateImplemented = true

// PreAllocate the file for performance reasons
func PreAllocate(size int64, out *os.File) error {
	if size <= 0 {
		return nil
	}

	var (
		iosb       ioStatusBlock
		fsSizeInfo fileFsSizeInformation
		allocInfo  fileAllocationInformation
	)

	// Query info about the block sizes on the file system
	_, _, e1 := ntQueryVolumeInformationFile.Call(
		uintptr(out.Fd()),
		uintptr(unsafe.Pointer(&iosb)),
		uintptr(unsafe.Pointer(&fsSizeInfo)),
		uintptr(unsafe.Sizeof(fsSizeInfo)),
		uintptr(3), // FileFsSizeInformation
	)
	if e1 != nil && e1 != syscall.Errno(0) {
		return errors.Wrap(e1, "preAllocate NtQueryVolumeInformationFile failed")
	}

	// Calculate the allocation size
	clusterSize := uint64(fsSizeInfo.BytesPerSector) * uint64(fsSizeInfo.SectorsPerAllocationUnit)
	if clusterSize <= 0 {
		return errors.Errorf("preAllocate clusterSize %d <= 0", clusterSize)
	}
	allocInfo.AllocationSize = (1 + uint64(size-1)/clusterSize) * clusterSize

	// Ask for the allocation
	_, _, e1 = ntSetInformationFile.Call(
		uintptr(out.Fd()),
		uintptr(unsafe.Pointer(&iosb)),
		uintptr(unsafe.Pointer(&allocInfo)),
		uintptr(unsafe.Sizeof(allocInfo)),
		uintptr(19), // FileAllocationInformation
	)
	if e1 != nil && e1 != syscall.Errno(0) {
		return errors.Wrap(e1, "preAllocate NtSetInformationFile failed")
	}

	return nil
}

const (
	FSCTL_SET_SPARSE = 0x000900c4
)

// SetSparseImplemented is a constant indicating whether the
// implementation of SetSparse actually does anything.
const SetSparseImplemented = true

// SetSparse makes the file be a sparse file
func SetSparse(out *os.File) error {
	err := syscall.DeviceIoControl(syscall.Handle(out.Fd()), FSCTL_SET_SPARSE, nil, 0, nil, 0, nil, nil)
	if err != nil {
		return errors.Wrap(err, "DeviceIoControl FSCTL_SET_SPARSE")
	}
	return nil
}
<commit_msg>lib/file: fix SetSparse on Windows 7 which fixes downloads of files > 250MB<commit_after>//+build windows

package file

import (
	"os"
	"syscall"
	"unsafe"

	"github.com/pkg/errors"
	"golang.org/x/sys/windows"
)

var (
	ntdll                        = windows.NewLazySystemDLL("ntdll.dll")
	ntQueryVolumeInformationFile = ntdll.NewProc("NtQueryVolumeInformationFile")
	ntSetInformationFile         = ntdll.NewProc("NtSetInformationFile")
)

type fileAllocationInformation struct {
	AllocationSize uint64
}

type fileFsSizeInformation struct {
	TotalAllocationUnits     uint64
	AvailableAllocationUnits uint64
	SectorsPerAllocationUnit uint32
	BytesPerSector           uint32
}

type ioStatusBlock struct {
	Status, Information uintptr
}

// PreallocateImplemented is a constant indicating whether the
// implementation of Preallocate actually does anything.
const PreallocateImplemented = true

// PreAllocate the file for performance reasons
func PreAllocate(size int64, out *os.File) error {
	if size <= 0 {
		return nil
	}

	var (
		iosb       ioStatusBlock
		fsSizeInfo fileFsSizeInformation
		allocInfo  fileAllocationInformation
	)

	// Query info about the block sizes on the file system
	_, _, e1 := ntQueryVolumeInformationFile.Call(
		uintptr(out.Fd()),
		uintptr(unsafe.Pointer(&iosb)),
		uintptr(unsafe.Pointer(&fsSizeInfo)),
		uintptr(unsafe.Sizeof(fsSizeInfo)),
		uintptr(3), // FileFsSizeInformation
	)
	if e1 != nil && e1 != syscall.Errno(0) {
		return errors.Wrap(e1, "preAllocate NtQueryVolumeInformationFile failed")
	}

	// Calculate the allocation size
	clusterSize := uint64(fsSizeInfo.BytesPerSector) * uint64(fsSizeInfo.SectorsPerAllocationUnit)
	if clusterSize <= 0 {
		return errors.Errorf("preAllocate clusterSize %d <= 0", clusterSize)
	}
	allocInfo.AllocationSize = (1 + uint64(size-1)/clusterSize) * clusterSize

	// Ask for the allocation
	_, _, e1 = ntSetInformationFile.Call(
		uintptr(out.Fd()),
		uintptr(unsafe.Pointer(&iosb)),
		uintptr(unsafe.Pointer(&allocInfo)),
		uintptr(unsafe.Sizeof(allocInfo)),
		uintptr(19), // FileAllocationInformation
	)
	if e1 != nil && e1 != syscall.Errno(0) {
		return errors.Wrap(e1, "preAllocate NtSetInformationFile failed")
	}

	return nil
}

const (
	FSCTL_SET_SPARSE = 0x000900c4
)

// SetSparseImplemented is a constant indicating whether the
// implementation of SetSparse actually does anything.
const SetSparseImplemented = true

// SetSparse makes the file be a sparse file
func SetSparse(out *os.File) error {
	var bytesReturned uint32
	err := syscall.DeviceIoControl(syscall.Handle(out.Fd()), FSCTL_SET_SPARSE, nil, 0, nil, 0, &bytesReturned, nil)
	if err != nil {
		return errors.Wrap(err, "DeviceIoControl FSCTL_SET_SPARSE")
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package syntax

// Token is the set of lexical tokens and reserved words.
type Token int

// The list of all possible tokens and reserved words.
const (
	illegalTok Token = iota
	_EOF
	_Lit
	_LitWord

	sglQuote // '
	dblQuote // "
	bckQuote // `

	And     // &
	AndExpr // &&
	OrExpr  // ||
	Or      // |
	pipeAll // |& - bash

	dollar       // $
	dollSglQuote // $' - bash
	dollDblQuote // $" - bash
	dollBrace    // ${
	dollBrack    // $[
	dollParen    // $(
	dollDblParen // $((
	leftBrack    // [
	leftParen    // (
	dblLeftParen // (( - bash

	rightBrace    // }
	rightBrack    // ]
	rightParen    // )
	dblRightParen // ))
	semicolon     // ;

	dblSemicolon // ;;
	semiFall     // ;& - bash
	dblSemiFall  // ;;& - bash

	Mul // *
	Not // !
	Inc // ++
	Dec // --
	Pow // **
	Eql // ==
	Neq // !=
	Leq // <=
	Geq // >=

	AddAssgn // +=
	SubAssgn // -=
	MulAssgn // *=
	QuoAssgn // /=
	RemAssgn // %=
	AndAssgn // &=
	OrAssgn  // |=
	XorAssgn // ^=
	ShlAssgn // <<=
	ShrAssgn // >>=

	Gtr      // >
	Shr      // >>
	Lss      // <
	rdrInOut // <>
	dplIn    // <&
	dplOut   // >&
	clbOut   // >|
	Shl      // <<
	dashHdoc // <<-
	wordHdoc // <<< - bash
	rdrAll   // &> - bash
	appAll   // &>> - bash

	cmdIn  // <( - bash
	cmdOut // >( - bash

	Add      // +
	ColAdd   // :+
	Sub      // -
	ColSub   // :-
	Quest    // ?
	ColQuest // :?
	Assgn    // =
	ColAssgn // :=
	Rem      // %
	dblRem   // %%
	Hash     // #
	dblHash  // ##
	Xor      // ^
	dblXor   // ^^ - bash
	Comma    // ,
	dblComma // ,, - bash
	Quo      // /
	dblQuo   // //
	Colon    // :

	tsNot     // !
	tsExists  // -e
	tsRegFile // -f
	tsDirect  // -d
	tsCharSp  // -c
	tsBlckSp  // -b
	tsNmPipe  // -p
	tsSocket  // -S
	tsSmbLink // -L
	tsGIDSet  // -g
	tsUIDSet  // -u
	tsRead    // -r
	tsWrite   // -w
	tsExec    // -x
	tsNoEmpty // -s
	tsFdTerm  // -t
	tsEmpStr  // -z
	tsNempStr // -n
	tsOptSet  // -o
	tsVarSet  // -v
	tsRefVar  // -R

	TsReMatch // =~
	TsNewer   // -nt
	TsOlder   // -ot
	TsDevIno  // -ef
	TsEql     // -eq
	TsNeq     // -ne
	TsLeq     // -le
	TsGeq     // -ge
	TsLss     // -lt
	TsGtr     // -gt

	globQuest // ?(
	globMul   // *(
	globAdd   // +(
	globAt    // @(
	globNot   // !(
)

type RedirOperator Token

const (
	RdrOut = RedirOperator(Gtr) + iota
	AppOut
	RdrIn
	RdrInOut
	DplIn
	DplOut
	ClbOut
	Hdoc
	DashHdoc
	WordHdoc
	RdrAll
	AppAll
)

func (o RedirOperator) String() string { return Token(o).String() }

type ProcOperator Token

const (
	CmdIn = ProcOperator(cmdIn) + iota
	CmdOut
)

func (o ProcOperator) String() string { return Token(o).String() }

type GlobOperator Token

const (
	GlobQuest = GlobOperator(globQuest) + iota
	GlobMul
	GlobAdd
	GlobAt
	GlobNot
)

func (o GlobOperator) String() string { return Token(o).String() }

type BinCmdOperator Token

const (
	AndStmt = BinCmdOperator(AndExpr) + iota
	OrStmt
	Pipe
	PipeAll
)

func (o BinCmdOperator) String() string { return Token(o).String() }

type CaseOperator Token

const (
	DblSemicolon = CaseOperator(dblSemicolon) + iota
	SemiFall
	DblSemiFall
)

func (o CaseOperator) String() string { return Token(o).String() }

type ParExpOperator Token

const (
	SubstAdd = ParExpOperator(Add) + iota
	SubstColAdd
	SubstSub
	SubstColSub
	SubstQuest
	SubstColQuest
	SubstAssgn
	SubstColAssgn
	RemSmallSuffix
	RemLargeSuffix
	RemSmallPrefix
	RemLargePrefix
	UpperFirst
	UpperAll
	LowerFirst
	LowerAll
)

func (o ParExpOperator) String() string { return Token(o).String() }

type UnTestOperator Token

const (
	TsNot = UnTestOperator(tsNot) + iota
	TsExists
	TsRegFile
	TsDirect
	TsCharSp
	TsBlckSp
	TsNmPipe
	TsSocket
	TsSmbLink
	TsGIDSet
	TsUIDSet
	TsRead
	TsWrite
	TsExec
	TsNoEmpty
	TsFdTerm
	TsEmpStr
	TsNempStr
	TsOptSet
	TsVarSet
	TsRefVar
)

func (o UnTestOperator) String() string { return Token(o).String() }

// Pos is the internal representation of a position within a source
// file.
type Pos int

var defaultPos Pos

const maxPos = Pos(^uint(0) >> 1)

// Position describes a position within a source file including the line
// and column location. A Position is valid if the line number is > 0.
type Position struct {
	Offset int // byte offset, starting at 0
	Line   int // line number, starting at 1
	Column int // column number, starting at 1 (in bytes)
}

var tokNames = map[Token]string{
	illegalTok: "illegal",
	_EOF:       "EOF",
	_Lit:       "Lit",
	_LitWord:   "LitWord",

	sglQuote: "'",
	dblQuote: `"`,
	bckQuote: "`",

	And:     "&",
	AndExpr: "&&",
	OrExpr:  "||",
	Or:      "|",
	pipeAll: "|&",

	dollar:       "$",
	dollSglQuote: "$'",
	dollDblQuote: `$"`,
	dollBrace:    "${",
	dollBrack:    "$[",
	dollParen:    "$(",
	dollDblParen: "$((",
	leftBrack:    "[",
	leftParen:    "(",
	dblLeftParen: "((",

	rightBrace:    "}",
	rightBrack:    "]",
	rightParen:    ")",
	dblRightParen: "))",
	semicolon:     ";",

	dblSemicolon: ";;",
	semiFall:     ";&",
	dblSemiFall:  ";;&",

	Gtr:      ">",
	Shr:      ">>",
	Lss:      "<",
	rdrInOut: "<>",
	dplIn:    "<&",
	dplOut:   ">&",
	clbOut:   ">|",
	Shl:      "<<",
	dashHdoc: "<<-",
	wordHdoc: "<<<",
	rdrAll:   "&>",
	appAll:   "&>>",

	cmdIn:  "<(",
	cmdOut: ">(",

	Add:      "+",
	ColAdd:   ":+",
	Sub:      "-",
	ColSub:   ":-",
	Quest:    "?",
	ColQuest: ":?",
	Assgn:    "=",
	ColAssgn: ":=",
	Rem:      "%",
	dblRem:   "%%",
	Hash:     "#",
	dblHash:  "##",
	Xor:      "^",
	dblXor:   "^^",
	Comma:    ",",
	dblComma: ",,",
	Quo:      "/",
	dblQuo:   "//",
	Colon:    ":",

	Mul: "*",
	Not: "!",
	Inc: "++",
	Dec: "--",
	Pow: "**",
	Eql: "==",
	Neq: "!=",
	Leq: "<=",
	Geq: ">=",

	AddAssgn: "+=",
	SubAssgn: "-=",
	MulAssgn: "*=",
	QuoAssgn: "/=",
	RemAssgn: "%=",
	AndAssgn: "&=",
	OrAssgn:  "|=",
	XorAssgn: "^=",
	ShlAssgn: "<<=",
	ShrAssgn: ">>=",

	tsNot:     "!",
	tsExists:  "-e",
	tsRegFile: "-f",
	tsDirect:  "-d",
	tsCharSp:  "-c",
	tsBlckSp:  "-b",
	tsNmPipe:  "-p",
	tsSocket:  "-S",
	tsSmbLink: "-L",
	tsGIDSet:  "-g",
	tsUIDSet:  "-u",
	tsRead:    "-r",
	tsWrite:   "-w",
	tsExec:    "-x",
	tsNoEmpty: "-s",
	tsFdTerm:  "-t",
	tsEmpStr:  "-z",
	tsNempStr: "-n",
	tsOptSet:  "-o",
	tsVarSet:  "-v",
	tsRefVar:  "-R",

	TsReMatch: "=~",
	TsNewer:   "-nt",
	TsOlder:   "-ot",
	TsDevIno:  "-ef",
	TsEql:     "-eq",
	TsNeq:     "-ne",
	TsLeq:     "-le",
	TsGeq:     "-ge",
	TsLss:     "-lt",
	TsGtr:     "-gt",

	globQuest: "?(",
	globMul:   "*(",
	globAdd:   "+(",
	globAt:    "@(",
	globNot:   "!(",
}

func (t Token) String() string { return tokNames[t] }
<commit_msg>syntax: group all token String methods<commit_after>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package syntax

// Token is the set of lexical tokens and reserved words.
type Token int

// The list of all possible tokens and reserved words.
const (
	illegalTok Token = iota
	_EOF
	_Lit
	_LitWord

	sglQuote // '
	dblQuote // "
	bckQuote // `

	And     // &
	AndExpr // &&
	OrExpr  // ||
	Or      // |
	pipeAll // |& - bash

	dollar       // $
	dollSglQuote // $' - bash
	dollDblQuote // $" - bash
	dollBrace    // ${
	dollBrack    // $[
	dollParen    // $(
	dollDblParen // $((
	leftBrack    // [
	leftParen    // (
	dblLeftParen // (( - bash

	rightBrace    // }
	rightBrack    // ]
	rightParen    // )
	dblRightParen // ))
	semicolon     // ;

	dblSemicolon // ;;
	semiFall     // ;& - bash
	dblSemiFall  // ;;& - bash

	Mul // *
	Not // !
	Inc // ++
	Dec // --
	Pow // **
	Eql // ==
	Neq // !=
	Leq // <=
	Geq // >=

	AddAssgn // +=
	SubAssgn // -=
	MulAssgn // *=
	QuoAssgn // /=
	RemAssgn // %=
	AndAssgn // &=
	OrAssgn  // |=
	XorAssgn // ^=
	ShlAssgn // <<=
	ShrAssgn // >>=

	Gtr      // >
	Shr      // >>
	Lss      // <
	rdrInOut // <>
	dplIn    // <&
	dplOut   // >&
	clbOut   // >|
	Shl      // <<
	dashHdoc // <<-
	wordHdoc // <<< - bash
	rdrAll   // &> - bash
	appAll   // &>> - bash

	cmdIn  // <( - bash
	cmdOut // >( - bash

	Add      // +
	ColAdd   // :+
	Sub      // -
	ColSub   // :-
	Quest    // ?
	ColQuest // :?
	Assgn    // =
	ColAssgn // :=
	Rem      // %
	dblRem   // %%
	Hash     // #
	dblHash  // ##
	Xor      // ^
	dblXor   // ^^ - bash
	Comma    // ,
	dblComma // ,, - bash
	Quo      // /
	dblQuo   // //
	Colon    // :

	tsNot     // !
	tsExists  // -e
	tsRegFile // -f
	tsDirect  // -d
	tsCharSp  // -c
	tsBlckSp  // -b
	tsNmPipe  // -p
	tsSocket  // -S
	tsSmbLink // -L
	tsGIDSet  // -g
	tsUIDSet  // -u
	tsRead    // -r
	tsWrite   // -w
	tsExec    // -x
	tsNoEmpty // -s
	tsFdTerm  // -t
	tsEmpStr  // -z
	tsNempStr // -n
	tsOptSet  // -o
	tsVarSet  // -v
	tsRefVar  // -R

	TsReMatch // =~
	TsNewer   // -nt
	TsOlder   // -ot
	TsDevIno  // -ef
	TsEql     // -eq
	TsNeq     // -ne
	TsLeq     // -le
	TsGeq     // -ge
	TsLss     // -lt
	TsGtr     // -gt

	globQuest // ?(
	globMul   // *(
	globAdd   // +(
	globAt    // @(
	globNot   // !(
)

type RedirOperator Token

const (
	RdrOut = RedirOperator(Gtr) + iota
	AppOut
	RdrIn
	RdrInOut
	DplIn
	DplOut
	ClbOut
	Hdoc
	DashHdoc
	WordHdoc
	RdrAll
	AppAll
)

type ProcOperator Token

const (
	CmdIn = ProcOperator(cmdIn) + iota
	CmdOut
)

type GlobOperator Token

const (
	GlobQuest = GlobOperator(globQuest) + iota
	GlobMul
	GlobAdd
	GlobAt
	GlobNot
)

type BinCmdOperator Token

const (
	AndStmt = BinCmdOperator(AndExpr) + iota
	OrStmt
	Pipe
	PipeAll
)

type CaseOperator Token

const (
	DblSemicolon = CaseOperator(dblSemicolon) + iota
	SemiFall
	DblSemiFall
)

type ParExpOperator Token

const (
	SubstAdd = ParExpOperator(Add) + iota
	SubstColAdd
	SubstSub
	SubstColSub
	SubstQuest
	SubstColQuest
	SubstAssgn
	SubstColAssgn
	RemSmallSuffix
	RemLargeSuffix
	RemSmallPrefix
	RemLargePrefix
	UpperFirst
	UpperAll
	LowerFirst
	LowerAll
)

type UnTestOperator Token

const (
	TsNot = UnTestOperator(tsNot) + iota
	TsExists
	TsRegFile
	TsDirect
	TsCharSp
	TsBlckSp
	TsNmPipe
	TsSocket
	TsSmbLink
	TsGIDSet
	TsUIDSet
	TsRead
	TsWrite
	TsExec
	TsNoEmpty
	TsFdTerm
	TsEmpStr
	TsNempStr
	TsOptSet
	TsVarSet
	TsRefVar
)

func (o RedirOperator) String() string  { return Token(o).String() }
func (o ProcOperator) String() string   { return Token(o).String() }
func (o GlobOperator) String() string   { return Token(o).String() }
func (o BinCmdOperator) String() string { return Token(o).String() }
func (o CaseOperator) String() string   { return Token(o).String() }
func (o ParExpOperator) String() string { return Token(o).String() }
func (o UnTestOperator) String() string { return Token(o).String() }

// Pos is the internal representation of a position within a source
// file.
type Pos int

var defaultPos Pos

const maxPos = Pos(^uint(0) >> 1)

// Position describes a position within a source file including the line
// and column location. A Position is valid if the line number is > 0.
type Position struct {
	Offset int // byte offset, starting at 0
	Line   int // line number, starting at 1
	Column int // column number, starting at 1 (in bytes)
}

var tokNames = map[Token]string{
	illegalTok: "illegal",
	_EOF:       "EOF",
	_Lit:       "Lit",
	_LitWord:   "LitWord",

	sglQuote: "'",
	dblQuote: `"`,
	bckQuote: "`",

	And:     "&",
	AndExpr: "&&",
	OrExpr:  "||",
	Or:      "|",
	pipeAll: "|&",

	dollar:       "$",
	dollSglQuote: "$'",
	dollDblQuote: `$"`,
	dollBrace:    "${",
	dollBrack:    "$[",
	dollParen:    "$(",
	dollDblParen: "$((",
	leftBrack:    "[",
	leftParen:    "(",
	dblLeftParen: "((",

	rightBrace:    "}",
	rightBrack:    "]",
	rightParen:    ")",
	dblRightParen: "))",
	semicolon:     ";",

	dblSemicolon: ";;",
	semiFall:     ";&",
	dblSemiFall:  ";;&",

	Gtr:      ">",
	Shr:      ">>",
	Lss:      "<",
	rdrInOut: "<>",
	dplIn:    "<&",
	dplOut:   ">&",
	clbOut:   ">|",
	Shl:      "<<",
	dashHdoc: "<<-",
	wordHdoc: "<<<",
	rdrAll:   "&>",
	appAll:   "&>>",

	cmdIn:  "<(",
	cmdOut: ">(",

	Add:      "+",
	ColAdd:   ":+",
	Sub:      "-",
	ColSub:   ":-",
	Quest:    "?",
	ColQuest: ":?",
	Assgn:    "=",
	ColAssgn: ":=",
	Rem:      "%",
	dblRem:   "%%",
	Hash:     "#",
	dblHash:  "##",
	Xor:      "^",
	dblXor:   "^^",
	Comma:    ",",
	dblComma: ",,",
	Quo:      "/",
	dblQuo:   "//",
	Colon:    ":",

	Mul: "*",
	Not: "!",
	Inc: "++",
	Dec: "--",
	Pow: "**",
	Eql: "==",
	Neq: "!=",
	Leq: "<=",
	Geq: ">=",

	AddAssgn: "+=",
	SubAssgn: "-=",
	MulAssgn: "*=",
	QuoAssgn: "/=",
	RemAssgn: "%=",
	AndAssgn: "&=",
	OrAssgn:  "|=",
	XorAssgn: "^=",
	ShlAssgn: "<<=",
	ShrAssgn: ">>=",

	tsNot:     "!",
	tsExists:  "-e",
	tsRegFile: "-f",
	tsDirect:  "-d",
	tsCharSp:  "-c",
	tsBlckSp:  "-b",
	tsNmPipe:  "-p",
	tsSocket:  "-S",
	tsSmbLink: "-L",
	tsGIDSet:  "-g",
	tsUIDSet:  "-u",
	tsRead:    "-r",
	tsWrite:   "-w",
	tsExec:    "-x",
	tsNoEmpty: "-s",
	tsFdTerm:  "-t",
	tsEmpStr:  "-z",
	tsNempStr: "-n",
	tsOptSet:  "-o",
	tsVarSet:  "-v",
	tsRefVar:  "-R",

	TsReMatch: "=~",
	TsNewer:   "-nt",
	TsOlder:   "-ot",
	TsDevIno:  "-ef",
	TsEql:     "-eq",
	TsNeq:     "-ne",
	TsLeq:     "-le",
	TsGeq:     "-ge",
	TsLss:     "-lt",
	TsGtr:     "-gt",

	globQuest: "?(",
	globMul:   "*(",
	globAdd:   "+(",
	globAt:    "@(",
	globNot:   "!(",
}

func (t Token) String() string { return tokNames[t] }
<|endoftext|>


<commit_before>// Copyright 2016 The etcd 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 e2e

import (
	"fmt"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/coreos/etcd/pkg/fileutil"
	"github.com/coreos/etcd/pkg/testutil"
)

// TestReleaseUpgrade ensures that changes to master branch does not affect
// upgrade from latest etcd releases.
func TestReleaseUpgrade(t *testing.T) {
	lastReleaseBinary := binDir + "/etcd-last-release"
	if !fileutil.Exist(lastReleaseBinary) {
		t.Skipf("%q does not exist", lastReleaseBinary)
	}

	defer testutil.AfterTest(t)

	copiedCfg := configNoTLS
	copiedCfg.execPath = lastReleaseBinary
	copiedCfg.snapCount = 3
	copiedCfg.baseScheme = "unix" // to avoid port conflict

	epc, err := newEtcdProcessCluster(&copiedCfg)
	if err != nil {
		t.Fatalf("could not start etcd process cluster (%v)", err)
	}
	defer func() {
		if errC := epc.Close(); errC != nil {
			t.Fatalf("error closing etcd processes (%v)", errC)
		}
	}()
	// 3.0 boots as 2.3 then negotiates up to 3.0
	// so there's a window at boot time where it doesn't have V3rpcCapability enabled
	// poll /version until etcdcluster is >2.3.x before making v3 requests
	for i := 0; i < 7; i++ {
		if err = cURLGet(epc, cURLReq{endpoint: "/version", expected: `"etcdcluster":"3.1`}); err != nil {
			t.Logf("#%d: v3 is not ready yet (%v)", i, err)
			time.Sleep(time.Second)
			continue
		}
		break
	}
	if err != nil {
		t.Fatalf("cannot pull version (%v)", err)
	}

	os.Setenv("ETCDCTL_API", "3")
	defer os.Unsetenv("ETCDCTL_API")
	cx := ctlCtx{
		t:           t,
		cfg:         configNoTLS,
		dialTimeout: 7 * time.Second,
		quorum:      true,
		epc:         epc,
	}
	var kvs []kv
	for i := 0; i < 5; i++ {
		kvs = append(kvs, kv{key: fmt.Sprintf("foo%d", i), val: "bar"})
	}
	for i := range kvs {
		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
			cx.t.Fatalf("#%d: ctlV3Put error (%v)", i, err)
		}
	}

	for i := range epc.procs {
		if err := epc.procs[i].Stop(); err != nil {
			t.Fatalf("#%d: error closing etcd process (%v)", i, err)
		}
		epc.procs[i].cfg.execPath = binDir + "/etcd"
		epc.procs[i].cfg.keepDataDir = true

		if err := epc.procs[i].Restart(); err != nil {
			t.Fatalf("error restarting etcd process (%v)", err)
		}

		for j := range kvs {
			if err := ctlV3Get(cx, []string{kvs[j].key}, []kv{kvs[j]}...); err != nil {
				cx.t.Fatalf("#%d-%d: ctlV3Get error (%v)", i, j, err)
			}
		}
	}
}

func TestReleaseUpgradeWithRestart(t *testing.T) {
	lastReleaseBinary := binDir + "/etcd-last-release"
	if !fileutil.Exist(lastReleaseBinary) {
		t.Skipf("%q does not exist", lastReleaseBinary)
	}

	defer testutil.AfterTest(t)

	copiedCfg := configNoTLS
	copiedCfg.execPath = lastReleaseBinary
	copiedCfg.snapCount = 10
	copiedCfg.baseScheme = "unix"

	epc, err := newEtcdProcessCluster(&copiedCfg)
	if err != nil {
		t.Fatalf("could not start etcd process cluster (%v)", err)
	}
	defer func() {
		if errC := epc.Close(); errC != nil {
			t.Fatalf("error closing etcd processes (%v)", errC)
		}
	}()

	os.Setenv("ETCDCTL_API", "3")
	defer os.Unsetenv("ETCDCTL_API")
	cx := ctlCtx{
		t:           t,
		cfg:         configNoTLS,
		dialTimeout: 7 * time.Second,
		quorum:      true,
		epc:         epc,
	}
	var kvs []kv
	for i := 0; i < 50; i++ {
		kvs = append(kvs, kv{key: fmt.Sprintf("foo%d", i), val: "bar"})
	}
	for i := range kvs {
		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
			cx.t.Fatalf("#%d: ctlV3Put error (%v)", i, err)
		}
	}

	for i := range epc.procs {
		if err := epc.procs[i].Stop(); err != nil {
			t.Fatalf("#%d: error closing etcd process (%v)", i, err)
		}
	}

	var wg sync.WaitGroup
	wg.Add(len(epc.procs))
	for i := range epc.procs {
		go func(i int) {
			epc.procs[i].cfg.execPath = binDir + "/etcd"
			epc.procs[i].cfg.keepDataDir = true
			if err := epc.procs[i].Restart(); err != nil {
				t.Fatalf("error restarting etcd process (%v)", err)
			}
			wg.Done()
		}(i)
	}
	wg.Wait()

	if err := ctlV3Get(cx, []string{kvs[0].key}, []kv{kvs[0]}...); err != nil {
		t.Fatal(err)
	}
}
<commit_msg>e2e: use version.Cluster for release test<commit_after>// Copyright 2016 The etcd 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 e2e

import (
	"fmt"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/coreos/etcd/pkg/fileutil"
	"github.com/coreos/etcd/pkg/testutil"
	"github.com/coreos/etcd/version"
)

// TestReleaseUpgrade ensures that changes to master branch does not affect
// upgrade from latest etcd releases.
func TestReleaseUpgrade(t *testing.T) {
	lastReleaseBinary := binDir + "/etcd-last-release"
	if !fileutil.Exist(lastReleaseBinary) {
		t.Skipf("%q does not exist", lastReleaseBinary)
	}

	defer testutil.AfterTest(t)

	copiedCfg := configNoTLS
	copiedCfg.execPath = lastReleaseBinary
	copiedCfg.snapCount = 3
	copiedCfg.baseScheme = "unix" // to avoid port conflict

	epc, err := newEtcdProcessCluster(&copiedCfg)
	if err != nil {
		t.Fatalf("could not start etcd process cluster (%v)", err)
	}
	defer func() {
		if errC := epc.Close(); errC != nil {
			t.Fatalf("error closing etcd processes (%v)", errC)
		}
	}()
	// 3.0 boots as 2.3 then negotiates up to 3.0
	// so there's a window at boot time where it doesn't have V3rpcCapability enabled
	// poll /version until etcdcluster is >2.3.x before making v3 requests
	for i := 0; i < 7; i++ {
		if err = cURLGet(epc, cURLReq{endpoint: "/version", expected: `"etcdcluster":"` + version.Cluster(version.Version)}); err != nil {
			t.Logf("#%d: v3 is not ready yet (%v)", i, err)
			time.Sleep(time.Second)
			continue
		}
		break
	}
	if err != nil {
		t.Fatalf("cannot pull version (%v)", err)
	}

	os.Setenv("ETCDCTL_API", "3")
	defer os.Unsetenv("ETCDCTL_API")
	cx := ctlCtx{
		t:           t,
		cfg:         configNoTLS,
		dialTimeout: 7 * time.Second,
		quorum:      true,
		epc:         epc,
	}
	var kvs []kv
	for i := 0; i < 5; i++ {
		kvs = append(kvs, kv{key: fmt.Sprintf("foo%d", i), val: "bar"})
	}
	for i := range kvs {
		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
			cx.t.Fatalf("#%d: ctlV3Put error (%v)", i, err)
		}
	}

	for i := range epc.procs {
		if err := epc.procs[i].Stop(); err != nil {
			t.Fatalf("#%d: error closing etcd process (%v)", i, err)
		}
		epc.procs[i].cfg.execPath = binDir + "/etcd"
		epc.procs[i].cfg.keepDataDir = true

		if err := epc.procs[i].Restart(); err != nil {
			t.Fatalf("error restarting etcd process (%v)", err)
		}

		for j := range kvs {
			if err := ctlV3Get(cx, []string{kvs[j].key}, []kv{kvs[j]}...); err != nil {
				cx.t.Fatalf("#%d-%d: ctlV3Get error (%v)", i, j, err)
			}
		}
	}
}

func TestReleaseUpgradeWithRestart(t *testing.T) {
	lastReleaseBinary := binDir + "/etcd-last-release"
	if !fileutil.Exist(lastReleaseBinary) {
		t.Skipf("%q does not exist", lastReleaseBinary)
	}

	defer testutil.AfterTest(t)

	copiedCfg := configNoTLS
	copiedCfg.execPath = lastReleaseBinary
	copiedCfg.snapCount = 10
	copiedCfg.baseScheme = "unix"

	epc, err := newEtcdProcessCluster(&copiedCfg)
	if err != nil {
		t.Fatalf("could not start etcd process cluster (%v)", err)
	}
	defer func() {
		if errC := epc.Close(); errC != nil {
			t.Fatalf("error closing etcd processes (%v)", errC)
		}
	}()

	os.Setenv("ETCDCTL_API", "3")
	defer os.Unsetenv("ETCDCTL_API")
	cx := ctlCtx{
		t:           t,
		cfg:         configNoTLS,
		dialTimeout: 7 * time.Second,
		quorum:      true,
		epc:         epc,
	}
	var kvs []kv
	for i := 0; i < 50; i++ {
		kvs = append(kvs, kv{key: fmt.Sprintf("foo%d", i), val: "bar"})
	}
	for i := range kvs {
		if err := ctlV3Put(cx, kvs[i].key, kvs[i].val, ""); err != nil {
			cx.t.Fatalf("#%d: ctlV3Put error (%v)", i, err)
		}
	}

	for i := range epc.procs {
		if err := epc.procs[i].Stop(); err != nil {
			t.Fatalf("#%d: error closing etcd process (%v)", i, err)
		}
	}

	var wg sync.WaitGroup
	wg.Add(len(epc.procs))
	for i := range epc.procs {
		go func(i int) {
			epc.procs[i].cfg.execPath = binDir + "/etcd"
			epc.procs[i].cfg.keepDataDir = true
			if err := epc.procs[i].Restart(); err != nil {
				t.Fatalf("error restarting etcd process (%v)", err)
			}
			wg.Done()
		}(i)
	}
	wg.Wait()

	if err := ctlV3Get(cx, []string{kvs[0].key}, []kv{kvs[0]}...); err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Hajime Hoshi
//
// 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 mobile

import (
	"errors"
	"runtime"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

var chError <-chan error

// Start starts the game and returns immediately.
//
// Different from ebiten.Run, this invokes only the game loop and not the main (UI) loop.
func Start(f func(*ebiten.Image) error, width, height, scale int, title string) {
	chError = ebiten.RunWithoutMainLoop(f, width, height, scale, title)
}

func SetScreenSize(width, height int) {
	ui.CurrentUI().SetScreenSize(width, height)
}

func SetScreenScale(scale int) {
	ui.CurrentUI().SetScreenScale(scale)
}

func Render() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if chError == nil {
		return errors.New("mobile: chError must not be nil: Start is not called yet?")
	}
	return ui.Render(chError)
}
<commit_msg>mobile: Add a build tag<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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.

// +build android

package mobile

import (
	"errors"
	"runtime"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

var chError <-chan error

// Start starts the game and returns immediately.
//
// Different from ebiten.Run, this invokes only the game loop and not the main (UI) loop.
func Start(f func(*ebiten.Image) error, width, height, scale int, title string) {
	chError = ebiten.RunWithoutMainLoop(f, width, height, scale, title)
}

func SetScreenSize(width, height int) {
	ui.CurrentUI().SetScreenSize(width, height)
}

func SetScreenScale(scale int) {
	ui.CurrentUI().SetScreenScale(scale)
}

func Render() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if chError == nil {
		return errors.New("mobile: chError must not be nil: Start is not called yet?")
	}
	return ui.Render(chError)
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Constantin Schomburg <me@cschomburg.com>
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package scheduler

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"time"

	"github.com/xconstruct/stark/proto"
	"github.com/xconstruct/stark/util"
)

type Task struct {
	Id         int64         `json:"-"`
	Duration   string        `json:"duration,omitempty"`
	Time       time.Time     `json:"time,omitempty"`
	Location   string        `json:"location,omitempty"`
	Reply      proto.Message `json:"reply,omitempty"`
	CreatedOn  time.Time     `json:"created,omitempty"`
	FinishedOn time.Time     `json:"finished,omitempty"`
}

func (t Task) String() string {
	return fmt.Sprintf("On %s schedule task '%s'.",
		util.FuzzyTime(t.Time),
		t.Reply,
	)
}

type Database interface {
	Setup() error
	StoreTask(t Task) error
	GetNextTask() (Task, error)
}

const schema = `
CREATE TABLE IF NOT EXISTS scheduler_tasks (
	id INT(10) NOT NULL AUTO_INCREMENT,
	time DATETIME NOT NULL,
	location VARCHAR(100) NOT NULL,
	reply TEXT,
	created_on TIMESTAMP NULL,
	finished_on TIMESTAMP NULL,
	PRIMARY KEY (id),
	KEY time (time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`

const schemaSqlite3 = `
CREATE TABLE IF NOT EXISTS scheduler_tasks (
	id INTEGER PRIMARY KEY,
	time DATETIME NOT NULL,
	location VARCHAR(100) NOT NULL,
	reply TEXT,
	created_on TIMESTAMP NULL,
	finished_on TIMESTAMP NULL
);
CREATE INDEX IF NOT EXISTS time ON scheduler_tasks (time);
`

type sqlDatabase struct {
	Driver string
	Db     *sql.DB
}

func (d *sqlDatabase) Setup() error {
	var err error
	if d.Driver == "sqlite3" {
		_, err = d.Db.Exec(schemaSqlite3)
	} else {
		_, err = d.Db.Exec(schema)
	}
	return err
}

func (d *sqlDatabase) StoreTask(t Task) error {
	reply, err := json.Marshal(t.Reply)
	if err != nil {
		return err
	}
	if t.CreatedOn.IsZero() {
		t.CreatedOn = time.Now()
	}

	if t.Id != 0 {
		stmt, err := d.Db.Prepare(`
			UPDATE scheduler_tasks
			SET time = ?, location = ?, reply = ?,
				created_on = ?, finished_on = ?
			WHERE id = ?`)
		if err != nil {
			return err
		}
		_, err = stmt.Exec(t.Time, t.Location, string(reply), t.CreatedOn, t.FinishedOn, t.Id)
	} else {
		stmt, err := d.Db.Prepare(`
			INSERT INTO scheduler_tasks
			(time, location, reply, created_on, finished_on)
			VALUES (?, ?, ?, ?, ?)`)
		if err != nil {
			return err
		}
		_, err = stmt.Exec(t.Time, t.Location, reply, t.CreatedOn, t.FinishedOn)
	}
	return err
}

func (d *sqlDatabase) GetNextTask() (Task, error) {
	row := d.Db.QueryRow(`
		SELECT id, time, location, reply, created_on, finished_on
		FROM scheduler_tasks
		WHERE finished_on < DATE('0001-01-02')
		ORDER BY time ASC
		LIMIT 1`)

	var t Task
	reply := ""
	if err := row.Scan(&t.Id, &t.Time, &t.Location, &reply, &t.CreatedOn, &t.FinishedOn); err != nil {
		return t, err
	}

	err := json.Unmarshal([]byte(reply), &t.Reply)
	return t, err
}
<commit_msg>Scheduler: Improved message text.<commit_after>// Copyright (C) 2014 Constantin Schomburg <me@cschomburg.com>
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package scheduler

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"time"

	"github.com/xconstruct/stark/proto"
	"github.com/xconstruct/stark/util"
)

type Task struct {
	Id         int64         `json:"-"`
	Duration   string        `json:"duration,omitempty"`
	Time       time.Time     `json:"time,omitempty"`
	Location   string        `json:"location,omitempty"`
	Reply      proto.Message `json:"reply,omitempty"`
	CreatedOn  time.Time     `json:"created,omitempty"`
	FinishedOn time.Time     `json:"finished,omitempty"`
}

func (t Task) String() string {
	text := t.Reply.PayloadGetString("text")
	if text == "" {
		text = t.Reply.Action
	}
	return fmt.Sprintf("Schedule task '%s' on %s.",
		text,
		util.FuzzyTime(t.Time),
	)
}

type Database interface {
	Setup() error
	StoreTask(t Task) error
	GetNextTask() (Task, error)
}

const schema = `
CREATE TABLE IF NOT EXISTS scheduler_tasks (
	id INT(10) NOT NULL AUTO_INCREMENT,
	time DATETIME NOT NULL,
	location VARCHAR(100) NOT NULL,
	reply TEXT,
	created_on TIMESTAMP NULL,
	finished_on TIMESTAMP NULL,
	PRIMARY KEY (id),
	KEY time (time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`

const schemaSqlite3 = `
CREATE TABLE IF NOT EXISTS scheduler_tasks (
	id INTEGER PRIMARY KEY,
	time DATETIME NOT NULL,
	location VARCHAR(100) NOT NULL,
	reply TEXT,
	created_on TIMESTAMP NULL,
	finished_on TIMESTAMP NULL
);
CREATE INDEX IF NOT EXISTS time ON scheduler_tasks (time);
`

type sqlDatabase struct {
	Driver string
	Db     *sql.DB
}

func (d *sqlDatabase) Setup() error {
	var err error
	if d.Driver == "sqlite3" {
		_, err = d.Db.Exec(schemaSqlite3)
	} else {
		_, err = d.Db.Exec(schema)
	}
	return err
}

func (d *sqlDatabase) StoreTask(t Task) error {
	reply, err := json.Marshal(t.Reply)
	if err != nil {
		return err
	}
	if t.CreatedOn.IsZero() {
		t.CreatedOn = time.Now()
	}

	if t.Id != 0 {
		stmt, err := d.Db.Prepare(`
			UPDATE scheduler_tasks
			SET time = ?, location = ?, reply = ?,
				created_on = ?, finished_on = ?
			WHERE id = ?`)
		if err != nil {
			return err
		}
		_, err = stmt.Exec(t.Time, t.Location, string(reply), t.CreatedOn, t.FinishedOn, t.Id)
	} else {
		stmt, err := d.Db.Prepare(`
			INSERT INTO scheduler_tasks
			(time, location, reply, created_on, finished_on)
			VALUES (?, ?, ?, ?, ?)`)
		if err != nil {
			return err
		}
		_, err = stmt.Exec(t.Time, t.Location, reply, t.CreatedOn, t.FinishedOn)
	}
	return err
}

func (d *sqlDatabase) GetNextTask() (Task, error) {
	row := d.Db.QueryRow(`
		SELECT id, time, location, reply, created_on, finished_on
		FROM scheduler_tasks
		WHERE finished_on < DATE('0001-01-02')
		ORDER BY time ASC
		LIMIT 1`)

	var t Task
	reply := ""
	if err := row.Scan(&t.Id, &t.Time, &t.Location, &reply, &t.CreatedOn, &t.FinishedOn); err != nil {
		return t, err
	}

	err := json.Unmarshal([]byte(reply), &t.Reply)
	return t, err
}
<|endoftext|>


<commit_before>package model

import (
	"crypto/sha256"
	"encoding/hex"
	"strconv"
	"time"
)

type Game struct {
	Id       string
	Black    string
	White    string
	Size     uint8
	Handicap uint8
	Turn     uint16
	Board    [19][19]uint8
	Captured [2]uint8
}

// Create a game using a hash of the game parameters as an ID
func NewGame(black string, white string, size uint8) *Game {
	time := time.Now().Unix()
	uniq := []byte(strconv.FormatInt(time, 10) + white + black)
	checksum := sha256.Sum224(uniq)
	trunc := checksum[:7]
	hexid := hex.EncodeToString(trunc)

	g := &Game{Id: hexid, White: white, Black: black, Size: size, Turn: 1}
	client.Cmd("HMSET", "game:"+hexid, "black", g.Black, "white", g.White, "size", g.Size, "turn", g.Turn)
	return g
}

// Loads a game for a provided id
func LoadGame(id string) (*Game, error) {
	resp, err := client.Cmd("HGETALL", "game:"+id).Map()
	if err != nil {
		return nil, err
	}
	size, _ := strconv.Atoi(resp["size"])
	turn, _ := strconv.Atoi(resp["turn"])
	g := &Game{Id: id, Black: resp["black"], White: resp["white"], Size: uint8(size), Turn: uint16(turn)}
	return g, nil
}

func (g *Game) Up() string {
	if g.Turn % 2 == 0 {
		return g.Black
	} else {
		return g.White
	}
}
<commit_msg>Include board size in hashed game data<commit_after>package model

import (
	"crypto/sha256"
	"encoding/hex"
	"strconv"
	"time"
)

type Game struct {
	Id       string
	Black    string
	White    string
	Size     uint8
	Handicap uint8
	Turn     uint16
	Board    [19][19]uint8
	Captured [2]uint8
}

// Create a game using a hash of the game parameters as an ID
func NewGame(black string, white string, size uint8) *Game {
	time := time.Now().Unix()
	uniq := []byte(strconv.FormatInt(time, 10) + white + black + strconv.Itoa(int(size)))
	checksum := sha256.Sum224(uniq)
	trunc := checksum[:7]
	hexid := hex.EncodeToString(trunc)

	g := &Game{Id: hexid, White: white, Black: black, Size: size, Turn: 1}
	client.Cmd("HMSET", "game:"+hexid, "black", g.Black, "white", g.White, "size", g.Size, "turn", g.Turn)
	return g
}

// Loads a game for a provided id
func LoadGame(id string) (*Game, error) {
	resp, err := client.Cmd("HGETALL", "game:"+id).Map()
	if err != nil {
		return nil, err
	}
	size, _ := strconv.Atoi(resp["size"])
	turn, _ := strconv.Atoi(resp["turn"])
	g := &Game{Id: id, Black: resp["black"], White: resp["white"], Size: uint8(size), Turn: uint16(turn)}
	return g, nil
}

func (g *Game) Up() string {
	if g.Turn % 2 == 0 {
		return g.Black
	} else {
		return g.White
	}
}
<|endoftext|>


<commit_before>package myconfig

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/coreos/etcd/clientv3"
)

const (
	dialTimeout    = 5 * time.Second
	requestTimeout = 1 * time.Second
)

// Config holds configuration data.
type Config struct {
	Endpoints []string
	Env       string
	Service   string
}

// Client is configuration client.
type Client struct {
	etcdClient    *clientv3.Client
	globalPrefix  string
	servicePrefix string
	data          *data
}

// New creates configuration client.
func New(cfg Config) (*Client, error) {

	ec, err := clientv3.New(clientv3.Config{
		Endpoints:   cfg.Endpoints,
		DialTimeout: dialTimeout,
	})

	if err != nil {
		return nil, err
	}

	c := &Client{
		etcdClient: ec,
		data:       newData(),
	}

	if err := c.initKeyPrefixes(cfg.Env, cfg.Service); err != nil {
		return nil, fmt.Errorf("prefixes: %v", err)
	}

	dm, err := c.get(c.globalPrefix)

	c.data.update(dm)
	return c, nil

}

const companyKey = "com"

func (c *Client) initKeyPrefixes(env, service string) error {
	if env == "" {
		return errors.New("empty env")
	}
	if service == "" {
		return errors.New("empty service")
	}
	root := fmt.Sprintf("/%s/%s", companyKey, env)
	c.globalPrefix = fmt.Sprintf("%s/global", root)
	c.servicePrefix = fmt.Sprintf("%s/%s", root, service)
	return nil
}

func (c *Client) get(prefix string) (dataMap, error) {

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	resp, err := c.etcdClient.Get(
		ctx,
		prefix,
		clientv3.WithPrefix(),
		clientv3.WithSerializable(),
	)

	defer cancel()

	dm := dataMap{}

	if err != nil {
		return dm, err
	}

	if len(resp.Kvs) < 1 {
		return dm, errors.New("not exists")
	}

	var k, v string

	for _, ev := range resp.Kvs {
		k = string(ev.Key)
		v = string(ev.Value)

		dm[k] = v
	}
	return dm, nil
}

// Close closes client.
func Close(c *Client) {

	err := c.etcdClient.Close()
	if err != nil {
		// TODO(dvrkps): add better logging
		log.Print(err)
	}
}
<commit_msg>etcdconfig/myconfig: rename setPrefixes<commit_after>package myconfig

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/coreos/etcd/clientv3"
)

const (
	dialTimeout    = 5 * time.Second
	requestTimeout = 1 * time.Second
)

// Config holds configuration data.
type Config struct {
	Endpoints []string
	Env       string
	Service   string
}

// Client is configuration client.
type Client struct {
	etcdClient    *clientv3.Client
	globalPrefix  string
	servicePrefix string
	data          *data
}

// New creates configuration client.
func New(cfg Config) (*Client, error) {

	ec, err := clientv3.New(clientv3.Config{
		Endpoints:   cfg.Endpoints,
		DialTimeout: dialTimeout,
	})

	if err != nil {
		return nil, err
	}

	c := &Client{
		etcdClient: ec,
		data:       newData(),
	}

	if err := c.setPrefixes(cfg.Env, cfg.Service); err != nil {
		return nil, fmt.Errorf("prefixes: %v", err)
	}

	dm, err := c.get(c.globalPrefix)

	c.data.update(dm)
	return c, nil

}

const companyKey = "com"

func (c *Client) setPrefixes(env, service string) error {
	if env == "" {
		return errors.New("empty env")
	}
	if service == "" {
		return errors.New("empty service")
	}
	root := fmt.Sprintf("/%s/%s", companyKey, env)
	c.globalPrefix = fmt.Sprintf("%s/global", root)
	c.servicePrefix = fmt.Sprintf("%s/%s", root, service)
	return nil
}

func (c *Client) get(prefix string) (dataMap, error) {

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	resp, err := c.etcdClient.Get(
		ctx,
		prefix,
		clientv3.WithPrefix(),
		clientv3.WithSerializable(),
	)

	defer cancel()

	dm := dataMap{}

	if err != nil {
		return dm, err
	}

	if len(resp.Kvs) < 1 {
		return dm, errors.New("not exists")
	}

	var k, v string

	for _, ev := range resp.Kvs {
		k = string(ev.Key)
		v = string(ev.Value)

		dm[k] = v
	}
	return dm, nil
}

// Close closes client.
func Close(c *Client) {

	err := c.etcdClient.Close()
	if err != nil {
		// TODO(dvrkps): add better logging
		log.Print(err)
	}
}
<|endoftext|>


<commit_before>// Compute missing pieces for a torrent.
package taipei

import (
	"crypto/sha1"
	"errors"
	"runtime"
)

func checkPieces(fs FileStore, totalLength int64, m *MetaInfo) (good, bad int64, goodBits *Bitset, err error) {
	pieceLength := m.Info.PieceLength
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	goodBits = NewBitset(int(numPieces))
	ref := m.Info.Pieces
	if len(ref) != int(numPieces*sha1.Size) {
		err = errors.New("Incorrect Info.Pieces length")
		return
	}
	currentSums, err := computeSums(fs, totalLength, m.Info.PieceLength)
	if err != nil {
		return
	}
	for i := int64(0); i < numPieces; i++ {
		base := i * sha1.Size
		end := base + sha1.Size
		if checkEqual(ref[base:end], currentSums[base:end]) {
			good++
			goodBits.Set(int(i))
		} else {
			bad++
		}
	}
	return
}

func checkEqual(ref string, current []byte) bool {
	for i := 0; i < len(current); i++ {
		if ref[i] != current[i] {
			return false
		}
	}
	return true
}

type chunk struct {
	i    int64
	data []byte
}

// computeSums reads the file content and computes the SHA1 hash for each
// piece. Spawns parallel goroutines to compute the hashes, since each
// computation takes ~30ms.
func computeSums(fs FileStore, totalLength int64, pieceLength int64) (sums []byte, err error) {
	// Calculate the SHA1 hash for each piece in parallel goroutines.
	hashes := make(chan chunk)
	results := make(chan chunk, 3)
	for i := int64(0); i < int64(runtime.GOMAXPROCS(0)); i++ {
		go hashPiece(hashes, results)
	}

	// Read file content and send to "pieces", keeping order.
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	go func() {
		for i := int64(0); i < numPieces; i++ {
			piece := make([]byte, pieceLength, pieceLength)
			if i == numPieces-1 {
				piece = piece[0 : totalLength-i*pieceLength]
			}
			// Ignore errors.
			fs.ReadAt(piece, i*pieceLength)
			hashes <- chunk{i: i, data: piece}
		}
		close(hashes)
	}()

	// Merge back the results.
	sums = make([]byte, sha1.Size*numPieces)
	for i := int64(0); i < numPieces; i++ {
		h := <-results
		copy(sums[h.i*sha1.Size:], h.data)
	}
	return
}

func hashPiece(h chan chunk, result chan chunk) {
	hasher := sha1.New()
	for piece := range h {
		hasher.Reset()
		_, err := hasher.Write(piece.data)
		if err != nil {
			result <- chunk{piece.i, nil}
		} else {
			result <- chunk{piece.i, hasher.Sum(nil)}
		}
	}
}

func checkPiece(fs FileStore, totalLength int64, m *MetaInfo, pieceIndex int) (good bool, err error) {
	ref := m.Info.Pieces
	currentSum, err := computePieceSum(fs, totalLength, m.Info.PieceLength, pieceIndex)
	if err != nil {
		return
	}
	base := pieceIndex * sha1.Size
	end := base + sha1.Size
	good = checkEqual(ref[base:end], currentSum)
	return
}

func computePieceSum(fs FileStore, totalLength int64, pieceLength int64, pieceIndex int) (sum []byte, err error) {
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	hasher := sha1.New()
	piece := make([]byte, pieceLength)
	if int64(pieceIndex) == numPieces-1 {
		piece = piece[0 : totalLength-int64(pieceIndex)*pieceLength]
	}
	_, err = fs.ReadAt(piece, int64(pieceIndex)*pieceLength)
	if err != nil {
		return
	}
	_, err = hasher.Write(piece)
	if err != nil {
		return
	}
	sum = hasher.Sum(nil)
	return
}
<commit_msg>Remove unnecessary type conversion. Props to coredump.<commit_after>// Compute missing pieces for a torrent.
package taipei

import (
	"crypto/sha1"
	"errors"
	"runtime"
)

func checkPieces(fs FileStore, totalLength int64, m *MetaInfo) (good, bad int64, goodBits *Bitset, err error) {
	pieceLength := m.Info.PieceLength
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	goodBits = NewBitset(int(numPieces))
	ref := m.Info.Pieces
	if len(ref) != int(numPieces*sha1.Size) {
		err = errors.New("Incorrect Info.Pieces length")
		return
	}
	currentSums, err := computeSums(fs, totalLength, m.Info.PieceLength)
	if err != nil {
		return
	}
	for i := int64(0); i < numPieces; i++ {
		base := i * sha1.Size
		end := base + sha1.Size
		if checkEqual(ref[base:end], currentSums[base:end]) {
			good++
			goodBits.Set(int(i))
		} else {
			bad++
		}
	}
	return
}

func checkEqual(ref string, current []byte) bool {
	for i := 0; i < len(current); i++ {
		if ref[i] != current[i] {
			return false
		}
	}
	return true
}

type chunk struct {
	i    int64
	data []byte
}

// computeSums reads the file content and computes the SHA1 hash for each
// piece. Spawns parallel goroutines to compute the hashes, since each
// computation takes ~30ms.
func computeSums(fs FileStore, totalLength int64, pieceLength int64) (sums []byte, err error) {
	// Calculate the SHA1 hash for each piece in parallel goroutines.
	hashes := make(chan chunk)
	results := make(chan chunk, 3)
	for i := 0; i < runtime.GOMAXPROCS(0); i++ {
		go hashPiece(hashes, results)
	}

	// Read file content and send to "pieces", keeping order.
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	go func() {
		for i := int64(0); i < numPieces; i++ {
			piece := make([]byte, pieceLength, pieceLength)
			if i == numPieces-1 {
				piece = piece[0 : totalLength-i*pieceLength]
			}
			// Ignore errors.
			fs.ReadAt(piece, i*pieceLength)
			hashes <- chunk{i: i, data: piece}
		}
		close(hashes)
	}()

	// Merge back the results.
	sums = make([]byte, sha1.Size*numPieces)
	for i := int64(0); i < numPieces; i++ {
		h := <-results
		copy(sums[h.i*sha1.Size:], h.data)
	}
	return
}

func hashPiece(h chan chunk, result chan chunk) {
	hasher := sha1.New()
	for piece := range h {
		hasher.Reset()
		_, err := hasher.Write(piece.data)
		if err != nil {
			result <- chunk{piece.i, nil}
		} else {
			result <- chunk{piece.i, hasher.Sum(nil)}
		}
	}
}

func checkPiece(fs FileStore, totalLength int64, m *MetaInfo, pieceIndex int) (good bool, err error) {
	ref := m.Info.Pieces
	currentSum, err := computePieceSum(fs, totalLength, m.Info.PieceLength, pieceIndex)
	if err != nil {
		return
	}
	base := pieceIndex * sha1.Size
	end := base + sha1.Size
	good = checkEqual(ref[base:end], currentSum)
	return
}

func computePieceSum(fs FileStore, totalLength int64, pieceLength int64, pieceIndex int) (sum []byte, err error) {
	numPieces := (totalLength + pieceLength - 1) / pieceLength
	hasher := sha1.New()
	piece := make([]byte, pieceLength)
	if int64(pieceIndex) == numPieces-1 {
		piece = piece[0 : totalLength-int64(pieceIndex)*pieceLength]
	}
	_, err = fs.ReadAt(piece, int64(pieceIndex)*pieceLength)
	if err != nil {
		return
	}
	_, err = hasher.Write(piece)
	if err != nil {
		return
	}
	sum = hasher.Sum(nil)
	return
}
<|endoftext|>


<commit_before>package ciutil

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"sync"
)

var (
	// Set Travis CI addrs by default though UpdateTravisCIIPAddrs will update it
	// with latest one.
	// $ dig +short nat.travisci.net | sort
	// # Updated on 2018-06-03.
	muTravisIPAddrs sync.RWMutex
	travisIPAddrs   = map[string]bool{
		"104.154.113.151": true,
		"104.154.120.187": true,
		"104.197.236.150": true,
		"146.148.51.141":  true,
		"146.148.58.237":  true,
		"147.75.192.163":  true,
		"207.254.16.35":   true,
		"207.254.16.36":   true,
		"207.254.16.37":   true,
		"207.254.16.38":   true,
		"207.254.16.39":   true,
		"34.233.56.198":   true,
		"34.234.4.53":     true,
		"35.184.226.236":  true,
		"35.184.48.144":   true,
		"35.184.96.71":    true,
		"35.188.184.134":  true,
		"35.188.1.99":     true,
		"35.188.73.34":    true,
		"35.192.136.167":  true,
		"35.192.187.174":  true,
		"35.192.19.50":    true,
		"35.192.217.12":   true,
		"35.192.85.2":     true,
		"35.193.203.142":  true,
		"35.193.211.2":    true,
		"35.193.7.13":     true,
		"35.202.145.110":  true,
		"35.202.68.136":   true,
		"35.202.78.106":   true,
		"35.224.112.202":  true,
		"35.226.126.204":  true,
		"52.3.55.28":      true,
		"52.45.185.117":   true,
		"52.45.220.64":    true,
		"52.54.31.11":     true,
		"52.54.40.118":    true,
		"54.208.31.17":    true,
	}

	// https://www.appveyor.com/docs/build-environment/#ip-addresses
	appveyorIPAddrs = map[string]bool{
		"74.205.54.20":    true,
		"104.197.110.30":  true,
		"104.197.145.181": true,
		"146.148.85.29":   true,
		"67.225.139.254":  true,
		"67.225.138.82":   true,
		"67.225.139.144":  true,
		"138.91.141.243":  true,
	}
)

// IsFromCI returns true if given request is from tructed CI provider.
func IsFromCI(r *http.Request) bool {
	return IsFromTravisCI(r) || IsFromAppveyor(r)
}

// IsFromTravisCI returns true if given request is from Travis CI.
// https://docs.travis-ci.com/user/ip-addresses/
func IsFromTravisCI(r *http.Request) bool {
	muTravisIPAddrs.RLock()
	defer muTravisIPAddrs.RUnlock()
	return travisIPAddrs[ipFromReq(r)]
}

// https://docs.travis-ci.com/user/ip-addresses/
func UpdateTravisCIIPAddrs(cli *http.Client) error {
	ips, err := ipAddrs("nat.travisci.net", cli)
	if err != nil {
		return err
	}
	muTravisIPAddrs.Lock()
	defer muTravisIPAddrs.Unlock()
	travisIPAddrs = map[string]bool{}
	for _, ip := range ips {
		travisIPAddrs[ip] = true
	}
	return nil
}

// IsFromAppveyor returns true if given request is from Appveyor.
// https://www.appveyor.com/docs/build-environment/#ip-addresses
func IsFromAppveyor(r *http.Request) bool {
	return appveyorIPAddrs[ipFromReq(r)]
}

func ipFromReq(r *http.Request) string {
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return r.RemoteAddr
	}
	return ip
}

// Cannot use "github.com/miekg/dns" in Google App Engine.
// Use dnsjson.com instead as workaround.
func ipAddrs(target string, cli *http.Client) ([]string, error) {
	url := fmt.Sprintf("https://dnsjson.com/%s/A.json", target)
	c := http.DefaultClient
	if cli != nil {
		c = cli
	}
	r, err := c.Get(url)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()

	var res struct {
		Results struct {
			Records []string `json:"records"`
		} `json:"results"`
	}

	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}

	if len(res.Results.Records) == 0 {
		return nil, fmt.Errorf("failed to get IP addresses of %s", target)
	}

	return res.Results.Records, nil
}
<commit_msg>doghouse: Use "Forwarded" header<commit_after>package ciutil

import (
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"strings"
	"sync"
)

var (
	// Set Travis CI addrs by default though UpdateTravisCIIPAddrs will update it
	// with latest one.
	// $ dig +short nat.travisci.net | sort
	// # Updated on 2018-06-03.
	muTravisIPAddrs sync.RWMutex
	travisIPAddrs   = map[string]bool{
		"104.154.113.151": true,
		"104.154.120.187": true,
		"104.197.236.150": true,
		"146.148.51.141":  true,
		"146.148.58.237":  true,
		"147.75.192.163":  true,
		"207.254.16.35":   true,
		"207.254.16.36":   true,
		"207.254.16.37":   true,
		"207.254.16.38":   true,
		"207.254.16.39":   true,
		"34.233.56.198":   true,
		"34.234.4.53":     true,
		"35.184.226.236":  true,
		"35.184.48.144":   true,
		"35.184.96.71":    true,
		"35.188.184.134":  true,
		"35.188.1.99":     true,
		"35.188.73.34":    true,
		"35.192.136.167":  true,
		"35.192.187.174":  true,
		"35.192.19.50":    true,
		"35.192.217.12":   true,
		"35.192.85.2":     true,
		"35.193.203.142":  true,
		"35.193.211.2":    true,
		"35.193.7.13":     true,
		"35.202.145.110":  true,
		"35.202.68.136":   true,
		"35.202.78.106":   true,
		"35.224.112.202":  true,
		"35.226.126.204":  true,
		"52.3.55.28":      true,
		"52.45.185.117":   true,
		"52.45.220.64":    true,
		"52.54.31.11":     true,
		"52.54.40.118":    true,
		"54.208.31.17":    true,
	}

	// https://www.appveyor.com/docs/build-environment/#ip-addresses
	appveyorIPAddrs = map[string]bool{
		"74.205.54.20":    true,
		"104.197.110.30":  true,
		"104.197.145.181": true,
		"146.148.85.29":   true,
		"67.225.139.254":  true,
		"67.225.138.82":   true,
		"67.225.139.144":  true,
		"138.91.141.243":  true,
	}
)

// IsFromCI returns true if given request is from tructed CI provider.
func IsFromCI(r *http.Request) bool {
	return IsFromTravisCI(r) || IsFromAppveyor(r)
}

// IsFromTravisCI returns true if given request is from Travis CI.
// https://docs.travis-ci.com/user/ip-addresses/
func IsFromTravisCI(r *http.Request) bool {
	muTravisIPAddrs.RLock()
	defer muTravisIPAddrs.RUnlock()
	return travisIPAddrs[ipFromReq(r)]
}

// https://docs.travis-ci.com/user/ip-addresses/
func UpdateTravisCIIPAddrs(cli *http.Client) error {
	ips, err := ipAddrs("nat.travisci.net", cli)
	if err != nil {
		return err
	}
	muTravisIPAddrs.Lock()
	defer muTravisIPAddrs.Unlock()
	travisIPAddrs = map[string]bool{}
	for _, ip := range ips {
		travisIPAddrs[ip] = true
	}
	return nil
}

// IsFromAppveyor returns true if given request is from Appveyor.
// https://www.appveyor.com/docs/build-environment/#ip-addresses
func IsFromAppveyor(r *http.Request) bool {
	return appveyorIPAddrs[ipFromReq(r)]
}

func ipFromReq(r *http.Request) string {
	if f := r.Header.Get("Forwarded"); f != "" {
		for _, kv := range strings.Split(f, ";") {
			if kvPair := strings.SplitN(kv, "=", 2); len(kvPair) == 2 &&
				strings.ToLower(strings.TrimSpace(kvPair[0])) == "for" {
				return strings.Trim(kvPair[1], ` "`)
			}
		}
	}

	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return r.RemoteAddr
	}
	return ip
}

// Cannot use "github.com/miekg/dns" in Google App Engine.
// Use dnsjson.com instead as workaround.
func ipAddrs(target string, cli *http.Client) ([]string, error) {
	url := fmt.Sprintf("https://dnsjson.com/%s/A.json", target)
	c := http.DefaultClient
	if cli != nil {
		c = cli
	}
	r, err := c.Get(url)
	if err != nil {
		return nil, err
	}
	defer r.Body.Close()

	var res struct {
		Results struct {
			Records []string `json:"records"`
		} `json:"results"`
	}

	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}

	if len(res.Results.Records) == 0 {
		return nil, fmt.Errorf("failed to get IP addresses of %s", target)
	}

	return res.Results.Records, nil
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

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

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

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

package mo

import (
	"fmt"
	"reflect"
	"regexp"

	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
)

var arrayOfRegexp = regexp.MustCompile("ArrayOf(.*)$")

func anyTypeToValue(t interface{}) reflect.Value {
	rt := reflect.TypeOf(t)
	rv := reflect.ValueOf(t)

	// Dereference if ArrayOfXYZ type
	m := arrayOfRegexp.FindStringSubmatch(rt.Name())
	if len(m) > 0 {
		// ArrayOfXYZ type has single field named XYZ
		rv = rv.FieldByName(m[1])
		if !rv.IsValid() {
			panic(fmt.Sprintf("expected %s type to have field %s", m[0], m[1]))
		}
	}

	return rv
}

func buildValueMap(v reflect.Value, m map[string]reflect.Value) {
	t := v.Type().Elem()
	for i := 0; i < t.NumField(); i++ {
		sft := t.Field(i)
		if sft.Anonymous {
			// Recurse into embedded field
			buildValueMap(v.Elem().Field(i).Addr(), m)
			continue
		}

		tag := sft.Tag.Get("mo")
		if tag == "" {
			continue
		}

		m[tag] = v.Elem().Field(i)
	}
}

// Returns pointer to type t.
func objectContentToType(o types.ObjectContent, t reflect.Type) reflect.Value {
	v := reflect.New(t)

	// Build map of property names to assignable reflect.Value
	m := make(map[string]reflect.Value)
	buildValueMap(v, m)

	for _, p := range o.PropSet {
		rv, ok := m[p.Name]
		if ok {
			pv := anyTypeToValue(p.Val)

			// If type is a pointer, create new instance of type
			if rv.Kind() == reflect.Ptr {
				rv.Set(reflect.New(rv.Type().Elem()))
				rv = rv.Elem()
			}

			// If type is an interface, check if pv implements it
			if rv.Kind() == reflect.Interface {
				rt := rv.Type()
				pt := pv.Type()
				if !pt.Implements(rt) {
					// Check if pointer to pv implements it
					if reflect.PtrTo(pt).Implements(rt) {
						npv := reflect.New(pt)
						npv.Elem().Set(pv)
						pv = npv
					} else {
						panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
					}
				}
			}

			rv.Set(pv)
		}
	}

	return v
}

func RetrieveProperties(r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error {
	rt := reflect.TypeOf(dst)
	if rt.Kind() != reflect.Ptr {
		panic("need pointer")
	}

	rv := reflect.ValueOf(dst).Elem()
	if !rv.CanSet() {
		panic("cannot set dst")
	}

	var isSlice bool

	switch rt.Elem().Kind() {
	case reflect.Struct:
	case reflect.Slice:
		isSlice = true
	default:
		panic("unexpected type")
	}

	req := types.RetrieveProperties{
		This: pc,
		SpecSet: []types.PropertyFilterSpec{
			{
				ObjectSet: []types.ObjectSpec{
					{
						Obj:  obj,
						Skip: false,
					},
				},
				PropSet: []types.PropertySpec{
					{
						All:  true,
						Type: obj.Type,
					},
				},
			},
		},
	}

	res, err := methods.RetrieveProperties(r, &req)
	if err != nil {
		return err
	}

	if isSlice {
		panic("TODO(PN)")
	} else {
		switch len(res.Returnval) {
		case 0:
		case 1:
			v := objectContentToType(res.Returnval[0], rt.Elem())
			rv.Set(v.Elem())
		default:
			// If dst is not a slice, expect to receive 0 or 1 results
			panic("more than 1 result")
		}
	}

	return nil
}
<commit_msg>Allow custom request for mo.RetrieveProperties<commit_after>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

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

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

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

package mo

import (
	"fmt"
	"reflect"
	"regexp"

	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/soap"
	"github.com/vmware/govmomi/vim25/types"
)

var arrayOfRegexp = regexp.MustCompile("ArrayOf(.*)$")

func anyTypeToValue(t interface{}) reflect.Value {
	rt := reflect.TypeOf(t)
	rv := reflect.ValueOf(t)

	// Dereference if ArrayOfXYZ type
	m := arrayOfRegexp.FindStringSubmatch(rt.Name())
	if len(m) > 0 {
		// ArrayOfXYZ type has single field named XYZ
		rv = rv.FieldByName(m[1])
		if !rv.IsValid() {
			panic(fmt.Sprintf("expected %s type to have field %s", m[0], m[1]))
		}
	}

	return rv
}

func buildValueMap(v reflect.Value, m map[string]reflect.Value) {
	t := v.Type().Elem()
	for i := 0; i < t.NumField(); i++ {
		sft := t.Field(i)

		// Recurse into embedded field
		if sft.Anonymous {
			buildValueMap(v.Elem().Field(i).Addr(), m)
			continue
		}

		tag := sft.Tag.Get("mo")
		if tag == "" {
			continue
		}

		m[tag] = v.Elem().Field(i)
	}
}

// Returns pointer to type t.
func objectContentToType(o types.ObjectContent, t reflect.Type) reflect.Value {
	v := reflect.New(t)

	// Build map of property names to assignable reflect.Value
	m := make(map[string]reflect.Value)
	buildValueMap(v, m)

	for _, p := range o.PropSet {
		rv, ok := m[p.Name]
		if ok {
			pv := anyTypeToValue(p.Val)

			// If type is a pointer, create new instance of type
			if rv.Kind() == reflect.Ptr {
				rv.Set(reflect.New(rv.Type().Elem()))
				rv = rv.Elem()
			}

			// If type is an interface, check if pv implements it
			if rv.Kind() == reflect.Interface {
				rt := rv.Type()
				pt := pv.Type()
				if !pt.Implements(rt) {
					// Check if pointer to pv implements it
					if reflect.PtrTo(pt).Implements(rt) {
						npv := reflect.New(pt)
						npv.Elem().Set(pv)
						pv = npv
					} else {
						panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
					}
				}
			}

			rv.Set(pv)
		}
	}

	return v
}

// RetrievePropertiesForRequest calls the RetrieveProperties method with the
// specified request and decodes the response struct into the value pointed to
// by dst.
func RetrievePropertiesForRequest(r soap.RoundTripper, req types.RetrieveProperties, dst interface{}) error {
	rt := reflect.TypeOf(dst)
	if rt.Kind() != reflect.Ptr {
		panic("need pointer")
	}

	rv := reflect.ValueOf(dst).Elem()
	if !rv.CanSet() {
		panic("cannot set dst")
	}

	isSlice := false
	switch rt.Elem().Kind() {
	case reflect.Struct:
	case reflect.Slice:
		isSlice = true
	default:
		panic("unexpected type")
	}

	res, err := methods.RetrieveProperties(r, &req)
	if err != nil {
		return err
	}

	if isSlice {
		elemType := rt.Elem().Elem()
		for _, p := range res.Returnval {
			v := objectContentToType(p, elemType)
			rv.Set(reflect.Append(rv, v.Elem()))
		}
	} else {
		ptrType := rt.Elem()
		switch len(res.Returnval) {
		case 0:
		case 1:
			v := objectContentToType(res.Returnval[0], ptrType)
			rv.Set(v.Elem())
		default:
			// If dst is not a slice, expect to receive 0 or 1 results
			panic("more than 1 result")
		}
	}

	return nil
}

// RetrieveProperties retrieves the properties of the managed object specified
// as obj and decodes the response struct into the value pointed to by dst.
func RetrieveProperties(r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error {
	req := types.RetrieveProperties{
		This: pc,
		SpecSet: []types.PropertyFilterSpec{
			{
				ObjectSet: []types.ObjectSpec{
					{
						Obj:  obj,
						Skip: false,
					},
				},
				PropSet: []types.PropertySpec{
					{
						All:  true,
						Type: obj.Type,
					},
				},
			},
		},
	}

	return RetrievePropertiesForRequest(r, req, dst)
}
<|endoftext|>


<commit_before>// +build linux
package tap

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"unsafe"
)

var (
	IfceHwAddrNotFound = errors.New("Failed to find the hardware addr of interface.")
)

const (
	cIFF_TUN   = 0x0001
	cIFF_TAP   = 0x0002
	cIFF_NO_PI = 0x1000
)

type ifReq struct {
	Name  [0x10]byte
	Flags uint16
	pad   [0x28 - 0x10 - 2]byte
}

func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
	var req ifReq
	req.Flags = flags
	copy(req.Name[:], ifName)
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
	if errno != 0 {
		err = errno
		return
	}
	createdIFName = strings.Trim(string(req.Name[:]), "\x00")
	return
}

// NewTAP creates a new tap interface.
// Windows version behaves a little bit differently to Linux version.
func newTAP() (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), "", cIFF_TAP|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}
	ifce = &Interface{tap: true, file: file, name: name}
	// find the mac address of interface.
	ifaces, err := net.Interfaces()
	if err != nil {
		return
	}
	for _, v := range ifaces {
		if v.Name == name {
			copy(ifce.mac[:6], v.HardwareAddr[:6])
			return ifce, ifce.up()
		}
	}
	err = IfceHwAddrNotFound
	return
}

func (ifce *Interface) up() (err error) {
	sargs := fmt.Sprintf("link dev %s up", ifce.name)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) setIP(ip_mask *net.IPNet) (err error) {
	sargs := fmt.Sprintf("addr add %s dev %s", ip_mask, ifce.name)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func addRoute(ip net.IP, ip_mask *net.IPNet, ifce string) (err error) {
	sargs := fmt.Sprintf("route add %s via %s dev %s", ip_mask, ip, ifce)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) addRoute(ip net.IP, ip_mask *net.IPNet) (err error) {
	return addRoute(ip, ip_mask, ifce.name)
}

func delRoute(ip net.IP, ip_mask *net.IPNet, ifce string) (err error) {
	sargs := fmt.Sprintf("route del %s via %s dev %s", ip_mask, ip, ifce)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) delRoute(ip net.IP, ip_mask *net.IPNet) (err error) {
	return delRoute(ip, ip_mask, ifce.name)
}
<commit_msg>Fix bug when bring up tap0 on linux.<commit_after>// +build linux
package tap

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"unsafe"
)

var (
	IfceHwAddrNotFound = errors.New("Failed to find the hardware addr of interface.")
)

const (
	cIFF_TUN   = 0x0001
	cIFF_TAP   = 0x0002
	cIFF_NO_PI = 0x1000
)

type ifReq struct {
	Name  [0x10]byte
	Flags uint16
	pad   [0x28 - 0x10 - 2]byte
}

func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
	var req ifReq
	req.Flags = flags
	copy(req.Name[:], ifName)
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
	if errno != 0 {
		err = errno
		return
	}
	createdIFName = strings.Trim(string(req.Name[:]), "\x00")
	return
}

// NewTAP creates a new tap interface.
// Windows version behaves a little bit differently to Linux version.
func newTAP() (ifce *Interface, err error) {
	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	name, err := createInterface(file.Fd(), "", cIFF_TAP|cIFF_NO_PI)
	if err != nil {
		return nil, err
	}
	ifce = &Interface{tap: true, file: file, name: name}
	// find the mac address of interface.
	ifaces, err := net.Interfaces()
	if err != nil {
		return
	}
	for _, v := range ifaces {
		if v.Name == name {
			copy(ifce.mac[:6], v.HardwareAddr[:6])
			return ifce, ifce.up()
		}
	}
	err = IfceHwAddrNotFound
	return
}

func (ifce *Interface) up() (err error) {
	sargs := fmt.Sprintf("link set dev %s up mtu 1400", ifce.name)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) setIP(ip_mask *net.IPNet) (err error) {
	sargs := fmt.Sprintf("addr add %s dev %s", ip_mask, ifce.name)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func addRoute(ip net.IP, ip_mask *net.IPNet, ifce string) (err error) {
	sargs := fmt.Sprintf("route add %s via %s dev %s", ip_mask, ip, ifce)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) addRoute(ip net.IP, ip_mask *net.IPNet) (err error) {
	return addRoute(ip, ip_mask, ifce.name)
}

func delRoute(ip net.IP, ip_mask *net.IPNet, ifce string) (err error) {
	sargs := fmt.Sprintf("route del %s via %s dev %s", ip_mask, ip, ifce)
	args := strings.Split(sargs, " ")
	cmd := exec.Command("ip", args...)
	err = cmd.Run()
	return
}

func (ifce *Interface) delRoute(ip net.IP, ip_mask *net.IPNet) (err error) {
	return delRoute(ip, ip_mask, ifce.name)
}
<|endoftext|>


<commit_before>package bird

import (
	"io/ioutil"
	"reflect"
	"testing"
)

func readSampleData(filename string) ([]byte, error) {
	sample := "../test/" + filename
	return ioutil.ReadFile(sample)
}

func TestParseBgpRoutes(t *testing.T) {

	inputs := []string{
		"1 imported, 0 filtered, 2 exported, 1 preferred",
		"0 imported, 2846 exported", // Bird 1.4.x
	}

	expected := []Parsed{
		Parsed{
			"imported":  int64(1),
			"filtered":  int64(0),
			"exported":  int64(2),
			"preferred": int64(1),
		},
		Parsed{
			"imported": int64(0),
			"exported": int64(2846),
		},
	}

	for i, in := range inputs {
		routes := parseBgpRoutes(in)
		if !reflect.DeepEqual(routes, expected[i]) {
			t.Error("Parse bgpRoutes:", routes, "expected:", expected[i])
		}
	}

}

func TestParseRoutesAll(t *testing.T) {
	sample, err := readSampleData("routes_bird1_ipv4.sample")
	if err != nil {
		t.Error(err)
	}

	result := parseRoutes(sample)
	routes, ok := result["routes"].([]Parsed)
	if !ok {
		t.Error("Error getting routes")
	}

	if len(routes) != 4 {
		t.Error("Expected number of routes to be 4")
	}

	assertRouteIsEqual(expectedRoute{
		network: "16.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  true,
	}, routes[0], "Route 1", t)
	assertRouteIsEqual(expectedRoute{
		network: "200.0.0.0/24",
		gateway: "1.2.3.15",
		asPath:  []string{"1339"},
		community: [][]int64{
			{65011, 40},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  true,
	}, routes[1], "Route 2", t)
	assertRouteIsEqual(expectedRoute{
		network: "200.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  false,
	}, routes[2], "Route 3", t)
	assertRouteIsEqual(expectedRoute{
		network: "16.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  true,
	}, routes[3], "Route 4", t)
}

func TestParseRoutesAllBird1(t *testing.T) {
	sample, err := readSampleData("routes_bird1_ipv6.sample")
	if err != nil {
		t.Error(err)
	}

	result := parseRoutes(sample)
	routes, ok := result["routes"].([]Parsed)
	if !ok {
		t.Fatal("Error getting routes")
	}

	if len(routes) != 3 {
		t.Fatalf("Expected 3 routes but got %d", len(routes))
	}

	assertIpv6RoutesAsExpected(routes, t)
}

func TestParseRoutesAllBird2(t *testing.T) {
	sample, err := readSampleData("routes_bird2_ipv6.sample")
	if err != nil {
		t.Error(err)
	}

	result := parseRoutes(sample)
	routes, ok := result["routes"].([]Parsed)
	if !ok {
		t.Fatal("Error getting routes")
	}

	if len(routes) != 3 {
		t.Fatalf("Expected 3 routes but got %d", len(routes))
	}

	assertIpv6RoutesAsExpected(routes, t)
}

func assertIpv6RoutesAsExpected(routes []Parsed, t *testing.T) {
	assertRouteIsEqual(expectedRoute{
		network: "2001:4860::/32",
		gateway: "fe80:ffff:ffff::1",
		asPath:  []string{"15169"},
		community: [][]int64{
			{9033, 3001},
			{65000, 680},
		},
		largeCommunities: [][]int64{
			{48821, 0, 2000},
			{48821, 0, 2100},
		},
		metric:   500,
		primary:  true,
		protocol: "upstream1",
	}, routes[0], "Route 1", t)
	assertRouteIsEqual(expectedRoute{
		network: "2001:4860::/32",
		gateway: "fe80:ffff:ffff::2",
		asPath:  []string{"50629", "15169"},
		community: [][]int64{
			{50629, 200},
			{50629, 201},
		},
		largeCommunities: [][]int64{
			{48821, 0, 3000},
			{48821, 0, 3100},
		},
		metric:   100,
		primary:  false,
		protocol: "upstream2",
	}, routes[1], "Route 2", t)
	assertRouteIsEqual(expectedRoute{
		network: "2001:678:1e0::/48",
		gateway: "fe80:ffff:ffff::2",
		asPath:  []string{"202739"},
		community: [][]int64{
			{48821, 2000},
			{48821, 2100},
		},
		largeCommunities: [][]int64{
			{48821, 0, 2000},
			{48821, 0, 2100},
		},
		metric:   5000,
		primary:  true,
		protocol: "upstream2",
	}, routes[2], "Route 3", t)
}

func assertRouteIsEqual(expected expectedRoute, actual Parsed, name string, t *testing.T) {
	if prefix := actual["network"].(string); prefix != expected.network {
		t.Fatal(name, ": Expected network to be:", expected.network, "not", prefix)
	}

	if nextHop := actual["gateway"].(string); nextHop != expected.gateway {
		t.Fatal(name, ": Expected gateway to be:", expected.gateway, "not", nextHop)
	}

	if metric := actual["metric"].(int64); metric != expected.metric {
		t.Fatal(name, ": Expected metric to be:", expected.metric, "not", metric)
	}

	if protocol := actual["from_protocol"].(string); protocol != expected.protocol {
		t.Fatal(name, ": Expected protocol to be:", expected.protocol, "not", protocol)
	}

	bgp := actual["bgp"].(Parsed)
	if asPath := bgp["as_path"].([]string); !reflect.DeepEqual(asPath, expected.asPath) {
		t.Fatal(name, ": Expected as_path to be:", expected.asPath, "not", asPath)
	}

	if community := bgp["communities"].([][]int64); !reflect.DeepEqual(community, expected.community) {
		t.Fatal(name, ": Expected community to be:", expected.community, "not", community)
	}

	if largeCommunity := bgp["large_communities"].([][]int64); !reflect.DeepEqual(largeCommunity, expected.largeCommunities) {
		t.Fatal(name, ": Expected large_community to be:", expected.largeCommunities, "not", largeCommunity)
	}
}

type expectedRoute struct {
	network          string
	gateway          string
	asPath           []string
	community        [][]int64
	largeCommunities [][]int64
	metric           int64
	protocol         string
	primary          bool
}
<commit_msg>test refacotring ipv6<commit_after>package bird

import (
	"io/ioutil"
	"reflect"
	"testing"
)

func readSampleData(filename string) ([]byte, error) {
	sample := "../test/" + filename
	return ioutil.ReadFile(sample)
}

func TestParseBgpRoutes(t *testing.T) {

	inputs := []string{
		"1 imported, 0 filtered, 2 exported, 1 preferred",
		"0 imported, 2846 exported", // Bird 1.4.x
	}

	expected := []Parsed{
		Parsed{
			"imported":  int64(1),
			"filtered":  int64(0),
			"exported":  int64(2),
			"preferred": int64(1),
		},
		Parsed{
			"imported": int64(0),
			"exported": int64(2846),
		},
	}

	for i, in := range inputs {
		routes := parseBgpRoutes(in)
		if !reflect.DeepEqual(routes, expected[i]) {
			t.Error("Parse bgpRoutes:", routes, "expected:", expected[i])
		}
	}

}

func TestParseRoutesAll(t *testing.T) {
	sample, err := readSampleData("routes_bird1_ipv4.sample")
	if err != nil {
		t.Error(err)
	}

	result := parseRoutes(sample)
	routes, ok := result["routes"].([]Parsed)
	if !ok {
		t.Error("Error getting routes")
	}

	if len(routes) != 4 {
		t.Fatal("Expected 4 routes but got ", len(routes))
	}

	assertRouteIsEqual(expectedRoute{
		network: "16.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  true,
	}, routes[0], "Route 1", t)
	assertRouteIsEqual(expectedRoute{
		network: "200.0.0.0/24",
		gateway: "1.2.3.15",
		asPath:  []string{"1339"},
		community: [][]int64{
			{65011, 40},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8497_AS1339",
		primary:  true,
	}, routes[1], "Route 2", t)
	assertRouteIsEqual(expectedRoute{
		network: "200.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  false,
	}, routes[2], "Route 3", t)
	assertRouteIsEqual(expectedRoute{
		network: "16.0.0.0/24",
		gateway: "1.2.3.16",
		asPath:  []string{"1340"},
		community: [][]int64{
			{65011, 3},
			{9033, 3251},
		},
		largeCommunities: [][]int64{
			{9033, 65666, 12},
			{9033, 65666, 9},
		},
		metric:   100,
		protocol: "ID8503_AS1340",
		primary:  true,
	}, routes[3], "Route 4", t)
}

func TestParseRoutesAllBird1(t *testing.T) {
	runTestForIpv6WithTemplate("routes_bird1_ipv6.sample", t)
}

func TestParseRoutesAllBird2(t *testing.T) {
	runTestForIpv6WithTemplate("routes_bird2_ipv6.sample", t)
}

func runTestForIpv6WithTemplate(template string, t *testing.T) {
	sample, err := readSampleData(template)
	if err != nil {
		t.Error(err)
	}

	result := parseRoutes(sample)
	routes, ok := result["routes"].([]Parsed)
	if !ok {
		t.Fatal("Error getting routes")
	}

	if len(routes) != 3 {
		t.Fatal("Expected 3 routes but got ", len(routes))
	}

	assertRouteIsEqual(expectedRoute{
		network: "2001:4860::/32",
		gateway: "fe80:ffff:ffff::1",
		asPath:  []string{"15169"},
		community: [][]int64{
			{9033, 3001},
			{65000, 680},
		},
		largeCommunities: [][]int64{
			{48821, 0, 2000},
			{48821, 0, 2100},
		},
		metric:   500,
		primary:  true,
		protocol: "upstream1",
	}, routes[0], "Route 1", t)
	assertRouteIsEqual(expectedRoute{
		network: "2001:4860::/32",
		gateway: "fe80:ffff:ffff::2",
		asPath:  []string{"50629", "15169"},
		community: [][]int64{
			{50629, 200},
			{50629, 201},
		},
		largeCommunities: [][]int64{
			{48821, 0, 3000},
			{48821, 0, 3100},
		},
		metric:   100,
		primary:  false,
		protocol: "upstream2",
	}, routes[1], "Route 2", t)
	assertRouteIsEqual(expectedRoute{
		network: "2001:678:1e0::/48",
		gateway: "fe80:ffff:ffff::2",
		asPath:  []string{"202739"},
		community: [][]int64{
			{48821, 2000},
			{48821, 2100},
		},
		largeCommunities: [][]int64{
			{48821, 0, 2000},
			{48821, 0, 2100},
		},
		metric:   5000,
		primary:  true,
		protocol: "upstream2",
	}, routes[2], "Route 3", t)
}

func assertRouteIsEqual(expected expectedRoute, actual Parsed, name string, t *testing.T) {
	if prefix := actual["network"].(string); prefix != expected.network {
		t.Fatal(name, ": Expected network to be:", expected.network, "not", prefix)
	}

	if nextHop := actual["gateway"].(string); nextHop != expected.gateway {
		t.Fatal(name, ": Expected gateway to be:", expected.gateway, "not", nextHop)
	}

	if metric := actual["metric"].(int64); metric != expected.metric {
		t.Fatal(name, ": Expected metric to be:", expected.metric, "not", metric)
	}

	if protocol := actual["from_protocol"].(string); protocol != expected.protocol {
		t.Fatal(name, ": Expected protocol to be:", expected.protocol, "not", protocol)
	}

	bgp := actual["bgp"].(Parsed)
	if asPath := bgp["as_path"].([]string); !reflect.DeepEqual(asPath, expected.asPath) {
		t.Fatal(name, ": Expected as_path to be:", expected.asPath, "not", asPath)
	}

	if community := bgp["communities"].([][]int64); !reflect.DeepEqual(community, expected.community) {
		t.Fatal(name, ": Expected community to be:", expected.community, "not", community)
	}

	if largeCommunity := bgp["large_communities"].([][]int64); !reflect.DeepEqual(largeCommunity, expected.largeCommunities) {
		t.Fatal(name, ": Expected large_community to be:", expected.largeCommunities, "not", largeCommunity)
	}
}

type expectedRoute struct {
	network          string
	gateway          string
	asPath           []string
	community        [][]int64
	largeCommunities [][]int64
	metric           int64
	protocol         string
	primary          bool
}
<|endoftext|>


<commit_before>package base

import (
	"fmt"
	"gopkg.in/orivil/orivil.v0"
)

type Controller struct {
	*orivil.App
}

// @route {get}/
func (this *Controller) Index() {

	this.WriteString("
hello orivil!
")
}
<commit_msg>Update controller.go<commit_after>package base

import (
	"gopkg.in/orivil/orivil.v0"
)

type Controller struct {
	*orivil.App
}

// @route {get}/
func (this *Controller) Index() {

	this.WriteString("
hello orivil!
")
}
<|endoftext|>