<commit_before>// Copyright 2015 The Gogs 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 git

import (
	"fmt"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) IsLink() bool {
	return te.mode == ENTRY_MODE_SYMLINK
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	entryName string
	infos     []interface{}
	err       error
}

// GetCommitsInfo takes advantages of concurrey to speed up getting information
// of all commits that are corresponding to these entries.
// TODO: limit max goroutines number should be configurable
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	// Length of taskChan determines how many goroutines (subprocesses) can run at the same time.
	// The length of revChan should be same as taskChan so goroutines whoever finished job can
	// exit as early as possible, only store data inside channel.
	taskChan := make(chan bool, 10)
	revChan := make(chan commitInfo, 10)
	doneChan := make(chan error)

	// Receive loop will exit when it collects same number of data pieces as tree entries.
	// It notifies doneChan before exits or notify early with possible error.
	infoMap := make(map[string][]interface{}, len(tes))
	go func() {
		i := 0
		for info := range revChan {
			if info.err != nil {
				doneChan <- info.err
				return
			}

			infoMap[info.entryName] = info.infos
			i++
			if i == len(tes) {
				break
			}
		}
		doneChan <- nil
	}()

	for i := range tes {
		// When taskChan is idle (or has empty slots), put operation will not block.
		// However when taskChan is full, code will block and wait any running goroutines to finish.
		taskChan <- true

		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{entryName: tes[i].Name()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
				<-taskChan // Clear one slot from taskChan to allow new goroutines to start.
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{entryName: tes[i].Name()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil && !IsErrNotExist(err) {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smURL := ""
			if sm != nil {
				smURL = sm.URL
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smURL, tes[i].ID.String())}
			}
			revChan <- cinfo
			<-taskChan
		}(i)
	}

	if err := <-doneChan; err != nil {
		return nil, err
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].Name()]
	}
	return commitsInfo, nil
}
<commit_msg>Can set a custom max number of goroutine (#26)<commit_after>// Copyright 2015 The Gogs 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 git

import (
	"fmt"
	"path"
	"path/filepath"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) IsLink() bool {
	return te.mode == ENTRY_MODE_SYMLINK
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	entryName string
	infos     []interface{}
	err       error
}

// GetCommitsInfo takes advantages of concurrency to speed up getting information
// of all commits that are corresponding to these entries. This method will automatically
// choose the right number of goroutine (concurrency) to use related of the host CPU.
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	return tes.GetCommitsInfoWithCustomConcurrency(commit, treePath, 0)
}

// GetCommitsInfoWithCustomConcurrency takes advantages of concurrency to speed up getting information
// of all commits that are corresponding to these entries. If the given maxConcurrency is negative or
// equal to zero:  the right number of goroutine (concurrency) to use will be choosen related of the
// host CPU.
func (tes Entries) GetCommitsInfoWithCustomConcurrency(commit *Commit, treePath string, maxConcurrency int) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	if maxConcurrency <= 0 {
		maxConcurrency = runtime.NumCPU()
	}

	// Length of taskChan determines how many goroutines (subprocesses) can run at the same time.
	// The length of revChan should be same as taskChan so goroutines whoever finished job can
	// exit as early as possible, only store data inside channel.
	taskChan := make(chan bool, maxConcurrency)
	revChan := make(chan commitInfo, maxConcurrency)
	doneChan := make(chan error)

	// Receive loop will exit when it collects same number of data pieces as tree entries.
	// It notifies doneChan before exits or notify early with possible error.
	infoMap := make(map[string][]interface{}, len(tes))
	go func() {
		i := 0
		for info := range revChan {
			if info.err != nil {
				doneChan <- info.err
				return
			}

			infoMap[info.entryName] = info.infos
			i++
			if i == len(tes) {
				break
			}
		}
		doneChan <- nil
	}()

	for i := range tes {
		// When taskChan is idle (or has empty slots), put operation will not block.
		// However when taskChan is full, code will block and wait any running goroutines to finish.
		taskChan <- true

		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{entryName: tes[i].Name()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
				<-taskChan // Clear one slot from taskChan to allow new goroutines to start.
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{entryName: tes[i].Name()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil && !IsErrNotExist(err) {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smURL := ""
			if sm != nil {
				smURL = sm.URL
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smURL, tes[i].ID.String())}
			}
			revChan <- cinfo
			<-taskChan
		}(i)
	}

	if err := <-doneChan; err != nil {
		return nil, err
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].Name()]
	}
	return commitsInfo, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gogs 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 git

import (
	"fmt"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	id    string
	entry string
	infos []interface{}
	err   error
}

// GetCommitsInfo takes advantages of concurrey to speed up getting information
// of all commits that are corresponding to these entries.
// TODO: limit max goroutines at same time
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	revChan := make(chan commitInfo, 10)

	infoMap := make(map[string][]interface{}, len(tes))
	for i := range tes {
		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{id: tes[i].ID.String(), entry: tes[i].Name()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{id: tes[i].ID.String(), entry: tes[i].Name()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smUrl := ""
			if sm != nil {
				smUrl = sm.Url
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smUrl, tes[i].ID.String())}
			}
			revChan <- cinfo
		}(i)
	}

	i := 0
	for info := range revChan {
		if info.err != nil {
			return nil, info.err
		}

		infoMap[info.entry] = info.infos
		i++
		if i == len(tes) {
			break
		}
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].Name()]
	}
	return commitsInfo, nil
}
<commit_msg>change commitInfo.entry to commitInfo.entryName<commit_after>// Copyright 2015 The Gogs 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 git

import (
	"fmt"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

type EntryMode int

// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
	ENTRY_MODE_BLOB    EntryMode = 0100644
	ENTRY_MODE_EXEC    EntryMode = 0100755
	ENTRY_MODE_SYMLINK EntryMode = 0120000
	ENTRY_MODE_COMMIT  EntryMode = 0160000
	ENTRY_MODE_TREE    EntryMode = 0040000
)

type TreeEntry struct {
	ID   sha1
	Type ObjectType

	mode EntryMode
	name string

	ptree *Tree

	commited bool

	size  int64
	sized bool
}

func (te *TreeEntry) Name() string {
	return te.name
}

func (te *TreeEntry) Size() int64 {
	if te.IsDir() {
		return 0
	} else if te.sized {
		return te.size
	}

	stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
	if err != nil {
		return 0
	}

	te.sized = true
	te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
	return te.size
}

func (te *TreeEntry) IsSubModule() bool {
	return te.mode == ENTRY_MODE_COMMIT
}

func (te *TreeEntry) IsDir() bool {
	return te.mode == ENTRY_MODE_TREE
}

func (te *TreeEntry) Blob() *Blob {
	return &Blob{
		repo:      te.ptree.repo,
		TreeEntry: te,
	}
}

type Entries []*TreeEntry

var sorter = []func(t1, t2 *TreeEntry) bool{
	func(t1, t2 *TreeEntry) bool {
		return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
	},
	func(t1, t2 *TreeEntry) bool {
		return t1.name < t2.name
	},
}

func (tes Entries) Len() int      { return len(tes) }
func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
func (tes Entries) Less(i, j int) bool {
	t1, t2 := tes[i], tes[j]
	var k int
	for k = 0; k < len(sorter)-1; k++ {
		sort := sorter[k]
		switch {
		case sort(t1, t2):
			return true
		case sort(t2, t1):
			return false
		}
	}
	return sorter[k](t1, t2)
}

func (tes Entries) Sort() {
	sort.Sort(tes)
}

type commitInfo struct {
	id        string
	entryName string
	infos     []interface{}
	err       error
}

// GetCommitsInfo takes advantages of concurrey to speed up getting information
// of all commits that are corresponding to these entries.
// TODO: limit max goroutines at same time
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
	if len(tes) == 0 {
		return nil, nil
	}

	revChan := make(chan commitInfo, 10)

	infoMap := make(map[string][]interface{}, len(tes))
	for i := range tes {
		if tes[i].Type != OBJECT_COMMIT {
			go func(i int) {
				cinfo := commitInfo{id: tes[i].ID.String(), entryName: tes[i].Name()}
				c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
				if err != nil {
					cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
				} else {
					cinfo.infos = []interface{}{tes[i], c}
				}
				revChan <- cinfo
			}(i)
			continue
		}

		// Handle submodule
		go func(i int) {
			cinfo := commitInfo{id: tes[i].ID.String(), entryName: tes[i].Name()}
			sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
				revChan <- cinfo
				return
			}

			smUrl := ""
			if sm != nil {
				smUrl = sm.Url
			}

			c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
			if err != nil {
				cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
			} else {
				cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smUrl, tes[i].ID.String())}
			}
			revChan <- cinfo
		}(i)
	}

	i := 0
	for info := range revChan {
		if info.err != nil {
			return nil, info.err
		}

		infoMap[info.entryName] = info.infos
		i++
		if i == len(tes) {
			break
		}
	}

	commitsInfo := make([][]interface{}, len(tes))
	for i := 0; i < len(tes); i++ {
		commitsInfo[i] = infoMap[tes[i].Name()]
	}
	return commitsInfo, nil
}
<|endoftext|>


<commit_before>
import (
	"math"
)

type Vector struct {
	    x, y, z float64
}

func validateImpact (tri1, tri2, tri3 Vector, object Object) Vector {

	// calculate the cross-product of the norm and direction
	if object.ObjectSpace > distDiff(object) {
		return impact(object)
	}

func distDiff(object) float64 {

	tri1, tri2, height = object.Position[0],object.Position[2],object.Position[2]

	centroid Vector := {(tri1[0]+tri2[0]+tri3[0])/3,(tri1[1]+tri2[1]+tri3[1])/3,(tri1[2]+tri2[2]+tri3[2])/3}

	diff := math.Abs(centroid)-math.Abs(object.Position)

	return diff
}
func impact (object Object) Object {
	// just changing the z - direction
	object.Direction[2] = -object.Direction[2]
	return
}

func normTriangle (){

	point := triCentroid()

	surfaceNorm := crossProduct(a,b)
}
func makeVertex () {

}

func triCentroid () {

}
<commit_msg>updated triP<commit_after>
import (
	"math"
	"github.com/go-gl/mathgl/mgl64"
)

func closestPoint (tri1, tri2, tri3 mgl64.Vec3, object Object)
mgl64.Vec3 {

	// not correct but good enough
	var centroid mgl64.Vec3
	centroid := tri1

	// norm of the triangle, make sure that this is right-oriented
	norm := normTriangle(tri1-tri3, tri2-tri3)

	// projection of vector u on the normal
	proj := object.Position.Projection(norm)

	if object.Size > distDiff(proj, centroid) {
		return impact(object)
	}

// projection method
func (v1 mgl64.Vec3) Projection(v2 mgl64.Vec3) mgl64.Vec3 {
	return mgl64.Vec3{v1.Dot(v2)/(math.Pow(v2[0],2),
	math.Pow(v2[1],2),math.Pow(v2[2],2))*v2}

func (v1 Vec3) Add(v2 Vec3) Vec3 {
	return Vec3{v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]}
}

func distDiff(object Object, centroid mgl64.Vec3) float64 {
	diff := (centroid-object.Position).Len()
	return diff
}

func impact (object Object) Object {
	// just changing the z - direction
	// if it is x,y,z
	object.Direction[2] = -object.Direction[2]
	return object
}

func normTriangle (triPoint1, triPoint2 mgl64.Vec3){
	// make sure that this is right-oriented
	surfaceNorm := triPoint1.Cross(triPoint2)
	return surfaceNorm
}
<|endoftext|>


<commit_before>// +build windows

package i18n_test

import (
	"os"
	"path/filepath"

	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/i18n"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	"github.com/pivotal-cf-experimental/jibber_jabber"

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

var _ = Describe("i18n.Init() function", func() {
	var (
		configRepo core_config.ReadWriter
	)

	BeforeEach(func() {
		i18n.Resources_path = filepath.Join("cf", "i18n", "test_fixtures")
		configRepo = testconfig.NewRepositoryWithDefaults()
	})

	Describe("When a user has a locale configuration set", func() {
		Context("creates a valid T function", func() {
			BeforeEach(func() {
				configRepo.SetLocale("en_US")
			})

			It("returns a usable T function for simple strings", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Hello world!")
				Ω("Hello world!").Should(Equal(translation))
			})

			It("returns a usable T function for complex strings (interpolated)", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Deleting domain {{.DomainName}} as {{.Username}}...", map[string]interface{}{"DomainName": "foo.com", "Username": "Anand"})
				Ω("Deleting domain foo.com as Anand...").Should(Equal(translation))
			})
		})
	})

	Describe("When a user does not have a locale configuration set", func() {
		BeforeEach(func() {
			//All these tests require the system language to be English
			Ω(jibber_jabber.DetectIETF()).Should(Equal("en-US"))
		})

		Context("creates a valid T function", func() {
			BeforeEach(func() {
				os.Setenv("LC_ALL", "en_US.UTF-8")
			})

			It("returns a usable T function for simple strings", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Change user password")
				Ω("Change user password").Should(Equal(translation))
			})

			It("returns a usable T function for complex strings (interpolated)", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Deleting domain {{.DomainName}} as {{.Username}}...", map[string]interface{}{"DomainName": "foo", "Username": "Anand"})
				Ω("Deleting domain foo as Anand...").Should(Equal(translation))
			})
		})

		It("matches zh_CN to zh_Hans", func() {
			os.Setenv("LC_ALL", "zh_CN.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("buildpack未找到").Should(Equal(translation))
		})

		It("matches zh_TW to zh_Hant", func() {
			os.Setenv("LC_ALL", "zh_TW.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("(Hant)No buildpacks found").Should(Equal(translation))
		})

		It("matches zh_HK to zh_Hant", func() {
			os.Setenv("LC_ALL", "zh_HK.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("(Hant)No buildpacks found").Should(Equal(translation))
		})
	})
})
<commit_msg>fix failing HK/TW Windows 32 unit test<commit_after>// +build windows

package i18n_test

import (
	"os"
	"path/filepath"

	"github.com/cloudfoundry/cli/cf/configuration/core_config"
	"github.com/cloudfoundry/cli/cf/i18n"
	testconfig "github.com/cloudfoundry/cli/testhelpers/configuration"
	"github.com/pivotal-cf-experimental/jibber_jabber"

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

var _ = Describe("i18n.Init() function", func() {
	var (
		configRepo core_config.ReadWriter
	)

	BeforeEach(func() {
		i18n.Resources_path = filepath.Join("cf", "i18n", "test_fixtures")
		configRepo = testconfig.NewRepositoryWithDefaults()
	})

	Describe("When a user has a locale configuration set", func() {
		Context("creates a valid T function", func() {
			BeforeEach(func() {
				configRepo.SetLocale("en_US")
			})

			It("returns a usable T function for simple strings", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Hello world!")
				Ω("Hello world!").Should(Equal(translation))
			})

			It("returns a usable T function for complex strings (interpolated)", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Deleting domain {{.DomainName}} as {{.Username}}...", map[string]interface{}{"DomainName": "foo.com", "Username": "Anand"})
				Ω("Deleting domain foo.com as Anand...").Should(Equal(translation))
			})
		})
	})

	Describe("When a user does not have a locale configuration set", func() {
		BeforeEach(func() {
			os.Setenv("LC_ALL", "en_US.UTF-8")

			//All these tests require the system language to be English
			Ω(jibber_jabber.DetectIETF()).Should(Equal("en-US"))
		})

		Context("creates a valid T function", func() {
			It("returns a usable T function for simple strings", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Change user password")
				Ω("Change user password").Should(Equal(translation))
			})

			It("returns a usable T function for complex strings (interpolated)", func() {
				T := i18n.Init(configRepo)
				Ω(T).ShouldNot(BeNil())

				translation := T("Deleting domain {{.DomainName}} as {{.Username}}...", map[string]interface{}{"DomainName": "foo", "Username": "Anand"})
				Ω("Deleting domain foo as Anand...").Should(Equal(translation))
			})
		})

	})

	Describe("When locale is HK/TW", func() {
		It("matches zh_CN to zh_Hans", func() {
			os.Setenv("LC_ALL", "zh_CN.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("buildpack未找到").Should(Equal(translation))
		})

		It("matches zh_TW to zh_Hant", func() {
			os.Setenv("LC_ALL", "zh_TW.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("(Hant)No buildpacks found").Should(Equal(translation))
		})

		It("matches zh_HK to zh_Hant", func() {
			os.Setenv("LC_ALL", "zh_HK.UTF-8")
			T := i18n.Init(configRepo)
			Ω(T).ShouldNot(BeNil())

			translation := T("No buildpacks found")
			Ω("(Hant)No buildpacks found").Should(Equal(translation))
		})
	})
})
<|endoftext|>


<commit_before>package rpc

import (
	"encoding/json"

	"github.com/gopherjs/websocket"
)

type Call struct {
	ServiceMethod string
	Args, Reply   interface{}
	Error         error
	Done          chan *Call
}

type request struct {
	Method string         `json:"method"`
	ID     uint           `json:"id"`
	Params [1]interface{} `json:"params"`
}

type Client struct {
	ws     *websocket.Websocket
	nextID uint
	reqs   map[uint]func(json.RawMessage, error)
}

func Dial(addr string) (*Client, error) {
	w, err := websocket.New(addr)
	if err != nil {
		return nil, err
	}
	return &Client{
		ws:   w,
		reqs: make(map[uint]func(json.RawMessage, error)),
	}, nil
}

func (c *Client) Call(method string, args interface{}, reply interface{}) error {
	call := <-c.Go(method, args, reply, make(chan *Call, 1)).Done
	return call.Error
}

func (c *Client) Close() error {
	return c.w.Close()
}

func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
	call := &Call{
		ServiceMethod: method,
		Args:          args,
		Reply:         reply,
	}
	if done == nil {
		call.Done = make(chan *Call, 1)
	} else {
		call.Done = done
	}
	c.nextID++
	id := c.nextID
	c.reqs[id] = func(rm json.RawMessage, err error) {
		if err != nil {
			call.Error = err
		} else if err = json.Unmarshal(rm, reply); err != nil {
			call.Error = err
		}
		call.Done <- call
	}
	return call
}
<commit_msg>Added onMessage handler<commit_after>package rpc

import (
	"encoding/json"

	"github.com/gopherjs/websocket"
)

type Call struct {
	ServiceMethod string
	Args, Reply   interface{}
	Error         error
	Done          chan *Call
}

type request struct {
	Method string         `json:"method"`
	ID     uint           `json:"id"`
	Params [1]interface{} `json:"params"`
}

type Client struct {
	ws     *websocket.Websocket
	nextID uint
	reqs   map[uint]func(json.RawMessage, error)
}

func Dial(addr string) (*Client, error) {
	w, err := websocket.New(addr)
	if err != nil {
		return nil, err
	}
	reqs := make(map[uint]func(json.RawMessage, error))
	w.AddEventListener("message", false, func(e *js.Object) {
		var (
			r request
			m json.RawMessage
		)
		r.Params[0] = &m
		err := json.UnmarshalString(e.Get("data").String(), &r)
		f, ok := reqs[r.ID]
		if ok {
			delete(reqs, r.ID)
			f(m, err)
		}
	})
	return &Client{
		ws:   w,
		reqs: reqs,
	}, nil
}

func (c *Client) Call(method string, args interface{}, reply interface{}) error {
	call := <-c.Go(method, args, reply, make(chan *Call, 1)).Done
	return call.Error
}

func (c *Client) Close() error {
	return c.w.Close()
}

func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
	call := &Call{
		ServiceMethod: method,
		Args:          args,
		Reply:         reply,
	}
	if done == nil {
		call.Done = make(chan *Call, 1)
	} else {
		call.Done = done
	}
	c.nextID++
	id := c.nextID
	c.reqs[id] = func(rm json.RawMessage, err error) {
		if err != nil {
			call.Error = err
		} else if err = json.Unmarshal(rm, reply); err != nil {
			call.Error = err
		}
		call.Done <- call
	}
	return call
}
<|endoftext|>


<commit_before>//go:generate packer-sdc mapstructure-to-hcl2 -type Config

// NB this code was based on https://github.com/hashicorp/packer/blob/81522dced0b25084a824e79efda02483b12dc7cd/provisioner/windows-restart/provisioner.go

package update

import (
	"bytes"
	"context"
	_ "embed" // this is needed for using the go:embed directive
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
	"time"
	"unicode/utf16"

	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/hashicorp/packer-plugin-sdk/common"
	"github.com/hashicorp/packer-plugin-sdk/packer"
	"github.com/hashicorp/packer-plugin-sdk/retry"
	"github.com/hashicorp/packer-plugin-sdk/template/config"
	"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
	"github.com/hashicorp/packer-plugin-sdk/uuid"
)

const (
	elevatedPath                 = "C:/Windows/Temp/packer-windows-update-elevated.ps1"
	elevatedCommand              = "PowerShell -ExecutionPolicy Bypass -OutputFormat Text -File C:/Windows/Temp/packer-windows-update-elevated.ps1"
	windowsUpdatePath            = "C:/Windows/Temp/packer-windows-update.ps1"
	pendingRebootElevatedPath    = "C:/Windows/Temp/packer-windows-update-pending-reboot-elevated.ps1"
	pendingRebootElevatedCommand = "PowerShell -ExecutionPolicy Bypass -OutputFormat Text -File C:/Windows/Temp/packer-windows-update-pending-reboot-elevated.ps1"
	restartCommand               = "shutdown.exe -f -r -t 0 -c \"packer restart\""
	testRestartCommand           = "shutdown.exe -f -r -t 60 -c \"packer restart test\""
	abortTestRestartCommand      = "shutdown.exe -a"
	retryableDelay               = 5 * time.Second
)

//go:embed windows-update.ps1
var windowsUpdatePs1 []byte

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// The timeout for waiting for the machine to restart
	RestartTimeout time.Duration `mapstructure:"restart_timeout"`

	// Instructs the communicator to run the remote script as a
	// Windows scheduled task, effectively elevating the remote
	// user by impersonating a logged-in user.
	Username string `mapstructure:"username"`
	Password string `mapstructure:"password"`

	// The updates search criteria.
	// See the IUpdateSearcher::Search method at https://docs.microsoft.com/en-us/windows/desktop/api/wuapi/nf-wuapi-iupdatesearcher-search.
	SearchCriteria string `mapstructure:"search_criteria"`

	// Filters the installed Windows updates. If no filter is
	// matched the update is NOT installed.
	Filters []string `mapstructure:"filters"`

	// Adds a limit to how many updates are installed at a time
	UpdateLimit int `mapstructure:"update_limit"`

	// Max times the provisioner will try install the updates
	// in case of failure.
	UpdateMaxRetries int `mapstructure:"update_max_retries"`

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

func (b *Provisioner) ConfigSpec() hcldec.ObjectSpec {
	return b.config.FlatMapstructure().HCL2Spec()
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"execute_command",
			},
		},
	}, raws...)
	if err != nil {
		return err
	}

	if p.config.RestartTimeout == 0 {
		p.config.RestartTimeout = 4 * time.Hour
	}

	if p.config.Username == "" {
		p.config.Username = "SYSTEM"
	}

	var errs error

	if p.config.Username == "" {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Must supply an 'username'"))
	}

	if p.config.UpdateLimit == 0 {
		p.config.UpdateLimit = 1000
	}

	if p.config.UpdateMaxRetries == 0 {
		p.config.UpdateMaxRetries = 5
	}

	return errs
}

func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error {
	uploadTimeout := 5 * time.Minute
	ui.Say("Uploading the Windows update elevated script...")
	var buffer bytes.Buffer
	err := elevatedTemplate.Execute(&buffer, elevatedOptions{
		Username:        p.config.Username,
		Password:        p.config.Password,
		TaskDescription: "Packer Windows update elevated task",
		TaskName:        fmt.Sprintf("packer-windows-update-%s", uuid.TimeOrderedUUID()),
		Command:         p.windowsUpdateCommand(),
	})
	if err != nil {
		fmt.Printf("Error creating elevated template: %s", err)
		return err
	}
	err = retry.Config{StartTimeout: uploadTimeout}.Run(ctx, func(context.Context) error {
		if err := comm.Upload(
			elevatedPath,
			bytes.NewReader(buffer.Bytes()),
			nil); err != nil {
			return fmt.Errorf("Error uploading the Windows update elevated script: %s", err)
		}
		return nil
	})
	if err != nil {
		return err
	}

	ui.Say("Uploading the Windows update check for reboot required elevated script...")
	buffer.Reset()
	err = elevatedTemplate.Execute(&buffer, elevatedOptions{
		Username:        p.config.Username,
		Password:        p.config.Password,
		TaskDescription: "Packer Windows update pending reboot elevated task",
		TaskName:        fmt.Sprintf("packer-windows-update-pending-reboot-%s", uuid.TimeOrderedUUID()),
		Command:         p.windowsUpdateCheckForRebootRequiredCommand(),
	})
	if err != nil {
		fmt.Printf("Error creating elevated template: %s", err)
		return err
	}
	err = retry.Config{StartTimeout: uploadTimeout}.Run(ctx, func(context.Context) error {
		if err := comm.Upload(
			pendingRebootElevatedPath,
			bytes.NewReader(buffer.Bytes()),
			nil); err != nil {
			return fmt.Errorf("Error uploading the Windows update check for reboot required elevated script: %s", err)
		}
		return nil
	})
	if err != nil {
		return err
	}

	ui.Say("Uploading the Windows update script...")
	err = comm.Upload(
		windowsUpdatePath,
		bytes.NewReader(windowsUpdatePs1),
		nil)
	if err != nil {
		return err
	}

	for {
		restartPending, err := p.update(ctx, ui, comm)
		if err != nil {
			return err
		}

		if !restartPending {
			return nil
		}

		err = p.restart(ctx, ui, comm)
		if err != nil {
			return err
		}
	}
}

func (p *Provisioner) update(ctx context.Context, ui packer.Ui, comm packer.Communicator) (bool, error) {
	ui.Say("Running Windows update...")
	var restartPending bool
	err := retry.Config{
		RetryDelay: func() time.Duration { return retryableDelay },
		Tries:      p.config.UpdateMaxRetries,
	}.Run(ctx, func(ctx context.Context) error {
		cmd := &packer.RemoteCmd{Command: elevatedCommand}
		err := cmd.RunWithUi(ctx, comm, ui)
		if err != nil {
			return err
		}
		var exitStatus = cmd.ExitStatus()
		switch exitStatus {
		case 0:
			return nil
		case 101:
			restartPending = true
			return nil
		default:
			return fmt.Errorf("Windows update script exited with non-zero exit status: %d", exitStatus)
		}
	})
	return restartPending, err
}

func (p *Provisioner) restart(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
	restartPending := true
	for restartPending {
		ui.Say("Restarting the machine...")
		err := p.retryable(ctx, func(ctx context.Context) error {
			cmd := &packer.RemoteCmd{Command: restartCommand}
			err := cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}
			exitStatus := cmd.ExitStatus()
			if exitStatus != 0 {
				return fmt.Errorf("Failed to restart the machine with exit status: %d", exitStatus)
			}
			return err
		})
		if err != nil {
			return err
		}

		ui.Say("Waiting for machine to become available...")
		err = p.retryable(ctx, func(ctx context.Context) error {
			// wait for the machine to reboot.
			cmd := &packer.RemoteCmd{Command: testRestartCommand}
			err := cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}
			exitStatus := cmd.ExitStatus()
			if exitStatus != 0 {
				return fmt.Errorf("Machine not yet available (exit status %d)", exitStatus)
			}
			cmd = &packer.RemoteCmd{Command: abortTestRestartCommand}
			err = cmd.RunWithUi(ctx, comm, ui)

			return err
		})
		if err != nil {
			return err
		}

		ui.Say("Checking for pending restart...")
		err = p.retryable(ctx, func(ctx context.Context) error {
			cmd := &packer.RemoteCmd{Command: pendingRebootElevatedCommand}
			err = cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}

			exitStatus := cmd.ExitStatus()
			switch {
			case exitStatus == 0:
				restartPending = false
			case exitStatus == 101:
				restartPending = true
			default:
				return fmt.Errorf("Machine not yet available (exit status %d)", exitStatus)
			}

			return err
		})
		if err != nil {
			return err
		}

		if restartPending {
			ui.Say("Restart is still pending...")
		} else {
			ui.Say("Restart complete")
		}
	}

	return nil
}

// retryable will retry the given function over and over until a
// non-error is returned, RestartTimeout expires, or ctx is
// cancelled.
func (p *Provisioner) retryable(ctx context.Context, f func(ctx context.Context) error) error {
	return retry.Config{
		RetryDelay:   func() time.Duration { return retryableDelay },
		StartTimeout: p.config.RestartTimeout,
	}.Run(ctx, f)
}

func (p *Provisioner) windowsUpdateCommand() string {
	return fmt.Sprintf(
		"PowerShell -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand %s",
		base64.StdEncoding.EncodeToString(
			encodeUtf16Le(fmt.Sprintf(
				"%s%s%s -UpdateLimit %d",
				windowsUpdatePath,
				searchCriteriaArgument(p.config.SearchCriteria),
				filtersArgument(p.config.Filters),
				p.config.UpdateLimit))))
}

func (p *Provisioner) windowsUpdateCheckForRebootRequiredCommand() string {
	return fmt.Sprintf(
		"PowerShell -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand %s",
		base64.StdEncoding.EncodeToString(
			encodeUtf16Le(fmt.Sprintf(
				"%s -OnlyCheckForRebootRequired",
				windowsUpdatePath))))
}

func encodeUtf16Le(s string) []byte {
	d := utf16.Encode([]rune(s))
	b := make([]byte, len(d)*2)
	for i, r := range d {
		b[i*2] = byte(r)
		b[i*2+1] = byte(r >> 8)
	}
	return b
}

func searchCriteriaArgument(searchCriteria string) string {
	if searchCriteria == "" {
		return ""
	}

	var buffer bytes.Buffer

	buffer.WriteString(" -SearchCriteria ")
	buffer.WriteString(escapePowerShellString(searchCriteria))

	return buffer.String()
}

func filtersArgument(filters []string) string {
	if filters == nil {
		return ""
	}

	var buffer bytes.Buffer

	buffer.WriteString(" -Filters ")

	for i, filter := range filters {
		if i > 0 {
			buffer.WriteString(",")
		}
		buffer.WriteString(escapePowerShellString(filter))
	}

	return buffer.String()
}

func escapePowerShellString(value string) string {
	return fmt.Sprintf(
		"'%s'",
		// escape single quotes with another single quote.
		strings.Replace(value, "'", "''", -1))
}
<commit_msg>move the uploadTimeout declaration to the module const block<commit_after>//go:generate packer-sdc mapstructure-to-hcl2 -type Config

// NB this code was based on https://github.com/hashicorp/packer/blob/81522dced0b25084a824e79efda02483b12dc7cd/provisioner/windows-restart/provisioner.go

package update

import (
	"bytes"
	"context"
	_ "embed" // this is needed for using the go:embed directive
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
	"time"
	"unicode/utf16"

	"github.com/hashicorp/hcl/v2/hcldec"
	"github.com/hashicorp/packer-plugin-sdk/common"
	"github.com/hashicorp/packer-plugin-sdk/packer"
	"github.com/hashicorp/packer-plugin-sdk/retry"
	"github.com/hashicorp/packer-plugin-sdk/template/config"
	"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
	"github.com/hashicorp/packer-plugin-sdk/uuid"
)

const (
	elevatedPath                 = "C:/Windows/Temp/packer-windows-update-elevated.ps1"
	elevatedCommand              = "PowerShell -ExecutionPolicy Bypass -OutputFormat Text -File C:/Windows/Temp/packer-windows-update-elevated.ps1"
	windowsUpdatePath            = "C:/Windows/Temp/packer-windows-update.ps1"
	pendingRebootElevatedPath    = "C:/Windows/Temp/packer-windows-update-pending-reboot-elevated.ps1"
	pendingRebootElevatedCommand = "PowerShell -ExecutionPolicy Bypass -OutputFormat Text -File C:/Windows/Temp/packer-windows-update-pending-reboot-elevated.ps1"
	restartCommand               = "shutdown.exe -f -r -t 0 -c \"packer restart\""
	testRestartCommand           = "shutdown.exe -f -r -t 60 -c \"packer restart test\""
	abortTestRestartCommand      = "shutdown.exe -a"
	retryableDelay               = 5 * time.Second
	uploadTimeout                = 5 * time.Minute
)

//go:embed windows-update.ps1
var windowsUpdatePs1 []byte

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	// The timeout for waiting for the machine to restart
	RestartTimeout time.Duration `mapstructure:"restart_timeout"`

	// Instructs the communicator to run the remote script as a
	// Windows scheduled task, effectively elevating the remote
	// user by impersonating a logged-in user.
	Username string `mapstructure:"username"`
	Password string `mapstructure:"password"`

	// The updates search criteria.
	// See the IUpdateSearcher::Search method at https://docs.microsoft.com/en-us/windows/desktop/api/wuapi/nf-wuapi-iupdatesearcher-search.
	SearchCriteria string `mapstructure:"search_criteria"`

	// Filters the installed Windows updates. If no filter is
	// matched the update is NOT installed.
	Filters []string `mapstructure:"filters"`

	// Adds a limit to how many updates are installed at a time
	UpdateLimit int `mapstructure:"update_limit"`

	// Max times the provisioner will try install the updates
	// in case of failure.
	UpdateMaxRetries int `mapstructure:"update_max_retries"`

	ctx interpolate.Context
}

type Provisioner struct {
	config Config
}

func (b *Provisioner) ConfigSpec() hcldec.ObjectSpec {
	return b.config.FlatMapstructure().HCL2Spec()
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	err := config.Decode(&p.config, &config.DecodeOpts{
		Interpolate:        true,
		InterpolateContext: &p.config.ctx,
		InterpolateFilter: &interpolate.RenderFilter{
			Exclude: []string{
				"execute_command",
			},
		},
	}, raws...)
	if err != nil {
		return err
	}

	if p.config.RestartTimeout == 0 {
		p.config.RestartTimeout = 4 * time.Hour
	}

	if p.config.Username == "" {
		p.config.Username = "SYSTEM"
	}

	var errs error

	if p.config.Username == "" {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Must supply an 'username'"))
	}

	if p.config.UpdateLimit == 0 {
		p.config.UpdateLimit = 1000
	}

	if p.config.UpdateMaxRetries == 0 {
		p.config.UpdateMaxRetries = 5
	}

	return errs
}

func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error {
	ui.Say("Uploading the Windows update elevated script...")
	var buffer bytes.Buffer
	err := elevatedTemplate.Execute(&buffer, elevatedOptions{
		Username:        p.config.Username,
		Password:        p.config.Password,
		TaskDescription: "Packer Windows update elevated task",
		TaskName:        fmt.Sprintf("packer-windows-update-%s", uuid.TimeOrderedUUID()),
		Command:         p.windowsUpdateCommand(),
	})
	if err != nil {
		fmt.Printf("Error creating elevated template: %s", err)
		return err
	}
	err = retry.Config{StartTimeout: uploadTimeout}.Run(ctx, func(context.Context) error {
		if err := comm.Upload(
			elevatedPath,
			bytes.NewReader(buffer.Bytes()),
			nil); err != nil {
			return fmt.Errorf("Error uploading the Windows update elevated script: %s", err)
		}
		return nil
	})
	if err != nil {
		return err
	}

	ui.Say("Uploading the Windows update check for reboot required elevated script...")
	buffer.Reset()
	err = elevatedTemplate.Execute(&buffer, elevatedOptions{
		Username:        p.config.Username,
		Password:        p.config.Password,
		TaskDescription: "Packer Windows update pending reboot elevated task",
		TaskName:        fmt.Sprintf("packer-windows-update-pending-reboot-%s", uuid.TimeOrderedUUID()),
		Command:         p.windowsUpdateCheckForRebootRequiredCommand(),
	})
	if err != nil {
		fmt.Printf("Error creating elevated template: %s", err)
		return err
	}
	err = retry.Config{StartTimeout: uploadTimeout}.Run(ctx, func(context.Context) error {
		if err := comm.Upload(
			pendingRebootElevatedPath,
			bytes.NewReader(buffer.Bytes()),
			nil); err != nil {
			return fmt.Errorf("Error uploading the Windows update check for reboot required elevated script: %s", err)
		}
		return nil
	})
	if err != nil {
		return err
	}

	ui.Say("Uploading the Windows update script...")
	err = comm.Upload(
		windowsUpdatePath,
		bytes.NewReader(windowsUpdatePs1),
		nil)
	if err != nil {
		return err
	}

	for {
		restartPending, err := p.update(ctx, ui, comm)
		if err != nil {
			return err
		}

		if !restartPending {
			return nil
		}

		err = p.restart(ctx, ui, comm)
		if err != nil {
			return err
		}
	}
}

func (p *Provisioner) update(ctx context.Context, ui packer.Ui, comm packer.Communicator) (bool, error) {
	ui.Say("Running Windows update...")
	var restartPending bool
	err := retry.Config{
		RetryDelay: func() time.Duration { return retryableDelay },
		Tries:      p.config.UpdateMaxRetries,
	}.Run(ctx, func(ctx context.Context) error {
		cmd := &packer.RemoteCmd{Command: elevatedCommand}
		err := cmd.RunWithUi(ctx, comm, ui)
		if err != nil {
			return err
		}
		var exitStatus = cmd.ExitStatus()
		switch exitStatus {
		case 0:
			return nil
		case 101:
			restartPending = true
			return nil
		default:
			return fmt.Errorf("Windows update script exited with non-zero exit status: %d", exitStatus)
		}
	})
	return restartPending, err
}

func (p *Provisioner) restart(ctx context.Context, ui packer.Ui, comm packer.Communicator) error {
	restartPending := true
	for restartPending {
		ui.Say("Restarting the machine...")
		err := p.retryable(ctx, func(ctx context.Context) error {
			cmd := &packer.RemoteCmd{Command: restartCommand}
			err := cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}
			exitStatus := cmd.ExitStatus()
			if exitStatus != 0 {
				return fmt.Errorf("Failed to restart the machine with exit status: %d", exitStatus)
			}
			return err
		})
		if err != nil {
			return err
		}

		ui.Say("Waiting for machine to become available...")
		err = p.retryable(ctx, func(ctx context.Context) error {
			// wait for the machine to reboot.
			cmd := &packer.RemoteCmd{Command: testRestartCommand}
			err := cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}
			exitStatus := cmd.ExitStatus()
			if exitStatus != 0 {
				return fmt.Errorf("Machine not yet available (exit status %d)", exitStatus)
			}
			cmd = &packer.RemoteCmd{Command: abortTestRestartCommand}
			err = cmd.RunWithUi(ctx, comm, ui)

			return err
		})
		if err != nil {
			return err
		}

		ui.Say("Checking for pending restart...")
		err = p.retryable(ctx, func(ctx context.Context) error {
			cmd := &packer.RemoteCmd{Command: pendingRebootElevatedCommand}
			err = cmd.RunWithUi(ctx, comm, ui)
			if err != nil {
				return err
			}

			exitStatus := cmd.ExitStatus()
			switch {
			case exitStatus == 0:
				restartPending = false
			case exitStatus == 101:
				restartPending = true
			default:
				return fmt.Errorf("Machine not yet available (exit status %d)", exitStatus)
			}

			return err
		})
		if err != nil {
			return err
		}

		if restartPending {
			ui.Say("Restart is still pending...")
		} else {
			ui.Say("Restart complete")
		}
	}

	return nil
}

// retryable will retry the given function over and over until a
// non-error is returned, RestartTimeout expires, or ctx is
// cancelled.
func (p *Provisioner) retryable(ctx context.Context, f func(ctx context.Context) error) error {
	return retry.Config{
		RetryDelay:   func() time.Duration { return retryableDelay },
		StartTimeout: p.config.RestartTimeout,
	}.Run(ctx, f)
}

func (p *Provisioner) windowsUpdateCommand() string {
	return fmt.Sprintf(
		"PowerShell -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand %s",
		base64.StdEncoding.EncodeToString(
			encodeUtf16Le(fmt.Sprintf(
				"%s%s%s -UpdateLimit %d",
				windowsUpdatePath,
				searchCriteriaArgument(p.config.SearchCriteria),
				filtersArgument(p.config.Filters),
				p.config.UpdateLimit))))
}

func (p *Provisioner) windowsUpdateCheckForRebootRequiredCommand() string {
	return fmt.Sprintf(
		"PowerShell -ExecutionPolicy Bypass -OutputFormat Text -EncodedCommand %s",
		base64.StdEncoding.EncodeToString(
			encodeUtf16Le(fmt.Sprintf(
				"%s -OnlyCheckForRebootRequired",
				windowsUpdatePath))))
}

func encodeUtf16Le(s string) []byte {
	d := utf16.Encode([]rune(s))
	b := make([]byte, len(d)*2)
	for i, r := range d {
		b[i*2] = byte(r)
		b[i*2+1] = byte(r >> 8)
	}
	return b
}

func searchCriteriaArgument(searchCriteria string) string {
	if searchCriteria == "" {
		return ""
	}

	var buffer bytes.Buffer

	buffer.WriteString(" -SearchCriteria ")
	buffer.WriteString(escapePowerShellString(searchCriteria))

	return buffer.String()
}

func filtersArgument(filters []string) string {
	if filters == nil {
		return ""
	}

	var buffer bytes.Buffer

	buffer.WriteString(" -Filters ")

	for i, filter := range filters {
		if i > 0 {
			buffer.WriteString(",")
		}
		buffer.WriteString(escapePowerShellString(filter))
	}

	return buffer.String()
}

func escapePowerShellString(value string) string {
	return fmt.Sprintf(
		"'%s'",
		// escape single quotes with another single quote.
		strings.Replace(value, "'", "''", -1))
}
<|endoftext|>


<commit_before>package license

import (
	"runtime"
	"testing"

	"github.com/admpub/log"
	"github.com/admpub/nging/v3/application/library/config"
	"github.com/stretchr/testify/assert"
	"golang.org/x/net/publicsuffix"
)

func init() {
	(&ServerURL{
		Tracker: `http://nging.coscms.com/product/script/nging/tracker.js`,
		Product: `http://nging.coscms.com/product/detail/nging`,
		License: `http://nging.coscms.com/product/license/nging`,
		Version: `http://nging.coscms.com/product/version/nging`,
	}).Apply()
	config.Version.BuildOS = runtime.GOOS
	config.Version.BuildArch = runtime.GOARCH
}

func TestLicenseDownload(t *testing.T) {
	err := Download(nil)
	if err != nil {
		panic(err)
	}
}

func TestLicenseLatestVersion(t *testing.T) {
	defer log.Close()
	_, err := LatestVersion(nil, false)
	if err != nil {
		panic(err)
	}
}

func TestLicenseValidateFromOfficial(t *testing.T) {
	err := validateFromOfficial(nil)
	if err != nil {
		panic(err)
	}
}

func TestLicenseEqDomain(t *testing.T) {
	defer log.Close()
	assert.True(t, EqDomain(`www.webx.top`, `webx.top`))

	domain, err := publicsuffix.EffectiveTLDPlusOne(`www.webx.top`)
	assert.Nil(t, err)
	assert.Equal(t, `webx.top`, domain)

	publicSuffix, icann := publicsuffix.PublicSuffix(`www.webx.top`)
	assert.True(t, icann)
	assert.Equal(t, `top`, publicSuffix)

	publicSuffix, icann = publicsuffix.PublicSuffix(`www.webx.x`)
	assert.False(t, icann)
	assert.Equal(t, `x`, publicSuffix)
}
<commit_msg>update<commit_after>package license

import (
	"runtime"
	"testing"

	"github.com/admpub/log"
	"github.com/admpub/nging/v3/application/library/config"
	"github.com/stretchr/testify/assert"
	"golang.org/x/net/publicsuffix"
)

func init() {
	(&ServerURL{
		Tracker: `http://nging.coscms.com/product/script/nging/tracker.js`,
		Product: `http://nging.coscms.com/product/detail/nging`,
		License: `http://nging.coscms.com/product/license/nging`,
		Version: `http://nging.coscms.com/product/version/nging`,
	}).Apply()
	config.Version.BuildOS = runtime.GOOS
	config.Version.BuildArch = runtime.GOARCH
}

func TestLicenseDownload(t *testing.T) {
	err := Download(nil)
	if err != nil {
		panic(err)
	}
}

func TestLicenseLatestVersion(t *testing.T) {
	defer log.Close()
	_, err := LatestVersion(nil, false)
	if err != nil {
		panic(err)
	}
}

func TestLicenseValidateFromOfficial(t *testing.T) {
	err := validateFromOfficial(nil)
	if err != nil {
		panic(err)
	}
}

func TestLicenseEqDomain(t *testing.T) {
	defer log.Close()
	assert.True(t, EqDomain(`www.webx.top`, `webx.top`))

	domain, err := publicsuffix.EffectiveTLDPlusOne(`www.webx.top`)
	assert.Nil(t, err)
	assert.Equal(t, `webx.top`, domain)

	domain, err = publicsuffix.EffectiveTLDPlusOne(`www.abc.com.cn`)
	assert.Nil(t, err)
	assert.Equal(t, `abc.com.cn`, domain)

	domain, err = publicsuffix.EffectiveTLDPlusOne(`com.cn`)
	assert.NotNil(t, err)
	assert.Equal(t, ``, domain)

	publicSuffix, icann := publicsuffix.PublicSuffix(`www.webx.top`)
	assert.True(t, icann)
	assert.Equal(t, `top`, publicSuffix)

	publicSuffix, icann = publicsuffix.PublicSuffix(`www.webx.x`)
	assert.False(t, icann)
	assert.Equal(t, `x`, publicSuffix)
}
<|endoftext|>


<commit_before>package veneur

import (
	"bytes"
	"compress/zlib"
	"encoding/json"
	"flag"
	"fmt"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stripe/veneur/tdigest"
)

const ε = .00002

var DebugMode bool

func TestMain(m *testing.M) {
	flag.Parse()
	DebugMode = flag.Lookup("test.v").Value.(flag.Getter).Get().(bool)
	os.Exit(m.Run())
}

// set up a boilerplate local config for later use
func localConfig() Config {
	return Config{
		APIHostname: "http://localhost",
		Debug:       DebugMode,
		Hostname:    "localhost",

		// Use a shorter interval for tests
		Interval:            50 * time.Millisecond,
		Key:                 "",
		MetricMaxLength:     4096,
		Percentiles:         []float64{.5, .75, .99},
		ReadBufferSizeBytes: 2097152,
		UDPAddr:             "localhost:8126",
		HTTPAddr:            "localhost:8127",
		ForwardAddr:         "http://localhost",
		NumWorkers:          96,

		// Use only one reader, so that we can run tests
		// on platforms which do not support SO_REUSEPORT
		NumReaders: 1,

		// Currently this points nowhere, which is intentional.
		// We don't need internal metrics for the tests, and they make testing
		// more complicated.
		StatsAddr:  "localhost:8125",
		Tags:       []string{},
		SentryDSN:  "",
		FlushLimit: 1024,
	}
}

// assertMetrics checks that all expected metrics are present
// and have the correct value
func assertMetrics(t *testing.T, metrics DDMetricsRequest, expectedMetrics map[string]float64) {
	// it doesn't count as accidentally quadratic if it's intentional
	for metricName, expectedValue := range expectedMetrics {
		assertMetric(t, metrics, metricName, expectedValue)
	}
}

func assertMetric(t *testing.T, metrics DDMetricsRequest, metricName string, value float64) {
	defer func() {
		if r := recover(); r != nil {
			assert.Fail(t, "error extracting metrics", r)
		}
	}()
	for _, metric := range metrics.Series {
		if metric.Name == metricName {
			assert.Equal(t, int(value+.5), int(metric.Value[0][1]+.5), fmt.Sprintf("Incorrect value for metric %s", metricName))
			return
		}
	}
	assert.Fail(t, "did not find expected metric", metricName)
}

// setupLocalServer creates a local server from the specified config
// and starts listening for requests. It returns the server for inspection.
func setupLocalServer(t *testing.T, config Config) Server {
	server, err := NewFromConfig(config)
	if err != nil {
		t.Fatal(err)
	}

	packetPool := &sync.Pool{
		New: func() interface{} {
			return make([]byte, config.MetricMaxLength)
		},
	}

	for i := 0; i < config.NumReaders; i++ {
		go func() {
			defer func() {
				if r := recover(); r != nil {
					assert.Fail(t, "reader panicked while reading from socket", err)
				}
			}()
			server.ReadSocket(packetPool, config.NumReaders != 1)
		}()
	}

	go server.HTTPServe()
	return server
}

// DDMetricsRequest represents the body of the POST request
// for sending metrics data to Datadog
type DDMetricsRequest struct {
	Series []DDMetric
}

func TestLocalServerUnaggregatedMetrics(t *testing.T) {
	expectedMetrics := map[string]float64{
		"a.b.c.max": 100,
		"a.b.c.min": 1,

		// Count is normalized by second
		// so 5 values/50ms = 100 values/s
		"a.b.c.count": 100,

		// tdigest approximation causes this to be off by 1
		"a.b.c.50percentile": 6,
		"a.b.c.75percentile": 42,
		"a.b.c.99percentile": 98,
	}

	remoteServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		var ddmetrics DDMetricsRequest
		err = json.NewDecoder(zr).Decode(&ddmetrics)
		if err != nil {
			t.Fatal(err)
		}
		assert.Equal(t, 6, len(ddmetrics.Series), "incorrect number of elements in the flushed series on the remote server")
		assertMetrics(t, ddmetrics, expectedMetrics)
		w.WriteHeader(http.StatusAccepted)
	}))
	config := localConfig()
	config.APIHostname = remoteServer.URL

	server := setupLocalServer(t, config)
	defer server.Shutdown()

	metricValues := []float64{1.0, 2.0, 7.0, 8.0, 100.0}

	for _, value := range metricValues {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "a.b.c",
				Type: "histogram",
			},
			Value:      value,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  true,
		})
	}
	server.Flush(config.Interval, config.FlushLimit)
}

func TestLocalServerMixedMetrics(t *testing.T) {

	// We can't be guaranteed that we will receive this exact stream
	// but we should expect that they represent the same underlying tdigest
	const ExpectedGobStream = "\r\xff\x87\x02\x01\x02\xff\x88\x00\x01\xff\x84\x00\x007\xff\x83\x03\x01\x01\bCentroid\x01\xff\x84\x00\x01\x03\x01\x04Mean\x01\b\x00\x01\x06Weight\x01\b\x00\x01\aSamples\x01\xff\x86\x00\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00/\xff\x88\x00\x05\x01\xfe\xf0?\x01\xfe\xf0?\x00\x01@\x01\xfe\xf0?\x00\x01\xfe\x1c@\x01\xfe\xf0?\x00\x01\xfe @\x01\xfe\xf0?\x00\x01\xfeY@\x01\xfe\xf0?\x00\x05\b\x00\xfeY@\x05\b\x00\xfe\xf0?\x05\b\x00\xfeY@"

	const ABCCountRaw = 5
	const ABCCountNormalized = 100

	expectedMetrics := map[string]float64{
		"x.y.z":     800,
		"a.b.c.max": 100,
		"a.b.c.min": 1,

		// Count is normalized by second
		// so 5 values/50ms = 100 values/s
		"a.b.c.count": ABCCountNormalized,
	}

	// Set up a remote server (the API that we're sending the data to)
	// e.g. Datadog
	remoteServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		var ddmetrics DDMetricsRequest

		err = json.NewDecoder(zr).Decode(&ddmetrics)
		if err != nil {
			t.Fatal(err)
		}
		assert.Equal(t, len(expectedMetrics), len(ddmetrics.Series), "incorrect number of elements in the flushed series on the remote server")
		assertMetrics(t, ddmetrics, expectedMetrics)
		w.WriteHeader(http.StatusAccepted)
	}))

	globalVeneur := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		type requestItem struct {
			Name      string      `json:"name"`
			Tags      interface{} `json:"tags"`
			Tagstring string      `json:"tagstring"`
			Type      string      `json:"type"`
			Value     []byte      `json:"value"`
		}

		var metrics []requestItem

		err = json.NewDecoder(zr).Decode(&metrics)
		if err != nil {
			t.Fatal(err)
		}

		assert.Equal(t, 1, len(metrics), "incorrect number of elements in the flushed series")

		tdExpected := tdigest.NewMerging(100, false)
		err = tdExpected.GobDecode([]byte(ExpectedGobStream))
		assert.NoError(t, err, "Should not have encountered error in decoding expected gob stream")

		td := tdigest.NewMerging(100, false)
		err = td.GobDecode(metrics[0].Value)
		assert.NoError(t, err, "Should not have encountered error in decoding gob stream")

		assert.Equal(t, expectedMetrics["a.b.c.min"], td.Min(), "Minimum value is incorrect")
		assert.Equal(t, expectedMetrics["a.b.c.max"], td.Max(), "Maximum value is incorrect")

		// The remote server receives the raw count, *not* the normalized count
		assert.InEpsilon(t, ABCCountRaw, td.Count(), ε)
		assert.Equal(t, tdExpected, td, "Underlying tdigest structure is incorrect")

		w.WriteHeader(http.StatusAccepted)
	}))

	config := localConfig()
	config.APIHostname = remoteServer.URL
	config.ForwardAddr = globalVeneur.URL
	config.NumWorkers = 1

	server := setupLocalServer(t, config)
	defer server.Shutdown()

	histogramValues := []float64{1.0, 2.0, 7.0, 8.0, 100.0}

	// Create non-local metrics that should be passed to the global veneur instance
	for _, value := range histogramValues {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "a.b.c",
				Type: "histogram",
			},
			Value:      value,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  false,
		})
	}

	const CountSize = 40
	for i := 0; i < CountSize; i++ {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "x.y.z",
				Type: "counter",
			},
			Value:      1.0,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  true,
		})
	}

	server.Flush(config.Interval, config.FlushLimit)
}

func TestSplitBytes(t *testing.T) {
	rand.Seed(time.Now().Unix())
	buf := make([]byte, 1000)

	for i := 0; i < 1000; i++ {
		// we construct a string of random length which is approximately 1/3rd A
		// and the other 2/3rds B
		buf = buf[:rand.Intn(cap(buf))]
		for i := range buf {
			if rand.Intn(3) == 0 {
				buf[i] = 'A'
			} else {
				buf[i] = 'B'
			}
		}
		checkBufferSplit(t, buf)
		buf = buf[:cap(buf)]
	}

	// also test pathological cases that the fuzz is unlikely to find
	checkBufferSplit(t, nil)
	checkBufferSplit(t, []byte{})
}

func checkBufferSplit(t *testing.T, buf []byte) {
	var testSplit [][]byte
	sb := NewSplitBytes(buf, 'A')
	for sb.Next() {
		testSplit = append(testSplit, sb.Chunk())
	}

	// now compare our split to the "real" implementation of split
	assert.EqualValues(t, bytes.Split(buf, []byte{'A'}), testSplit, "should have split %s correctly", buf)
}
<commit_msg>Increment HTTP ports for build server<commit_after>package veneur

import (
	"bytes"
	"compress/zlib"
	"encoding/json"
	"flag"
	"fmt"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stripe/veneur/tdigest"
)

const ε = .00002

var DebugMode bool

func TestMain(m *testing.M) {
	flag.Parse()
	DebugMode = flag.Lookup("test.v").Value.(flag.Getter).Get().(bool)
	os.Exit(m.Run())
}

// On the CI server, we can't be guaranteed that the port will be
// released immediately after the server is shut down. Instead, use
// a unique port for each test. As long as we don't have an insane number
// of integration tests, we should be fine.
var HttpAddrPort = 8127

var localHandler http.Handler

// set up a boilerplate local config for later use
func localConfig() Config {
  port := HttpAddrPort
  HttpAddrPort++

	return Config{
		APIHostname: "http://localhost",
		Debug:       DebugMode,
		Hostname:    "localhost",

		// Use a shorter interval for tests
		Interval:            50 * time.Millisecond,
		Key:                 "",
		MetricMaxLength:     4096,
		Percentiles:         []float64{.5, .75, .99},
		ReadBufferSizeBytes: 2097152,
		UDPAddr:             "localhost:8126",
		HTTPAddr:            fmt.Sprintf("localhost:%d", port),
		ForwardAddr:         "http://localhost",
		NumWorkers:          96,

		// Use only one reader, so that we can run tests
		// on platforms which do not support SO_REUSEPORT
		NumReaders: 1,

		// Currently this points nowhere, which is intentional.
		// We don't need internal metrics for the tests, and they make testing
		// more complicated.
		StatsAddr:  "localhost:8125",
		Tags:       []string{},
		SentryDSN:  "",
		FlushLimit: 1024,
	}
}

// assertMetrics checks that all expected metrics are present
// and have the correct value
func assertMetrics(t *testing.T, metrics DDMetricsRequest, expectedMetrics map[string]float64) {
	// it doesn't count as accidentally quadratic if it's intentional
	for metricName, expectedValue := range expectedMetrics {
		assertMetric(t, metrics, metricName, expectedValue)
	}
}

func assertMetric(t *testing.T, metrics DDMetricsRequest, metricName string, value float64) {
	defer func() {
		if r := recover(); r != nil {
			assert.Fail(t, "error extracting metrics", r)
		}
	}()
	for _, metric := range metrics.Series {
		if metric.Name == metricName {
			assert.Equal(t, int(value+.5), int(metric.Value[0][1]+.5), fmt.Sprintf("Incorrect value for metric %s", metricName))
			return
		}
	}
	assert.Fail(t, "did not find expected metric", metricName)
}

// setupLocalServer creates a local server from the specified config
// and starts listening for requests. It returns the server for inspection.
func setupLocalServer(t *testing.T, config Config) Server {
	server, err := NewFromConfig(config)
	if err != nil {
		t.Fatal(err)
	}

	packetPool := &sync.Pool{
		New: func() interface{} {
			return make([]byte, config.MetricMaxLength)
		},
	}

	for i := 0; i < config.NumReaders; i++ {
		go func() {
			defer func() {
				if r := recover(); r != nil {
					assert.Fail(t, "reader panicked while reading from socket", err)
				}
			}()
			server.ReadSocket(packetPool, config.NumReaders != 1)
		}()
	}

	go server.HTTPServe()
	return server
}

// DDMetricsRequest represents the body of the POST request
// for sending metrics data to Datadog
type DDMetricsRequest struct {
	Series []DDMetric
}

func TestLocalServerUnaggregatedMetrics(t *testing.T) {
	expectedMetrics := map[string]float64{
		"a.b.c.max": 100,
		"a.b.c.min": 1,

		// Count is normalized by second
		// so 5 values/50ms = 100 values/s
		"a.b.c.count": 100,

		// tdigest approximation causes this to be off by 1
		"a.b.c.50percentile": 6,
		"a.b.c.75percentile": 42,
		"a.b.c.99percentile": 98,
	}

	remoteServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		var ddmetrics DDMetricsRequest
		err = json.NewDecoder(zr).Decode(&ddmetrics)
		if err != nil {
			t.Fatal(err)
		}
		assert.Equal(t, 6, len(ddmetrics.Series), "incorrect number of elements in the flushed series on the remote server")
		assertMetrics(t, ddmetrics, expectedMetrics)
		w.WriteHeader(http.StatusAccepted)
	}))
	config := localConfig()
	config.APIHostname = remoteServer.URL

	server := setupLocalServer(t, config)
	defer server.Shutdown()

	metricValues := []float64{1.0, 2.0, 7.0, 8.0, 100.0}

	for _, value := range metricValues {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "a.b.c",
				Type: "histogram",
			},
			Value:      value,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  true,
		})
	}
	server.Flush(config.Interval, config.FlushLimit)
}

func TestLocalServerMixedMetrics(t *testing.T) {

	// We can't be guaranteed that we will receive this exact stream
	// but we should expect that they represent the same underlying tdigest
	const ExpectedGobStream = "\r\xff\x87\x02\x01\x02\xff\x88\x00\x01\xff\x84\x00\x007\xff\x83\x03\x01\x01\bCentroid\x01\xff\x84\x00\x01\x03\x01\x04Mean\x01\b\x00\x01\x06Weight\x01\b\x00\x01\aSamples\x01\xff\x86\x00\x00\x00\x17\xff\x85\x02\x01\x01\t[]float64\x01\xff\x86\x00\x01\b\x00\x00/\xff\x88\x00\x05\x01\xfe\xf0?\x01\xfe\xf0?\x00\x01@\x01\xfe\xf0?\x00\x01\xfe\x1c@\x01\xfe\xf0?\x00\x01\xfe @\x01\xfe\xf0?\x00\x01\xfeY@\x01\xfe\xf0?\x00\x05\b\x00\xfeY@\x05\b\x00\xfe\xf0?\x05\b\x00\xfeY@"

	const ABCCountRaw = 5
	const ABCCountNormalized = 100

	expectedMetrics := map[string]float64{
		"x.y.z":     800,
		"a.b.c.max": 100,
		"a.b.c.min": 1,

		// Count is normalized by second
		// so 5 values/50ms = 100 values/s
		"a.b.c.count": ABCCountNormalized,
	}

	// Set up a remote server (the API that we're sending the data to)
	// e.g. Datadog
	remoteServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		var ddmetrics DDMetricsRequest

		err = json.NewDecoder(zr).Decode(&ddmetrics)
		if err != nil {
			t.Fatal(err)
		}
		assert.Equal(t, len(expectedMetrics), len(ddmetrics.Series), "incorrect number of elements in the flushed series on the remote server")
		assertMetrics(t, ddmetrics, expectedMetrics)
		w.WriteHeader(http.StatusAccepted)
	}))

	globalVeneur := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		zr, err := zlib.NewReader(r.Body)
		if err != nil {
			t.Fatal(err)
		}

		type requestItem struct {
			Name      string      `json:"name"`
			Tags      interface{} `json:"tags"`
			Tagstring string      `json:"tagstring"`
			Type      string      `json:"type"`
			Value     []byte      `json:"value"`
		}

		var metrics []requestItem

		err = json.NewDecoder(zr).Decode(&metrics)
		if err != nil {
			t.Fatal(err)
		}

		assert.Equal(t, 1, len(metrics), "incorrect number of elements in the flushed series")

		tdExpected := tdigest.NewMerging(100, false)
		err = tdExpected.GobDecode([]byte(ExpectedGobStream))
		assert.NoError(t, err, "Should not have encountered error in decoding expected gob stream")

		td := tdigest.NewMerging(100, false)
		err = td.GobDecode(metrics[0].Value)
		assert.NoError(t, err, "Should not have encountered error in decoding gob stream")

		assert.Equal(t, expectedMetrics["a.b.c.min"], td.Min(), "Minimum value is incorrect")
		assert.Equal(t, expectedMetrics["a.b.c.max"], td.Max(), "Maximum value is incorrect")

		// The remote server receives the raw count, *not* the normalized count
		assert.InEpsilon(t, ABCCountRaw, td.Count(), ε)
		assert.Equal(t, tdExpected, td, "Underlying tdigest structure is incorrect")

		w.WriteHeader(http.StatusAccepted)
	}))

	config := localConfig()
	config.APIHostname = remoteServer.URL
	config.ForwardAddr = globalVeneur.URL
	config.NumWorkers = 1

	server := setupLocalServer(t, config)
	defer server.Shutdown()

	histogramValues := []float64{1.0, 2.0, 7.0, 8.0, 100.0}

	// Create non-local metrics that should be passed to the global veneur instance
	for _, value := range histogramValues {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "a.b.c",
				Type: "histogram",
			},
			Value:      value,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  false,
		})
	}

	const CountSize = 40
	for i := 0; i < CountSize; i++ {
		server.Workers[0].ProcessMetric(&UDPMetric{
			MetricKey: MetricKey{
				Name: "x.y.z",
				Type: "counter",
			},
			Value:      1.0,
			Digest:     12345,
			SampleRate: 1.0,
			LocalOnly:  true,
		})
	}

	server.Flush(config.Interval, config.FlushLimit)
}

func TestSplitBytes(t *testing.T) {
	rand.Seed(time.Now().Unix())
	buf := make([]byte, 1000)

	for i := 0; i < 1000; i++ {
		// we construct a string of random length which is approximately 1/3rd A
		// and the other 2/3rds B
		buf = buf[:rand.Intn(cap(buf))]
		for i := range buf {
			if rand.Intn(3) == 0 {
				buf[i] = 'A'
			} else {
				buf[i] = 'B'
			}
		}
		checkBufferSplit(t, buf)
		buf = buf[:cap(buf)]
	}

	// also test pathological cases that the fuzz is unlikely to find
	checkBufferSplit(t, nil)
	checkBufferSplit(t, []byte{})
}

func checkBufferSplit(t *testing.T, buf []byte) {
	var testSplit [][]byte
	sb := NewSplitBytes(buf, 'A')
	for sb.Next() {
		testSplit = append(testSplit, sb.Chunk())
	}

	// now compare our split to the "real" implementation of split
	assert.EqualValues(t, bytes.Split(buf, []byte{'A'}), testSplit, "should have split %s correctly", buf)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"testing"
	"time"
)

func TestServer(t *testing.T) {
	go StartServer()
	time.Sleep(100 * time.Millisecond)
	r := Get("/api/auth", t)
	if r != 405 {
		t.Errorf("GET /api/auth did not return 405, instead returned %d\n", r)
	}

	r = Get("/api/user", t)
	if r != 404 {
		t.Errorf("GET /api/user did not return 200, instead returned %d\n", r)
	}

	r = Get("/api/message", t)
	if r != 200 {
		t.Errorf("GET /api/message did not return 200, instead returned %d\n", r)
	}

}

func Get(path string, t *testing.T) int {
	get_url := fmt.Sprintf("http://127.0.0.1:8080%s", path)
	res, err := http.Get(get_url)
	if err != nil {
		t.Errorf(err.Error())
		return 0
	}

	fmt.Printf("GET %s: %d\n", path, res.StatusCode)
	return res.StatusCode
}
<commit_msg>Add testing for PUT /api/user<commit_after>package main

import (
	"fmt"
	"net/http"
	"strings"
	"testing"
	"time"
)

func TestServer(t *testing.T) {
	go StartServer()
	time.Sleep(100 * time.Millisecond)
	r := Get("/api/auth", t)
	if r != 405 {
		t.Errorf("GET /api/auth did not return 405, instead returned %d\n", r)
	}

	r = Get("/api/user", t)
	if r != 404 {
		t.Errorf("GET /api/user did not return 200, instead returned %d\n", r)
	}

	r = Get("/api/message", t)
	if r != 200 {
		t.Errorf("GET /api/message did not return 200, instead returned %d\n", r)
	}

	r = Put("/api/user", "{\"id\": 123, \"username\":\"asdf\", \"password\": \"fdsa\"}", t)
	if r != 201 {
		t.Errorf("PUT /api/user did not return 201, instead returned %d\n", r)
	}

}

func Get(path string, t *testing.T) int {
	get_url := fmt.Sprintf("http://127.0.0.1:8080%s", path)
	res, err := http.Get(get_url)
	if err != nil {
		t.Errorf(err.Error())
		return 0
	}
	defer res.Body.Close()

	fmt.Printf("GET %s: %d\n", path, res.StatusCode)
	return res.StatusCode
}

func Post(path, body string, t *testing.T) int {
	post_url := fmt.Sprintf("http://127.0.0.1:8080%s", path)
	bodyType := "application/json"
	res, err := http.Post(post_url, bodyType, strings.NewReader(body))
	if err != nil {
		t.Errorf(err.Error())
		return 0
	}
	defer res.Body.Close()

	fmt.Printf("POST %s: %d\n", path, res.StatusCode)
	return res.StatusCode
}

func Put(path, body string, t *testing.T) int {
	put_url := fmt.Sprintf("http://127.0.0.1:8080%s", path)
	bodyType := "application/json"
	req, err := http.NewRequest("PUT", put_url, strings.NewReader(body))
	if err != nil {
		t.Errorf(err.Error())
		return 0
	}

	req.Header.Add("Content-Type", bodyType)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		t.Errorf(err.Error())
		return 0
	}
	defer res.Body.Close()

	fmt.Printf("PUT %s: %d\n", path, res.StatusCode)
	return res.StatusCode
}
<|endoftext|>


<commit_before>package goredis

import (
	"testing"
)

func TestBgRewriteAof(t *testing.T) {
	if err := r.BgRewriteAof(); err != nil {
		t.Error(err)
	}
}

func TestBgSave(t *testing.T) {
	if err := r.BgSave(); err != nil {
		t.Error(err)
	}
}

func TestClientList(t *testing.T) {
	_, err := r.ClientList()
	if err != nil {
		t.Error(err)
	}
}

func TestDBSize(t *testing.T) {
	r.FlushDB()
	n, err := r.DBSize()
	if err != nil {
		t.Error(err)
	}
	if n != 0 {
		t.Fail()
	}
}
<commit_msg>add more server test case<commit_after>package goredis

import (
	"testing"
)

func TestBgRewriteAof(t *testing.T) {
	if err := r.BgRewriteAof(); err != nil {
		t.Error(err)
	}
}

func TestBgSave(t *testing.T) {
	if err := r.BgSave(); err != nil {
		t.Error(err)
	}
}

func TestClientList(t *testing.T) {
	_, err := r.ClientList()
	if err != nil {
		t.Error(err)
	}
}

func TestDBSize(t *testing.T) {
	r.FlushDB()
	n, err := r.DBSize()
	if err != nil {
		t.Error(err)
	}
	if n != 0 {
		t.Fail()
	}
}

func TestFlushAll(t *testing.T) {
	if err := r.FlushAll(); err != nil {
		t.Error(err)
	}
}

func TestFlushDB(t *testing.T) {
	if err := r.FlushDB(); err != nil {
		t.Error(err)
	}
}

func TestLastSave(t *testing.T) {
	r.Save()
	if timestamp, err := r.LastSave(); err != nil {
		t.Error(err)
	} else if timestamp <= 0 {
		t.Fail()
	}
}

func TestSave(t *testing.T) {
	if err := r.Save(); err != nil {
		t.Error(err)
	}
}

func TestTime(t *testing.T) {
	tt, err := r.Time()
	if err != nil {
		t.Error(err)
	}
	if len(tt) != 2 {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package gotcp

import (
	"fmt"
	"net"
	"testing"
	"time"
)

// test tips
/******************************************************/

var OnConnectInfo, OnMessageInfo, OnCloseInfo, OnIOErrorInfo string

/******************************************************/

// delegate
/******************************************************/
type Delegate struct{}

func (this *Delegate) OnConnect(c *Conn) bool {
	p, err := c.AsyncReadPacket(5 * time.Second)
	if err != nil {
		return false
	}

	OnConnectInfo = fmt.Sprintf("OnConnect[%v,%v,%v]", p.GetLen(), p.GetType(), string(p.GetData()))

	fmt.Printf("OnConnect[%v,%v,%v]\n", p.GetLen(), p.GetType(), string(p.GetData()))
	return true
}

func (this *Delegate) OnMessage(c *Conn, p *Packet) bool {
	OnMessageInfo = fmt.Sprintf("OnMessage[%v,%v,%v]", p.GetLen(), p.GetType(), string(p.GetData()))
	fmt.Println(OnMessageInfo)

	if string(p.GetData()) == "logout" {
		c.WritePacket(NewPacket(888, []byte("ok")))
		return false
	}

	c.AsyncWritePacket(NewPacket(999, []byte(string(p.GetData())+",ok")), 5*time.Second)

	return true
}

func (this *Delegate) OnClose(c *Conn) {
	OnCloseInfo = fmt.Sprintf("OnClose[%v]", c.IsClosed())
	fmt.Println(OnCloseInfo)
}

func (this *Delegate) OnIOError(c *Conn, err error) {
	if err != nil {
		OnIOErrorInfo = fmt.Sprintf("OnIOError[%v]", err)
	}
	fmt.Println(OnIOErrorInfo)
}

/******************************************************/

func simulateClient(t *testing.T) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8989")
	conn, _ := net.DialTCP("tcp", nil, tcpAddr)

	// OnConnect
	conn.Write(NewPacket(777, []byte("login")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnConnectInfo != "OnConnect[13,777,login]" {
		t.Fatal()
	}

	// OnMessage
	conn.Write(NewPacket(666, []byte("helloworld")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnMessageInfo != "OnMessage[18,666,helloworld]" {
		t.Fatal()
	}

	retPacket, _ := ReadPacket(conn, 2048)
	if retPacket.GetLen() != 21 || retPacket.GetType() != 999 || string(retPacket.GetData()) != "helloworld,ok" {
		t.Fatal()
	}

	// OnClose
	conn.Write(NewPacket(555, []byte("logout")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnMessageInfo != "OnMessage[14,555,logout]" {
		t.Fatal()
	}

	retPacket, _ = ReadPacket(conn, 2048)
	if retPacket.GetLen() != 10 || retPacket.GetType() != 888 || string(retPacket.GetData()) != "ok" {
		t.Fatal()
	}

	if OnCloseInfo != "OnClose[true]" {
		t.Fatal()
	}

	// OnIOError
	if OnIOErrorInfo != fmt.Sprintf("OnIOError[%v]", ReadPacketError) {
		t.Fatal()
	}
}

func TestServer(t *testing.T) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8989")
	listener, _ := net.ListenTCP("tcp", tcpAddr)

	config := &Config{
		AcceptTimeout:          5 * time.Second,
		ReadTimeout:            5 * time.Second,
		WriteTimeout:           5 * time.Second,
		MaxPacketLength:        int32(2048),
		SendPacketChanLimit:    int32(10),
		ReceivePacketChanLimit: int32(10),
	}
	delegate := &Delegate{}

	svr := NewServer(config, delegate)
	go svr.Start(listener)

	time.Sleep(time.Second)

	simulateClient(t)

	svr.Stop()
}
<commit_msg>Update<commit_after>package gotcp

import (
	"fmt"
	"net"
	"testing"
	"time"
)

// test tips
/******************************************************/

var OnConnectTip, OnMessageTip, OnCloseTip, OnIOErrorTip string

/******************************************************/

// delegate
/******************************************************/
type Delegate struct{}

func (this *Delegate) OnConnect(c *Conn) bool {
	p, err := c.AsyncReadPacket(5 * time.Second)
	if err != nil {
		return false
	}

	OnConnectTip = fmt.Sprintf("OnConnect[%v,%v,%v]", p.GetLen(), p.GetType(), string(p.GetData()))

	fmt.Println(OnConnectTip)
	return true
}

func (this *Delegate) OnMessage(c *Conn, p *Packet) bool {
	OnMessageTip = fmt.Sprintf("OnMessage[%v,%v,%v]", p.GetLen(), p.GetType(), string(p.GetData()))
	fmt.Println(OnMessageTip)

	if string(p.GetData()) == "logout" {
		c.WritePacket(NewPacket(888, []byte("ok")))
		return false
	}

	c.AsyncWritePacket(NewPacket(999, []byte(string(p.GetData())+",ok")), 5*time.Second)

	return true
}

func (this *Delegate) OnClose(c *Conn) {
	OnCloseTip = fmt.Sprintf("OnClose[%v]", c.IsClosed())
	fmt.Println(OnCloseTip)
}

func (this *Delegate) OnIOError(c *Conn, err error) {
	if err != nil {
		OnIOErrorTip = fmt.Sprintf("OnIOError[%v]", err)
	}
	fmt.Println(OnIOErrorTip)
}

/******************************************************/

func simulateClient(t *testing.T) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8989")
	conn, _ := net.DialTCP("tcp", nil, tcpAddr)

	// OnConnect
	conn.Write(NewPacket(777, []byte("login")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnConnectTip != "OnConnect[13,777,login]" {
		t.Fatal()
	}

	// OnMessage
	conn.Write(NewPacket(666, []byte("helloworld")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnMessageTip != "OnMessage[18,666,helloworld]" {
		t.Fatal()
	}

	retPacket, _ := ReadPacket(conn, 2048)
	if retPacket.GetLen() != 21 || retPacket.GetType() != 999 || string(retPacket.GetData()) != "helloworld,ok" {
		t.Fatal()
	}

	// OnClose
	conn.Write(NewPacket(555, []byte("logout")).Serialize())
	time.Sleep(100 * time.Millisecond)
	if OnMessageTip != "OnMessage[14,555,logout]" {
		t.Fatal()
	}

	retPacket, _ = ReadPacket(conn, 2048)
	if retPacket.GetLen() != 10 || retPacket.GetType() != 888 || string(retPacket.GetData()) != "ok" {
		t.Fatal()
	}

	if OnCloseTip != "OnClose[true]" {
		t.Fatal()
	}

	// OnIOError
	if OnIOErrorTip != fmt.Sprintf("OnIOError[%v]", ReadPacketError) {
		t.Fatal()
	}
}

func TestServer(t *testing.T) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", "127.0.0.1:8989")
	listener, _ := net.ListenTCP("tcp", tcpAddr)

	config := &Config{
		AcceptTimeout:          5 * time.Second,
		ReadTimeout:            5 * time.Second,
		WriteTimeout:           5 * time.Second,
		MaxPacketLength:        int32(2048),
		SendPacketChanLimit:    int32(10),
		ReceivePacketChanLimit: int32(10),
	}
	delegate := &Delegate{}

	svr := NewServer(config, delegate)
	go svr.Start(listener)

	time.Sleep(time.Second)

	simulateClient(t)

	svr.Stop()
}
<|endoftext|>


<commit_before>package service

import (
	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/errors"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/simonleung8/flags"
	"github.com/simonleung8/flags/flag"
)

type PurgeServiceInstance struct {
	ui          terminal.UI
	serviceRepo api.ServiceRepository
}

func init() {
	command_registry.Register(&PurgeServiceInstance{})
}

func (cmd *PurgeServiceInstance) MetaData() command_registry.CommandMetadata {
	fs := make(map[string]flags.FlagSet)
	fs["f"] = &cliFlags.BoolFlag{Name: "f", Usage: T("Force deletion without confirmation")}

	return command_registry.CommandMetadata{
		Name:        "purge-service-instance",
		Description: T("Recursively remove a service instance and child objects from Cloud Foundry database without making requests to a service broker"),
		Usage:       T("CF_NAME purge-service-instance SERVICE_INSTANCE") + "\n\n" + cmd.scaryWarningMessage(),
		Flags:       fs,
	}
}

func (cmd *PurgeServiceInstance) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) (reqs []requirements.Requirement, err error) {
	if len(fc.Args()) != 1 {
		cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + command_registry.Commands.CommandUsage("purge-service-instance"))
	}

	reqs = []requirements.Requirement{requirementsFactory.NewLoginRequirement()}
	return
}

func (cmd *PurgeServiceInstance) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
	cmd.ui = deps.Ui
	cmd.serviceRepo = deps.RepoLocator.GetServiceRepository()
	return cmd
}

func (cmd *PurgeServiceInstance) scaryWarningMessage() string {
	return T(`WARNING: This operation assumes that the service broker responsible for this service instance is no longer available or is not responding with a 200 or 410, and the service instance has been deleted, leaving orphan records in Cloud Foundry's database. All knowledge of the service instance will be removed from Cloud Foundry, including service bindings and service keys.`)
}

func (cmd *PurgeServiceInstance) Execute(c flags.FlagContext) {
	instanceName := c.Args()[0]

	instance, apiErr := cmd.serviceRepo.FindInstanceByName(instanceName)

	switch apiErr.(type) {
	case nil:
	case *errors.ModelNotFoundError:
		cmd.ui.Warn(T("Service instance {{.InstanceName}} not found",
			map[string]interface{}{"InstanceName": instanceName},
		))
		return
	default:
		cmd.ui.Failed(apiErr.Error())
	}

	confirmed := c.Bool("f")
	if !confirmed {
		cmd.ui.Warn(cmd.scaryWarningMessage())
		confirmed = cmd.ui.Confirm(T("Really purge service instance {{.InstanceName}} from Cloud Foundry?",
			map[string]interface{}{"InstanceName": instanceName},
		))
	}

	if !confirmed {
		return
	}
	cmd.ui.Say(T("Purging service {{.InstanceName}}...", map[string]interface{}{"InstanceName": instanceName}))
	err := cmd.serviceRepo.PurgeServiceInstance(instance)
	if err != nil {
		cmd.ui.Failed(err.Error())
	}

	cmd.ui.Ok()
}
<commit_msg>purge-service-instance: Remove named return args<commit_after>package service

import (
	"github.com/cloudfoundry/cli/cf/api"
	"github.com/cloudfoundry/cli/cf/command_registry"
	"github.com/cloudfoundry/cli/cf/errors"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
	"github.com/simonleung8/flags"
	"github.com/simonleung8/flags/flag"
)

type PurgeServiceInstance struct {
	ui          terminal.UI
	serviceRepo api.ServiceRepository
}

func init() {
	command_registry.Register(&PurgeServiceInstance{})
}

func (cmd *PurgeServiceInstance) MetaData() command_registry.CommandMetadata {
	fs := make(map[string]flags.FlagSet)
	fs["f"] = &cliFlags.BoolFlag{Name: "f", Usage: T("Force deletion without confirmation")}

	return command_registry.CommandMetadata{
		Name:        "purge-service-instance",
		Description: T("Recursively remove a service instance and child objects from Cloud Foundry database without making requests to a service broker"),
		Usage:       T("CF_NAME purge-service-instance SERVICE_INSTANCE") + "\n\n" + cmd.scaryWarningMessage(),
		Flags:       fs,
	}
}

func (cmd *PurgeServiceInstance) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
	if len(fc.Args()) != 1 {
		cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + command_registry.Commands.CommandUsage("purge-service-instance"))
	}

	return []requirements.Requirement{
		requirementsFactory.NewLoginRequirement(),
	}, nil
}

func (cmd *PurgeServiceInstance) SetDependency(deps command_registry.Dependency, pluginCall bool) command_registry.Command {
	cmd.ui = deps.Ui
	cmd.serviceRepo = deps.RepoLocator.GetServiceRepository()
	return cmd
}

func (cmd *PurgeServiceInstance) scaryWarningMessage() string {
	return T(`WARNING: This operation assumes that the service broker responsible for this service instance is no longer available or is not responding with a 200 or 410, and the service instance has been deleted, leaving orphan records in Cloud Foundry's database. All knowledge of the service instance will be removed from Cloud Foundry, including service bindings and service keys.`)
}

func (cmd *PurgeServiceInstance) Execute(c flags.FlagContext) {
	instanceName := c.Args()[0]

	instance, apiErr := cmd.serviceRepo.FindInstanceByName(instanceName)

	switch apiErr.(type) {
	case nil:
	case *errors.ModelNotFoundError:
		cmd.ui.Warn(T("Service instance {{.InstanceName}} not found",
			map[string]interface{}{"InstanceName": instanceName},
		))
		return
	default:
		cmd.ui.Failed(apiErr.Error())
	}

	confirmed := c.Bool("f")
	if !confirmed {
		cmd.ui.Warn(cmd.scaryWarningMessage())
		confirmed = cmd.ui.Confirm(T("Really purge service instance {{.InstanceName}} from Cloud Foundry?",
			map[string]interface{}{"InstanceName": instanceName},
		))
	}

	if !confirmed {
		return
	}
	cmd.ui.Say(T("Purging service {{.InstanceName}}...", map[string]interface{}{"InstanceName": instanceName}))
	err := cmd.serviceRepo.PurgeServiceInstance(instance)
	if err != nil {
		cmd.ui.Failed(err.Error())
	}

	cmd.ui.Ok()
}
<|endoftext|>


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

// bench-uploader uploads bench results to cloud storage.
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/coreos/dbtester/remotestorage"
	"github.com/spf13/cobra"
)

// TODO: vendor gRPC and combine this into bench
// Currently, we get:
// panic: http: multiple registrations for /debug/requests

var (
	Command = &cobra.Command{
		Use:   "bench-uploader",
		Short: "Uploads to cloud storage.",
		RunE:  CommandFunc,
	}
)

var (
	from        string
	to          string
	isDirectory bool

	googleCloudProjectName        string
	googleCloudStorageJSONKeyPath string
	googleCloudStorageBucketName  string
)

func init() {
	cobra.EnablePrefixMatching = true
}

func init() {
	Command.PersistentFlags().StringVar(&from, "from", "", "file to upload.")
	Command.PersistentFlags().StringVar(&to, "to", "", "file path to upload.")
	Command.PersistentFlags().BoolVar(&isDirectory, "directory", false, "'true' if uploading directory.")
	Command.PersistentFlags().StringVar(&googleCloudProjectName, "google-cloud-project-name", "", "Google cloud project name.")
	Command.PersistentFlags().StringVar(&googleCloudStorageJSONKeyPath, "google-cloud-storage-json-key-path", "", "Path of JSON key file.")
	Command.PersistentFlags().StringVar(&googleCloudStorageBucketName, "google-cloud-storage-bucket-name", "", "Google cloud storage bucket name.")
}

func main() {
	log.Printf("bench-uploader started at %s\n", time.Now().String()[:19])
	if err := Command.Execute(); err != nil {
		fmt.Fprintln(os.Stdout, err)
		os.Exit(1)
	}
	log.Printf("bench-uploader ended at %s\n", time.Now().String()[:19])
}

func CommandFunc(cmd *cobra.Command, args []string) error {
	kbs, err := ioutil.ReadFile(googleCloudStorageJSONKeyPath)
	if err != nil {
		return fmt.Errorf("error when opening %s(%v)", googleCloudStorageJSONKeyPath, err)
	}
	u, err := remotestorage.NewGoogleCloudStorage(kbs, googleCloudProjectName)
	if err != nil {
		return fmt.Errorf("error when NewGoogleCloudStorage %s(%v)", googleCloudProjectName, err)
	}
	if !isDirectory {
		if err := u.UploadFile(googleCloudStorageBucketName, from, to); err != nil {
			return err
		}
	} else {
		if err := u.UploadDir(googleCloudStorageBucketName, from, to); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>update<commit_after>// Copyright 2016 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// bench-uploader uploads bench results to cloud storage.
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/coreos/dbtester/remotestorage"
	"github.com/spf13/cobra"
)

// TODO: vendor gRPC and combine this into bench
// Currently, we get:
// panic: http: multiple registrations for /debug/requests

var (
	Command = &cobra.Command{
		Use:   "bench-uploader",
		Short: "Uploads to cloud storage.",
		RunE:  CommandFunc,
	}
)

var (
	from        string
	to          string
	isDirectory bool

	googleCloudProjectName        string
	googleCloudStorageJSONKeyPath string
	googleCloudStorageBucketName  string
)

func init() {
	cobra.EnablePrefixMatching = true
}

func init() {
	Command.PersistentFlags().StringVar(&from, "from", "", "file to upload.")
	Command.PersistentFlags().StringVar(&to, "to", "", "file path to upload.")
	Command.PersistentFlags().BoolVar(&isDirectory, "directory", false, "'true' if uploading directory.")
	Command.PersistentFlags().StringVar(&googleCloudProjectName, "google-cloud-project-name", "", "Google cloud project name.")
	Command.PersistentFlags().StringVar(&googleCloudStorageJSONKeyPath, "google-cloud-storage-json-key-path", "", "Path of JSON key file.")
	Command.PersistentFlags().StringVar(&googleCloudStorageBucketName, "google-cloud-storage-bucket-name", "", "Google cloud storage bucket name.")
}

func main() {
	log.Printf("bench-uploader started at %s\n", time.Now().String()[:19])
	if err := Command.Execute(); err != nil {
		fmt.Fprintln(os.Stdout, err)
		os.Exit(1)
	}
	log.Printf("bench-uploader ended at %s\n", time.Now().String()[:19])
}

func CommandFunc(cmd *cobra.Command, args []string) error {
	kbs, err := ioutil.ReadFile(googleCloudStorageJSONKeyPath)
	if err != nil {
		return fmt.Errorf("error when opening key %s(%v)", googleCloudStorageJSONKeyPath, err)
	}
	u, err := remotestorage.NewGoogleCloudStorage(kbs, googleCloudProjectName)
	if err != nil {
		return fmt.Errorf("error when NewGoogleCloudStorage %s(%v)", googleCloudProjectName, err)
	}
	if !isDirectory {
		if err := u.UploadFile(googleCloudStorageBucketName, from, to); err != nil {
			return err
		}
	} else {
		if err := u.UploadDir(googleCloudStorageBucketName, from, to); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>