<commit_before>package mixpanel

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

var IgnoreTime *time.Time = &time.Time{}

type MixpanelError struct {
	URL string
	Err error
}

func (err *MixpanelError) Cause() error {
	return err.Err
}

func (err *MixpanelError) Error() string {
	return "mixpanel: " + err.Err.Error()
}

type ErrTrackFailed struct {
	Body string
	Resp *http.Response
}

func (err *ErrTrackFailed) Error() string {
	return fmt.Sprintf("Mixpanel did not return 1 when tracking: %s", err.Body)
}

// The Mixapanel struct store the mixpanel endpoint and the project token
type Mixpanel interface {
	// Create a mixpanel event
	Track(distinctId, eventName string, e *Event) error

	// Set properties for a mixpanel user.
	Update(distinctId string, u *Update) error

	Alias(distinctId, newId string) error
}

// The Mixapanel struct store the mixpanel endpoint and the project token
type mixpanel struct {
	Client *http.Client
	Token  string
	ApiURL string
}

// A mixpanel event
type Event struct {
	// IP-address of the user. Leave empty to use autodetect, or set to "0" to
	// not specify an ip-address.
	IP string

	// Timestamp. Set to nil to use the current time.
	Timestamp *time.Time

	// Custom properties. At least one must be specified.
	Properties map[string]interface{}
}

// An update of a user in mixpanel
type Update struct {
	// IP-address of the user. Leave empty to use autodetect, or set to "0" to
	// not specify an ip-address at all.
	IP string

	// Timestamp. Set to nil to use the current time, or IgnoreTime to not use a
	// timestamp.
	Timestamp *time.Time

	// Update operation such as "$set", "$update" etc.
	Operation string

	// Custom properties. At least one must be specified.
	Properties map[string]interface{}
}

// Track create a events to current distinct id
func (m *mixpanel) Alias(distinctId, newId string) error {
	props := map[string]interface{}{
		"token":       m.Token,
		"distinct_id": distinctId,
		"alias":       newId,
	}

	params := map[string]interface{}{
		"event":      "$create_alias",
		"properties": props,
	}

	return m.send("track", params, false)
}

// Track create a events to current distinct id
func (m *mixpanel) Track(distinctId, eventName string, e *Event) error {
	props := map[string]interface{}{
		"token":       m.Token,
		"distinct_id": distinctId,
	}
	if e.IP != "" {
		props["ip"] = e.IP
	}
	if e.Timestamp != nil {
		props["time"] = e.Timestamp.Unix()
	}

	for key, value := range e.Properties {
		props[key] = value
	}

	params := map[string]interface{}{
		"event":      eventName,
		"properties": props,
	}

	autoGeolocate := e.IP == ""

	return m.send("track", params, autoGeolocate)
}

// Updates a user in mixpanel. See
// https://mixpanel.com/help/reference/http#people-analytics-updates
func (m *mixpanel) Update(distinctId string, u *Update) error {
	params := map[string]interface{}{
		"$token":       m.Token,
		"$distinct_id": distinctId,
	}

	if u.IP != "" {
		params["$ip"] = u.IP
	}
	if u.Timestamp == IgnoreTime {
		params["$ignore_time"] = true
	} else if u.Timestamp != nil {
		params["$time"] = u.Timestamp.Unix()
	}

	params[u.Operation] = u.Properties

	autoGeolocate := u.IP == ""

	return m.send("engage", params, autoGeolocate)
}

func (m *mixpanel) to64(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

func (m *mixpanel) send(eventType string, params interface{}, autoGeolocate bool) error {
	data, err := json.Marshal(params)

	if err != nil {
		return err
	}

	url := m.ApiURL + "/" + eventType + "?data=" + m.to64(data)

	if autoGeolocate {
		url += "&ip=1"
	}

	wrapErr := func(err error) error {
		return &MixpanelError{URL: url, Err: err}
	}

	resp, err := m.Client.Get(url)

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

	defer resp.Body.Close()

	body, bodyErr := ioutil.ReadAll(resp.Body)

	if bodyErr != nil {
		return wrapErr(bodyErr)
	}

	if strBody := string(body); strBody != "1" && strBody != "1\n" {
		return wrapErr(&ErrTrackFailed{Body: strBody, Resp: resp})
	}

	return nil
}

// New returns the client instance. If apiURL is blank, the default will be used
// ("https://api.mixpanel.com").
func New(token, apiURL string) Mixpanel {
	return NewFromClient(http.DefaultClient, token, apiURL)
}

// Creates a client instance using the specified client instance. This is useful
// when using a proxy.
func NewFromClient(c *http.Client, token, apiURL string) Mixpanel {
	if apiURL == "" {
		apiURL = "https://api.mixpanel.com"
	}

	return &mixpanel{
		Client: c,
		Token:  token,
		ApiURL: apiURL,
	}
}
<commit_msg>Fix some method comments<commit_after>package mixpanel

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

var IgnoreTime *time.Time = &time.Time{}

type MixpanelError struct {
	URL string
	Err error
}

func (err *MixpanelError) Cause() error {
	return err.Err
}

func (err *MixpanelError) Error() string {
	return "mixpanel: " + err.Err.Error()
}

type ErrTrackFailed struct {
	Body string
	Resp *http.Response
}

func (err *ErrTrackFailed) Error() string {
	return fmt.Sprintf("Mixpanel did not return 1 when tracking: %s", err.Body)
}

// The Mixapanel struct store the mixpanel endpoint and the project token
type Mixpanel interface {
	// Create a mixpanel event
	Track(distinctId, eventName string, e *Event) error

	// Set properties for a mixpanel user.
	Update(distinctId string, u *Update) error

	// Create an alias for an existing distinct id
	Alias(distinctId, newId string) error
}

// The Mixapanel struct store the mixpanel endpoint and the project token
type mixpanel struct {
	Client *http.Client
	Token  string
	ApiURL string
}

// A mixpanel event
type Event struct {
	// IP-address of the user. Leave empty to use autodetect, or set to "0" to
	// not specify an ip-address.
	IP string

	// Timestamp. Set to nil to use the current time.
	Timestamp *time.Time

	// Custom properties. At least one must be specified.
	Properties map[string]interface{}
}

// An update of a user in mixpanel
type Update struct {
	// IP-address of the user. Leave empty to use autodetect, or set to "0" to
	// not specify an ip-address at all.
	IP string

	// Timestamp. Set to nil to use the current time, or IgnoreTime to not use a
	// timestamp.
	Timestamp *time.Time

	// Update operation such as "$set", "$update" etc.
	Operation string

	// Custom properties. At least one must be specified.
	Properties map[string]interface{}
}

// Alias create an alias for an existing distinct id
func (m *mixpanel) Alias(distinctId, newId string) error {
	props := map[string]interface{}{
		"token":       m.Token,
		"distinct_id": distinctId,
		"alias":       newId,
	}

	params := map[string]interface{}{
		"event":      "$create_alias",
		"properties": props,
	}

	return m.send("track", params, false)
}

// Track create an event for an existing distinct id
func (m *mixpanel) Track(distinctId, eventName string, e *Event) error {
	props := map[string]interface{}{
		"token":       m.Token,
		"distinct_id": distinctId,
	}
	if e.IP != "" {
		props["ip"] = e.IP
	}
	if e.Timestamp != nil {
		props["time"] = e.Timestamp.Unix()
	}

	for key, value := range e.Properties {
		props[key] = value
	}

	params := map[string]interface{}{
		"event":      eventName,
		"properties": props,
	}

	autoGeolocate := e.IP == ""

	return m.send("track", params, autoGeolocate)
}

// Update updates a user in mixpanel. See
// https://mixpanel.com/help/reference/http#people-analytics-updates
func (m *mixpanel) Update(distinctId string, u *Update) error {
	params := map[string]interface{}{
		"$token":       m.Token,
		"$distinct_id": distinctId,
	}

	if u.IP != "" {
		params["$ip"] = u.IP
	}
	if u.Timestamp == IgnoreTime {
		params["$ignore_time"] = true
	} else if u.Timestamp != nil {
		params["$time"] = u.Timestamp.Unix()
	}

	params[u.Operation] = u.Properties

	autoGeolocate := u.IP == ""

	return m.send("engage", params, autoGeolocate)
}

func (m *mixpanel) to64(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

func (m *mixpanel) send(eventType string, params interface{}, autoGeolocate bool) error {
	data, err := json.Marshal(params)

	if err != nil {
		return err
	}

	url := m.ApiURL + "/" + eventType + "?data=" + m.to64(data)

	if autoGeolocate {
		url += "&ip=1"
	}

	wrapErr := func(err error) error {
		return &MixpanelError{URL: url, Err: err}
	}

	resp, err := m.Client.Get(url)

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

	defer resp.Body.Close()

	body, bodyErr := ioutil.ReadAll(resp.Body)

	if bodyErr != nil {
		return wrapErr(bodyErr)
	}

	if strBody := string(body); strBody != "1" && strBody != "1\n" {
		return wrapErr(&ErrTrackFailed{Body: strBody, Resp: resp})
	}

	return nil
}

// New returns the client instance. If apiURL is blank, the default will be used
// ("https://api.mixpanel.com").
func New(token, apiURL string) Mixpanel {
	return NewFromClient(http.DefaultClient, token, apiURL)
}

// Creates a client instance using the specified client instance. This is useful
// when using a proxy.
func NewFromClient(c *http.Client, token, apiURL string) Mixpanel {
	if apiURL == "" {
		apiURL = "https://api.mixpanel.com"
	}

	return &mixpanel{
		Client: c,
		Token:  token,
		ApiURL: apiURL,
	}
}
<|endoftext|>


<commit_before>// Package bitutils provides a collection of utilities to deal with bits.
package bitutils

import (
	"fmt"
)

// W is the length of a machine word.
const W = 64

// Magic constants.
const (
	lowers2 = 0x5555555555555555
	lowers4 = 0x3333333333333333
	lowers8 = 0x0f0f0f0f0f0f0f0f
	lowest8 = 0x0101010101010101
)

// Word represents a 64-bit binary string.
type Word uint64

// exp2[i] is 2^i.
var exp2 [W]Word

func init() {
	for i := 0; i < len(exp2); i++ {
		exp2[i] = Word(1) << uint(i)
	}
}

// String returns binary string w[0]w[1]...w[63].
func (w Word) String() string {
	return fmt.Sprintf("%064b", w)
}

// Count1 returns the number of ones contained in w.
func (w Word) Count1() int {
	w -= (w >> 1) & lowers2
	w = (w & lowers4) + ((w >> 2) & lowers4)
	w = (w + (w >> 4)) & lowers8
	return int((w * lowest8) >> 56)
}

// Count0 returns the number of zeros contained in w.
func (w Word) Count0() int {
	return W - w.Count1()
}

// Count returns the number of b[0]'s contained in w.
func (w Word) Count(b int) int {
	m := Word(0) - (Word(b^1) & Word(1))
	return (w ^ m).Count1()
}

// Get returns w[i].
func (w Word) Get(i int) Word {
	w = w >> uint(i)
	return w & exp2[0]
}

// Set1 sets w[i] to 1.
func (w Word) Set1(i int) Word {
	return w | exp2[i]
}

// Set0 sets w[i] to 0.
func (w Word) Set0(i int) Word {
	return w & ^exp2[i]
}

// Flip flips w[i].
func (w Word) Flip(i int) Word {
	return w ^ exp2[i]
}

// Rank1 returns the number of ones in w[0]...w[i].
func (w Word) Rank1(i int) int {
	w = w << uint(W-i-1)
	return w.Count1()
}

// Rank0 returns the number of zeros in w[0]...w[i].
func (w Word) Rank0(i int) int {
	w = ^w << uint(W-i-1)
	return w.Count1()
}
<commit_msg>Refactor Count<commit_after>// Package bitutils provides a collection of utilities to deal with bits.
package bitutils

import (
	"fmt"
)

// W is the length of a machine word.
const W = 64

// Magic constants.
const (
	lowers2 = 0x5555555555555555
	lowers4 = 0x3333333333333333
	lowers8 = 0x0f0f0f0f0f0f0f0f
	lowest8 = 0x0101010101010101
)

// Word represents a 64-bit binary string.
type Word uint64

// exp2[i] is 2^i.
var exp2 [W]Word

func init() {
	for i := 0; i < len(exp2); i++ {
		exp2[i] = Word(1) << uint(i)
	}
}

// String returns binary string w[0]w[1]...w[63].
func (w Word) String() string {
	return fmt.Sprintf("%064b", w)
}

// Count1 returns the number of ones contained in w.
func (w Word) Count1() int {
	w -= (w >> 1) & lowers2
	w = (w & lowers4) + ((w >> 2) & lowers4)
	w = (w + (w >> 4)) & lowers8
	return int((w * lowest8) >> 56)
}

// Count0 returns the number of zeros contained in w.
func (w Word) Count0() int {
	return W - w.Count1()
}

// Count returns the number of b[0]'s contained in w.
func (w Word) Count(b int) int {
	w = w ^ (^Word(0) + Word(b))
	return w.Count1()
}

// Get returns w[i].
func (w Word) Get(i int) Word {
	w = w >> uint(i)
	return w & exp2[0]
}

// Set1 sets w[i] to 1.
func (w Word) Set1(i int) Word {
	return w | exp2[i]
}

// Set0 sets w[i] to 0.
func (w Word) Set0(i int) Word {
	return w & ^exp2[i]
}

// Flip flips w[i].
func (w Word) Flip(i int) Word {
	return w ^ exp2[i]
}

// Rank1 returns the number of ones in w[0]...w[i].
func (w Word) Rank1(i int) int {
	w = w << uint(W-i-1)
	return w.Count1()
}

// Rank0 returns the number of zeros in w[0]...w[i].
func (w Word) Rank0(i int) int {
	w = ^w << uint(W-i-1)
	return w.Count1()
}
<|endoftext|>


<commit_before>package bloomapi

import (
	"fmt"
	"net/http/pprof"
	"github.com/gorilla/mux"
	"github.com/codegangsta/negroni"
	"gopkg.in/unrolled/render.v1"
	"github.com/spf13/viper"
	"github.com/gocodo/bloomdb"
)

var r = render.New(render.Options{})
var bdb *bloomdb.BloomDatabase

func Server() {
	fmt.Println("Running Server")

	bdb = bloomdb.CreateDB()
	router := mux.NewRouter()

	router.HandleFunc("/api/search", SearchHandler).Methods("GET")
	router.HandleFunc("/api/npis/{npi:[0-9]+}", NpiHandler).Methods("GET")
	router.HandleFunc("/api/sources", SourcesHandler).Methods("GET")
	router.HandleFunc("/api/search/{source}", SearchSourceHandler).Methods("GET")
	router.HandleFunc("/api/sources/{source}/{id}", ItemHandler).Methods("GET")

  /*runtime.SetBlockProfileRate(1)
	dr := router.PathPrefix("/debug/pprof").Subrouter()
	dr.HandleFunc("/", pprof.Index)
	dr.HandleFunc("/cmdline", pprof.Cmdline)
	dr.HandleFunc("/profile", pprof.Profile)
	dr.HandleFunc("/symbol", pprof.Symbol)
	dr.HandleFunc("/block", pprof.Handler("block").ServeHTTP)
	dr.HandleFunc("/heap", pprof.Handler("heap").ServeHTTP)
	dr.HandleFunc("/goroutine", pprof.Handler("goroutine").ServeHTTP)
	dr.HandleFunc("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)*/

	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":" + viper.GetString("bloomapiPort"))
}
<commit_msg>removing dependency on net/http/pprof<commit_after>package bloomapi

import (
	"fmt"
	"github.com/gorilla/mux"
	"github.com/codegangsta/negroni"
	"gopkg.in/unrolled/render.v1"
	"github.com/spf13/viper"
	"github.com/gocodo/bloomdb"
)

var r = render.New(render.Options{})
var bdb *bloomdb.BloomDatabase

func Server() {
	fmt.Println("Running Server")

	bdb = bloomdb.CreateDB()
	router := mux.NewRouter()

	router.HandleFunc("/api/search", SearchHandler).Methods("GET")
	router.HandleFunc("/api/npis/{npi:[0-9]+}", NpiHandler).Methods("GET")
	router.HandleFunc("/api/sources", SourcesHandler).Methods("GET")
	router.HandleFunc("/api/search/{source}", SearchSourceHandler).Methods("GET")
	router.HandleFunc("/api/sources/{source}/{id}", ItemHandler).Methods("GET")

  /*runtime.SetBlockProfileRate(1)
	dr := router.PathPrefix("/debug/pprof").Subrouter()
	dr.HandleFunc("/", pprof.Index)
	dr.HandleFunc("/cmdline", pprof.Cmdline)
	dr.HandleFunc("/profile", pprof.Profile)
	dr.HandleFunc("/symbol", pprof.Symbol)
	dr.HandleFunc("/block", pprof.Handler("block").ServeHTTP)
	dr.HandleFunc("/heap", pprof.Handler("heap").ServeHTTP)
	dr.HandleFunc("/goroutine", pprof.Handler("goroutine").ServeHTTP)
	dr.HandleFunc("/threadcreate", pprof.Handler("threadcreate").ServeHTTP)*/

	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":" + viper.GetString("bloomapiPort"))
}
<|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 net

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

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		defer ln.Close()
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	switch runtime.GOOS {
	case "windows", "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer func() {
		ln.Close()
		os.Remove(tmpname)
	}()

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}

func TestTCPClose(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	l, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer l.Close()

	read := func(r io.Reader) error {
		var m [1]byte
		_, err := r.Read(m[:])
		return err
	}

	go func() {
		c, err := Dial("tcp", l.Addr().String())
		if err != nil {
			t.Fatal(err)
		}

		go read(c)

		time.Sleep(10 * time.Millisecond)
		c.Close()
	}()

	c, err := l.Accept()
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	for err == nil {
		err = read(c)
	}
	if err != nil && err != io.EOF {
		t.Fatal(err)
	}
}

func TestErrorNil(t *testing.T) {
	c, err := Dial("tcp", "127.0.0.1:65535")
	if err == nil {
		t.Fatal("Dial 127.0.0.1:65535 succeeded")
	}
	if c != nil {
		t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
	}

	// Make Listen fail by relistening on the same address.
	l, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal("Listen 127.0.0.1:0: %v", err)
	}
	defer l.Close()
	l1, err := Listen("tcp", l.Addr().String())
	if err == nil {
		t.Fatal("second Listen %v: %v", l.Addr(), err)
	}
	if l1 != nil {
		t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
	}

	// Make ListenPacket fail by relistening on the same address.
	lp, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatal("Listen 127.0.0.1:0: %v", err)
	}
	defer lp.Close()
	lp1, err := ListenPacket("udp", lp.LocalAddr().String())
	if err == nil {
		t.Fatal("second Listen %v: %v", lp.LocalAddr(), err)
	}
	if lp1 != nil {
		t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
	}
}
<commit_msg>net: fix nits found by go tool vet<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.

package net

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

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		defer ln.Close()
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	switch runtime.GOOS {
	case "windows", "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer func() {
		ln.Close()
		os.Remove(tmpname)
	}()

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}

func TestTCPClose(t *testing.T) {
	switch runtime.GOOS {
	case "plan9":
		t.Skipf("skipping test on %q", runtime.GOOS)
	}
	l, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer l.Close()

	read := func(r io.Reader) error {
		var m [1]byte
		_, err := r.Read(m[:])
		return err
	}

	go func() {
		c, err := Dial("tcp", l.Addr().String())
		if err != nil {
			t.Fatal(err)
		}

		go read(c)

		time.Sleep(10 * time.Millisecond)
		c.Close()
	}()

	c, err := l.Accept()
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	for err == nil {
		err = read(c)
	}
	if err != nil && err != io.EOF {
		t.Fatal(err)
	}
}

func TestErrorNil(t *testing.T) {
	c, err := Dial("tcp", "127.0.0.1:65535")
	if err == nil {
		t.Fatal("Dial 127.0.0.1:65535 succeeded")
	}
	if c != nil {
		t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
	}

	// Make Listen fail by relistening on the same address.
	l, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen 127.0.0.1:0: %v", err)
	}
	defer l.Close()
	l1, err := Listen("tcp", l.Addr().String())
	if err == nil {
		t.Fatalf("second Listen %v: %v", l.Addr(), err)
	}
	if l1 != nil {
		t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
	}

	// Make ListenPacket fail by relistening on the same address.
	lp, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen 127.0.0.1:0: %v", err)
	}
	defer lp.Close()
	lp1, err := ListenPacket("udp", lp.LocalAddr().String())
	if err == nil {
		t.Fatalf("second Listen %v: %v", lp.LocalAddr(), err)
	}
	if lp1 != nil {
		t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/mg/i"
	"math"
	"os"
	"regexp"
)

type gene struct {
	atEnd bool
	data  []interface{}
	cur   string
}

func Gene(pattern string) i.Forward {
	r := regexp.MustCompile("[()]")
	tokens := r.Split(pattern, -1)
	g := gene{atEnd: false, data: make([]interface{}, 0, len(tokens))}
	for i, v := range tokens {
		if math.Mod(float64(i), 2) == 0 {
			// constant
			if v != "" {
				g.data = append(g.data, v)
			}
		} else {
			// option
			if v != "" {
				option := make([]interface{}, 0, len(v)+1)
				option = append(option, 0)
				for _, c := range v {
					option = append(option, string(c))
				}
				g.data = append(g.data, option)
			}
		}
	}
	g.Next()
	return &g
}

func (g *gene) Error() error {
	return nil
}

func (g *gene) Value() interface{} {
	return g.cur
}

func (g *gene) AtEnd() bool {
	return g.cur == ""
}

func (g *gene) Next() error {
	if g.atEnd {
		g.cur = ""
		return nil
	}
	finishedIncr := false
	var result bytes.Buffer
	for _, t := range g.data {
		if v, ok := t.(string); ok {
			result.WriteString(v)
		} else if v, ok := t.([]interface{}); ok {
			n := v[0].(int)
			result.WriteString(v[n+1].(string))
			if !finishedIncr {
				if n == len(v)-2 {
					v[0] = 0
				} else {
					v[0] = v[0].(int) + 1
					finishedIncr = true
				}
			}
		}
	}
	g.atEnd = !finishedIncr
	g.cur = result.String()
	return nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("Usage %s PATTERN\n", os.Args[0])
		os.Exit(0)
	}

	i.Each(
		Gene(os.Args[1]),
		func(itr i.Iterator) bool {
			fmt.Println(itr.Value())
			return true
		})
}
<commit_msg>genes: add SetError()<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/mg/i"
	"math"
	"os"
	"regexp"
)

type gene struct {
	atEnd bool
	data  []interface{}
	cur   string
}

func Gene(pattern string) i.Forward {
	r := regexp.MustCompile("[()]")
	tokens := r.Split(pattern, -1)
	g := gene{atEnd: false, data: make([]interface{}, 0, len(tokens))}
	for i, v := range tokens {
		if math.Mod(float64(i), 2) == 0 {
			// constant
			if v != "" {
				g.data = append(g.data, v)
			}
		} else {
			// option
			if v != "" {
				option := make([]interface{}, 0, len(v)+1)
				option = append(option, 0)
				for _, c := range v {
					option = append(option, string(c))
				}
				g.data = append(g.data, option)
			}
		}
	}
	g.Next()
	return &g
}

func (g *gene) Error() error {
	return nil
}

func (g *gene) SetError(err error) {
}

func (g *gene) Value() interface{} {
	return g.cur
}

func (g *gene) AtEnd() bool {
	return g.cur == ""
}

func (g *gene) Next() error {
	if g.atEnd {
		g.cur = ""
		return nil
	}
	finishedIncr := false
	var result bytes.Buffer
	for _, t := range g.data {
		if v, ok := t.(string); ok {
			result.WriteString(v)
		} else if v, ok := t.([]interface{}); ok {
			n := v[0].(int)
			result.WriteString(v[n+1].(string))
			if !finishedIncr {
				if n == len(v)-2 {
					v[0] = 0
				} else {
					v[0] = v[0].(int) + 1
					finishedIncr = true
				}
			}
		}
	}
	g.atEnd = !finishedIncr
	g.cur = result.String()
	return nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("Usage %s PATTERN\n", os.Args[0])
		os.Exit(0)
	}

	i.Each(
		Gene(os.Args[1]),
		func(itr i.Iterator) bool {
			fmt.Println(itr.Value())
			return true
		})
}
<|endoftext|>


<commit_before>package admin

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/jinzhu/gorm"
	"github.com/qor/media_library"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/config"
	"github.com/qor/qor-example/db"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/transition"
	"github.com/qor/qor/utils"
	"github.com/qor/qor/validations"
)

var Admin *admin.Admin
var Countries = []string{"China", "Japan", "USA"}

func init() {
	Admin = admin.New(&qor.Config{DB: db.Publish.DraftDB()})
	Admin.SetSiteName("Qor DEMO")
	Admin.SetAuth(Auth{})

	// Add Dashboard
	Admin.AddMenu(&admin.Menu{Name: "Dashboard", Link: "/admin"})

	// Add Asset Manager, for rich editor
	assetManager := Admin.AddResource(&media_library.AssetManager{}, &admin.Config{Invisible: true})

	// Add Product
	product := Admin.AddResource(&models.Product{}, &admin.Config{Menu: []string{"Product Management"}})
	product.Meta(&admin.Meta{Name: "MadeCountry", Type: "select_one", Collection: Countries})
	product.Meta(&admin.Meta{Name: "Description", Type: "rich_editor", Resource: assetManager})
	sizeVariation := Admin.NewResource(&models.SizeVariation{}, &admin.Config{Invisible: true})
	sizeVariation.NewAttrs("-ColorVariation")
	sizeVariation.EditAttrs(
		&admin.Section{
			Rows: [][]string{
				{"Size", "AvailableQuantity"},
			},
		},
	)
	colorVariation := Admin.NewResource(&models.ColorVariation{}, &admin.Config{Invisible: true})
	colorVariation.Meta(&admin.Meta{Name: "SizeVariations", Resource: sizeVariation})
	colorVariation.NewAttrs("-Product")
	colorVariation.EditAttrs("-Product")
	product.Meta(&admin.Meta{Name: "ColorVariations", Resource: colorVariation})
	product.SearchAttrs("Name", "Code", "Category.Name", "Brand.Name")
	product.EditAttrs(
		&admin.Section{
			Title: "Basic Information",
			Rows: [][]string{
				{"Name"},
				{"Code", "Price"},
			}},
		&admin.Section{
			Title: "Organization",
			Rows: [][]string{
				{"Category", "Collections", "MadeCountry"},
			}},
		"Description",
		"ColorVariations",
	)

	for _, country := range Countries {
		var country = country
		product.Scope(&admin.Scope{Name: country, Group: "Made Country", Handle: func(db *gorm.DB, ctx *qor.Context) *gorm.DB {
			return db.Where("made_country = ?", country)
		}})
	}

	product.IndexAttrs("-ColorVariations")

	Admin.AddResource(&models.Color{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Size{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Category{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Collection{}, &admin.Config{Menu: []string{"Product Management"}})

	// Add Order
	orderItem := Admin.NewResource(&models.OrderItem{})
	orderItem.Meta(&admin.Meta{Name: "SizeVariation", Type: "select_one", Collection: sizeVariationCollection})

	order := Admin.AddResource(&models.Order{}, &admin.Config{Menu: []string{"Order Management"}})
	order.Meta(&admin.Meta{Name: "ShippingAddress", Type: "single_edit"})
	order.Meta(&admin.Meta{Name: "BillingAddress", Type: "single_edit"})
	order.Meta(&admin.Meta{Name: "ShippedAt", Type: "date"})
	order.Meta(&admin.Meta{Name: "OrderItems", Resource: orderItem})

	// define scopes for Order
	for _, state := range []string{"checkout", "cancelled", "paid", "paid_cancelled", "processing", "shipped", "returned"} {
		var state = state
		order.Scope(&admin.Scope{
			Name:  state,
			Label: strings.Title(strings.Replace(state, "_", " ", -1)),
			Group: "Order Status",
			Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
				return db.Where(models.Order{Transition: transition.Transition{State: state}})
			},
		})
	}
	order.IndexAttrs("-DiscountValue", "-OrderItems", "-AbandonedReason")
	order.NewAttrs("-DiscountValue", "-AbandonedReason")
	order.EditAttrs("-DiscountValue", "-AbandonedReason")
	order.ShowAttrs("-DiscountValue", "-AbandonedReason")
	order.SearchAttrs("User.Name", "User.Email", "ShippingAddress.ContactName", "ShippingAddress.Address1", "ShippingAddress.Address2")

	// Define another resource for same model
	abandonedOrder := Admin.AddResource(&models.Order{}, &admin.Config{Name: "Abandoned Order", Menu: []string{"Order Management"}})
	abandonedOrder.Meta(&admin.Meta{Name: "ShippingAddress", Type: "single_edit"})
	abandonedOrder.Meta(&admin.Meta{Name: "BillingAddress", Type: "single_edit"})

	// Define default scope for abandoned orders
	abandonedOrder.Scope(&admin.Scope{
		Default: true,
		Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
			return db.Where("abandoned_reason IS NOT NULL AND abandoned_reason <> ?", "")
		},
	})

	// Define scopes for abandoned orders
	for _, amount := range []int{5000, 10000, 20000} {
		var amount = amount
		abandonedOrder.Scope(&admin.Scope{
			Name:  fmt.Sprint(amount),
			Group: "Amount Greater Than",
			Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
				return db.Where("payment_amount > ?", amount)
			},
		})
	}

	abandonedOrder.IndexAttrs("-ShippingAddress", "-BillingAddress", "-DiscountValue", "-OrderItems")
	abandonedOrder.NewAttrs("-DiscountValue")
	abandonedOrder.EditAttrs("-DiscountValue")
	abandonedOrder.ShowAttrs("-DiscountValue")

	// Add Store
	store := Admin.AddResource(&models.Store{}, &admin.Config{Menu: []string{"Store Management"}})
	store.AddValidator(func(record interface{}, metaValues *resource.MetaValues, context *qor.Context) error {
		if meta := metaValues.Get("Name"); meta != nil {
			if name := utils.ToString(meta.Value); strings.TrimSpace(name) == "" {
				return validations.NewError(record, "Name", "Name can't be blank")
			}
		}
		return nil
	})

	// Add Translations
	Admin.AddResource(config.Config.I18n, &admin.Config{Menu: []string{"Site Management"}})

	// Add Setting
	Admin.AddResource(&models.Setting{}, &admin.Config{Singleton: true})

	// Add User
	user := Admin.AddResource(&models.User{})
	user.IndexAttrs("ID", "Email", "Name", "Gender", "Role")

	// Add Publish
	Admin.AddResource(db.Publish, &admin.Config{Singleton: true})

	initFuncMap()
	initRouter()
}

func sizeVariationCollection(resource interface{}, context *qor.Context) (results [][]string) {
	for _, sizeVariation := range models.SizeVariations() {
		results = append(results, []string{strconv.Itoa(int(sizeVariation.ID)), sizeVariation.Stringify()})
	}
	return
}
<commit_msg>Use Meta.Resource after register meta<commit_after>package admin

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/jinzhu/gorm"
	"github.com/qor/media_library"
	"github.com/qor/qor"
	"github.com/qor/qor-example/app/models"
	"github.com/qor/qor-example/config"
	"github.com/qor/qor-example/db"
	"github.com/qor/qor/admin"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/transition"
	"github.com/qor/qor/utils"
	"github.com/qor/qor/validations"
)

var Admin *admin.Admin
var Countries = []string{"China", "Japan", "USA"}

func init() {
	Admin = admin.New(&qor.Config{DB: db.Publish.DraftDB()})
	Admin.SetSiteName("Qor DEMO")
	Admin.SetAuth(Auth{})

	// Add Dashboard
	Admin.AddMenu(&admin.Menu{Name: "Dashboard", Link: "/admin"})

	// Add Asset Manager, for rich editor
	assetManager := Admin.AddResource(&media_library.AssetManager{}, &admin.Config{Invisible: true})

	// Add Product
	product := Admin.AddResource(&models.Product{}, &admin.Config{Menu: []string{"Product Management"}})
	product.Meta(&admin.Meta{Name: "MadeCountry", Type: "select_one", Collection: Countries})
	product.Meta(&admin.Meta{Name: "Description", Type: "rich_editor", Resource: assetManager})

	colorVariationMeta := product.Meta(&admin.Meta{Name: "ColorVariations"})
	colorVariation := colorVariationMeta.Resource
	colorVariation.NewAttrs("-Product")
	colorVariation.EditAttrs("-Product")

	sizeVariationMeta := colorVariation.Meta(&admin.Meta{Name: "SizeVariations"})
	sizeVariation := sizeVariationMeta.Resource
	sizeVariation.NewAttrs("-ColorVariation")
	sizeVariation.EditAttrs(
		&admin.Section{
			Rows: [][]string{
				{"Size", "AvailableQuantity"},
			},
		},
	)

	product.SearchAttrs("Name", "Code", "Category.Name", "Brand.Name")
	product.EditAttrs(
		&admin.Section{
			Title: "Basic Information",
			Rows: [][]string{
				{"Name"},
				{"Code", "Price"},
			}},
		&admin.Section{
			Title: "Organization",
			Rows: [][]string{
				{"Category", "Collections", "MadeCountry"},
			}},
		"Description",
		"ColorVariations",
	)

	for _, country := range Countries {
		var country = country
		product.Scope(&admin.Scope{Name: country, Group: "Made Country", Handle: func(db *gorm.DB, ctx *qor.Context) *gorm.DB {
			return db.Where("made_country = ?", country)
		}})
	}

	product.IndexAttrs("-ColorVariations")

	Admin.AddResource(&models.Color{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Size{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Category{}, &admin.Config{Menu: []string{"Product Management"}})
	Admin.AddResource(&models.Collection{}, &admin.Config{Menu: []string{"Product Management"}})

	// Add Order
	order := Admin.AddResource(&models.Order{}, &admin.Config{Menu: []string{"Order Management"}})
	order.Meta(&admin.Meta{Name: "ShippingAddress", Type: "single_edit"})
	order.Meta(&admin.Meta{Name: "BillingAddress", Type: "single_edit"})
	order.Meta(&admin.Meta{Name: "ShippedAt", Type: "date"})

	orderItemMeta := order.Meta(&admin.Meta{Name: "OrderItems"})
	orderItemMeta.Resource.Meta(&admin.Meta{Name: "SizeVariation", Type: "select_one", Collection: sizeVariationCollection})

	// define scopes for Order
	for _, state := range []string{"checkout", "cancelled", "paid", "paid_cancelled", "processing", "shipped", "returned"} {
		var state = state
		order.Scope(&admin.Scope{
			Name:  state,
			Label: strings.Title(strings.Replace(state, "_", " ", -1)),
			Group: "Order Status",
			Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
				return db.Where(models.Order{Transition: transition.Transition{State: state}})
			},
		})
	}
	order.IndexAttrs("-DiscountValue", "-OrderItems", "-AbandonedReason")
	order.NewAttrs("-DiscountValue", "-AbandonedReason")
	order.EditAttrs("-DiscountValue", "-AbandonedReason")
	order.ShowAttrs("-DiscountValue", "-AbandonedReason")
	order.SearchAttrs("User.Name", "User.Email", "ShippingAddress.ContactName", "ShippingAddress.Address1", "ShippingAddress.Address2")

	// Define another resource for same model
	abandonedOrder := Admin.AddResource(&models.Order{}, &admin.Config{Name: "Abandoned Order", Menu: []string{"Order Management"}})
	abandonedOrder.Meta(&admin.Meta{Name: "ShippingAddress", Type: "single_edit"})
	abandonedOrder.Meta(&admin.Meta{Name: "BillingAddress", Type: "single_edit"})

	// Define default scope for abandoned orders
	abandonedOrder.Scope(&admin.Scope{
		Default: true,
		Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
			return db.Where("abandoned_reason IS NOT NULL AND abandoned_reason <> ?", "")
		},
	})

	// Define scopes for abandoned orders
	for _, amount := range []int{5000, 10000, 20000} {
		var amount = amount
		abandonedOrder.Scope(&admin.Scope{
			Name:  fmt.Sprint(amount),
			Group: "Amount Greater Than",
			Handle: func(db *gorm.DB, context *qor.Context) *gorm.DB {
				return db.Where("payment_amount > ?", amount)
			},
		})
	}

	abandonedOrder.IndexAttrs("-ShippingAddress", "-BillingAddress", "-DiscountValue", "-OrderItems")
	abandonedOrder.NewAttrs("-DiscountValue")
	abandonedOrder.EditAttrs("-DiscountValue")
	abandonedOrder.ShowAttrs("-DiscountValue")

	// Add Store
	store := Admin.AddResource(&models.Store{}, &admin.Config{Menu: []string{"Store Management"}})
	store.AddValidator(func(record interface{}, metaValues *resource.MetaValues, context *qor.Context) error {
		if meta := metaValues.Get("Name"); meta != nil {
			if name := utils.ToString(meta.Value); strings.TrimSpace(name) == "" {
				return validations.NewError(record, "Name", "Name can't be blank")
			}
		}
		return nil
	})

	// Add Translations
	Admin.AddResource(config.Config.I18n, &admin.Config{Menu: []string{"Site Management"}})

	// Add Setting
	Admin.AddResource(&models.Setting{}, &admin.Config{Singleton: true})

	// Add User
	user := Admin.AddResource(&models.User{})
	user.IndexAttrs("ID", "Email", "Name", "Gender", "Role")

	// Add Publish
	Admin.AddResource(db.Publish, &admin.Config{Singleton: true})

	initFuncMap()
	initRouter()
}

func sizeVariationCollection(resource interface{}, context *qor.Context) (results [][]string) {
	for _, sizeVariation := range models.SizeVariations() {
		results = append(results, []string{strconv.Itoa(int(sizeVariation.ID)), sizeVariation.Stringify()})
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

// This file defines miscellaneous structs and utility methods that are used
// throughout the system.

// Contributors: Jeff Overbey

package doctor

import (
	"fmt"
	"strconv"
)

// An OffsetLength consists of two integers: a 0-based offset and a nonnegative
// length.  An OffsetLength is used to specify a region of a string or file.
// For example, given the string "ABCDEFG", the substring CDE could be
// specified by
//     OffsetLength{offset: 2, length: 3}
type OffsetLength struct {
	Offset int `json:"offset"`
	Length int `json:"length"`
}

func (o *OffsetLength) OffsetPastEnd() int {
	return o.Offset + o.Length
}

func (o *OffsetLength) String() string {
	return "offset " + strconv.Itoa(o.Offset) +
		", length " + strconv.Itoa(o.Length)
}

// A TextSelection represents a selection in a text editor.  It consists of a
// filename, the line/column where the selected text begins, and the
// line/column where the text selection ends.  The end line and column must be
// greater than or equal to the start line and column, respectively.  Line and
// column numbers are 1-based.
type TextSelection struct {
	Filename  string
	StartLine int
	StartCol  int
	EndLine   int
	EndCol    int
}

func (s *TextSelection) String() string {
	return fmt.Sprintf("%s:%d,%d:%d,%d",
		s.Filename, s.StartLine, s.StartCol, s.EndLine, s.EndCol)
}

func (s *TextSelection) ShortString() string {
	return fmt.Sprintf("%d,%d:%d,%d",
		s.StartLine, s.StartCol, s.EndLine, s.EndCol)
}

func digraphClosure(digraph [][]int) [][]int {
	if !validateGraph(digraph) {
		panic("invalid graph")
	}
	result := make([][]int, len(digraph))
	index := make([]int, len(digraph))
	lowlink := make([]int, len(digraph))
	stack := []int{}
	nextIndex := 1
	var scc func(v int)
	scc = func(v int) {
		result[v] = []int{v}
		index[v] = nextIndex
		lowlink[v] = nextIndex
		nextIndex++
		stack = append(stack, v)
		for _, w := range digraph[v] {
			if index[w] == 0 {
				scc(w)
				lowlink[v] = min(lowlink[v], lowlink[w])
			} else if contains(stack, w) {
				lowlink[v] = min(lowlink[v], lowlink[w])
			}
			result[v] = union(result[v], result[w])
		}
		if lowlink[v] == index[v] {
			for {
				w := stack[len(stack)-1]
				stack = stack[0 : len(stack)-1]
				result[w] = result[v]
				if w == v {
					break
				}
			}
		}
	}
	for i, _ := range digraph {
		if index[i] == 0 {
			scc(i)
		}
	}
	return result
}

func validateGraph(digraph [][]int) bool {
	for _, adj := range digraph {
		for _, idx := range adj {
			if idx < 0 || idx >= len(digraph) {
				return false
			}
		}
	}
	return true
}

func union(u, v []int) []int {
	result := make([]int, len(u), len(u)+len(v))
	copy(result, u)
	for _, value := range v {
		if !contains(result, value) {
			result = append(result, value)
		}
	}
	return result
}

func contains(slice []int, value int) bool {
	for _, v := range slice {
		if v == value {
			return true
		}
	}
	return false
}
<commit_msg>Fixed typo in Tarjan SCC implementation<commit_after>// Copyright 2013 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.

// This file defines miscellaneous structs and utility methods that are used
// throughout the system.

// Contributors: Jeff Overbey

package doctor

import (
	"fmt"
	"strconv"
)

// An OffsetLength consists of two integers: a 0-based offset and a nonnegative
// length.  An OffsetLength is used to specify a region of a string or file.
// For example, given the string "ABCDEFG", the substring CDE could be
// specified by
//     OffsetLength{offset: 2, length: 3}
type OffsetLength struct {
	Offset int `json:"offset"`
	Length int `json:"length"`
}

func (o *OffsetLength) OffsetPastEnd() int {
	return o.Offset + o.Length
}

func (o *OffsetLength) String() string {
	return "offset " + strconv.Itoa(o.Offset) +
		", length " + strconv.Itoa(o.Length)
}

// A TextSelection represents a selection in a text editor.  It consists of a
// filename, the line/column where the selected text begins, and the
// line/column where the text selection ends.  The end line and column must be
// greater than or equal to the start line and column, respectively.  Line and
// column numbers are 1-based.
type TextSelection struct {
	Filename  string
	StartLine int
	StartCol  int
	EndLine   int
	EndCol    int
}

func (s *TextSelection) String() string {
	return fmt.Sprintf("%s:%d,%d:%d,%d",
		s.Filename, s.StartLine, s.StartCol, s.EndLine, s.EndCol)
}

func (s *TextSelection) ShortString() string {
	return fmt.Sprintf("%d,%d:%d,%d",
		s.StartLine, s.StartCol, s.EndLine, s.EndCol)
}

func digraphClosure(digraph [][]int) [][]int {
	if !validateGraph(digraph) {
		panic("invalid graph")
	}
	result := make([][]int, len(digraph))
	index := make([]int, len(digraph))
	lowlink := make([]int, len(digraph))
	stack := []int{}
	nextIndex := 1
	var scc func(v int)
	scc = func(v int) {
		result[v] = []int{v}
		index[v] = nextIndex
		lowlink[v] = nextIndex
		nextIndex++
		stack = append(stack, v)
		for _, w := range digraph[v] {
			if index[w] == 0 {
				scc(w)
				lowlink[v] = min(lowlink[v], lowlink[w])
			} else if contains(stack, w) {
				lowlink[v] = min(lowlink[v], index[w])
			}
			result[v] = union(result[v], result[w])
		}
		if lowlink[v] == index[v] {
			for {
				w := stack[len(stack)-1]
				stack = stack[0 : len(stack)-1]
				result[w] = result[v]
				if w == v {
					break
				}
			}
		}
	}
	for i, _ := range digraph {
		if index[i] == 0 {
			scc(i)
		}
	}
	return result
}

func validateGraph(digraph [][]int) bool {
	for _, adj := range digraph {
		for _, idx := range adj {
			if idx < 0 || idx >= len(digraph) {
				return false
			}
		}
	}
	return true
}

func union(u, v []int) []int {
	result := make([]int, len(u), len(u)+len(v))
	copy(result, u)
	for _, value := range v {
		if !contains(result, value) {
			result = append(result, value)
		}
	}
	return result
}

func contains(slice []int, value int) bool {
	for _, v := range slice {
		if v == value {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package config

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

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

func init() {
	configDirectoryPath = "./tmp"
}

func TestDefaultDatabasePathIsSetWhenConfigIsEmpty(t *testing.T) {
	rmdirConfig()
	config, err := ReadConfig()
	if err != nil {
		t.Fatal(err)
	}
	assert.NotEmpty(t, config.DatabasePath)
}

func TestCanSetDatabasePath(t *testing.T) {
	rmdirConfig()
	config, err := ReadConfig()
	if err != nil {
		t.Fatal(err)
	}
	config.DatabasePath = "foo"
	err = config.WriteConfig()
	if err != nil {
		t.Fatal(err)
	}
	contents, err := ioutil.ReadFile(configFilePath())
	if err != nil {
		t.Fatal(err)
	}
	rmdirConfig()
	assert.True(t, strings.IndexAny(string(contents), "foo") >= 0)
}

func mkdirConfig() {
	err := os.MkdirAll(configDirectoryPath, 0700)
	if err != nil {
		panic(err)
	}
}

func rmdirConfig() {
	err := os.RemoveAll(configDirectoryPath)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Collapse err checking to one line<commit_after>package config

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

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

func init() {
	configDirectoryPath = "./tmp"
}

func TestDefaultDatabasePathIsSetWhenConfigIsEmpty(t *testing.T) {
	rmdirConfig()
	config, err := ReadConfig()
	if err != nil {
		t.Fatal(err)
	}
	assert.NotEmpty(t, config.DatabasePath)
}

func TestCanSetDatabasePath(t *testing.T) {
	rmdirConfig()
	config, err := ReadConfig()
	if err != nil {
		t.Fatal(err)
	}
	config.DatabasePath = "foo"
	err = config.WriteConfig()
	if err != nil {
		t.Fatal(err)
	}
	contents, err := ioutil.ReadFile(configFilePath())
	if err != nil {
		t.Fatal(err)
	}
	rmdirConfig()
	assert.True(t, strings.IndexAny(string(contents), "foo") >= 0)
}

func mkdirConfig() {
	if err := os.MkdirAll(configDirectoryPath, 0700); err != nil {
		panic(err)
	}
}

func rmdirConfig() {
	if err := os.RemoveAll(configDirectoryPath); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package hstspreload

import (
	"fmt"
	"sync"
	"testing"
)

func ExamplePreloadableDomain() {
	header, issues := PreloadableDomain("wikipedia.org")
	if header != nil {
		fmt.Printf("Header: %s", *header)
	}
	fmt.Printf("Issues %v", issues)
}

/******** Utility functions tests. ********/

var testCheckDomainFormatTests = []struct {
	domain   string
	expected Issues
}{
	{".example.com",
		Issues{Errors: []Issue{{Code: "domain.format.begins_with_dot"}}},
	},
	{"example.com.",
		Issues{Errors: []Issue{{Code: "domain.format.ends_with_dot"}}},
	},
	{"example..com",
		Issues{Errors: []Issue{{Code: "domain.format.contains_double_dot"}}},
	},
	{"example",
		Issues{Errors: []Issue{{Code: "domain.format.only_one_label"}}},
	},
	{"example&co.com",
		Issues{Errors: []Issue{{Code: "domain.format.invalid_characters"}}},
	},
}

func TestCheckDomainFormat(t *testing.T) {
	for _, tt := range testCheckDomainFormatTests {
		issues := checkDomainFormat(tt.domain)
		if !issues.Match(tt.expected) {
			t.Errorf(issuesShouldMatch, issues, tt.expected)
		}
	}
}

var testPreloadableDomainLevel = []struct {
	domain   string
	expected Issues
}{
	{"github.io",
		Issues{Errors: []Issue{{
			Code: "internal.domain.name.cannot_compute_etld1",
		}}},
	},
	{"example.com",
		Issues{},
	},
	{"example.co.uk",
		Issues{},
	},
	{"subdomain.example.com",
		Issues{Errors: []Issue{{
			Code:    "domain.is_subdomain",
			Message: "`subdomain.example.com` is a subdomain. Please preload `example.com` instead. (Due to the size of the preload list and the behaviour of cookies across subdomains, we only accept automated preload list submissions of whole registered domains.)",
		}}},
	},
}

func TestPreloadableDomainLevel(t *testing.T) {
	for _, tt := range testPreloadableDomainLevel {
		issues := preloadableDomainLevel(tt.domain)
		if !issues.Match(tt.expected) {
			t.Errorf(issuesShouldMatch, issues, tt.expected)
		}
	}
}

/******** Real domain tests. ********/

// Avoid hitting the network for short tests.
// This gives us performant, deterministic, and offline testing.
func skipIfShort(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping domain test.")
	}
}

type preloadableDomainTest struct {
	function       func(domain string) (*string, Issues)
	description    string
	domain         string
	expectHeader   bool
	expectedHeader string
	expectedIssues Issues
}

var preloadableDomainTests = []preloadableDomainTest{

	/********* PreloadableDomain() ********/

	{
		PreloadableDomain,
		"valid HSTS",
		"wikipedia.org",
		true, "max-age=31536000; includeSubDomains; preload",
		Issues{},
	},
	{
		PreloadableDomain,
		"no TLS",
		"neverssl.com",
		false, "",
		Issues{
			Errors: []Issue{{Code: "domain.tls.cannot_connect"}},
		},
	},
	{
		PreloadableDomain,
		"incomplete chain",
		"incomplete-chain.badssl.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "domain.is_subdomain"},
				{
					Code:    "domain.tls.invalid_cert_chain",
					Message: "https://incomplete-chain.badssl.com uses an incomplete or invalid certificate chain. Check out your site at https://www.ssllabs.com/ssltest/",
				},
			},
		},
	},
	{
		PreloadableDomain,
		"www.no_tls (not whitelisted)",
		"lgarron.github.io",
		false, "",
		Issues{
			Errors: []Issue{
				Issue{Code: "response.no_header", Summary: "No HSTS header", Message: "Response error: No HSTS header is present on the response."},
				Issue{Code: "domain.www.no_tls", Summary: "www subdomain does not support HTTPS", Message: "Domain error: The www subdomain exists, but we couldn't connect to it using HTTPS (\"x509: certificate is valid for www.github.com, *.github.com, github.com, *.github.io, github.io, *.githubusercontent.com, githubusercontent.com, not www.lgarron.github.io\"). Since many people type this by habit, HSTS preloading would likely cause issues for your site."},
			},
		},
	},
	{
		PreloadableDomain,
		"www.no_tls whitelisted",
		"hstspreload.appspot.com",
		true, "max-age=31536000; includeSubDomains; preload",
		Issues{},
	},
	{
		PreloadableDomain,
		"self-signed",
		"self-signed.badssl.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "domain.is_subdomain"},
				{
					Code:    "domain.tls.invalid_cert_chain",
					Message: "https://self-signed.badssl.com uses an incomplete or invalid certificate chain. Check out your site at https://www.ssllabs.com/ssltest/",
				},
			},
		},
	},
	{
		PreloadableDomain,
		"SHA-1",
		"sha1.badssl.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "domain.is_subdomain"},
				{
					Code:    "domain.tls.sha1",
					Message: "One or more of the certificates in your certificate chain is signed using SHA-1. This needs to be replaced. See https://security.googleblog.com/2015/12/an-update-on-sha-1-certificates-in.html. (The first SHA-1 certificate found has a common-name of \"*.badssl.com\".)",
				},
				{Code: "response.no_header"},
			},
		},
	},
	{
		PreloadableDomain,
		"subdomain",
		"en.wikipedia.org",
		true, "max-age=31536000; includeSubDomains; preload",
		Issues{Errors: []Issue{{
			Code:    "domain.is_subdomain",
			Message: "`en.wikipedia.org` is a subdomain. Please preload `wikipedia.org` instead. (Due to the size of the preload list and the behaviour of cookies across subdomains, we only accept automated preload list submissions of whole registered domains.)",
		}}},
	},
	{
		PreloadableDomain,
		"no HSTS",
		"example.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "response.no_header"},
				{
					Code:    "redirects.http.no_redirect",
					Message: "`http://example.com` does not redirect to `https://example.com`.",
				},
			},
		},
	},
	{
		PreloadableDomain,
		"bogus domain",
		"example.notadomain",
		false, "",
		Issues{Errors: []Issue{{Code: "domain.tls.cannot_connect"}}},
	},

	/******** RemovableDomain() ********/

	{
		RemovableDomain,
		"no header",
		"example.com",
		false, "",
		Issues{Errors: []Issue{{Code: "response.no_header"}}},
	},
	{
		RemovableDomain,
		"no preload directive",
		"hsts.badssl.com",
		true, "max-age=15768000; includeSubDomains",
		Issues{},
	},
	{
		RemovableDomain,
		"preloaded",
		"preloaded-hsts.badssl.com",
		true, "max-age=15768000; includeSubDomains; preload",
		Issues{Errors: []Issue{{Code: "header.removable.contains.preload"}}},
	},
}

func TestPreloadableDomainAndRemovableDomain(t *testing.T) {
	skipIfShort(t)
	t.Parallel()

	wg := sync.WaitGroup{}
	wg.Add(len(preloadableDomainTests))

	for _, tt := range preloadableDomainTests {
		go func(tt preloadableDomainTest) {
			header, issues := tt.function(tt.domain)

			if tt.expectHeader {
				if header == nil {
					t.Errorf("[%s] %s: Did not receive exactly one HSTS header", tt.description, tt.domain)
				} else if *header != tt.expectedHeader {
					t.Errorf(`[%s] %s: Did not receive expected header.
				Actual: "%v"
				Expected: "%v"`, tt.description, tt.domain, *header, tt.expectedHeader)
				}
			} else {
				if header != nil {
					t.Errorf("[%s] %s: Did not expect a header, but received `%s`", tt.description, tt.domain, *header)
				}
			}

			if !issues.Match(tt.expectedIssues) {
				t.Errorf("[%s] %s: "+issuesShouldMatch, tt.description, tt.domain, issues, tt.expectedIssues)
			}
			wg.Done()
		}(tt)
	}

	wg.Wait()
}
<commit_msg>Disable broken tests.<commit_after>package hstspreload

import (
	"fmt"
	"sync"
	"testing"
)

func ExamplePreloadableDomain() {
	header, issues := PreloadableDomain("wikipedia.org")
	if header != nil {
		fmt.Printf("Header: %s", *header)
	}
	fmt.Printf("Issues %v", issues)
}

/******** Utility functions tests. ********/

var testCheckDomainFormatTests = []struct {
	domain   string
	expected Issues
}{
	{".example.com",
		Issues{Errors: []Issue{{Code: "domain.format.begins_with_dot"}}},
	},
	{"example.com.",
		Issues{Errors: []Issue{{Code: "domain.format.ends_with_dot"}}},
	},
	{"example..com",
		Issues{Errors: []Issue{{Code: "domain.format.contains_double_dot"}}},
	},
	{"example",
		Issues{Errors: []Issue{{Code: "domain.format.only_one_label"}}},
	},
	{"example&co.com",
		Issues{Errors: []Issue{{Code: "domain.format.invalid_characters"}}},
	},
}

func TestCheckDomainFormat(t *testing.T) {
	for _, tt := range testCheckDomainFormatTests {
		issues := checkDomainFormat(tt.domain)
		if !issues.Match(tt.expected) {
			t.Errorf(issuesShouldMatch, issues, tt.expected)
		}
	}
}

var testPreloadableDomainLevel = []struct {
	domain   string
	expected Issues
}{
	{"github.io",
		Issues{Errors: []Issue{{
			Code: "internal.domain.name.cannot_compute_etld1",
		}}},
	},
	{"example.com",
		Issues{},
	},
	{"example.co.uk",
		Issues{},
	},
	{"subdomain.example.com",
		Issues{Errors: []Issue{{
			Code:    "domain.is_subdomain",
			Message: "`subdomain.example.com` is a subdomain. Please preload `example.com` instead. (Due to the size of the preload list and the behaviour of cookies across subdomains, we only accept automated preload list submissions of whole registered domains.)",
		}}},
	},
}

func TestPreloadableDomainLevel(t *testing.T) {
	for _, tt := range testPreloadableDomainLevel {
		issues := preloadableDomainLevel(tt.domain)
		if !issues.Match(tt.expected) {
			t.Errorf(issuesShouldMatch, issues, tt.expected)
		}
	}
}

/******** Real domain tests. ********/

// Avoid hitting the network for short tests.
// This gives us performant, deterministic, and offline testing.
func skipIfShort(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping domain test.")
	}
}

type preloadableDomainTest struct {
	function       func(domain string) (*string, Issues)
	description    string
	domain         string
	expectHeader   bool
	expectedHeader string
	expectedIssues Issues
}

var preloadableDomainTests = []preloadableDomainTest{

	/********* PreloadableDomain() ********/

	{
		PreloadableDomain,
		"valid HSTS",
		"wikipedia.org",
		true, "max-age=31536000; includeSubDomains; preload",
		Issues{},
	},
	{
		PreloadableDomain,
		"no TLS",
		"neverssl.com",
		false, "",
		Issues{
			Errors: []Issue{{Code: "domain.tls.cannot_connect"}},
		},
	},
	{
		PreloadableDomain,
		"incomplete chain",
		"incomplete-chain.badssl.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "domain.is_subdomain"},
				{
					Code:    "domain.tls.invalid_cert_chain",
					Message: "https://incomplete-chain.badssl.com uses an incomplete or invalid certificate chain. Check out your site at https://www.ssllabs.com/ssltest/",
				},
			},
		},
	},
	{
		PreloadableDomain,
		"www.no_tls (not whitelisted)",
		"lgarron.github.io",
		false, "",
		Issues{
			Errors: []Issue{
				Issue{Code: "response.no_header", Summary: "No HSTS header", Message: "Response error: No HSTS header is present on the response."},
				Issue{Code: "domain.www.no_tls", Summary: "www subdomain does not support HTTPS", Message: "Domain error: The www subdomain exists, but we couldn't connect to it using HTTPS (\"x509: certificate is valid for www.github.com, *.github.com, github.com, *.github.io, github.io, *.githubusercontent.com, githubusercontent.com, not www.lgarron.github.io\"). Since many people type this by habit, HSTS preloading would likely cause issues for your site."},
			},
		},
	},
	// {
	// 	PreloadableDomain,
	// 	"www.no_tls whitelisted",
	// 	"hstspreload.appspot.com",
	// 	true, "max-age=31536000; includeSubDomains; preload",
	// 	Issues{},
	// },
	{
		PreloadableDomain,
		"self-signed",
		"self-signed.badssl.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "domain.is_subdomain"},
				{
					Code:    "domain.tls.invalid_cert_chain",
					Message: "https://self-signed.badssl.com uses an incomplete or invalid certificate chain. Check out your site at https://www.ssllabs.com/ssltest/",
				},
			},
		},
	},
	// {
	// 	PreloadableDomain,
	// 	"SHA-1",
	// 	"sha1.badssl.com",
	// 	false, "",
	// 	Issues{
	// 		Errors: []Issue{
	// 			{Code: "domain.is_subdomain"},
	// 			{
	// 				Code:    "domain.tls.sha1",
	// 				Message: "One or more of the certificates in your certificate chain is signed using SHA-1. This needs to be replaced. See https://security.googleblog.com/2015/12/an-update-on-sha-1-certificates-in.html. (The first SHA-1 certificate found has a common-name of \"*.badssl.com\".)",
	// 			},
	// 			{Code: "response.no_header"},
	// 		},
	// 	},
	// },
	{
		PreloadableDomain,
		"subdomain",
		"en.wikipedia.org",
		true, "max-age=31536000; includeSubDomains; preload",
		Issues{Errors: []Issue{{
			Code:    "domain.is_subdomain",
			Message: "`en.wikipedia.org` is a subdomain. Please preload `wikipedia.org` instead. (Due to the size of the preload list and the behaviour of cookies across subdomains, we only accept automated preload list submissions of whole registered domains.)",
		}}},
	},
	{
		PreloadableDomain,
		"no HSTS",
		"example.com",
		false, "",
		Issues{
			Errors: []Issue{
				{Code: "response.no_header"},
				{
					Code:    "redirects.http.no_redirect",
					Message: "`http://example.com` does not redirect to `https://example.com`.",
				},
			},
		},
	},
	{
		PreloadableDomain,
		"bogus domain",
		"example.notadomain",
		false, "",
		Issues{Errors: []Issue{{Code: "domain.tls.cannot_connect"}}},
	},

	/******** RemovableDomain() ********/

	{
		RemovableDomain,
		"no header",
		"example.com",
		false, "",
		Issues{Errors: []Issue{{Code: "response.no_header"}}},
	},
	{
		RemovableDomain,
		"no preload directive",
		"hsts.badssl.com",
		true, "max-age=15768000; includeSubDomains",
		Issues{},
	},
	{
		RemovableDomain,
		"preloaded",
		"preloaded-hsts.badssl.com",
		true, "max-age=15768000; includeSubDomains; preload",
		Issues{Errors: []Issue{{Code: "header.removable.contains.preload"}}},
	},
}

func TestPreloadableDomainAndRemovableDomain(t *testing.T) {
	skipIfShort(t)
	t.Parallel()

	wg := sync.WaitGroup{}
	wg.Add(len(preloadableDomainTests))

	for _, tt := range preloadableDomainTests {
		go func(tt preloadableDomainTest) {
			header, issues := tt.function(tt.domain)

			if tt.expectHeader {
				if header == nil {
					t.Errorf("[%s] %s: Did not receive exactly one HSTS header", tt.description, tt.domain)
				} else if *header != tt.expectedHeader {
					t.Errorf(`[%s] %s: Did not receive expected header.
				Actual: "%v"
				Expected: "%v"`, tt.description, tt.domain, *header, tt.expectedHeader)
				}
			} else {
				if header != nil {
					t.Errorf("[%s] %s: Did not expect a header, but received `%s`", tt.description, tt.domain, *header)
				}
			}

			if !issues.Match(tt.expectedIssues) {
				t.Errorf("[%s] %s: "+issuesShouldMatch, tt.description, tt.domain, issues, tt.expectedIssues)
			}
			wg.Done()
		}(tt)
	}

	wg.Wait()
}
<|endoftext|>


<commit_before>package edit

import (
	"fmt"
	"os"
	"time"
)

var (
	// EscTimeout is the amount of time after which an \033 (\x1b) character is
	// parsed as a standalone Esc key press instead of starting an escape
	// sequence. Modern terminal emulators send escape sequences very fast, so
	// 10ms is more than sufficient. SSH connections on a slow link can be
	// problematic,
	EscTimeout = 10 * time.Millisecond
)

// Special rune values used in the return value of (*Reader).ReadRune.
const (
	// No rune received before specified time.
	runeTimeout rune = -1 - iota
	// Error occured in AsyncReader. The error is left at the readError field.
	runeReadError
)

// Reader converts a stream of runes into a stream of OneRead's.
type Reader struct {
	ar        *AsyncReader
	keyChan   chan Key
	cprChan   chan pos
	mouseChan chan mouseEvent
	errChan   chan error
	quit      chan struct{}
}

type mouseEvent struct {
	pos
	down   bool
	button int
	mod    Mod
}

// BadEscSeq indicates that a escape sequence has been read from the terminal,
// but it cannot be parsed.
type BadEscSeq struct {
	seq string
	msg string
}

func newBadEscSeq(seq string, msg string) *BadEscSeq {
	return &BadEscSeq{seq, msg}
}

func (bes *BadEscSeq) Error() string {
	return fmt.Sprintf("bad escape sequence %q: %s", bes.seq, bes.msg)
}

// NewReader creates a new Reader on the given terminal file.
func NewReader(f *os.File) *Reader {
	rd := &Reader{
		NewAsyncReader(f),
		make(chan Key),
		make(chan pos),
		make(chan mouseEvent),
		make(chan error),
		nil,
	}
	return rd
}

// KeyChan returns the channel onto which the Reader writes Keys it has read.
func (rd *Reader) KeyChan() <-chan Key {
	return rd.keyChan
}

// CPRChan returns the channel onto which the Reader writes CPRs it has read.
func (rd *Reader) CPRChan() <-chan pos {
	return rd.cprChan
}

// MouseChan returns the channel onto which the Reader writes mouse events it
// has read.
func (rd *Reader) MouseChan() <-chan mouseEvent {
	return rd.mouseChan
}

// ErrorChan returns the channel onto which the Reader writes errors it came
// across during the reading process.
func (rd *Reader) ErrorChan() <-chan error {
	return rd.errChan
}

// Run runs the Reader. It blocks until Quit is called and should be called in
// a separate goroutine.
func (rd *Reader) Run() {
	runes := rd.ar.Chan()
	rd.quit = make(chan struct{})
	go rd.ar.Run()

	for {
		select {
		case r := <-runes:
			rd.readOne(r)
		case <-rd.quit:
			return
		}
	}
}

// Quit terminates the loop of Run.
func (rd *Reader) Quit() {
	rd.ar.Quit()
	close(rd.quit)
}

// Close releases files associated with the Reader. It does not close the file
// used to create it.
func (rd *Reader) Close() {
	rd.ar.Close()
}

// readOne attempts to read one key or CPR, led by a rune already read.
func (rd *Reader) readOne(r rune) {
	var k Key
	var cpr pos
	var mouse mouseEvent
	var err error
	var currentSeq string

	// readRune attempts to read a rune within the predefined timeout. It
	// writes to the err and currentSeq variable in the outer scope.
	readRune :=
		func(d time.Duration) rune {
			select {
			case r := <-rd.ar.Chan():
				currentSeq += string(r)
				return r
			case err = <-rd.ar.ErrorChan():
				return runeReadError
			case <-After(d):
				return runeTimeout
			}
		}

	defer func() {
		if k != (Key{}) {
			select {
			case rd.keyChan <- k:
			case <-rd.quit:
			}
		} else if cpr != (pos{}) {
			select {
			case rd.cprChan <- cpr:
			case <-rd.quit:
			}
		} else if mouse != (mouseEvent{}) {
			select {
			case rd.mouseChan <- mouse:
			case <-rd.quit:
			}
		}
		if err != nil {
			select {
			case rd.errChan <- err:
			case <-rd.quit:
			}
		}
	}()

	switch r {
	case Tab, Enter, Backspace:
		k = Key{r, 0}
	case 0x0:
		k = Key{'`', Ctrl} // ^@
	case 0x1d:
		k = Key{'6', Ctrl} // ^^
	case 0x1f:
		k = Key{'/', Ctrl} // ^_
	case 0x1b: // ^[ Escape
		r2 := readRune(EscTimeout)
		if r2 == runeTimeout || r2 == runeReadError {
			k = Key{'[', Ctrl}
			break
		}
		switch r2 {
		case '[':
			// CSI style function key sequence, looks like [\d;]*[^\d;]
			// Read numeric parameters (if any)
			nums := make([]int, 1, 2)
			seq := "\x1b["
			timeout := EscTimeout
			isMouse := false
		CSISeq:
			for {
				r = readRune(timeout)
				// Timeout can only happen at first readRune.
				if r == runeTimeout || r == runeReadError {
					k = Key{'[', Alt}
					return
				}
				seq += string(r)
				// After first rune read we turn off the timeout
				timeout = -1
				switch {
				case r == ';':
					nums = append(nums, 0)
				case r == '<':
					isMouse = true
				case '0' <= r && r <= '9':
					cur := len(nums) - 1
					nums[cur] = nums[cur]*10 + int(r-'0')
				default:
					break CSISeq
				}
			}
			if r == 'R' {
				// CPR
				if len(nums) != 2 {
					err = newBadEscSeq(currentSeq, "bad CPR")
					return
				}
				cpr = pos{nums[0], nums[1]}
			} else if isMouse && (r == 'm' || r == 'M') {
				if len(nums) != 3 {
					err = newBadEscSeq(currentSeq, "bad mouse event")
					return
				}
				down := r == 'M'
				n0 := nums[0]
				button := n0 & 3
				mod := Mod(0)
				if n0&4 != 0 {
					mod |= Shift
				}
				if n0&8 != 0 {
					mod |= Alt
				}
				if n0&16 != 0 {
					mod |= Ctrl
				}
				mouse = mouseEvent{pos{nums[2], nums[1]}, down, button, mod}
			} else {
				k, err = parseCSI(nums, r, seq)
			}
		case 'O':
			// G3 style function key sequence: read one rune.
			r = readRune(EscTimeout)
			if r == runeTimeout || r == runeReadError {
				k = Key{r2, Alt}
				return
			}
			r, ok := g3Seq[r]
			if ok {
				k = Key{r, 0}
			} else {
				err = newBadEscSeq(currentSeq, "bad G3")
			}
		default:
			k = Key{r2, Alt}
		}
	default:
		// Sane Ctrl- sequences that agree with the keyboard...
		if 0x1 <= r && r <= 0x1d {
			k = Key{r + 0x40, Ctrl}
		} else {
			k = Key{r, 0}
		}
	}
}

// G3-style key sequences: \eO followed by exactly one character. For instance,
// \eOP is F1.
var g3Seq = map[rune]rune{
	// F1-F4: xterm, libvte and tmux
	'P': F1, 'Q': F2,
	'R': F3, 'S': F4,

	// Home and End: libvte
	'H': Home, 'F': End,
}

// Tables for CSI-style key sequences, which are \e[ followed by a list of
// semicolon-delimited numeric arguments, before being concluded by a
// non-numeric, non-semicolon rune.

// CSI-style key sequences that can be identified based on the ending rune. For
// instance, \e[A is Up.
var keyByLast = map[rune]Key{
	'A': Key{Up, 0}, 'B': Key{Down, 0},
	'C': Key{Right, 0}, 'D': Key{Left, 0},
	'H': Key{Home, 0}, 'F': Key{End, 0},
	'Z': Key{Tab, Shift},
}

// CSI-style key sequences ending with '~' and can be identified based on
// the only number argument. For instance, \e[1~ is Home.
var keyByNum0 = map[int]rune{
	1: Home, 2: Insert, 3: Delete, 4: End, 5: PageUp, 6: PageDown,
	11: F1, 12: F2, 13: F3, 14: F4,
	15: F5, 17: F6, 18: F7, 19: F8, 20: F9, 21: F10, 23: F11, 24: F12,
}

// CSI-style key sequences ending with '~', with 27 as the first numeric
// argument. For instance, \e[27;9~ is Tab.
//
// The list is taken blindly from tmux source xterm-keys.c. I don't have a
// keyboard-terminal combination that generate such sequences, but assumably
// some PC keyboard with a numpad can.
var keyByNum2 = map[int]rune{
	9: '\t', 13: '\r',
	33: '!', 35: '#', 39: '\'', 40: '(', 41: ')', 43: '+', 44: ',', 45: '-',
	46: '.',
	48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7',
	56: '8', 57: '9',
	58: ':', 59: ';', 60: '<', 61: '=', 62: '>', 63: ';',
}

// parseCSI parses a CSI-style key sequence.
func parseCSI(nums []int, last rune, seq string) (Key, error) {
	if k, ok := keyByLast[last]; ok {
		if len(nums) == 0 {
			// Unmodified: \e[A (Up)
			return k, nil
		} else if len(nums) == 2 && nums[0] == 1 {
			// Modified: \e[1;5A (Ctrl-Up)
			return xtermModify(k, nums[1], seq)
		} else {
			return ZeroKey, newBadEscSeq(seq, "bad CSI")
		}
	}

	if last == '~' {
		if len(nums) == 1 || len(nums) == 2 {
			if r, ok := keyByNum0[nums[0]]; ok {
				k := Key{r, 0}
				if len(nums) == 1 {
					// Unmodified: \e[5~ (PageUp)
					return k, nil
				}
				// Modified: \e[5;5~ (Ctrl-PageUp)
				return xtermModify(k, nums[1], seq)
			}
		} else if len(nums) == 3 && nums[0] == 27 {
			if r, ok := keyByNum2[nums[2]]; ok {
				k := Key{r, 0}
				return xtermModify(k, nums[1], seq)
			}
		}
	}

	return ZeroKey, newBadEscSeq(seq, "bad CSI")
}

func xtermModify(k Key, mod int, seq string) (Key, error) {
	switch mod {
	case 0:
		// do nothing
	case 2:
		k.Mod |= Shift
	case 3:
		k.Mod |= Alt
	case 4:
		k.Mod |= Shift | Alt
	case 5:
		k.Mod |= Ctrl
	case 6:
		k.Mod |= Shift | Ctrl
	case 7:
		k.Mod |= Alt | Ctrl
	case 8:
		k.Mod |= Shift | Alt | Ctrl
	default:
		return ZeroKey, newBadEscSeq(seq, "bad mod")
	}
	return k, nil
}
<commit_msg>Fix parsing of unmodified function keys.<commit_after>package edit

import (
	"fmt"
	"os"
	"time"
)

var (
	// EscTimeout is the amount of time after which an \033 (\x1b) character is
	// parsed as a standalone Esc key press instead of starting an escape
	// sequence. Modern terminal emulators send escape sequences very fast, so
	// 10ms is more than sufficient. SSH connections on a slow link can be
	// problematic,
	EscTimeout = 10 * time.Millisecond
)

// Special rune values used in the return value of (*Reader).ReadRune.
const (
	// No rune received before specified time.
	runeTimeout rune = -1 - iota
	// Error occured in AsyncReader. The error is left at the readError field.
	runeReadError
)

// Reader converts a stream of runes into a stream of OneRead's.
type Reader struct {
	ar        *AsyncReader
	keyChan   chan Key
	cprChan   chan pos
	mouseChan chan mouseEvent
	errChan   chan error
	quit      chan struct{}
}

type mouseEvent struct {
	pos
	down   bool
	button int
	mod    Mod
}

// BadEscSeq indicates that a escape sequence has been read from the terminal,
// but it cannot be parsed.
type BadEscSeq struct {
	seq string
	msg string
}

func newBadEscSeq(seq string, msg string) *BadEscSeq {
	return &BadEscSeq{seq, msg}
}

func (bes *BadEscSeq) Error() string {
	return fmt.Sprintf("bad escape sequence %q: %s", bes.seq, bes.msg)
}

// NewReader creates a new Reader on the given terminal file.
func NewReader(f *os.File) *Reader {
	rd := &Reader{
		NewAsyncReader(f),
		make(chan Key),
		make(chan pos),
		make(chan mouseEvent),
		make(chan error),
		nil,
	}
	return rd
}

// KeyChan returns the channel onto which the Reader writes Keys it has read.
func (rd *Reader) KeyChan() <-chan Key {
	return rd.keyChan
}

// CPRChan returns the channel onto which the Reader writes CPRs it has read.
func (rd *Reader) CPRChan() <-chan pos {
	return rd.cprChan
}

// MouseChan returns the channel onto which the Reader writes mouse events it
// has read.
func (rd *Reader) MouseChan() <-chan mouseEvent {
	return rd.mouseChan
}

// ErrorChan returns the channel onto which the Reader writes errors it came
// across during the reading process.
func (rd *Reader) ErrorChan() <-chan error {
	return rd.errChan
}

// Run runs the Reader. It blocks until Quit is called and should be called in
// a separate goroutine.
func (rd *Reader) Run() {
	runes := rd.ar.Chan()
	rd.quit = make(chan struct{})
	go rd.ar.Run()

	for {
		select {
		case r := <-runes:
			rd.readOne(r)
		case <-rd.quit:
			return
		}
	}
}

// Quit terminates the loop of Run.
func (rd *Reader) Quit() {
	rd.ar.Quit()
	close(rd.quit)
}

// Close releases files associated with the Reader. It does not close the file
// used to create it.
func (rd *Reader) Close() {
	rd.ar.Close()
}

// readOne attempts to read one key or CPR, led by a rune already read.
func (rd *Reader) readOne(r rune) {
	var k Key
	var cpr pos
	var mouse mouseEvent
	var err error
	var currentSeq string

	// readRune attempts to read a rune within the predefined timeout. It
	// writes to the err and currentSeq variable in the outer scope.
	readRune :=
		func(d time.Duration) rune {
			select {
			case r := <-rd.ar.Chan():
				currentSeq += string(r)
				return r
			case err = <-rd.ar.ErrorChan():
				return runeReadError
			case <-After(d):
				return runeTimeout
			}
		}

	defer func() {
		if k != (Key{}) {
			select {
			case rd.keyChan <- k:
			case <-rd.quit:
			}
		} else if cpr != (pos{}) {
			select {
			case rd.cprChan <- cpr:
			case <-rd.quit:
			}
		} else if mouse != (mouseEvent{}) {
			select {
			case rd.mouseChan <- mouse:
			case <-rd.quit:
			}
		}
		if err != nil {
			select {
			case rd.errChan <- err:
			case <-rd.quit:
			}
		}
	}()

	switch r {
	case Tab, Enter, Backspace:
		k = Key{r, 0}
	case 0x0:
		k = Key{'`', Ctrl} // ^@
	case 0x1d:
		k = Key{'6', Ctrl} // ^^
	case 0x1f:
		k = Key{'/', Ctrl} // ^_
	case 0x1b: // ^[ Escape
		r2 := readRune(EscTimeout)
		if r2 == runeTimeout || r2 == runeReadError {
			k = Key{'[', Ctrl}
			break
		}
		switch r2 {
		case '[':
			// CSI style function key sequence, looks like [\d;]*[^\d;]
			// Read numeric parameters (if any)
			nums := make([]int, 0, 2)
			seq := "\x1b["
			timeout := EscTimeout
			isMouse := false
		CSISeq:
			for {
				r = readRune(timeout)
				// Timeout can only happen at first readRune.
				if r == runeTimeout || r == runeReadError {
					k = Key{'[', Alt}
					return
				}
				seq += string(r)
				// After first rune read we turn off the timeout
				timeout = -1
				switch {
				case r == ';':
					nums = append(nums, 0)
				case r == '<':
					isMouse = true
				case '0' <= r && r <= '9':
					if len(nums) == 0 {
						nums = append(nums, 0)
					}
					cur := len(nums) - 1
					nums[cur] = nums[cur]*10 + int(r-'0')
				default:
					break CSISeq
				}
			}
			if r == 'R' {
				// CPR
				if len(nums) != 2 {
					err = newBadEscSeq(currentSeq, "bad CPR")
					return
				}
				cpr = pos{nums[0], nums[1]}
			} else if isMouse && (r == 'm' || r == 'M') {
				if len(nums) != 3 {
					err = newBadEscSeq(currentSeq, "bad mouse event")
					return
				}
				down := r == 'M'
				n0 := nums[0]
				button := n0 & 3
				mod := Mod(0)
				if n0&4 != 0 {
					mod |= Shift
				}
				if n0&8 != 0 {
					mod |= Alt
				}
				if n0&16 != 0 {
					mod |= Ctrl
				}
				mouse = mouseEvent{pos{nums[2], nums[1]}, down, button, mod}
			} else {
				k, err = parseCSI(nums, r, seq)
			}
		case 'O':
			// G3 style function key sequence: read one rune.
			r = readRune(EscTimeout)
			if r == runeTimeout || r == runeReadError {
				k = Key{r2, Alt}
				return
			}
			r, ok := g3Seq[r]
			if ok {
				k = Key{r, 0}
			} else {
				err = newBadEscSeq(currentSeq, "bad G3")
			}
		default:
			k = Key{r2, Alt}
		}
	default:
		// Sane Ctrl- sequences that agree with the keyboard...
		if 0x1 <= r && r <= 0x1d {
			k = Key{r + 0x40, Ctrl}
		} else {
			k = Key{r, 0}
		}
	}
}

// G3-style key sequences: \eO followed by exactly one character. For instance,
// \eOP is F1.
var g3Seq = map[rune]rune{
	// F1-F4: xterm, libvte and tmux
	'P': F1, 'Q': F2,
	'R': F3, 'S': F4,

	// Home and End: libvte
	'H': Home, 'F': End,
}

// Tables for CSI-style key sequences, which are \e[ followed by a list of
// semicolon-delimited numeric arguments, before being concluded by a
// non-numeric, non-semicolon rune.

// CSI-style key sequences that can be identified based on the ending rune. For
// instance, \e[A is Up.
var keyByLast = map[rune]Key{
	'A': Key{Up, 0}, 'B': Key{Down, 0},
	'C': Key{Right, 0}, 'D': Key{Left, 0},
	'H': Key{Home, 0}, 'F': Key{End, 0},
	'Z': Key{Tab, Shift},
}

// CSI-style key sequences ending with '~' and can be identified based on
// the only number argument. For instance, \e[1~ is Home.
var keyByNum0 = map[int]rune{
	1: Home, 2: Insert, 3: Delete, 4: End, 5: PageUp, 6: PageDown,
	11: F1, 12: F2, 13: F3, 14: F4,
	15: F5, 17: F6, 18: F7, 19: F8, 20: F9, 21: F10, 23: F11, 24: F12,
}

// CSI-style key sequences ending with '~', with 27 as the first numeric
// argument. For instance, \e[27;9~ is Tab.
//
// The list is taken blindly from tmux source xterm-keys.c. I don't have a
// keyboard-terminal combination that generate such sequences, but assumably
// some PC keyboard with a numpad can.
var keyByNum2 = map[int]rune{
	9: '\t', 13: '\r',
	33: '!', 35: '#', 39: '\'', 40: '(', 41: ')', 43: '+', 44: ',', 45: '-',
	46: '.',
	48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7',
	56: '8', 57: '9',
	58: ':', 59: ';', 60: '<', 61: '=', 62: '>', 63: ';',
}

// parseCSI parses a CSI-style key sequence.
func parseCSI(nums []int, last rune, seq string) (Key, error) {
	if k, ok := keyByLast[last]; ok {
		if len(nums) == 0 {
			// Unmodified: \e[A (Up)
			return k, nil
		} else if len(nums) == 2 && nums[0] == 1 {
			// Modified: \e[1;5A (Ctrl-Up)
			return xtermModify(k, nums[1], seq)
		} else {
			return ZeroKey, newBadEscSeq(seq, "bad CSI")
		}
	}

	if last == '~' {
		if len(nums) == 1 || len(nums) == 2 {
			if r, ok := keyByNum0[nums[0]]; ok {
				k := Key{r, 0}
				if len(nums) == 1 {
					// Unmodified: \e[5~ (PageUp)
					return k, nil
				}
				// Modified: \e[5;5~ (Ctrl-PageUp)
				return xtermModify(k, nums[1], seq)
			}
		} else if len(nums) == 3 && nums[0] == 27 {
			if r, ok := keyByNum2[nums[2]]; ok {
				k := Key{r, 0}
				return xtermModify(k, nums[1], seq)
			}
		}
	}

	return ZeroKey, newBadEscSeq(seq, "bad CSI")
}

func xtermModify(k Key, mod int, seq string) (Key, error) {
	switch mod {
	case 0:
		// do nothing
	case 2:
		k.Mod |= Shift
	case 3:
		k.Mod |= Alt
	case 4:
		k.Mod |= Shift | Alt
	case 5:
		k.Mod |= Ctrl
	case 6:
		k.Mod |= Shift | Ctrl
	case 7:
		k.Mod |= Alt | Ctrl
	case 8:
		k.Mod |= Shift | Alt | Ctrl
	default:
		return ZeroKey, newBadEscSeq(seq, "bad mod")
	}
	return k, nil
}
<|endoftext|>


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

package command

import (
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/coreos/etcd/pkg/transport"
)

var (
	ErrNoAvailSrc = errors.New("no available argument and stdin")
)

// trimsplit slices s into all substrings separated by sep and returns a
// slice of the substrings between the separator with all leading and trailing
// white space removed, as defined by Unicode.
func trimsplit(s, sep string) []string {
	raw := strings.Split(s, ",")
	trimmed := make([]string, 0)
	for _, r := range raw {
		trimmed = append(trimmed, strings.TrimSpace(r))
	}
	return trimmed
}

func argOrStdin(args []string, stdin io.Reader, i int) (string, error) {
	if i < len(args) {
		return args[i], nil
	}
	bytes, err := ioutil.ReadAll(stdin)
	if string(bytes) == "" || err != nil {
		return "", ErrNoAvailSrc
	}
	return string(bytes), nil
}

func getPeersFlagValue(c *cli.Context) []string {
	peerstr := c.GlobalString("peers")

	// Use an environment variable if nothing was supplied on the
	// command line
	if peerstr == "" {
		peerstr = os.Getenv("ETCDCTL_PEERS")
	}

	// If we still don't have peers, use a default
	if peerstr == "" {
		peerstr = "127.0.0.1:4001"
	}

	return strings.Split(peerstr, ",")
}

func getEndpoints(c *cli.Context) ([]string, error) {
	eps := getPeersFlagValue(c)
	for i, ep := range eps {
		u, err := url.Parse(ep)
		if err != nil {
			return nil, err
		}

		if u.Scheme == "" {
			u.Scheme = "http"
		}

		eps[i] = u.String()
	}
	return eps, nil
}

func getTransport(c *cli.Context) (*http.Transport, error) {
	cafile := c.GlobalString("ca-file")
	certfile := c.GlobalString("cert-file")
	keyfile := c.GlobalString("key-file")

	// Use an environment variable if nothing was supplied on the
	// command line
	if cafile == "" {
		cafile = os.Getenv("ETCDCTL_CA_FILE")
	}
	if certfile == "" {
		certfile = os.Getenv("ETCDCTL_CERT_FILE")
	}
	if keyfile == "" {
		keyfile = os.Getenv("ETCDCTL_KEY_FILE")
	}

	tls := transport.TLSInfo{
		CAFile:   cafile,
		CertFile: certfile,
		KeyFile:  keyfile,
	}
	return transport.NewTransport(tls)

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

package command

import (
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/coreos/etcd/pkg/transport"
)

var (
	ErrNoAvailSrc = errors.New("no available argument and stdin")
)

// trimsplit slices s into all substrings separated by sep and returns a
// slice of the substrings between the separator with all leading and trailing
// white space removed, as defined by Unicode.
func trimsplit(s, sep string) []string {
	raw := strings.Split(s, ",")
	trimmed := make([]string, 0)
	for _, r := range raw {
		trimmed = append(trimmed, strings.TrimSpace(r))
	}
	return trimmed
}

func argOrStdin(args []string, stdin io.Reader, i int) (string, error) {
	if i < len(args) {
		return args[i], nil
	}
	bytes, err := ioutil.ReadAll(stdin)
	if string(bytes) == "" || err != nil {
		return "", ErrNoAvailSrc
	}
	return string(bytes), nil
}

func getPeersFlagValue(c *cli.Context) []string {
	peerstr := c.GlobalString("peers")

	// Use an environment variable if nothing was supplied on the
	// command line
	if peerstr == "" {
		peerstr = os.Getenv("ETCDCTL_PEERS")
	}

	// If we still don't have peers, use a default
	if peerstr == "" {
		peerstr = "127.0.0.1:4001,127.0.0.1:2379"
	}

	return strings.Split(peerstr, ",")
}

func getEndpoints(c *cli.Context) ([]string, error) {
	eps := getPeersFlagValue(c)
	for i, ep := range eps {
		u, err := url.Parse(ep)
		if err != nil {
			return nil, err
		}

		if u.Scheme == "" {
			u.Scheme = "http"
		}

		eps[i] = u.String()
	}
	return eps, nil
}

func getTransport(c *cli.Context) (*http.Transport, error) {
	cafile := c.GlobalString("ca-file")
	certfile := c.GlobalString("cert-file")
	keyfile := c.GlobalString("key-file")

	// Use an environment variable if nothing was supplied on the
	// command line
	if cafile == "" {
		cafile = os.Getenv("ETCDCTL_CA_FILE")
	}
	if certfile == "" {
		certfile = os.Getenv("ETCDCTL_CERT_FILE")
	}
	if keyfile == "" {
		keyfile = os.Getenv("ETCDCTL_KEY_FILE")
	}

	tls := transport.TLSInfo{
		CAFile:   cafile,
		CertFile: certfile,
		KeyFile:  keyfile,
	}
	return transport.NewTransport(tls)

}
<|endoftext|>