<commit_before>package hal

// Broker is an instance of a broker that can send/receive events.
type Broker interface {
	Name() string
	Send(Evt)
	RoomIdToName(string) string
	RoomNameToId(string) string
	UserIdToName(string) string
	UserNameToId(string) string
	Stream(out chan *Evt)
}

// BrokerConfig is used to create named instances of brokers using NewBroker()
type BrokerConfig interface {
	NewBroker(name string) Broker
}

// Brokers is a stack of brokers.
type Brokers []Broker

// Has returns true if the handle's stack contains a broker with the provided name.
func (bs Brokers) Has(name string) bool {
	for _, b := range bs {
		if b.Name() == name {
			return true
		}
	}

	return false
}

// Push puts a broker at the top of the stack.
func (bs Brokers) Push(b Broker) {
	bs = append(bs, b)
}

// Pop removes the broker from the top of the stack and returns it.
func (bs Brokers) Pop() Broker {
	if len(bs) == 0 {
		panic("Pop() called on empty broker list.")
	}

	out := bs[len(bs)-1]

	bs = bs[0 : len(bs)-2]

	return out
}

// First returns the first broker on the stack.
func (bs Brokers) First() Broker {
	if len(bs) == 0 {
		panic("First() called on empty broker list.")
	}

	return bs[0]
}

// Last returns the last broker on the stack.
func (bs Brokers) Last() Broker {
	if len(bs) == 0 {
		panic("Last() called on empty broker list.")
	}

	return bs[len(bs)-1]
}

// Previous finds the provided broker by matching its name against
// an item in the broker list and returns the item before it in that list.
func (bs Brokers) Previous(current Broker) Broker {
	if len(bs) == 0 {
		panic("Previous() called on empty broker list.")
	}
	if len(bs) == 1 {
		panic("Previous() called on a broker list with only one item.")
	}

	for i, b := range bs {
		if b.Name() == current.Name() {
			if i == 0 {
				panic("Previous() called on the first entry in the broker list.")
			}

			return bs[i-1]
		}
	}

	panic("Couldn't find a previous broker.")
}

// Clone returns a shallow-cloned Brokers list.
func (bs Brokers) Clone() Brokers {
	clone := make(Brokers, len(bs))
	copy(clone, bs)
	return clone
}
<commit_msg>add a TODO<commit_after>package hal

// Broker is an instance of a broker that can send/receive events.
type Broker interface {
	Name() string
	Send(Evt)
	RoomIdToName(string) string
	RoomNameToId(string) string
	UserIdToName(string) string
	UserNameToId(string) string
	Stream(out chan *Evt)
}

// BrokerConfig is used to create named instances of brokers using NewBroker()
type BrokerConfig interface {
	NewBroker(name string) Broker
}

// TODO: consider reverting all this Broker stack stuff now that forwarding
// has proven to be a bad idea (that led to a better one)

// Brokers is a stack of brokers.
type Brokers []Broker

// Has returns true if the handle's stack contains a broker with the provided name.
func (bs Brokers) Has(name string) bool {
	for _, b := range bs {
		if b.Name() == name {
			return true
		}
	}

	return false
}

// Push puts a broker at the top of the stack.
func (bs Brokers) Push(b Broker) {
	bs = append(bs, b)
}

// Pop removes the broker from the top of the stack and returns it.
func (bs Brokers) Pop() Broker {
	if len(bs) == 0 {
		panic("Pop() called on empty broker list.")
	}

	out := bs[len(bs)-1]

	bs = bs[0 : len(bs)-2]

	return out
}

// First returns the first broker on the stack.
func (bs Brokers) First() Broker {
	if len(bs) == 0 {
		panic("First() called on empty broker list.")
	}

	return bs[0]
}

// Last returns the last broker on the stack.
func (bs Brokers) Last() Broker {
	if len(bs) == 0 {
		panic("Last() called on empty broker list.")
	}

	return bs[len(bs)-1]
}

// Previous finds the provided broker by matching its name against
// an item in the broker list and returns the item before it in that list.
func (bs Brokers) Previous(current Broker) Broker {
	if len(bs) == 0 {
		panic("Previous() called on empty broker list.")
	}
	if len(bs) == 1 {
		panic("Previous() called on a broker list with only one item.")
	}

	for i, b := range bs {
		if b.Name() == current.Name() {
			if i == 0 {
				panic("Previous() called on the first entry in the broker list.")
			}

			return bs[i-1]
		}
	}

	panic("Couldn't find a previous broker.")
}

// Clone returns a shallow-cloned Brokers list.
func (bs Brokers) Clone() Brokers {
	clone := make(Brokers, len(bs))
	copy(clone, bs)
	return clone
}
<|endoftext|>


<commit_before>package main

import "math/big"

// An intMono represents the monomial coeff*X^deg.
// The zero value for an intMono represents the zero monomial.
type intMono struct {
	coeff big.Int
	deg   big.Int
}

// Returns whether m and n have the same coefficient and degree.
func (m *intMono) Eq(n *intMono) bool {
	return m.coeff.Cmp(&n.coeff) == 0 && m.deg.Cmp(&n.deg) == 0
}

// Sets m to a deep copy of n.
func (m *intMono) Set(n *intMono) {
	m.coeff.Set(&n.coeff)
	m.deg.Set(&n.deg)
}

// Sets m to the product of n and coeff*X^deg.
func (m *intMono) Mul(n *intMono, coeff, deg *big.Int) {
	m.coeff.Mul(&n.coeff, coeff)
	m.deg.Add(&n.deg, deg)
}

// The container for a polynomial's terms.
type termList []intMono

// Returns a termList of the given size, possibly reusing term's
// space.
func (terms termList) make(n int) termList {
	if n <= cap(terms) {
		// Reuse the space.
		return terms[0:n]
	}
	// Otherwise, allocate a new array. No need to worry about
	// allocating extra space since we don't have to worry about
	// carries.
	return make(termList, n)
}

// An IntPoly represents the polynomial with the given non-zero terms
// in order of ascending degree.
// The zero value for an IntPoly represents the zero polynomial.
type IntPoly struct {
	terms termList
}

// Builds a new IntPoly from the given list of coefficient/degree
// pairs. Each coefficient must be non-zero, each degree must be
// non-negative, and the list must be in ascending order of degree.
func NewIntPoly(terms [][2]*big.Int) *IntPoly {
	var p IntPoly
	p.terms = p.terms.make(len(terms))
	for i, term := range terms {
		if term[0].Sign() == 0 {
			panic("zero coefficient")
		}
		if term[1].Sign() < 0 {
			panic("negative degree")
		}
		if i > 0 && term[1].Cmp(terms[i-1][1]) <= 0 {
			panic("non-increasing degree")
		}
		p.terms[i].coeff.Set(term[0])
		p.terms[i].deg.Set(term[1])
	}
	return &p
}

// Returns whether p and q have the same terms.
func (p *IntPoly) Eq(q *IntPoly) bool {
	if len(p.terms) != len(q.terms) {
		return false
	}
	for i, pTerm := range p.terms {
		if !pTerm.Eq(&q.terms[i]) {
			return false
		}
	}
	return true
}

// Sets p to a deep copy of q.
func (p *IntPoly) Set(q *IntPoly) *IntPoly {
	if p == q {
		return p
	}
	p.terms = p.terms.make(len(q.terms))
	for i, _ := range p.terms {
		p.terms[i].Set(&q.terms[i])
	}
	return p
}

// Sets p to the sum of q and r.
func (p *IntPoly) Add(q, r *IntPoly) *IntPoly {
	// Since we go left to right, reusing p's term array is okay
	// even if p aliases q or r (or both).
	terms := p.terms.make(len(q.terms) + len(r.terms))

	i, j, k := 0, 0, 0
	for ; j < len(q.terms) && k < len(r.terms); i++ {
		term := &terms[i]
		qTerm := &q.terms[j]
		rTerm := &r.terms[k]
		cmp := qTerm.deg.Cmp(&rTerm.deg)
		if cmp < 0 {
			term.Set(qTerm)
			j++
		} else if cmp > 0 {
			term.Set(rTerm)
			k++
		} else {
			term.coeff.Add(&qTerm.coeff, &rTerm.coeff)
			term.deg.Set(&qTerm.deg)
			j++
			k++
		}
	}

	if j < len(q.terms) {
		for ; j < len(q.terms); j++ {
			terms[i].Set(&q.terms[j])
			i++
		}
	} else if k < len(r.terms) {
		for ; k < len(r.terms); k++ {
			terms[i].Set(&r.terms[k])
			i++
		}
	}

	p.terms = terms[0:i]
	return p
}

// Sets p to the product of q and coeff*X^deg. coeff must not be zero
// and deg must not be negative.
func (p *IntPoly) MulMono(q *IntPoly, coeff, deg *big.Int) *IntPoly {
	if coeff.Sign() == 0 {
		panic("zero coefficient")
	}
	if deg.Sign() < 0 {
		panic("negative degree")
	}
	// Since we go left to right, reusing p's term array is okay
	// even if p aliases q.
	terms := p.terms.make(len(q.terms))
	for i, _ := range terms {
		terms[i].Mul(&q.terms[i], coeff, deg)
	}
	p.terms = terms
	return p
}

// Sets p to the product of q and r.
func (p *IntPoly) Mul(q, r *IntPoly) *IntPoly {
	if len(r.terms) > len(q.terms) {
		q, r = r, q
	}
	prod := IntPoly{}
	for _, term := range r.terms {
		t := IntPoly{}
		t.MulMono(q, &term.coeff, &term.deg)
		prod.Add(&prod, &t)
	}
	*p = prod
	return p
}

// Returns a copy of the identity polynomial.
func newIntPolyIdentity() *IntPoly {
	return NewIntPoly([][2]*big.Int{{big.NewInt(1), big.NewInt(0)}})
}

// Sets p to q raised to the kth power. k must be non-negative.
func (p *IntPoly) Pow(q *IntPoly, k *big.Int) *IntPoly {
	if k.Sign() < 0 {
		panic("negative power")
	}
	pow := IntPoly{}
	if k.Sign() == 0 {
		pow = *newIntPolyIdentity()
	} else {
		pow.Set(q)
		// TODO(akalin): Implement repeated squaring.
		for i := big.NewInt(1); i.Cmp(k) < 0; i.Add(i, big.NewInt(1)) {
			pow.Mul(&pow, q)
		}
	}
	*p = pow
	return p
}
<commit_msg>Implement repeated squaring for polynomial exponentiation<commit_after>package main

import "math/big"

// An intMono represents the monomial coeff*X^deg.
// The zero value for an intMono represents the zero monomial.
type intMono struct {
	coeff big.Int
	deg   big.Int
}

// Returns whether m and n have the same coefficient and degree.
func (m *intMono) Eq(n *intMono) bool {
	return m.coeff.Cmp(&n.coeff) == 0 && m.deg.Cmp(&n.deg) == 0
}

// Sets m to a deep copy of n.
func (m *intMono) Set(n *intMono) {
	m.coeff.Set(&n.coeff)
	m.deg.Set(&n.deg)
}

// Sets m to the product of n and coeff*X^deg.
func (m *intMono) Mul(n *intMono, coeff, deg *big.Int) {
	m.coeff.Mul(&n.coeff, coeff)
	m.deg.Add(&n.deg, deg)
}

// The container for a polynomial's terms.
type termList []intMono

// Returns a termList of the given size, possibly reusing term's
// space.
func (terms termList) make(n int) termList {
	if n <= cap(terms) {
		// Reuse the space.
		return terms[0:n]
	}
	// Otherwise, allocate a new array. No need to worry about
	// allocating extra space since we don't have to worry about
	// carries.
	return make(termList, n)
}

// An IntPoly represents the polynomial with the given non-zero terms
// in order of ascending degree.
// The zero value for an IntPoly represents the zero polynomial.
type IntPoly struct {
	terms termList
}

// Builds a new IntPoly from the given list of coefficient/degree
// pairs. Each coefficient must be non-zero, each degree must be
// non-negative, and the list must be in ascending order of degree.
func NewIntPoly(terms [][2]*big.Int) *IntPoly {
	var p IntPoly
	p.terms = p.terms.make(len(terms))
	for i, term := range terms {
		if term[0].Sign() == 0 {
			panic("zero coefficient")
		}
		if term[1].Sign() < 0 {
			panic("negative degree")
		}
		if i > 0 && term[1].Cmp(terms[i-1][1]) <= 0 {
			panic("non-increasing degree")
		}
		p.terms[i].coeff.Set(term[0])
		p.terms[i].deg.Set(term[1])
	}
	return &p
}

// Returns whether p and q have the same terms.
func (p *IntPoly) Eq(q *IntPoly) bool {
	if len(p.terms) != len(q.terms) {
		return false
	}
	for i, pTerm := range p.terms {
		if !pTerm.Eq(&q.terms[i]) {
			return false
		}
	}
	return true
}

// Sets p to a deep copy of q.
func (p *IntPoly) Set(q *IntPoly) *IntPoly {
	if p == q {
		return p
	}
	p.terms = p.terms.make(len(q.terms))
	for i, _ := range p.terms {
		p.terms[i].Set(&q.terms[i])
	}
	return p
}

// Sets p to the sum of q and r.
func (p *IntPoly) Add(q, r *IntPoly) *IntPoly {
	// Since we go left to right, reusing p's term array is okay
	// even if p aliases q or r (or both).
	terms := p.terms.make(len(q.terms) + len(r.terms))

	i, j, k := 0, 0, 0
	for ; j < len(q.terms) && k < len(r.terms); i++ {
		term := &terms[i]
		qTerm := &q.terms[j]
		rTerm := &r.terms[k]
		cmp := qTerm.deg.Cmp(&rTerm.deg)
		if cmp < 0 {
			term.Set(qTerm)
			j++
		} else if cmp > 0 {
			term.Set(rTerm)
			k++
		} else {
			term.coeff.Add(&qTerm.coeff, &rTerm.coeff)
			term.deg.Set(&qTerm.deg)
			j++
			k++
		}
	}

	if j < len(q.terms) {
		for ; j < len(q.terms); j++ {
			terms[i].Set(&q.terms[j])
			i++
		}
	} else if k < len(r.terms) {
		for ; k < len(r.terms); k++ {
			terms[i].Set(&r.terms[k])
			i++
		}
	}

	p.terms = terms[0:i]
	return p
}

// Sets p to the product of q and coeff*X^deg. coeff must not be zero
// and deg must not be negative.
func (p *IntPoly) MulMono(q *IntPoly, coeff, deg *big.Int) *IntPoly {
	if coeff.Sign() == 0 {
		panic("zero coefficient")
	}
	if deg.Sign() < 0 {
		panic("negative degree")
	}
	// Since we go left to right, reusing p's term array is okay
	// even if p aliases q.
	terms := p.terms.make(len(q.terms))
	for i, _ := range terms {
		terms[i].Mul(&q.terms[i], coeff, deg)
	}
	p.terms = terms
	return p
}

// Sets p to the product of q and r.
func (p *IntPoly) Mul(q, r *IntPoly) *IntPoly {
	if len(r.terms) > len(q.terms) {
		q, r = r, q
	}
	prod := IntPoly{}
	for _, term := range r.terms {
		t := IntPoly{}
		t.MulMono(q, &term.coeff, &term.deg)
		prod.Add(&prod, &t)
	}
	*p = prod
	return p
}

// Returns a copy of the identity polynomial.
func newIntPolyIdentity() *IntPoly {
	return NewIntPoly([][2]*big.Int{{big.NewInt(1), big.NewInt(0)}})
}

// Sets p to q raised to the kth power. k must be non-negative.
func (p *IntPoly) Pow(q *IntPoly, k *big.Int) *IntPoly {
	if k.Sign() < 0 {
		panic("negative power")
	}
	pow := newIntPolyIdentity()
	for i := k.BitLen() - 1; i >= 0; i-- {
		pow.Mul(pow, pow)
		if k.Bit(i) != 0 {
			pow.Mul(pow, q)
		}
	}
	*p = *pow
	return p
}
<|endoftext|>


<commit_before>package chess

import (
	"fmt"
)

type Board struct {
	Squares []*Square
}

func NewEmptyBoard() (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}

	return &b, nil
}

func NewBoard() (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}
	if err := b.LoadFromFEN(FEN("TODO")); err != nil {
		return nil, err
	}

	return &b, nil
}

func BoardFEN(fen FEN) (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}
	if err := b.LoadFromFEN(fen); err != nil {
		return nil, err
	}

	return &b, nil
}

func (b *Board) build(files, ranks int) error {
	for rank := 1; rank <= ranks; rank++ {
		for file := 1; file <= files; file++ {
			s, err := NewSquare(file, rank)
			if err != nil {
				return err
			}
			b.Squares = append(b.Squares, s)
		}
	}
	return nil
}

func (b *Board) LoadFromFEN(f FEN) error {
	if !f.IsValid() {
		return fmt.Errorf("Invalid FEN %s", f)
	}

	for _, s := range b.Squares {

		//White
		if (s.File == A && s.Rank == 1) || (s.File == H && s.Rank == 1) {
			r, _ := NewRook(s, White)
			s.SetPiece(r)
		}

		//White
		if (s.File == B && s.Rank == 1) || (s.File == G && s.Rank == 1) {
			k, _ := NewKnight(s, White)
			s.SetPiece(k)
		}

		//White
		if s.File == E && s.Rank == 1  {
			k, _ := NewKing(s, White)
			s.SetPiece(k)
		}

		//DUMMY
		if s.File == A && s.Rank == 3  {
			k, _ := NewRook(s, Black)
			s.SetPiece(k)
		}

		//Black
		if (s.File == A && s.Rank == 8) || (s.File == H && s.Rank == 8) {
			r, _ := NewRook(s, Black)
			s.SetPiece(r)
		}

		//Black
		if (s.File == B && s.Rank == 8) || (s.File == G && s.Rank == 8) {
			k, _ := NewKnight(s, Black)
			s.SetPiece(k)
		}

		//White
		if s.File == E && s.Rank == 8  {
			k, _ := NewKing(s, Black)
			s.SetPiece(k)
		}

	}

	return nil
}

func (b *Board) GetSquare(file, rank int) *Square {
	for _, s := range b.Squares {
		if s.File == file && s.Rank == rank {
			return s
		}
	}

	return nil
}
<commit_msg>adding board info that is used by FEN<commit_after>package chess

import (
	"fmt"
)

type CastlingRights struct {
	WhiteKingSideAvailable  bool
	WhiteQueenSideAvailable bool
	BlackKingSideAvailable  bool
	BlackQueenSideAvailable bool
}

type Board struct {
	Squares         []*Square
	ActiveColor     Color
	CastlingRights  CastlingRights
	EnPassantSquare *Square
	HalfMoveClock   int
	FullMoveNumber  int
}

func NewEmptyBoard() (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}
	b.ActiveColor = White
	b.CastlingRights = CastlingRights{
		WhiteKingSideAvailable:true,
		WhiteQueenSideAvailable:true,
		BlackKingSideAvailable:true,
		BlackQueenSideAvailable:true,
	}
	b.EnPassantSquare = nil
	b.HalfMoveClock = 0
	b.FullMoveNumber = 1

	return &b, nil
}

func NewBoard() (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}
	if err := b.LoadFromFEN(FEN("TODO")); err != nil {
		return nil, err
	}

	return &b, nil
}

func BoardFEN(fen FEN) (*Board, error) {
	var b Board

	if err := b.build(8, 8); err != nil {
		return nil, err
	}
	if err := b.LoadFromFEN(fen); err != nil {
		return nil, err
	}

	return &b, nil
}

func (b *Board) build(files, ranks int) error {
	for rank := 1; rank <= ranks; rank++ {
		for file := 1; file <= files; file++ {
			s, err := NewSquare(file, rank)
			if err != nil {
				return err
			}
			b.Squares = append(b.Squares, s)
		}
	}
	return nil
}

func (b *Board) LoadFromFEN(f FEN) error {
	if !f.IsValid() {
		return fmt.Errorf("Invalid FEN %s", f)
	}

	for _, s := range b.Squares {

		//White
		if (s.File == A && s.Rank == 1) || (s.File == H && s.Rank == 1) {
			r, _ := NewRook(s, White)
			s.SetPiece(r)
		}

		//White
		if (s.File == B && s.Rank == 1) || (s.File == G && s.Rank == 1) {
			k, _ := NewKnight(s, White)
			s.SetPiece(k)
		}

		//White
		if s.File == E && s.Rank == 1 {
			k, _ := NewKing(s, White)
			s.SetPiece(k)
		}

		//DUMMY
		if s.File == A && s.Rank == 3 {
			k, _ := NewRook(s, Black)
			s.SetPiece(k)
		}

		//Black
		if (s.File == A && s.Rank == 8) || (s.File == H && s.Rank == 8) {
			r, _ := NewRook(s, Black)
			s.SetPiece(r)
		}

		//Black
		if (s.File == B && s.Rank == 8) || (s.File == G && s.Rank == 8) {
			k, _ := NewKnight(s, Black)
			s.SetPiece(k)
		}

		//White
		if s.File == E && s.Rank == 8 {
			k, _ := NewKing(s, Black)
			s.SetPiece(k)
		}

	}

	return nil
}

func (b *Board) GetSquare(file, rank int) *Square {
	for _, s := range b.Squares {
		if s.File == file && s.Rank == rank {
			return s
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"testing"
)

var h host

var filetests = []string{
	"http://localhost:6060/",
	"localhost",
}

func init() {
	h = host{name: "localhost"}
	s := make([]string, 0)
	h.addrs = append(s, "127.0.0.1")
}

func TestReadHosts(t *testing.T) {
	readHosts()
	for i, f := range filetests {
		if hosts[i].name != f {
			t.Errorf("hosts[%d]: got host{name: %s}, want host{name: %s}", i, hosts[i].name, f)
		}
	}
}

func TestPing(t *testing.T) {
	want := resp{
		seq:  0,
		code: 0,
		to:   "127.0.0.1",
		from: "127.0.0.1",
		body: fmt.Sprintf("Ranger-Chooch-%s", h.name),
	}
	h.ping()
	if h.resps[0].seq != want.seq {
		t.Errorf("h.resps[0].seq got %d, want %d", h.resps[0].seq, want.seq)
	}
	if h.resps[0].code != want.code {
		t.Errorf("h.resps[0].code got %d, want %d", h.resps[0].code, want.code)
	}
	if h.resps[0].to != want.to {
		t.Errorf("h.resps[0].to got %s, want %s", h.resps[0].to, want.to)
	}
	if h.resps[0].from != want.from {
		t.Errorf("h.resps[0].from got %s, want %s", h.resps[0].from, want.from)
	}
	if h.resps[0].body != want.body {
		t.Errorf("h.resps[0].body got %s, want %s", h.resps[0].body, want.body)
	}
}

func TestHtoI(t *testing.T) {
	h := host{name: "localhost"}
	want := "127.0.0.1"
	err := h.htoi()
	if err != nil {
		t.Fatal(err)
	}
	got := h.addrs[0]
	if got != want {
		t.Errorf("h.addrs: got %s, want %s", got, want)
	}
}

func TestUnpackUrls(t *testing.T) {
	h.name = "http://localhost/path"
	want := host{protocol: "http", name: "localhost", endpoint: "/path"}
	err := h.unpackUrls()
	if err != nil {
		t.Error(err)
	}
	if h.protocol != want.protocol {
		t.Errorf("h.protocol got %s, want %s", h.protocol, want.protocol)
	}
	if h.name != want.name {
		t.Errorf("h.name got %s, want %s", h.name, want.name)
	}
	if h.endpoint != want.endpoint {
		t.Errorf("h.endpoint got %s, want %s", h.endpoint, want.endpoint)
	}
}
<commit_msg>Add non-url case for TestUnpackUrls<commit_after>package main

import (
	"fmt"
	"testing"
)

var h host

var filetests = []string{
	"http://localhost:6060/",
	"localhost",
}

func init() {
	h = host{name: "localhost"}
	s := make([]string, 0)
	h.addrs = append(s, "127.0.0.1")
}

func TestReadHosts(t *testing.T) {
	readHosts()
	for i, f := range filetests {
		if hosts[i].name != f {
			t.Errorf("hosts[%d]: got host{name: %s}, want host{name: %s}", i, hosts[i].name, f)
		}
	}
}

func TestPing(t *testing.T) {
	want := resp{
		seq:  0,
		code: 0,
		to:   "127.0.0.1",
		from: "127.0.0.1",
		body: fmt.Sprintf("Ranger-Chooch-%s", h.name),
	}
	h.ping()
	if h.resps[0].seq != want.seq {
		t.Errorf("h.resps[0].seq got %d, want %d", h.resps[0].seq, want.seq)
	}
	if h.resps[0].code != want.code {
		t.Errorf("h.resps[0].code got %d, want %d", h.resps[0].code, want.code)
	}
	if h.resps[0].to != want.to {
		t.Errorf("h.resps[0].to got %s, want %s", h.resps[0].to, want.to)
	}
	if h.resps[0].from != want.from {
		t.Errorf("h.resps[0].from got %s, want %s", h.resps[0].from, want.from)
	}
	if h.resps[0].body != want.body {
		t.Errorf("h.resps[0].body got %s, want %s", h.resps[0].body, want.body)
	}
}

func TestHtoI(t *testing.T) {
	h := host{name: "localhost"}
	want := "127.0.0.1"
	err := h.htoi()
	if err != nil {
		t.Fatal(err)
	}
	got := h.addrs[0]
	if got != want {
		t.Errorf("h.addrs: got %s, want %s", got, want)
	}
}

func TestUnpackUrls(t *testing.T) {
	err := h.unpackUrls()
	if err != nil {
		t.Error(err)
	}
	if h.protocol != "" {
		t.Errorf("h.protocol got %s, want \"\"", h.protocol)
	}
	if h.endpoint != "" {
		t.Errorf("h.endpoint got %s, want \"\"", h.endpoint)
	}

	h.name = "http://localhost/path"
	want := host{protocol: "http", name: "localhost", endpoint: "/path"}
	err = h.unpackUrls()
	if err != nil {
		t.Error(err)
	}
	if h.protocol != want.protocol {
		t.Errorf("h.protocol got %s, want %s", h.protocol, want.protocol)
	}
	if h.name != want.name {
		t.Errorf("h.name got %s, want %s", h.name, want.name)
	}
	if h.endpoint != want.endpoint {
		t.Errorf("h.endpoint got %s, want %s", h.endpoint, want.endpoint)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2016 Nuxeo SA (http://nuxeo.com/) and others.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cli
import (
	"github.com/coreos/etcd/client"
	"github.com/arkenio/arken/goarken/model"
	"github.com/arkenio/arken/goarken/storage"
	"github.com/arkenio/arken/goarken/drivers"
	"github.com/spf13/viper"
	"errors"
	"fmt"
	"time"
)

func CreateEtcdClient() client.KeysAPI {
	etcdAdress := viper.GetString("etcdAddress")

	cfg := client.Config{
		Endpoints:               []string{etcdAdress},
		Transport:               client.DefaultTransport,
		HeaderTimeoutPerRequest: time.Second,
	}
	c, err := client.New(cfg)
	if err != nil {
		log.Fatal(err)
	}
	return client.NewKeysAPI(c)

}

func CreateServiceDriver(etcdClient client.KeysAPI) (model.ServiceDriver, error) {

	rancherHost := viper.GetString("rancher.host")
	accessKey := viper.GetString("rancher.accessKey")
	secretKey := viper.GetString("rancher.secretKey")

	switch viper.GetString("driver") {
	case "rancher":
		log.Infof("Rancher host: %s",rancherHost)
		log.Infof("Rancher Access key: %s", accessKey)
		log.Infof("Rancher Secret key: ************************",)
		sd, err := drivers.NewRancherServiceDriver(rancherHost,accessKey,secretKey)
		if err != nil {
			return nil, errors.New(fmt.Sprintf("Unable to connect to Rancher : %s", err.Error()))
		}

		return sd, nil;

	default:
		return drivers.NewFleetServiceDriver(viper.GetString("etcdAddress")),nil
	}
}

func CreateWatcherFromCli(client client.KeysAPI) *storage.Watcher {
	return storage.NewWatcher(client, viper.GetString("serviceDir"), viper.GetString("domainDir"))

}

<commit_msg>NXIO-580: change var names to match rancher env vars<commit_after>// Copyright © 2016 Nuxeo SA (http://nuxeo.com/) and others.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cli

import (
	"errors"
	"fmt"
	"github.com/arkenio/arken/goarken/drivers"
	"github.com/arkenio/arken/goarken/model"
	"github.com/arkenio/arken/goarken/storage"
	"github.com/coreos/etcd/client"
	"github.com/spf13/viper"
	"time"
)

func CreateEtcdClient() client.KeysAPI {
	etcdAdress := viper.GetString("etcdAddress")

	cfg := client.Config{
		Endpoints:               []string{etcdAdress},
		Transport:               client.DefaultTransport,
		HeaderTimeoutPerRequest: time.Second,
	}
	c, err := client.New(cfg)
	if err != nil {
		log.Fatal(err)
	}
	return client.NewKeysAPI(c)

}

func CreateServiceDriver(etcdClient client.KeysAPI) (model.ServiceDriver, error) {

	rancherHost := viper.GetString("CATTLE_URL")
	if rancherHost == "" {
		rancherHost = viper.GetString("rancher.host") //compat with old catalog def
	}

	accessKey := viper.GetString("CATTLE_ACCESS_KEY")
	if accessKey == "" {
		accessKey = viper.GetString("rancher.accessKey") //compat with old catalog def
	}

	secretKey := viper.GetString("CATTLE_SECRET_KEY")
	if secretKey == "" {
		secretKey = viper.GetString("rancher.secretKey") //compat with old catalog def
	}

	switch viper.GetString("driver") {
	case "rancher":
		log.Infof("Rancher host: %s", rancherHost)
		log.Infof("Rancher Access key: %s", accessKey)
		log.Infof("Rancher Secret key: ************************")
		sd, err := drivers.NewRancherServiceDriver(rancherHost, accessKey, secretKey)
		if err != nil {
			return nil, errors.New(fmt.Sprintf("Unable to connect to Rancher : %s", err.Error()))
		}

		return sd, nil

	default:
		return drivers.NewFleetServiceDriver(viper.GetString("etcdAddress")), nil
	}
}

func CreateWatcherFromCli(client client.KeysAPI) *storage.Watcher {
	return storage.NewWatcher(client, viper.GetString("serviceDir"), viper.GetString("domainDir"))

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"

	functions "github.com/funcy/functions_go"
	"github.com/urfave/cli"
)

// Version of Functions CLI
var Version = "0.3.26"

func version() cli.Command {
	r := versionCmd{VersionApi: functions.NewVersionApi()}
	return cli.Command{
		Name:   "version",
		Usage:  "displays fn and functions daemon versions",
		Action: r.version,
	}
}

type versionCmd struct {
	*functions.VersionApi
}

func (r *versionCmd) version(c *cli.Context) error {
	apiURL := os.Getenv("API_URL")
	if apiURL == "" {
		apiURL = "http://localhost:8080"
	}

	u, err := url.Parse(apiURL)
	if err != nil {
		return err
	}
	r.Configuration.BasePath = u.String()

	fmt.Println("Client version:", Version)
	v, _, err := r.VersionGet()
	if err != nil {
		return err
	}
	fmt.Println("Server version", v.Version)
	return nil
}
<commit_msg>fn tool: 0.3.27 release [skip ci]<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"

	functions "github.com/funcy/functions_go"
	"github.com/urfave/cli"
)

// Version of Functions CLI
var Version = "0.3.27"

func version() cli.Command {
	r := versionCmd{VersionApi: functions.NewVersionApi()}
	return cli.Command{
		Name:   "version",
		Usage:  "displays fn and functions daemon versions",
		Action: r.version,
	}
}

type versionCmd struct {
	*functions.VersionApi
}

func (r *versionCmd) version(c *cli.Context) error {
	apiURL := os.Getenv("API_URL")
	if apiURL == "" {
		apiURL = "http://localhost:8080"
	}

	u, err := url.Parse(apiURL)
	if err != nil {
		return err
	}
	r.Configuration.BasePath = u.String()

	fmt.Println("Client version:", Version)
	v, _, err := r.VersionGet()
	if err != nil {
		return err
	}
	fmt.Println("Server version", v.Version)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"fmt"
	"strings"

	"encoding/json"
	"log"
	"net/http"

	"github.com/gorilla/mux"

	"bytes"
	"encoding/gob"
	"time"

	"github.com/boltdb/bolt"

	"github.com/spacemonkeygo/errors"
)

type PhoneNumber string

type Address struct {
	Address1   string `json:"address1"`
	Address2   string `json:"address2"`
	City       string `json:"city"`
	Province   string `json:"province"`
	PostalCode string `json:"postalCode"`
}

type GroupPreRegistration struct {
	SecurityKey []byte `json:"-"`

	PackName  string `json:"packName"`
	GroupName string `json:"groupName"`
	Council   string `json:"council"`

	ContactLeaderFirstName   string      `json:"contactLeaderFirstName"`
	ContactLeaderLastName    string      `json:"contactLeaderLastName"`
	ContactLeaderPhoneNumber PhoneNumber `json:"contactLeaderPhoneNumber"`
	ContactLeaderAddress     Address     `json:"contactLeaderAddress"`

	ContactLeaderEmail string    `json:"contactLeaderEmail"`
	ValidatedOn        time.Time `json:"-"`
	ValidationToken    string    `json:"-"`

	EstimatedYouth   int `json:"estimatedYouth"`
	EstimatedLeaders int `json:"estimatedLeaders"`
}

func (gpr *GroupPreRegistration) Key() []byte {
	if gpr.SecurityKey == nil {
		var random [128]byte
		if _, err := rand.Read(random[:]); err != nil {
			panic(err)
		}
		gpr.SecurityKey = random[:]
	}
	return gpr.SecurityKey
}

func (gpr GroupPreRegistration) OrganicKey() string {
	return fmt.Sprintf("%s-%s-%s", strings.TrimSpace(gpr.Council), strings.TrimSpace(gpr.GroupName), strings.TrimSpace(gpr.PackName))
}

type PreRegDb interface {
	CreateRecord(rec *GroupPreRegistration) error
}

var (
	DBError             = errors.NewClass("Database Error")
	GroupAlreadyCreated = DBError.NewClass("Group already exists")
)

var (
	BOLT_GROUPBUCKET         = []byte("BUCKET_GROUP")
	BOLT_GROUPNAMEMAPBUCKET  = []byte("BUCKET_GROUPNAMEMAP")
	BOLT_GROUPEMAILMAPBUCKET = []byte("BUCKET_GROUPEMAILMAP")
)

type preRegDbBolt struct {
	db *bolt.DB
}

func NewPreRegBoltDb(db *bolt.DB) (PreRegDb, error) {
	prdb := &preRegDbBolt{
		db: db,
	}
	if err := prdb.init(); err != nil {
		return nil, err
	}
	return prdb, nil
}

func (d *preRegDbBolt) CreateRecord(in *GroupPreRegistration) error {
	return d.db.Update(func(tx *bolt.Tx) error {
		gb := tx.Bucket(BOLT_GROUPBUCKET)
		gnmb := tx.Bucket(BOLT_GROUPNAMEMAPBUCKET)
		gemb := tx.Bucket(BOLT_GROUPEMAILMAPBUCKET)
		if gb.Get(in.Key()) != nil {
			log.Printf("Managed to get a duplicate security key somehow!")
			return GroupAlreadyCreated.New("Group with security key %v already exists", in.Key())
		} else if gnmb.Get([]byte(in.OrganicKey())) != nil {
			return GroupAlreadyCreated.New("Group with organic key %v already exists", in.OrganicKey())
		} else if gemb.Get([]byte(in.ContactLeaderEmail)) != nil {
			return GroupAlreadyCreated.New("Group with contact email %v already exists", in.ContactLeaderEmail)
		} else {
			data := &bytes.Buffer{}
			encoder := gob.NewEncoder(data)
			if err := encoder.Encode(in); err != nil {
				return err
			}
			if err := gb.Put(in.Key(), data.Bytes()); err != nil {
				return err
			}
			if err := gnmb.Put([]byte(in.OrganicKey()), in.Key()); err != nil {
				return err
			}
			if err := gemb.Put([]byte(in.ContactLeaderEmail), in.Key()); err != nil {
				return err
			}
		}
		return nil
	})
}

func (d *preRegDbBolt) init() error {
	return d.db.Update(func(tx *bolt.Tx) error {
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPBUCKET); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPNAMEMAPBUCKET); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPEMAILMAPBUCKET); err != nil {
			return err
		}
		return nil
	})
}

type PreRegHandler struct {
	db PreRegDb
}

func (h *PreRegHandler) Create(w http.ResponseWriter, r *http.Request) {
	input := GroupPreRegistration{}
	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&input); err != nil {
		log.Printf("Got error while decoding json: %s", err)
		http.Error(w, "Invalid group json given", 400)
		return
	}

	if err := h.db.CreateRecord(&input); err != nil {
		log.Printf("Failed to insert record!  Error: %s", err)
		http.Error(w, "Failed to insert record", 500)
		return
	} else {
		w.WriteHeader(http.StatusCreated)
	}
}

func registerGroupPreRegistrationHandler(r *mux.Router, db *bolt.DB) {
	prdb, err := NewPreRegBoltDb(db)
	if err != nil {
		log.Fatal(err)
	}
	preRegHandler := PreRegHandler{
		db: prdb,
	}

	r.HandleFunc("/prereg", preRegHandler.Create).Methods("POST")
}
<commit_msg>Update backend to match frontend urls.<commit_after>package main

import (
	"crypto/rand"
	"fmt"
	"strings"

	"encoding/json"
	"log"
	"net/http"

	"github.com/gorilla/mux"

	"bytes"
	"encoding/gob"
	"time"

	"github.com/boltdb/bolt"

	"github.com/spacemonkeygo/errors"
)

type PhoneNumber string

type Address struct {
	Address1   string `json:"address1"`
	Address2   string `json:"address2"`
	City       string `json:"city"`
	Province   string `json:"province"`
	PostalCode string `json:"postalCode"`
}

type GroupPreRegistration struct {
	SecurityKey []byte `json:"-"`

	PackName  string `json:"packName"`
	GroupName string `json:"groupName"`
	Council   string `json:"council"`

	ContactLeaderFirstName   string      `json:"contactLeaderFirstName"`
	ContactLeaderLastName    string      `json:"contactLeaderLastName"`
	ContactLeaderPhoneNumber PhoneNumber `json:"contactLeaderPhoneNumber"`
	ContactLeaderAddress     Address     `json:"contactLeaderAddress"`

	ContactLeaderEmail string    `json:"contactLeaderEmail"`
	ValidatedOn        time.Time `json:"-"`
	ValidationToken    string    `json:"-"`

	EstimatedYouth   int `json:"estimatedYouth"`
	EstimatedLeaders int `json:"estimatedLeaders"`
}

func (gpr *GroupPreRegistration) Key() []byte {
	if gpr.SecurityKey == nil {
		var random [128]byte
		if _, err := rand.Read(random[:]); err != nil {
			panic(err)
		}
		gpr.SecurityKey = random[:]
	}
	return gpr.SecurityKey
}

func (gpr GroupPreRegistration) OrganicKey() string {
	return fmt.Sprintf("%s-%s-%s", strings.TrimSpace(gpr.Council), strings.TrimSpace(gpr.GroupName), strings.TrimSpace(gpr.PackName))
}

type PreRegDb interface {
	CreateRecord(rec *GroupPreRegistration) error
}

var (
	DBError             = errors.NewClass("Database Error")
	GroupAlreadyCreated = DBError.NewClass("Group already exists")
)

var (
	BOLT_GROUPBUCKET         = []byte("BUCKET_GROUP")
	BOLT_GROUPNAMEMAPBUCKET  = []byte("BUCKET_GROUPNAMEMAP")
	BOLT_GROUPEMAILMAPBUCKET = []byte("BUCKET_GROUPEMAILMAP")
)

type preRegDbBolt struct {
	db *bolt.DB
}

func NewPreRegBoltDb(db *bolt.DB) (PreRegDb, error) {
	prdb := &preRegDbBolt{
		db: db,
	}
	if err := prdb.init(); err != nil {
		return nil, err
	}
	return prdb, nil
}

func (d *preRegDbBolt) CreateRecord(in *GroupPreRegistration) error {
	return d.db.Update(func(tx *bolt.Tx) error {
		gb := tx.Bucket(BOLT_GROUPBUCKET)
		gnmb := tx.Bucket(BOLT_GROUPNAMEMAPBUCKET)
		gemb := tx.Bucket(BOLT_GROUPEMAILMAPBUCKET)
		if gb.Get(in.Key()) != nil {
			log.Printf("Managed to get a duplicate security key somehow!")
			return GroupAlreadyCreated.New("Group with security key %v already exists", in.Key())
		} else if gnmb.Get([]byte(in.OrganicKey())) != nil {
			return GroupAlreadyCreated.New("Group with organic key %v already exists", in.OrganicKey())
		} else if gemb.Get([]byte(in.ContactLeaderEmail)) != nil {
			return GroupAlreadyCreated.New("Group with contact email %v already exists", in.ContactLeaderEmail)
		} else {
			data := &bytes.Buffer{}
			encoder := gob.NewEncoder(data)
			if err := encoder.Encode(in); err != nil {
				return err
			}
			if err := gb.Put(in.Key(), data.Bytes()); err != nil {
				return err
			}
			if err := gnmb.Put([]byte(in.OrganicKey()), in.Key()); err != nil {
				return err
			}
			if err := gemb.Put([]byte(in.ContactLeaderEmail), in.Key()); err != nil {
				return err
			}
		}
		return nil
	})
}

func (d *preRegDbBolt) init() error {
	return d.db.Update(func(tx *bolt.Tx) error {
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPBUCKET); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPNAMEMAPBUCKET); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists(BOLT_GROUPEMAILMAPBUCKET); err != nil {
			return err
		}
		return nil
	})
}

type PreRegHandler struct {
	db PreRegDb
}

func (h *PreRegHandler) Create(w http.ResponseWriter, r *http.Request) {
	input := GroupPreRegistration{}
	decoder := json.NewDecoder(r.Body)
	if err := decoder.Decode(&input); err != nil {
		log.Printf("Got error while decoding json: %s", err)
		http.Error(w, "Invalid group json given", 400)
		return
	}

	if err := h.db.CreateRecord(&input); err != nil {
		log.Printf("Failed to insert record!  Error: %s", err)
		http.Error(w, "Failed to insert record", 500)
		return
	} else {
		w.WriteHeader(http.StatusCreated)
	}
}

func registerGroupPreRegistrationHandler(r *mux.Router, db *bolt.DB) {
	prdb, err := NewPreRegBoltDb(db)
	if err != nil {
		log.Fatal(err)
	}
	preRegHandler := PreRegHandler{
		db: prdb,
	}

	r.HandleFunc("/preregistration", preRegHandler.Create).Methods("POST")
}
<|endoftext|>


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

package helper

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
)

var (
	gitExecutable string
)

// Git calls the system git in the project directory with specified arguments
func Git(ev map[string]string, projectPath string, args ...string) (int, error) {
	command := exec.Command(gitExecutable, args...)
	env := Environ(os.Environ())
	for key := range ev {
		env.Unset(key)
	}
	for key, value := range ev {
		log.Printf("Setting '%s' to '%s'", key, value)
		env = append(env, fmt.Sprintf("%s=%s", key, value))
	}
	command.Dir = projectPath
	command.Env = env
	command.Stdout = os.Stdout
	command.Stdin = os.Stdin
	command.Stderr = os.Stderr
	return StartAndWait(command)
}

func init() {
	var err error
	gitExecutable, err = exec.LookPath("git")
	if err != nil {
		log.Fatalf("Could not locate git: '%#v'", err)
	}
}

// HasChanges checks whether a repo is clean or has changes ( modifications or additions )
func HasChanges(ev map[string]string, projectPath string) (bool, error) {
	// git status --porcelain
	command := exec.Command(gitExecutable, "status", "--porcelain")
	env := Environ(os.Environ())
	for key := range ev {
		env.Unset(key)
	}
	for key, value := range ev {
		log.Printf("Setting '%s' to '%s'", key, value)
		env = append(env, fmt.Sprintf("%s=%s", key, value))
	}
	command.Dir = projectPath
	command.Env = env
	out, err := command.Output()
	if err != nil {
		return true, err
	}
	scanner := bufio.NewScanner(bytes.NewBuffer(out))
	for scanner.Scan() {
		return true, nil
	}
	return false, nil
}

// HasBranch checks if there is a branch locally or remotely
func HasBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	ok, err := HasRemoteBranch(ev, projectPath, branch)
	if err != nil {
		return false, err
	}
	ok2, err := HasLocalBranch(ev, projectPath, branch)
	return ok && ok2, err
}

// HasRemoteBranch checks if there is a branch remotely
func HasRemoteBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	exitcode, err := Git(ev, projectPath, "ls-remote", "--exit-code", ".", fmt.Sprintf("origin/%s", branch))
	if exitcode == 0 && err == nil {
		return true, nil
	}
	return false, err
}

// HasLocalBranch checks if there is a branch locally
func HasLocalBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	exitcode, err := Git(ev, projectPath, "rev-parse", "--verify", branch)
	if exitcode == 0 && err == nil {
		return true, nil
	}
	return false, err
}
<commit_msg>Fix: handling of branch detection<commit_after>// Copyright © 2017 Sascha Andres <sascha.andres@outlook.com>
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package helper

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
)

var (
	gitExecutable string
)

// Git calls the system git in the project directory with specified arguments
func Git(ev map[string]string, projectPath string, args ...string) (int, error) {
	command := exec.Command(gitExecutable, args...)
	env := Environ(os.Environ())
	for key := range ev {
		env.Unset(key)
	}
	for key, value := range ev {
		log.Printf("Setting '%s' to '%s'", key, value)
		env = append(env, fmt.Sprintf("%s=%s", key, value))
	}
	command.Dir = projectPath
	command.Env = env
	command.Stdout = os.Stdout
	command.Stdin = os.Stdin
	command.Stderr = os.Stderr
	return StartAndWait(command)
}

func init() {
	var err error
	gitExecutable, err = exec.LookPath("git")
	if err != nil {
		log.Fatalf("Could not locate git: '%#v'", err)
	}
}

// HasChanges checks whether a repo is clean or has changes ( modifications or additions )
func HasChanges(ev map[string]string, projectPath string) (bool, error) {
	// git status --porcelain
	command := exec.Command(gitExecutable, "status", "--porcelain")
	env := Environ(os.Environ())
	for key := range ev {
		env.Unset(key)
	}
	for key, value := range ev {
		log.Printf("Setting '%s' to '%s'", key, value)
		env = append(env, fmt.Sprintf("%s=%s", key, value))
	}
	command.Dir = projectPath
	command.Env = env
	out, err := command.Output()
	if err != nil {
		return true, err
	}
	scanner := bufio.NewScanner(bytes.NewBuffer(out))
	for scanner.Scan() {
		return true, nil
	}
	return false, nil
}

// HasBranch checks if there is a branch locally or remotely
func HasBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	ok, err := HasRemoteBranch(ev, projectPath, branch)
	if err != nil {
		return false, err
	}
	ok2, err := HasLocalBranch(ev, projectPath, branch)
	return ok && ok2, err
}

// HasRemoteBranch checks if there is a branch remotely
func HasRemoteBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	exitcode, err := Git(ev, projectPath, "ls-remote", "--exit-code", ".", fmt.Sprintf("origin/%s", branch))
	if exitcode == 0 {
		return true, nil
	}
	if err != nil {
		return true, nil
	}
	return false, nil
}

// HasLocalBranch checks if there is a branch locally
func HasLocalBranch(ev map[string]string, projectPath, branch string) (bool, error) {
	exitcode, _ := Git(ev, projectPath, "rev-parse", "--verify", branch)
	if exitcode == 0 {
		return true, nil
	}
	return false, nil
}
<|endoftext|>


<commit_before>package http

import (
  "../log"
)

func init() {
  log.InitLog()
}

type HttpRequest struct {
}

<commit_msg>Delete route.go<commit_after><|endoftext|>


<commit_before>package httpclient

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/gobs/pretty"
	"github.com/gobs/simplejson"
)

var (
	DefaultClient = &http.Client{} // we use our own default client, so we can change the TLS configuration

	NoRedirect       = errors.New("No redirect")
	TooManyRedirects = errors.New("stopped after 10 redirects")
)

//
// Allow connections via HTTPS even if something is wrong with the certificate
// (self-signed or expired)
//
func AllowInsecure(insecure bool) {
	if insecure {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}

		DefaultClient.Transport = tr
	} else {
		DefaultClient.Transport = nil
	}
}

//
// Set connection timeout
//
func SetTimeout(t time.Duration) {
	DefaultClient.Timeout = t
}

//
// HTTP error
//
type HttpError struct {
	Code    int
	Message string
}

func (e HttpError) Error() string {
	return e.Message
}

func (e HttpError) String() string {
	return fmt.Sprintf("ERROR: %v %v", e.Code, e.Message)
}

//
// CloseResponse makes sure we close the response body
//
func CloseResponse(r *http.Response) {
	if r != nil && r.Body != nil {
		io.Copy(ioutil.Discard, r.Body)
		r.Body.Close()
	}
}

//
// A wrapper for http.Response
//
type HttpResponse struct {
	http.Response
}

func (r *HttpResponse) ContentType() string {
	content_type := r.Header.Get("Content-Type")
	if len(content_type) == 0 {
		return content_type
	}

	return strings.TrimSpace(strings.Split(content_type, ";")[0])
}

//
// Close makes sure that all data from the body is read
// before closing the reader.
//
// If that is not the desider behaviour, just call HttpResponse.Body.Close()
//
func (r *HttpResponse) Close() {
        if r != nil {
	    CloseResponse(&r.Response)
        }
}

//
// ResponseError checks the StatusCode and return an error if needed.
// The error is of type HttpError
//
func (r *HttpResponse) ResponseError() error {
	class := r.StatusCode / 100
	if class != 2 && class != 3 {
		return HttpError{Code: r.StatusCode, Message: "HTTP " + r.Status}
	}

	return nil
}

//
// Check if the input value is a "primitive" that can be safely stringified
//
func canStringify(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Bool,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Float32, reflect.Float64,
		reflect.String:
		return true
	default:
		return false
	}
}

//
// Given a base URL and a bag of parameteters returns the URL with the encoded parameters
//
func URLWithPathParams(base string, path string, params map[string]interface{}) (u *url.URL) {

	u, err := url.Parse(base)
	if err != nil {
		log.Fatal(err)
	}

	if len(path) > 0 {
		u, err = u.Parse(path)
		if err != nil {
			log.Fatal(err)
		}
	}

	q := u.Query()

	for k, v := range params {
		val := reflect.ValueOf(v)

		switch val.Kind() {
		case reflect.Slice:
			if val.IsNil() { // TODO: add an option to ignore empty values
				q.Set(k, "")
				continue
			}
			fallthrough

		case reflect.Array:
			for i := 0; i < val.Len(); i++ {
				av := val.Index(i)

				if canStringify(av) {
					q.Add(k, fmt.Sprintf("%v", av))
				}
			}

		default:
			if canStringify(val) {
				q.Set(k, fmt.Sprintf("%v", v))
			} else {
				log.Fatal("Invalid type ", val)
			}
		}
	}

	u.RawQuery = q.Encode()
	return u
}

func URLWithParams(base string, params map[string]interface{}) (u *url.URL) {
	return URLWithPathParams(base, "", params)
}

//
// http.Get with params
//
func Get(urlStr string, params map[string]interface{}) (*HttpResponse, error) {
	resp, err := DefaultClient.Get(URLWithParams(urlStr, params).String())
	if err == nil {
		return &HttpResponse{*resp}, nil
	} else {
		CloseResponse(resp)
		return nil, err
	}
}

//
// http.Post with params
//
func Post(urlStr string, params map[string]interface{}) (*HttpResponse, error) {
	resp, err := DefaultClient.PostForm(urlStr, URLWithParams(urlStr, params).Query())
	if err == nil {
		return &HttpResponse{*resp}, nil
	} else {
		CloseResponse(resp)
		return nil, err
	}
}

//
//  Read the body
//
func (resp *HttpResponse) Content() []byte {
	body, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	return body
}

//
//  Try to parse the response body as JSON
//
func (resp *HttpResponse) Json() (json *simplejson.Json) {
	json, _ = simplejson.LoadBytes(resp.Content())
	return
}

////////////////////////////////////////////////////////////////////////

//
// http.Client with some defaults and stuff
//
type HttpClient struct {
	// the http.Client
	client *http.Client

	// the base URL for this client
	BaseURL *url.URL

	// the client UserAgent string
	UserAgent string

	// Common headers to be passed on each request
	Headers map[string]string

	// if Verbose, log request and response info
	Verbose bool
}

//
// Create a new HttpClient
//
func NewHttpClient(base string) (httpClient *HttpClient) {
	httpClient = new(HttpClient)
	httpClient.client = &http.Client{CheckRedirect: httpClient.checkRedirect}
	httpClient.Headers = make(map[string]string)

	if u, err := url.Parse(base); err != nil {
		log.Fatal(err)
	} else {
		httpClient.BaseURL = u
	}

	return
}

//
// Allow connections via HTTPS even if something is wrong with the certificate
// (self-signed or expired)
//
func (self *HttpClient) AllowInsecure(insecure bool) {
	if insecure {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}

		self.client.Transport = tr
	} else {
		self.client.Transport = nil
	}
}

//
// Set connection timeout
//
func (self *HttpClient) SetTimeout(t time.Duration) {
	self.client.Timeout = t
}

//
// Set LocalAddr in Dialer
//
func (self *HttpClient) SetLocalAddr(addr string) {
	transport, ok := self.client.Transport.(*http.Transport)
	if transport == nil {
		if transport, ok = http.DefaultTransport.(*http.Transport); !ok {
			log.Println("SetLocalAddr for http.DefaultTransport != http.Transport")
			return
		}
	} else if !ok {
		log.Println("SetLocalAddr for client.Transport != http.Transport")
		return
	}
	if tcpaddr, err := net.ResolveTCPAddr("tcp", addr); err == nil {
		transport.Dial = (&net.Dialer{
			Timeout:   30 * time.Second, // defaults from net/http DefaultTransport
			KeepAlive: 30 * time.Second, // defaults from net/http DefaultTransport
			LocalAddr: tcpaddr,
		}).Dial
	} else {
		log.Println("Failed to resolve", addr, " to a TCP address")
	}
}

//
// add default headers plus extra headers
//
func (self *HttpClient) addHeaders(req *http.Request, headers map[string]string) {

	if len(self.UserAgent) > 0 {
		req.Header.Set("User-Agent", self.UserAgent)
	}

	for k, v := range self.Headers {
		req.Header.Set(k, v)
	}

	for k, v := range headers {
		if strings.ToLower(k) == "content-length" {
			if len, err := strconv.Atoi(v); err == nil && req.ContentLength <= 0 {
				req.ContentLength = int64(len)
			}
		} else {
			req.Header.Set(k, v)
		}
	}

}

//
// the callback for CheckRedirect, used to pass along the headers in case of redirection
//
func (self *HttpClient) checkRedirect(req *http.Request, via []*http.Request) error {
	if req.Method == "HEAD" {
		// don't follow redirects on a HEAD request
		return NoRedirect
	}

	if self.Verbose {
		log.Println("REDIRECT:", len(via), req.URL)
	}

	if len(via) >= 10 {
		return TooManyRedirects
	}

	// TODO: check for same host before adding headers
	self.addHeaders(req, nil)
	return nil
}

//
// Create a request object given the method, path, body and extra headers
//
func (self *HttpClient) Request(method string, urlpath string, body io.Reader, headers map[string]string) (req *http.Request) {
	if u, err := self.BaseURL.Parse(urlpath); err != nil {
		log.Fatal(err)
	} else {
		urlpath = u.String()
	}

	req, err := http.NewRequest(method, urlpath, body)
	if err != nil {
		log.Fatal(err)
	}

	self.addHeaders(req, headers)
	return
}

//
// Execute request
//
func (self *HttpClient) Do(req *http.Request) (*HttpResponse, error) {
	if self.Verbose {
		log.Println("REQUEST:", req.Method, req.URL, pretty.PrettyFormat(req.Header))
	}

	resp, err := self.client.Do(req)
	if urlerr, ok := err.(*url.Error); ok && urlerr.Err == NoRedirect {
		err = nil // redirect on HEAD is not an error
	}
	if err == nil {
		if self.Verbose {
			log.Println("RESPONSE:", resp.Status, pretty.PrettyFormat(resp.Header))
		}

		return &HttpResponse{*resp}, nil
	} else {
		if self.Verbose {
			log.Println("ERROR:", err, "REQUEST:", req.Method, req.URL, pretty.PrettyFormat(req.Header))
		}

		CloseResponse(resp)
		return nil, err
	}
}

//
// Execute a DELETE request
//
func (self *HttpClient) Delete(path string, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("DELETE", path, nil, headers)
	return self.Do(req)
}

//
// Execute a HEAD request
//
func (self *HttpClient) Head(path string, params map[string]interface{}, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("HEAD", URLWithParams(path, params).String(), nil, headers)
	return self.Do(req)
}

//
// Execute a GET request
//
func (self *HttpClient) Get(path string, params map[string]interface{}, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("GET", URLWithParams(path, params).String(), nil, headers)
	return self.Do(req)
}

//
// Execute a POST request
//
func (self *HttpClient) Post(path string, content io.Reader, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("POST", path, content, headers)
	return self.Do(req)
}

//
// Execute a PUT request
//
func (self *HttpClient) Put(path string, content io.Reader, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("PUT", path, content, headers)
	return self.Do(req)
}
<commit_msg>Added GetTransport / SetTransport to update connection transport<commit_after>package httpclient

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/gobs/pretty"
	"github.com/gobs/simplejson"
)

var (
	DefaultClient = &http.Client{} // we use our own default client, so we can change the TLS configuration

	NoRedirect       = errors.New("No redirect")
	TooManyRedirects = errors.New("stopped after 10 redirects")
)

//
// Allow connections via HTTPS even if something is wrong with the certificate
// (self-signed or expired)
//
func AllowInsecure(insecure bool) {
	if insecure {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}

		DefaultClient.Transport = tr
	} else {
		DefaultClient.Transport = nil
	}
}

//
// Set connection timeout
//
func SetTimeout(t time.Duration) {
	DefaultClient.Timeout = t
}

//
// HTTP error
//
type HttpError struct {
	Code    int
	Message string
}

func (e HttpError) Error() string {
	return e.Message
}

func (e HttpError) String() string {
	return fmt.Sprintf("ERROR: %v %v", e.Code, e.Message)
}

//
// CloseResponse makes sure we close the response body
//
func CloseResponse(r *http.Response) {
	if r != nil && r.Body != nil {
		io.Copy(ioutil.Discard, r.Body)
		r.Body.Close()
	}
}

//
// A wrapper for http.Response
//
type HttpResponse struct {
	http.Response
}

func (r *HttpResponse) ContentType() string {
	content_type := r.Header.Get("Content-Type")
	if len(content_type) == 0 {
		return content_type
	}

	return strings.TrimSpace(strings.Split(content_type, ";")[0])
}

//
// Close makes sure that all data from the body is read
// before closing the reader.
//
// If that is not the desider behaviour, just call HttpResponse.Body.Close()
//
func (r *HttpResponse) Close() {
	if r != nil {
		CloseResponse(&r.Response)
	}
}

//
// ResponseError checks the StatusCode and return an error if needed.
// The error is of type HttpError
//
func (r *HttpResponse) ResponseError() error {
	class := r.StatusCode / 100
	if class != 2 && class != 3 {
		return HttpError{Code: r.StatusCode, Message: "HTTP " + r.Status}
	}

	return nil
}

//
// Check if the input value is a "primitive" that can be safely stringified
//
func canStringify(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Bool,
		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Float32, reflect.Float64,
		reflect.String:
		return true
	default:
		return false
	}
}

//
// Given a base URL and a bag of parameteters returns the URL with the encoded parameters
//
func URLWithPathParams(base string, path string, params map[string]interface{}) (u *url.URL) {

	u, err := url.Parse(base)
	if err != nil {
		log.Fatal(err)
	}

	if len(path) > 0 {
		u, err = u.Parse(path)
		if err != nil {
			log.Fatal(err)
		}
	}

	q := u.Query()

	for k, v := range params {
		val := reflect.ValueOf(v)

		switch val.Kind() {
		case reflect.Slice:
			if val.IsNil() { // TODO: add an option to ignore empty values
				q.Set(k, "")
				continue
			}
			fallthrough

		case reflect.Array:
			for i := 0; i < val.Len(); i++ {
				av := val.Index(i)

				if canStringify(av) {
					q.Add(k, fmt.Sprintf("%v", av))
				}
			}

		default:
			if canStringify(val) {
				q.Set(k, fmt.Sprintf("%v", v))
			} else {
				log.Fatal("Invalid type ", val)
			}
		}
	}

	u.RawQuery = q.Encode()
	return u
}

func URLWithParams(base string, params map[string]interface{}) (u *url.URL) {
	return URLWithPathParams(base, "", params)
}

//
// http.Get with params
//
func Get(urlStr string, params map[string]interface{}) (*HttpResponse, error) {
	resp, err := DefaultClient.Get(URLWithParams(urlStr, params).String())
	if err == nil {
		return &HttpResponse{*resp}, nil
	} else {
		CloseResponse(resp)
		return nil, err
	}
}

//
// http.Post with params
//
func Post(urlStr string, params map[string]interface{}) (*HttpResponse, error) {
	resp, err := DefaultClient.PostForm(urlStr, URLWithParams(urlStr, params).Query())
	if err == nil {
		return &HttpResponse{*resp}, nil
	} else {
		CloseResponse(resp)
		return nil, err
	}
}

//
//  Read the body
//
func (resp *HttpResponse) Content() []byte {
	body, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	return body
}

//
//  Try to parse the response body as JSON
//
func (resp *HttpResponse) Json() (json *simplejson.Json) {
	json, _ = simplejson.LoadBytes(resp.Content())
	return
}

////////////////////////////////////////////////////////////////////////

//
// http.Client with some defaults and stuff
//
type HttpClient struct {
	// the http.Client
	client *http.Client

	// the base URL for this client
	BaseURL *url.URL

	// the client UserAgent string
	UserAgent string

	// Common headers to be passed on each request
	Headers map[string]string

	// if Verbose, log request and response info
	Verbose bool
}

//
// Create a new HttpClient
//
func NewHttpClient(base string) (httpClient *HttpClient) {
	httpClient = new(HttpClient)
	httpClient.client = &http.Client{CheckRedirect: httpClient.checkRedirect}
	httpClient.Headers = make(map[string]string)

	if u, err := url.Parse(base); err != nil {
		log.Fatal(err)
	} else {
		httpClient.BaseURL = u
	}

	return
}

//
// Set Transport
//
func (self *HttpClient) SetTransport(tr http.RoundTripper) {
	self.client.Transport = tr
}

//
// Get current Transport
//
func (self *HttpClient) GetTransport() http.RoundTripper {
	return self.client.Transport
}

//
// Allow connections via HTTPS even if something is wrong with the certificate
// (self-signed or expired)
//
func (self *HttpClient) AllowInsecure(insecure bool) {
	if insecure {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}

		self.client.Transport = tr
	} else {
		self.client.Transport = nil
	}
}

//
// Set connection timeout
//
func (self *HttpClient) SetTimeout(t time.Duration) {
	self.client.Timeout = t
}

//
// Set LocalAddr in Dialer
//
func (self *HttpClient) SetLocalAddr(addr string) {
	transport, ok := self.client.Transport.(*http.Transport)
	if transport == nil {
		if transport, ok = http.DefaultTransport.(*http.Transport); !ok {
			log.Println("SetLocalAddr for http.DefaultTransport != http.Transport")
			return
		}
	} else if !ok {
		log.Println("SetLocalAddr for client.Transport != http.Transport")
		return
	}
	if tcpaddr, err := net.ResolveTCPAddr("tcp", addr); err == nil {
		transport.Dial = (&net.Dialer{
			Timeout:   30 * time.Second, // defaults from net/http DefaultTransport
			KeepAlive: 30 * time.Second, // defaults from net/http DefaultTransport
			LocalAddr: tcpaddr,
		}).Dial
	} else {
		log.Println("Failed to resolve", addr, " to a TCP address")
	}
}

//
// add default headers plus extra headers
//
func (self *HttpClient) addHeaders(req *http.Request, headers map[string]string) {

	if len(self.UserAgent) > 0 {
		req.Header.Set("User-Agent", self.UserAgent)
	}

	for k, v := range self.Headers {
		req.Header.Set(k, v)
	}

	for k, v := range headers {
		if strings.ToLower(k) == "content-length" {
			if len, err := strconv.Atoi(v); err == nil && req.ContentLength <= 0 {
				req.ContentLength = int64(len)
			}
		} else {
			req.Header.Set(k, v)
		}
	}

}

//
// the callback for CheckRedirect, used to pass along the headers in case of redirection
//
func (self *HttpClient) checkRedirect(req *http.Request, via []*http.Request) error {
	if req.Method == "HEAD" {
		// don't follow redirects on a HEAD request
		return NoRedirect
	}

	if self.Verbose {
		log.Println("REDIRECT:", len(via), req.URL)
	}

	if len(via) >= 10 {
		return TooManyRedirects
	}

	// TODO: check for same host before adding headers
	self.addHeaders(req, nil)
	return nil
}

//
// Create a request object given the method, path, body and extra headers
//
func (self *HttpClient) Request(method string, urlpath string, body io.Reader, headers map[string]string) (req *http.Request) {
	if u, err := self.BaseURL.Parse(urlpath); err != nil {
		log.Fatal(err)
	} else {
		urlpath = u.String()
	}

	req, err := http.NewRequest(method, urlpath, body)
	if err != nil {
		log.Fatal(err)
	}

	self.addHeaders(req, headers)
	return
}

//
// Execute request
//
func (self *HttpClient) Do(req *http.Request) (*HttpResponse, error) {
	if self.Verbose {
		log.Println("REQUEST:", req.Method, req.URL, pretty.PrettyFormat(req.Header))
	}

	resp, err := self.client.Do(req)
	if urlerr, ok := err.(*url.Error); ok && urlerr.Err == NoRedirect {
		err = nil // redirect on HEAD is not an error
	}
	if err == nil {
		if self.Verbose {
			log.Println("RESPONSE:", resp.Status, pretty.PrettyFormat(resp.Header))
		}

		return &HttpResponse{*resp}, nil
	} else {
		if self.Verbose {
			log.Println("ERROR:", err, "REQUEST:", req.Method, req.URL, pretty.PrettyFormat(req.Header))
		}

		CloseResponse(resp)
		return nil, err
	}
}

//
// Execute a DELETE request
//
func (self *HttpClient) Delete(path string, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("DELETE", path, nil, headers)
	return self.Do(req)
}

//
// Execute a HEAD request
//
func (self *HttpClient) Head(path string, params map[string]interface{}, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("HEAD", URLWithParams(path, params).String(), nil, headers)
	return self.Do(req)
}

//
// Execute a GET request
//
func (self *HttpClient) Get(path string, params map[string]interface{}, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("GET", URLWithParams(path, params).String(), nil, headers)
	return self.Do(req)
}

//
// Execute a POST request
//
func (self *HttpClient) Post(path string, content io.Reader, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("POST", path, content, headers)
	return self.Do(req)
}

//
// Execute a PUT request
//
func (self *HttpClient) Put(path string, content io.Reader, headers map[string]string) (*HttpResponse, error) {
	req := self.Request("PUT", path, content, headers)
	return self.Do(req)
}
<|endoftext|>


<commit_before>/* httpstress is a library for HTTP stress testing

It launches one goroutine per concurrent connection and does not count successful attempts.

A CLI utility is avaliable at github.com/chillum/httpstress-go */
package httpstress

import (
	"errors"
	"net/http"
	"regexp"
)

// Library version
const Version = "1.2"

/* httpstress.Test launches {conn} goroutines to fetch HTTP/HTTPS locations in {urls} list

If {max} is more than {conn}, more goroutines will spawn as other are finished,
resulting in {max} queries (but no more than {conn} in every moment).
Returns map: {url}, {fail count} or error (failed URL message). Example:

	urls := []string{"https://google.com", "http://localhost"}

	out, err := httpstress.Test(2, 4, urls) // Makes 4 HTTP requests total, 2 concurrent.

	if err != nil {
		// Invalid arguments.
	} else {
		if len(out) == 0 {
			// No failed requests.
		} else {
			// Process failed requests.
			for url, num := range out {
				log.Println(url, "failed", num, "times.")
			}
		}
	} */
func Test(conn int, max int, urls []string) (results map[string]int, err error) {
	for _, i := range urls {
		if m, _ := regexp.MatchString("^https?://", i); !m {
			err = errors.New("Not a HTTP/HTTPS URL: " + i)
			return
		}
	}

	results = make(map[string]int)
	failures := make(chan string)
	finished := make(chan bool)
	total := len(urls) - 1
	trans := &http.Transport{MaxIdleConnsPerHost: conn} // Use persistent connections.
	client := &http.Client{Transport: trans}
	n := 0
	i := 0

	if max < len(urls) {
		max = len(urls)
	}

	go logger(failures, results)
	for ; i < conn; i++ { // Launch initial workers.
		go worker(&urls[n], failures, finished, client)

		if n < total {
			n++
		} else {
			n = 0
		}
	}
	for ; i < max; i++ { // Launch more workers as initial finish.
		if <-finished {
			go worker(&urls[n], failures, finished, client)

			if n < total {
				n++
			} else {
				n = 0
			}
		}
	}
	for i := 0; i < conn; i++ { // Wait for active workers.
		<-finished
	}
	return
}

func logger(failures <-chan string, results map[string]int) {
	for {
		select {
		case url := <-failures:
			results[url]++
		}
	}
}

func worker(url *string, failures chan<- string, finished chan<- bool, client *http.Client) {
	resp, err := client.Get(*url)
	if err != nil {
		failures <- *url
	}
	if resp != nil {
		resp.Body.Close()
	}
	finished <- true
}
<commit_msg>more comments<commit_after>/* httpstress is a library for HTTP stress testing

It launches one goroutine per concurrent connection and does not count successful attempts.

A CLI utility is avaliable at github.com/chillum/httpstress-go */
package httpstress

import (
	"errors"
	"net/http"
	"regexp"
)

// Library version
const Version = "1.2"

/* httpstress.Test launches {conn} goroutines to fetch HTTP/HTTPS locations in {urls} list

If {max} is more than {conn}, more goroutines will spawn as other are finished,
resulting in {max} queries (but no more than {conn} in every moment).
Returns map: {url}, {fail count} or error (failed URL message). Example:

	urls := []string{"https://google.com", "http://localhost"}

	out, err := httpstress.Test(2, 4, urls) // Makes 4 HTTP requests total, 2 concurrent.

	if err != nil {
		// Invalid arguments.
	} else {
		if len(out) == 0 {
			// No failed requests.
		} else {
			// Process failed requests.
			for url, num := range out {
				log.Println(url, "failed", num, "times.")
			}
		}
	} */
func Test(conn int, max int, urls []string) (results map[string]int, err error) {
	for _, i := range urls {
		if m, _ := regexp.MatchString("^https?://", i); !m {
			err = errors.New("Not a HTTP/HTTPS URL: " + i)
			return
		}
	}

	results = make(map[string]int)
	failures := make(chan string)
	finished := make(chan bool)
	total := len(urls) - 1
	trans := &http.Transport{MaxIdleConnsPerHost: conn} // Use persistent connections.
	client := &http.Client{Transport: trans}
	n := 0
	i := 0

	// Ensure, every URL gets a request.
	if max < len(urls) {
		max = len(urls)
	}

	go logger(failures, results)
	for ; i < conn; i++ { // Launch initial workers.
		go worker(&urls[n], failures, finished, client)

		if n < total {
			n++
		} else {
			n = 0
		}
	}
	for ; i < max; i++ { // Launch more workers as initial finish.
		if <-finished {
			go worker(&urls[n], failures, finished, client)

			if n < total {
				n++
			} else {
				n = 0
			}
		}
	}
	for i := 0; i < conn; i++ { // Wait for active workers.
		<-finished
	}
	return
}

func logger(failures <-chan string, results map[string]int) {
	for {
		select {
		case url := <-failures:
			results[url]++
		}
	}
}

func worker(url *string, failures chan<- string, finished chan<- bool, client *http.Client) {
	resp, err := client.Get(*url)
	if err != nil {
		failures <- *url
	}
	if resp != nil {
		resp.Body.Close()
	}
	finished <- true
}
<|endoftext|>


<commit_before>package icmp

import (
	"fmt"
	"net"
	"syscall"
	"time"
)

// Trace represents trace properties
type Trace struct {
	src     string
	dest    string
	ttl     int
	timeout int64
}

// Init set the basic parameters
func (i *Trace) Init(dest string, timeout int64) {
	i.dest = dest
	i.timeout = timeout
}

// SetTTL set the IP packat time to live
func (i *Trace) SetTTL(ttl int) {
	i.ttl = ttl
}

// Send tries to send an UDP packet
func (i *Trace) Send() error {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
	if err != nil {
		println(err.Error())
	}
	defer syscall.Close(fd)
	// Set options
	syscall.SetsockoptInt(fd, 0x0, syscall.IP_TTL, i.ttl)

	b := net.ParseIP(i.dest).To4()
	addr := syscall.SockaddrInet4{
		Port: 33434,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}
	if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
		return err
	}

	return nil
}

// Bind starts to listen for ICMP reply
func (i *Trace) Bind() int {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
	if err != nil {
		println("e2", err.Error())
	}
	tv := syscall.NsecToTimeval(1e6 * i.timeout)
	err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
	if err != nil {
		println(err.Error())
	}
	b := net.ParseIP("0.0.0.0").To4()
	addr := syscall.SockaddrInet4{
		Port: 0,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}

	if err := syscall.Bind(fd, &addr); err != nil {
		println("e3", err.Error())
	}
	return fd
}

// Recv gets the replied icmp packet
func (i *Trace) Recv(fd int) (int, int, string) {
	var typ, code int
	buf := make([]byte, 512)
	n, from, err := syscall.Recvfrom(fd, buf, 0)
	if err == nil {
		buf = buf[:n]
		typ = int(buf[20])  // ICMP Type
		code = int(buf[21]) // ICMP Code
	}
	if typ != 0 {
		b := from.(*syscall.SockaddrInet4).Addr
		return typ, code, fmt.Sprintf("%v.%v.%v.%v", b[0], b[1], b[2], b[3])
	}
	return typ, code, ""
}

// Done close the socket
func (i *Trace) Done(fd int) {
	syscall.Close(fd)
}

// Run provides trace based on the other methods
func (i *Trace) Run(ip string) {
	var (
		trace Trace
		done  = false
	)
	ipAddr, err := net.ResolveIPAddr("ip4", ip)
	if err != nil {
		println("error: can not resolve")
		return
	}
	fmt.Printf("Traceroute to %s (%s), 30 hops max\n", ip, ipAddr.String())
	trace.Init(ipAddr.String(), 5000)
	fd := trace.Bind()
	for i := 1; i < 30; i++ {
		fmt.Printf("%d  ", i)
		for b := 0; b < 1; b++ {
			trace.SetTTL(i)
			ts := time.Now().UnixNano()
			err := trace.Send()
			if err != nil {
				println("e5", err.Error())
			}
			t, c, ip := trace.Recv(fd)
			elapsed := time.Now().UnixNano() - ts
			if t == 0 {
				fmt.Printf("*  ")
			} else {
				name, _ := net.LookupAddr(ip)
				if len(name) > 0 {
					fmt.Printf("%s (%s) %.3f ms ", name[0], ip, float64(elapsed)/1e6)
				} else {
					fmt.Printf("%s %.3f ms ", ip, float64(elapsed)/1e6)
				}
			}
			if c == 3 {
				done = true
			}
		}
		fmt.Printf("\n")
		if done {
			break
		}
	}
	trace.Done(fd)
}

// header returns icmp header
func (i *Trace) header() []byte {
	icmp := []byte{
		8, 0, // echo request, 8bit: type=8, 8bit: code=0
		0, 0, // 16bit: check sum=0(init)
		0, 0, 0, 0, // 32bit: not used=0
	}
	cs := checkSum(icmp)
	icmp[2] = byte(cs)
	icmp[3] = byte(cs >> 8)
	return icmp
}

// checksum calculates header checksum
func checkSum(value []byte) uint16 {
	sum := uint32(0)

	for i, n := 0, len(value); i < n; i += 2 {
		sum += uint32(value[i+1]<<8) + uint32(value[i])
	}

	sum = (sum >> 16) + (sum & 0xffff)
	sum += (sum >> 16)
	return uint16(^sum)
}
<commit_msg>clean up code, removed unuse codes<commit_after>package icmp

import (
	"fmt"
	"net"
	"syscall"
	"time"
)

// Trace represents trace properties
type Trace struct {
	src     string
	dest    string
	ttl     int
	timeout int64
}

// Init set the basic parameters
func (i *Trace) Init(dest string, timeout int64) {
	i.dest = dest
	i.timeout = timeout
}

// SetTTL set the IP packat time to live
func (i *Trace) SetTTL(ttl int) {
	i.ttl = ttl
}

// Send tries to send an UDP packet
func (i *Trace) Send() error {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
	if err != nil {
		println(err.Error())
	}
	defer syscall.Close(fd)
	// Set options
	syscall.SetsockoptInt(fd, 0x0, syscall.IP_TTL, i.ttl)

	b := net.ParseIP(i.dest).To4()
	addr := syscall.SockaddrInet4{
		Port: 33434,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}
	if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
		return err
	}

	return nil
}

// Bind starts to listen for ICMP reply
func (i *Trace) Bind() int {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
	if err != nil {
		println("e2", err.Error())
	}
	tv := syscall.NsecToTimeval(1e6 * i.timeout)
	err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
	if err != nil {
		println(err.Error())
	}
	b := net.ParseIP("0.0.0.0").To4()
	addr := syscall.SockaddrInet4{
		Port: 0,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}

	if err := syscall.Bind(fd, &addr); err != nil {
		println("e3", err.Error())
	}
	return fd
}

// Recv gets the replied icmp packet
func (i *Trace) Recv(fd int) (int, int, string) {
	var typ, code int
	buf := make([]byte, 512)
	n, from, err := syscall.Recvfrom(fd, buf, 0)
	if err == nil {
		buf = buf[:n]
		typ = int(buf[20])  // ICMP Type
		code = int(buf[21]) // ICMP Code
	}
	if typ != 0 {
		b := from.(*syscall.SockaddrInet4).Addr
		return typ, code, fmt.Sprintf("%v.%v.%v.%v", b[0], b[1], b[2], b[3])
	}
	return typ, code, ""
}

// Done close the socket
func (i *Trace) Done(fd int) {
	syscall.Close(fd)
}

// Run provides trace based on the other methods
func (i *Trace) Run(ip string) {
	var (
		trace Trace
		done  = false
	)
	ipAddr, err := net.ResolveIPAddr("ip4", ip)
	if err != nil {
		println("error: can not resolve")
		return
	}
	fmt.Printf("Traceroute to %s (%s), 30 hops max\n", ip, ipAddr.String())
	trace.Init(ipAddr.String(), 5000)
	fd := trace.Bind()
	for i := 1; i < 30; i++ {
		fmt.Printf("%d  ", i)
		for b := 0; b < 1; b++ {
			trace.SetTTL(i)
			ts := time.Now().UnixNano()
			err := trace.Send()
			if err != nil {
				println("e5", err.Error())
			}
			t, c, ip := trace.Recv(fd)
			elapsed := time.Now().UnixNano() - ts
			if t == 0 {
				fmt.Printf("*  ")
			} else {
				name, _ := net.LookupAddr(ip)
				if len(name) > 0 {
					fmt.Printf("%s (%s) %.3f ms ", name[0], ip, float64(elapsed)/1e6)
				} else {
					fmt.Printf("%s %.3f ms ", ip, float64(elapsed)/1e6)
				}
			}
			if c == 3 {
				done = true
			}
		}
		fmt.Printf("\n")
		if done {
			break
		}
	}
	trace.Done(fd)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"expvar"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestDumbNilishIndex(t *testing.T) {
	tmpl := loadIndex()
	buf := new(bytes.Buffer)
	err := tmpl.Execute(buf, &clientInfo{})
	if err != nil {
		t.Errorf("index execution blew up with nilish clientInfo: %#v", err)
	}
	if len(buf.Bytes()) == 0 {
		t.Errorf("index execution did not write anything")
	}
}

type acmeTest struct {
	challPath       string
	acmeRedirectURL string
	expected        string
	code            int
}

func TestACMERedirect(t *testing.T) {
	staticVars := new(expvar.Map).Init()
	staticHandler := makeStaticHandler("/static", staticVars)
	tests := []acmeTest{
		// same domain redirect, acmeRedirectURL leads with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/example.com",
			expected:        "/example.com/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com/",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
		// Busted acmeRedirectURL. Meant to be a domain, but was not.
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "example.com",
			expected:        "/.well-known/acme-challenge/example.com/.well-known/acme-challenge/foobar",
		},
		// same domain redirect, acmeRedirectURL leads and trails with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/okay/",
			expected:        "/example.com/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge",
			acmeRedirectURL: "http://example.com",
			expected:        "/.well-known/acme-challenge/",
			code:            http.StatusMovedPermanently,
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/",
			acmeRedirectURL: "http://example.com",
			expected:        "",
			code:            http.StatusOK,
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
	}
	for i, tt := range tests {
		tm := tlsMux("www.howsmyssl.com", "www.howsmyssl.com", tt.acmeRedirectURL, staticHandler)
		r, err := http.NewRequest("GET", tt.challPath, nil)
		if err != nil {
			t.Fatalf("borked request for %#v: %s", tt.challPath, err)
		}
		w := httptest.NewRecorder()
		tm.ServeHTTP(w, r)

		location := w.Header().Get("Location")
		if tt.code == 0 {
			tt.code = http.StatusFound
		}
		if w.Code != tt.code {
			t.Errorf("#%d, want %d, got %d", i, tt.code, w.Code)
		}
		if location != tt.expected {
			t.Errorf("#%d, want %#v, got %#v", i, tt.expected, location)
		}
	}
}

type vhostTest struct {
	rawVHost  string
	httpsAddr string

	expectedRouteHost    string
	expectedRedirectHost string
}

func TestVHostCalculation(t *testing.T) {
	tests := []vhostTest{
		vhostTest{
			rawVHost:             "www.howsmyssl.com",
			httpsAddr:            "0:10443",
			expectedRouteHost:    "www.howsmyssl.com",
			expectedRedirectHost: "www.howsmyssl.com",
		},
		vhostTest{
			rawVHost:             "localhost:10443",
			httpsAddr:            "localhost:10443",
			expectedRouteHost:    "localhost",
			expectedRedirectHost: "localhost:10443",
		},
		vhostTest{
			rawVHost:             "example.com:10443",
			httpsAddr:            "localhost:10443",
			expectedRouteHost:    "example.com",
			expectedRedirectHost: "example.com:10443",
		},
		vhostTest{
			rawVHost:             "example.com:443",
			httpsAddr:            "0:443",
			expectedRouteHost:    "example.com",
			expectedRedirectHost: "example.com",
		},
	}
	staticVars := new(expvar.Map).Init()
	staticHandler := makeStaticHandler("/static", staticVars)

	for i, vt := range tests {
		routeHost, redirectHost := calculateDomains(vt.rawVHost, vt.httpsAddr)
		if routeHost != vt.expectedRouteHost {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want routeHost %#v, got %s", i, vt.rawVHost, vt.httpsAddr, vt.expectedRouteHost, routeHost)
		}
		if redirectHost != vt.expectedRedirectHost {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want redirectHost %#v, got %#v", i, vt.rawVHost, vt.httpsAddr, vt.expectedRedirectHost, redirectHost)
		}

		tm := tlsMux(vt.expectedRouteHost, vt.expectedRedirectHost, "http://otherexample.com", staticHandler)
		r, err := http.NewRequest("GET", "https://howsmyssl.com/", nil)
		if err != nil {
			t.Fatalf("borked request")
		}
		w := httptest.NewRecorder()
		tm.ServeHTTP(w, r)
		expectedLocation := "https://" + vt.expectedRedirectHost + "/"
		location := w.Header()["Location"][0]
		if w.Code != http.StatusMovedPermanently {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want Code %d, got %d", i, vt.rawVHost, vt.httpsAddr, http.StatusMovedPermanently, w.Code)
		}
		if location != expectedLocation {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want Location %s, got %s", i, vt.rawVHost, vt.httpsAddr, expectedLocation, location)
		}
	}
}
<commit_msg>correct tests<commit_after>package main

import (
	"bytes"
	"expvar"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestDumbNilishIndex(t *testing.T) {
	tmpl := loadIndex()
	buf := new(bytes.Buffer)
	err := tmpl.Execute(buf, &clientInfo{})
	if err != nil {
		t.Errorf("index execution blew up with nilish clientInfo: %#v", err)
	}
	if len(buf.Bytes()) == 0 {
		t.Errorf("index execution did not write anything")
	}
}

type acmeTest struct {
	challPath       string
	acmeRedirectURL string
	expected        string
	code            int
}

func TestACMERedirect(t *testing.T) {
	staticVars := new(expvar.Map).Init()
	staticHandler := makeStaticHandler("/static", staticVars)
	tests := []acmeTest{
		// same domain redirect, acmeRedirectURL leads with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/example.com",
			expected:        "/example.com/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com/",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
		// Busted acmeRedirectURL. Meant to be a domain, but was not.
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "example.com",
			expected:        "/.well-known/acme-challenge/example.com/.well-known/acme-challenge/foobar",
		},
		// same domain redirect, acmeRedirectURL leads and trails with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/okay/",
			expected:        "/okay/.well-known/acme-challenge/foobar",
		},
		// same domain redirect, acmeRedirectURL leads and trails with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/okay/",
			expected:        "/okay/.well-known/acme-challenge/foobar",
		},
		// same domain redirect, acmeRedirectURL leads with "/"
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "/okay",
			expected:        "/okay/.well-known/acme-challenge/foobar",
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge",
			acmeRedirectURL: "http://example.com",
			expected:        "/.well-known/acme-challenge/",
			code:            http.StatusMovedPermanently,
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/",
			acmeRedirectURL: "http://example.com",
			expected:        "",
			code:            http.StatusOK,
		},
		{
			challPath:       "https://www.howsmyssl.com/.well-known/acme-challenge/foobar",
			acmeRedirectURL: "http://example.com",
			expected:        "http://example.com/.well-known/acme-challenge/foobar",
		},
	}
	for i, tt := range tests {
		tm := tlsMux("www.howsmyssl.com", "www.howsmyssl.com", tt.acmeRedirectURL, staticHandler)
		r, err := http.NewRequest("GET", tt.challPath, nil)
		if err != nil {
			t.Fatalf("borked request for %#v: %s", tt.challPath, err)
		}
		w := httptest.NewRecorder()
		tm.ServeHTTP(w, r)

		location := w.Header().Get("Location")
		if tt.code == 0 {
			tt.code = http.StatusFound
		}
		if w.Code != tt.code {
			t.Errorf("#%d, want %d, got %d", i, tt.code, w.Code)
		}
		if location != tt.expected {
			t.Errorf("#%d, %q, want %#v, got %#v", i, tt.acmeRedirectURL, tt.expected, location)
		}
	}
}

type vhostTest struct {
	rawVHost  string
	httpsAddr string

	expectedRouteHost    string
	expectedRedirectHost string
}

func TestVHostCalculation(t *testing.T) {
	tests := []vhostTest{
		vhostTest{
			rawVHost:             "www.howsmyssl.com",
			httpsAddr:            "0:10443",
			expectedRouteHost:    "www.howsmyssl.com",
			expectedRedirectHost: "www.howsmyssl.com",
		},
		vhostTest{
			rawVHost:             "localhost:10443",
			httpsAddr:            "localhost:10443",
			expectedRouteHost:    "localhost",
			expectedRedirectHost: "localhost:10443",
		},
		vhostTest{
			rawVHost:             "example.com:10443",
			httpsAddr:            "localhost:10443",
			expectedRouteHost:    "example.com",
			expectedRedirectHost: "example.com:10443",
		},
		vhostTest{
			rawVHost:             "example.com:443",
			httpsAddr:            "0:443",
			expectedRouteHost:    "example.com",
			expectedRedirectHost: "example.com",
		},
	}
	staticVars := new(expvar.Map).Init()
	staticHandler := makeStaticHandler("/static", staticVars)

	for i, vt := range tests {
		routeHost, redirectHost := calculateDomains(vt.rawVHost, vt.httpsAddr)
		if routeHost != vt.expectedRouteHost {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want routeHost %#v, got %s", i, vt.rawVHost, vt.httpsAddr, vt.expectedRouteHost, routeHost)
		}
		if redirectHost != vt.expectedRedirectHost {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want redirectHost %#v, got %#v", i, vt.rawVHost, vt.httpsAddr, vt.expectedRedirectHost, redirectHost)
		}

		tm := tlsMux(vt.expectedRouteHost, vt.expectedRedirectHost, "http://otherexample.com", staticHandler)
		r, err := http.NewRequest("GET", "https://howsmyssl.com/", nil)
		if err != nil {
			t.Fatalf("borked request")
		}
		w := httptest.NewRecorder()
		tm.ServeHTTP(w, r)
		expectedLocation := "https://" + vt.expectedRedirectHost + "/"
		location := w.Header()["Location"][0]
		if w.Code != http.StatusMovedPermanently {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want Code %d, got %d", i, vt.rawVHost, vt.httpsAddr, http.StatusMovedPermanently, w.Code)
		}
		if location != expectedLocation {
			t.Errorf("#%d vhost %#v, httpsAddr %#v: want Location %s, got %s", i, vt.rawVHost, vt.httpsAddr, expectedLocation, location)
		}
	}
}
<|endoftext|>


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

package bleve

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

func TestIndexCreateNewOverExisting(t *testing.T) {
	defer os.RemoveAll("testidx")

	index, err := New("testidx", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()
	index, err = New("testidx", NewIndexMapping())
	if err != ErrorIndexPathExists {
		t.Fatalf("expected error index path exists, got %v", err)
	}
}

func TestIndexOpenNonExisting(t *testing.T) {
	_, err := Open("doesnotexist")
	if err != ErrorIndexPathDoesNotExist {
		t.Fatalf("expected error index path does not exist, got %v", err)
	}
}

func TestIndexOpenMetaMissingOrCorrupt(t *testing.T) {
	defer os.RemoveAll("testidx")

	index, err := New("testidx", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()

	// now intentionally change the storage type
	ioutil.WriteFile("testidx/index_meta.json", []byte(`{"storage":"mystery"}`), 0666)

	index, err = Open("testidx")
	if err != ErrorUnknownStorageType {
		t.Fatalf("expected error unkown storage type, got %v", err)
	}

	// now intentionally corrupt the metadata
	ioutil.WriteFile("testidx/index_meta.json", []byte("corrupted"), 0666)

	index, err = Open("testidx")
	if err != ErrorIndexMetaCorrupt {
		t.Fatalf("expected error index metadata corrupted, got %v", err)
	}

	// no intentionally remove the metadata
	os.Remove("testidx/index_meta.json")

	index, err = Open("testidx")
	if err != ErrorIndexMetaMissing {
		t.Fatalf("expected error index metadata missing, got %v", err)
	}
}

func TestInMemIndex(t *testing.T) {

	index, err := New("", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()
}

func TestClosedIndex(t *testing.T) {
	index, err := New("", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()

	err = index.Index("test", "test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	err = index.Delete("test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	b := NewBatch()
	err = index.Batch(b)
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Document("test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.DocCount()
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Search(NewSearchRequest(NewTermQuery("test")))
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Fields()
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}
}
<commit_msg>added more index crud<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
//  except in compliance with the License. You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//  Unless required by applicable law or agreed to in writing, software distributed under the
//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
//  either express or implied. See the License for the specific language governing permissions
//  and limitations under the License.

package bleve

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

func TestCrud(t *testing.T) {
	defer os.RemoveAll("testidx")

	index, err := New("testidx", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}

	doca := map[string]interface{}{
		"name": "marty",
		"desc": "gophercon india",
	}
	err = index.Index("a", doca)
	if err != nil {
		t.Error(err)
	}

	docy := map[string]interface{}{
		"name": "jasper",
		"desc": "clojure",
	}
	err = index.Index("y", docy)
	if err != nil {
		t.Error(err)
	}

	err = index.Delete("y")
	if err != nil {
		t.Error(err)
	}

	docx := map[string]interface{}{
		"name": "rose",
		"desc": "googler",
	}
	err = index.Index("x", docx)
	if err != nil {
		t.Error(err)
	}

	err = index.SetInternal([]byte("status"), []byte("pending"))
	if err != nil {
		t.Error(err)
	}

	docb := map[string]interface{}{
		"name": "steve",
		"desc": "cbft master",
	}
	batch := NewBatch()
	batch.Index("b", docb)
	batch.Delete("x")
	batch.SetInternal([]byte("batchi"), []byte("batchv"))
	batch.DeleteInternal([]byte("status"))
	err = index.Batch(batch)
	if err != nil {
		t.Error(err)
	}
	val, err := index.GetInternal([]byte("batchi"))
	if err != nil {
		t.Error(err)
	}
	if string(val) != "batchv" {
		t.Errorf("expected 'batchv', got '%s'", val)
	}
	val, err = index.GetInternal([]byte("status"))
	if err != nil {
		t.Error(err)
	}
	if val != nil {
		t.Errorf("expected nil, got '%s'", val)
	}

	err = index.SetInternal([]byte("seqno"), []byte("7"))
	if err != nil {
		t.Error(err)
	}
	err = index.SetInternal([]byte("status"), []byte("ready"))
	if err != nil {
		t.Error(err)
	}
	err = index.DeleteInternal([]byte("status"))
	if err != nil {
		t.Error(err)
	}
	val, err = index.GetInternal([]byte("status"))
	if err != nil {
		t.Error(err)
	}
	if val != nil {
		t.Errorf("expected nil, got '%s'", val)
	}

	val, err = index.GetInternal([]byte("seqno"))
	if err != nil {
		t.Error(err)
	}
	if string(val) != "7" {
		t.Errorf("expected '7', got '%s'", val)
	}
}

func TestIndexCreateNewOverExisting(t *testing.T) {
	defer os.RemoveAll("testidx")

	index, err := New("testidx", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()
	index, err = New("testidx", NewIndexMapping())
	if err != ErrorIndexPathExists {
		t.Fatalf("expected error index path exists, got %v", err)
	}
}

func TestIndexOpenNonExisting(t *testing.T) {
	_, err := Open("doesnotexist")
	if err != ErrorIndexPathDoesNotExist {
		t.Fatalf("expected error index path does not exist, got %v", err)
	}
}

func TestIndexOpenMetaMissingOrCorrupt(t *testing.T) {
	defer os.RemoveAll("testidx")

	index, err := New("testidx", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()

	// now intentionally change the storage type
	ioutil.WriteFile("testidx/index_meta.json", []byte(`{"storage":"mystery"}`), 0666)

	index, err = Open("testidx")
	if err != ErrorUnknownStorageType {
		t.Fatalf("expected error unkown storage type, got %v", err)
	}

	// now intentionally corrupt the metadata
	ioutil.WriteFile("testidx/index_meta.json", []byte("corrupted"), 0666)

	index, err = Open("testidx")
	if err != ErrorIndexMetaCorrupt {
		t.Fatalf("expected error index metadata corrupted, got %v", err)
	}

	// no intentionally remove the metadata
	os.Remove("testidx/index_meta.json")

	index, err = Open("testidx")
	if err != ErrorIndexMetaMissing {
		t.Fatalf("expected error index metadata missing, got %v", err)
	}
}

func TestInMemIndex(t *testing.T) {

	index, err := New("", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()
}

func TestClosedIndex(t *testing.T) {
	index, err := New("", NewIndexMapping())
	if err != nil {
		t.Fatal(err)
	}
	index.Close()

	err = index.Index("test", "test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	err = index.Delete("test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	b := NewBatch()
	err = index.Batch(b)
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Document("test")
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.DocCount()
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Search(NewSearchRequest(NewTermQuery("test")))
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}

	_, err = index.Fields()
	if err != ErrorIndexClosed {
		t.Errorf("expected error index closed, got %v", err)
	}
}
<|endoftext|>