<commit_before>package orm

import (
	"reflect"
	"testing"
)

func TestSave(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//check if the object is stored in the table and if the ID is populated after insert
	ormTest.DropTable()
	ormTest.CreateTable()
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	err = ormTest.Save(&dslTest)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	id := dslTest.ID
	if id != 1 {
		t.Fatalf("want: 1; got: %v", id)
	}

	dslTestFind, err := ormTest.Select().ByID(id)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj := dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	obj.FieldInt = 222
	err = ormTest.Save(&obj)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	dslTestFindUptated, err := ormTest.Select().ByID(id)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj = dslTestFindUptated.(DSLTest)

	if dslTestFindUptated == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 222 {
		t.Fatalf("want: 222, got: %v", obj.FieldInt)
	}

	dslTestNegativeID := DSLTest{FieldString: "teststring", FieldInt: 123, ID: -1}
	err = ormTest.Save(&dslTestNegativeID)
	if err.Error() != "Negative ID not allowed: {-1 teststring 123}" {
		t.Fatalf("want: `Negative ID not allowed: {-1 teststring 123}`, got `%v`", err)
	}
}

func TestInsertAndUpdate(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	//create a new handler for DSLTest structure
	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//DropTable & CreateTable
	ormTest.DropTable()
	ormTest.CreateTable()

	//create a test object
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	object := reflect.ValueOf(&dslTest).Elem()

	//insert on db
	err = ormTest.insert(object)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	if dslTest.ID != 1 {
		t.Fatalf("\ndslTest.ID got:\t %v\nWant:\t\t\t 1\n", dslTest.ID)
	}

	//check if the object was persisted
	dslTestFind, err := ormTest.Select().ByID(1)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj := dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 123 {
		t.Fatalf("want: 123, got: %v", obj.FieldInt)
	}

	//change FieldInt atribute
	obj.FieldInt = 222

	//update on db
	object = reflect.ValueOf(&obj).Elem()
	err = ormTest.update(object)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	//check if the object was correctly updated
	dslTestFind, err = ormTest.Select().ByID(1)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj = dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 222 {
		t.Fatalf("want: 222, got: %v", obj.FieldInt)
	}

	//force a error on insert
	oldInsertSQL := ormTest.insertSQL
	ormTest.insertSQL = "wrong-sql"
	err = ormTest.insert(object)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.insertSQL = oldInsertSQL

	//force a error on insert
	oldUpdateSQL := ormTest.updateSQL
	ormTest.updateSQL = "wrong-sql"
	err = ormTest.update(object)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.updateSQL = oldUpdateSQL
}

func TestAssembleValuesArray(t *testing.T) {

}

func TestAssembleSQLInsertStatement(t *testing.T) {
	var handler Handler
	handler.table = DSLTest{}

	//check if the sqlInsert string is assembled correctly
	handler.assembleSQLInsert()
	expected := `insert into DSLTest(FieldString, FieldInt) values ($1, $2) RETURNING id;`
	got := handler.insertSQL
	if got != expected {
		t.Fatalf("\nExpected:\t %v\nGot:\t\t %v\n", expected, got)
	}

	//expectedMap := []saveField{}
	mapInsert := handler.insertMap
	if len(mapInsert) != 2 {
		t.Fatalf("\nmapInsert lengh:\t %v\nWant:\t\t\t 2\n", len(mapInsert))
	}

	if mapInsert[0].name != "FieldString" || mapInsert[0].fieldType != "string" {
		t.Fatalf("\nmapInsert[0] got:\t %v\nWant:\t\t\t {FieldString string}\n", mapInsert[0])
	}

	if mapInsert[1].name != "FieldInt" || mapInsert[1].fieldType != "int" {
		t.Fatalf("\nmapInsert[0] got:\t %v\nWant:\t\t\t {FieldInt int}\n", mapInsert[1])
	}
}

func TestAssembleSQLUpdate(t *testing.T) {
	var handler Handler
	handler.table = DSLTest{}

	handler.assembleSQLUpdate()
	expected := `update DSLTest set FieldString = $1, FieldInt = $2 where id = $3`
	got := handler.updateSQL
	if got != expected {
		t.Fatalf("\nExpected:\t %v\nGot:\t\t %v\n", expected, got)
	}

	updateMap := handler.updateMap
	if len(updateMap) != 3 {
		t.Fatalf("updateMap lenght: %v, want: 3", len(updateMap))
	}

	if updateMap[0].name != "FieldString" || updateMap[0].fieldType != "string" {
		t.Fatalf("updateMap[0] got:\t %v\nWant:\t\t\t {FieldString string}\n", updateMap[0])
	}

	if updateMap[1].name != "FieldInt" || updateMap[1].fieldType != "int" {
		t.Fatalf("updateMap[1] got:\t %v\nWant:\t\t\t {FieldInt int}\n", updateMap[1])
	}

	if updateMap[2].name != "ID" || updateMap[2].fieldType != "int" {
		t.Fatalf("updateMap[2] got: %v, want: {ID int}\n", updateMap[2])
	}
}
<commit_msg>Improve unit test for Save<commit_after>package orm

import (
	"reflect"
	"testing"
)

func TestSave(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//DropTable & CreateTable
	ormTest.DropTable()
	ormTest.CreateTable()

	//Check if we get an error when we try to insert a diferent object for this handler
	dslTestWithoutID := DSLTestWithoutID{FieldString: "teststring", FieldInt: 123}
	err = ormTest.Save(&dslTestWithoutID)
	if err.Error() != "Object table name (DSLTestWithoutID) is diferent from handler table name (DSLTest)" {
		t.Fatalf("Want: `Object table name (DSLTestWithoutID) is diferent from handler table name (DSLTest)`, got: `%v`", err)
	}

	//save a new object
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	err = ormTest.Save(&dslTest)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	//check if the id is 1
	id := dslTest.ID
	if id != 1 {
		t.Fatalf("want: 1; got: %v", id)
	}

	//check if the object was persisted
	dslTestFind, err := ormTest.Select().ByID(id)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj := dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	//update the FieldInt atribute
	obj.FieldInt = 222
	err = ormTest.Save(&obj)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	//check if the changes were persisted
	dslTestFindUptated, err := ormTest.Select().ByID(id)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj = dslTestFindUptated.(DSLTest)

	if dslTestFindUptated == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 222 {
		t.Fatalf("want: 222, got: %v", obj.FieldInt)
	}

	//check if we got an error when trying to insert an object with negative ID
	dslTestNegativeID := DSLTest{FieldString: "teststring", FieldInt: 123, ID: -1}
	err = ormTest.Save(&dslTestNegativeID)
	if err.Error() != "Negative ID not allowed: {-1 teststring 123}" {
		t.Fatalf("want: `Negative ID not allowed: {-1 teststring 123}`, got `%v`", err)
	}
}

func TestInsertAndUpdate(t *testing.T) {
	//connect to Postgres
	orm, scream := ConnectToPostgres()
	if scream != nil {
		panic(scream)
	}

	//create a new handler for DSLTest structure
	ormTest, err := orm.NewHandler(DSLTest{})
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	//DropTable & CreateTable
	ormTest.DropTable()
	ormTest.CreateTable()

	//create a test object
	dslTest := DSLTest{FieldString: "teststring", FieldInt: 123}
	object := reflect.ValueOf(&dslTest).Elem()

	//insert on db
	err = ormTest.insert(object)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	if dslTest.ID != 1 {
		t.Fatalf("\ndslTest.ID got:\t %v\nWant:\t\t\t 1\n", dslTest.ID)
	}

	//check if the object was persisted
	dslTestFind, err := ormTest.Select().ByID(1)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj := dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 123 {
		t.Fatalf("want: 123, got: %v", obj.FieldInt)
	}

	//change FieldInt atribute
	obj.FieldInt = 222

	//update on db
	object = reflect.ValueOf(&obj).Elem()
	err = ormTest.update(object)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	//check if the object was correctly updated
	dslTestFind, err = ormTest.Select().ByID(1)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	obj = dslTestFind.(DSLTest)

	if dslTestFind == nil {
		t.Fatalf("want: a valida object, got nil")
	}

	if obj.FieldInt != 222 {
		t.Fatalf("want: 222, got: %v", obj.FieldInt)
	}

	//force a error on insert
	oldInsertSQL := ormTest.insertSQL
	ormTest.insertSQL = "wrong-sql"
	err = ormTest.insert(object)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.insertSQL = oldInsertSQL

	//force a error on insert
	oldUpdateSQL := ormTest.updateSQL
	ormTest.updateSQL = "wrong-sql"
	err = ormTest.update(object)
	if err.Error() != "pq: syntax error at or near \"wrong\"" {
		t.Fatalf("want: `pq: syntax error at or near \"wrong\"`, got: `%v`", err)
	}
	ormTest.updateSQL = oldUpdateSQL
}

func TestAssembleValuesArray(t *testing.T) {

}

func TestAssembleSQLInsertStatement(t *testing.T) {
	var handler Handler
	handler.table = DSLTest{}

	//check if the sqlInsert string is assembled correctly
	handler.assembleSQLInsert()
	expected := `insert into DSLTest(FieldString, FieldInt) values ($1, $2) RETURNING id;`
	got := handler.insertSQL
	if got != expected {
		t.Fatalf("\nExpected:\t %v\nGot:\t\t %v\n", expected, got)
	}

	//expectedMap := []saveField{}
	mapInsert := handler.insertMap
	if len(mapInsert) != 2 {
		t.Fatalf("\nmapInsert lengh:\t %v\nWant:\t\t\t 2\n", len(mapInsert))
	}

	if mapInsert[0].name != "FieldString" || mapInsert[0].fieldType != "string" {
		t.Fatalf("\nmapInsert[0] got:\t %v\nWant:\t\t\t {FieldString string}\n", mapInsert[0])
	}

	if mapInsert[1].name != "FieldInt" || mapInsert[1].fieldType != "int" {
		t.Fatalf("\nmapInsert[0] got:\t %v\nWant:\t\t\t {FieldInt int}\n", mapInsert[1])
	}
}

func TestAssembleSQLUpdate(t *testing.T) {
	var handler Handler
	handler.table = DSLTest{}

	handler.assembleSQLUpdate()
	expected := `update DSLTest set FieldString = $1, FieldInt = $2 where id = $3`
	got := handler.updateSQL
	if got != expected {
		t.Fatalf("\nExpected:\t %v\nGot:\t\t %v\n", expected, got)
	}

	updateMap := handler.updateMap
	if len(updateMap) != 3 {
		t.Fatalf("updateMap lenght: %v, want: 3", len(updateMap))
	}

	if updateMap[0].name != "FieldString" || updateMap[0].fieldType != "string" {
		t.Fatalf("updateMap[0] got:\t %v\nWant:\t\t\t {FieldString string}\n", updateMap[0])
	}

	if updateMap[1].name != "FieldInt" || updateMap[1].fieldType != "int" {
		t.Fatalf("updateMap[1] got:\t %v\nWant:\t\t\t {FieldInt int}\n", updateMap[1])
	}

	if updateMap[2].name != "ID" || updateMap[2].fieldType != "int" {
		t.Fatalf("updateMap[2] got: %v, want: {ID int}\n", updateMap[2])
	}
}
<|endoftext|>


<commit_before>package logger

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"
)

var (
	VERBOSE = &LogLevel{tag: "VERBOSE", ordinal: 1}
	DEBUG   = &LogLevel{tag: "DEBUG  ", ordinal: 2}
	INFO    = &LogLevel{tag: "INFO   ", ordinal: 3}
	ERROR   = &LogLevel{tag: "ERROR  ", ordinal: 4}

	vLog = log.New(&proxy{level: VERBOSE}, "", 0)
	dLog = log.New(&proxy{level: DEBUG}, "", 0)
	iLog = log.New(&proxy{level: INFO}, "", 0)
	eLog = log.New(&proxy{level: ERROR}, "", log.Lshortfile)

	currentLevel = INFO
	timeFormat   = "2006-01-02 15:04:05"
	logFile      = os.Stderr
)

type LogLevel struct {
	tag     string
	ordinal int
}

type proxy struct {
	level *LogLevel
}

func (t *proxy) Write(p []byte) (n int, err error) {

	if currentLevel.ordinal <= t.level.ordinal {

		timeStamp := time.Now().Format(timeFormat)

		prefix := timeStamp + " " + t.level.tag + " "

		var prefixCount, logCount int

		prefixCount, err = logFile.Write([]byte(prefix))
		if err == nil {
			logCount, err = logFile.Write(p)
		}

		return (prefixCount + logCount), err
	} else {
		return 0, nil
	}
}

func getLevel(level string) *LogLevel {
	logLevel := strings.TrimSpace(strings.ToUpper(level))

	switch logLevel {
	case strings.TrimSpace(VERBOSE.tag):
		return VERBOSE
	case strings.TrimSpace(DEBUG.tag):
		return DEBUG
	case strings.TrimSpace(INFO.tag):
		return INFO
	case strings.TrimSpace(ERROR.tag):
		return ERROR
	}

	return INFO
}

func Init() {
	// Set the default log to use the same format as this library
	log.SetOutput(&proxy{level: INFO})
	log.SetFlags(0)
}

func SetLogLevel(newLevel string) {
	level := getLevel(newLevel)
	I("Setting log level to", level.tag)
	currentLevel = level
}

func SetTimeFormat(format string) {
	timeFormat = format
}

func SetLogFileLocation(fileLocation string) {
	// Close previous log file
	if logFile != os.Stderr {
		logFile.Close()
	}

	f, err := os.OpenFile(fileLocation, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		E("Error opening log file: %v", err)
		panic(err)
	}
	logFile = f
}

func V(v ...interface{}) {
	if currentLevel.ordinal <= VERBOSE.ordinal {
		vLog.Output(3, fmt.Sprintln(v...))
	}
}

func D(v ...interface{}) {
	if currentLevel.ordinal <= DEBUG.ordinal {
		dLog.Output(3, fmt.Sprintln(v...))
	}
}

func I(v ...interface{}) {
	if currentLevel.ordinal <= INFO.ordinal {
		iLog.Output(3, fmt.Sprintln(v...))
	}
}

func E(v ...interface{}) {
	if currentLevel.ordinal <= ERROR.ordinal {
		eLog.Output(3, fmt.Sprintln(v...))
	}
}
<commit_msg>Try to create log directory when setting the output log file.<commit_after>package logger

import (
	"fmt"
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

var (
	VERBOSE = &LogLevel{tag: "VERBOSE", ordinal: 1}
	DEBUG   = &LogLevel{tag: "DEBUG  ", ordinal: 2}
	INFO    = &LogLevel{tag: "INFO   ", ordinal: 3}
	ERROR   = &LogLevel{tag: "ERROR  ", ordinal: 4}

	vLog = log.New(&proxy{level: VERBOSE}, "", 0)
	dLog = log.New(&proxy{level: DEBUG}, "", 0)
	iLog = log.New(&proxy{level: INFO}, "", 0)
	eLog = log.New(&proxy{level: ERROR}, "", log.Lshortfile)

	currentLevel = INFO
	timeFormat   = "2006-01-02 15:04:05"
	logFile      = os.Stderr
)

type LogLevel struct {
	tag     string
	ordinal int
}

type proxy struct {
	level *LogLevel
}

func (t *proxy) Write(p []byte) (n int, err error) {

	if currentLevel.ordinal <= t.level.ordinal {

		timeStamp := time.Now().Format(timeFormat)

		prefix := timeStamp + " " + t.level.tag + " "

		var prefixCount, logCount int

		prefixCount, err = logFile.Write([]byte(prefix))
		if err == nil {
			logCount, err = logFile.Write(p)
		}

		return (prefixCount + logCount), err
	} else {
		return 0, nil
	}
}

func getLevel(level string) *LogLevel {
	logLevel := strings.TrimSpace(strings.ToUpper(level))

	switch logLevel {
	case strings.TrimSpace(VERBOSE.tag):
		return VERBOSE
	case strings.TrimSpace(DEBUG.tag):
		return DEBUG
	case strings.TrimSpace(INFO.tag):
		return INFO
	case strings.TrimSpace(ERROR.tag):
		return ERROR
	}

	return INFO
}

func Init() {
	// Set the default log to use the same format as this library
	log.SetOutput(&proxy{level: INFO})
	log.SetFlags(0)
}

func SetLogLevel(newLevel string) {
	level := getLevel(newLevel)
	I("Setting log level to", level.tag)
	currentLevel = level
}

func SetTimeFormat(format string) {
	timeFormat = format
}

func SetLogFileLocation(fileLocation string) {

	// Try to create log directory
	logFilePath, _ := filepath.Abs(fileLocation)
	err := os.MkdirAll(path.Dir(logFilePath), 0755)

	if err != nil {
		E("Cannot create log directory:", err)
		os.Exit(-1)
	}

	f, err := os.OpenFile(fileLocation, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		E("Error opening log file:", err)
		os.Exit(-1)
	}

	// Close previous log file
	if logFile != os.Stderr {
		logFile.Close()
	}

	logFile = f
}

func V(v ...interface{}) {
	if currentLevel.ordinal <= VERBOSE.ordinal {
		vLog.Output(3, fmt.Sprintln(v...))
	}
}

func D(v ...interface{}) {
	if currentLevel.ordinal <= DEBUG.ordinal {
		dLog.Output(3, fmt.Sprintln(v...))
	}
}

func I(v ...interface{}) {
	if currentLevel.ordinal <= INFO.ordinal {
		iLog.Output(3, fmt.Sprintln(v...))
	}
}

func E(v ...interface{}) {
	if currentLevel.ordinal <= ERROR.ordinal {
		eLog.Output(3, fmt.Sprintln(v...))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/dsnet/golib/strconv"
)

type packetLogger struct {
	logger logger
	last   time.Time // Last time we printed statistics
	c      chan packetLog
	m      map[packetLog]packetCount
	rx, tx struct{ okay, drop packetCount }
}

type packetLog struct {
	direction  direction
	dropped    bool
	ipVersion  int
	ipProtocol int
	srcAddr    [4]byte
	dstAddr    [4]byte
	srcPort    uint16
	dstPort    uint16
	length     int
}

type packetCount struct {
	count uint64
	sizes uint64
}

func newPacketLogger(ctx context.Context, wg *sync.WaitGroup, logger logger) *packetLogger {
	pl := &packetLogger{
		logger: logger,
		last:   time.Now().Round(time.Second),
		c:      make(chan packetLog, 1024),
		m:      make(map[packetLog]packetCount),
	}
	wg.Add(1)
	go func() {
		defer wg.Done()
		pl.monitor(ctx)
	}()
	return pl
}

// Log logs the packet for periodic printing of aggregated statistics.
func (pl *packetLogger) Log(b []byte, d direction, dropped bool) {
	ip := ipPacket(b)
	p := packetLog{
		direction:  d,
		dropped:    dropped,
		ipVersion:  ip.Version(),
		length:     len(b),
		ipProtocol: ip.Protocol(),
	}
	if p.ipVersion == 4 {
		p.srcAddr, p.dstAddr = ip.AddressesV4()
	}
	if p.ipProtocol == udp || p.ipProtocol == tcp {
		p.srcPort, p.dstPort = transportPacket(ip.Body()).Ports()
	}
	pl.c <- p
}

func (pl *packetLogger) monitor(ctx context.Context) {
	t := time.NewTicker(30 * time.Second)
	defer t.Stop()

	for {
		select {
		case p := <-pl.c:
			size := p.length
			p.length = 0
			pc := pl.m[p]
			pc.count++
			pc.sizes += uint64(size)
			pl.m[p] = pc
		case <-t.C:
			var count, sizes uint64
			for _, v := range pl.m {
				count += v.count
				sizes += v.sizes
			}
			if count < (1<<12) && sizes < (1<<18) && time.Now().Sub(pl.last) < time.Hour {
				continue // Skip printing statistics if traffic is low.
			}
			pl.print()
		case <-ctx.Done():
			pl.print()
			return
		}
	}
}

// print prints an aggregated summary of all packets.
// To avoid races, this method is only called from monitor.
func (pl *packetLogger) print() {
	if len(pl.m) == 0 {
		return
	}
	stats := make([]string, 2) // First 2 lines for total stats
	protoNames := map[int]string{icmp: "ICMP", udp: "UDP", tcp: "TCP"}
	for k, v := range pl.m {
		var pc *packetCount
		switch {
		case !k.dropped && k.direction == outbound:
			pc = &pl.tx.okay
		case !k.dropped && k.direction == inbound:
			pc = &pl.rx.okay
		case k.dropped && k.direction == outbound:
			pc = &pl.tx.drop
		case k.dropped && k.direction == inbound:
			pc = &pl.rx.drop
		}
		pc.count += v.count
		pc.sizes += v.sizes

		proto := protoNames[k.ipProtocol]
		if proto == "" {
			proto = fmt.Sprintf("Unknown%d", k.ipProtocol)
		}
		var drop string
		if k.dropped {
			drop = "dropped "
		}
		link := fmt.Sprintf("%s:%d -> %s:%d", formatIPv4(k.srcAddr), k.srcPort, formatIPv4(k.dstAddr), k.dstPort)
		if k.ipProtocol != tcp && k.ipProtocol != udp {
			link = fmt.Sprintf("%s -> %s", formatIPv4(k.srcAddr), formatIPv4(k.dstAddr))
		}
		stats = append(stats, fmt.Sprintf("\tIPv%d/%s %s - %cx %d %spackets (%sB)",
			k.ipVersion, proto, link, k.direction, v.count, drop, formatIEC(v.sizes)))
	}
	stats[0] = fmt.Sprintf("\tRx %d total packets (%sB), dropped %d total packets (%sB)",
		pl.rx.okay.count, formatIEC(pl.rx.okay.sizes), pl.rx.drop.count, formatIEC(pl.rx.drop.sizes))
	stats[1] = fmt.Sprintf("\tTx %d total packets (%sB), dropped %d total packets (%sB)",
		pl.tx.okay.count, formatIEC(pl.tx.okay.sizes), pl.tx.drop.count, formatIEC(pl.tx.drop.sizes))
	sort.Strings(stats[2:])
	period := time.Now().Round(time.Second).Sub(pl.last)
	pl.logger.Printf("Packet statistics (%v):\n%s", period, strings.Join(stats, "\n"))
	pl.m = map[packetLog]packetCount{}
	pl.last = time.Now().Round(time.Second)
}

func formatIEC(n uint64) string {
	s := strconv.FormatPrefix(float64(n), strconv.IEC, 2)
	return strings.TrimSuffix(strings.TrimRight(s, "0"), ".")
}

func formatIPv4(ip [4]byte) string {
	return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}
<commit_msg>Rename strconv package to unitconv<commit_after>package main

import (
	"context"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/dsnet/golib/unitconv"
)

type packetLogger struct {
	logger logger
	last   time.Time // Last time we printed statistics
	c      chan packetLog
	m      map[packetLog]packetCount
	rx, tx struct{ okay, drop packetCount }
}

type packetLog struct {
	direction  direction
	dropped    bool
	ipVersion  int
	ipProtocol int
	srcAddr    [4]byte
	dstAddr    [4]byte
	srcPort    uint16
	dstPort    uint16
	length     int
}

type packetCount struct {
	count uint64
	sizes uint64
}

func newPacketLogger(ctx context.Context, wg *sync.WaitGroup, logger logger) *packetLogger {
	pl := &packetLogger{
		logger: logger,
		last:   time.Now().Round(time.Second),
		c:      make(chan packetLog, 1024),
		m:      make(map[packetLog]packetCount),
	}
	wg.Add(1)
	go func() {
		defer wg.Done()
		pl.monitor(ctx)
	}()
	return pl
}

// Log logs the packet for periodic printing of aggregated statistics.
func (pl *packetLogger) Log(b []byte, d direction, dropped bool) {
	ip := ipPacket(b)
	p := packetLog{
		direction:  d,
		dropped:    dropped,
		ipVersion:  ip.Version(),
		length:     len(b),
		ipProtocol: ip.Protocol(),
	}
	if p.ipVersion == 4 {
		p.srcAddr, p.dstAddr = ip.AddressesV4()
	}
	if p.ipProtocol == udp || p.ipProtocol == tcp {
		p.srcPort, p.dstPort = transportPacket(ip.Body()).Ports()
	}
	pl.c <- p
}

func (pl *packetLogger) monitor(ctx context.Context) {
	t := time.NewTicker(30 * time.Second)
	defer t.Stop()

	for {
		select {
		case p := <-pl.c:
			size := p.length
			p.length = 0
			pc := pl.m[p]
			pc.count++
			pc.sizes += uint64(size)
			pl.m[p] = pc
		case <-t.C:
			var count, sizes uint64
			for _, v := range pl.m {
				count += v.count
				sizes += v.sizes
			}
			if count < (1<<12) && sizes < (1<<18) && time.Now().Sub(pl.last) < time.Hour {
				continue // Skip printing statistics if traffic is low.
			}
			pl.print()
		case <-ctx.Done():
			pl.print()
			return
		}
	}
}

// print prints an aggregated summary of all packets.
// To avoid races, this method is only called from monitor.
func (pl *packetLogger) print() {
	if len(pl.m) == 0 {
		return
	}
	stats := make([]string, 2) // First 2 lines for total stats
	protoNames := map[int]string{icmp: "ICMP", udp: "UDP", tcp: "TCP"}
	for k, v := range pl.m {
		var pc *packetCount
		switch {
		case !k.dropped && k.direction == outbound:
			pc = &pl.tx.okay
		case !k.dropped && k.direction == inbound:
			pc = &pl.rx.okay
		case k.dropped && k.direction == outbound:
			pc = &pl.tx.drop
		case k.dropped && k.direction == inbound:
			pc = &pl.rx.drop
		}
		pc.count += v.count
		pc.sizes += v.sizes

		proto := protoNames[k.ipProtocol]
		if proto == "" {
			proto = fmt.Sprintf("Unknown%d", k.ipProtocol)
		}
		var drop string
		if k.dropped {
			drop = "dropped "
		}
		link := fmt.Sprintf("%s:%d -> %s:%d", formatIPv4(k.srcAddr), k.srcPort, formatIPv4(k.dstAddr), k.dstPort)
		if k.ipProtocol != tcp && k.ipProtocol != udp {
			link = fmt.Sprintf("%s -> %s", formatIPv4(k.srcAddr), formatIPv4(k.dstAddr))
		}
		stats = append(stats, fmt.Sprintf("\tIPv%d/%s %s - %cx %d %spackets (%sB)",
			k.ipVersion, proto, link, k.direction, v.count, drop, formatIEC(v.sizes)))
	}
	stats[0] = fmt.Sprintf("\tRx %d total packets (%sB), dropped %d total packets (%sB)",
		pl.rx.okay.count, formatIEC(pl.rx.okay.sizes), pl.rx.drop.count, formatIEC(pl.rx.drop.sizes))
	stats[1] = fmt.Sprintf("\tTx %d total packets (%sB), dropped %d total packets (%sB)",
		pl.tx.okay.count, formatIEC(pl.tx.okay.sizes), pl.tx.drop.count, formatIEC(pl.tx.drop.sizes))
	sort.Strings(stats[2:])
	period := time.Now().Round(time.Second).Sub(pl.last)
	pl.logger.Printf("Packet statistics (%v):\n%s", period, strings.Join(stats, "\n"))
	pl.m = map[packetLog]packetCount{}
	pl.last = time.Now().Round(time.Second)
}

func formatIEC(n uint64) string {
	s := unitconv.FormatPrefix(float64(n), unitconv.IEC, 2)
	return strings.TrimSuffix(strings.TrimRight(s, "0"), ".")
}

func formatIPv4(ip [4]byte) string {
	return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}
<|endoftext|>


<commit_before>package lsh

import (
	"testing"
)

const (
	path = "../data/tiny_images_small.bin"
)

func floatToIntPoint(p Point) []int {
	q := make([]int, len(p))
	for i := range p {
		q[i] = int(p[i])
	}
	return q
}

func Test_CountPoint(t *testing.T) {
	n := CountPoint(path, 3072)
	if n != 100 {
		t.Error("Should have 100 points in the test dataset")
	}
	t.Log(n)
}

func Test_PointIterator(t *testing.T) {
	parser := NewTinyImagePointParser()
	n := CountPoint(path, parser.ByteLen)
	it := NewDataPointIterator(path, parser)
	p, err := it.Next()
	for err == nil {
		t.Log(p)
		p, err = it.Next()
	}
	ids := SelectQueries(n, 10)
	it = NewQueryPointIterator(path, parser, ids)
	p, err = it.Next()
	for err == nil {
		t.Log(p)
		p, err = it.Next()
	}
}
<commit_msg>fix util test<commit_after>package lsh

import (
	"testing"
)

const (
	path = "../../data/tiny_images_small.bin"
)

func floatToIntPoint(p Point) []int {
	q := make([]int, len(p))
	for i := range p {
		q[i] = int(p[i])
	}
	return q
}

func Test_CountPoint(t *testing.T) {
	n := CountPoint(path, 3072)
	if n != 100 {
		t.Error("Should have 100 points in the test dataset")
	}
	t.Log(n)
}

func Test_PointIterator(t *testing.T) {
	parser := NewTinyImagePointParser()
	n := CountPoint(path, parser.ByteLen)
	it := NewDataPointIterator(path, parser)
	p, err := it.Next()
	for err == nil {
		t.Log(p)
		p, err = it.Next()
	}
	ids := SelectQueries(n, 10)
	it = NewQueryPointIterator(path, parser, ids)
	p, err = it.Next()
	for err == nil {
		t.Log(p)
		p, err = it.Next()
	}
}
<|endoftext|>


<commit_before>package nsqd

import (
	"fmt"
	"io/ioutil"
	"path"
	"path/filepath"
	"reflect"
	"runtime"
	"strconv"
	"testing"
	"time"

	"github.com/bitly/go-simplejson"
)

func assert(t *testing.T, condition bool, msg string, v ...interface{}) {
	if !condition {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d: "+msg+"\033[39m\n\n",
			append([]interface{}{filepath.Base(file), line}, v...)...)
		t.FailNow()
	}
}

func equal(t *testing.T, act, exp interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n",
			filepath.Base(file), line, exp, act)
		t.FailNow()
	}
}

func nequal(t *testing.T, act, exp interface{}) {
	if reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n",
			filepath.Base(file), line, exp, act)
		t.FailNow()
	}
}

type tbLog interface {
	Log(...interface{})
}

type testLogger struct {
	tbLog
}

func (tl *testLogger) Output(maxdepth int, s string) error {
	tl.Log(s)
	return nil
}

func newTestLogger(tbl tbLog) logger {
	return &testLogger{tbl}
}

func getMetadata(n *NSQD) (*simplejson.Json, error) {
	fn := fmt.Sprintf(path.Join(n.opts.DataPath, "nsqd.%d.dat"), n.opts.ID)
	data, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}

	js, err := simplejson.NewJson(data)
	if err != nil {
		return nil, err
	}
	return js, nil
}

func TestStartup(t *testing.T) {
	iterations := 300
	doneExitChan := make(chan int)

	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	opts.MaxBytesPerFile = 10240
	_, _, nsqd := mustStartNSQD(opts)

	topicName := "nsqd_test" + strconv.Itoa(int(time.Now().Unix()))

	exitChan := make(chan int)
	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	// verify nsqd metadata shows no topics
	err := nsqd.PersistMetadata()
	equal(t, err, nil)
	metaData, err := getMetadata(nsqd)
	equal(t, err, nil)
	topics, err := metaData.Get("topics").Array()
	equal(t, err, nil)
	equal(t, len(topics), 0)

	body := make([]byte, 256)
	topic := nsqd.GetTopic(topicName)
	for i := 0; i < iterations; i++ {
		msg := NewMessage(<-nsqd.idChan, body)
		topic.PutMessage(msg)
	}

	t.Logf("pulling from channel")
	channel1 := topic.GetChannel("ch1")

	t.Logf("read %d msgs", iterations/2)
	for i := 0; i < iterations/2; i++ {
		msg := <-channel1.clientMsgChan
		t.Logf("read message %d", i+1)
		equal(t, msg.Body, body)
	}

	for {
		if channel1.Depth() == int64(iterations/2) {
			break
		}
		time.Sleep(50 * time.Millisecond)
	}

	// make sure metadata shows the topic
	metaData, err = getMetadata(nsqd)
	equal(t, err, nil)
	topics, err = metaData.Get("topics").Array()
	equal(t, err, nil)
	equal(t, len(topics), 1)
	observedTopicName, err := metaData.Get("topics").GetIndex(0).Get("name").String()
	equal(t, observedTopicName, topicName)
	equal(t, err, nil)

	exitChan <- 1
	<-doneExitChan

	// start up a new nsqd w/ the same folder

	opts = NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	opts.MaxBytesPerFile = 10240
	_, _, nsqd = mustStartNSQD(opts)

	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	topic = nsqd.GetTopic(topicName)
	// should be empty; channel should have drained everything
	count := topic.Depth()
	equal(t, count, int64(0))

	channel1 = topic.GetChannel("ch1")

	for {
		if channel1.Depth() == int64(iterations/2) {
			break
		}
		time.Sleep(50 * time.Millisecond)
	}

	// read the other half of the messages
	for i := 0; i < iterations/2; i++ {
		msg := <-channel1.clientMsgChan
		t.Logf("read message %d", i+1)
		equal(t, msg.Body, body)
	}

	// verify we drained things
	equal(t, len(topic.memoryMsgChan), 0)
	equal(t, topic.backend.Depth(), int64(0))

	exitChan <- 1
	<-doneExitChan
}

func TestEphemeralTopicsAndChannels(t *testing.T) {
	// ephemeral topics/channels are lazily removed after the last channel/client is removed
	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	_, _, nsqd := mustStartNSQD(opts)

	topicName := "ephemeral_topic" + strconv.Itoa(int(time.Now().Unix())) + "#ephemeral"
	doneExitChan := make(chan int)

	exitChan := make(chan int)
	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	body := []byte("an_ephemeral_message")
	topic := nsqd.GetTopic(topicName)
	ephemeralChannel := topic.GetChannel("ch1#ephemeral")
	client := newClientV2(0, nil, &context{nsqd})
	ephemeralChannel.AddClient(client.ID, client)

	msg := NewMessage(<-nsqd.idChan, body)
	topic.PutMessage(msg)
	msg = <-ephemeralChannel.clientMsgChan
	equal(t, msg.Body, body)

	ephemeralChannel.RemoveClient(client.ID)

	time.Sleep(50 * time.Millisecond)

	topic.Lock()
	numChannels := len(topic.channelMap)
	topic.Unlock()
	equal(t, numChannels, 0)

	nsqd.Lock()
	numTopics := len(nsqd.topicMap)
	nsqd.Unlock()
	equal(t, numTopics, 0)

	exitChan <- 1
	<-doneExitChan
}

func metadataForChannel(n *NSQD, topicIndex int, channelIndex int) *simplejson.Json {
	metadata, _ := getMetadata(n)
	mChannels := metadata.Get("topics").GetIndex(topicIndex).Get("channels")
	return mChannels.GetIndex(channelIndex)
}

func TestPauseMetadata(t *testing.T) {
	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	_, _, nsqd := mustStartNSQD(opts)
	defer nsqd.Exit()

	topicName := "pause_metadata" + strconv.Itoa(int(time.Now().Unix()))
	topic := nsqd.GetTopic(topicName)
	channel := topic.GetChannel("ch")

	b, _ := metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, false)

	channel.Pause()

	b, _ = metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, true)

	channel.UnPause()

	b, _ = metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, false)
}
<commit_msg>nsqd: de-flake TestEphemeralTopicsAndChannels<commit_after>package nsqd

import (
	"fmt"
	"io/ioutil"
	"path"
	"path/filepath"
	"reflect"
	"runtime"
	"strconv"
	"testing"
	"time"

	"github.com/bitly/go-simplejson"
)

func assert(t *testing.T, condition bool, msg string, v ...interface{}) {
	if !condition {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d: "+msg+"\033[39m\n\n",
			append([]interface{}{filepath.Base(file), line}, v...)...)
		t.FailNow()
	}
}

func equal(t *testing.T, act, exp interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n",
			filepath.Base(file), line, exp, act)
		t.FailNow()
	}
}

func nequal(t *testing.T, act, exp interface{}) {
	if reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		t.Logf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n",
			filepath.Base(file), line, exp, act)
		t.FailNow()
	}
}

type tbLog interface {
	Log(...interface{})
}

type testLogger struct {
	tbLog
}

func (tl *testLogger) Output(maxdepth int, s string) error {
	tl.Log(s)
	return nil
}

func newTestLogger(tbl tbLog) logger {
	return &testLogger{tbl}
}

func getMetadata(n *NSQD) (*simplejson.Json, error) {
	fn := fmt.Sprintf(path.Join(n.opts.DataPath, "nsqd.%d.dat"), n.opts.ID)
	data, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, err
	}

	js, err := simplejson.NewJson(data)
	if err != nil {
		return nil, err
	}
	return js, nil
}

func TestStartup(t *testing.T) {
	iterations := 300
	doneExitChan := make(chan int)

	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	opts.MaxBytesPerFile = 10240
	_, _, nsqd := mustStartNSQD(opts)

	topicName := "nsqd_test" + strconv.Itoa(int(time.Now().Unix()))

	exitChan := make(chan int)
	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	// verify nsqd metadata shows no topics
	err := nsqd.PersistMetadata()
	equal(t, err, nil)
	metaData, err := getMetadata(nsqd)
	equal(t, err, nil)
	topics, err := metaData.Get("topics").Array()
	equal(t, err, nil)
	equal(t, len(topics), 0)

	body := make([]byte, 256)
	topic := nsqd.GetTopic(topicName)
	for i := 0; i < iterations; i++ {
		msg := NewMessage(<-nsqd.idChan, body)
		topic.PutMessage(msg)
	}

	t.Logf("pulling from channel")
	channel1 := topic.GetChannel("ch1")

	t.Logf("read %d msgs", iterations/2)
	for i := 0; i < iterations/2; i++ {
		msg := <-channel1.clientMsgChan
		t.Logf("read message %d", i+1)
		equal(t, msg.Body, body)
	}

	for {
		if channel1.Depth() == int64(iterations/2) {
			break
		}
		time.Sleep(50 * time.Millisecond)
	}

	// make sure metadata shows the topic
	metaData, err = getMetadata(nsqd)
	equal(t, err, nil)
	topics, err = metaData.Get("topics").Array()
	equal(t, err, nil)
	equal(t, len(topics), 1)
	observedTopicName, err := metaData.Get("topics").GetIndex(0).Get("name").String()
	equal(t, observedTopicName, topicName)
	equal(t, err, nil)

	exitChan <- 1
	<-doneExitChan

	// start up a new nsqd w/ the same folder

	opts = NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	opts.MaxBytesPerFile = 10240
	_, _, nsqd = mustStartNSQD(opts)

	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	topic = nsqd.GetTopic(topicName)
	// should be empty; channel should have drained everything
	count := topic.Depth()
	equal(t, count, int64(0))

	channel1 = topic.GetChannel("ch1")

	for {
		if channel1.Depth() == int64(iterations/2) {
			break
		}
		time.Sleep(50 * time.Millisecond)
	}

	// read the other half of the messages
	for i := 0; i < iterations/2; i++ {
		msg := <-channel1.clientMsgChan
		t.Logf("read message %d", i+1)
		equal(t, msg.Body, body)
	}

	// verify we drained things
	equal(t, len(topic.memoryMsgChan), 0)
	equal(t, topic.backend.Depth(), int64(0))

	exitChan <- 1
	<-doneExitChan
}

func TestEphemeralTopicsAndChannels(t *testing.T) {
	// ephemeral topics/channels are lazily removed after the last channel/client is removed
	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	opts.MemQueueSize = 100
	_, _, nsqd := mustStartNSQD(opts)

	topicName := "ephemeral_topic" + strconv.Itoa(int(time.Now().Unix())) + "#ephemeral"
	doneExitChan := make(chan int)

	exitChan := make(chan int)
	go func() {
		<-exitChan
		nsqd.Exit()
		doneExitChan <- 1
	}()

	body := []byte("an_ephemeral_message")
	topic := nsqd.GetTopic(topicName)
	ephemeralChannel := topic.GetChannel("ch1#ephemeral")
	client := newClientV2(0, nil, &context{nsqd})
	ephemeralChannel.AddClient(client.ID, client)

	msg := NewMessage(<-nsqd.idChan, body)
	topic.PutMessage(msg)
	msg = <-ephemeralChannel.clientMsgChan
	equal(t, msg.Body, body)

	ephemeralChannel.RemoveClient(client.ID)

	time.Sleep(100 * time.Millisecond)

	topic.Lock()
	numChannels := len(topic.channelMap)
	topic.Unlock()
	equal(t, numChannels, 0)

	nsqd.Lock()
	numTopics := len(nsqd.topicMap)
	nsqd.Unlock()
	equal(t, numTopics, 0)

	exitChan <- 1
	<-doneExitChan
}

func metadataForChannel(n *NSQD, topicIndex int, channelIndex int) *simplejson.Json {
	metadata, _ := getMetadata(n)
	mChannels := metadata.Get("topics").GetIndex(topicIndex).Get("channels")
	return mChannels.GetIndex(channelIndex)
}

func TestPauseMetadata(t *testing.T) {
	opts := NewNSQDOptions()
	opts.Logger = newTestLogger(t)
	_, _, nsqd := mustStartNSQD(opts)
	defer nsqd.Exit()

	topicName := "pause_metadata" + strconv.Itoa(int(time.Now().Unix()))
	topic := nsqd.GetTopic(topicName)
	channel := topic.GetChannel("ch")

	b, _ := metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, false)

	channel.Pause()

	b, _ = metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, true)

	channel.UnPause()

	b, _ = metadataForChannel(nsqd, 0, 0).Get("paused").Bool()
	equal(t, b, false)
}
<|endoftext|>


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

package xurls

import (
	"regexp"
)

//go:generate go run tools/tldsgen/main.go
//go:generate go run tools/regexgen/main.go

const (
	letters    = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"
	iriChar    = letters + `0-9`
	ipv4Addr   = `(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])`
	ipv6Addr   = `([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{0,4}|:[0-9A-Fa-f]{1,4})?|(:[0-9A-Fa-f]{1,4}){0,2})|(:[0-9A-Fa-f]{1,4}){0,3})|(:[0-9A-Fa-f]{1,4}){0,4})|:(:[0-9A-Fa-f]{1,4}){0,5})((:[0-9A-Fa-f]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9A-Fa-f]{1,4}:){1,6}|:):[0-9A-Fa-f]{0,4}|([0-9A-Fa-f]{1,4}:){7}:`
	ipAddr     = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri        = `[` + iriChar + `]([` + iriChar + `\-]{0,61}[` + iriChar + `])?`
	hostName   = `(` + iri + `\.)+` + gtld
	domainName = `(` + hostName + `|` + ipAddr + `|localhost)`
	webURL     = `((https?://([a-zA-Z0-9$-_.+!*'(),;?&=]{1,64}(:[a-zA-Z0-9$\-_.+!*'(),;?&=]{1,25})?\@)?)?(` + domainName + `)(:[0-9]{1,5})?)(/([` + iriChar + `;/?:@&=#~\-.+!*'(),_])*)?`
	email      = `[a-zA-Z0-9._%\-+]{1,256}@` + domainName
	all        = `(` + webURL + `|` + email + `)`
)

// Regex expressions that match various kinds of urls and addresses
var (
	WebURL = regexp.MustCompile(webURL)
	Email  = regexp.MustCompile(email)
	All    = regexp.MustCompile(all)
)
<commit_msg>Remove auth part from webURL<commit_after>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import (
	"regexp"
)

//go:generate go run tools/tldsgen/main.go
//go:generate go run tools/regexgen/main.go

const (
	letters    = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"
	iriChar    = letters + `0-9`
	ipv4Addr   = `(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])`
	ipv6Addr   = `([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{0,4}|:[0-9A-Fa-f]{1,4})?|(:[0-9A-Fa-f]{1,4}){0,2})|(:[0-9A-Fa-f]{1,4}){0,3})|(:[0-9A-Fa-f]{1,4}){0,4})|:(:[0-9A-Fa-f]{1,4}){0,5})((:[0-9A-Fa-f]{1,4}){2}|:(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])(\.(25[0-5]|(2[0-4]|1[0-9]|[1-9])?[0-9])){3})|(([0-9A-Fa-f]{1,4}:){1,6}|:):[0-9A-Fa-f]{0,4}|([0-9A-Fa-f]{1,4}:){7}:`
	ipAddr     = `(` + ipv4Addr + `|` + ipv6Addr + `)`
	iri        = `[` + iriChar + `]([` + iriChar + `\-]{0,61}[` + iriChar + `])?`
	hostName   = `(` + iri + `\.)+` + gtld
	domainName = `(` + hostName + `|` + ipAddr + `|localhost)`
	webURL     = `((https?://)?(` + domainName + `)(:[0-9]{1,5})?)(/([` + iriChar + `;/?:@&=#~\-.+!*'(),_])*)?`
	email      = `[a-zA-Z0-9._%\-+]{1,256}@` + domainName
	all        = `(` + webURL + `|` + email + `)`
)

// Regex expressions that match various kinds of urls and addresses
var (
	WebURL = regexp.MustCompile(webURL)
	Email  = regexp.MustCompile(email)
	All    = regexp.MustCompile(all)
)
<|endoftext|>


<commit_before>package main_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func test_with_hscript(t *testing.T, t_name, content string, t_err error) {

	workdir, err := ioutil.TempDir("", "hwaf-test-")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer os.RemoveAll(workdir)

	err = os.Chdir(workdir)
	if err != nil {
		t.Fatalf(err.Error())
	}

	hwaf, err := newlogger("hwaf.log")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer hwaf.Close()

	for _, cmd := range [][]string{
		{"hwaf", "init", "-v=1", "."},
		{"hwaf", "setup", "-v=1"},
		{"hwaf", "pkg", "create", "-script=hscript", "-v=1", "mypkg"},
		{"hwaf", "pkg", "ls"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil {
			hwaf.Display()
			t.Fatalf("cmd %v failed: %v", cmd, err)
		}
	}

	mypkgdir := filepath.Join("src", "mypkg")

	// hscript.yml file
	ff, err := os.Create(filepath.Join(mypkgdir, "hscript.yml"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(content)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	err = os.MkdirAll(filepath.Join(mypkgdir, "waftools"), 0777)
	if err != nil {
		t.Fatalf(err.Error())
	}

	// waftools/script-1.py
	ff, err = os.Create(filepath.Join(mypkgdir, "waftools", "script-1.py"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(`
## -*- python -*-
def no_configure(ctx):
    pass

def no_build(ctx):
    pass

`)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	// waftools/script-2.py
	ff, err = os.Create(filepath.Join(mypkgdir, "waftools", "script-2.py"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(`
## -*- python -*-
import waflib.Logs as msg

def configure(ctx):
    msg.info("tool script-2 loaded from configure")
    pass

def build(ctx):
    msg.info("tool script-1 loaded from configure")
    pass

`)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	for _, cmd := range [][]string{
		{"hwaf", "configure"},
		//{"hwaf"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil && t_err == nil {
			hwaf.Display()
			t.Fatalf("in test [%s] cmd %v failed: %v", t_name, cmd, err)
		}
	}
}

func TestHwafHscriptSections(t *testing.T) {

	//var no_error error = nil
	var w_error error = fmt.Errorf("error expected")

	for _, tt := range []struct {
		name     string
		content  string
		expected error
	}{
		{
			name: "empty hscript",
			content: `
# -*- yaml -*-

`,
			expected: w_error,
		},
		{
			name: "empty content hscript",
			content: `
# -*- yaml -*-
package: {}
options: {}
configure: {}
build: {}
`,
			expected: w_error,
		},
		{
			name: "valid empty content hscript",
			content: `
# -*- yaml -*-
package: {name: "mypkg"}
options: {}
configure: {}
build: {}
`,
			expected: nil,
		},
		{
			name: "mispelled packages",
			content: `
# -*- yaml -*-
packaGes: {
}
`,
			expected: w_error,
		},
		{
			name: "missing packages content",
			content: `
# -*- yaml -*-
package: {
}
`,
			expected: w_error,
		},
		{
			name: "misspelled packages content",
			content: `
# -*- yaml -*-
package: {
 naMe: [],
}
`,
			expected: w_error,
		},
		{
			name: "miss-type packages content",
			content: `
# -*- yaml -*-
package: {
 name: ["mypkg"],
}
`,
			expected: w_error,
		},
		{
			name: "miss-spelled configure content (environ)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 environ: {},
}
`,
			expected: w_error,
		},
		{
			name: "miss-type configure content (declare-tags)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 env: {},
 declare-tags: {},
}
`,
			expected: w_error,
		},
		{
			name: "miss-type configure content (apply-tags)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 env: {},
 declare-tags: [],
 apply-tags: {},
}
`,
			expected: w_error,
		},
		{
			name: "valid hscript",
			content: `
# -*- yaml -*-

## with comments
package: {
 ## this is the name of the package
 name: "mypkg",
 authors: ["me", "you", "everybody"],
 managers: ["somebody", "higher being"],

 deps: {
 },
}

## options declared to the command line
options: {
 tools: ["compiler_cxx", "find_python"],
}

configure: {
 tools: ["compiler_cxx", "find_python"],
 env: {
  MYPATH: "/some/path",
  PREPENDPATH: "/mypath/python:${PREPENDPATH}",
  APPENDPATH:  "${APPENDPATH}:/mypath/python",
 },
 declare-tags: [
  {x86_64-slc5-gcc48-opt: [x86_64, linux, slc5, 64b, gcc48, gcc, opt]},
  {x86_64-slc6-gcc48-opt: [x86_64, linux, slc5, 64b, gcc48, gcc, opt]},
  {my-graphics-tag: []},
 ],
 apply-tags: [
   x86_64-slc6-gcc48-opt,
   my-graphics-tag,
 ],

 hwaf-call: [
  "waftools/script-1.py",
  "waftools/script-2.py",
 ],
}

build: {
 hwaf-call: [
  "waftools/script-1.py",
  "waftools/script-2.py",
 ],

 cxx-hello-world: {
   features: "cxx cxxshlib",
   source:   "src/mypkgtool.cxx",
   target:   "hello-world",
 },

 cxx-hello-app: {
   features: [cxx, cxxprogram],
   source:   src/myapp.cxx,
   target:   hello-app,
   use:      [cxx-hello-world],
   cxxflags: [-O3],
   defines:  [MYDEFINE=1, NDEBUG],
   cflags:   -g,
   install_path: "${INSTALL_AREA}/share/bin",
 },
}
`,
			expected: nil,
		},
	} {
		test_with_hscript(t, tt.name, tt.content, tt.expected)
	}
}

// EOF
<commit_msg>test: add hwaf-call with hscript<commit_after>package main_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
)

func test_with_hscript(t *testing.T, t_name, content string, t_err error) {

	workdir, err := ioutil.TempDir("", "hwaf-test-")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer os.RemoveAll(workdir)

	err = os.Chdir(workdir)
	if err != nil {
		t.Fatalf(err.Error())
	}

	hwaf, err := newlogger("hwaf.log")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer hwaf.Close()

	for _, cmd := range [][]string{
		{"hwaf", "init", "-v=1", "."},
		{"hwaf", "setup", "-v=1"},
		{"hwaf", "pkg", "create", "-script=hscript", "-v=1", "mypkg"},
		{"hwaf", "pkg", "ls"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil {
			hwaf.Display()
			t.Fatalf("cmd %v failed: %v", cmd, err)
		}
	}

	mypkgdir := filepath.Join("src", "mypkg")

	// hscript.yml file
	ff, err := os.Create(filepath.Join(mypkgdir, "hscript.yml"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(content)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	err = os.MkdirAll(filepath.Join(mypkgdir, "waftools"), 0777)
	if err != nil {
		t.Fatalf(err.Error())
	}

	// waftools/script-1.py
	ff, err = os.Create(filepath.Join(mypkgdir, "waftools", "script-1.py"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(`
## -*- python -*-
def no_configure(ctx):
    pass

def no_build(ctx):
    pass

`)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	// waftools/script-2.py
	ff, err = os.Create(filepath.Join(mypkgdir, "waftools", "script-2.py"))
	if err != nil {
		t.Fatalf(err.Error())
	}
	_, err = ff.WriteString(`
## -*- python -*-
import waflib.Logs as msg

def configure(ctx):
    msg.info("tool script-2 loaded from configure")
    pass

def build(ctx):
    msg.info("tool script-1 loaded from configure")
    pass

`)
	if err != nil {
		t.Fatalf(err.Error())
	}

	ff.Sync()
	ff.Close()

	for _, cmd := range [][]string{
		{"hwaf", "configure"},
		//{"hwaf"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil && t_err == nil {
			hwaf.Display()
			t.Fatalf("in test [%s] cmd %v failed: %v", t_name, cmd, err)
		}
	}
}

func TestHwafHscriptSections(t *testing.T) {

	//var no_error error = nil
	var w_error error = fmt.Errorf("error expected")

	for _, tt := range []struct {
		name     string
		content  string
		expected error
	}{
		{
			name: "empty hscript",
			content: `
# -*- yaml -*-

`,
			expected: w_error,
		},
		{
			name: "empty content hscript",
			content: `
# -*- yaml -*-
package: {}
options: {}
configure: {}
build: {}
`,
			expected: w_error,
		},
		{
			name: "valid empty content hscript",
			content: `
# -*- yaml -*-
package: {name: "mypkg"}
options: {}
configure: {}
build: {}
`,
			expected: nil,
		},
		{
			name: "mispelled packages",
			content: `
# -*- yaml -*-
packaGes: {
}
`,
			expected: w_error,
		},
		{
			name: "missing packages content",
			content: `
# -*- yaml -*-
package: {
}
`,
			expected: w_error,
		},
		{
			name: "misspelled packages content",
			content: `
# -*- yaml -*-
package: {
 naMe: [],
}
`,
			expected: w_error,
		},
		{
			name: "miss-type packages content",
			content: `
# -*- yaml -*-
package: {
 name: ["mypkg"],
}
`,
			expected: w_error,
		},
		{
			name: "miss-spelled configure content (environ)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 environ: {},
}
`,
			expected: w_error,
		},
		{
			name: "miss-type configure content (declare-tags)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 env: {},
 declare-tags: {},
}
`,
			expected: w_error,
		},
		{
			name: "miss-type configure content (apply-tags)",
			content: `
# -*- yaml -*-
package: {
 name: "mypkg",
 authors: "me",
 deps: {
 },
}

options: {}

configure: {
 tools: [],
 env: {},
 declare-tags: [],
 apply-tags: {},
}
`,
			expected: w_error,
		},
		{
			name: "valid hscript",
			content: `
# -*- yaml -*-

## with comments
package: {
 ## this is the name of the package
 name: "mypkg",
 authors: ["me", "you", "everybody"],
 managers: ["somebody", "higher being"],

 deps: {
 },
}

## options declared to the command line
options: {
 tools: ["compiler_cxx", "find_python"],
}

configure: {
 tools: ["compiler_cxx", "find_python"],
 env: {
  MYPATH: "/some/path",
  PREPENDPATH: "/mypath/python:${PREPENDPATH}",
  APPENDPATH:  "${APPENDPATH}:/mypath/python",
 },
 declare-tags: [
  {x86_64-slc5-gcc48-opt: [x86_64, linux, slc5, 64b, gcc48, gcc, opt]},
  {x86_64-slc6-gcc48-opt: [x86_64, linux, slc5, 64b, gcc48, gcc, opt]},
  {my-graphics-tag: []},
 ],
 apply-tags: [
   x86_64-slc6-gcc48-opt,
   my-graphics-tag,
 ],

 hwaf-call: [
  "waftools/script-1.py",
  "waftools/script-2.py",
 ],
}

build: {
 hwaf-call: [
  "waftools/script-1.py",
  "waftools/script-2.py",
 ],

 cxx-hello-world: {
   features: "cxx cxxshlib",
   source:   "src/mypkgtool.cxx",
   target:   "hello-world",
 },

 cxx-hello-app: {
   features: [cxx, cxxprogram],
   source:   src/myapp.cxx,
   target:   hello-app,
   use:      [cxx-hello-world],
   cxxflags: [-O3],
   defines:  [MYDEFINE=1, NDEBUG],
   cflags:   -g,
   install_path: "${INSTALL_AREA}/share/bin",
 },
}
`,
			expected: nil,
		},
	} {
		test_with_hscript(t, tt.name, tt.content, tt.expected)
	}
}

func TestHscriptHwafCall(t *testing.T) {

	workdir, err := ioutil.TempDir("", "hwaf-test-")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer os.RemoveAll(workdir)
	//fmt.Printf(">>> test: %s\n", workdir)

	err = os.Chdir(workdir)
	if err != nil {
		t.Fatalf(err.Error())
	}

	hwaf, err := newlogger("hwaf.log")
	if err != nil {
		t.Fatalf(err.Error())
	}
	defer hwaf.Close()

	const hscript_settings_tmpl = `
## -*- yaml -*-

package: {
  name: "settings",
  authors: ["my"],
}

configure: {
  tools: ["compiler_c", "compiler_cxx", "python"],
  env: {
    PYTHONPATH: "${INSTALL_AREA}/python:${PYTHONPATH}"
  },
  hwaf-call: [
    "my_feature.py",
  ],
}

build: {
  hwaf-call: [
    "my_feature.py",
  ],
}
`
	const myfeat_tmpl = `
# -*- python -*-

# stdlib imports
#import os
import os.path as osp
#import sys

# waf imports ---
import waflib.Utils
import waflib.Logs as msg
import waflib.Configure
import waflib.Build
import waflib.Task
from waflib.TaskGen import feature, before_method, after_method, extension, after

def configure(ctx):
    msg.info("configure: hello from feature my_feature")
    return

def build(ctx):
    msg.info("build: hello from feature my_feature")
    return

@extension('.foo')
def foo_hook(self, node):
    msg.info('foo_hook: node=%s' % node.abspath())
    return

def my_feature_foo(self, name, source, target, **kw):
    """A test task to copy input into output
    """
    kw['rule'] = '/bin/cp ${SRC} ${TGT}'
    kw['source'] = source
    kw['target'] = target
    kw['name'] = name
    o = self(**kw)

    msg.info("in: %s" % source)
    msg.info("out: %s" % target)

    self.install_files(
       '${INSTALL_AREA}/data',
       target,
       relative_trick = False,
    )
    return
waflib.Build.BuildContext.my_feature_foo = my_feature_foo
`

	const hscript_pkg1_tmpl = `
## -*- yaml -*-

package: {
   name: "pkg1",
   authors: ["me"],
   deps: {
     public: [
       "settings",
     ],
   }
}

configure: {
   tools: ["compiler_c", "compiler_cxx", "find_python"],
   env: {
      PYTHONPATH: "${INSTALL_AREA}/python:${PYTHONPATH}",
   },
}

build: {
   mytask: {
      features: "my_feature_foo",
      source: "data.foo",
      target: "data.out",
   },
}
`

	// build project
	for _, cmd := range [][]string{
		{"hwaf", "init", "-v=1", "."},
		{"hwaf", "setup", "-v=1"},
		{"hwaf", "pkg", "create", "-v=1", "settings"},
		{"hwaf", "pkg", "create", "-v=1", "pkg1"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil {
			hwaf.Display()
			t.Fatalf("cmd %v failed: %v", cmd, err)
		}
	}

	err = ioutil.WriteFile(
		"src/settings/hscript.yml",
		[]byte(hscript_settings_tmpl),
		0777,
	)
	if err != nil {
		hwaf.Display()
		t.Fatalf("error creating src/settings/hscript.yml: %v\n", err)
	}

	err = ioutil.WriteFile(
		"src/settings/my_feature.py",
		[]byte(myfeat_tmpl),
		0777,
	)
	if err != nil {
		hwaf.Display()
		t.Fatalf("error creating src/settings/my_feature.py: %v\n", err)
	}

	err = ioutil.WriteFile(
		"src/pkg1/hscript.yml",
		[]byte(hscript_pkg1_tmpl),
		0777,
	)
	if err != nil {
		hwaf.Display()
		t.Fatalf("error creating src/pkg1/hscript.yml: %v\n", err)
	}

	err = ioutil.WriteFile(
		"src/pkg1/data.foo",
		[]byte("## my data\n"),
		0444,
	)
	if err != nil {
		hwaf.Display()
		t.Fatalf("error creating src/pkg1/hscript.yml: %v\n", err)
	}

	for _, cmd := range [][]string{
		{"hwaf", "configure"},
		{"hwaf", "build", "install", "-vv"},
	} {
		err := hwaf.Run(cmd[0], cmd[1:]...)
		if err != nil {
			hwaf.Display()
			t.Fatalf("cmd %v failed: %v", cmd, err)
		}
	}

	path_exists := func(name string) bool {
		_, err := os.Stat(name)
		if err == nil {
			return true
		}
		if os.IsNotExist(err) {
			return false
		}
		return false
	}

	fname := "install-area/data/data.out"
	if !path_exists(fname) {
		hwaf.Display()
		t.Fatalf("no such file installed: %v", fname)
	}

	//hwaf.Display()
}

// EOF
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"runtime"
	"os/exec"
)

var cmdLogout = &Command{
	Usage: "logout",
	Short: "Log out from force.com",
	Long: `
  force logout -u=username

  Example:

    force logout -u=user@example.org
`,
}

func init() {
	cmdLogout.Run = runLogout
}

var (
	userName1 = cmdLogout.Flag.String("u", "", "Username for Soap Login")
)

func runLogout(cmd *Command, args []string) {
	if *userName1 == "" {
		fmt.Println("Missing required argument...")
		cmd.Flag.Usage()
	}
	Config.Delete("accounts", *userName1)
	if active, _ := Config.Load("current", "account"); active == *userName1 {
		Config.Delete("current", "account")
		SetActiveLoginDefault()
	}
	if runtime.GOOS == "windows" {
		cmd := exec.Command("title", account)
		cmd.Run()
	} else {
		title := fmt.Sprintf("\033];%s\007", "")
		fmt.Printf(title)
	}
}
<commit_msg>fix terminal title for logout<commit_after>package main

import (
	"fmt"
	"runtime"
	"os/exec"
)

var cmdLogout = &Command{
	Usage: "logout",
	Short: "Log out from force.com",
	Long: `
  force logout -u=username

  Example:

    force logout -u=user@example.org
`,
}

func init() {
	cmdLogout.Run = runLogout
}

var (
	userName1 = cmdLogout.Flag.String("u", "", "Username for Soap Login")
)

func runLogout(cmd *Command, args []string) {
	if *userName1 == "" {
		fmt.Println("Missing required argument...")
		cmd.Flag.Usage()
		return
	}
	Config.Delete("accounts", *userName1)
	if active, _ := Config.Load("current", "account"); active == *userName1 {
		Config.Delete("current", "account")
		SetActiveLoginDefault()
	}
	if runtime.GOOS == "windows" {
		cmd := exec.Command("title", account)
		cmd.Run()
	} else {
		title := fmt.Sprintf("\033];%s\007", "")
		fmt.Printf(title)
	}
}
<|endoftext|>


<commit_before>package dht

import (
	"context"
	"fmt"
	"strings"

	"github.com/libp2p/go-libp2p-core/peer"

	cid "github.com/ipfs/go-cid"
	logging "github.com/ipfs/go-log"
	pb "github.com/libp2p/go-libp2p-kad-dht/pb"
	kb "github.com/libp2p/go-libp2p-kbucket"
	notif "github.com/libp2p/go-libp2p-routing/notifications"
)

func tryFormatLoggableKey(k string) (string, error) {
	if len(k) == 0 {
		return "", fmt.Errorf("loggableKey is empty")
	}
	var proto, cstr string
	if k[0] == '/' {
		// it's a path (probably)
		protoEnd := strings.IndexByte(k[1:], '/')
		if protoEnd < 0 {
			return k, fmt.Errorf("loggableKey starts with '/' but is not a path: %x", k)
		}
		proto = k[1 : protoEnd+1]
		cstr = k[protoEnd+2:]
	} else {
		proto = "provider"
		cstr = k
	}

	c, err := cid.Cast([]byte(cstr))
	if err != nil {
		return "", fmt.Errorf("loggableKey could not cast key to a CID: %x %v", k, err)
	}
	return fmt.Sprintf("/%s/%s", proto, c.String()), nil
}

func loggableKey(k string) logging.LoggableMap {
	newKey, err := tryFormatLoggableKey(k)
	if err != nil {
		logger.Debug(err)
	} else {
		k = newKey
	}

	return logging.LoggableMap{
		"key": k,
	}
}

// Kademlia 'node lookup' operation. Returns a channel of the K closest peers
// to the given key
func (dht *IpfsDHT) GetClosestPeers(ctx context.Context, key string) (<-chan peer.ID, error) {
	e := logger.EventBegin(ctx, "getClosestPeers", loggableKey(key))
	tablepeers := dht.routingTable.NearestPeers(kb.ConvertKey(key), AlphaValue)
	if len(tablepeers) == 0 {
		return nil, kb.ErrLookupFailure
	}

	out := make(chan peer.ID, KValue)

	// since the query doesnt actually pass our context down
	// we have to hack this here. whyrusleeping isnt a huge fan of goprocess
	parent := ctx
	query := dht.newQuery(key, func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
		// For DHT query command
		notif.PublishQueryEvent(parent, &notif.QueryEvent{
			Type: notif.SendingQuery,
			ID:   p,
		})

		pmes, err := dht.findPeerSingle(ctx, p, peer.ID(key))
		if err != nil {
			logger.Debugf("error getting closer peers: %s", err)
			return nil, err
		}
		peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())

		// For DHT query command
		notif.PublishQueryEvent(parent, &notif.QueryEvent{
			Type:      notif.PeerResponse,
			ID:        p,
			Responses: peers,
		})

		return &dhtQueryResult{closerPeers: peers}, nil
	})

	go func() {
		defer close(out)
		defer e.Done()
		// run it!
		res, err := query.Run(ctx, tablepeers)
		if err != nil {
			logger.Debugf("closestPeers query run error: %s", err)
		}

		if res != nil && res.queriedSet != nil {
			sorted := kb.SortClosestPeers(res.queriedSet.Peers(), kb.ConvertKey(key))
			if len(sorted) > KValue {
				sorted = sorted[:KValue]
			}

			for _, p := range sorted {
				out <- p
			}
		}
	}()

	return out, nil
}
<commit_msg>Add timeout<commit_after>package dht

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/libp2p/go-libp2p-core/peer"

	cid "github.com/ipfs/go-cid"
	logging "github.com/ipfs/go-log"
	pb "github.com/libp2p/go-libp2p-kad-dht/pb"
	kb "github.com/libp2p/go-libp2p-kbucket"
	notif "github.com/libp2p/go-libp2p-routing/notifications"
)

func tryFormatLoggableKey(k string) (string, error) {
	if len(k) == 0 {
		return "", fmt.Errorf("loggableKey is empty")
	}
	var proto, cstr string
	if k[0] == '/' {
		// it's a path (probably)
		protoEnd := strings.IndexByte(k[1:], '/')
		if protoEnd < 0 {
			return k, fmt.Errorf("loggableKey starts with '/' but is not a path: %x", k)
		}
		proto = k[1 : protoEnd+1]
		cstr = k[protoEnd+2:]
	} else {
		proto = "provider"
		cstr = k
	}

	c, err := cid.Cast([]byte(cstr))
	if err != nil {
		return "", fmt.Errorf("loggableKey could not cast key to a CID: %x %v", k, err)
	}
	return fmt.Sprintf("/%s/%s", proto, c.String()), nil
}

func loggableKey(k string) logging.LoggableMap {
	newKey, err := tryFormatLoggableKey(k)
	if err != nil {
		logger.Debug(err)
	} else {
		k = newKey
	}

	return logging.LoggableMap{
		"key": k,
	}
}

// Kademlia 'node lookup' operation. Returns a channel of the K closest peers
// to the given key
func (dht *IpfsDHT) GetClosestPeers(ctx context.Context, key string) (<-chan peer.ID, error) {
	e := logger.EventBegin(ctx, "getClosestPeers", loggableKey(key))
	tablepeers := dht.routingTable.NearestPeers(kb.ConvertKey(key), AlphaValue)
	if len(tablepeers) == 0 {
		return nil, kb.ErrLookupFailure
	}

	out := make(chan peer.ID, KValue)

	// since the query doesnt actually pass our context down
	// we have to hack this here. whyrusleeping isnt a huge fan of goprocess
	parent := ctx
	query := dht.newQuery(key, func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
		// For DHT query command
		notif.PublishQueryEvent(parent, &notif.QueryEvent{
			Type: notif.SendingQuery,
			ID:   p,
		})

		pmes, err := dht.findPeerSingle(ctx, p, peer.ID(key))
		if err != nil {
			logger.Debugf("error getting closer peers: %s", err)
			return nil, err
		}
		peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())

		// For DHT query command
		notif.PublishQueryEvent(parent, &notif.QueryEvent{
			Type:      notif.PeerResponse,
			ID:        p,
			Responses: peers,
		})

		return &dhtQueryResult{closerPeers: peers}, nil
	})

	go func() {
		defer close(out)
		defer e.Done()
		timedCtx, cancel := context.WithTimeout(ctx, time.Minute)
		defer cancel()
		// run it!
		res, err := query.Run(timedCtx, tablepeers)
		if err != nil {
			logger.Debugf("closestPeers query run error: %s", err)
		}

		if res != nil && res.queriedSet != nil {
			sorted := kb.SortClosestPeers(res.queriedSet.Peers(), kb.ConvertKey(key))
			if len(sorted) > KValue {
				sorted = sorted[:KValue]
			}

			for _, p := range sorted {
				out <- p
			}
		}
	}()

	return out, nil
}
<|endoftext|>


<commit_before>package model

import (
	"fmt"
	"os"
	"path/filepath"
	"testing"

	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// ggzRoot a path to the ggz root
var ggzRoot string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGgzRoot string) {
	var err error
	ggzRoot = pathToGgzRoot
	fixturesDir := filepath.Join(pathToGgzRoot, "model", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}
	os.Exit(m.Run())
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GGZ_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(true)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<commit_msg>refactor: change variable.<commit_after>package model

import (
	"fmt"
	"os"
	"path/filepath"
	"testing"

	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// Root a path to the ggz root
var Root string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGgzRoot string) {
	var err error
	Root = pathToGgzRoot
	fixturesDir := filepath.Join(pathToGgzRoot, "model", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}
	os.Exit(m.Run())
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GGZ_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(true)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<|endoftext|>


<commit_before>package core

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/AWE/lib/clientGroupAcl"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/core/uuid"
	"github.com/MG-RAST/AWE/lib/user"
	"github.com/MG-RAST/golib/uniuri"
	"labix.org/v2/mgo/bson"
	"os"
	"regexp"
	"strconv"
	"time"
)

type ClientGroup struct {
	Id           string                        `bson:"id" json:"id"`
	IP_CIDR      string                        `bson:"ip_cidr" json:"ip_cidr"`
	Name         string                        `bson:"name" json:"name"`
	Token        string                        `bson:"token" json:"token"`
	Acl          clientGroupAcl.ClientGroupAcl `bson:"acl" json:"-"`
	CreatedOn    time.Time                     `bson:"created_on" json:"created_on"`
	Expiration   time.Time                     `bson:"expiration" json:"expiration"`
	LastModified time.Time                     `bson:"last_modified" json:"last_modified"`
}

var (
	CGNameRegex = regexp.MustCompile(`^[A-Za-z0-9\_-\.]+$`)
)

func CreateClientGroup(name string, u *user.User) (cg *ClientGroup, err error) {
	q := bson.M{"name": name}
	clientgroups := new(ClientGroups)
	if count, err := dbFindClientGroups(q, clientgroups); err != nil {
		return nil, err
	} else if count > 0 {
		return nil, errors.New("A clientgroup already exists with this name.")
	}

	if !CGNameRegex.Match([]byte(name)) {
		return nil, errors.New("Clientgroup name must contain only alphanumeric characters, underscore, dash or dot.")
	}

	t := time.Now()

	cg = new(ClientGroup)
	cg.Id = uuid.New()
	cg.IP_CIDR = "0.0.0.0/0"
	cg.Name = name
	cg.Expiration = t.AddDate(10, 0, 0)
	cg.Acl.SetOwner(u.Uuid)
	cg.Acl.Set(u.Uuid, clientGroupAcl.Rights{"read": true, "write": true, "delete": true, "execute": true})
	cg.CreatedOn = t
	cg.SetToken()

	if err = cg.Save(); err != nil {
		err = errors.New("error in cg.Save(), error=" + err.Error())
		return
	}

	return
}

func (cg *ClientGroup) SetToken() {
	var host string
	if hostname, err := os.Hostname(); err == nil {
		host = fmt.Sprintf("%s:%d", hostname, conf.API_PORT)
	}
	cg.Token = "name=" + cg.Name + "|id=" + cg.Id + "|exp=" + strconv.FormatInt(cg.Expiration.Unix(), 10) + "|server=" + host + "|sig=" + uniuri.NewLen(256)
	return
}

func (cg *ClientGroup) Save() (err error) {
	cg.LastModified = time.Now()
	err = dbUpsert(cg)
	return
}
<commit_msg>debug<commit_after>package core

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/AWE/lib/clientGroupAcl"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/core/uuid"
	"github.com/MG-RAST/AWE/lib/user"
	"github.com/MG-RAST/golib/uniuri"
	"labix.org/v2/mgo/bson"
	"os"
	"regexp"
	"strconv"
	"time"
)

type ClientGroup struct {
	Id           string                        `bson:"id" json:"id"`
	IP_CIDR      string                        `bson:"ip_cidr" json:"ip_cidr"`
	Name         string                        `bson:"name" json:"name"`
	Token        string                        `bson:"token" json:"token"`
	Acl          clientGroupAcl.ClientGroupAcl `bson:"acl" json:"-"`
	CreatedOn    time.Time                     `bson:"created_on" json:"created_on"`
	Expiration   time.Time                     `bson:"expiration" json:"expiration"`
	LastModified time.Time                     `bson:"last_modified" json:"last_modified"`
}

var (
	CGNameRegex = regexp.MustCompile(`^[A-Za-z0-9\_\-\.]+$`)
)

func CreateClientGroup(name string, u *user.User) (cg *ClientGroup, err error) {
	q := bson.M{"name": name}
	clientgroups := new(ClientGroups)
	if count, err := dbFindClientGroups(q, clientgroups); err != nil {
		return nil, err
	} else if count > 0 {
		return nil, errors.New("A clientgroup already exists with this name.")
	}

	if !CGNameRegex.Match([]byte(name)) {
		return nil, errors.New("Clientgroup name must contain only alphanumeric characters, underscore, dash or dot.")
	}

	t := time.Now()

	cg = new(ClientGroup)
	cg.Id = uuid.New()
	cg.IP_CIDR = "0.0.0.0/0"
	cg.Name = name
	cg.Expiration = t.AddDate(10, 0, 0)
	cg.Acl.SetOwner(u.Uuid)
	cg.Acl.Set(u.Uuid, clientGroupAcl.Rights{"read": true, "write": true, "delete": true, "execute": true})
	cg.CreatedOn = t
	cg.SetToken()

	if err = cg.Save(); err != nil {
		err = errors.New("error in cg.Save(), error=" + err.Error())
		return
	}

	return
}

func (cg *ClientGroup) SetToken() {
	var host string
	if hostname, err := os.Hostname(); err == nil {
		host = fmt.Sprintf("%s:%d", hostname, conf.API_PORT)
	}
	cg.Token = "name=" + cg.Name + "|id=" + cg.Id + "|exp=" + strconv.FormatInt(cg.Expiration.Unix(), 10) + "|server=" + host + "|sig=" + uniuri.NewLen(256)
	return
}

func (cg *ClientGroup) Save() (err error) {
	cg.LastModified = time.Now()
	err = dbUpsert(cg)
	return
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"log"
	"strings"
	"sync"

	"github.com/fsouza/go-dockerclient"
)

type AttachManager struct {
	sync.Mutex
	attached map[string]*LogPump
	channels map[chan *AttachEvent]struct{}
	client   *docker.Client
}

func NewAttachManager(client *docker.Client) *AttachManager {
	m := &AttachManager{
		attached: make(map[string]*LogPump),
		channels: make(map[chan *AttachEvent]struct{}),
		client:   client,
	}
	containers, err := client.ListContainers(docker.ListContainersOptions{})
	assert(err, "attacher")
	for _, listing := range containers {
		m.attach(listing.ID[:12])
	}
	go func() {
		events := make(chan *docker.APIEvents)
		// TODO: resolve this workaround. https://github.com/fsouza/go-dockerclient/issues/101
		assert(client.AddEventListener(events), "attacher")
		assert(client.RemoveEventListener(events), "attacher")
		assert(client.AddEventListener(events), "attacher")
		for msg := range events {
			debug("event:", msg.ID[:12], msg.Status)
			if msg.Status == "start" {
				go m.attach(msg.ID[:12])
			}
		}
		log.Fatal("ruh roh") // todo: loop?
	}()
	return m
}

func (m *AttachManager) attach(id string) {
	container, err := m.client.InspectContainer(id)
	assert(err, "attacher")
	name := container.Name[1:]
	success := make(chan struct{})
	failure := make(chan error)
	outrd, outwr := io.Pipe()
	errrd, errwr := io.Pipe()
	go func() {
		err := m.client.AttachToContainer(docker.AttachToContainerOptions{
			Container:    id,
			OutputStream: outwr,
			ErrorStream:  errwr,
			Stdin:        false,
			Stdout:       true,
			Stderr:       true,
			Stream:       true,
			Success:      success,
		})
		outwr.Close()
		errwr.Close()
		debug("attach:", id, "finished")
		if err != nil {
			close(success)
			failure <- err
		}
		m.send(&AttachEvent{Type: "detach", ID: id, Name: name})
		m.Lock()
		delete(m.attached, id)
		m.Unlock()
	}()
	_, ok := <-success
	if ok {
		m.Lock()
		m.attached[id] = NewLogPump(outrd, errrd, id, name)
		m.Unlock()
		success <- struct{}{}
		m.send(&AttachEvent{ID: id, Name: name, Type: "attach"})
		debug("attach:", id, "success")
		return
	}
	debug("attach:", id, "failure:", <-failure)
}

func (m *AttachManager) send(event *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	for ch, _ := range m.channels {
		// TODO: log err after timeout and continue
		ch <- event
	}
}

func (m *AttachManager) addListener(ch chan *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	m.channels[ch] = struct{}{}
	go func() {
		for id, pump := range m.attached {
			ch <- &AttachEvent{ID: id, Name: pump.Name, Type: "attach"}
		}
	}()
}

func (m *AttachManager) removeListener(ch chan *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	delete(m.channels, ch)
}

func (m *AttachManager) Get(id string) *LogPump {
	m.Lock()
	defer m.Unlock()
	return m.attached[id]
}

func (m *AttachManager) Listen(source *Source, logstream chan *Log, closer <-chan bool) {
	if source == nil {
		source = new(Source)
	}
	events := make(chan *AttachEvent)
	m.addListener(events)
	defer m.removeListener(events)
	for {
		select {
		case event := <-events:
			if event.Type == "attach" && (source.All() ||
				(source.ID != "" && strings.HasPrefix(event.ID, source.ID)) ||
				(source.Name != "" && event.Name == source.Name) ||
				(source.Filter != "" && strings.Contains(event.Name, source.Filter))) {
				pump := m.Get(event.ID)
				pump.AddListener(logstream)
				defer func() {
					if pump != nil {
						pump.RemoveListener(logstream)
					}
				}()
			} else if source.ID != "" && event.Type == "detach" &&
				strings.HasPrefix(event.ID, source.ID) {
				return
			}
		case <-closer:
			return
		}
	}
}

type LogPump struct {
	sync.Mutex
	ID       string
	Name     string
	channels map[chan *Log]struct{}
}

func NewLogPump(stdout, stderr io.Reader, id, name string) *LogPump {
	obj := &LogPump{
		ID:       id,
		Name:     name,
		channels: make(map[chan *Log]struct{}),
	}
	pump := func(typ string, source io.Reader) {
		buf := bufio.NewReader(source)
		for {
			data, err := buf.ReadBytes('\n')
			if err != nil {
				if err != io.EOF {
					debug("pump:", id, typ+":", err)
				}
				return
			}
			obj.send(&Log{
				Data: strings.TrimSuffix(string(data), "\n"),
				ID:   id,
				Name: name,
				Type: typ,
			})
		}
	}
	go pump("stdout", stdout)
	go pump("stderr", stderr)
	return obj
}

func (o *LogPump) send(log *Log) {
	o.Lock()
	defer o.Unlock()
	for ch, _ := range o.channels {
		// TODO: log err after timeout and continue
		ch <- log
	}
}

func (o *LogPump) AddListener(ch chan *Log) {
	o.Lock()
	defer o.Unlock()
	o.channels[ch] = struct{}{}
}

func (o *LogPump) RemoveListener(ch chan *Log) {
	o.Lock()
	defer o.Unlock()
	delete(o.channels, ch)
}
<commit_msg>remove workaround for https://github.com/fsouza/go-dockerclient/issues/101<commit_after>package main

import (
	"bufio"
	"io"
	"log"
	"strings"
	"sync"

	"github.com/fsouza/go-dockerclient"
)

type AttachManager struct {
	sync.Mutex
	attached map[string]*LogPump
	channels map[chan *AttachEvent]struct{}
	client   *docker.Client
}

func NewAttachManager(client *docker.Client) *AttachManager {
	m := &AttachManager{
		attached: make(map[string]*LogPump),
		channels: make(map[chan *AttachEvent]struct{}),
		client:   client,
	}
	containers, err := client.ListContainers(docker.ListContainersOptions{})
	assert(err, "attacher")
	for _, listing := range containers {
		m.attach(listing.ID[:12])
	}
	go func() {
		events := make(chan *docker.APIEvents)
		assert(client.AddEventListener(events), "attacher")
		for msg := range events {
			debug("event:", msg.ID[:12], msg.Status)
			if msg.Status == "start" {
				go m.attach(msg.ID[:12])
			}
		}
		log.Fatal("ruh roh") // todo: loop?
	}()
	return m
}

func (m *AttachManager) attach(id string) {
	container, err := m.client.InspectContainer(id)
	assert(err, "attacher")
	name := container.Name[1:]
	success := make(chan struct{})
	failure := make(chan error)
	outrd, outwr := io.Pipe()
	errrd, errwr := io.Pipe()
	go func() {
		err := m.client.AttachToContainer(docker.AttachToContainerOptions{
			Container:    id,
			OutputStream: outwr,
			ErrorStream:  errwr,
			Stdin:        false,
			Stdout:       true,
			Stderr:       true,
			Stream:       true,
			Success:      success,
		})
		outwr.Close()
		errwr.Close()
		debug("attach:", id, "finished")
		if err != nil {
			close(success)
			failure <- err
		}
		m.send(&AttachEvent{Type: "detach", ID: id, Name: name})
		m.Lock()
		delete(m.attached, id)
		m.Unlock()
	}()
	_, ok := <-success
	if ok {
		m.Lock()
		m.attached[id] = NewLogPump(outrd, errrd, id, name)
		m.Unlock()
		success <- struct{}{}
		m.send(&AttachEvent{ID: id, Name: name, Type: "attach"})
		debug("attach:", id, "success")
		return
	}
	debug("attach:", id, "failure:", <-failure)
}

func (m *AttachManager) send(event *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	for ch, _ := range m.channels {
		// TODO: log err after timeout and continue
		ch <- event
	}
}

func (m *AttachManager) addListener(ch chan *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	m.channels[ch] = struct{}{}
	go func() {
		for id, pump := range m.attached {
			ch <- &AttachEvent{ID: id, Name: pump.Name, Type: "attach"}
		}
	}()
}

func (m *AttachManager) removeListener(ch chan *AttachEvent) {
	m.Lock()
	defer m.Unlock()
	delete(m.channels, ch)
}

func (m *AttachManager) Get(id string) *LogPump {
	m.Lock()
	defer m.Unlock()
	return m.attached[id]
}

func (m *AttachManager) Listen(source *Source, logstream chan *Log, closer <-chan bool) {
	if source == nil {
		source = new(Source)
	}
	events := make(chan *AttachEvent)
	m.addListener(events)
	defer m.removeListener(events)
	for {
		select {
		case event := <-events:
			if event.Type == "attach" && (source.All() ||
				(source.ID != "" && strings.HasPrefix(event.ID, source.ID)) ||
				(source.Name != "" && event.Name == source.Name) ||
				(source.Filter != "" && strings.Contains(event.Name, source.Filter))) {
				pump := m.Get(event.ID)
				pump.AddListener(logstream)
				defer func() {
					if pump != nil {
						pump.RemoveListener(logstream)
					}
				}()
			} else if source.ID != "" && event.Type == "detach" &&
				strings.HasPrefix(event.ID, source.ID) {
				return
			}
		case <-closer:
			return
		}
	}
}

type LogPump struct {
	sync.Mutex
	ID       string
	Name     string
	channels map[chan *Log]struct{}
}

func NewLogPump(stdout, stderr io.Reader, id, name string) *LogPump {
	obj := &LogPump{
		ID:       id,
		Name:     name,
		channels: make(map[chan *Log]struct{}),
	}
	pump := func(typ string, source io.Reader) {
		buf := bufio.NewReader(source)
		for {
			data, err := buf.ReadBytes('\n')
			if err != nil {
				if err != io.EOF {
					debug("pump:", id, typ+":", err)
				}
				return
			}
			obj.send(&Log{
				Data: strings.TrimSuffix(string(data), "\n"),
				ID:   id,
				Name: name,
				Type: typ,
			})
		}
	}
	go pump("stdout", stdout)
	go pump("stderr", stderr)
	return obj
}

func (o *LogPump) send(log *Log) {
	o.Lock()
	defer o.Unlock()
	for ch, _ := range o.channels {
		// TODO: log err after timeout and continue
		ch <- log
	}
}

func (o *LogPump) AddListener(ch chan *Log) {
	o.Lock()
	defer o.Unlock()
	o.channels[ch] = struct{}{}
}

func (o *LogPump) RemoveListener(ch chan *Log) {
	o.Lock()
	defer o.Unlock()
	delete(o.channels, ch)
}
<|endoftext|>


<commit_before>// Copyright 2016 The Serviced 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 auth

import (
	"crypto/rsa"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	// Verify JWTIdentity implements the Identity interface
	_ Identity   = &jwtIdentity{}
	_ jwt.Claims = &jwtIdentity{}
)

// jwtIdentity is an implementation of the Identity interface based on a JSON
// web token.
type jwtIdentity struct {
	Host        string `json:"hid,omitempty"`
	Pool        string `json:"pid,omitempty"`
	ExpiresAt   int64  `json:"exp,omitempty"`
	IssuedAt    int64  `json:"iat,omitempty"`
	AdminAccess bool   `json:"adm,omitempty"`
	DFSAccess   bool   `json:"dfs,omitempty"`
	PubKey      string `json:"key,omitempty"`
}

// ParseJWTIdentity parses a JSON Web Token string, verifying that it was signed by the master.
func ParseJWTIdentity(token string) (Identity, error) {
	claims := &jwtIdentity{}
	parsed, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
		// Validate the algorithm matches the key
		if _, ok := token.Method.(*jwt.SigningMethodRSAPSS); !ok {
			return nil, ErrInvalidSigningMethod
		}
		key, err := GetMasterPublicKey()
		if err != nil {
			return nil, err
		}
		if _, ok := key.(*rsa.PublicKey); !ok {
			return nil, ErrNotRSAPublicKey
		}
		return key, nil
	})
	if err != nil {
		if verr, ok := err.(*jwt.ValidationError); ok {
			if verr.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, ErrIdentityTokenExpired
			}
			if verr.Errors&(jwt.ValidationErrorNotValidYet|jwt.ValidationErrorIssuedAt) != 0 {
				return nil, ErrIdentityTokenNotValidYet
			}
			if verr.Errors&(jwt.ValidationErrorSignatureInvalid|jwt.ValidationErrorUnverifiable) != 0 {
				return nil, ErrIdentityTokenBadSig
			}
			return nil, verr.Inner
		}
		return nil, err
	}
	if claims, ok := parsed.Claims.(*jwtIdentity); ok && parsed.Valid {
		return claims, nil
	}
	return nil, ErrIdentityTokenInvalid
}

// CreateJWTIdentity returns a signed string
func CreateJWTIdentity(hostID, poolID string, admin, dfs bool, pubKeyPEM []byte, expiration time.Duration) (string, error) {
	now := jwt.TimeFunc().UTC()
	claims := &jwtIdentity{
		Host:        hostID,
		Pool:        poolID,
		ExpiresAt:   now.Add(expiration).Unix(),
		IssuedAt:    now.Unix(),
		AdminAccess: admin,
		DFSAccess:   dfs,
		PubKey:      string(pubKeyPEM),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodPS256, claims)
	masterPrivKey, err := getMasterPrivateKey()
	if err != nil {
		return "", err
	}
	return token.SignedString(masterPrivKey)
}

func (id *jwtIdentity) Valid() error {

	if id.Expired() {
		return ErrIdentityTokenExpired
	}

	now := jwt.TimeFunc().UTC().Unix()
	if now < id.IssuedAt {
		return ErrIdentityTokenNotValidYet
	}

	return nil
}

func (id *jwtIdentity) Expired() bool {
	now := jwt.TimeFunc().UTC().Unix()
	return now >= id.ExpiresAt
}

func (id *jwtIdentity) HostID() string {
	return id.Host

}

func (id *jwtIdentity) PoolID() string {
	return id.Pool

}

func (id *jwtIdentity) HasAdminAccess() bool {
	return id.AdminAccess
}

func (id *jwtIdentity) HasDFSAccess() bool {
	return id.DFSAccess
}

func (id *jwtIdentity) Verifier() (Verifier, error) {
	return RSAVerifierFromPEM([]byte(id.PubKey))
}
<commit_msg>Remove unnecessary checking<commit_after>// Copyright 2016 The Serviced 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 auth

import (
	"time"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	// Verify JWTIdentity implements the Identity interface
	_ Identity   = &jwtIdentity{}
	_ jwt.Claims = &jwtIdentity{}
)

// jwtIdentity is an implementation of the Identity interface based on a JSON
// web token.
type jwtIdentity struct {
	Host        string `json:"hid,omitempty"`
	Pool        string `json:"pid,omitempty"`
	ExpiresAt   int64  `json:"exp,omitempty"`
	IssuedAt    int64  `json:"iat,omitempty"`
	AdminAccess bool   `json:"adm,omitempty"`
	DFSAccess   bool   `json:"dfs,omitempty"`
	PubKey      string `json:"key,omitempty"`
}

// ParseJWTIdentity parses a JSON Web Token string, verifying that it was signed by the master.
func ParseJWTIdentity(token string) (Identity, error) {
	claims := &jwtIdentity{}
	parsed, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
		// Validate the algorithm matches the key
		if _, ok := token.Method.(*jwt.SigningMethodRSAPSS); !ok {
			return nil, ErrInvalidSigningMethod
		}
		return GetMasterPublicKey()
	})
	if err != nil {
		if verr, ok := err.(*jwt.ValidationError); ok {
			if verr.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, ErrIdentityTokenExpired
			}
			if verr.Errors&(jwt.ValidationErrorNotValidYet|jwt.ValidationErrorIssuedAt) != 0 {
				return nil, ErrIdentityTokenNotValidYet
			}
			if verr.Errors&(jwt.ValidationErrorSignatureInvalid|jwt.ValidationErrorUnverifiable) != 0 {
				return nil, ErrIdentityTokenBadSig
			}
			return nil, verr.Inner
		}
		return nil, err
	}
	if claims, ok := parsed.Claims.(*jwtIdentity); ok && parsed.Valid {
		return claims, nil
	}
	return nil, ErrIdentityTokenInvalid
}

// CreateJWTIdentity returns a signed string
func CreateJWTIdentity(hostID, poolID string, admin, dfs bool, pubKeyPEM []byte, expiration time.Duration) (string, error) {
	now := jwt.TimeFunc().UTC()
	claims := &jwtIdentity{
		Host:        hostID,
		Pool:        poolID,
		ExpiresAt:   now.Add(expiration).Unix(),
		IssuedAt:    now.Unix(),
		AdminAccess: admin,
		DFSAccess:   dfs,
		PubKey:      string(pubKeyPEM),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodPS256, claims)
	masterPrivKey, err := getMasterPrivateKey()
	if err != nil {
		return "", err
	}
	return token.SignedString(masterPrivKey)
}

func (id *jwtIdentity) Valid() error {

	if id.Expired() {
		return ErrIdentityTokenExpired
	}

	now := jwt.TimeFunc().UTC().Unix()
	if now < id.IssuedAt {
		return ErrIdentityTokenNotValidYet
	}

	return nil
}

func (id *jwtIdentity) Expired() bool {
	now := jwt.TimeFunc().UTC().Unix()
	return now >= id.ExpiresAt
}

func (id *jwtIdentity) HostID() string {
	return id.Host

}

func (id *jwtIdentity) PoolID() string {
	return id.Pool

}

func (id *jwtIdentity) HasAdminAccess() bool {
	return id.AdminAccess
}

func (id *jwtIdentity) HasDFSAccess() bool {
	return id.DFSAccess
}

func (id *jwtIdentity) Verifier() (Verifier, error) {
	return RSAVerifierFromPEM([]byte(id.PubKey))
}
<|endoftext|>