<commit_before>package clock

import (
	"sort"
	"sync"
	"time"
)

// Clock represents an interface to the functions in the standard library time
// package. Two implementations are available in the clock package. The first
// is a real-time clock which simply wraps the time package's functions. The
// second is a mock clock which will only make forward progress when
// programmatically adjusted.
type Clock interface {
	After(d time.Duration) <-chan time.Time
	AfterFunc(d time.Duration, f func()) *Timer
	Now() time.Time
	Sleep(d time.Duration)
	Tick(d time.Duration) <-chan time.Time
	Ticker(d time.Duration) *Ticker
	Timer(d time.Duration) *Timer
}

// New returns an instance of a real-time clock.
func New() Clock {
	return &clock{}
}

// clock implements a real-time clock by simply wrapping the time package functions.
type clock struct{}

func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) }

func (c *clock) AfterFunc(d time.Duration, f func()) *Timer {
	return &Timer{timer: time.AfterFunc(d, f)}
}

func (c *clock) Now() time.Time { return time.Now() }

func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }

func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) }

func (c *clock) Ticker(d time.Duration) *Ticker {
	t := time.NewTicker(d)
	return &Ticker{C: t.C, ticker: t}
}

func (c *clock) Timer(d time.Duration) *Timer {
	t := time.NewTimer(d)
	return &Timer{C: t.C, timer: t}
}

// Mock represents a mock clock that only moves forward programmically.
// It can be preferable to a real-time clock when testing time-based functionality.
type Mock struct {
	mu     sync.Mutex
	now    time.Time   // current time
	timers clockTimers // tickers & timers
}

// NewMock returns an instance of a mock clock.
// The current time of the mock clock on initialization is the Unix epoch.
func NewMock() *Mock {
	return &Mock{now: time.Unix(0, 0)}
}

// Add moves the current time of the mock clock forward by the duration.
// This should only be called from a single goroutine at a time.
func (m *Mock) Add(d time.Duration) {
	// Calculate the final current time.
	t := m.now.Add(d)

	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// Sets the current time of the mock clock to a specific one.
// This should only be called from a single goroutine at a time.
func (m *Mock) Set(t time.Time) {
	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// runNextTimer executes the next timer in chronological order and moves the
// current time to the timer's next tick time. The next time is not executed if
// it's next time if after the max time. Returns true if a timer is executed.
func (m *Mock) runNextTimer(max time.Time) bool {
	m.mu.Lock()

	// Sort timers by time.
	sort.Sort(m.timers)

	// If we have no more timers then exit.
	if len(m.timers) == 0 {
		m.mu.Unlock()
		return false
	}

	// Retrieve next timer. Exit if next tick is after new time.
	t := m.timers[0]
	if t.Next().After(max) {
		m.mu.Unlock()
		return false
	}

	// Move "now" forward and unlock clock.
	m.now = t.Next()
	m.mu.Unlock()

	// Execute timer.
	t.Tick(m.now)
	return true
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *Mock) After(d time.Duration) <-chan time.Time {
	return m.Timer(d).C
}

// AfterFunc waits for the duration to elapse and then executes a function.
// A Timer is returned that can be stopped.
func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer {
	t := m.Timer(d)
	t.C = nil
	t.fn = f
	return t
}

// Now returns the current wall time on the mock clock.
func (m *Mock) Now() time.Time {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.now
}

// Sleep pauses the goroutine for the given duration on the mock clock.
// The clock must be moved forward in a separate goroutine.
func (m *Mock) Sleep(d time.Duration) {
	<-m.After(d)
}

// Tick is a convenience function for Ticker().
// It will return a ticker channel that cannot be stopped.
func (m *Mock) Tick(d time.Duration) <-chan time.Time {
	return m.Ticker(d).C
}

// Ticker creates a new instance of Ticker.
func (m *Mock) Ticker(d time.Duration) *Ticker {
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time, 1)
	t := &Ticker{
		C:    ch,
		c:    ch,
		mock: m,
		d:    d,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTicker)(t))
	return t
}

// Timer creates a new instance of Timer.
func (m *Mock) Timer(d time.Duration) *Timer {
	ch := make(chan time.Time, 1)
	t := &Timer{
		C:    ch,
		c:    ch,
		mock: m,
		next: m.Now().Add(d),
	}
	m.addTimer((*internalTimer)(t))
	return t
}

func (m *Mock) addTimer(t *internalTimer) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.timers = append(m.timers, t)
	sort.Sort(m.timers)
}

func (m *Mock) removeClockTimer(t clockTimer) bool {
	m.mu.Lock()
	defer m.mu.Unlock()
	ret := false
	for i, timer := range m.timers {
		if timer == t {
			ret = true
			copy(m.timers[i:], m.timers[i+1:])
			m.timers[len(m.timers)-1] = nil
			m.timers = m.timers[:len(m.timers)-1]
			break
		}
	}
	sort.Sort(m.timers)
	return ret
}

// clockTimer represents an object with an associated start time.
type clockTimer interface {
	Next() time.Time
	Tick(time.Time)
}

// clockTimers represents a list of sortable timers.
type clockTimers []clockTimer

func (a clockTimers) Len() int           { return len(a) }
func (a clockTimers) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) }

// Timer represents a single event.
// The current time will be sent on C, unless the timer was created by AfterFunc.
type Timer struct {
	C     <-chan time.Time
	c     chan time.Time
	timer *time.Timer // realtime impl, if set
	next  time.Time   // next tick time
	mock  *Mock       // mock clock, if set
	fn    func()      // AfterFunc function, if set
}

// Stop turns off the timer.
func (t *Timer) Stop() {
	if t.timer != nil {
		t.timer.Stop()
	} else {
		t.mock.removeClockTimer((*internalTimer)(t))
	}
}

// Reset changes the timer to expire after duration d. It returns true if the
// timer had been active, false if the timer had expired or been stopped.
func (t *Timer) Reset(d time.Duration) bool {
	if t.timer != nil {
		return t.timer.Reset(d)
	} else {
		ret := t.mock.removeClockTimer((*internalTimer)(t))
		t.next = t.mock.Now().Add(d)
		t.mock.addTimer((*internalTimer)(t))
		return ret
	}
}

type internalTimer Timer

func (t *internalTimer) Next() time.Time { return t.next }
func (t *internalTimer) Tick(now time.Time) {
	if t.fn != nil {
		t.fn()
	} else {
		t.c <- now
	}
	t.mock.removeClockTimer((*internalTimer)(t))
	gosched()
}

// Ticker holds a channel that receives "ticks" at regular intervals.
type Ticker struct {
	C      <-chan time.Time
	c      chan time.Time
	ticker *time.Ticker  // realtime impl, if set
	next   time.Time     // next tick time
	mock   *Mock         // mock clock, if set
	d      time.Duration // time between ticks
}

// Stop turns off the ticker.
func (t *Ticker) Stop() {
	if t.ticker != nil {
		t.ticker.Stop()
	} else {
		t.mock.removeClockTimer((*internalTicker)(t))
	}
}

type internalTicker Ticker

func (t *internalTicker) Next() time.Time { return t.next }
func (t *internalTicker) Tick(now time.Time) {
	select {
	case t.c <- now:
	default:
	}
	t.next = now.Add(t.d)
	gosched()
}

// Sleep momentarily so that other goroutines can process.
func gosched() { time.Sleep(1 * time.Millisecond) }
<commit_msg>stop returns bool<commit_after>package clock

import (
	"sort"
	"sync"
	"time"
)

// Clock represents an interface to the functions in the standard library time
// package. Two implementations are available in the clock package. The first
// is a real-time clock which simply wraps the time package's functions. The
// second is a mock clock which will only make forward progress when
// programmatically adjusted.
type Clock interface {
	After(d time.Duration) <-chan time.Time
	AfterFunc(d time.Duration, f func()) *Timer
	Now() time.Time
	Sleep(d time.Duration)
	Tick(d time.Duration) <-chan time.Time
	Ticker(d time.Duration) *Ticker
	Timer(d time.Duration) *Timer
}

// New returns an instance of a real-time clock.
func New() Clock {
	return &clock{}
}

// clock implements a real-time clock by simply wrapping the time package functions.
type clock struct{}

func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) }

func (c *clock) AfterFunc(d time.Duration, f func()) *Timer {
	return &Timer{timer: time.AfterFunc(d, f)}
}

func (c *clock) Now() time.Time { return time.Now() }

func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }

func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) }

func (c *clock) Ticker(d time.Duration) *Ticker {
	t := time.NewTicker(d)
	return &Ticker{C: t.C, ticker: t}
}

func (c *clock) Timer(d time.Duration) *Timer {
	t := time.NewTimer(d)
	return &Timer{C: t.C, timer: t}
}

// Mock represents a mock clock that only moves forward programmically.
// It can be preferable to a real-time clock when testing time-based functionality.
type Mock struct {
	mu     sync.Mutex
	now    time.Time   // current time
	timers clockTimers // tickers & timers
}

// NewMock returns an instance of a mock clock.
// The current time of the mock clock on initialization is the Unix epoch.
func NewMock() *Mock {
	return &Mock{now: time.Unix(0, 0)}
}

// Add moves the current time of the mock clock forward by the duration.
// This should only be called from a single goroutine at a time.
func (m *Mock) Add(d time.Duration) {
	// Calculate the final current time.
	t := m.now.Add(d)

	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// Sets the current time of the mock clock to a specific one.
// This should only be called from a single goroutine at a time.
func (m *Mock) Set(t time.Time) {
	// Continue to execute timers until there are no more before the new time.
	for {
		if !m.runNextTimer(t) {
			break
		}
	}

	// Ensure that we end with the new time.
	m.mu.Lock()
	m.now = t
	m.mu.Unlock()

	// Give a small buffer to make sure the other goroutines get handled.
	gosched()
}

// runNextTimer executes the next timer in chronological order and moves the
// current time to the timer's next tick time. The next time is not executed if
// it's next time if after the max time. Returns true if a timer is executed.
func (m *Mock) runNextTimer(max time.Time) bool {
	m.mu.Lock()

	// Sort timers by time.
	sort.Sort(m.timers)

	// If we have no more timers then exit.
	if len(m.timers) == 0 {
		m.mu.Unlock()
		return false
	}

	// Retrieve next timer. Exit if next tick is after new time.
	t := m.timers[0]
	if t.Next().After(max) {
		m.mu.Unlock()
		return false
	}

	// Move "now" forward and unlock clock.
	m.now = t.Next()
	m.mu.Unlock()

	// Execute timer.
	t.Tick(m.now)
	return true
}

// After waits for the duration to elapse and then sends the current time on the returned channel.
func (m *Mock) After(d time.Duration) <-chan time.Time {
	return m.Timer(d).C
}

// AfterFunc waits for the duration to elapse and then executes a function.
// A Timer is returned that can be stopped.
func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer {
	t := m.Timer(d)
	t.C = nil
	t.fn = f
	return t
}

// Now returns the current wall time on the mock clock.
func (m *Mock) Now() time.Time {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.now
}

// Sleep pauses the goroutine for the given duration on the mock clock.
// The clock must be moved forward in a separate goroutine.
func (m *Mock) Sleep(d time.Duration) {
	<-m.After(d)
}

// Tick is a convenience function for Ticker().
// It will return a ticker channel that cannot be stopped.
func (m *Mock) Tick(d time.Duration) <-chan time.Time {
	return m.Ticker(d).C
}

// Ticker creates a new instance of Ticker.
func (m *Mock) Ticker(d time.Duration) *Ticker {
	m.mu.Lock()
	defer m.mu.Unlock()
	ch := make(chan time.Time, 1)
	t := &Ticker{
		C:    ch,
		c:    ch,
		mock: m,
		d:    d,
		next: m.now.Add(d),
	}
	m.timers = append(m.timers, (*internalTicker)(t))
	return t
}

// Timer creates a new instance of Timer.
func (m *Mock) Timer(d time.Duration) *Timer {
	ch := make(chan time.Time, 1)
	t := &Timer{
		C:    ch,
		c:    ch,
		mock: m,
		next: m.Now().Add(d),
	}
	m.addTimer((*internalTimer)(t))
	return t
}

func (m *Mock) addTimer(t *internalTimer) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.timers = append(m.timers, t)
}

func (m *Mock) removeClockTimer(t clockTimer) bool {
	m.mu.Lock()
	defer m.mu.Unlock()
	ret := false
	for i, timer := range m.timers {
		if timer == t {
			ret = true
			copy(m.timers[i:], m.timers[i+1:])
			m.timers[len(m.timers)-1] = nil
			m.timers = m.timers[:len(m.timers)-1]
			break
		}
	}
	sort.Sort(m.timers)
	return ret
}

// clockTimer represents an object with an associated start time.
type clockTimer interface {
	Next() time.Time
	Tick(time.Time)
}

// clockTimers represents a list of sortable timers.
type clockTimers []clockTimer

func (a clockTimers) Len() int           { return len(a) }
func (a clockTimers) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) }

// Timer represents a single event.
// The current time will be sent on C, unless the timer was created by AfterFunc.
type Timer struct {
	C     <-chan time.Time
	c     chan time.Time
	timer *time.Timer // realtime impl, if set
	next  time.Time   // next tick time
	mock  *Mock       // mock clock, if set
	fn    func()      // AfterFunc function, if set
}

// Stop turns off the timer.
func (t *Timer) Stop() bool {
	if t.timer != nil {
		return t.timer.Stop()
	}
	return t.mock.removeClockTimer((*internalTimer)(t))
}

// Reset changes the timer to expire after duration d. It returns true if the
// timer had been active, false if the timer had expired or been stopped.
func (t *Timer) Reset(d time.Duration) bool {
	if t.timer != nil {
		return t.timer.Reset(d)
	}
	ret := t.mock.removeClockTimer((*internalTimer)(t))
	t.next = t.mock.Now().Add(d)
	t.mock.addTimer((*internalTimer)(t))
	return ret
}

type internalTimer Timer

func (t *internalTimer) Next() time.Time { return t.next }
func (t *internalTimer) Tick(now time.Time) {
	if t.fn != nil {
		t.fn()
	} else {
		t.c <- now
	}
	t.mock.removeClockTimer((*internalTimer)(t))
	gosched()
}

// Ticker holds a channel that receives "ticks" at regular intervals.
type Ticker struct {
	C      <-chan time.Time
	c      chan time.Time
	ticker *time.Ticker  // realtime impl, if set
	next   time.Time     // next tick time
	mock   *Mock         // mock clock, if set
	d      time.Duration // time between ticks
}

// Stop turns off the ticker.
func (t *Ticker) Stop() {
	if t.ticker != nil {
		t.ticker.Stop()
	} else {
		t.mock.removeClockTimer((*internalTicker)(t))
	}
}

type internalTicker Ticker

func (t *internalTicker) Next() time.Time { return t.next }
func (t *internalTicker) Tick(now time.Time) {
	select {
	case t.c <- now:
	default:
	}
	t.next = now.Add(t.d)
	gosched()
}

// Sleep momentarily so that other goroutines can process.
func gosched() { time.Sleep(1 * time.Millisecond) }
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/fredhsu/go-eapi"
	"io/ioutil"
	"os"
)

type EosNode struct {
	Hostname      string
	MgmtIp        string
	Username      string
	Password      string
	Ssl           bool
	Reachable     bool
	ConfigCorrect bool
	Uptime        float64
	Version       string
	Config        string
}

func writeConfigFile(path string, n EosNode, config string) {
	filename := path + n.Hostname + ".eos"
	err := ioutil.WriteFile(filename, []byte(config), 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("wrote to ", filename)
}

func readSwitches(filename string) []EosNode {
	var switches []EosNode

	file, err := os.Open("switches.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&switches)
	if err != nil {
		panic(err)
	}
	return switches
}

func genSwitches(nodes []EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for _, node := range nodes {
			out <- node
		}
		close(out)
	}()
	return out
}

func buildUrl(node EosNode) string {
	prefix := "http"
	if node.Ssl == true {
		prefix = prefix + "s"
	}
	url := prefix + "://" + node.Username + ":" + node.Password + "@" + node.Hostname + "/command-api"
	return url
}

func getConfigs(in <-chan EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for n := range in {
			cmds := []string{"enable", "show running-config"}
			url := buildUrl(n)
			response := eapi.Call(url, cmds, "text")
			config := response.Result[1]["output"].(string)
			n.Config = config
			out <- n
		}
		close(out)
	}()
	return out
}

func getVersion(in <-chan EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for n := range in {
			cmds := []string{"show version"}
			url := buildUrl(n)
			response := eapi.Call(url, cmds, "json")
			version := response.Result[0]["version"].(string)
			n.Version = version
			out <- n
		}
		close(out)
	}()
	return out
}

func main() {
	// swFilePtr := flag.String("swfile", "switches.json", "A JSON file with switches to fetch")
	// pathPtr := flag.String("path", "./baseconfigs", "a directory to store the configs")
	// flag.Parse() // command-line flag parsing
	// fmt.Println(*swFilePtr)
	// fmt.Println(*pathPtr)
	switches := readSwitches("switches.json")
	// path := "./baseconfigs/"

	fmt.Println("############# Using Pipelines ###################")
	c1 := genSwitches(switches)
	c2 := getConfigs(c1)
	out := getVersion(c2)
	for i := 0; i < len(switches); i++ {
		fmt.Println(<-out)
	}

}
<commit_msg>clean up of pipeline<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/fredhsu/go-eapi"
	"io/ioutil"
	"os"
)

type EosNode struct {
	Hostname      string
	MgmtIp        string
	Username      string
	Password      string
	Ssl           bool
	Reachable     bool
	ConfigCorrect bool
	Uptime        float64
	Version       string
	Config        string
}

func readSwitches(filename string) []EosNode {
	var switches []EosNode

	file, err := os.Open("switches.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&switches)
	if err != nil {
		panic(err)
	}
	return switches
}

func genSwitches(nodes []EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for _, node := range nodes {
			out <- node
		}
		close(out)
	}()
	return out
}

func buildUrl(node EosNode) string {
	prefix := "http"
	if node.Ssl == true {
		prefix = prefix + "s"
	}
	url := prefix + "://" + node.Username + ":" + node.Password + "@" + node.Hostname + "/command-api"
	return url
}

func getConfigs(in <-chan EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for n := range in {
			cmds := []string{"enable", "show running-config"}
			url := buildUrl(n)
			response := eapi.Call(url, cmds, "text")
			config := response.Result[1]["output"].(string)
			n.Config = config
			out <- n
		}
		close(out)
	}()
	return out
}

func getVersion(in <-chan EosNode) <-chan EosNode {
	out := make(chan EosNode)
	go func() {
		for n := range in {
			cmds := []string{"show version"}
			url := buildUrl(n)
			response := eapi.Call(url, cmds, "json")
			version := response.Result[0]["version"].(string)
			n.Version = version
			out <- n
		}
		close(out)
	}()
	return out
}

func main() {
	switches := readSwitches("switches.json")

	fmt.Println("############# Using Pipelines ###################")
	c1 := genSwitches(switches)
	c2 := getConfigs(c1)
	out := getVersion(c2)
	for i := 0; i < len(switches); i++ {
		fmt.Println(<-out)
	}

}
<|endoftext|>


<commit_before>package epos

import (
	"testing"
)

func TestStore(t *testing.T) {
	db, err := OpenDatabase("testdb1")
	if err != nil {
		t.Fatalf("couldn't open testdb1: %v", err)
	}
	defer db.Close()

	id, err := db.Coll("foo").Insert([]string{"hello", "world!"})
	if err != nil {
		t.Error("couldn't insert string slice: %v", err)
	} else {
		t.Logf("string slice id = %d", id)
	}

	id, err = db.Coll("foo").Insert(struct { X, Y string } { X: "pan-galactic", Y: "gargle-blaster" })
	if err != nil {
		t.Errorf("couldn't insert struct: %v", err)
	} else {
		t.Logf("struct id = %d", id)
	}

	if err = db.Remove(); err != nil {
		t.Errorf("db.Remove failed: %v", err)
	}
}
<commit_msg>add benchmarks for insert, update, delete.<commit_after>package epos

import (
	"testing"
)

func TestStore(t *testing.T) {
	db, err := OpenDatabase("testdb1")
	if err != nil {
		t.Fatalf("couldn't open testdb1: %v", err)
	}
	defer db.Close()

	id, err := db.Coll("foo").Insert([]string{"hello", "world!"})
	if err != nil {
		t.Error("couldn't insert string slice: %v", err)
	} else {
		t.Logf("string slice id = %d", id)
	}

	id, err = db.Coll("foo").Insert(struct { X, Y string } { X: "pan-galactic", Y: "gargle-blaster" })
	if err != nil {
		t.Errorf("couldn't insert struct: %v", err)
	} else {
		t.Logf("struct id = %d", id)
	}

	if err = db.Remove(); err != nil {
		t.Errorf("db.Remove failed: %v", err)
	}
}

var benchmarkData = struct {
		Name string
		Age uint
		SSN string
		LuckyNumbers []int
	} {
		Name: "John J. McWhackadoodle",
		Age: 29,
		SSN: "078-05-1120",
		LuckyNumbers: []int{23, 43},
	}

func BenchmarkInsert(b *testing.B) {
	b.StopTimer()

	db, _ := OpenDatabase("testdb_bench_insert")

	b.StartTimer()

	for i := 0 ; i < b.N ; i++ {
		_, err := db.Coll("bench").Insert(benchmarkData)
		if err != nil {
			b.Fatal("insert failed: ", err)
		}
	}

	b.StopTimer()
	db.Close()
	db.Remove()
}

func BenchmarkUpdate(b *testing.B) {
	b.StopTimer()

	db, _ := OpenDatabase("testdb_bench_update")

	id, err := db.Coll("bench").Insert(benchmarkData)
	if err != nil {
		b.Fatal("insert failed: ", err)
	}

	b.StartTimer()

	for i := 0; i < b.N ; i++ {
		benchmarkData.LuckyNumbers[0], benchmarkData.LuckyNumbers[1] = benchmarkData.LuckyNumbers[1], benchmarkData.LuckyNumbers[0]
		if err = db.Coll("bench").Update(id, data); err != nil {
			b.Fatal("update failed: ", err)
		}
	}

	b.StopTimer()
	db.Close()
	db.Remove()
}

func BenchmarkDelete(b *testing.B) {
	b.StopTimer()

	db, _ := OpenDatabase("testdb_bench_delete")

	b.StartTimer()

	for i := 0 ; i < b.N ; i++ {
		b.StopTimer()
		id, err := db.Coll("bench").Insert(benchmarkData)
		if err != nil {
			b.Fatal("insert failed: ", err)
		}
		b.StartTimer()
		if err = db.Coll("bench").Delete(id); err != nil {
			b.Fatal("delete failed: ", err)
		}
	}

	b.StopTimer()
	db.Close()
	db.Remove()

}
<|endoftext|>


<commit_before>// A set of comprehensive testing tools for use with the normal Go testing system.
//
// Example Usage
//
// The following is a complete example using assert in a standard test function:
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(t, a, b, "The two words should be the same.")
//
//    }
//
// if you assert many times, use the below:
//
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//      assert := assert.New(t)
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(a, b, "The two words should be the same.")
//    }
//
// Assertions
//
// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the
// testing framework. This allows the assertion funcs to write the failings and other details to
// the correct place.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.
//
// Here is an overview of the assert functions:
//
//    assert.Equal(t, expected, actual [, message [, format-args])
//
//    assert.NotEqual(t, notExpected, actual [, message [, format-args]])
//
//    assert.True(t, actualBool [, message [, format-args]])
//
//    assert.False(t, actualBool [, message [, format-args]])
//
//    assert.Nil(t, actualObject [, message [, format-args]])
//
//    assert.NotNil(t, actualObject [, message [, format-args]])
//
//    assert.Empty(t, actualObject [, message [, format-args]])
//
//    assert.NotEmpty(t, actualObject [, message [, format-args]])
//
//    assert.Len(t, actualObject, expectedLength, [, message [, format-args]])
//
//    assert.Error(t, errorObject [, message [, format-args]])
//
//    assert.NoError(t, errorObject [, message [, format-args]])
//
//    assert.EqualError(t, theError, errString [, message [, format-args]])
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.Panics(t, func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(t, func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
//
//    assert.InDelta(t, numA, numB, delta, [, message [, format-args]])
//
//    assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]])
//
// assert package contains Assertions object. it has assertion methods.
//
// Here is an overview of the assert functions:
//    assert.Equal(expected, actual [, message [, format-args])
//
//    assert.NotEqual(notExpected, actual [, message [, format-args]])
//
//    assert.True(actualBool [, message [, format-args]])
//
//    assert.False(actualBool [, message [, format-args]])
//
//    assert.Nil(actualObject [, message [, format-args]])
//
//    assert.NotNil(actualObject [, message [, format-args]])
//
//    assert.Empty(actualObject [, message [, format-args]])
//
//    assert.NotEmpty(actualObject [, message [, format-args]])
//
//    assert.Len(actualObject, expectedLength, [, message [, format-args]])
//
//    assert.Error(errorObject [, message [, format-args]])
//
//    assert.NoError(errorObject [, message [, format-args]])
//
//    assert.EqualError(theError, errString [, message [, format-args]])
//
//    assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.Panics(func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
//
//    assert.InDelta(numA, numB, delta, [, message [, format-args]])
//
//    assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]])
package assert
<commit_msg>Doc entry for EqualValues assertion<commit_after>// A set of comprehensive testing tools for use with the normal Go testing system.
//
// Example Usage
//
// The following is a complete example using assert in a standard test function:
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(t, a, b, "The two words should be the same.")
//
//    }
//
// if you assert many times, use the below:
//
//    import (
//      "testing"
//      "github.com/stretchr/testify/assert"
//    )
//
//    func TestSomething(t *testing.T) {
//      assert := assert.New(t)
//
//      var a string = "Hello"
//      var b string = "Hello"
//
//      assert.Equal(a, b, "The two words should be the same.")
//    }
//
// Assertions
//
// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
// All assertion functions take, as the first argument, the `*testing.T` object provided by the
// testing framework. This allows the assertion funcs to write the failings and other details to
// the correct place.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.
//
// Here is an overview of the assert functions:
//
//    assert.Equal(t, expected, actual [, message [, format-args]])
//
//    assert.EqualValues(t, expected, actual [, message [, format-args]])
//
//    assert.NotEqual(t, notExpected, actual [, message [, format-args]])
//
//    assert.True(t, actualBool [, message [, format-args]])
//
//    assert.False(t, actualBool [, message [, format-args]])
//
//    assert.Nil(t, actualObject [, message [, format-args]])
//
//    assert.NotNil(t, actualObject [, message [, format-args]])
//
//    assert.Empty(t, actualObject [, message [, format-args]])
//
//    assert.NotEmpty(t, actualObject [, message [, format-args]])
//
//    assert.Len(t, actualObject, expectedLength, [, message [, format-args]])
//
//    assert.Error(t, errorObject [, message [, format-args]])
//
//    assert.NoError(t, errorObject [, message [, format-args]])
//
//    assert.EqualError(t, theError, errString [, message [, format-args]])
//
//    assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.Panics(t, func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(t, func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
//
//    assert.InDelta(t, numA, numB, delta, [, message [, format-args]])
//
//    assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]])
//
// assert package contains Assertions object. it has assertion methods.
//
// Here is an overview of the assert functions:
//    assert.Equal(expected, actual [, message [, format-args]])
//
//    assert.EqualValues(expected, actual [, message [, format-args]])
//
//    assert.NotEqual(notExpected, actual [, message [, format-args]])
//
//    assert.True(actualBool [, message [, format-args]])
//
//    assert.False(actualBool [, message [, format-args]])
//
//    assert.Nil(actualObject [, message [, format-args]])
//
//    assert.NotNil(actualObject [, message [, format-args]])
//
//    assert.Empty(actualObject [, message [, format-args]])
//
//    assert.NotEmpty(actualObject [, message [, format-args]])
//
//    assert.Len(actualObject, expectedLength, [, message [, format-args]])
//
//    assert.Error(errorObject [, message [, format-args]])
//
//    assert.NoError(errorObject [, message [, format-args]])
//
//    assert.EqualError(theError, errString [, message [, format-args]])
//
//    assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
//
//    assert.IsType(expectedObject, actualObject [, message [, format-args]])
//
//    assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]])
//
//    assert.Panics(func(){
//
//	    // call code that should panic
//
//    } [, message [, format-args]])
//
//    assert.NotPanics(func(){
//
//	    // call code that should not panic
//
//    } [, message [, format-args]])
//
//    assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
//
//    assert.InDelta(numA, numB, delta, [, message [, format-args]])
//
//    assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]])
package assert
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package recursion

// AllSubsets generates all size k subsets of {1,2,...,n}.
// The number of all generated subsets is n!/(k!(n-k)!), which
// is combination without repetition.
// The time and the space complexity is O(c*k), where c=n!/(k!(n-k)!).
func AllSubsets(n, k int) (subset [][]int) {
	if k == 0 {
		return nil
	}
	var combinations func(i int, set []int)
	combinations = func(i int, set []int) {
		if len(set) == k {
			subset = append(subset, append([]int(nil), set...))
			return
		}
		for j := i; j <= n; j++ { // First execution of this cycle generates the first values in every subset.
			set = append(set, j)
			combinations(j+1, set)
			set = set[:len(set)-1]
		}
	}
	combinations(1, nil)
	return subset
}
<commit_msg>Remove unnecessary slice appending and re-slicing<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package recursion

// AllSubsets generates all size k subsets of {1,2,...,n}.
// The number of all generated subsets is n!/(k!(n-k)!), which
// is combination without repetition.
// The time and the space complexity is O(c*k), where c=n!/(k!(n-k)!).
func AllSubsets(n, k int) (subset [][]int) {
	if k == 0 {
		return nil
	}
	set := make([]int, k)
	var combinations func(o, p int)
	combinations = func(o, p int) {
		if p == k {
			subset = append(subset, append([]int(nil), set...))
			return
		}
		for i := o; i <= n; i++ { // First execution of this cycle generates the first values in every subset.
			set[p] = i
			combinations(i+1, p+1)
		}
	}
	combinations(1, 0)
	return subset
}
<|endoftext|>


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

package testing

import (
	"fmt";
	"flag";
)

var chatty = flag.Bool("chatty", false, "chatty")

// Insert tabs after newlines - but not the last one
func tabify(s string) string {
	for i := 0; i < len(s) - 1; i++ {	// -1 because if last char is newline, don't bother
		if s[i] == '\n' {
			return s[0:i+1] + "\t" + tabify(s[i+1:len(s)]);
		}
	}
	return s
}

type T struct {
	errors	string;
	failed	bool;
	ch	chan *T;
}

func (t *T) Fail() {
	t.failed = true
}

func (t *T) FailNow() {
	t.Fail();
	t.ch <- t;
	sys.Goexit();
}

func (t *T) Log(args ...) {
	t.errors += "\t" + tabify(fmt.Sprintln(args));
}

func (t *T) Logf(format string, args ...) {
	t.errors += tabify(fmt.Sprintf("\t" + format, args));
	l := len(t.errors);
	if l > 0 && t.errors[l-1] != '\n' {
		t.errors += "\n"
	}
}

func (t *T) Error(args ...) {
	t.Log(args);
	t.Fail();
}

func (t *T) Errorf(format string, args ...) {
	t.Logf(format, args);
	t.Fail();
}

func (t *T) Fatal(args ...) {
	t.Log(args);
	t.FailNow();
}

func (t *T) Fatalf(format string, args ...) {
	t.Logf(format, args);
	t.FailNow();
}

type Test struct {
	Name string;
	F func(*T);
}

func tRunner(t *T, test *Test) {
	test.F(t);
	t.ch <- t;
}

func Main(tests []Test) {
	flag.Parse();
	ok := true;
	if len(tests) == 0 {
		println("testing: warning: no tests to run");
	}
	for i := 0; i < len(tests); i++ {
		if *chatty {
			println("=== RUN ", tests[i].Name);
		}
		t := new(T);
		t.ch = make(chan *T);
		go tRunner(t, &tests[i]);
		<-t.ch;
		if t.failed {
			println("--- FAIL:", tests[i].Name);
			print(t.errors);
			ok = false;
		} else if *chatty {
			println("--- PASS:", tests[i].Name);
			print(t.errors);
		}
	}
	if !ok {
		println("FAIL");
		sys.Exit(1);
	}
	println("PASS");
}
<commit_msg>document testing and incidentally gotest<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The testing package provides support for automated testing of Go packages.
// It is intended to be used in concert with the ``gotest'' utility, which automates
// execution of any function of the form
//     func TestXxx(*testing.T)
// where Xxx can by any alphanumeric string (but the first letter must not be in
// [a-z]) and serves to identify the test routine.
// These TestXxx routines should be declared within the package they are testing.
package testing

import (
	"fmt";
	"flag";
)

// Report as tests are run; default is silent for success.
var chatty = flag.Bool("chatty", false, "chatty")

// Insert tabs after newlines - but not the last one
func tabify(s string) string {
	for i := 0; i < len(s) - 1; i++ {	// -1 because if last char is newline, don't bother
		if s[i] == '\n' {
			return s[0:i+1] + "\t" + tabify(s[i+1:len(s)]);
		}
	}
	return s
}

// T is a type passed to Test functions to manage test state and support formatted test logs.
// Logs are accumulated during execution and dumped to standard error when done.
type T struct {
	errors	string;
	failed	bool;
	ch	chan *T;
}

// Fail marks the Test function as having failed but continues execution.
func (t *T) Fail() {
	t.failed = true
}

// FailNow marks the Test function as having failed and stops its execution.
// Execution will continue at the next Test.
func (t *T) FailNow() {
	t.Fail();
	t.ch <- t;
	sys.Goexit();
}

// Log formats its arguments using default formatting, analogous to Print(),
// and records the text in the error log.
func (t *T) Log(args ...) {
	t.errors += "\t" + tabify(fmt.Sprintln(args));
}

// Log formats its arguments according to the format, analogous to Printf(),
// and records the text in the error log.
func (t *T) Logf(format string, args ...) {
	t.errors += tabify(fmt.Sprintf("\t" + format, args));
	l := len(t.errors);
	if l > 0 && t.errors[l-1] != '\n' {
		t.errors += "\n"
	}
}

// Error is equivalent to Log() followed by Fail().
func (t *T) Error(args ...) {
	t.Log(args);
	t.Fail();
}

// Errorf is equivalent to Logf() followed by Fail().
func (t *T) Errorf(format string, args ...) {
	t.Logf(format, args);
	t.Fail();
}

// Fatal is equivalent to Log() followed by FailNow().
func (t *T) Fatal(args ...) {
	t.Log(args);
	t.FailNow();
}

// Fatalf is equivalent to Logf() followed by FailNow().
func (t *T) Fatalf(format string, args ...) {
	t.Logf(format, args);
	t.FailNow();
}

// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type Test struct {
	Name string;
	F func(*T);
}

func tRunner(t *T, test *Test) {
	test.F(t);
	t.ch <- t;
}

// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
func Main(tests []Test) {
	flag.Parse();
	ok := true;
	if len(tests) == 0 {
		println("testing: warning: no tests to run");
	}
	for i := 0; i < len(tests); i++ {
		if *chatty {
			println("=== RUN ", tests[i].Name);
		}
		t := new(T);
		t.ch = make(chan *T);
		go tRunner(t, &tests[i]);
		<-t.ch;
		if t.failed {
			println("--- FAIL:", tests[i].Name);
			print(t.errors);
			ok = false;
		} else if *chatty {
			println("--- PASS:", tests[i].Name);
			print(t.errors);
		}
	}
	if !ok {
		println("FAIL");
		sys.Exit(1);
	}
	println("PASS");
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
)

func main() {
	gtk.Init(nil)
	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetPosition(gtk.WIN_POS_CENTER)
	window.SetTitle("Irken")
	window.SetIconName("gtk-dialog-info")
	window.Connect("destroy", func(ctx *glib.CallbackContext) {
		println("got destroy!", ctx.Data().(string))
		gtk.MainQuit()
	}, "foo")

	//--------------------------------------------------------
	// GtkVBox
	//--------------------------------------------------------
	vbox := gtk.NewVBox(false, 1)

	swin := gtk.NewScrolledWindow(nil, nil)
	swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	swin.SetShadowType(gtk.SHADOW_IN)
	textview := gtk.NewTextView()
	textview.SetSizeRequest(800, 600)
	//buffer := textview.GetBuffer()
	swin.Add(textview)
	vbox.Add(swin)

	hbox := gtk.NewHBox(false, 1)

	// entry
	entry := gtk.NewEntry()
	entry.SetSizeRequest(700, 40)
	hbox.Add(entry)

	button := gtk.NewButtonWithLabel("Send")
	button.Clicked(func (){
		println(entry.GetText())
	})
	hbox.Add(button)

	vbox.Add(hbox)

	window.Add(vbox)
	window.SetSizeRequest(800, 640)
	window.ShowAll()
	gtk.Main()
}<commit_msg>implemented rawirc into demo.go<commit_after>package main

import (
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
	"github.com/mattn/go-gtk/gdk"
	"irken/client"
	"fmt"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(10)
	glib.ThreadInit(nil)
	gdk.ThreadsInit()
	gdk.ThreadsEnter()
	gtk.Init(nil)

	window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	window.SetPosition(gtk.WIN_POS_CENTER)
	window.SetTitle("Irken")
	window.SetIconName("gtk-dialog-info")
	window.Connect("destroy", func(ctx *glib.CallbackContext) {
		println("got destroy!", ctx.Data().(string))
		gtk.MainQuit()
	}, "foo")

	cs, err := client.NewConnectSession("irc.freenode.net", "testurnstf", "whatever")
	if err != nil {
		fmt.Println(err)
	}

	cs.ReadToChannels()

	//--------------------------------------------------------
	// GtkVBox
	//--------------------------------------------------------
	vbox := gtk.NewVBox(false, 1)

	swin := gtk.NewScrolledWindow(nil, nil)
	swin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	swin.SetShadowType(gtk.SHADOW_IN)
	textview := gtk.NewTextView()
	textview.SetEditable(false)
	textview.SetCursorVisible(false)
	textview.SetWrapMode(gtk.WRAP_WORD)
	textview.SetSizeRequest(800, 600)
	textbuffer := textview.GetBuffer()
	swin.Add(textview)
	vbox.Add(swin)

	hbox := gtk.NewHBox(false, 1)

	// entry
	entry := gtk.NewEntry()
	entry.SetSizeRequest(700, 40)
	hbox.Add(entry)

	button := gtk.NewButtonWithLabel("Send")
	button.Clicked(func (){
		cs.Conn.Write(entry.GetText())
		entry.SetText("")
	})
	hbox.Add(button)

	vbox.Add(hbox)

	window.Add(vbox)
	window.SetSizeRequest(800, 640)
	window.ShowAll()

	cs.NewChannel("#freenode")

	go func() {
		for {
			line := <-cs.IrcChannels[""].Ch
			gdk.ThreadsEnter()
			var endIter gtk.TextIter
			textbuffer.GetEndIter(&endIter)
			textbuffer.Insert(&endIter, line.Output())
			textview.ScrollToIter(&endIter, 0.0, false, 0.0, 0.0)
			gdk.ThreadsLeave()
		}
	}()

	go func() {
		for {
			line := <-cs.IrcChannels["#freenode"].Ch
			gdk.ThreadsEnter()
			var endIter gtk.TextIter
			textbuffer.GetEndIter(&endIter)
			textbuffer.Insert(&endIter, line.Output())
			textview.ScrollToIter(&endIter, 0.0, false, 0.0, 0.0)
			gdk.ThreadsLeave()
		}
	}()

	gtk.Main()
}<|endoftext|>


<commit_before>// Copyright 2018 Istio 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 version

import (
	"github.com/spf13/cobra"
)

// CobraCommand is a command used to print version information.
func CobraCommand() *cobra.Command {
	var short bool

	cmd := &cobra.Command{
		Use:   "version",
		Short: "Prints out build version information",
		Run: func(cmd *cobra.Command, args []string) {
			if short {
				cmd.Printf("%s\n", Info)
			} else {
				cmd.Printf("%s", Info.LongForm())
			}
		},
	}

	cmd.PersistentFlags().BoolVarP(&short, "short", "s", short, "Displays a short form of the version information")

	return cmd
}
<commit_msg>Introduce pkg/collateral (#3014)<commit_after>// Copyright 2018 Istio 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 version

import (
	"github.com/spf13/cobra"
)

// CobraCommand returns a command used to print version information.
func CobraCommand() *cobra.Command {
	var short bool

	cmd := &cobra.Command{
		Use:   "version",
		Short: "Prints out build version information",
		Run: func(cmd *cobra.Command, args []string) {
			if short {
				cmd.Printf("%s\n", Info)
			} else {
				cmd.Printf("%s", Info.LongForm())
			}
		},
	}

	cmd.PersistentFlags().BoolVarP(&short, "short", "s", short, "Displays a short form of the version information")

	return cmd
}
<|endoftext|>


<commit_before>package main

import(
	"io"
	"log"
	"net/http"
	"os"
	"io/ioutil"
	"strings"
	"time"
	"flag"
	"strconv"
	"encoding/json"
	"github.com/coreos/etcd/clientv3"
	"golang.org/x/net/context"
)

var (
	cli *clientv3.Client
	Separator = "/"
)

func main() {
	host := flag.String("h","0.0.0.0","host name or ip address")
	port := flag.Int("p", 8080, "port")
	name := flag.String("n", "/request", "request root name")
	flag.CommandLine.Parse(os.Args[1:])

	// v2
	http.HandleFunc(*name, v2request)

	// v3
	http.HandleFunc("/connect", connect)
	http.HandleFunc("/put", put)
	http.HandleFunc("/get", get)
	http.HandleFunc("/delete", del)
	// dirctory mode
	http.HandleFunc("/getpath", getPath)

	wd, err := os.Getwd()
	if err != nil{
		log.Fatal(err)
	}

	//log.Println(http.Dir(wd + "/assets"))

	http.Handle("/", http.FileServer(http.Dir(wd + "/assets"))) // view static directory

	log.Printf("listening on %s:%d\n", *host, *port)
	err = http.ListenAndServe(*host + ":" + strconv.Itoa(*port), nil)
	if err != nil {
		log.Fatal(err)
	}
}

func v2request(w http.ResponseWriter, r *http.Request){
	if err := r.ParseForm(); err != nil {
		log.Println(err.Error())
	}
	log.Println(r.Method, "v2", r.FormValue("url"), r.PostForm.Encode())

	body := strings.NewReader(r.PostForm.Encode())
	req, err := http.NewRequest(r.Method, r.Form.Get("url"), body)
	if err != nil {
		io.WriteString(w, err.Error())
		return
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	client := &http.Client{Timeout: 10*time.Second} // important!!!
	resp, err := client.Do(req)
	if err != nil {
		io.WriteString(w, err.Error())
	}else {
		result, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			io.WriteString(w, "Get data failed: " + err.Error())
		}else {
			io.WriteString(w, string(result))
		}
	}
}

func connect(w http.ResponseWriter, r *http.Request){
	if cli != nil {
		etcdHost := cli.Endpoints()[0]
		if r.FormValue("host") == etcdHost {
			io.WriteString(w, "running")
			return
		}else {
			if err := cli.Close();err != nil {
				log.Println(err.Error())
			}
		}
	}
	endpoints := []string{r.FormValue("host")}
	var err error
	cli, err = clientv3.New(clientv3.Config{
		Endpoints:   endpoints,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Println(r.Method, "v3", "connect fail.")
		io.WriteString(w, string(err.Error()))
	}else {
		log.Println(r.Method, "v3", "connect success.")
		io.WriteString(w, "ok")
	}
}

func put(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	value := r.FormValue("value")
	ttl := r.FormValue("ttl")
	log.Println("PUT", "v3", key)

	var err error
	data := make(map[string]interface{})
	if ttl != "" {
		var sec int64
		sec, err = strconv.ParseInt(ttl, 10, 64)
		if err != nil {
			log.Println(err.Error())
		}
		var leaseResp *clientv3.LeaseGrantResponse
		leaseResp, err = cli.Grant(context.TODO(), sec)
		_, err = cli.Put(context.Background(), key, value, clientv3.WithLease(leaseResp.ID))
	}else {
		_, err = cli.Put(context.Background(), key, value)
	}
	if err != nil {
		io.WriteString(w, string(err.Error()))
	}else {
		if resp, err := cli.Get(context.Background(), key, clientv3.WithPrefix());err != nil {
			data["errorCode"] = err.Error()
		}else {
			if resp.Count > 0 {
				kv := resp.Kvs[0]
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				node["ttl"] = getTTL(kv.Lease)
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				data["node"] = node
			}
		}
		var dataByte []byte
		if dataByte, err = json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
	}
}

func get(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	data := make(map[string]interface{})
	log.Println("GET", "v3", key)

	if resp, err := cli.Get(context.Background(), key, clientv3.WithPrefix());err != nil {
		data["errorCode"] = err.Error()
	}else {
		if r.FormValue("prefix") == "true" {
			pnode := make(map[string]interface{})
			pnode["key"] = key
			pnode["nodes"] = make([]map[string]interface{}, 0)
			for _, kv := range resp.Kvs {
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				if key == string(kv.Key) {
					node["ttl"] = getTTL(kv.Lease)
				} else {
					node["ttl"] = 0
				}
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				nodes := pnode["nodes"].([]map[string]interface{})
				pnode["nodes"] = append(nodes, node)
			}
			data["node"] = pnode
		}else {
			if resp.Count > 0 {
				kv := resp.Kvs[0]
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				node["ttl"] = getTTL(kv.Lease)
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				data["node"] = node
			}else {
				data["errorCode"] = "The node does not exist."
			}
		}
	}
	var dataByte []byte
	var err error
	if dataByte, err = json.Marshal(data);err != nil {
		io.WriteString(w, err.Error())
	} else {
		io.WriteString(w, string(dataByte))
	}
}

func getPath(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	log.Println("GET", "v3", key)
	var (
		data = make(map[string]interface{})
		/*
			{1:["/"], 2:["/foo", "/foo2"], 3:["/foo/bar", "/foo2/bar"], 4:["/foo/bar/test"]}
		 */
		all = make(map[int][]map[string]interface{})
		min int
		max int
		prefixKey string
	)
	// parent
	presp, err := cli.Get(context.Background(), key)
	if err != nil {
		data["errorCode"] = err.Error()
		if dataByte, err := json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
		return
	}
	if key == Separator {
		min = 1
		prefixKey = Separator
	} else {
		min = len(strings.Split(key, Separator))
		prefixKey = key + Separator
	}
	max = min
	all[min] = []map[string]interface{}{{"key":key}}
	if presp.Count != 0 {
		all[min][0]["value"] = string(presp.Kvs[0].Value)
		all[min][0]["ttl"] = getTTL(presp.Kvs[0].Lease)
		all[min][0]["createdIndex"] = presp.Kvs[0].CreateRevision
		all[min][0]["modifiedIndex"] = presp.Kvs[0].ModRevision
	}
	all[min][0]["nodes"] = make([]map[string]interface{}, 0)

	//child
	resp, err := cli.Get(context.Background(), prefixKey, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
	if err != nil {
		data["errorCode"] = err.Error()
		if dataByte, err := json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
		return
	}

	for _, v := range resp.Kvs {
		if string(v.Key) == Separator {
			continue
		}
		keys := strings.Split(string(v.Key), Separator) // /foo/bar
		var begin bool
		for i := range keys { // ["", "foo", "bar"]
			k := strings.Join(keys[0:i+1], Separator)
			if k == "" {
				continue
			}
			if key == Separator {
				begin = true
			} else if k == key {
				begin = true
				continue
			}
			if begin {
				node := map[string]interface{}{"key":k}
				if node["key"].(string) == string(v.Key) {
					node["value"] = string(v.Value)
					if key == string(v.Key) {
						node["ttl"] = getTTL(v.Lease)
					} else {
						node["ttl"] = 0
					}
					node["createdIndex"] = v.CreateRevision
					node["modifiedIndex"] = v.ModRevision
				}
				level := len(strings.Split(k, Separator))
				if level > max {
					max = level
				}

				if _, ok := all[level];!ok {
					all[level] = make([]map[string]interface{}, 0)
				}
				levelNodes := all[level]
				var isExist bool
				for _, n := range levelNodes {
					if n["key"].(string) == k {
						isExist = true
					}
				}
				if !isExist {
					node["nodes"] = make([]map[string]interface{}, 0)
					all[level] = append(all[level], node)
				}
			}
		}
	}

	// parent-child mapping
	for i := max; i > min; i-- {
		for _, a := range all[i] {
			for _, pa := range all[i-1] {
				if i == 2 {
					pa["nodes"] = append(pa["nodes"].([]map[string]interface{}), a)
					pa["dir"] = true
				} else {
					if strings.HasPrefix(a["key"].(string), pa["key"].(string) + Separator) {
						pa["nodes"] = append(pa["nodes"].([]map[string]interface{}), a)
						pa["dir"] = true
					}
				}
			}
		}
	}
	data = all[min][0]
	if dataByte, err := json.Marshal(map[string]interface{}{"node":data});err != nil {
		io.WriteString(w, err.Error())
	} else {
		io.WriteString(w, string(dataByte))
	}
}

func del(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	dir := r.FormValue("dir")
	log.Println("DELETE", "v3", key)

	if _, err := cli.Delete(context.Background(), key);err != nil {
		io.WriteString(w, err.Error())
		return
	}

	if dir == "true" {
		if _, err := cli.Delete(context.Background(), key + "/", clientv3.WithPrefix());err != nil {
			io.WriteString(w, err.Error())
			return
		}
	}
	io.WriteString(w, "ok")
}

func getTTL(lease int64) int64 {
	resp, err := cli.Lease.TimeToLive(context.Background(), clientv3.LeaseID(lease))
	if err != nil {
		return 0
	}
	if resp.TTL == -1 {
		return 0
	}
	return resp.TTL
}
<commit_msg>Improve httpserver<commit_after>package main

import(
	"io"
	"log"
	"net/http"
	"os"
	"io/ioutil"
	"strings"
	"time"
	"flag"
	"strconv"
	"encoding/json"
	"github.com/coreos/etcd/clientv3"
	"golang.org/x/net/context"
)

var (
	cli *clientv3.Client
	Separator = "/"
)

func main() {
	host := flag.String("h","0.0.0.0","host name or ip address")
	port := flag.Int("p", 8080, "port")
	name := flag.String("n", "/request", "request root name")
	flag.CommandLine.Parse(os.Args[1:])

	// v2
	http.HandleFunc(*name, v2request)

	// v3
	http.HandleFunc("/connect", connect)
	http.HandleFunc("/put", put)
	http.HandleFunc("/get", get)
	http.HandleFunc("/delete", del)
	// dirctory mode
	http.HandleFunc("/getpath", getPath)

	wd, err := os.Getwd()
	if err != nil{
		log.Fatal(err)
	}

	//log.Println(http.Dir(wd + "/assets"))

	http.Handle("/", http.FileServer(http.Dir(wd + "/assets"))) // view static directory

	log.Printf("listening on %s:%d\n", *host, *port)
	err = http.ListenAndServe(*host + ":" + strconv.Itoa(*port), nil)
	if err != nil {
		log.Fatal(err)
	}
}

func v2request(w http.ResponseWriter, r *http.Request){
	if err := r.ParseForm(); err != nil {
		log.Println(err.Error())
	}
	log.Println(r.Method, "v2", r.FormValue("url"), r.PostForm.Encode())

	body := strings.NewReader(r.PostForm.Encode())
	req, err := http.NewRequest(r.Method, r.Form.Get("url"), body)
	if err != nil {
		io.WriteString(w, err.Error())
		return
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	client := &http.Client{Timeout: 10*time.Second} // important!!!
	resp, err := client.Do(req)
	if err != nil {
		io.WriteString(w, err.Error())
	}else {
		result, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			io.WriteString(w, "Get data failed: " + err.Error())
		}else {
			io.WriteString(w, string(result))
		}
	}
}

func connect(w http.ResponseWriter, r *http.Request){
	if cli != nil {
		etcdHost := cli.Endpoints()[0]
		if r.FormValue("host") == etcdHost {
			io.WriteString(w, "running")
			return
		}else {
			if err := cli.Close();err != nil {
				log.Println(err.Error())
			}
		}
	}
	endpoints := []string{r.FormValue("host")}
	var err error
	cli, err = clientv3.New(clientv3.Config{
		Endpoints:   endpoints,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Println(r.Method, "v3", "connect fail.")
		io.WriteString(w, string(err.Error()))
	}else {
		log.Println(r.Method, "v3", "connect success.")
		io.WriteString(w, "ok")
	}
}

func put(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	value := r.FormValue("value")
	ttl := r.FormValue("ttl")
	log.Println("PUT", "v3", key)

	var err error
	data := make(map[string]interface{})
	if ttl != "" {
		var sec int64
		sec, err = strconv.ParseInt(ttl, 10, 64)
		if err != nil {
			log.Println(err.Error())
		}
		var leaseResp *clientv3.LeaseGrantResponse
		leaseResp, err = cli.Grant(context.TODO(), sec)
		_, err = cli.Put(context.Background(), key, value, clientv3.WithLease(leaseResp.ID))
	}else {
		_, err = cli.Put(context.Background(), key, value)
	}
	if err != nil {
		io.WriteString(w, string(err.Error()))
	}else {
		if resp, err := cli.Get(context.Background(), key, clientv3.WithPrefix());err != nil {
			data["errorCode"] = err.Error()
		}else {
			if resp.Count > 0 {
				kv := resp.Kvs[0]
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				node["ttl"] = getTTL(kv.Lease)
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				data["node"] = node
			}
		}
		var dataByte []byte
		if dataByte, err = json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
	}
}

func get(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	data := make(map[string]interface{})
	log.Println("GET", "v3", key)

	if resp, err := cli.Get(context.Background(), key, clientv3.WithPrefix());err != nil {
		data["errorCode"] = err.Error()
	}else {
		if r.FormValue("prefix") == "true" {
			pnode := make(map[string]interface{})
			pnode["key"] = key
			pnode["nodes"] = make([]map[string]interface{}, 0)
			for _, kv := range resp.Kvs {
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				if key == string(kv.Key) {
					node["ttl"] = getTTL(kv.Lease)
				} else {
					node["ttl"] = 0
				}
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				nodes := pnode["nodes"].([]map[string]interface{})
				pnode["nodes"] = append(nodes, node)
			}
			data["node"] = pnode
		}else {
			if resp.Count > 0 {
				kv := resp.Kvs[0]
				node := make(map[string]interface{})
				node["key"] = string(kv.Key)
				node["value"] = string(kv.Value)
				node["dir"] = false
				node["ttl"] = getTTL(kv.Lease)
				node["createdIndex"] = kv.CreateRevision
				node["modifiedIndex"] = kv.ModRevision
				data["node"] = node
			}else {
				data["errorCode"] = "The node does not exist."
			}
		}
	}
	var dataByte []byte
	var err error
	if dataByte, err = json.Marshal(data);err != nil {
		io.WriteString(w, err.Error())
	} else {
		io.WriteString(w, string(dataByte))
	}
}

func getPath(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	log.Println("GET", "v3", key)
	var (
		data = make(map[string]interface{})
		/*
			{1:["/"], 2:["/foo", "/foo2"], 3:["/foo/bar", "/foo2/bar"], 4:["/foo/bar/test"]}
		 */
		all = make(map[int][]map[string]interface{})
		min int
		max int
		prefixKey string
	)
	// parent
	presp, err := cli.Get(context.Background(), key)
	if err != nil {
		data["errorCode"] = err.Error()
		if dataByte, err := json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
		return
	}
	if key == Separator {
		min = 1
		prefixKey = Separator
	} else {
		min = len(strings.Split(key, Separator))
		prefixKey = key + Separator
	}
	max = min
	all[min] = []map[string]interface{}{{"key":key}}
	if presp.Count != 0 {
		all[min][0]["value"] = string(presp.Kvs[0].Value)
		all[min][0]["ttl"] = getTTL(presp.Kvs[0].Lease)
		all[min][0]["createdIndex"] = presp.Kvs[0].CreateRevision
		all[min][0]["modifiedIndex"] = presp.Kvs[0].ModRevision
	}
	all[min][0]["nodes"] = make([]map[string]interface{}, 0)

	//child
	resp, err := cli.Get(context.Background(), prefixKey, clientv3.WithPrefix(), clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend))
	if err != nil {
		data["errorCode"] = err.Error()
		if dataByte, err := json.Marshal(data);err != nil {
			io.WriteString(w, err.Error())
		} else {
			io.WriteString(w, string(dataByte))
		}
		return
	}

	for _, kv := range resp.Kvs {
		if string(kv.Key) == Separator {
			continue
		}
		keys := strings.Split(string(kv.Key), Separator) // /foo/bar
		var begin bool
		for i := range keys { // ["", "foo", "bar"]
			k := strings.Join(keys[0:i+1], Separator)
			if k == "" {
				continue
			}
			if key == Separator {
				begin = true
			} else if k == key {
				begin = true
				continue
			}
			if begin {
				node := map[string]interface{}{"key":k}
				if node["key"].(string) == string(kv.Key) {
					node["value"] = string(kv.Value)
					if key == string(kv.Key) {
						node["ttl"] = getTTL(kv.Lease)
					} else {
						node["ttl"] = 0
					}
					node["createdIndex"] = kv.CreateRevision
					node["modifiedIndex"] = kv.ModRevision
				}
				level := len(strings.Split(k, Separator))
				if level > max {
					max = level
				}

				if _, ok := all[level];!ok {
					all[level] = make([]map[string]interface{}, 0)
				}
				levelNodes := all[level]
				var isExist bool
				for _, n := range levelNodes {
					if n["key"].(string) == k {
						isExist = true
					}
				}
				if !isExist {
					node["nodes"] = make([]map[string]interface{}, 0)
					all[level] = append(all[level], node)
				}
			}
		}
	}

	// parent-child mapping
	for i := max; i > min; i-- {
		for _, a := range all[i] {
			for _, pa := range all[i-1] {
				if i == 2 {
					pa["nodes"] = append(pa["nodes"].([]map[string]interface{}), a)
					pa["dir"] = true
				} else {
					if strings.HasPrefix(a["key"].(string), pa["key"].(string) + Separator) {
						pa["nodes"] = append(pa["nodes"].([]map[string]interface{}), a)
						pa["dir"] = true
					}
				}
			}
		}
	}
	data = all[min][0]
	if dataByte, err := json.Marshal(map[string]interface{}{"node":data});err != nil {
		io.WriteString(w, err.Error())
	} else {
		io.WriteString(w, string(dataByte))
	}
}

func del(w http.ResponseWriter, r *http.Request){
	key := r.FormValue("key")
	dir := r.FormValue("dir")
	log.Println("DELETE", "v3", key)

	if _, err := cli.Delete(context.Background(), key);err != nil {
		io.WriteString(w, err.Error())
		return
	}

	if dir == "true" {
		if _, err := cli.Delete(context.Background(), key + "/", clientv3.WithPrefix());err != nil {
			io.WriteString(w, err.Error())
			return
		}
	}
	io.WriteString(w, "ok")
}

func getTTL(lease int64) int64 {
	resp, err := cli.Lease.TimeToLive(context.Background(), clientv3.LeaseID(lease))
	if err != nil {
		return 0
	}
	if resp.TTL == -1 {
		return 0
	}
	return resp.TTL
}
<|endoftext|>


<commit_before>//  Copyright 2017 Walter Schulze
//
//  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 main

import (
	"fmt"
	"go/ast"
	"go/types"
	"os"
	"strings"

	"golang.org/x/tools/go/loader"
)

const eqFuncPrefix = "deriveEqual"

func generateEqual(p Printer, pkgInfo *loader.PackageInfo, calls []*ast.CallExpr) {
	qual := types.RelativeTo(pkgInfo.Pkg)
	m := newTypesMap(qual)

	for _, call := range calls {
		fn, ok := call.Fun.(*ast.Ident)
		if !ok {
			continue
		}
		if !strings.HasPrefix(fn.Name, eqFuncPrefix) {
			continue
		}
		if len(call.Args) != 2 {
			fmt.Fprintf(os.Stderr, "%s does not have two arguments\n", fn.Name)
			continue
		}
		t0 := pkgInfo.TypeOf(call.Args[0])
		t1 := pkgInfo.TypeOf(call.Args[1])
		if !types.Identical(t0, t1) {
			fmt.Fprintf(os.Stderr, "%s has two arguments, but they are of different types %s != %s\n",
				fn.Name, t0, t1)
			continue
		}
		name := strings.TrimPrefix(fn.Name, eqFuncPrefix)
		qual := types.RelativeTo(pkgInfo.Pkg)
		typeStr := typeName(t0, qual)
		if typeStr != name {
			//TODO think about whether this is really necessary
			fmt.Fprintf(os.Stderr, "%s's suffix %s does not match the type %s\n",
				fn.Name, name, typeStr)
			continue
		}
		m.Set(t0, false)
	}

	eq := newEqual(p, m, qual, eqFuncPrefix)

	for _, typ := range m.List() {
		eq.genFuncFor(typ)
	}
	for _, typ := range m.List() {
		if m.Get(typ) {
			continue
		}
		eq.genFuncFor(typ)
	}
}

func newEqual(printer Printer, typesMap TypesMap, qual types.Qualifier, prefix string) *equal {
	return &equal{
		printer:  printer,
		typesMap: typesMap,
		qual:     qual,
		bytesPkg: printer.NewImport("bytes"),
		prefix:   prefix,
	}
}

type equal struct {
	printer  Printer
	typesMap TypesMap
	qual     types.Qualifier
	bytesPkg Import
	prefix   string
}

func (this *equal) funcName(typ types.Type) string {
	return eqFuncPrefix + typeName(typ, this.qual)
}

func (this *equal) genFuncFor(typ types.Type) {
	p := this.printer
	m := this.typesMap
	m.Set(typ, true)
	typeStr := types.TypeString(typ, this.qual)
	p.P("")
	p.P("func %s(this, that %s) bool {", this.funcName(typ), typeStr)
	p.In()
	switch ttyp := typ.(type) {
	case *types.Pointer:
		ref := ttyp.Elem()
		switch tttyp := ref.Underlying().(type) {
		case *types.Struct:
			numFields := tttyp.NumFields()
			if numFields == 0 {
				p.P("return (this == nil && that == nil) || (this != nil) && (that != nil)")
			} else {
				p.P("return (this == nil && that == nil) || (this != nil) && (that != nil) &&")
			}
			p.In()
			for i := 0; i < numFields; i++ {
				field := tttyp.Field(i)
				fieldType := field.Type()
				fieldName := field.Name()
				thisField := "this." + fieldName
				thatField := "that." + fieldName
				fieldStr, err := this.field(thisField, thatField, fieldType)
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
					return
				}
				if (i + 1) != numFields {
					p.P(fieldStr + " &&")
				} else {
					p.P(fieldStr)
				}
			}
			p.Out()
		case *types.Basic:
			fieldStr, err := this.field("this", "that", typ)
			if err != nil {
				fmt.Fprintf(os.Stderr, err.Error())
				return
			}
			p.P("return " + fieldStr)
		default:
			fmt.Fprintf(os.Stderr, "unsupported: pointer is not a named struct, but %#v\n", ref)
			return
		}
	case *types.Slice:
		p.P("if this == nil || that == nil {")
		p.In()
		p.P("return this == nil && that == nil")
		p.Out()
		p.P("}")
		p.P("if len(this) != len(that) {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.P("for i := 0; i < len(this); i++ {")
		p.In()
		eqStr, err := this.field("this[i]", "that[i]", ttyp.Elem())
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			return
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	case *types.Array:
		p.P("for i := 0; i < len(this); i++ {")
		p.In()
		eqStr, err := this.field("this[i]", "that[i]", ttyp.Elem())
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			return
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	case *types.Map:
		p.P("if this == nil || that == nil {")
		p.In()
		p.P("return this == nil && that == nil")
		p.Out()
		p.P("}")
		p.P("if len(this) != len(that) {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.P("for k, v := range this {")
		p.In()
		p.P("thatv, ok := that[k]")
		p.P("if !ok {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		eqStr, err := this.field("v", "thatv", ttyp.Elem())
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			return
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	default:
		fmt.Fprintf(os.Stderr, "unsupported type: %#v", typ)
		return
	}
	p.Out()
	p.P("}")
}

func not(s string) string {
	if s[0] == '(' {
		return "!" + s
	}
	return "!(" + s + ")"
}

func isComparable(tt types.Type) bool {
	t := tt.Underlying()
	switch typ := t.(type) {
	case *types.Basic:
		return typ.Kind() != types.UntypedNil
	case *types.Struct:
		for i := 0; i < typ.NumFields(); i++ {
			f := typ.Field(i)
			ft := f.Type()
			if !isComparable(ft) {
				return false
			}
		}
		return true
	case *types.Array:
		return isComparable(typ.Elem())
	}
	return false
}

func (this *equal) field(thisField, thatField string, fieldType types.Type) (string, error) {
	if isComparable(fieldType) {
		return fmt.Sprintf("%s == %s", thisField, thatField), nil
	}
	switch typ := fieldType.(type) {
	case *types.Pointer:
		ref := typ.Elem()
		if _, ok := ref.(*types.Named); ok {
			return fmt.Sprintf("%s.Equal(%s)", thisField, thatField), nil
		}
		eqStr, err := this.field("*"+thisField, "*"+thatField, ref)
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("((%[1]s == nil && %[2]s == nil) || (%[1]s != nil && %[2]s != nil && %[3]s))", thisField, thatField, eqStr), nil
	case *types.Array:
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Slice:
		if b, ok := typ.Elem().(*types.Basic); ok && b.Kind() == types.Byte {
			return fmt.Sprintf("%s.Equal(%s, %s)", this.bytesPkg(), thisField, thatField), nil
		}
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Map:
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Named:
		return fmt.Sprintf("%s.Equal(&%s)", thisField, thatField), nil
	default: // *Chan, *Tuple, *Signature, *Interface, *types.Basic.Kind() == types.UntypedNil, *Struct
		return "", fmt.Errorf("unsupported type %#v", fieldType)
	}
}
<commit_msg>better error propogration for equal<commit_after>//  Copyright 2017 Walter Schulze
//
//  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 main

import (
	"fmt"
	"go/ast"
	"go/types"
	"os"
	"strings"

	"golang.org/x/tools/go/loader"
)

const eqFuncPrefix = "deriveEqual"

func generateEqual(p Printer, pkgInfo *loader.PackageInfo, calls []*ast.CallExpr) {
	qual := types.RelativeTo(pkgInfo.Pkg)
	m := newTypesMap(qual)

	for _, call := range calls {
		fn, ok := call.Fun.(*ast.Ident)
		if !ok {
			continue
		}
		if !strings.HasPrefix(fn.Name, eqFuncPrefix) {
			continue
		}
		if len(call.Args) != 2 {
			fmt.Fprintf(os.Stderr, "%s does not have two arguments\n", fn.Name)
			continue
		}
		t0 := pkgInfo.TypeOf(call.Args[0])
		t1 := pkgInfo.TypeOf(call.Args[1])
		if !types.Identical(t0, t1) {
			fmt.Fprintf(os.Stderr, "%s has two arguments, but they are of different types %s != %s\n",
				fn.Name, t0, t1)
			continue
		}
		name := strings.TrimPrefix(fn.Name, eqFuncPrefix)
		qual := types.RelativeTo(pkgInfo.Pkg)
		typeStr := typeName(t0, qual)
		if typeStr != name {
			//TODO think about whether this is really necessary
			fmt.Fprintf(os.Stderr, "%s's suffix %s does not match the type %s\n",
				fn.Name, name, typeStr)
			continue
		}
		m.Set(t0, false)
	}

	eq := newEqual(p, m, qual, eqFuncPrefix)

	for _, typ := range m.List() {
		if err := eq.genFuncFor(typ); err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
		}
	}
	for _, typ := range m.List() {
		if m.Get(typ) {
			continue
		}
		if err := eq.genFuncFor(typ); err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
		}
	}
}

func newEqual(printer Printer, typesMap TypesMap, qual types.Qualifier, prefix string) *equal {
	return &equal{
		printer:  printer,
		typesMap: typesMap,
		qual:     qual,
		bytesPkg: printer.NewImport("bytes"),
		prefix:   prefix,
	}
}

type equal struct {
	printer  Printer
	typesMap TypesMap
	qual     types.Qualifier
	bytesPkg Import
	prefix   string
}

func (this *equal) funcName(typ types.Type) string {
	return eqFuncPrefix + typeName(typ, this.qual)
}

func (this *equal) genFuncFor(typ types.Type) error {
	p := this.printer
	m := this.typesMap
	m.Set(typ, true)
	typeStr := types.TypeString(typ, this.qual)
	p.P("")
	p.P("func %s(this, that %s) bool {", this.funcName(typ), typeStr)
	p.In()
	switch ttyp := typ.(type) {
	case *types.Pointer:
		ref := ttyp.Elem()
		switch tttyp := ref.Underlying().(type) {
		case *types.Struct:
			numFields := tttyp.NumFields()
			if numFields == 0 {
				p.P("return (this == nil && that == nil) || (this != nil) && (that != nil)")
			} else {
				p.P("return (this == nil && that == nil) || (this != nil) && (that != nil) &&")
			}
			p.In()
			for i := 0; i < numFields; i++ {
				field := tttyp.Field(i)
				fieldType := field.Type()
				fieldName := field.Name()
				thisField := "this." + fieldName
				thatField := "that." + fieldName
				fieldStr, err := this.field(thisField, thatField, fieldType)
				if err != nil {
					return err
				}
				if (i + 1) != numFields {
					p.P(fieldStr + " &&")
				} else {
					p.P(fieldStr)
				}
			}
			p.Out()
		case *types.Basic:
			fieldStr, err := this.field("this", "that", typ)
			if err != nil {
				return err
			}
			p.P("return " + fieldStr)
		default:
			return fmt.Errorf("unsupported: pointer is not a named struct, but %#v\n", ref)
		}
	case *types.Slice:
		p.P("if this == nil || that == nil {")
		p.In()
		p.P("return this == nil && that == nil")
		p.Out()
		p.P("}")
		p.P("if len(this) != len(that) {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.P("for i := 0; i < len(this); i++ {")
		p.In()
		eqStr, err := this.field("this[i]", "that[i]", ttyp.Elem())
		if err != nil {
			return err
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	case *types.Array:
		p.P("for i := 0; i < len(this); i++ {")
		p.In()
		eqStr, err := this.field("this[i]", "that[i]", ttyp.Elem())
		if err != nil {
			return err
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	case *types.Map:
		p.P("if this == nil || that == nil {")
		p.In()
		p.P("return this == nil && that == nil")
		p.Out()
		p.P("}")
		p.P("if len(this) != len(that) {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.P("for k, v := range this {")
		p.In()
		p.P("thatv, ok := that[k]")
		p.P("if !ok {")
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		eqStr, err := this.field("v", "thatv", ttyp.Elem())
		if err != nil {
			return err
		}
		p.P("if %s {", not(eqStr))
		p.In()
		p.P("return false")
		p.Out()
		p.P("}")
		p.Out()
		p.P("}")
		p.P("return true")
	default:
		return fmt.Errorf("unsupported type: %#v", typ)
	}
	p.Out()
	p.P("}")
	return nil
}

func not(s string) string {
	if s[0] == '(' {
		return "!" + s
	}
	return "!(" + s + ")"
}

func isComparable(tt types.Type) bool {
	t := tt.Underlying()
	switch typ := t.(type) {
	case *types.Basic:
		return typ.Kind() != types.UntypedNil
	case *types.Struct:
		for i := 0; i < typ.NumFields(); i++ {
			f := typ.Field(i)
			ft := f.Type()
			if !isComparable(ft) {
				return false
			}
		}
		return true
	case *types.Array:
		return isComparable(typ.Elem())
	}
	return false
}

func (this *equal) field(thisField, thatField string, fieldType types.Type) (string, error) {
	if isComparable(fieldType) {
		return fmt.Sprintf("%s == %s", thisField, thatField), nil
	}
	switch typ := fieldType.(type) {
	case *types.Pointer:
		ref := typ.Elem()
		if _, ok := ref.(*types.Named); ok {
			return fmt.Sprintf("%s.Equal(%s)", thisField, thatField), nil
		}
		eqStr, err := this.field("*"+thisField, "*"+thatField, ref)
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("((%[1]s == nil && %[2]s == nil) || (%[1]s != nil && %[2]s != nil && %[3]s))", thisField, thatField, eqStr), nil
	case *types.Array:
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Slice:
		if b, ok := typ.Elem().(*types.Basic); ok && b.Kind() == types.Byte {
			return fmt.Sprintf("%s.Equal(%s, %s)", this.bytesPkg(), thisField, thatField), nil
		}
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Map:
		if !this.typesMap.Get(typ) {
			this.typesMap.Set(typ, false)
		}
		return fmt.Sprintf("%s(%s, %s)", this.funcName(typ), thisField, thatField), nil
	case *types.Named:
		return fmt.Sprintf("%s.Equal(&%s)", thisField, thatField), nil
	default: // *Chan, *Tuple, *Signature, *Interface, *types.Basic.Kind() == types.UntypedNil, *Struct
		return "", fmt.Errorf("unsupported type %#v", fieldType)
	}
}
<|endoftext|>


<commit_before>package tarantool

import (
	"context"
	"errors"
	"fmt"
)

var (
	// ErrNotSupported is returned when an unimplemented query type or operation is encountered.
	ErrNotSupported = NewQueryError(ErrUnsupported, "not supported yet")
	// ErrNotInReplicaSet means that join operation can not be performed on a replica set due to missing parameters.
	ErrNotInReplicaSet = NewQueryError(0, "Full Replica Set params hasn't been set")
	// ErrBadResult means that query result was of invalid type or length.
	ErrBadResult = NewQueryError(0, "invalid result")
	// ErrVectorClock is returns in case of bad manipulation with vector clock.
	ErrVectorClock = NewQueryError(0, "vclock manipulation")
	// ErrUnknownError is returns when ErrorCode isn't OK but Error is nil in Result.
	ErrUnknownError = NewQueryError(ErrUnknown, "unknown error")
	// ErrOldVersionAnon is returns when tarantool version doesn't support anonymous replication.
	ErrOldVersionAnon = errors.New("tarantool version is too old for anonymous replication. Min version is 2.3.1")
)

// Error has Temporary method which returns true if error is temporary.
// It is useful to quickly decide retry or not retry.
type Error interface {
	error
	Temporary() bool // Temporary true if the error is temporary
}

// ConnectionError is returned when something have been happened with connection.
type ConnectionError struct {
	error
}

// NewConnectionError returns ConnectionError with message and remoteAddr in error text.
func NewConnectionError(con *Connection, message string) *ConnectionError {
	return &ConnectionError{
		error: fmt.Errorf("%s, remote: %s", message, con.remoteAddr),
	}
}

// ConnectionClosedError returns ConnectionError with message about closed connection
// or error depending on the connection state. It is also has remoteAddr in error text.
func ConnectionClosedError(con *Connection) *ConnectionError {
	var message = "Connection closed"
	if err := con.getError(); err != nil {
		message = "Connection error: " + err.Error()
	}
	return NewConnectionError(con, message)
}

// Temporary implements Error interface.
func (e *ConnectionError) Temporary() bool {
	return true
}

// Timeout implements net.Error interface.
func (e *ConnectionError) Timeout() bool {
	return false
}

// ContextError is returned when request has been ended with context timeout or cancel.
type ContextError struct {
	error
	CtxErr error
}

// NewContextError returns ContextError with message and remoteAddr in error text.
// It is also has context error itself in CtxErr.
func NewContextError(ctx context.Context, con *Connection, message string) *ContextError {
	return &ContextError{
		error:  fmt.Errorf("%s: %s, remote: %s", message, ctx.Err(), con.remoteAddr),
		CtxErr: ctx.Err(),
	}
}

// Temporary implements Error interface.
func (e *ContextError) Temporary() bool {
	return true
}

// Timeout implements net.Error interface.
func (e *ContextError) Timeout() bool {
	return e.CtxErr == context.DeadlineExceeded
}

// QueryError is returned when query error has been happened.
// It has error Code.
type QueryError struct {
	error
	Code uint
}

// NewQueryError returns QueryError with message and Code.
func NewQueryError(code uint, message string) *QueryError {
	return &QueryError{
		Code:  code,
		error: errors.New(message),
	}
}

// Temporary implements Error interface.
func (e *QueryError) Temporary() bool {
	return false
}

// Timeout implements net.Error interface.
func (e *QueryError) Timeout() bool {
	return false
}

// UnexpectedReplicaSetUUIDError is returned when ReplicaSetUUID set in Options.ReplicaSetUUID is not equal to ReplicaSetUUID
// received during Join or JoinWithSnap. It is only an AnonSlave error!
type UnexpectedReplicaSetUUIDError struct {
	QueryError
	Expected string
	Got      string
}

// NewUnexpectedReplicaSetUUIDError returns UnexpectedReplicaSetUUIDError.
func NewUnexpectedReplicaSetUUIDError(expected string, got string) *UnexpectedReplicaSetUUIDError {
	return &UnexpectedReplicaSetUUIDError{
		QueryError: *NewQueryError(ErrClusterIDMismatch, fmt.Sprintf("Replica set UUID mismatch: expected %v, got %v", expected, got)),
		Expected:   expected,
		Got:        got,
	}
}

// Is for errors comparison
func (e *UnexpectedReplicaSetUUIDError) Is(target error) bool {
	_, ok := target.(*UnexpectedReplicaSetUUIDError)
	return ok
}

var _ Error = (*ConnectionError)(nil)
var _ Error = (*QueryError)(nil)
var _ Error = (*ContextError)(nil)
var _ Error = (*UnexpectedReplicaSetUUIDError)(nil)
<commit_msg>add specific type for connection closed error<commit_after>package tarantool

import (
	"context"
	"errors"
	"fmt"
)

var (
	// ErrNotSupported is returned when an unimplemented query type or operation is encountered.
	ErrNotSupported = NewQueryError(ErrUnsupported, "not supported yet")
	// ErrNotInReplicaSet means that join operation can not be performed on a replica set due to missing parameters.
	ErrNotInReplicaSet = NewQueryError(0, "Full Replica Set params hasn't been set")
	// ErrBadResult means that query result was of invalid type or length.
	ErrBadResult = NewQueryError(0, "invalid result")
	// ErrVectorClock is returns in case of bad manipulation with vector clock.
	ErrVectorClock = NewQueryError(0, "vclock manipulation")
	// ErrUnknownError is returns when ErrorCode isn't OK but Error is nil in Result.
	ErrUnknownError = NewQueryError(ErrUnknown, "unknown error")
	// ErrOldVersionAnon is returns when tarantool version doesn't support anonymous replication.
	ErrOldVersionAnon = errors.New("tarantool version is too old for anonymous replication. Min version is 2.3.1")

	// ErrConnectionClosed returns when connection is no longer alive.
	ErrConnectionClosed = errors.New("connection closed")
)

// Error has Temporary method which returns true if error is temporary.
// It is useful to quickly decide retry or not retry.
type Error interface {
	error
	Temporary() bool // Temporary true if the error is temporary
}

// ConnectionError is returned when something have been happened with connection.
type ConnectionError struct {
	error
}

// NewConnectionError returns ConnectionError, which contains wrapped with remoteAddr error.
func NewConnectionError(con *Connection, err error) *ConnectionError {
	return &ConnectionError{
		error: fmt.Errorf("%w, remote: %s", err, con.remoteAddr),
	}
}

// ConnectionClosedError returns ConnectionError with message about closed connection
// or error depending on the connection state. It is also has remoteAddr in error text.
func ConnectionClosedError(con *Connection) *ConnectionError {
	var err = ErrConnectionClosed
	if connErr := con.getError(); connErr != nil {
		err = fmt.Errorf("%w: %v", err, connErr.Error())
	}
	return NewConnectionError(con, err)
}

// Temporary implements Error interface.
func (e *ConnectionError) Temporary() bool {
	return !errors.Is(e.error, ErrConnectionClosed)
}

// Timeout implements net.Error interface.
func (e *ConnectionError) Timeout() bool {
	return false
}

// ContextError is returned when request has been ended with context timeout or cancel.
type ContextError struct {
	error
	CtxErr error
}

// NewContextError returns ContextError with message and remoteAddr in error text.
// It is also has context error itself in CtxErr.
func NewContextError(ctx context.Context, con *Connection, message string) *ContextError {
	return &ContextError{
		error:  fmt.Errorf("%s: %s, remote: %s", message, ctx.Err(), con.remoteAddr),
		CtxErr: ctx.Err(),
	}
}

// Temporary implements Error interface.
func (e *ContextError) Temporary() bool {
	return true
}

// Timeout implements net.Error interface.
func (e *ContextError) Timeout() bool {
	return e.CtxErr == context.DeadlineExceeded
}

// QueryError is returned when query error has been happened.
// It has error Code.
type QueryError struct {
	error
	Code uint
}

// NewQueryError returns QueryError with message and Code.
func NewQueryError(code uint, message string) *QueryError {
	return &QueryError{
		Code:  code,
		error: errors.New(message),
	}
}

// Temporary implements Error interface.
func (e *QueryError) Temporary() bool {
	return false
}

// Timeout implements net.Error interface.
func (e *QueryError) Timeout() bool {
	return false
}

// UnexpectedReplicaSetUUIDError is returned when ReplicaSetUUID set in Options.ReplicaSetUUID is not equal to ReplicaSetUUID
// received during Join or JoinWithSnap. It is only an AnonSlave error!
type UnexpectedReplicaSetUUIDError struct {
	QueryError
	Expected string
	Got      string
}

// NewUnexpectedReplicaSetUUIDError returns UnexpectedReplicaSetUUIDError.
func NewUnexpectedReplicaSetUUIDError(expected string, got string) *UnexpectedReplicaSetUUIDError {
	return &UnexpectedReplicaSetUUIDError{
		QueryError: *NewQueryError(ErrClusterIDMismatch, fmt.Sprintf("Replica set UUID mismatch: expected %v, got %v", expected, got)),
		Expected:   expected,
		Got:        got,
	}
}

// Is for errors comparison
func (e *UnexpectedReplicaSetUUIDError) Is(target error) bool {
	_, ok := target.(*UnexpectedReplicaSetUUIDError)
	return ok
}

var _ Error = (*ConnectionError)(nil)
var _ Error = (*QueryError)(nil)
var _ Error = (*ContextError)(nil)
var _ Error = (*UnexpectedReplicaSetUUIDError)(nil)
<|endoftext|>


<commit_before>package jsh

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

/*
DefaultError can be customized in order to provide a more customized error
Detail message when an Internal Server Error occurs. Optionally, you can modify
a returned jsh.Error before sending it as a response as well.
*/
var DefaultErrorDetail = "Request failed, something went wrong."

// DefaultTitle can be customized to provide a more customized ISE Title
var DefaultErrorTitle = "Internal Server Error"

/*
Error consists of a number of contextual attributes to make conveying
certain error type simpler as per the JSON API specification:
http://jsonapi.org/format/#error-objects

	error := &jsh.Error{
		Title: "Authentication Failure",
		Detail: "Category 4 Username Failure",
		Status: 401
	}

	jsh.Send(w, r, error)
*/
type Error struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Status int    `json:"status"`
	Source struct {
		Pointer string `json:"pointer"`
	} `json:"source"`
	ISE string `json:"-"`
}

/*
Error will print an internal server error if set, or default back to the SafeError()
format if not. As usual, err.Error() should not be considered safe for presentation
to the end user, use err.SafeError() instead.
*/
func (e *Error) Error() string {
	if e.ISE != "" {
		return fmt.Sprintf("HTTP %d - %s", e.Status, e.ISE)
	}

	return e.SafeError()
}

/*
SafeError is a formatted error string that does not include an associated internal
server error such that it is safe to return this error message to an end user.
*/
func (e *Error) SafeError() string {
	msg := fmt.Sprintf("HTTP %d: %s - %s", e.Status, e.Title, e.Detail)
	if e.Source.Pointer != "" {
		msg += fmt.Sprintf("Source.Pointer: %s", e.Source.Pointer)
	}

	return msg
}

/*
Validate ensures that the an error meets all JSON API criteria.
*/
func (e *Error) Validate(r *http.Request, response bool) *Error {

	if e.Status < 400 || e.Status > 600 {
		return ISE(fmt.Sprintf("Invalid HTTP Status for error %+v\n", e))
	} else if e.Status == 422 && e.Source.Pointer == "" {
		return ISE(fmt.Sprintf("Source Pointer must be set for 422 Status errors"))
	}

	return nil
}

/*
ISE is a convenience function for creating a ready-to-go Internal Service Error
response. The message you pass in is set to the ErrorObject.ISE attribute so you
can gracefully log ISE's internally before sending them.
*/
func ISE(internalMessage string) *Error {
	return &Error{
		Title:  DefaultErrorTitle,
		Detail: DefaultErrorDetail,
		Status: http.StatusInternalServerError,
		ISE:    internalMessage,
	}
}

/*
InputError creates a properly formatted HTTP Status 422 error with an appropriate
user safe message. The parameter "attribute" will format err.Source.Pointer to be
"/data/attributes/<attribute>".
*/
func InputError(msg string, attribute string) *Error {
	err := &Error{
		Title:  "Invalid Attribute",
		Detail: msg,
		Status: 422,
	}

	// Assign this after the fact, easier to do
	err.Source.Pointer = fmt.Sprintf("/data/attributes/%s", strings.ToLower(attribute))

	return err
}

// SpecificationError is used whenever the Client violates the JSON API Spec
func SpecificationError(detail string) *Error {
	return &Error{
		Title:  "JSON API Specification Error",
		Detail: detail,
		Status: http.StatusNotAcceptable,
	}
}

// NotFound returns a 404 formatted error
func NotFound(resourceType string, id string) *Error {
	return &Error{
		Title:  "Not Found",
		Detail: fmt.Sprintf("No resource of type '%s' exists for ID: %s", resourceType, id),
		Status: http.StatusNotFound,
	}
}
<commit_msg>Error status should deserialise as a string.<commit_after>package jsh

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

/*
DefaultError can be customized in order to provide a more customized error
Detail message when an Internal Server Error occurs. Optionally, you can modify
a returned jsh.Error before sending it as a response as well.
*/
var DefaultErrorDetail = "Request failed, something went wrong."

// DefaultTitle can be customized to provide a more customized ISE Title
var DefaultErrorTitle = "Internal Server Error"

/*
Error consists of a number of contextual attributes to make conveying
certain error type simpler as per the JSON API specification:
http://jsonapi.org/format/#error-objects

	error := &jsh.Error{
		Title: "Authentication Failure",
		Detail: "Category 4 Username Failure",
		Status: 401
	}

	jsh.Send(w, r, error)
*/
type Error struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Status int    `json:"status,string"`
	Source struct {
		Pointer string `json:"pointer"`
	} `json:"source"`
	ISE string `json:"-"`
}

/*
Error will print an internal server error if set, or default back to the SafeError()
format if not. As usual, err.Error() should not be considered safe for presentation
to the end user, use err.SafeError() instead.
*/
func (e *Error) Error() string {
	if e.ISE != "" {
		return fmt.Sprintf("HTTP %d - %s", e.Status, e.ISE)
	}

	return e.SafeError()
}

/*
SafeError is a formatted error string that does not include an associated internal
server error such that it is safe to return this error message to an end user.
*/
func (e *Error) SafeError() string {
	msg := fmt.Sprintf("HTTP %d: %s - %s", e.Status, e.Title, e.Detail)
	if e.Source.Pointer != "" {
		msg += fmt.Sprintf("Source.Pointer: %s", e.Source.Pointer)
	}

	return msg
}

/*
Validate ensures that the an error meets all JSON API criteria.
*/
func (e *Error) Validate(r *http.Request, response bool) *Error {

	if e.Status < 400 || e.Status > 600 {
		return ISE(fmt.Sprintf("Invalid HTTP Status for error %+v\n", e))
	} else if e.Status == 422 && e.Source.Pointer == "" {
		return ISE(fmt.Sprintf("Source Pointer must be set for 422 Status errors"))
	}

	return nil
}

/*
ISE is a convenience function for creating a ready-to-go Internal Service Error
response. The message you pass in is set to the ErrorObject.ISE attribute so you
can gracefully log ISE's internally before sending them.
*/
func ISE(internalMessage string) *Error {
	return &Error{
		Title:  DefaultErrorTitle,
		Detail: DefaultErrorDetail,
		Status: http.StatusInternalServerError,
		ISE:    internalMessage,
	}
}

/*
InputError creates a properly formatted HTTP Status 422 error with an appropriate
user safe message. The parameter "attribute" will format err.Source.Pointer to be
"/data/attributes/<attribute>".
*/
func InputError(msg string, attribute string) *Error {
	err := &Error{
		Title:  "Invalid Attribute",
		Detail: msg,
		Status: 422,
	}

	// Assign this after the fact, easier to do
	err.Source.Pointer = fmt.Sprintf("/data/attributes/%s", strings.ToLower(attribute))

	return err
}

// SpecificationError is used whenever the Client violates the JSON API Spec
func SpecificationError(detail string) *Error {
	return &Error{
		Title:  "JSON API Specification Error",
		Detail: detail,
		Status: http.StatusNotAcceptable,
	}
}

// NotFound returns a 404 formatted error
func NotFound(resourceType string, id string) *Error {
	return &Error{
		Title:  "Not Found",
		Detail: fmt.Sprintf("No resource of type '%s' exists for ID: %s", resourceType, id),
		Status: http.StatusNotFound,
	}
}
<|endoftext|>


<commit_before>package glfw

//#include <GLFW/glfw3.h>
//void glfwSetErrorCallbackCB();
import "C"

const (
	NotInitialized     = C.GLFW_NOT_INITIALIZED     //GLFW has not been initialized.
	NoCurrentContext   = C.GLFW_NO_CURRENT_CONTEXT  //No context is current.
	InvalidEnum        = C.GLFW_INVALID_ENUM        //One of the enum parameters for the function was given an invalid enum.
	InvalidValue       = C.GLFW_INVALID_VALUE       //One of the parameters for the function was given an invalid value.
	OutOfMemory        = C.GLFW_OUT_OF_MEMORY       //A memory allocation failed.
	ApiUnavailable     = C.GLFW_API_UNAVAILABLE     //GLFW could not find support for the requested client API on the system.
	VersionUnavailable = C.GLFW_VERSION_UNAVAILABLE //The requested client API version is not available.
	PlatformError      = C.GLFW_PLATFORM_ERROR      //A platform-specific error occurred that does not match any of the more specific categories.
	FormatUnavailable  = C.GLFW_FORMAT_UNAVAILABLE  //The clipboard did not contain data in the requested format.
)

type goErrorFunc func(int, string)

var fErrorHolder goErrorFunc

//export goErrorCB
func goErrorCB(err C.int, desc *C.char) {
	fErrorHolder(int(err), C.GoString(desc))
}

//SetErrorCallback sets the error callback, which is called with an error code
//and a human-readable description each time a GLFW error occurs.
//
//This function may be called before Init.
//
//Function signature for this callback is: func(int, string)
func SetErrorCallback(cbfun goErrorFunc) {
	fErrorHolder = cbfun
	C.glfwSetErrorCallbackCB()
}
<commit_msg>Stricter type checks. Add ErrorCode type.<commit_after>package glfw

//#include <GLFW/glfw3.h>
//void glfwSetErrorCallbackCB();
import "C"

//ErrorCode corresponds to an error code.
type ErrorCode int

//Error codes.
const (
	NotInitialized     ErrorCode = C.GLFW_NOT_INITIALIZED     //GLFW has not been initialized.
	NoCurrentContext   ErrorCode = C.GLFW_NO_CURRENT_CONTEXT  //No context is current.
	InvalidEnum        ErrorCode = C.GLFW_INVALID_ENUM        //One of the enum parameters for the function was given an invalid enum.
	InvalidValue       ErrorCode = C.GLFW_INVALID_VALUE       //One of the parameters for the function was given an invalid value.
	OutOfMemory        ErrorCode = C.GLFW_OUT_OF_MEMORY       //A memory allocation failed.
	ApiUnavailable     ErrorCode = C.GLFW_API_UNAVAILABLE     //GLFW could not find support for the requested client API on the system.
	VersionUnavailable ErrorCode = C.GLFW_VERSION_UNAVAILABLE //The requested client API version is not available.
	PlatformError      ErrorCode = C.GLFW_PLATFORM_ERROR      //A platform-specific error occurred that does not match any of the more specific categories.
	FormatUnavailable  ErrorCode = C.GLFW_FORMAT_UNAVAILABLE  //The clipboard did not contain data in the requested format.
)

type goErrorFunc func(ErrorCode, string)

var fErrorHolder goErrorFunc

//export goErrorCB
func goErrorCB(err C.int, desc *C.char) {
	fErrorHolder(ErrorCode(err), C.GoString(desc))
}

//SetErrorCallback sets the error callback, which is called with an error code
//and a human-readable description each time a GLFW error occurs.
//
//This function may be called before Init.
//
//Function signature for this callback is: func(int, string)
func SetErrorCallback(cbfun goErrorFunc) {
	fErrorHolder = cbfun
	C.glfwSetErrorCallbackCB()
}
<|endoftext|>