<commit_before>/*
 * LocationManager testing.
 */

package locationmanager

import (
	"fmt"
	"github.com/DiscoViking/goBrains/entity"
	"math"
	"testing"
)

// Limit movement to the default tank size.
func (c *circleHitbox) tUpdate(move CoordDelta) {
	c.update(move, coord{TANKSIZEX, TANKSIZEY})
}

// Verify that the number of hitboxes found were as expected.
func HitboxCheck(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected %v hitboxes, actual: %v",
			expected,
			actual)
	}
}

// Verify that the entries in the location manager are as expected.
func StoreCheck(t *testing.T, lm *LocationManager, entries int) {
	if entries != lm.NumberOwned() {
		t.Errorf("Expected %v entries in LM, found %v entries.",
			entries,
			lm.NumberOwned())
	}
}

// Test co-ordinate handling; coords and DeltaCoords.
func TestCoord(t *testing.T) {
	loc := coord{0, 0}

	// Update location and verify it.
	loc.update(1, 2)

	if loc.locX != 1 {
		t.Errorf("Expected x-location update to %v, got %v.", 1, loc.locX)
	}
	if loc.locY != 2 {
		t.Errorf("Expected y-location update to %v, got %v.", 2, loc.locY)
	}
}

// Test the circle hitboxes.
func TestCircleHitbox(t *testing.T) {

	// Update the location of the hitbox.
	hb := &circleHitbox{
		centre:      coord{0, 0},
		orientation: 0,
		radius:      10,
		entity:      &entity.TestEntity{TeRadius: 0},
	}

	move := CoordDelta{1, 0}
	hb.tUpdate(move)

	if hb.centre.locX != 1 {
		t.Errorf("Expected x-location update to %v, got %v.", 1, hb.centre.locX)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	move = CoordDelta{0, math.Pi / 2}
	hb.tUpdate(move)

	if hb.orientation != (math.Pi / 2) {
		t.Errorf("Expected orientation update to %v, got %v.", (math.Pi / 2), hb.orientation)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	move = CoordDelta{2, 0}
	hb.tUpdate(move)

	if hb.centre.locY != 2 {
		t.Errorf("Expected y-location update to %v, got %v.", 2, hb.centre.locY)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	// Run checks on points inside and outside the hitbox.
	hb = &circleHitbox{
		centre:      coord{0, 0},
		orientation: (math.Pi * 2 / 6),
		radius:      10,
		entity:      &entity.TestEntity{TeRadius: 0},
	}

	loc := coord{1, 2}
	if !hb.isInside(loc) {
		t.Errorf("Expected location (1, 2) to be inside hitbox.  It wasn't.")
	}

	loc = coord{12, 8}
	if hb.isInside(loc) {
		t.Errorf("Expected location (12, 8) to be outside hitbox.  It wasn't.")
	}
}

// Test the location interface.
func TestLocation(t *testing.T) {

	// Set up a new location manager.
	lm := New()

	// The entity to query for.
	ent := &entity.TestEntity{TeRadius: 5}

	// Query for the entity which LM does not know about.  This must fail.
	res, comb := lm.GetLocation(ent)
	locx, locy, orient := comb.X, comb.Y, comb.Orient

	if res {
		t.Errorf("Lookup of unknown object succeeded; returned: (%v, %v, %v, %v))",
			res, locx, locy, orient)
		lm.PrintDebug()
	}

	// Add the entity and query for it.
	lm.AddEntAtLocation(ent, Combination{0, 0, 0})
	res, comb = lm.GetLocation(ent)
	locx, locy, orient = comb.X, comb.Y, comb.Orient

	if !res || (locx != 0) || (locy != 0) || (orient != 0) {
		t.Errorf("Lookup of known object failed; returned: (%v, %v, %v, %v))",
			res, locx, locy, orient)
		lm.PrintDebug()
	}
}

// Test the testing function - where entities start at the origin.
func TestOrigin(t *testing.T) {

	lmn := New()
	lmo := New()
	lmo.StartAtOrigin()

	entn := &entity.TestEntity{TeRadius: 5}
	ento := &entity.TestEntity{TeRadius: 5}
	lmn.AddEntity(entn)
	lmo.AddEntity(ento)

	res, comb := lmo.GetLocation(ento)
	if !res || (comb != Combination{0.0, 0.0, 0.0}) {
		t.Errorf("Position of entity incorrect; returned: (%v, %v)), expected: (%v, %v)",
			res, comb, true, Combination{0.0, 0.0, 0.0})
		lmo.PrintDebug()
	}

	res, comb = lmn.GetLocation(entn)
	if !res || (comb == Combination{0.0, 0.0, 0.0}) {
		t.Errorf("Position of entity incorrect; returned: (%v, %v)),  result away from origin",
			res, comb)
		lmn.PrintDebug()
	}

}

// Test basic collision detection interface.
func TestDetection(t *testing.T) {

	// A test location find collisions here.
	var loc CoordDelta

	// Entities at a location.
	var col []entity.Entity

	// Set up a new location manager.
	cm := New()

	// Add two entities to be managed.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}

	cm.AddEntAtLocation(ent1, Combination{0.0, 0.0, 0.0})
	cm.AddEntAtLocation(ent2, Combination{0.0, 0.0, 0.0})

	HitboxCheck(t, 2, len(cm.hitboxes))

	// Check there are two hitboxes found at the origin.
	loc = CoordDelta{0, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 2, len(col))

	// Move a hitbox and verify it's moved.
	move := CoordDelta{10, 0}
	cm.ChangeLocation(move, ent2)

	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	// Verify that we can detect the moved entity.
	loc = CoordDelta{10, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	// Reduce radius of the entity at the origin and verify we stop detecting it.
	loc = CoordDelta{2, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	cm.ChangeRadius(1, ent1)
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 0, len(col))

	// A radius reduced to zero cannot be detected at all.
	loc = CoordDelta{0, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	cm.ChangeRadius(0, ent1)
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 0, len(col))
}

// Test object storage within LocationManager.
func TestStorage(t *testing.T) {
	// Set up a new location manager.
	cm := New()

	// Add two entities to be managed.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}

	cm.AddEntity(ent1)
	cm.AddEntity(ent2)

	StoreCheck(t, cm, 2)

	// Remove the entities from the CM.
	cm.RemoveEntity(ent1)
	cm.RemoveEntity(ent2)
	StoreCheck(t, cm, 0)

	// Add a new entry.
	cm.AddEntity(ent1)
	StoreCheck(t, cm, 1)

	// Extend the list again.
	ent3 := &entity.TestEntity{TeRadius: 5}
	cm.AddEntity(ent2)
	cm.AddEntity(ent3)
	StoreCheck(t, cm, 3)
}

// Test error cases.
func TestErrors(t *testing.T) {
	lm := New()

	// Two new entities, one of which is added to LM.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}
	lm.AddEntity(ent1)

	// Successful changes.
	lm.ChangeLocation(CoordDelta{0, 0}, ent1)
	lm.ChangeRadius(0, ent1)

	// Error changes.
	lm.ChangeLocation(CoordDelta{0, 0}, ent2)
	lm.ChangeRadius(0, ent2)
}

type tankSize struct {
	x, y float64
}

// Test how far we can go in a direction.
func tankDirection(t *testing.T, s tankSize, angle float64, exp coord) {

	cm := NewLocationManager(s.x, s.y)
	ent := &entity.TestEntity{TeRadius: 5}
	cm.AddEntAtLocation(ent, Combination{0.0, 0.0, angle})
	move := CoordDelta{TANKSIZEX * 99, 0}
	cm.ChangeLocation(move, ent)
	res, comb := cm.GetLocation(ent)
	locx, locy := comb.X, comb.Y

	if !res || (locx != exp.locX) || (locy != exp.locY) {
		t.Errorf("Expected entity to update location to maximum at (%v, %v), actually moved to (%v, %v)",
			s.x,
			s.y,
			locx,
			locy)
		cm.PrintDebug()
	}
}

// Ensure that we cannot exceed min or max range.
func tankLimit(t *testing.T, s tankSize) {

	// Move towards the maximum coordinate.
	tankDirection(t, s, (math.Pi / 4.0), coord{s.x, s.y})

	// Move away from the maximum coordinate.
	tankDirection(t, s, (math.Pi * (-3.0 / 4.0)), coord{0, 0})
}

// Test that units are held within the tank.
func TestTank(t *testing.T) {

	// Test various tank sizes.
	tankSizes := []tankSize{
		tankSize{TANKSIZEX, TANKSIZEY},      // Normal size.
		tankSize{TANKSIZEX, TANKSIZEX},      // Square.
		tankSize{TANKSIZEX, 10 * TANKSIZEY}, // Lopsided.
		tankSize{10 * TANKSIZEX, TANKSIZEY}, // Also lopsided.
		tankSize{0.0, 0.0},                  // Tiny.
	}

	for _, limit := range tankSizes {
		t.Logf("Test tank with size: (%v, %v)", limit.x, limit.y)

		// Attempt to reach max range.
		tankLimit(t, limit)
	}
}

// Debug functions.
func (cm *LocationManager) PrintDebug() {
	fmt.Printf("Location Manager: %v\n", cm)
	for ii, hb := range cm.hitboxes {
		fmt.Printf("  Hitbox %v\n", ii)
		fmt.Printf("    %v\n", hb)
	}
	fmt.Printf("\n")
}
<commit_msg>Updated LM tests to be compatible with new config model.<commit_after>/*
 * LocationManager testing.
 */

package locationmanager

import (
	"fmt"
	"math"
	"testing"

	"github.com/DiscoViking/goBrains/config"
	"github.com/DiscoViking/goBrains/entity"
)

const (
	BASE_WIDTH  = 800
	BASE_HEIGHT = 800
)

// Limit movement to the default tank size.
func (c *circleHitbox) tUpdate(move CoordDelta) {
	c.update(move, coord{BASE_WIDTH, BASE_HEIGHT})
}

// Verify that the number of hitboxes found were as expected.
func HitboxCheck(t *testing.T, expected, actual int) {
	if expected != actual {
		t.Errorf("Expected %v hitboxes, actual: %v",
			expected,
			actual)
	}
}

// Verify that the entries in the location manager are as expected.
func StoreCheck(t *testing.T, lm *LocationManager, entries int) {
	if entries != lm.NumberOwned() {
		t.Errorf("Expected %v entries in LM, found %v entries.",
			entries,
			lm.NumberOwned())
	}
}

// Test co-ordinate handling; coords and DeltaCoords.
func TestCoord(t *testing.T) {
	loc := coord{0, 0}

	// Update location and verify it.
	loc.update(1, 2)

	if loc.locX != 1 {
		t.Errorf("Expected x-location update to %v, got %v.", 1, loc.locX)
	}
	if loc.locY != 2 {
		t.Errorf("Expected y-location update to %v, got %v.", 2, loc.locY)
	}
}

// Test the circle hitboxes.
func TestCircleHitbox(t *testing.T) {

	// Update the location of the hitbox.
	hb := &circleHitbox{
		centre:      coord{0, 0},
		orientation: 0,
		radius:      10,
		entity:      &entity.TestEntity{TeRadius: 0},
	}

	move := CoordDelta{1, 0}
	hb.tUpdate(move)

	if hb.centre.locX != 1 {
		t.Errorf("Expected x-location update to %v, got %v.", 1, hb.centre.locX)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	move = CoordDelta{0, math.Pi / 2}
	hb.tUpdate(move)

	if hb.orientation != (math.Pi / 2) {
		t.Errorf("Expected orientation update to %v, got %v.", (math.Pi / 2), hb.orientation)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	move = CoordDelta{2, 0}
	hb.tUpdate(move)

	if hb.centre.locY != 2 {
		t.Errorf("Expected y-location update to %v, got %v.", 2, hb.centre.locY)
		fmt.Printf("  Hitbox: %v\n", hb)
	}

	// Run checks on points inside and outside the hitbox.
	hb = &circleHitbox{
		centre:      coord{0, 0},
		orientation: (math.Pi * 2 / 6),
		radius:      10,
		entity:      &entity.TestEntity{TeRadius: 0},
	}

	loc := coord{1, 2}
	if !hb.isInside(loc) {
		t.Errorf("Expected location (1, 2) to be inside hitbox.  It wasn't.")
	}

	loc = coord{12, 8}
	if hb.isInside(loc) {
		t.Errorf("Expected location (12, 8) to be outside hitbox.  It wasn't.")
	}
}

// Test the location interface.
func TestLocation(t *testing.T) {

	// Set up a new location manager.
	lm := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)

	// The entity to query for.
	ent := &entity.TestEntity{TeRadius: 5}

	// Query for the entity which LM does not know about.  This must fail.
	res, comb := lm.GetLocation(ent)
	locx, locy, orient := comb.X, comb.Y, comb.Orient

	if res {
		t.Errorf("Lookup of unknown object succeeded; returned: (%v, %v, %v, %v))",
			res, locx, locy, orient)
		lm.PrintDebug()
	}

	// Add the entity and query for it.
	lm.AddEntAtLocation(ent, Combination{0, 0, 0})
	res, comb = lm.GetLocation(ent)
	locx, locy, orient = comb.X, comb.Y, comb.Orient

	if !res || (locx != 0) || (locy != 0) || (orient != 0) {
		t.Errorf("Lookup of known object failed; returned: (%v, %v, %v, %v))",
			res, locx, locy, orient)
		lm.PrintDebug()
	}
}

// Test the testing function - where entities start at the origin.
func TestOrigin(t *testing.T) {

	lmn := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)
	lmo := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)
	lmo.StartAtOrigin()

	entn := &entity.TestEntity{TeRadius: 5}
	ento := &entity.TestEntity{TeRadius: 5}
	lmn.AddEntity(entn)
	lmo.AddEntity(ento)

	res, comb := lmo.GetLocation(ento)
	if !res || (comb != Combination{0.0, 0.0, 0.0}) {
		t.Errorf("Position of entity incorrect; returned: (%v, %v)), expected: (%v, %v)",
			res, comb, true, Combination{0.0, 0.0, 0.0})
		lmo.PrintDebug()
	}

	res, comb = lmn.GetLocation(entn)
	if !res || (comb == Combination{0.0, 0.0, 0.0}) {
		t.Errorf("Position of entity incorrect; returned: (%v, %v)),  result away from origin",
			res, comb)
		lmn.PrintDebug()
	}

}

// Test basic collision detection interface.
func TestDetection(t *testing.T) {

	// A test location find collisions here.
	var loc CoordDelta

	// Entities at a location.
	var col []entity.Entity

	// Set up a new location manager.
	cm := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)

	// Add two entities to be managed.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}

	cm.AddEntAtLocation(ent1, Combination{0.0, 0.0, 0.0})
	cm.AddEntAtLocation(ent2, Combination{0.0, 0.0, 0.0})

	HitboxCheck(t, 2, len(cm.hitboxes))

	// Check there are two hitboxes found at the origin.
	loc = CoordDelta{0, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 2, len(col))

	// Move a hitbox and verify it's moved.
	move := CoordDelta{10, 0}
	cm.ChangeLocation(move, ent2)

	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	// Verify that we can detect the moved entity.
	loc = CoordDelta{10, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	// Reduce radius of the entity at the origin and verify we stop detecting it.
	loc = CoordDelta{2, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	cm.ChangeRadius(1, ent1)
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 0, len(col))

	// A radius reduced to zero cannot be detected at all.
	loc = CoordDelta{0, 0}
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 1, len(col))

	cm.ChangeRadius(0, ent1)
	col = cm.GetCollisions(loc, ent1)
	HitboxCheck(t, 0, len(col))
}

// Test object storage within LocationManager.
func TestStorage(t *testing.T) {
	// Set up a new location manager.
	cm := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)

	// Add two entities to be managed.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}

	cm.AddEntity(ent1)
	cm.AddEntity(ent2)

	StoreCheck(t, cm, 2)

	// Remove the entities from the CM.
	cm.RemoveEntity(ent1)
	cm.RemoveEntity(ent2)
	StoreCheck(t, cm, 0)

	// Add a new entry.
	cm.AddEntity(ent1)
	StoreCheck(t, cm, 1)

	// Extend the list again.
	ent3 := &entity.TestEntity{TeRadius: 5}
	cm.AddEntity(ent2)
	cm.AddEntity(ent3)
	StoreCheck(t, cm, 3)
}

// Test error cases.
func TestErrors(t *testing.T) {
	lm := NewLocationManager(BASE_WIDTH, BASE_HEIGHT)

	// Two new entities, one of which is added to LM.
	ent1 := &entity.TestEntity{TeRadius: 5}
	ent2 := &entity.TestEntity{TeRadius: 5}
	lm.AddEntity(ent1)

	// Successful changes.
	lm.ChangeLocation(CoordDelta{0, 0}, ent1)
	lm.ChangeRadius(0, ent1)

	// Error changes.
	lm.ChangeLocation(CoordDelta{0, 0}, ent2)
	lm.ChangeRadius(0, ent2)
}

type tankSize struct {
	x, y float64
}

// Test how far we can go in a direction.
func tankDirection(t *testing.T, s tankSize, angle float64, exp coord) {

	cm := NewLocationManager(s.x, s.y)
	ent := &entity.TestEntity{TeRadius: 5}
	cm.AddEntAtLocation(ent, Combination{0.0, 0.0, angle})
	move := CoordDelta{s.x * 99, 0}
	cm.ChangeLocation(move, ent)
	res, comb := cm.GetLocation(ent)
	locx, locy := comb.X, comb.Y

	if !res || (locx != exp.locX) || (locy != exp.locY) {
		t.Errorf("Expected entity to update location to maximum at (%v, %v), actually moved to (%v, %v)",
			s.x,
			s.y,
			locx,
			locy)
		cm.PrintDebug()
	}
}

// Ensure that we cannot exceed min or max range.
func tankLimit(t *testing.T, s tankSize) {

	// Move towards the maximum coordinate.
	tankDirection(t, s, (math.Pi / 4.0), coord{s.x, s.y})

	// Move away from the maximum coordinate.
	tankDirection(t, s, (math.Pi * (-3.0 / 4.0)), coord{0, 0})
}

// Test that units are held within the tank.
func TestTank(t *testing.T) {

	// Test various tank sizes.
	tankSizes := []tankSize{
		tankSize{BASE_WIDTH, BASE_HEIGHT},      // Normal size.
		tankSize{BASE_WIDTH, BASE_HEIGHT},      // Square.
		tankSize{BASE_WIDTH, 10 * BASE_HEIGHT}, // Lopsided.
		tankSize{10 * BASE_WIDTH, BASE_HEIGHT}, // Also lopsided.
		tankSize{0.0, 0.0},                     // Tiny.
	}

	for _, limit := range tankSizes {
		t.Logf("Test tank with size: (%v, %v)", limit.x, limit.y)

		// Attempt to reach max range.
		tankLimit(t, limit)
	}
}

// Debug functions.
func (cm *LocationManager) PrintDebug() {
	fmt.Printf("Location Manager: %v\n", cm)
	for ii, hb := range cm.hitboxes {
		fmt.Printf("  Hitbox %v\n", ii)
		fmt.Printf("    %v\n", hb)
	}
	fmt.Printf("\n")
}

// Tests we can load a new LM with settings from global config.
func TestNew(t *testing.T) {
	config.Load("../config/test_config.gcfg")
	lm := New()

	exp := coord{800, 800}
	if lm.maxPoint != exp {
		t.Errorf("Wrong max point. Expected %v, got %v.", exp, lm.maxPoint)
	}
}
<|endoftext|>


<commit_before>package gedcom

import (
	"errors"
	"io"
	"strings"

	"github.com/MJKWoolnough/parser"
)

const (
	alpha       = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
	delim       = " "
	digit       = "0123456789"
	alphanum    = alpha + digit
	otherchar   = "!\"$%&'()*+,-./:;<=>?[\\]^`{|}~" // + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe" // ANSEL
	nonAt       = alpha + digit + otherchar + " #"
	terminators = "\r\n"
	anyChar     = alpha + digit + otherchar + "# @"
	levelIgnore = terminators + delim + "	"
	invalidchar = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\xab\xac\xad\x1e\x1f\x7f" + terminators + "@"
)

const (
	tokenLevel parser.TokenType = iota
	tokenXref
	tokenTag
	tokenPointer
	tokenLine
	tokenEndLine
)

type tokeniser struct {
	parser.Parser
	options
}

func newTokeniser(r io.Reader, o options) *tokeniser {
	t := &tokeniser{
		Parser:  parser.NewReaderParser(r),
		options: o,
	}
	t.State = t.level
	return t
}

func (t *tokeniser) level() (parser.Token, parser.StateFn) {
	t.AcceptRun(levelIgnore)
	t.Get()
	if t.Peek() == -1 {
		return t.Done()
	}
	if !t.Accept(digit) {
		t.Err = ErrInvalidLevel
		return t.Error()
	}
	t.AcceptRun(digit)
	if !t.Accept(delim) {
		t.Err = ErrMissingDelim
		return t.Error()
	}
	return parser.Token{
		tokenLevel,
		strings.TrimSpace(t.Get()),
	}, t.optionalXrefID
}

func (t *tokeniser) optionalXrefID() (parser.Token, parser.StateFn) {
	if t.Peek() == '@' {
		return t.xrefID()
	}
	return t.tag()
}

func (t *tokeniser) readPointer() (string, error) {
	if !t.Accept(alphanum) {
		return "", ErrInvalidPointer
	}
	t.AcceptRun(nonAt)
	if !t.Accept("@") {
		return "", ErrInvalidPointer
	}
	pointer := t.Get()
	return pointer[1 : len(pointer)-1], nil
}

func (t *tokeniser) xrefID() (parser.Token, parser.StateFn) {
	t.Accept("@")
	pointer, err := t.readPointer()
	if err != nil {
		t.Err = err
		return t.Error()
	}
	if !t.Accept(delim) {
		t.Err = ErrMissingDelim
		return t.Error()
	}
	t.Get()
	return parser.Token{
		tokenXref,
		strings.Trim(pointer, "@"),
	}, t.tag
}

func (t *tokeniser) tag() (parser.Token, parser.StateFn) {
	if !t.Accept(alphanum) {
		t.Err = ErrInvalidTag
		return t.Error()
	}
	t.AcceptRun(alphanum)
	tag := t.Get()
	if t.Accept(delim) {
		t.Get()
		return parser.Token{
			tokenTag,
			tag,
		}, t.lineValue
	}
	next := t.endLine
	if t.Peek() == -1 {
		next = t.Done
	} else {
		if !t.Accept(terminators) {
			t.Err = ErrInvalidTag
			return t.Error()
		}
		t.AcceptRun(terminators)
		t.Get()
	}
	return parser.Token{
		tokenTag,
		tag,
	}, next
}

func (t *tokeniser) endLine() (parser.Token, parser.StateFn) {
	return parser.Token{
		tokenEndLine,
		"",
	}, t.level
}

func (t *tokeniser) lineValue() (parser.Token, parser.StateFn) {
	if t.Peek() == '@' {
		t.Accept("@")
		if t.Peek() != '@' {
			pointer, err := t.readPointer()
			if err != nil {
				if !t.allowInvalidEscape {
					t.Err = err
					return t.Error()
				}
			} else {
				t.AcceptRun(terminators)
				t.Get()
				return parser.Token{
					tokenPointer,
					pointer,
				}, t.level
			}
		}
	}
	next := t.level
	for {
		for {
			if t.allowUnknownCharset && t.Except(invalidchar) {
				t.ExceptRun(invalidchar)
			} else if t.Accept(nonAt) {
				t.AcceptRun(nonAt)
			} else if t.Accept("@") {
				if t.allowInvalidEscape || t.Accept("@") {
					continue
				}
				if !t.Accept("#") {
					t.Err = ErrBadEscape
					return t.Error()
				}
				if t.allowUnknownCharset {
					t.ExceptRun(invalidchar)
				} else {
					t.AcceptRun(nonAt)
				}
				if !t.Accept("@") {
					t.Err = ErrBadEscape
					return t.Error()
				}
			} else {
				break
			}
		}
		p := t.Peek()
		if p == -1 {
			next = t.Done
			break
		}
		if strings.ContainsRune(terminators, p) {
			t.AcceptRun(terminators)
			if !t.allowTerminatorsInValue {
				break
			}
			p = t.Peek()
			if p == -1 {
				next = t.Done
				break
			}
			if strings.ContainsRune(digit, p) {
				break
			}
		} else {
			if !t.allowInvalidChars {
				t.Err = ErrBadChar
				return t.Error()
			}
			t.Except("")
		}
	}
	return parser.Token{
		tokenLine,
		strings.TrimSpace(t.Get()),
	}, next
}

// Errors
var (
	ErrInvalidLevel   = errors.New("invalid level num")
	ErrMissingDelim   = errors.New("missing delminitator")
	ErrInvalidPointer = errors.New("invalid pointer string")
	ErrInvalidTag     = errors.New("invalid tag")
	ErrBadEscape      = errors.New("bad escape sequence")
	ErrBadChar        = errors.New("bad character")
)
<commit_msg>Updated to new parser package<commit_after>package gedcom

import (
	"errors"
	"io"
	"strings"

	"github.com/MJKWoolnough/parser"
)

const (
	alpha       = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
	delim       = " "
	digit       = "0123456789"
	alphanum    = alpha + digit
	otherchar   = "!\"$%&'()*+,-./:;<=>?[\\]^`{|}~" // + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe" // ANSEL
	nonAt       = alpha + digit + otherchar + " #"
	terminators = "\r\n"
	anyChar     = alpha + digit + otherchar + "# @"
	levelIgnore = terminators + delim + "	"
	invalidchar = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\xab\xac\xad\x1e\x1f\x7f" + terminators + "@"
)

const (
	tokenLevel parser.TokenType = iota
	tokenXref
	tokenTag
	tokenPointer
	tokenLine
	tokenEndLine
)

type tokeniser struct {
	parser.Parser
	options
}

func newTokeniser(r io.Reader, o options) *tokeniser {
	t := &tokeniser{
		Parser:  parser.NewReaderParser(r),
		options: o,
	}
	t.TokeniserState(t.level)
	return t
}

func (t *tokeniser) level(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	p.AcceptRun(levelIgnore)
	p.Lexeme()
	if p.Peek() == -1 {
		return p.Done()
	}
	if !p.Accept(digit) {
		p.SetError(ErrInvalidLevel)
		return p.Error()
	}
	p.AcceptRun(digit)
	if !p.Accept(delim) {
		p.SetError(ErrMissingDelim)
		return p.Error()
	}
	return parser.Token{
		tokenLevel,
		strings.TrimSpace(p.Lexeme()),
	}, t.optionalXrefID
}

func (t *tokeniser) optionalXrefID(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	if p.Peek() == '@' {
		return t.xrefID(p)
	}
	return t.tag(p)
}

func (t *tokeniser) readPointer(p *parser.Tokeniser) (string, error) {
	if !p.Accept(alphanum) {
		return "", ErrInvalidPointer
	}
	p.AcceptRun(nonAt)
	if !p.Accept("@") {
		return "", ErrInvalidPointer
	}
	pointer := p.Lexeme()
	return pointer[1 : len(pointer)-1], nil
}

func (t *tokeniser) xrefID(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	p.Accept("@")
	pointer, err := t.readPointer(p)
	if err != nil {
		p.SetError(err)
		return p.Error()
	}
	if !p.Accept(delim) {
		p.SetError(ErrMissingDelim)
		return p.Error()
	}
	p.Lexeme()
	return parser.Token{
		tokenXref,
		strings.Trim(pointer, "@"),
	}, t.tag
}

func (t *tokeniser) tag(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	if !p.Accept(alphanum) {
		p.SetError(ErrInvalidTag)
		return p.Error()
	}
	p.AcceptRun(alphanum)
	tag := p.Lexeme()
	if p.Accept(delim) {
		p.Lexeme()
		return parser.Token{
			tokenTag,
			tag,
		}, t.lineValue
	}
	next := t.endLine
	if p.Peek() == -1 {
		next = (*parser.Tokeniser).Done
	} else {
		if !p.Accept(terminators) {
			p.SetError(ErrInvalidTag)
			return p.Error()
		}
		p.AcceptRun(terminators)
		p.Lexeme()
	}
	return parser.Token{
		tokenTag,
		tag,
	}, next
}

func (t *tokeniser) endLine(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	return parser.Token{
		tokenEndLine,
		"",
	}, t.level
}

func (t *tokeniser) lineValue(p *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
	if p.Peek() == '@' {
		p.Accept("@")
		if p.Peek() != '@' {
			pointer, err := t.readPointer(p)
			if err != nil {
				if !t.allowInvalidEscape {
					p.SetError(err)
					return p.Error()
				}
			} else {
				p.AcceptRun(terminators)
				p.Lexeme()
				return parser.Token{
					tokenPointer,
					pointer,
				}, t.level
			}
		}
	}
	next := t.level
	for {
		for {
			if t.allowUnknownCharset && p.Except(invalidchar) {
				p.ExceptRun(invalidchar)
			} else if p.Accept(nonAt) {
				p.AcceptRun(nonAt)
			} else if p.Accept("@") {
				if t.allowInvalidEscape || p.Accept("@") {
					continue
				}
				if !p.Accept("#") {
					p.SetError(ErrBadEscape)
					return p.Error()
				}
				if t.allowUnknownCharset {
					p.ExceptRun(invalidchar)
				} else {
					p.AcceptRun(nonAt)
				}
				if !p.Accept("@") {
					p.SetError(ErrBadEscape)
					return p.Error()
				}
			} else {
				break
			}
		}
		pe := p.Peek()
		if pe == -1 {
			next = (*parser.Tokeniser).Done
			break
		}
		if strings.ContainsRune(terminators, pe) {
			p.AcceptRun(terminators)
			if !t.allowTerminatorsInValue {
				break
			}
			pe = p.Peek()
			if pe == -1 {
				next = (*parser.Tokeniser).Done
				break
			}
			if strings.ContainsRune(digit, pe) {
				break
			}
		} else {
			if !t.allowInvalidChars {
				p.SetError(ErrBadChar)
				return p.Error()
			}
			p.Except("")
		}
	}
	return parser.Token{
		tokenLine,
		strings.TrimSpace(p.Lexeme()),
	}, next
}

// Errors
var (
	ErrInvalidLevel   = errors.New("invalid level num")
	ErrMissingDelim   = errors.New("missing delminitator")
	ErrInvalidPointer = errors.New("invalid pointer string")
	ErrInvalidTag     = errors.New("invalid tag")
	ErrBadEscape      = errors.New("bad escape sequence")
	ErrBadChar        = errors.New("bad character")
)
<|endoftext|>


<commit_before>package tor

import (
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gopher-net/dknet"
	"github.com/vishvananda/netlink"
)

// Return the IPv4 address of a network interface
func getIfaceAddr(name string) (*net.IPNet, error) {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		return nil, err
	}
	addrs, err := netlink.AddrList(iface, netlink.FAMILY_V4)
	if err != nil {
		return nil, err
	}
	if len(addrs) == 0 {
		return nil, fmt.Errorf("Interface %s has no IP addresses", name)
	}
	if len(addrs) > 1 {
		logrus.Infof("Interface [ %v ] has more than 1 IPv4 address. Defaulting to using [ %v ]\n", name, addrs[0].IP)
	}
	return addrs[0].IPNet, nil
}

// Set the IP addr of a netlink interface
func setInterfaceIP(name string, rawIP string) error {
	retries := 2
	var iface netlink.Link
	var err error
	for i := 0; i < retries; i++ {
		iface, err = netlink.LinkByName(name)
		if err == nil {
			break
		}
		logrus.Debugf("error retrieving new bridge netlink link [ %s ]... retrying", name)
		time.Sleep(2 * time.Second)
	}
	if err != nil {
		return fmt.Errorf("Abandoning retrieving the new bridge link from netlink, Run [ ip link ] to troubleshoot the error: %v", err)
	}
	ipNet, err := netlink.ParseIPNet(rawIP)
	if err != nil {
		return err
	}
	addr := &netlink.Addr{ipNet, ""}
	return netlink.AddrAdd(iface, addr)
}

// Create veth pair. Peername is renamed to eth0 in the container
func vethPair(suffix string, bridgeName string) (*netlink.Veth, error) {
	br, err := netlink.LinkByName(bridgeName)
	if err != nil {
		return nil, err
	}

	la := netlink.NewLinkAttrs()
	la.Name = torPortPrefix + suffix
	la.MasterIndex = br.Attrs().Index

	return &netlink.Veth{
		LinkAttrs: la,
		PeerName:  "ethc" + suffix,
	}, nil
}

// Enable a netlink interface
func interfaceUp(name string) error {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		return fmt.Errorf("Error retrieving a link named [ %s ]: %v", iface.Attrs().Name, err)
	}
	return netlink.LinkSetUp(iface)
}

func truncateID(id string) string {
	return id[:5]
}

func getBridgeMTU(opts map[string]interface{}) (int, error) {
	bridgeMTU := defaultMTU
	if opts != nil {
		if mtu, ok := opts[mtuOption].(int); ok {
			bridgeMTU = mtu
		}
	}
	return bridgeMTU, nil
}

func getBridgeName(id string, opts map[string]interface{}) (string, error) {
	bridgeName := bridgePrefix + truncateID(id)
	if opts != nil {
		if name, ok := opts[bridgeNameOption].(string); ok {
			bridgeName = name
		}
	}
	return bridgeName, nil
}

func getGatewayIP(r *dknet.CreateNetworkRequest) (string, string, error) {
	// FIXME: Dear future self, I'm sorry for leaving you with this mess, but I want to get this working ASAP
	// This should be an array
	// We need to handle case where we have
	// a. v6 and v4 - dual stack
	// auxilliary address
	// multiple subnets on one network
	// also in that case, we'll need a function to determine the correct default gateway based on it's IP/Mask
	var gatewayIP string

	if len(r.IPv6Data) > 0 {
		if r.IPv6Data[0] != nil {
			if r.IPv6Data[0].Gateway != "" {
				gatewayIP = r.IPv6Data[0].Gateway
			}
		}
	}
	// Assumption: IPAM will provide either IPv4 OR IPv6 but not both
	// We may want to modify this in future to support dual stack
	if len(r.IPv4Data) > 0 {
		if r.IPv4Data[0] != nil {
			if r.IPv4Data[0].Gateway != "" {
				gatewayIP = r.IPv4Data[0].Gateway
			}
		}
	}

	if gatewayIP == "" {
		return "", "", fmt.Errorf("No gateway IP found")
	}
	parts := strings.Split(gatewayIP, "/")
	if parts[0] == "" || parts[1] == "" {
		return "", "", fmt.Errorf("Cannot split gateway IP address")
	}
	return parts[0], parts[1], nil
}

func (d *Driver) getTorRouterIP() (string, error) {
	c, err := d.dockerClient.InspectContainer(defaultTorContainer)
	if err != nil {
		return "", fmt.Errorf("Getting tor routing container %s failed: %v", defaultTorContainer, err)
	}

	return c.NetworkSettings.IPAddress, nil
}
<commit_msg>make go gettable<commit_after>package tor

import (
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gopher-net/dknet"
	"github.com/vishvananda/netlink"
)

// Return the IPv4 address of a network interface
func getIfaceAddr(name string) (*net.IPNet, error) {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		return nil, err
	}
	addrs, err := netlink.AddrList(iface, netlink.FAMILY_V4)
	if err != nil {
		return nil, err
	}
	if len(addrs) == 0 {
		return nil, fmt.Errorf("Interface %s has no IP addresses", name)
	}
	if len(addrs) > 1 {
		logrus.Infof("Interface [ %v ] has more than 1 IPv4 address. Defaulting to using [ %v ]\n", name, addrs[0].IP)
	}
	return addrs[0].IPNet, nil
}

// Set the IP addr of a netlink interface
func setInterfaceIP(name string, rawIP string) error {
	retries := 2
	var iface netlink.Link
	var err error
	for i := 0; i < retries; i++ {
		iface, err = netlink.LinkByName(name)
		if err == nil {
			break
		}
		logrus.Debugf("error retrieving new bridge netlink link [ %s ]... retrying", name)
		time.Sleep(2 * time.Second)
	}
	if err != nil {
		return fmt.Errorf("Abandoning retrieving the new bridge link from netlink, Run [ ip link ] to troubleshoot the error: %v", err)
	}
	ipNet, err := netlink.ParseIPNet(rawIP)
	if err != nil {
		return err
	}
	addr := &netlink.Addr{ipNet, "", 0, 0}
	return netlink.AddrAdd(iface, addr)
}

// Create veth pair. Peername is renamed to eth0 in the container
func vethPair(suffix string, bridgeName string) (*netlink.Veth, error) {
	br, err := netlink.LinkByName(bridgeName)
	if err != nil {
		return nil, err
	}

	la := netlink.NewLinkAttrs()
	la.Name = torPortPrefix + suffix
	la.MasterIndex = br.Attrs().Index

	return &netlink.Veth{
		LinkAttrs: la,
		PeerName:  "ethc" + suffix,
	}, nil
}

// Enable a netlink interface
func interfaceUp(name string) error {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		return fmt.Errorf("Error retrieving a link named [ %s ]: %v", iface.Attrs().Name, err)
	}
	return netlink.LinkSetUp(iface)
}

func truncateID(id string) string {
	return id[:5]
}

func getBridgeMTU(opts map[string]interface{}) (int, error) {
	bridgeMTU := defaultMTU
	if opts != nil {
		if mtu, ok := opts[mtuOption].(int); ok {
			bridgeMTU = mtu
		}
	}
	return bridgeMTU, nil
}

func getBridgeName(id string, opts map[string]interface{}) (string, error) {
	bridgeName := bridgePrefix + truncateID(id)
	if opts != nil {
		if name, ok := opts[bridgeNameOption].(string); ok {
			bridgeName = name
		}
	}
	return bridgeName, nil
}

func getGatewayIP(r *dknet.CreateNetworkRequest) (string, string, error) {
	// FIXME: Dear future self, I'm sorry for leaving you with this mess, but I want to get this working ASAP
	// This should be an array
	// We need to handle case where we have
	// a. v6 and v4 - dual stack
	// auxilliary address
	// multiple subnets on one network
	// also in that case, we'll need a function to determine the correct default gateway based on it's IP/Mask
	var gatewayIP string

	if len(r.IPv6Data) > 0 {
		if r.IPv6Data[0] != nil {
			if r.IPv6Data[0].Gateway != "" {
				gatewayIP = r.IPv6Data[0].Gateway
			}
		}
	}
	// Assumption: IPAM will provide either IPv4 OR IPv6 but not both
	// We may want to modify this in future to support dual stack
	if len(r.IPv4Data) > 0 {
		if r.IPv4Data[0] != nil {
			if r.IPv4Data[0].Gateway != "" {
				gatewayIP = r.IPv4Data[0].Gateway
			}
		}
	}

	if gatewayIP == "" {
		return "", "", fmt.Errorf("No gateway IP found")
	}
	parts := strings.Split(gatewayIP, "/")
	if parts[0] == "" || parts[1] == "" {
		return "", "", fmt.Errorf("Cannot split gateway IP address")
	}
	return parts[0], parts[1], nil
}

func (d *Driver) getTorRouterIP() (string, error) {
	c, err := d.dockerClient.InspectContainer(defaultTorContainer)
	if err != nil {
		return "", fmt.Errorf("Getting tor routing container %s failed: %v", defaultTorContainer, err)
	}

	return c.NetworkSettings.IPAddress, nil
}
<|endoftext|>


<commit_before>package networkwebsockets

import (
	"errors"
	"log"
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"

	tls "github.com/richtr/go-tls-srp"
	"github.com/richtr/websocket"
)

const (
	// Time allowed to write a message to any websocket.
	writeWait = 10 * time.Second

	// Time allowed to read the next pong message from any websocket.
	pongWait = 60 * time.Second

	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10

	// Maximum message size allowed from any websocket.
	maxMessageSize = 8192
)

type MessageHandler interface {
	Read(buf []byte) error
	Write(buf []byte) error
}

// JSON structure to message sending
type WireMessage struct {
	// Proxy message type: "connect", "disconnect", "message", "broadcast"
	Action string `json:"action"`

	Source string `json:"source,omitempty"`

	Target string `json:"target,omitempty"`

	// Message contents
	Payload string `json:"data,omitempty"`

	// Whether this message originated from a Proxy object
	fromProxy bool `json:"-"`
}

type Transport struct {
	conn    *websocket.Conn
	handler MessageHandler
	open    bool
	done    chan int // blocks until .Stop() is called
}

func NewTransport(conn *websocket.Conn, handler MessageHandler) *Transport {
	transport := &Transport{
		conn:    conn,
		handler: handler,

		done: make(chan int, 1),
	}

	return transport
}

func (t *Transport) Start() {
	var wg sync.WaitGroup
	wg.Add(2)

	go t.writePump(&wg)
	go t.readPump(&wg)

	t.open = true

	wg.Wait()
}

func (t *Transport) Stop() {
	t.open = false

	t.conn.Close()
}

// StopNotify returns a channel that receives a empty integer
// when the transport is closed
func (t *Transport) StopNotify() <-chan int { return t.done }

func (t *Transport) Read(buf []byte) error {
	if !t.open {
		return errors.New("Transport is not currently active for reading")
	}

	if t.handler == nil {
		return errors.New("Cannot read message. Transport does not have a handler assigned")
	}

	return t.handler.Read(buf)
}

func (t *Transport) Write(buf []byte) error {
	if !t.open {
		return errors.New("Transport is not currently active for writing")
	}

	if t.handler == nil {
		return errors.New("Cannot write message. Transport does not have a handler assigned")
	}

	return t.handler.Write(buf)
}

// readPump pumps messages from an individual websocket connection to the dispatcher
func (t *Transport) readPump(wg *sync.WaitGroup) {
	t.conn.SetReadLimit(maxMessageSize)
	t.conn.SetReadDeadline(time.Now().Add(pongWait))
	t.conn.SetPongHandler(func(string) error {
		t.conn.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})

	wg.Done()

	for {
		opCode, buf, err := t.conn.ReadMessage()
		if err != nil || opCode != websocket.TextMessage {
			break
		}

		// Pass incoming message to our assigned message handler
		if err := t.Read(buf); err != nil {
			log.Printf("err: %v", err)
		}
	}

	// Indicate object is closed
	t.done <- 1
}

// writePump keeps an individual websocket connection alive
func (t *Transport) writePump(wg *sync.WaitGroup) {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
	}()

	wg.Done()

	for {
		select {
		case <-ticker.C:
			t.conn.SetWriteDeadline(time.Now().Add(writeWait))
			if err := t.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

/** TLS-SRP Dialer interface **/

type TLSSRPDialer struct {
	*websocket.Dialer

	TLSClientConfig *tls.Config
}

// Dial creates a new TLS-SRP based client connection. Use requestHeader to specify the
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
// Use the response.Header to get the selected subprotocol
// (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
//
// If the WebSocket handshake fails, ErrBadHandshake is returned along with a
// non-nil *http.Response so that callers can handle redirects, authentication,
// etc.
func (d *TLSSRPDialer) Dial(url url.URL, requestHeader http.Header) (*websocket.Conn, *http.Response, error) {
	var deadline time.Time

	if d.HandshakeTimeout != 0 {
		deadline = time.Now().Add(d.HandshakeTimeout)
	}

	netConn, err := tls.Dial("tcp", url.Host, d.TLSClientConfig)
	if err != nil {
		return nil, nil, err
	}

	defer func() {
		if netConn != nil {
			netConn.Close()
		}
	}()

	if err := netConn.SetDeadline(deadline); err != nil {
		return nil, nil, err
	}

	if len(d.Subprotocols) > 0 {
		h := http.Header{}
		for k, v := range requestHeader {
			h[k] = v
		}
		h.Set("Sec-Websocket-Protocol", strings.Join(d.Subprotocols, ", "))
		requestHeader = h
	}

	conn, resp, err := websocket.NewClient(netConn, &url, requestHeader, d.ReadBufferSize, d.WriteBufferSize)
	if err != nil {
		return nil, resp, err
	}

	netConn.SetDeadline(time.Time{})
	netConn = nil // to avoid close in defer.
	return conn, resp, nil
}
<commit_msg>Set up transport read pump before write pump<commit_after>package networkwebsockets

import (
	"errors"
	"log"
	"net/http"
	"net/url"
	"strings"
	"sync"
	"time"

	tls "github.com/richtr/go-tls-srp"
	"github.com/richtr/websocket"
)

const (
	// Time allowed to write a message to any websocket.
	writeWait = 10 * time.Second

	// Time allowed to read the next pong message from any websocket.
	pongWait = 60 * time.Second

	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10

	// Maximum message size allowed from any websocket.
	maxMessageSize = 8192
)

type MessageHandler interface {
	Read(buf []byte) error
	Write(buf []byte) error
}

// JSON structure to message sending
type WireMessage struct {
	// Proxy message type: "connect", "disconnect", "message", "broadcast"
	Action string `json:"action"`

	Source string `json:"source,omitempty"`

	Target string `json:"target,omitempty"`

	// Message contents
	Payload string `json:"data,omitempty"`

	// Whether this message originated from a Proxy object
	fromProxy bool `json:"-"`
}

type Transport struct {
	conn    *websocket.Conn
	handler MessageHandler
	open    bool
	done    chan int // blocks until .Stop() is called
}

func NewTransport(conn *websocket.Conn, handler MessageHandler) *Transport {
	transport := &Transport{
		conn:    conn,
		handler: handler,

		done: make(chan int, 1),
	}

	return transport
}

func (t *Transport) Start() {
	var wg sync.WaitGroup
	wg.Add(2)

	go t.readPump(&wg)
	go t.writePump(&wg)

	t.open = true

	wg.Wait()
}

func (t *Transport) Stop() {
	t.open = false

	t.conn.Close()
}

// StopNotify returns a channel that receives a empty integer
// when the transport is closed
func (t *Transport) StopNotify() <-chan int { return t.done }

func (t *Transport) Read(buf []byte) error {
	if !t.open {
		return errors.New("Transport is not currently active for reading")
	}

	if t.handler == nil {
		return errors.New("Cannot read message. Transport does not have a handler assigned")
	}

	return t.handler.Read(buf)
}

func (t *Transport) Write(buf []byte) error {
	if !t.open {
		return errors.New("Transport is not currently active for writing")
	}

	if t.handler == nil {
		return errors.New("Cannot write message. Transport does not have a handler assigned")
	}

	return t.handler.Write(buf)
}

// readPump pumps messages from an individual websocket connection to the dispatcher
func (t *Transport) readPump(wg *sync.WaitGroup) {
	t.conn.SetReadLimit(maxMessageSize)
	t.conn.SetReadDeadline(time.Now().Add(pongWait))
	t.conn.SetPongHandler(func(string) error {
		t.conn.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})

	wg.Done()

	for {
		opCode, buf, err := t.conn.ReadMessage()
		if err != nil || opCode != websocket.TextMessage {
			break
		}

		// Pass incoming message to our assigned message handler
		if err := t.Read(buf); err != nil {
			log.Printf("err: %v", err)
		}
	}

	// Indicate object is closed
	t.done <- 1
}

// writePump keeps an individual websocket connection alive
func (t *Transport) writePump(wg *sync.WaitGroup) {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
	}()

	wg.Done()

	for {
		select {
		case <-ticker.C:
			t.conn.SetWriteDeadline(time.Now().Add(writeWait))
			if err := t.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

/** TLS-SRP Dialer interface **/

type TLSSRPDialer struct {
	*websocket.Dialer

	TLSClientConfig *tls.Config
}

// Dial creates a new TLS-SRP based client connection. Use requestHeader to specify the
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
// Use the response.Header to get the selected subprotocol
// (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
//
// If the WebSocket handshake fails, ErrBadHandshake is returned along with a
// non-nil *http.Response so that callers can handle redirects, authentication,
// etc.
func (d *TLSSRPDialer) Dial(url url.URL, requestHeader http.Header) (*websocket.Conn, *http.Response, error) {
	var deadline time.Time

	if d.HandshakeTimeout != 0 {
		deadline = time.Now().Add(d.HandshakeTimeout)
	}

	netConn, err := tls.Dial("tcp", url.Host, d.TLSClientConfig)
	if err != nil {
		return nil, nil, err
	}

	defer func() {
		if netConn != nil {
			netConn.Close()
		}
	}()

	if err := netConn.SetDeadline(deadline); err != nil {
		return nil, nil, err
	}

	if len(d.Subprotocols) > 0 {
		h := http.Header{}
		for k, v := range requestHeader {
			h[k] = v
		}
		h.Set("Sec-Websocket-Protocol", strings.Join(d.Subprotocols, ", "))
		requestHeader = h
	}

	conn, resp, err := websocket.NewClient(netConn, &url, requestHeader, d.ReadBufferSize, d.WriteBufferSize)
	if err != nil {
		return nil, resp, err
	}

	netConn.SetDeadline(time.Time{})
	netConn = nil // to avoid close in defer.
	return conn, resp, nil
}
<|endoftext|>


<commit_before>package vk

import (
	"encoding/json"
	"io"
	"net"
	"net/http"
	"net/url"
	"path"
	"time"
)

const (
	defaultHTTPTimeout        = 3 * time.Second
	defaultRequestTimeout     = 15 * time.Second
	defaultKeepAliveInterval  = 60 * time.Second
	defaultHTTPHeadersTimeout = defaultRequestTimeout
)

var (
	defaultHTTPClient = getDefaultHTTPClient()
)

// HTTPClient is abstaction under http client, that can Do requests
type HTTPClient interface {
	Do(*http.Request) (*http.Response, error)
}

// must panics on non-nil error
func must(err error) {
	if err != nil {
		panic(err)
	}
}

func (c *Client) Do(request Request, response Response) error {
	response.setRequest(request)
	req := request.HTTP()
	res, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	if res.StatusCode != http.StatusOK {
		return ErrBadResponseCode
	}
	return Process(res.Body).To(response)
}

// HTTP converts to *http.Request
func (r Request) HTTP() (req *http.Request) {
	values := url.Values{}
	// copy old params
	for k, v := range r.Values {
		values[k] = v
	}
	values.Add(paramVersion, defaultVersion)
	values.Add(paramHTTPS, defaultHTTPS)
	if len(r.Token) != 0 {
		values.Add(paramToken, r.Token)
	}

	u := url.URL{}
	u.Host = defaultHost
	u.Scheme = defaultScheme
	u.Path = path.Join(defaultPath, r.Method)
	u.RawQuery = values.Encode()

	req, err := http.NewRequest(defaultMethod, u.String(), nil)
	// only possible error may occur in url parsing
	// and that is completely unexpected
	must(err)

	return req
}

type vkResponseProcessor struct {
	input io.Reader
}

type Response interface {
	ServerError() error
	setRequest(request Request)
}

func (d vkResponseProcessor) To(response Response) error {
	if rc, ok := d.input.(io.ReadCloser); ok {
		defer rc.Close()
	}
	decoder := json.NewDecoder(d.input)
	if err := decoder.Decode(response); err != nil {
		return err
	}
	return response.ServerError()
}

func Process(input io.Reader) vkResponseProcessor {
	return vkResponseProcessor{input}
}

func getDefaultHTTPClient() HTTPClient {
	client := &http.Client{
		Timeout: defaultRequestTimeout,
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   defaultHTTPTimeout,
				KeepAlive: defaultKeepAliveInterval,
			}).Dial,
			TLSHandshakeTimeout:   defaultHTTPTimeout,
			ResponseHeaderTimeout: defaultHTTPHeadersTimeout,
		},
	}
	return client
}
<commit_msg>docs update<commit_after>package vk

import (
	"encoding/json"
	"io"
	"net"
	"net/http"
	"net/url"
	"path"
	"time"
)

const (
	defaultHTTPTimeout        = 3 * time.Second
	defaultRequestTimeout     = 15 * time.Second
	defaultKeepAliveInterval  = 60 * time.Second
	defaultHTTPHeadersTimeout = defaultRequestTimeout
)

var (
	defaultHTTPClient = getDefaultHTTPClient()
)

// HTTPClient is abstaction under http client, that can Do requests
type HTTPClient interface {
	Do(*http.Request) (*http.Response, error)
}

// must panics on non-nil error
func must(err error) {
	if err != nil {
		panic(err)
	}
}

func (c *Client) Do(request Request, response Response) error {
	response.setRequest(request)
	req := request.HTTP()
	res, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	if res.StatusCode != http.StatusOK {
		return ErrBadResponseCode
	}
	return Process(res.Body).To(response)
}

// HTTP converts to *http.Request
func (r Request) HTTP() (req *http.Request) {
	values := url.Values{}
	// copy old params
	for k, v := range r.Values {
		values[k] = v
	}
	values.Add(paramVersion, defaultVersion)
	values.Add(paramHTTPS, defaultHTTPS)
	if len(r.Token) != 0 {
		values.Add(paramToken, r.Token)
	}

	u := url.URL{}
	u.Host = defaultHost
	u.Scheme = defaultScheme
	u.Path = path.Join(defaultPath, r.Method)
	u.RawQuery = values.Encode()

	req, err := http.NewRequest(defaultMethod, u.String(), nil)
	// only possible error may occur in url parsing
	// and that is completely unexpected
	must(err)

	return req
}

type vkResponseProcessor struct {
	input io.Reader
}

// ResponseProcessor fills response struct from response
type ResponseProcessor interface {
	To(response Response) error
}

// Response will be filled by ResponseProcessor
// Struct supposed to be like
// 	type Data struct {
// 	    Error `json:"error"`
// 	    Response // ... some fields of response
//	}
//
// Containing Error implements Response interface
type Response interface {
	ServerError() error
	setRequest(request Request)
}

func (d vkResponseProcessor) To(response Response) error {
	if rc, ok := d.input.(io.ReadCloser); ok {
		defer rc.Close()
	}
	decoder := json.NewDecoder(d.input)
	if err := decoder.Decode(response); err != nil {
		return err
	}
	return response.ServerError()
}

func Process(input io.Reader) ResponseProcessor {
	return vkResponseProcessor{input}
}

func getDefaultHTTPClient() HTTPClient {
	client := &http.Client{
		Timeout: defaultRequestTimeout,
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   defaultHTTPTimeout,
				KeepAlive: defaultKeepAliveInterval,
			}).Dial,
			TLSHandshakeTimeout:   defaultHTTPTimeout,
			ResponseHeaderTimeout: defaultHTTPHeadersTimeout,
		},
	}
	return client
}
<|endoftext|>


<commit_before>package fidias

import (
	"context"
	"fmt"

	"github.com/hexablock/hexalog"
	"github.com/hexablock/hexatype"
)

// KVNetTransport implements a transport for key-value operations
type KVTransport interface {
	GetKey(ctx context.Context, host string, key []byte) (*hexatype.KeyValuePair, error)
}

type localHexalogTransport struct {
	host     string
	logstore *hexalog.LogStore
	remote   *hexalog.NetTransport
}

// GetEntry gets a local or remote entry based on host
func (trans *localHexalogTransport) GetEntry(host string, key, id []byte) (*hexatype.Entry, error) {
	if trans.host == host {
		return trans.logstore.GetEntry(key, id)
	}
	return trans.remote.GetEntry(host, key, id, &hexatype.RequestOptions{})
}

func (trans *localHexalogTransport) LastEntry(host string, key []byte) (*hexatype.Entry, error) {
	if trans.host == host {
		return trans.logstore.LastEntry(key), nil
	}
	return trans.remote.LastEntry(host, key, &hexatype.RequestOptions{})
}

type localKVTransport struct {
	host   string
	local  KeyValueStore
	remote KVTransport
}

func (trans *localKVTransport) GetKey(ctx context.Context, host string, key []byte) (*hexatype.KeyValuePair, error) {
	if trans.host == host {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("GetKey context cancelled")
		default:
			return trans.local.GetKey(key)
		}
	}
	return trans.remote.GetKey(ctx, host, key)
}

// type localTransport struct {
// 	host string
// 	// key-value local
// 	kvlocal KeyValueFSM
// 	// fidias transport as a whole. it contains the required key-value calls as well
// 	trans *NetTransport
// }

// GetKey gets a local or remote key-value pair based on the host.  It also takes a context
// for cancellation of requests
// func (trans *localTransport) GetKey(ctx context.Context, host string, key []byte) (*hexatype.KeyValuePair, error) {
// 	if trans.host == host {
// 		select {
// 		case <-ctx.Done():
// 			return nil, fmt.Errorf("GetKey context cancelled")
// 		default:
// 			return trans.kvlocal.Get(key)
// 		}
// 		//return trans.kvlocal.Get(key)
// 	}
// 	return trans.trans.GetKey(ctx, host, key)
// }
<commit_msg>Fixed context import<commit_after>package fidias

import (
	"fmt"

	"golang.org/x/net/context"

	"github.com/hexablock/hexalog"
	"github.com/hexablock/hexatype"
)

// KVTransport implements a transport for key-value operations
type KVTransport interface {
	GetKey(ctx context.Context, host string, key []byte) (*hexatype.KeyValuePair, error)
}

type localHexalogTransport struct {
	host     string
	logstore *hexalog.LogStore
	remote   *hexalog.NetTransport
}

// GetEntry gets a local or remote entry based on host
func (trans *localHexalogTransport) GetEntry(host string, key, id []byte) (*hexatype.Entry, error) {
	if trans.host == host {
		return trans.logstore.GetEntry(key, id)
	}
	return trans.remote.GetEntry(host, key, id, &hexatype.RequestOptions{})
}

func (trans *localHexalogTransport) LastEntry(host string, key []byte) (*hexatype.Entry, error) {
	if trans.host == host {
		return trans.logstore.LastEntry(key), nil
	}
	return trans.remote.LastEntry(host, key, &hexatype.RequestOptions{})
}

type localKVTransport struct {
	host   string
	local  KeyValueStore
	remote KVTransport
}

func (trans *localKVTransport) GetKey(ctx context.Context, host string, key []byte) (*hexatype.KeyValuePair, error) {
	if trans.host == host {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("GetKey context cancelled")
		default:
			return trans.local.GetKey(key)
		}
	}
	return trans.remote.GetKey(ctx, host, key)
}
<|endoftext|>


<commit_before>package trie

import (
	"fmt"
	"reflect"
	"sort"
	"testing"
	"unicode/utf8"
)

func TestIndex(t *testing.T) {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc"})
	matches := trie.Search("ab")
	expected := []string{"ab", "abc"}
	sort.Strings(matches)
	sort.Strings(expected)
	if !reflect.DeepEqual(matches, expected) {
		t.Errorf("expected search results %v expected %v", matches, expected)
	}
}

func TestInsert(t *testing.T) {
	trie := New()
	trie.Insert("ab")
	trie.Insert("ac")
	expected := Node{'a': Node{'b': Node{}, 'c': Node{}}}
	expected['a']['b'].end()
	expected['a']['c'].end()
	if !reflect.DeepEqual(trie, expected) {
		t.Errorf("unequal trie %q, %q", trie, expected)
	}
}

func TestAll(t *testing.T) {
	for _, test := range []struct {
		words []string
	}{
		{[]string{"ab", "ac"}},
		{[]string{"a", "ab", "ac"}},
		{[]string{"a", "ab", "ac", "abc"}},
		{[]string{"a", "ab", "ac", "abc", "abcdef"}},
	} {
		trie := New()
		for _, word := range test.words {
			trie.Insert(word)
		}
		all := trie.All("")
		sort.Strings(all)
		sort.Strings(test.words)
		if !reflect.DeepEqual(all, test.words) {
			t.Errorf("when calling all on trie the result set should be %q not %q", test.words, all)
		}
	}
}

func TestSearch(t *testing.T) {
	for _, test := range []struct {
		dict    []string
		search  string
		results []string
	}{
		{[]string{"ab", "ac"}, "ab", []string{"ab"}},
		{[]string{"a", "ab", "ac"}, "a", []string{"a", "ab", "ac"}},
		{[]string{"a", "ab", "ac", "abc"}, "ab", []string{"ab", "abc"}},
		{[]string{"a", "ab", "ac", "abc", "abcdef"}, "ab", []string{"ab", "abc", "abcdef"}},
	} {
		trie := New()
		for _, word := range test.dict {
			trie.Insert(word)
		}
		results := trie.Search(test.search)
		sort.Strings(results)
		sort.Strings(test.results)
		if !reflect.DeepEqual(test.results, results) {
			t.Errorf("when searching for %q the result set should be %q not %q", test.search, test.results, results)
		}
	}
}

func TestEnd(t *testing.T) {
	if utf8.ValidRune(end) {
		t.Errorf("end variable should not use a valid rune")
	}
}

func TestString(t *testing.T) {
	trie := New()
	trie.Index([]string{"a", "ab", "abc"})
	expected := "a\n b\n  c\n"
	if trie.String() != expected {
		t.Errorf("unexpected string representation of trie %q expected %q", trie.String(), expected)
	}
}

func ExampleNode() {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc"})
	fmt.Printf("%q", trie.Search("ab"))
	// Output: ["ab" "abc"]
}

func ExampleString() {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc", "abcd"})
	fmt.Printf("%s", trie)
	// Output: a
	//  b
	//   c
	//    d
	//  c
	//  d
}
<commit_msg>rename example<commit_after>package trie

import (
	"fmt"
	"reflect"
	"sort"
	"testing"
	"unicode/utf8"
)

func TestIndex(t *testing.T) {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc"})
	matches := trie.Search("ab")
	expected := []string{"ab", "abc"}
	sort.Strings(matches)
	sort.Strings(expected)
	if !reflect.DeepEqual(matches, expected) {
		t.Errorf("expected search results %v expected %v", matches, expected)
	}
}

func TestInsert(t *testing.T) {
	trie := New()
	trie.Insert("ab")
	trie.Insert("ac")
	expected := Node{'a': Node{'b': Node{}, 'c': Node{}}}
	expected['a']['b'].end()
	expected['a']['c'].end()
	if !reflect.DeepEqual(trie, expected) {
		t.Errorf("unequal trie %q, %q", trie, expected)
	}
}

func TestAll(t *testing.T) {
	for _, test := range []struct {
		words []string
	}{
		{[]string{"ab", "ac"}},
		{[]string{"a", "ab", "ac"}},
		{[]string{"a", "ab", "ac", "abc"}},
		{[]string{"a", "ab", "ac", "abc", "abcdef"}},
	} {
		trie := New()
		for _, word := range test.words {
			trie.Insert(word)
		}
		all := trie.All("")
		sort.Strings(all)
		sort.Strings(test.words)
		if !reflect.DeepEqual(all, test.words) {
			t.Errorf("when calling all on trie the result set should be %q not %q", test.words, all)
		}
	}
}

func TestSearch(t *testing.T) {
	for _, test := range []struct {
		dict    []string
		search  string
		results []string
	}{
		{[]string{"ab", "ac"}, "ab", []string{"ab"}},
		{[]string{"a", "ab", "ac"}, "a", []string{"a", "ab", "ac"}},
		{[]string{"a", "ab", "ac", "abc"}, "ab", []string{"ab", "abc"}},
		{[]string{"a", "ab", "ac", "abc", "abcdef"}, "ab", []string{"ab", "abc", "abcdef"}},
	} {
		trie := New()
		for _, word := range test.dict {
			trie.Insert(word)
		}
		results := trie.Search(test.search)
		sort.Strings(results)
		sort.Strings(test.results)
		if !reflect.DeepEqual(test.results, results) {
			t.Errorf("when searching for %q the result set should be %q not %q", test.search, test.results, results)
		}
	}
}

func TestEnd(t *testing.T) {
	if utf8.ValidRune(end) {
		t.Errorf("end variable should not use a valid rune")
	}
}

func TestString(t *testing.T) {
	trie := New()
	trie.Index([]string{"a", "ab", "abc"})
	expected := "a\n b\n  c\n"
	if trie.String() != expected {
		t.Errorf("unexpected string representation of trie %q expected %q", trie.String(), expected)
	}
}

func ExampleNode() {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc"})
	fmt.Printf("%q", trie.Search("ab"))
	// Output: ["ab" "abc"]
}

func ExamplePrint() {
	trie := New()
	trie.Index([]string{"ab", "ac", "ad", "abc", "abcd"})
	fmt.Printf("%s", trie)
	// Output: a
	//  b
	//   c
	//    d
	//  c
	//  d
}
<|endoftext|>


<commit_before>package logmetrics

import (
	"fmt"
	"log"
	"net"
	"time"
)

type keyPushStats struct {
	key_pushed  int64
	byte_pushed int64
	last_report time.Time
	hostname    string
	interval    int
}

func (f *keyPushStats) inc(data_written int) {
	f.key_pushed++
	f.byte_pushed += int64(data_written)
}

func (f *keyPushStats) getLine() []string {
	t := time.Now()

	f.last_report = t

	line := make([]string, 2)
	line[0] = fmt.Sprintf("logmetrics_collector.pusher.key_sent %d %d host=%s", t.Unix(), f.key_pushed, f.hostname)
	line[1] = fmt.Sprintf("logmetrics_collector.pusher.byte_sent %d %d host=%s", t.Unix(), f.byte_pushed, f.hostname)

	return line
}

func (f *keyPushStats) isTimeForStats() bool {
	return time.Now().Sub(f.last_report) > time.Duration(f.interval)*time.Second
}

func writeLine(config *Config, doNotSend bool, conn net.Conn, line string) (int, net.Conn) {
	if config.pushType == "tsd" {
		line = ("put " + line + "\n")
	} else {
		line = line + "\n"
	}

	byte_line := []byte(line)
	byte_written := len(byte_line)

	var err error
	if doNotSend {
		fmt.Print(line)
	} else {
		for {
			//Reconnect if needed
			if conn == nil {
				target := config.GetTsdTarget()
				log.Printf("Reconnecting to %s", target)

				if conn, err = net.Dial(config.pushProto, target); err != nil {
					log.Printf("Unable to reconnect: %s", err)
				}
			}

			if conn != nil {
				_, err = conn.Write(byte_line)

				if err != nil {
					log.Printf("Error writting data: %s", err)
					conn.Close()
					conn = nil
					time.Sleep(time.Duration(config.pushWait) * time.Second)
				} else {
					break
				}
			}

		}
	}

	return byte_written, conn
}

func StartTsdPushers(config *Config, tsd_pushers []chan []string, doNotSend bool) {
	if config.pushPort == 0 {
		return
	}

	hostname := getHostname()

	for i, _ := range tsd_pushers {
		channel_number := i

		log.Printf("TsdPusher[%d] started. Pushing keys to %s:%d over %s in %s format", channel_number, config.pushHost,
			config.pushPort, config.pushProto, config.pushType)

		tsd_push := tsd_pushers[channel_number]
		go func() {
			key_push_stats := keyPushStats{last_report: time.Now(), hostname: hostname, interval: config.stats_wait}

			//Check if TSD has something to say
			//if config.pushType == "tsd" {
			//	go func() {
			//		response_buffer := make([]byte, 1024)
			//		for {
			//			if conn != nil {
			//				if size, read_err := conn.Read(response_buffer); read_err != nil && read_err != io.EOF {
			//					log.Printf("Unable to read response: %s %+V", read_err, read_err)
			//				} else if size > 0 {
			//					log.Print(string(response_buffer))
			//				}
			//			}
			//		}
			//	}()
			//}

			var conn net.Conn
			for keys := range tsd_push {
				for _, line := range keys {
					var bytes_written int
					bytes_written, conn = writeLine(config, doNotSend, conn, line)

					key_push_stats.inc(bytes_written)

					//Stats on key pushed, limit checks with modulo (now() is a syscall)
					if (key_push_stats.key_pushed%10000) == 0 && key_push_stats.isTimeForStats() {
						for _, local_line := range key_push_stats.getLine() {
							bytes_written, conn = writeLine(config, doNotSend, conn, local_line)
							key_push_stats.inc(bytes_written)
						}
					}
				}
			}

		}()
	}
}
<commit_msg>Added wait time if reconnect fails.<commit_after>package logmetrics

import (
	"fmt"
	"log"
	"net"
	"time"
)

type keyPushStats struct {
	key_pushed  int64
	byte_pushed int64
	last_report time.Time
	hostname    string
	interval    int
}

func (f *keyPushStats) inc(data_written int) {
	f.key_pushed++
	f.byte_pushed += int64(data_written)
}

func (f *keyPushStats) getLine() []string {
	t := time.Now()

	f.last_report = t

	line := make([]string, 2)
	line[0] = fmt.Sprintf("logmetrics_collector.pusher.key_sent %d %d host=%s", t.Unix(), f.key_pushed, f.hostname)
	line[1] = fmt.Sprintf("logmetrics_collector.pusher.byte_sent %d %d host=%s", t.Unix(), f.byte_pushed, f.hostname)

	return line
}

func (f *keyPushStats) isTimeForStats() bool {
	return time.Now().Sub(f.last_report) > time.Duration(f.interval)*time.Second
}

func writeLine(config *Config, doNotSend bool, conn net.Conn, line string) (int, net.Conn) {
	if config.pushType == "tsd" {
		line = ("put " + line + "\n")
	} else {
		line = line + "\n"
	}

	byte_line := []byte(line)
	byte_written := len(byte_line)

	var err error
	if doNotSend {
		fmt.Print(line)
	} else {
		for {
			//Reconnect if needed
			if conn == nil {
				target := config.GetTsdTarget()
				log.Printf("Reconnecting to %s", target)

				if conn, err = net.Dial(config.pushProto, target); err != nil {
					log.Printf("Unable to reconnect: %s", err)
					time.Sleep(time.Duration(config.pushWait) * time.Second)
				}
			}

			if conn != nil {
				_, err = conn.Write(byte_line)

				if err != nil {
					log.Printf("Error writting data: %s", err)
					conn.Close()
					conn = nil
					time.Sleep(time.Duration(config.pushWait) * time.Second)
				} else {
					break
				}
			}

		}
	}

	return byte_written, conn
}

func StartTsdPushers(config *Config, tsd_pushers []chan []string, doNotSend bool) {
	if config.pushPort == 0 {
		return
	}

	hostname := getHostname()

	for i, _ := range tsd_pushers {
		channel_number := i

		log.Printf("TsdPusher[%d] started. Pushing keys to %s:%d over %s in %s format", channel_number, config.pushHost,
			config.pushPort, config.pushProto, config.pushType)

		tsd_push := tsd_pushers[channel_number]
		go func() {
			key_push_stats := keyPushStats{last_report: time.Now(), hostname: hostname, interval: config.stats_wait}

			//Check if TSD has something to say
			//if config.pushType == "tsd" {
			//	go func() {
			//		response_buffer := make([]byte, 1024)
			//		for {
			//			if conn != nil {
			//				if size, read_err := conn.Read(response_buffer); read_err != nil && read_err != io.EOF {
			//					log.Printf("Unable to read response: %s %+V", read_err, read_err)
			//				} else if size > 0 {
			//					log.Print(string(response_buffer))
			//				}
			//			}
			//		}
			//	}()
			//}

			var conn net.Conn
			for keys := range tsd_push {
				for _, line := range keys {
					var bytes_written int
					bytes_written, conn = writeLine(config, doNotSend, conn, line)

					key_push_stats.inc(bytes_written)

					//Stats on key pushed, limit checks with modulo (now() is a syscall)
					if (key_push_stats.key_pushed%10000) == 0 && key_push_stats.isTimeForStats() {
						for _, local_line := range key_push_stats.getLine() {
							bytes_written, conn = writeLine(config, doNotSend, conn, local_line)
							key_push_stats.inc(bytes_written)
						}
					}
				}
			}

		}()
	}
}
<|endoftext|>


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

package audio

func PlayersNumForTesting() int {
	c := CurrentContext()
	c.players.Lock()
	n := len(c.players.players)
	c.players.Unlock()
	return n
}
<commit_msg>audio: Bug fix: Test compilation error<commit_after>// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package audio

func PlayersNumForTesting() int {
	c := CurrentContext()
	c.mux.m.Lock()
	n := len(c.mux.ps)
	c.mux.m.Unlock()
	return n
}
<|endoftext|>


<commit_before>package auth

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestAuth0ManagerAuthenticate_ValidCreds(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, r.Method, "POST")
		assert.Equal(t, r.URL.Path, "/oauth/ro")

		var req oauthReq
		Unmarshal(t, r, &req)

		assert.Equal(t, req.Username, "valid username")
		assert.Equal(t, req.Password, "valid password")

		MarshalAndWrite(t, w, nil, 200)
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	valid, err := auth0Manager.Authenticate("valid username", "valid password")
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, valid, true)
}

func TestAuth0ManagerAuthenticate_InvalidCreds(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, r.Method, "POST")
		assert.Equal(t, r.URL.Path, "/oauth/ro")

		var req oauthReq
		Unmarshal(t, r, &req)

		assert.Equal(t, req.Username, "valid username")
		assert.Equal(t, req.Password, "invalid password")

		MarshalAndWrite(t, w, nil, 401)
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	valid, err := auth0Manager.Authenticate("valid username", "invalid password")
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, valid, false)
}

func TestAuth0ManagerAuthenticate_ValidCredsAreCached(t *testing.T) {
	count := 0

	handler := func(w http.ResponseWriter, r *http.Request) {
		MarshalAndWrite(t, w, nil, 200)
		count++
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	for i := 0; i < 2; i++ {
		valid, err := auth0Manager.Authenticate("valid username", "valid password")
		if err != nil {
			t.Fatal(err)
		}

		assert.Equal(t, valid, true)
	}

	assert.Equal(t, count, 1)
}

func TestAuth0ManagerAuthenticate_NotValidCredsAreChecked(t *testing.T) {
	timeMultiplier = 0
	count := 0

	handler := func(w http.ResponseWriter, r *http.Request) {
		if count == 0 {
			MarshalAndWrite(t, w, nil, 401)
		} else {
			MarshalAndWrite(t, w, nil, 200)
		}

		count++
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	for i, expected := range []bool{false, true} {
		valid, err := auth0Manager.Authenticate("username", "password")
		if err != nil {
			t.Fatal(err)
		}

		if valid != expected {
			t.Errorf("Error on iteration %d: result was %t, expected %t", i, valid, expected)
		}
	}

	assert.Equal(t, count, 2)
}
<commit_msg>test Auth0Manager retries on 429s<commit_after>package auth

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestAuth0ManagerAuthenticate_ValidCreds(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, r.Method, "POST")
		assert.Equal(t, r.URL.Path, "/oauth/ro")

		var req oauthReq
		Unmarshal(t, r, &req)

		assert.Equal(t, req.Username, "valid username")
		assert.Equal(t, req.Password, "valid password")

		MarshalAndWrite(t, w, nil, 200)
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	valid, err := auth0Manager.Authenticate("valid username", "valid password")
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, valid, true)
}

func TestAuth0ManagerAuthenticate_InvalidCreds(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, r.Method, "POST")
		assert.Equal(t, r.URL.Path, "/oauth/ro")

		var req oauthReq
		Unmarshal(t, r, &req)

		assert.Equal(t, req.Username, "valid username")
		assert.Equal(t, req.Password, "invalid password")

		MarshalAndWrite(t, w, nil, 401)
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	valid, err := auth0Manager.Authenticate("valid username", "invalid password")
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, valid, false)
}

func TestAuth0ManagerAuthenticate_ValidCredsAreCached(t *testing.T) {
	count := 0

	handler := func(w http.ResponseWriter, r *http.Request) {
		MarshalAndWrite(t, w, nil, 200)
		count++
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	for i := 0; i < 2; i++ {
		valid, err := auth0Manager.Authenticate("valid username", "valid password")
		if err != nil {
			t.Fatal(err)
		}

		assert.Equal(t, valid, true)
	}

	assert.Equal(t, count, 1)
}

func TestAuth0ManagerAuthenticate_NotValidCredsAreChecked(t *testing.T) {
	timeMultiplier = 0
	count := 0

	handler := func(w http.ResponseWriter, r *http.Request) {
		if count == 0 {
			MarshalAndWrite(t, w, nil, 401)
		} else {
			MarshalAndWrite(t, w, nil, 200)
		}

		count++
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	for i, expected := range []bool{false, true} {
		valid, err := auth0Manager.Authenticate("username", "password")
		if err != nil {
			t.Fatal(err)
		}

		if valid != expected {
			t.Errorf("Error on iteration %d: result was %t, expected %t", i, valid, expected)
		}
	}

	assert.Equal(t, count, 2)
}

func TestAuth0ManagerAuthenticate_RetriesOn429(t *testing.T) {
	count := 0

	handler := func(w http.ResponseWriter, r *http.Request) {
		if count < 2 {
			MarshalAndWrite(t, w, nil, 429)
		} else {
			MarshalAndWrite(t, w, nil, 200)
		}

		count++
	}

	auth0Manager, server := newAuth0ManagerAndServer(handler)
	defer server.Close()

	_, err := auth0Manager.Authenticate("", "")
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package polecalc

import "os"

// One-parameter scalar self-consistent equation
type SelfConsistentEquation interface {
	// return the absolute error associated with this equation under the given Environment
	AbsError(env Environment) float64
	// set the appropriate variable in env to value
	SetEnvironment(value float64, env *Environment)
	// range of possible values for SetEnvironment
	Range(env Environment) (float64, float64, os.Error)
}

// Return an Environment which solves eq to the given tolerance
func Solve(eq SelfConsistentEquation, env Environment, tolerance float64) (Environment, os.Error) {
	eqError := func(value float64) float64 {
		eq.SetEnvironment(value, &env)
		return eq.AbsError(env)
	}
	// if eq only has one root, left and right must bracket it
	// --- todo: need to verify this ---
	left, right, err := eq.Range(env)
	if err != nil {
		return env, err
	}
	solution, err := BisectionFullPrecision(eqError, left, right)
	if err != nil {
		return env, err
	}
	eq.SetEnvironment(solution, &env)
	return env, nil
}

// A group of self-consistent equations which may be coupled and must all be
// solved for the group to be considered solved.
type SelfConsistentSystem struct {
	Equations  []SelfConsistentEquation
	Tolerances []float64
}

// Solve the self-consistent system, returning the resulting Environment
func (system *SelfConsistentSystem) Solve(env Environment) (Environment, os.Error) {
	i := 0
	for !system.IsSolved(env) {
		// this should never be true: if it is, failed to iterate
		if i >= len(system.Equations) {
			panic("self-consistent system overran bounds")
		}
		// set env to the value that solves the equation
		newEnv, err := Solve(system.Equations[i], env, system.Tolerances[i])
		if err != nil {
			return env, err
		}
		env = newEnv
		// check if we need to iterate
		if !system.solvedUpTo(env, i) {
			// previous equations have been disturbed; restart
			i = 0
		} else {
			// ok to continue to next equation
			i++
		}
	}
	return env, nil
}

// Check if the first (maxIndex + 1) equations are solved
func (system *SelfConsistentSystem) solvedUpTo(env Environment, maxIndex int) bool {
	for i, eq := range system.Equations {
		if i > maxIndex {
			break
		}
		if eq.AbsError(env) > system.Tolerances[i] {
			return false
		}
	}
	return true
}

// Are all the self-consistent equations solved?
func (system *SelfConsistentSystem) IsSolved(env Environment) bool {
	if len(system.Equations) == 0 {
		return true
	}
	return system.solvedUpTo(env, len(system.Equations)-1)
}
<commit_msg>changed references to Environment in selfconsistent to arbitrary type<commit_after>package polecalc

import "os"

type Arguments interface{}

// One-parameter scalar self-consistent equation
type SelfConsistentEquation interface {
	// return the absolute error associated with this equation under the given Arguments
	AbsError(args Arguments) float64
	// set the appropriate variable in args to value
	SetArguments(value float64, args *Arguments)
	// range of possible values for SetArguments
	Range(args Arguments) (float64, float64, os.Error)
}

// Return an Arguments which solves eq to the given tolerance
func Solve(eq SelfConsistentEquation, args Arguments, tolerance float64) (Arguments, os.Error) {
	eqError := func(value float64) float64 {
		eq.SetArguments(value, &args)
		return eq.AbsError(args)
	}
	// if eq only has one root, left and right must bracket it
	// --- todo: need to verify this ---
	left, right, err := eq.Range(args)
	if err != nil {
		return args, err
	}
	solution, err := BisectionFullPrecision(eqError, left, right)
	if err != nil {
		return args, err
	}
	eq.SetArguments(solution, &args)
	return args, nil
}

// A group of self-consistent equations which may be coupled and must all be
// solved for the group to be considered solved.
type SelfConsistentSystem struct {
	Equations  []SelfConsistentEquation
	Tolerances []float64
}

// Solve the self-consistent system, returning the resulting Arguments
func (system *SelfConsistentSystem) Solve(args Arguments) (Arguments, os.Error) {
	i := 0
	for !system.IsSolved(args) {
		// this should never be true: if it is, failed to iterate
		if i >= len(system.Equations) {
			panic("self-consistent system overran bounds")
		}
		// set args to the value that solves the equation
		newEnv, err := Solve(system.Equations[i], args, system.Tolerances[i])
		if err != nil {
			return args, err
		}
		args = newEnv
		// check if we need to iterate
		if !system.solvedUpTo(args, i) {
			// previous equations have been disturbed; restart
			i = 0
		} else {
			// ok to continue to next equation
			i++
		}
	}
	return args, nil
}

// Check if the first (maxIndex + 1) equations are solved
func (system *SelfConsistentSystem) solvedUpTo(args Arguments, maxIndex int) bool {
	for i, eq := range system.Equations {
		if i > maxIndex {
			break
		}
		if eq.AbsError(args) > system.Tolerances[i] {
			return false
		}
	}
	return true
}

// Are all the self-consistent equations solved?
func (system *SelfConsistentSystem) IsSolved(args Arguments) bool {
	if len(system.Equations) == 0 {
		return true
	}
	return system.solvedUpTo(args, len(system.Equations)-1)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package announced

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/apimachinery/registered"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
)

type SchemeFunc func(*runtime.Scheme) error
type VersionToSchemeFunc map[string]SchemeFunc

// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory.
type GroupVersionFactoryArgs struct {
	GroupName   string
	VersionName string

	AddToScheme SchemeFunc
}

// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory.
type GroupMetaFactoryArgs struct {
	// GroupName is the name of the API-Group
	//
	// example: 'servicecatalog.k8s.io'
	GroupName              string
	VersionPreferenceOrder []string
	// ImportPrefix is the base go package of the API-Group
	//
	// example: 'k8s.io/kubernetes/pkg/apis/autoscaling'
	ImportPrefix string
	// RootScopedKinds are resources that are not namespaced.
	RootScopedKinds sets.String // nil is allowed
	IgnoredKinds    sets.String // nil is allowed

	// May be nil if there are no internal objects.
	AddInternalObjectsToScheme SchemeFunc
}

// NewGroupMetaFactory builds the args for you. This is for if you're
// constructing a factory all at once and not using the registry.
func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory {
	gmf := &GroupMetaFactory{
		GroupArgs:   groupArgs,
		VersionArgs: map[string]*GroupVersionFactoryArgs{},
	}
	for v, f := range versions {
		gmf.VersionArgs[v] = &GroupVersionFactoryArgs{
			GroupName:   groupArgs.GroupName,
			VersionName: v,
			AddToScheme: f,
		}
	}
	return gmf
}

// Announce adds this Group factory to the global factory registry. It should
// only be called if you constructed the GroupMetaFactory yourself via
// NewGroupMetadFactory.
// Note that this will panic on an error, since it's expected that you'll be
// calling this at initialization time and any error is a result of a
// programmer importing the wrong set of packages. If this assumption doesn't
// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory
// yourself.
func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory {
	if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil {
		panic(err)
	}
	return gmf
}

// GroupMetaFactory has the logic for actually assembling and registering a group.
//
// There are two ways of obtaining one of these.
// 1. You can announce your group and versions separately, and then let the
//    GroupFactoryRegistry assemble this object for you. (This allows group and
//    versions to be imported separately, without referencing each other, to
//    keep import trees small.)
// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement
//    for the old, bad way of doing things. You can then call .Announce() to
//    announce your constructed factory to any code that would like to do
//    things the new, better way.
//
// Note that GroupMetaFactory actually does construct GroupMeta objects, but
// currently it does so in a way that's very entangled with an
// APIRegistrationManager. It's a TODO item to cleanly separate that interface.
type GroupMetaFactory struct {
	GroupArgs *GroupMetaFactoryArgs
	// map of version name to version factory
	VersionArgs map[string]*GroupVersionFactoryArgs

	// assembled by Register()
	prioritizedVersionList []schema.GroupVersion
}

// Register constructs the finalized prioritized version list and sanity checks
// the announced group & versions. Then it calls register.
func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error {
	if gmf.GroupArgs == nil {
		return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs)
	}
	if len(gmf.VersionArgs) == 0 {
		return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName)
	}

	pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...)
	if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) {
		return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder)
	}
	prioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.GroupArgs.VersionPreferenceOrder {
		prioritizedVersions = append(
			prioritizedVersions,
			schema.GroupVersion{
				Group:   gmf.GroupArgs.GroupName,
				Version: v,
			},
		)
	}

	// Go through versions that weren't explicitly prioritized.
	unprioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.VersionArgs {
		if v.GroupName != gmf.GroupArgs.GroupName {
			return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName)
		}
		if pvSet.Has(v.VersionName) {
			pvSet.Delete(v.VersionName)
			continue
		}
		unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName})
	}
	if len(unprioritizedVersions) > 1 {
		glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions)
	}
	if pvSet.Len() != 0 {
		return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet)
	}
	prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...)
	m.RegisterVersions(prioritizedVersions)
	gmf.prioritizedVersionList = prioritizedVersions
	return nil
}

func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()
	if gmf.GroupArgs.RootScopedKinds != nil {
		rootScoped = gmf.GroupArgs.RootScopedKinds
	}
	ignoredKinds := sets.NewString()
	if gmf.GroupArgs.IgnoredKinds != nil {
		ignoredKinds = gmf.GroupArgs.IgnoredKinds
	}

	return meta.NewDefaultRESTMapperFromScheme(
		externalVersions,
		groupMeta.InterfacesFor,
		gmf.GroupArgs.ImportPrefix,
		ignoredKinds,
		rootScoped,
		scheme,
	)
}

// Enable enables group versions that are allowed, adds methods to the scheme, etc.
func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	externalVersions := []schema.GroupVersion{}
	for _, v := range gmf.prioritizedVersionList {
		if !m.IsAllowedVersion(v) {
			continue
		}
		externalVersions = append(externalVersions, v)
		if err := m.EnableVersions(v); err != nil {
			return err
		}
		gmf.VersionArgs[v.Version].AddToScheme(scheme)
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName)
		return nil
	}

	if gmf.GroupArgs.AddInternalObjectsToScheme != nil {
		gmf.GroupArgs.AddInternalObjectsToScheme(scheme)
	}

	preferredExternalVersion := externalVersions[0]
	accessor := meta.NewAccessor()

	groupMeta := &apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		SelfLinker:    runtime.SelfLinker(accessor),
	}
	for _, v := range externalVersions {
		gvf := gmf.VersionArgs[v.Version]
		if err := groupMeta.AddVersionInterfaces(
			schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
			&meta.VersionInterfaces{
				ObjectConvertor:  scheme,
				MetadataAccessor: accessor,
			},
		); err != nil {
			return err
		}
	}
	groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
	groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)

	if err := m.RegisterGroup(*groupMeta); err != nil {
		return err
	}
	return nil
}

// RegisterAndEnable is provided only to allow this code to get added in multiple steps.
// It's really bad that this is called in init() methods, but supporting this
// temporarily lets us do the change incrementally.
func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	if err := gmf.Register(registry); err != nil {
		return err
	}
	if err := gmf.Enable(registry, scheme); err != nil {
		return err
	}

	return nil
}
<commit_msg>Fix typo: NewGroupMetadFactory<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package announced

import (
	"fmt"

	"github.com/golang/glog"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apimachinery"
	"k8s.io/apimachinery/pkg/apimachinery/registered"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/sets"
)

type SchemeFunc func(*runtime.Scheme) error
type VersionToSchemeFunc map[string]SchemeFunc

// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory.
type GroupVersionFactoryArgs struct {
	GroupName   string
	VersionName string

	AddToScheme SchemeFunc
}

// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory.
type GroupMetaFactoryArgs struct {
	// GroupName is the name of the API-Group
	//
	// example: 'servicecatalog.k8s.io'
	GroupName              string
	VersionPreferenceOrder []string
	// ImportPrefix is the base go package of the API-Group
	//
	// example: 'k8s.io/kubernetes/pkg/apis/autoscaling'
	ImportPrefix string
	// RootScopedKinds are resources that are not namespaced.
	RootScopedKinds sets.String // nil is allowed
	IgnoredKinds    sets.String // nil is allowed

	// May be nil if there are no internal objects.
	AddInternalObjectsToScheme SchemeFunc
}

// NewGroupMetaFactory builds the args for you. This is for if you're
// constructing a factory all at once and not using the registry.
func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory {
	gmf := &GroupMetaFactory{
		GroupArgs:   groupArgs,
		VersionArgs: map[string]*GroupVersionFactoryArgs{},
	}
	for v, f := range versions {
		gmf.VersionArgs[v] = &GroupVersionFactoryArgs{
			GroupName:   groupArgs.GroupName,
			VersionName: v,
			AddToScheme: f,
		}
	}
	return gmf
}

// Announce adds this Group factory to the global factory registry. It should
// only be called if you constructed the GroupMetaFactory yourself via
// NewGroupMetaFactory.
// Note that this will panic on an error, since it's expected that you'll be
// calling this at initialization time and any error is a result of a
// programmer importing the wrong set of packages. If this assumption doesn't
// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory
// yourself.
func (gmf *GroupMetaFactory) Announce(groupFactoryRegistry APIGroupFactoryRegistry) *GroupMetaFactory {
	if err := groupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil {
		panic(err)
	}
	return gmf
}

// GroupMetaFactory has the logic for actually assembling and registering a group.
//
// There are two ways of obtaining one of these.
// 1. You can announce your group and versions separately, and then let the
//    GroupFactoryRegistry assemble this object for you. (This allows group and
//    versions to be imported separately, without referencing each other, to
//    keep import trees small.)
// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement
//    for the old, bad way of doing things. You can then call .Announce() to
//    announce your constructed factory to any code that would like to do
//    things the new, better way.
//
// Note that GroupMetaFactory actually does construct GroupMeta objects, but
// currently it does so in a way that's very entangled with an
// APIRegistrationManager. It's a TODO item to cleanly separate that interface.
type GroupMetaFactory struct {
	GroupArgs *GroupMetaFactoryArgs
	// map of version name to version factory
	VersionArgs map[string]*GroupVersionFactoryArgs

	// assembled by Register()
	prioritizedVersionList []schema.GroupVersion
}

// Register constructs the finalized prioritized version list and sanity checks
// the announced group & versions. Then it calls register.
func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error {
	if gmf.GroupArgs == nil {
		return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs)
	}
	if len(gmf.VersionArgs) == 0 {
		return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName)
	}

	pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...)
	if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) {
		return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder)
	}
	prioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.GroupArgs.VersionPreferenceOrder {
		prioritizedVersions = append(
			prioritizedVersions,
			schema.GroupVersion{
				Group:   gmf.GroupArgs.GroupName,
				Version: v,
			},
		)
	}

	// Go through versions that weren't explicitly prioritized.
	unprioritizedVersions := []schema.GroupVersion{}
	for _, v := range gmf.VersionArgs {
		if v.GroupName != gmf.GroupArgs.GroupName {
			return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName)
		}
		if pvSet.Has(v.VersionName) {
			pvSet.Delete(v.VersionName)
			continue
		}
		unprioritizedVersions = append(unprioritizedVersions, schema.GroupVersion{Group: v.GroupName, Version: v.VersionName})
	}
	if len(unprioritizedVersions) > 1 {
		glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions)
	}
	if pvSet.Len() != 0 {
		return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet)
	}
	prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...)
	m.RegisterVersions(prioritizedVersions)
	gmf.prioritizedVersionList = prioritizedVersions
	return nil
}

func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
	// the list of kinds that are scoped at the root of the api hierarchy
	// if a kind is not enumerated here, it is assumed to have a namespace scope
	rootScoped := sets.NewString()
	if gmf.GroupArgs.RootScopedKinds != nil {
		rootScoped = gmf.GroupArgs.RootScopedKinds
	}
	ignoredKinds := sets.NewString()
	if gmf.GroupArgs.IgnoredKinds != nil {
		ignoredKinds = gmf.GroupArgs.IgnoredKinds
	}

	return meta.NewDefaultRESTMapperFromScheme(
		externalVersions,
		groupMeta.InterfacesFor,
		gmf.GroupArgs.ImportPrefix,
		ignoredKinds,
		rootScoped,
		scheme,
	)
}

// Enable enables group versions that are allowed, adds methods to the scheme, etc.
func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	externalVersions := []schema.GroupVersion{}
	for _, v := range gmf.prioritizedVersionList {
		if !m.IsAllowedVersion(v) {
			continue
		}
		externalVersions = append(externalVersions, v)
		if err := m.EnableVersions(v); err != nil {
			return err
		}
		gmf.VersionArgs[v.Version].AddToScheme(scheme)
	}
	if len(externalVersions) == 0 {
		glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName)
		return nil
	}

	if gmf.GroupArgs.AddInternalObjectsToScheme != nil {
		gmf.GroupArgs.AddInternalObjectsToScheme(scheme)
	}

	preferredExternalVersion := externalVersions[0]
	accessor := meta.NewAccessor()

	groupMeta := &apimachinery.GroupMeta{
		GroupVersion:  preferredExternalVersion,
		GroupVersions: externalVersions,
		SelfLinker:    runtime.SelfLinker(accessor),
	}
	for _, v := range externalVersions {
		gvf := gmf.VersionArgs[v.Version]
		if err := groupMeta.AddVersionInterfaces(
			schema.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
			&meta.VersionInterfaces{
				ObjectConvertor:  scheme,
				MetadataAccessor: accessor,
			},
		); err != nil {
			return err
		}
	}
	groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
	groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)

	if err := m.RegisterGroup(*groupMeta); err != nil {
		return err
	}
	return nil
}

// RegisterAndEnable is provided only to allow this code to get added in multiple steps.
// It's really bad that this is called in init() methods, but supporting this
// temporarily lets us do the change incrementally.
func (gmf *GroupMetaFactory) RegisterAndEnable(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
	if err := gmf.Register(registry); err != nil {
		return err
	}
	if err := gmf.Enable(registry, scheme); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package vagrant

import (
	"io"
	"os"
	"os/exec"
	"strings"

	"github.com/hashicorp/otto/ui"
)

// SSHCache is a helper to cache the SSH connection info from Vagrant
// and use that for executing to avoid the overhead of loading Vagrant.
type SSHCache struct {
	// Path is the path to where the SSH cache file should go
	Path string

	// Vagrant is the Vagrant instance we'll use to execute Vagrant commands.
	Vagrant *Vagrant
}

// Exec executes SSH and opens a console.
//
// This will use the cached SSH info if it exists, or will otherwise
// drop into `vagrant ssh`. If cacheOkay is false, then it'll always go
// straight to `vagrant ssh`.
func (c *SSHCache) Exec(cacheOkay bool) error {
	// If we have the cache file, use that
	if _, err := os.Stat(c.Path); err == nil {
		cmd := exec.Command("ssh", "-F", c.Path, "default")
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Start(); err != nil {
			return err
		}
		if err := cmd.Wait(); err != nil {
			return err
		}
		return nil
	}

	// Otherwise raw SSH
	return c.Vagrant.Execute("ssh")
}

// Cache will execute "ssh-config" and cache the SSH info.
func (c *SSHCache) Cache() error {
	// We just copy the Vagrant instance so we can modify it without
	// worrying about restoring stuff.
	var mockUi ui.Mock
	vagrant := *c.Vagrant
	vagrant.Ui = &mockUi
	if err := vagrant.Execute("ssh-config"); err != nil {
		return err
	}

	// Write the output to the cache
	f, err := os.Create(c.Path)
	if err != nil {
		return err
	}
	defer f.Close()

	for _, raw := range mockUi.RawBuf {
		if _, err := io.Copy(f, strings.NewReader(raw)); err != nil {
			return err
		}
	}

	return nil
}

// Delete clears the cache.
func (c *SSHCache) Delete() error {
	// We ignore the return value here because it'll happen if the
	// file doesn't exist and we just don't care.
	os.Remove(c.Path)
	return nil
}
<commit_msg>helper/vagrant: log SSH command<commit_after>package vagrant

import (
	"io"
	"log"
	"os"
	"os/exec"
	"strings"

	"github.com/hashicorp/otto/ui"
)

// SSHCache is a helper to cache the SSH connection info from Vagrant
// and use that for executing to avoid the overhead of loading Vagrant.
type SSHCache struct {
	// Path is the path to where the SSH cache file should go
	Path string

	// Vagrant is the Vagrant instance we'll use to execute Vagrant commands.
	Vagrant *Vagrant
}

// Exec executes SSH and opens a console.
//
// This will use the cached SSH info if it exists, or will otherwise
// drop into `vagrant ssh`. If cacheOkay is false, then it'll always go
// straight to `vagrant ssh`.
func (c *SSHCache) Exec(cacheOkay bool) error {
	// If we have the cache file, use that
	if _, err := os.Stat(c.Path); err == nil {
		log.Printf("[DEBUG] ssh command: ssh -F " + c.Path + " default")
		cmd := exec.Command("ssh", "-F", c.Path, "default")
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Start(); err != nil {
			return err
		}
		if err := cmd.Wait(); err != nil {
			return err
		}
		return nil
	}

	// Otherwise raw SSH
	return c.Vagrant.Execute("ssh")
}

// Cache will execute "ssh-config" and cache the SSH info.
func (c *SSHCache) Cache() error {
	// We just copy the Vagrant instance so we can modify it without
	// worrying about restoring stuff.
	var mockUi ui.Mock
	vagrant := *c.Vagrant
	vagrant.Ui = &mockUi
	if err := vagrant.Execute("ssh-config"); err != nil {
		return err
	}

	// Write the output to the cache
	f, err := os.Create(c.Path)
	if err != nil {
		return err
	}
	defer f.Close()

	for _, raw := range mockUi.RawBuf {
		if _, err := io.Copy(f, strings.NewReader(raw)); err != nil {
			return err
		}
	}

	return nil
}

// Delete clears the cache.
func (c *SSHCache) Delete() error {
	// We ignore the return value here because it'll happen if the
	// file doesn't exist and we just don't care.
	os.Remove(c.Path)
	return nil
}
<|endoftext|>