<commit_before>// +build go1.8

package main

import (
	"compress/gzip"
	"encoding/json"
	"errors"
	"io"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"
)

var bsn bikeShareNetwork

func main() {
	log.Println("starting seagull")
	var err error
	bsn, err = getSeedData()
	if err != nil {
		log.Fatal(err)
	}

	http.Handle("/", http.FileServer(http.Dir("../frontend/www")))
	http.HandleFunc("/api/networks", GzipFunc(listNetworksHandler))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}

}

func (l Location) distance(lat, lng float64) float64 {
	R := 6371e3 // radius

	φ1 := (math.Pi * lat) / 180
	φ2 := (math.Pi * lng) / 180

	Δφ := (l.Latitude - lat) * math.Pi / 180
	Δλ := (l.Longitude - lng) * math.Pi / 180

	a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
		math.Cos(φ1)*math.Cos(φ2)*
			math.Sin(Δλ/2)*math.Sin(Δλ/2)
	return R * 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
}

var (
	ErrRangeQuery    = errors.New("failed to parse range query")
	ErrLocationQuery = errors.New("failed to parse location query")
)

func parseNetworksQuery(u url.Values) (float64, float64, float64, error) {
	_, latok := u["lat"]
	_, lngok := u["lng"]
	_, rngok := u["rng"]
	if !latok || !lngok {
		return 0, 0, 0, ErrLocationQuery
	}

	lat, err := strconv.ParseFloat(u["lat"][0], 10)
	if err != nil {
		return 0, 0, 0, err
	}

	lng, err := strconv.ParseFloat(u["lng"][0], 10)
	if err != nil {
		return lat, 0, 0, err
	}
	rng := 100000.0 // set default range
	if rngok {
		rng, err = strconv.ParseFloat(u["rng"][0], 10)
		if err != nil {
			return lat, lng, 100000, ErrRangeQuery
		}
	}

	return lat, lng, rng, nil
}

func listNetworksHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("listNetworks", r.RemoteAddr, r.RequestURI)
	defer timeLog(time.Now(), "listNetworks")

	type Shortnet struct {
		ID       string `json:"id"`
		Name     string `json:"name"`
		Location `json:"location"`
	}

	type Response struct {
		Networks []Shortnet `json:"networks"`
	}

	var networks Response
	for _, v := range bsn.Networks {
		short := Shortnet{
			ID:       v.ID,
			Name:     v.Name,
			Location: v.Location,
		}
		networks.Networks = append(networks.Networks, short)
	}

	q := r.URL.Query()
	lat, lng, rng, err := parseNetworksQuery(q)

	if err != nil {
		if err != ErrRangeQuery {
			log.Println("oops", err)
			enc := json.NewEncoder(w)
			if err := enc.Encode(networks); err != nil {
				log.Println(err)
			}
			return
		}
		log.Println(err)
	}
	for k, v := range networks.Networks {
		networks.Networks[k].Location.Distance = int(v.Location.distance(lat, lng))
	}

	sort.Slice(networks.Networks, func(i, j int) bool {
		return networks.Networks[i].Location.Distance < networks.Networks[j].Location.Distance
	})

	var within Response
	for _, v := range networks.Networks {
		if float64(v.Location.Distance) < rng {
			within.Networks = append(within.Networks, v)
		} else {
			// since it is a sorted list we can just exit loop
			break
		}
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(within); err != nil {
		log.Println(err)
	}

}

func getSeedData() (bikeShareNetwork, error) {
	defer timeLog(time.Now(), "getSeedData")
	// check if we have it first
	if _, err := os.Stat("bsn.json"); os.IsNotExist(err) {
		const bikeShareAPI = "http://api.citybik.es/v2/networks"

		var bsn bikeShareNetwork
		resp, err := http.Get(bikeShareAPI)
		if err != nil {
			return bsn, err
		}
		defer resp.Body.Close()

		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(&bsn); err != nil {
			return bsn, err
		}
		networks := len(bsn.Networks)
		for k, v := range bsn.Networks {
			log.Printf("(%3d of %3d) detail of %s, \n", k+1, networks, v.ID)
			var detail networkDetail
			resp, err := http.Get(bikeShareAPI + "/" + v.ID)
			if err != nil {
				log.Printf("error reading network detail for %s: %v", v.ID, err)
				break
			}
			defer resp.Body.Close()
			dec := json.NewDecoder(resp.Body)
			if err := dec.Decode(&detail); err != nil {
				log.Printf("error decoding detail json for %s: %v", v.ID, err)
				break
			}
			bsn.Networks[k] = detail.Detail
		}

		out, err := os.Create("bsn.json")
		if err != nil {
			log.Fatal(err)
		}
		defer out.Close()

		enc := json.NewEncoder(out)
		err = enc.Encode(bsn)
		if err != nil {
			log.Println(err)
		}

	}

	var bsn bikeShareNetwork

	in, err := os.Open("bsn.json")
	if err != nil {
		return bsn, err
	}

	dec := json.NewDecoder(in)
	if err := dec.Decode(&bsn); err != nil {
		return bsn, err
	}
	// get data from file

	return bsn, nil

}

type bikeShareNetwork struct {
	Networks []Network `json:"networks"`
}

type Network struct {
	Company  []string `json:"company"`
	Href     string   `json:"href"`
	ID       string   `json:"id"`
	Location `json:"location"`
	Name     string    `json:"name"`
	Stations []Station `json:"stations,omitempty"`
}

type networkDetail struct {
	Detail Network `json:"network"`
}

type Station struct {
	EmptySlots int       `json:"empty_slots"`
	FreeBikes  int       `json:"free_bikes"`
	ID         string    `json:"id"`
	Latitude   float64   `json:"latitude"`
	Longitude  float64   `json:"longitude"`
	Name       string    ` json:"name"`
	Timestamp  time.Time `json:"timestamp"` // look up local offset at location
}

type Location struct {
	City      string  `json:"city"`
	Country   string  `json:"country"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Distance  int     `json:"distance,omitempty"`
}

func (n *Network) UnmarshalJSON(data []byte) error {
	// Need too handle the one case company strings vs []string
	type ServerNetworks Network
	aux := &struct {
		Company interface{} `json:"company"`
		*ServerNetworks
	}{
		ServerNetworks: (*ServerNetworks)(n),
	}
	err := json.Unmarshal(data, &aux)
	if err != nil {
		return err
	}

	switch aux.Company.(type) {
	case string:
		c, ok := aux.Company.(string)
		if ok {
			n.Company = append(n.Company, c)
		}
	case []interface{}:
		cc, ok := aux.Company.([]interface{})
		if ok {
			for _, vv := range cc {
				switch vv.(type) {
				case string:
					c, ok := vv.(string)
					if ok {
						n.Company = append(n.Company, c)
					} else {
						log.Println("failed conversion to string")
					}
				}
			}
		}
	}
	return nil
}

type gzipResponseWriter struct {
	io.Writer
	http.ResponseWriter
}

func GzipFunc(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
			fn(w, r)
			w.Header().Set("Pragma", "no-cache")
			w.Header().Set("Content-Type", "application/json")
			return
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Pragma", "no-cache")
		w.Header().Set("Content-Type", "application/json")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		gzr := gzipResponseWriter{Writer: gz, ResponseWriter: w}
		fn(gzr, r)
	}
}

func (w gzipResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}

func timeLog(start time.Time, name string) {
	taken := time.Since(start)
	log.Printf("%s took %s", name, taken)
}
<commit_msg>http server change for clearer api<commit_after>// +build go1.8

package main

import (
	"encoding/json"
	"log"
	"math"
	"net/http"
	"os"
	"time"

	"github.com/kataras/iris"
	"github.com/kataras/iris/context"
)

// in lou of database for now
var bsn bikeShareNetwork
var netmap = make(map[string]Network)

func main() {
	log.Println("starting seagull")
	var err error
	bsn, err = getSeedData()
	if err != nil {
		log.Fatal(err)
	}

	// read only map from here
	// replace with database
	for _, v := range bsn.Networks {
		netmap[v.ID] = v
	}

	srv := iris.New()
	srv.StaticWeb("/", "../frontend/www")
	srv.Get("/api/network/{id:string}", getDetail)
	srv.Get("/api/network", getNetworkList)
	srv.Run(iris.Addr(":8080"))
}

func getDetail(ctx context.Context) {
	id := ctx.Params().Get("id")
	if id == "" {
		ctx.NotFound()
	}
	net, ok := netmap[id]
	if !ok {
		log.Printf("network %v does not exist", id)
		ctx.NotFound()
	}
	ctx.Gzip(true)
	ctx.JSON(net)
}

type Where struct {
	Lat, Lng float64
	Rng      float64
}

func getNetworkList(ctx context.Context) {
	at := Where{}
	err := ctx.ReadForm(&at)
	if err != nil {
		log.Println(err)
	}
	type Shortnet struct {
		ID       string `json:"id"`
		Name     string `json:"name"`
		Location `json:"location"`
	}

	type Response struct {
		Networks []Shortnet `json:"networks"`
	}
	ctx.Gzip(true)

	if at.Lat == 0 || at.Lng == 0 {
		var short Response
		for _, v := range bsn.Networks {
			s := Shortnet{
				ID:       v.ID,
				Name:     v.Name,
				Location: v.Location,
			}
			short.Networks = append(short.Networks, s)
		}
		ctx.JSON(short)
	}
	if at.Rng == 0 {
		at.Rng = 160000 // 160 km, 100 Miles
	}
	// compute diatnce
	var localised Response
	for _, v := range bsn.Networks {
		distance := v.Location.howfar(at)
		if distance < at.Rng {
			s := Shortnet{
				ID:       v.ID,
				Name:     v.Name,
				Location: v.Location,
			}
			s.Location.Distance = int(distance)
			localised.Networks = append(localised.Networks, s)
		}
	}
	ctx.JSON(localised)
}

func (l Location) howfar(at Where) float64 {
	R := 6371e3 // radius

	φ1 := (math.Pi * at.Lat) / 180
	φ2 := (math.Pi * at.Lng) / 180

	Δφ := (l.Latitude - at.Lat) * math.Pi / 180
	Δλ := (l.Longitude - at.Lng) * math.Pi / 180

	a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
		math.Cos(φ1)*math.Cos(φ2)*
			math.Sin(Δλ/2)*math.Sin(Δλ/2)
	return R * 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
}

func getSeedData() (bikeShareNetwork, error) {
	defer timeLog(time.Now(), "getSeedData")
	// check if we have it first
	if _, err := os.Stat("bsn.json"); os.IsNotExist(err) {
		const bikeShareAPI = "http://api.citybik.es/v2/networks"

		var bsn bikeShareNetwork
		resp, err := http.Get(bikeShareAPI)
		if err != nil {
			return bsn, err
		}
		defer resp.Body.Close()

		dec := json.NewDecoder(resp.Body)
		if err := dec.Decode(&bsn); err != nil {
			return bsn, err
		}
		networks := len(bsn.Networks)
		for k, v := range bsn.Networks {
			log.Printf("(%3d of %3d) detail of %s, \n", k+1, networks, v.ID)
			var detail networkDetail
			resp, err := http.Get(bikeShareAPI + "/" + v.ID)
			if err != nil {
				log.Printf("error reading network detail for %s: %v", v.ID, err)
				break
			}
			defer resp.Body.Close()
			dec := json.NewDecoder(resp.Body)
			if err := dec.Decode(&detail); err != nil {
				log.Printf("error decoding detail json for %s: %v", v.ID, err)
				break
			}
			bsn.Networks[k] = detail.Detail
		}

		out, err := os.Create("bsn.json")
		if err != nil {
			log.Fatal(err)
		}
		defer out.Close()

		enc := json.NewEncoder(out)
		err = enc.Encode(bsn)
		if err != nil {
			log.Println(err)
		}

	}

	var bsn bikeShareNetwork

	in, err := os.Open("bsn.json")
	if err != nil {
		return bsn, err
	}

	dec := json.NewDecoder(in)
	if err := dec.Decode(&bsn); err != nil {
		return bsn, err
	}
	// get data from file

	return bsn, nil

}

type bikeShareNetwork struct {
	Networks []Network `json:"networks"`
}

type Network struct {
	Company  []string `json:"company"`
	ID       string   `json:"id"`
	Location `json:"location"`
	Name     string    `json:"name"`
	Stations []Station `json:"stations,omitempty"`
}

type networkDetail struct {
	Detail Network `json:"network"`
}

type Station struct {
	EmptySlots int       `json:"empty_slots"`
	FreeBikes  int       `json:"free_bikes"`
	ID         string    `json:"id"`
	Latitude   float64   `json:"latitude"`
	Longitude  float64   `json:"longitude"`
	Name       string    ` json:"name"`
	Timestamp  time.Time `json:"timestamp"` // look up local offset at location
}

type Location struct {
	City      string  `json:"city"`
	Country   string  `json:"country"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Distance  int     `json:"distance,omitempty"`
}

func (n *Network) UnmarshalJSON(data []byte) error {
	// Need too handle the one case where company is string vs []string
	type ServerNetworks Network
	aux := &struct {
		Company interface{} `json:"company"`
		*ServerNetworks
	}{
		ServerNetworks: (*ServerNetworks)(n),
	}
	err := json.Unmarshal(data, &aux)
	if err != nil {
		return err
	}

	switch aux.Company.(type) {
	case string:
		c, ok := aux.Company.(string)
		if ok {
			n.Company = append(n.Company, c)
		}
	case []interface{}:
		cc, ok := aux.Company.([]interface{})
		if ok {
			for _, vv := range cc {
				switch vv.(type) {
				case string:
					c, ok := vv.(string)
					if ok {
						n.Company = append(n.Company, c)
					} else {
						log.Println("failed conversion to string")
					}
				}
			}
		}
	}
	return nil
}

func timeLog(start time.Time, name string) {
	taken := time.Since(start)
	log.Printf("%s took %s", name, taken)
}
<|endoftext|>


<commit_before>package repository

import (
	"reflect"
	"testing"
)

const (
	testRepositoryPath = "testing/repository"
)

func TestNewBaseRepository(t *testing.T) {
	type args struct {
		path string
	}
	tests := []struct {
		name string
		args args
		want Repository
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := NewBaseRepository(tt.args.path); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("NewBaseRepository() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Uninstall(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Uninstall(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Uninstall() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Find(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Find(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Find() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_IsInstalled(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name           string
		repositoryPath string
		args           args
		want           bool
		wantErr        bool
	}{
		{"Template is installed", testRepositoryPath, args{"valid"}, true, false},
		{"Template is not installed", testRepositoryPath, args{"not_installed"}, false, false},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := NewBaseRepository(tt.repositoryPath)
			got, err := b.IsInstalled(tt.args.templateID)
			if (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.IsInstalled() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("BaseRepository.IsInstalled() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Installed(t *testing.T) {
	tests := []struct {
		name    string
		b       *BaseRepository
		want    []string
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			got, err := b.Installed()
			if (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Installed() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("BaseRepository.Installed() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Link(t *testing.T) {
	type args struct {
		templatePath string
		templateName string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Link(tt.args.templatePath, tt.args.templateName); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Link() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Unlink(t *testing.T) {
	type args struct {
		templateName string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Unlink(tt.args.templateName); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Unlink() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Install(t *testing.T) {
	type args struct {
		templateLocator string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Install(tt.args.templateLocator); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Install() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Update(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Update(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Update() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}
<commit_msg>#9 add extra test to BaseRepository.IsInstalled<commit_after>package repository

import (
	"reflect"
	"testing"
)

const (
	testRepositoryPath = "testing/repository"
)

func TestNewBaseRepository(t *testing.T) {
	type args struct {
		path string
	}
	tests := []struct {
		name string
		args args
		want Repository
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := NewBaseRepository(tt.args.path); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("NewBaseRepository() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Uninstall(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Uninstall(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Uninstall() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Find(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Find(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Find() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_IsInstalled(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name           string
		repositoryPath string
		args           args
		want           bool
		wantErr        bool
	}{
		{"Template is installed", testRepositoryPath, args{"valid"}, true, false},
		{"Template is not installed", testRepositoryPath, args{"not_installed"}, false, false},
		{"Template invalid empty name", testRepositoryPath, args{""}, false, true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := NewBaseRepository(tt.repositoryPath)
			got, err := b.IsInstalled(tt.args.templateID)
			if (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.IsInstalled() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("BaseRepository.IsInstalled() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Installed(t *testing.T) {
	tests := []struct {
		name    string
		b       *BaseRepository
		want    []string
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			got, err := b.Installed()
			if (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Installed() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("BaseRepository.Installed() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestBaseRepository_Link(t *testing.T) {
	type args struct {
		templatePath string
		templateName string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Link(tt.args.templatePath, tt.args.templateName); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Link() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Unlink(t *testing.T) {
	type args struct {
		templateName string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Unlink(tt.args.templateName); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Unlink() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Install(t *testing.T) {
	type args struct {
		templateLocator string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Install(tt.args.templateLocator); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Install() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestBaseRepository_Update(t *testing.T) {
	type args struct {
		templateID string
	}
	tests := []struct {
		name    string
		b       *BaseRepository
		args    args
		wantErr bool
	}{
	// TODO: Add test cases.
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			b := &BaseRepository{}
			if err := b.Update(tt.args.templateID); (err != nil) != tt.wantErr {
				t.Errorf("BaseRepository.Update() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"sync"
	"time"

	"github.com/dustin/go-humanize"
)

var verbose = flag.Bool("v", false, "verbosity")
var concurrency = flag.Int("j", 2,
	"number of concurrent dumps")

func init() {
	log.SetFlags(log.Lmicroseconds)
}

func maybeFatal(err error, fmt string, args ...interface{}) {
	if err != nil {
		log.Fatalf(fmt, args...)
	}
}

func listDatabases(u url.URL) []string {
	u.Path = "/_all_dbs"
	res, err := http.Get(u.String())
	maybeFatal(err, "Error listing databases: %v", err)
	defer res.Body.Close()

	rv := []string{}
	d := json.NewDecoder(res.Body)
	err = d.Decode(&rv)
	maybeFatal(err, "Error decoding database list: %v", err)
	return rv
}

func vlog(s string, a ...interface{}) {
	if *verbose {
		log.Printf(s, a...)
	}
}

func compress(w io.Writer) io.WriteCloser {
	z, err := gzip.NewWriterLevel(w, gzip.BestCompression)
	maybeFatal(err, "NewWriterLevel: %v", err)
	return z
}

func dumpOne(dbname, u string) (int64, error) {
	res, err := http.Get(u)
	if err != nil {
		return 0, err
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		return 0, fmt.Errorf("HTTP Error: %v", res.Status)
	}

	outf, err := os.Create(dbname + ".json.gz")
	if err != nil {
		return 0, err
	}
	defer outf.Close()

	z := compress(outf)
	defer z.Close()
	return io.Copy(z, res.Body)
}

func dump(wg *sync.WaitGroup, u url.URL, ch <-chan string) {
	defer wg.Done()

	for db := range ch {
		start := time.Now()
		vlog("Dumping %v", db)
		u.Path = "/" + db + "/_dump"
		n, err := dumpOne(db, u.String())
		maybeFatal(err, "Error dumping %v: %v", u.String(), err)

		vlog("Dumped %v of %v in %v",
			humanize.Bytes(uint64(n)), db, time.Since(start))
	}
}

func main() {
	flag.Parse()

	if flag.NArg() == 0 {
		log.Fatalf("Seriesly URL required")
	}

	u, err := url.Parse(flag.Arg(0))
	maybeFatal(err, "Parsing %v: %v", flag.Arg(0), err)

	wg := &sync.WaitGroup{}
	ch := make(chan string)

	for i := 0; i < *concurrency; i++ {
		wg.Add(1)
		go dump(wg, *u, ch)
	}

	for _, db := range listDatabases(*u) {
		ch <- db
	}
	close(ch)

	wg.Wait()
}
<commit_msg>Dump tool:  Allow dumping only a single db<commit_after>package main

import (
	"compress/gzip"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"sync"
	"time"

	"github.com/dustin/go-humanize"
)

var (
	verbose     = flag.Bool("v", false, "verbosity")
	concurrency = flag.Int("j", 2,
		"number of concurrent dumps")
	dbName = flag.String("db", "", "which db to dump (default: all)")
)

func init() {
	log.SetFlags(log.Lmicroseconds)
}

func maybeFatal(err error, fmt string, args ...interface{}) {
	if err != nil {
		log.Fatalf(fmt, args...)
	}
}

func listDatabases(u url.URL) []string {
	u.Path = "/_all_dbs"
	res, err := http.Get(u.String())
	maybeFatal(err, "Error listing databases: %v", err)
	defer res.Body.Close()

	rv := []string{}
	d := json.NewDecoder(res.Body)
	err = d.Decode(&rv)
	maybeFatal(err, "Error decoding database list: %v", err)
	return rv
}

func vlog(s string, a ...interface{}) {
	if *verbose {
		log.Printf(s, a...)
	}
}

func compress(w io.Writer) io.WriteCloser {
	z, err := gzip.NewWriterLevel(w, gzip.BestCompression)
	maybeFatal(err, "NewWriterLevel: %v", err)
	return z
}

func dumpOne(dbname, u string) (int64, error) {
	res, err := http.Get(u)
	if err != nil {
		return 0, err
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		return 0, fmt.Errorf("HTTP Error: %v", res.Status)
	}

	outf, err := os.Create(dbname + ".json.gz")
	if err != nil {
		return 0, err
	}
	defer outf.Close()

	z := compress(outf)
	defer z.Close()
	return io.Copy(z, res.Body)
}

func dump(wg *sync.WaitGroup, u url.URL, ch <-chan string) {
	defer wg.Done()

	for db := range ch {
		start := time.Now()
		vlog("Dumping %v", db)
		u.Path = "/" + db + "/_dump"
		n, err := dumpOne(db, u.String())
		maybeFatal(err, "Error dumping %v: %v", u.String(), err)

		vlog("Dumped %v of %v in %v",
			humanize.Bytes(uint64(n)), db, time.Since(start))
	}
}

func main() {
	flag.Parse()

	if flag.NArg() == 0 {
		log.Fatalf("Seriesly URL required")
	}

	u, err := url.Parse(flag.Arg(0))
	maybeFatal(err, "Parsing %v: %v", flag.Arg(0), err)

	wg := &sync.WaitGroup{}
	ch := make(chan string)

	for i := 0; i < *concurrency; i++ {
		wg.Add(1)
		go dump(wg, *u, ch)
	}

	if *dbName == "" {
		for _, db := range listDatabases(*u) {
			ch <- db
		}
	} else {
		ch <- *dbName
	}
	close(ch)

	wg.Wait()
}
<|endoftext|>


<commit_before>// +build darwin

package mem

import (
	"context"
	"encoding/binary"
	"strconv"
	"strings"

	"github.com/shirou/gopsutil/internal/common"
	"golang.org/x/sys/unix"
)

func getHwMemsize() (uint64, error) {
	totalString, err := unix.Sysctl("hw.memsize")
	if err != nil {
		return 0, err
	}

	// unix.sysctl() helpfully assumes the result is a null-terminated string and
	// removes the last byte of the result if it's 0 :/
	totalString += "\x00"

	total := uint64(binary.LittleEndian.Uint64([]byte(totalString)))

	return total, nil
}

// SwapMemory returns swapinfo.
func SwapMemory() (*SwapMemoryStat, error) {
	return SwapMemoryWithContext(context.Background())
}

func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
	var ret *SwapMemoryStat

	swapUsage, err := common.DoSysctrlWithContext(ctx, "vm.swapusage")
	if err != nil {
		return ret, err
	}

	total := strings.Replace(swapUsage[2], "M", "", 1)
	used := strings.Replace(swapUsage[5], "M", "", 1)
	free := strings.Replace(swapUsage[8], "M", "", 1)

	total_v, err := strconv.ParseFloat(total, 64)
	if err != nil {
		return nil, err
	}
	used_v, err := strconv.ParseFloat(used, 64)
	if err != nil {
		return nil, err
	}
	free_v, err := strconv.ParseFloat(free, 64)
	if err != nil {
		return nil, err
	}

	u := float64(0)
	if total_v != 0 {
		u = ((total_v - free_v) / total_v) * 100.0
	}

	// vm.swapusage shows "M", multiply 1024 * 1024 to convert bytes.
	ret = &SwapMemoryStat{
		Total:       uint64(total_v * 1024 * 1024),
		Used:        uint64(used_v * 1024 * 1024),
		Free:        uint64(free_v * 1024 * 1024),
		UsedPercent: u,
	}

	return ret, nil
}
<commit_msg>[mem][darwin] Remove calls to sysctl binary in mem/mem_darwin.go #639<commit_after>// +build darwin

package mem

import (
	"context"
	"encoding/binary"
	"fmt"
	"unsafe"

	"golang.org/x/sys/unix"
)

func getHwMemsize() (uint64, error) {
	totalString, err := unix.Sysctl("hw.memsize")
	if err != nil {
		return 0, err
	}

	// unix.sysctl() helpfully assumes the result is a null-terminated string and
	// removes the last byte of the result if it's 0 :/
	totalString += "\x00"

	total := uint64(binary.LittleEndian.Uint64([]byte(totalString)))

	return total, nil
}

// xsw_usage in sys/sysctl.h
type swapUsage struct {
	Total     uint64
	Avail     uint64
	Used      uint64
	Pagesize  int32
	Encrypted bool
}

// SwapMemory returns swapinfo.
func SwapMemory() (*SwapMemoryStat, error) {
	return SwapMemoryWithContext(context.Background())
}

func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
	// https://github.com/yanllearnn/go-osstat/blob/ae8a279d26f52ec946a03698c7f50a26cfb427e3/memory/memory_darwin.go
	var ret *SwapMemoryStat

	value, err := unix.SysctlRaw("vm.swapusage")
	if err != nil {
		return ret, err
	}
	if len(value) != 32 {
		return ret, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
	}
	swap := (*swapUsage)(unsafe.Pointer(&value[0]))

	u := float64(0)
	if swap.Total != 0 {
		u = ((float64(swap.Total) - float64(swap.Avail)) / float64(swap.Total)) * 100.0
	}

	ret = &SwapMemoryStat{
		Total:       swap.Total,
		Used:        swap.Used,
		Free:        swap.Avail,
		UsedPercent: u,
	}

	return ret, nil
}
<|endoftext|>


<commit_before>// +build tools

/*
Copyright 2020 The Knative 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 tools

// This package imports things required by this repository, to force `go mod` to see them as dependencies
import (
	_ "k8s.io/code-generator"
	_ "knative.dev/hack"

	// codegen: hack/generate-knative.sh
	_ "knative.dev/pkg/hack"

	_ "k8s.io/code-generator/cmd/client-gen"
	_ "k8s.io/code-generator/cmd/deepcopy-gen"
	_ "k8s.io/code-generator/cmd/defaulter-gen"
	_ "k8s.io/code-generator/cmd/informer-gen"
	_ "k8s.io/code-generator/cmd/lister-gen"
	_ "k8s.io/kube-openapi/cmd/openapi-gen"
	_ "knative.dev/pkg/codegen/cmd/injection-gen"
)
<commit_msg>Format go code (#537)<commit_after>//go:build tools
// +build tools

/*
Copyright 2020 The Knative 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 tools

// This package imports things required by this repository, to force `go mod` to see them as dependencies
import (
	_ "k8s.io/code-generator"
	_ "knative.dev/hack"

	// codegen: hack/generate-knative.sh
	_ "knative.dev/pkg/hack"

	_ "k8s.io/code-generator/cmd/client-gen"
	_ "k8s.io/code-generator/cmd/deepcopy-gen"
	_ "k8s.io/code-generator/cmd/defaulter-gen"
	_ "k8s.io/code-generator/cmd/informer-gen"
	_ "k8s.io/code-generator/cmd/lister-gen"
	_ "k8s.io/kube-openapi/cmd/openapi-gen"
	_ "knative.dev/pkg/codegen/cmd/injection-gen"
)
<|endoftext|>


<commit_before>package octorrent

import (
	"bufio"
	"bytes"
	"reflect"
	"testing"
)

func getDecoder(d []byte) decoder {
	buf := bytes.NewBuffer(d)

	return decoder{
		*bufio.NewReader(buf),
	}
}

func TestReadInt(t *testing.T) {
	const i, o = "412e51", int64(412)
	dec := getDecoder([]byte(i))

	num, err := dec.readInt()
	if err != nil {
		t.Errorf("readInt returned error: %v", err)
	}

	if num != o {
		t.Errorf("readInt did return %i, but should return %i", num, o)
	}
}

func TestReadIntUntil(t *testing.T) {
	const i, o = "142", int64(14)
	dec := getDecoder([]byte(i))

	num, err := dec.readIntUntil('2')
	if err != nil {
		t.Errorf("readIntUntil returned error: %v", err)
	}

	if num != o {
		t.Errorf("readIntUntil did return %i, but should return %i", num, o)
	}
}

func TestReadString(t *testing.T) {
	const i, o = "4:testfoobar", "test"
	dec := getDecoder([]byte(i))

	str, err := dec.readString()
	if err != nil {
		t.Errorf("readString returned error: %v", err)
	}

	if str != o {
		t.Errorf("readString returned %s, but should return %s", str, o)
	}
}

func TestReadValue(t *testing.T) {
	// Make o an interface{} to set various types
	var o interface{}

	// String
	i, o := "4:test", "test"
	dec := getDecoder([]byte(i))

	str, err := dec.readValue()
	if err != nil {
		t.Errorf("readValue returned error while reading string: %v", err)
	}

	if str != o {
		t.Errorf("readValue returned %s, but should return %s", str, o)
	}

	// Int
	i, o = "i1337e", int64(1337)
	dec = getDecoder([]byte(i))

	num, err := dec.readValue()
	if err != nil {
		t.Errorf("readValue returned error while reading int: %v", err)
	}

	if num != o {
		t.Errorf("readValue returned %i, but should return %i", num, o)
	}
}

func TestReadList(t *testing.T) {
	const i = "4:testi4ee"
	o := []interface{}{"test", int64(4)}
	dec := getDecoder([]byte(i))

	list, err := dec.readList()
	if err != nil {
		t.Errorf("readList returned error: %v", err)
	}

	if !reflect.DeepEqual(list, o) {
		t.Errorf("readList returned %v, but should return %v", list, o)
	}
}

func TestReadDictionary(t *testing.T) {
	const i = "4:testi1337e3:foo3:bare"
	o := map[string]interface{}{
		"test": int64(1337),
		"foo":  "bar",
	}
	dec := getDecoder([]byte(i))

	dict, err := dec.readDictionary()
	if err != nil {
		t.Errorf("readDictionary returned error: %v", err)
	}

	if !reflect.DeepEqual(dict, o) {
		t.Errorf("readDictionary returned %v, but should %v", dict, o)
	}
}

func TestDecode(t *testing.T) {
	const i = "d4:testli4ei3ee3:foo3:bare"
	o := map[string]interface{}{
		"test": []interface{}{
			int64(4),
			int64(3),
		},
		"foo": "bar",
	}
	buf := bytes.NewBufferString(i)

	res, err := Decode(buf)
	if err != nil {
		t.Errorf("Decode returned error: %v", err)
	}

	if !reflect.DeepEqual(res, o) {
		t.Errorf("Decode returned %v, but should return %v", res, o)
	}
}
<commit_msg>Remove readValue test (do they make sense?)<commit_after>package octorrent

import (
	"bufio"
	"bytes"
	"reflect"
	"testing"
)

func getDecoder(d []byte) decoder {
	buf := bytes.NewBuffer(d)

	return decoder{
		*bufio.NewReader(buf),
	}
}

func TestReadInt(t *testing.T) {
	const i, o = "412e51", int64(412)
	dec := getDecoder([]byte(i))

	num, err := dec.readInt()
	if err != nil {
		t.Errorf("readInt returned error: %v", err)
	}

	if num != o {
		t.Errorf("readInt did return %i, but should return %i", num, o)
	}
}

func TestReadIntUntil(t *testing.T) {
	const i, o = "142", int64(14)
	dec := getDecoder([]byte(i))

	num, err := dec.readIntUntil('2')
	if err != nil {
		t.Errorf("readIntUntil returned error: %v", err)
	}

	if num != o {
		t.Errorf("readIntUntil did return %i, but should return %i", num, o)
	}
}

func TestReadString(t *testing.T) {
	const i, o = "4:testfoobar", "test"
	dec := getDecoder([]byte(i))

	str, err := dec.readString()
	if err != nil {
		t.Errorf("readString returned error: %v", err)
	}

	if str != o {
		t.Errorf("readString returned %s, but should return %s", str, o)
	}
}

func TestReadList(t *testing.T) {
	const i = "4:testi4ee"
	o := []interface{}{"test", int64(4)}
	dec := getDecoder([]byte(i))

	list, err := dec.readList()
	if err != nil {
		t.Errorf("readList returned error: %v", err)
	}

	if !reflect.DeepEqual(list, o) {
		t.Errorf("readList returned %v, but should return %v", list, o)
	}
}

func TestReadDictionary(t *testing.T) {
	const i = "4:testi1337e3:foo3:bare"
	o := map[string]interface{}{
		"test": int64(1337),
		"foo":  "bar",
	}
	dec := getDecoder([]byte(i))

	dict, err := dec.readDictionary()
	if err != nil {
		t.Errorf("readDictionary returned error: %v", err)
	}

	if !reflect.DeepEqual(dict, o) {
		t.Errorf("readDictionary returned %v, but should %v", dict, o)
	}
}

func TestDecode(t *testing.T) {
	const i = "d4:testli4ei3ee3:foo3:bare"
	o := map[string]interface{}{
		"test": []interface{}{
			int64(4),
			int64(3),
		},
		"foo": "bar",
	}
	buf := bytes.NewBufferString(i)

	res, err := Decode(buf)
	if err != nil {
		t.Errorf("Decode returned error: %v", err)
	}

	if !reflect.DeepEqual(res, o) {
		t.Errorf("Decode returned %v, but should return %v", res, o)
	}
}
<|endoftext|>


<commit_before>package towerfall

import (
	"fmt"
	"sort"
	"time"
)

type CompleteSnapshot map[string]*Snapshot

type Snapshot struct {
	Person *Person         `json:"person"`
	Total  *PlayerSnapshot `json:"total"`
	Rank   int             `json:"rank"`
	// The Tournaments map contains the same data structure, but
	// separated per tournament
	Tournaments map[string]*PlayerSnapshot `json:"tournaments"`
}

// A PlayerSnapshot is a sum of all total stats about a player
type PlayerSnapshot struct {
	Shots    int           `json:"shots"`
	Sweeps   int           `json:"sweeps"`
	Kills    int           `json:"kills"`
	Self     int           `json:"self"`
	Matches  int           `json:"matches"`
	Rounds   int           `json:"rounds"`
	Score    int           `json:"score"`
	Playtime time.Duration `json:"playtime"`
	Wins     int           `json:"wins"`
}

// NewSnapshot returns a full snapshot
func NewSnapshot(s *Server) CompleteSnapshot {
	ss := make(map[string]*Snapshot)
	s.DB.LoadPeople()
	for _, p := range s.DB.People {
		ss[p.ID] = &Snapshot{
			Person:      p,
			Tournaments: make(map[string]*PlayerSnapshot),
		}
	}

	// Calculate the per-tournament data points
	for _, t := range s.DB.Tournaments {
		tid := t.ID
		for _, m := range t.Matches {
			for _, p := range m.Players {
				if p.Person == nil {
					continue
				}

				pid := p.Person.ID
				if _, ok := ss[pid]; !ok {
					fmt.Println("Snapshot not set for player", p.Person)
					ss[p.Person.ID] = &Snapshot{
						Person:      p.Person,
						Tournaments: make(map[string]*PlayerSnapshot),
					}
				}
				if _, ok := ss[pid].Tournaments[tid]; !ok {
					ss[pid].Tournaments[tid] = &PlayerSnapshot{}
				}

				ss[pid].Tournaments[tid].Matches++
				ss[pid].Tournaments[tid].Rounds += len(m.Rounds)
				ss[pid].Tournaments[tid].Shots += p.Shots
				ss[pid].Tournaments[tid].Sweeps += p.Sweeps
				ss[pid].Tournaments[tid].Kills += p.Kills
				ss[pid].Tournaments[tid].Self += p.Self
				ss[pid].Tournaments[tid].Score += p.Score()
				ss[pid].Tournaments[tid].Playtime += m.Duration()
			}

		}

		// Only do the winner calculations if someone actually won
		if !t.Ended.IsZero() && len(t.Winners) > 0 {
			winner := t.Winners[0].Person.ID
			ss[winner].Tournaments[tid].Wins++
		}
	}

	// Summarize the per-tournament data points into the totals
	for pid := range ss {
		if ss[pid].Total == nil {
			ss[pid].Total = &PlayerSnapshot{}
		}

		for tid := range ss[pid].Tournaments {
			t := ss[pid].Tournaments[tid]

			ss[pid].Total.Matches += t.Matches
			ss[pid].Total.Rounds += t.Rounds
			ss[pid].Total.Shots += t.Shots
			ss[pid].Total.Sweeps += t.Sweeps
			ss[pid].Total.Kills += t.Kills
			ss[pid].Total.Self += t.Self
			ss[pid].Total.Score += t.Score
			ss[pid].Total.Playtime += t.Playtime
		}
	}

	// Add the Rank attribute to all the players
	ranked := make([]*Snapshot, len(ss))
	x := 0
	for _, p := range ss {
		ranked[x] = p
		x++
	}
	for x, p := range SortByRank(ranked) {
		ss[p.Person.ID].Rank = x + 1 // The +1 fixes zero-index.
	}

	return CompleteSnapshot(ss)
}

// ByRank is a sort.Interface that sorts players by tournament wins
// and then by total score.
type ByRank []*Snapshot

func (b ByRank) Len() int {
	return len(b)
}

func (b ByRank) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

func (b ByRank) Less(i, j int) bool {
	// If a person is not actively playing, they are definitely less.
	if b[i].Person.Disabled != b[j].Person.Disabled {
		return b[j].Person.Disabled
	}

	if b[i].Total.Wins == b[j].Total.Wins {
		return b[i].Total.Score > b[j].Total.Score
	}

	return b[i].Total.Wins > b[j].Total.Wins
}

func SortByRank(ps []*Snapshot) []*Snapshot {
	sort.Sort(ByRank(ps))
	return ps
}
<commit_msg>Fix stats bug where Wins were not carried over<commit_after>package towerfall

import (
	"fmt"
	"sort"
	"time"
)

type CompleteSnapshot map[string]*Snapshot

type Snapshot struct {
	Person *Person         `json:"person"`
	Total  *PlayerSnapshot `json:"total"`
	Rank   int             `json:"rank"`
	// The Tournaments map contains the same data structure, but
	// separated per tournament
	Tournaments map[string]*PlayerSnapshot `json:"tournaments"`
}

// A PlayerSnapshot is a sum of all total stats about a player
type PlayerSnapshot struct {
	Shots    int           `json:"shots"`
	Sweeps   int           `json:"sweeps"`
	Kills    int           `json:"kills"`
	Self     int           `json:"self"`
	Matches  int           `json:"matches"`
	Rounds   int           `json:"rounds"`
	Score    int           `json:"score"`
	Playtime time.Duration `json:"playtime"`
	Wins     int           `json:"wins"`
}

// NewSnapshot returns a full snapshot
func NewSnapshot(s *Server) CompleteSnapshot {
	ss := make(map[string]*Snapshot)
	s.DB.LoadPeople()
	for _, p := range s.DB.People {
		ss[p.ID] = &Snapshot{
			Person:      p,
			Tournaments: make(map[string]*PlayerSnapshot),
		}
	}

	// Calculate the per-tournament data points
	for _, t := range s.DB.Tournaments {
		tid := t.ID
		for _, m := range t.Matches {
			for _, p := range m.Players {
				if p.Person == nil {
					continue
				}

				pid := p.Person.ID
				if _, ok := ss[pid]; !ok {
					fmt.Println("Snapshot not set for player", p.Person)
					ss[p.Person.ID] = &Snapshot{
						Person:      p.Person,
						Tournaments: make(map[string]*PlayerSnapshot),
					}
				}
				if _, ok := ss[pid].Tournaments[tid]; !ok {
					ss[pid].Tournaments[tid] = &PlayerSnapshot{}
				}

				ss[pid].Tournaments[tid].Matches++
				ss[pid].Tournaments[tid].Rounds += len(m.Rounds)
				ss[pid].Tournaments[tid].Shots += p.Shots
				ss[pid].Tournaments[tid].Sweeps += p.Sweeps
				ss[pid].Tournaments[tid].Kills += p.Kills
				ss[pid].Tournaments[tid].Self += p.Self
				ss[pid].Tournaments[tid].Score += p.Score()
				ss[pid].Tournaments[tid].Playtime += m.Duration()
			}

		}

		// Only do the winner calculations if someone actually won
		if !t.Ended.IsZero() && len(t.Winners) > 0 {
			winner := t.Winners[0].Person.ID
			ss[winner].Tournaments[tid].Wins++
		}
	}

	// Summarize the per-tournament data points into the totals
	for pid := range ss {
		if ss[pid].Total == nil {
			ss[pid].Total = &PlayerSnapshot{}
		}

		for tid := range ss[pid].Tournaments {
			t := ss[pid].Tournaments[tid]

			ss[pid].Total.Matches += t.Matches
			ss[pid].Total.Rounds += t.Rounds
			ss[pid].Total.Shots += t.Shots
			ss[pid].Total.Sweeps += t.Sweeps
			ss[pid].Total.Kills += t.Kills
			ss[pid].Total.Self += t.Self
			ss[pid].Total.Score += t.Score
			ss[pid].Total.Playtime += t.Playtime
			ss[pid].Total.Wins += t.Wins
		}
	}

	// Add the Rank attribute to all the players
	ranked := make([]*Snapshot, len(ss))
	x := 0
	for _, p := range ss {
		ranked[x] = p
		x++
	}
	for x, p := range SortByRank(ranked) {
		ss[p.Person.ID].Rank = x + 1 // The +1 fixes zero-index.
	}

	return CompleteSnapshot(ss)
}

// ByRank is a sort.Interface that sorts players by tournament wins
// and then by total score.
type ByRank []*Snapshot

func (b ByRank) Len() int {
	return len(b)
}

func (b ByRank) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

func (b ByRank) Less(i, j int) bool {
	// If a person is not actively playing, they are definitely less.
	if b[i].Person.Disabled != b[j].Person.Disabled {
		return b[j].Person.Disabled
	}

	if b[i].Total.Wins == b[j].Total.Wins {
		return b[i].Total.Score > b[j].Total.Score
	}

	return b[i].Total.Wins > b[j].Total.Wins
}

func SortByRank(ps []*Snapshot) []*Snapshot {
	sort.Sort(ByRank(ps))
	return ps
}
<|endoftext|>


<commit_before>package minio

import (
	"fmt"
	"io/ioutil"
	"log"

	"os"

	"strconv"
	"strings"

	"net/http"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/httptracer"
)

var debugClient *Client

// Debug - entry.
func Debug() {
	app := cli.NewApp()
	app.Usage = "Minio debugger"
	app.Author = "Minio.io"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "endpoint",
		},
		cli.StringFlag{
			Name: "accesskey",
		},
		cli.StringFlag{
			Name: "secretkey",
		},
		cli.BoolFlag{
			Name: "secure",
		},
		cli.BoolFlag{
			Name: "trace",
		},
	}
	app.Before = debugMain
	app.Commands = []cli.Command{
		{
			Name:  "multipart",
			Usage: "Multipart related operations",
			Action: func(ctx *cli.Context) {
				fmt.Println("here")
				cli.ShowCommandHelp(ctx, "")
			},
			Subcommands: []cli.Command{
				{
					Name:   "new",
					Usage:  "New multipart upload",
					Action: debugNewMultipart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "bucket",
							Usage: "Bucket name",
						},
						cli.StringFlag{
							Name:  "object",
							Usage: "Object name",
						},
					},
				},
				{
					Name:   "upload",
					Usage:  "Upload part",
					Action: debugUploadPart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "bucket",
							Usage: "Bucket name",
						},
						cli.StringFlag{
							Name:  "object",
							Usage: "Object name",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
						cli.IntFlag{
							Name: "number",
						},
						cli.StringFlag{
							Name: "file",
						},
					},
				},
				{
					Name:   "complete",
					Usage:  "Complete multipart",
					Action: debugCompleteMultipart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
					},
				},
				{
					Name:   "listuploads",
					Usage:  "List incomplete uploads",
					Action: debugListMultipartUploads,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "prefix",
						},
						cli.StringFlag{
							Name: "keymarker",
						},
						cli.StringFlag{
							Name: "uploadidmarker",
						},
						cli.BoolFlag{
							Name: "delimiter",
						},
						cli.IntFlag{
							Name: "maxuploads",
						},
					},
				},
				{
					Name:   "listparts",
					Usage:  "List parts",
					Action: debugListUploadParts,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
						cli.IntFlag{
							Name: "partmarker",
						},
						cli.IntFlag{
							Name: "maxparts",
						},
					},
				},
				{
					Name:   "abort",
					Usage:  "Abort multipart upload",
					Action: debugAbortMultipartUpload,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
					},
				},
			},
		},
	}
	app.RunAndExitOnError()
}

func debugMain(ctx *cli.Context) error {
	endpoint := ctx.GlobalString("endpoint")
	secure := ctx.GlobalBool("secure")
	accessKey := ctx.GlobalString("accesskey")
	secretKey := ctx.GlobalString("secretkey")
	trace := ctx.GlobalBool("trace")
	transport := http.DefaultTransport
	if trace {
		transport = httptracer.GetNewTraceTransport(newTraceV4(), http.DefaultTransport)
	}
	var err error
	debugClient, err = New(endpoint, accessKey, secretKey, secure)
	if err != nil {
		fmt.Println(err)
		cli.ShowCommandHelp(ctx, "")
		return err
	}
	debugClient.SetCustomTransport(transport)
	return nil
}

func debugNewMultipart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	result, err := debugClient.initiateMultipartUpload(bucketName, objectName, "")
	if err != nil {
		log.Fatal(err)
		cli.ShowCommandHelp(ctx, "")
	}
	fmt.Println(result.UploadID)
}

func debugUploadPart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	partNum := ctx.Int("number")
	filePath := ctx.String("file")
	f, err := os.Open(filePath)
	if err != nil {
		log.Fatal(err)
	}
	md5sum, sha256sum, partSize, err := debugClient.hashCopy(ioutil.Discard, f)
	if err != nil {
		log.Fatal(err)
	}
	_, err = f.Seek(0, 1)
	if err != nil {
		log.Fatal(err)
	}
	part, err := debugClient.uploadPart(bucketName, objectName, uploadID, f, partNum, md5sum, sha256sum, partSize)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(part)
}

func debugCompleteMultipart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	parts := ctx.Args()
	var completeUpload completeMultipartUpload
	for _, part := range parts {
		split := strings.Split(part, ".")
		partNum, err := strconv.Atoi(split[0])
		if err != nil {
			log.Fatal(err)
		}
		md5sum := split[1]
		completeUpload.Parts = append(completeUpload.Parts, completePart{
			PartNumber: partNum,
			ETag:       md5sum,
		})
	}
	result, err := debugClient.completeMultipartUpload(bucketName, objectName, uploadID, completeUpload)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}

func debugListMultipartUploads(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	prefix := ctx.String("prefix")
	keyMarker := ctx.String("keymarker")
	uploadIDMarker := ctx.String("uploadidmarker")
	delimiter := ""
	maxuploads := ctx.Int("maxuploads")
	if ctx.Bool("delimiter") {
		delimiter = "/"
	}
	result, err := debugClient.listMultipartUploadsQuery(bucketName, keyMarker, uploadIDMarker, prefix, delimiter, maxuploads)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("bucket : ", result.Bucket)
	fmt.Println("keymarker : ", result.KeyMarker)
	fmt.Println("uploadidmarker : ", result.UploadIDMarker)
	fmt.Println("nextkeymarker : ", result.NextKeyMarker)
	fmt.Println("nextuploadidmarker : ", result.NextUploadIDMarker)
	fmt.Println("encodingtype : ", result.EncodingType)
	fmt.Println("maxuploads : ", result.MaxUploads)
	fmt.Println("istruncated : ", result.IsTruncated)
	fmt.Println("prefix : ", result.Prefix)
	fmt.Println("delimiter : ", result.Delimiter)
	fmt.Println("uploads :")
	for i, upload := range result.Uploads {
		fmt.Printf("  %d : %s, %s\n", i+1, upload.Key, upload.UploadID)
	}
	fmt.Println("commonprefixes : ")
	for i, p := range result.CommonPrefixes {
		fmt.Printf("  %d : %s\n", i+1, p)
	}
}

func debugListUploadParts(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	partmarker := ctx.Int("partmarker")
	maxParts := ctx.Int("maxparts")
	result, err := debugClient.listObjectPartsQuery(bucketName, objectName, uploadID, partmarker, maxParts)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("bucket : ", result.Bucket)
	fmt.Println("object : ", result.Key)
	fmt.Println("uploadid : ", result.UploadID)
	fmt.Println("nextpartmarker : ", result.NextPartNumberMarker)
	fmt.Println("istruncated : ", result.IsTruncated)
	fmt.Println("parts :")
	for i, part := range result.ObjectParts {
		fmt.Printf("  %d : %d %s %d\n", i+1, part.PartNumber, part.ETag, part.Size)
	}
}

func debugAbortMultipartUpload(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	err := debugClient.abortMultipartUpload(bucketName, objectName, uploadID)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add env variables.<commit_after>package minio

import (
	"fmt"
	"io/ioutil"
	"log"

	"os"

	"strconv"
	"strings"

	"net/http"

	"github.com/minio/cli"
	"github.com/minio/mc/pkg/httptracer"
)

var debugClient *Client

// Debug - entry.
func Debug() {
	app := cli.NewApp()
	app.Usage = "Minio debugger"
	app.Author = "Minio.io"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "endpoint",
		},
		cli.StringFlag{
			Name: "accesskey",
		},
		cli.StringFlag{
			Name: "secretkey",
		},
		cli.BoolFlag{
			Name: "secure",
		},
		cli.BoolFlag{
			Name: "trace",
		},
	}
	app.Before = debugMain
	app.Commands = []cli.Command{
		{
			Name:  "multipart",
			Usage: "Multipart related operations",
			Action: func(ctx *cli.Context) {
				fmt.Println("here")
				cli.ShowCommandHelp(ctx, "")
			},
			Subcommands: []cli.Command{
				{
					Name:   "new",
					Usage:  "New multipart upload",
					Action: debugNewMultipart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "bucket",
							Usage: "Bucket name",
						},
						cli.StringFlag{
							Name:  "object",
							Usage: "Object name",
						},
					},
				},
				{
					Name:   "upload",
					Usage:  "Upload part",
					Action: debugUploadPart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "bucket",
							Usage: "Bucket name",
						},
						cli.StringFlag{
							Name:  "object",
							Usage: "Object name",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
						cli.IntFlag{
							Name: "number",
						},
						cli.StringFlag{
							Name: "file",
						},
					},
				},
				{
					Name:   "complete",
					Usage:  "Complete multipart",
					Action: debugCompleteMultipart,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
					},
				},
				{
					Name:   "listuploads",
					Usage:  "List incomplete uploads",
					Action: debugListMultipartUploads,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "prefix",
						},
						cli.StringFlag{
							Name: "keymarker",
						},
						cli.StringFlag{
							Name: "uploadidmarker",
						},
						cli.BoolFlag{
							Name: "delimiter",
						},
						cli.IntFlag{
							Name: "maxuploads",
						},
					},
				},
				{
					Name:   "listparts",
					Usage:  "List parts",
					Action: debugListUploadParts,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
						cli.IntFlag{
							Name: "partmarker",
						},
						cli.IntFlag{
							Name: "maxparts",
						},
					},
				},
				{
					Name:   "abort",
					Usage:  "Abort multipart upload",
					Action: debugAbortMultipartUpload,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name: "bucket",
						},
						cli.StringFlag{
							Name: "object",
						},
						cli.StringFlag{
							Name: "uploadid",
						},
					},
				},
			},
		},
	}
	app.RunAndExitOnError()
}

type minioContext struct {
	Endpoint      string
	AccessKey     string
	SecretKey     string
	Secure, Trace bool
}

func newMinioContext(ctx *cli.Context) minioContext {
	minioCtx := minioContext{}
	minioCtx.Endpoint = ctx.GlobalString("endpoint")
	if minioCtx.Endpoint == "" {
		minioCtx.Endpoint = os.Getenv("ENDPOINT")
	}
	minioCtx.AccessKey = ctx.GlobalString("accesskey")
	if minioCtx.AccessKey == "" {
		minioCtx.AccessKey = os.Getenv("ACCESS_KEY")
	}
	minioCtx.SecretKey = ctx.GlobalString("secretkey")
	if minioCtx.SecretKey == "" {
		minioCtx.SecretKey = os.Getenv("SECRET_KEY")
	}
	minioCtx.Trace = ctx.GlobalBool("trace") || os.Getenv("TRACE") == "1"
	minioCtx.Secure = ctx.GlobalBool("secure") || os.Getenv("SECURE") == "1"
	return minioCtx
}

func debugMain(ctx *cli.Context) error {
	minioCtx := newMinioContext(ctx)
	transport := http.DefaultTransport
	if minioCtx.Trace {
		transport = httptracer.GetNewTraceTransport(newTraceV4(), http.DefaultTransport)
	}
	var err error
	debugClient, err = New(minioCtx.Endpoint, minioCtx.AccessKey, minioCtx.SecretKey, minioCtx.Secure)
	if err != nil {
		fmt.Println(err)
		cli.ShowCommandHelp(ctx, "")
		return err
	}
	debugClient.SetCustomTransport(transport)
	return nil
}

func debugNewMultipart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	result, err := debugClient.initiateMultipartUpload(bucketName, objectName, "")
	if err != nil {
		log.Fatal(err)
		cli.ShowCommandHelp(ctx, "")
	}
	fmt.Println(result.UploadID)
}

func debugUploadPart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	partNum := ctx.Int("number")
	filePath := ctx.String("file")
	f, err := os.Open(filePath)
	if err != nil {
		log.Fatal(err)
	}
	md5sum, sha256sum, partSize, err := debugClient.hashCopy(ioutil.Discard, f)
	if err != nil {
		log.Fatal(err)
	}
	_, err = f.Seek(0, 1)
	if err != nil {
		log.Fatal(err)
	}
	part, err := debugClient.uploadPart(bucketName, objectName, uploadID, f, partNum, md5sum, sha256sum, partSize)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(part)
}

func debugCompleteMultipart(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	parts := ctx.Args()
	var completeUpload completeMultipartUpload
	for _, part := range parts {
		split := strings.Split(part, ".")
		partNum, err := strconv.Atoi(split[0])
		if err != nil {
			log.Fatal(err)
		}
		md5sum := split[1]
		completeUpload.Parts = append(completeUpload.Parts, completePart{
			PartNumber: partNum,
			ETag:       md5sum,
		})
	}
	result, err := debugClient.completeMultipartUpload(bucketName, objectName, uploadID, completeUpload)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(result)
}

func debugListMultipartUploads(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	prefix := ctx.String("prefix")
	keyMarker := ctx.String("keymarker")
	uploadIDMarker := ctx.String("uploadidmarker")
	delimiter := ""
	maxuploads := ctx.Int("maxuploads")
	if ctx.Bool("delimiter") {
		delimiter = "/"
	}
	result, err := debugClient.listMultipartUploadsQuery(bucketName, keyMarker, uploadIDMarker, prefix, delimiter, maxuploads)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("bucket : ", result.Bucket)
	fmt.Println("keymarker : ", result.KeyMarker)
	fmt.Println("uploadidmarker : ", result.UploadIDMarker)
	fmt.Println("nextkeymarker : ", result.NextKeyMarker)
	fmt.Println("nextuploadidmarker : ", result.NextUploadIDMarker)
	fmt.Println("encodingtype : ", result.EncodingType)
	fmt.Println("maxuploads : ", result.MaxUploads)
	fmt.Println("istruncated : ", result.IsTruncated)
	fmt.Println("prefix : ", result.Prefix)
	fmt.Println("delimiter : ", result.Delimiter)
	fmt.Println("uploads :")
	for i, upload := range result.Uploads {
		fmt.Printf("  %d : %s, %s\n", i+1, upload.Key, upload.UploadID)
	}
	fmt.Println("commonprefixes : ")
	for i, p := range result.CommonPrefixes {
		fmt.Printf("  %d : %s\n", i+1, p)
	}
}

func debugListUploadParts(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	partmarker := ctx.Int("partmarker")
	maxParts := ctx.Int("maxparts")
	result, err := debugClient.listObjectPartsQuery(bucketName, objectName, uploadID, partmarker, maxParts)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("bucket : ", result.Bucket)
	fmt.Println("object : ", result.Key)
	fmt.Println("uploadid : ", result.UploadID)
	fmt.Println("nextpartmarker : ", result.NextPartNumberMarker)
	fmt.Println("istruncated : ", result.IsTruncated)
	fmt.Println("parts :")
	for i, part := range result.ObjectParts {
		fmt.Printf("  %d : %d %s %d\n", i+1, part.PartNumber, part.ETag, part.Size)
	}
}

func debugAbortMultipartUpload(ctx *cli.Context) {
	bucketName := ctx.String("bucket")
	objectName := ctx.String("object")
	uploadID := ctx.String("uploadid")
	err := debugClient.abortMultipartUpload(bucketName, objectName, uploadID)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 Xing Xing <mikespook@gmail.com> All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package worker

import (
    "io"
    "net"
    "github.com/mikespook/gearman-go/common"
)

// The agent of job server.
type agent struct {
    conn        net.Conn
    worker      *Worker
    in chan     []byte
    out chan    *Job
    addr string
}

// Create the agent of job server.
func newAgent(addr string, worker *Worker) (a *agent, err error) {
    conn, err := net.Dial(common.NETWORK, addr)
    if err != nil {
        return
    }
    a = &agent{
        conn: conn,
        worker: worker,
        addr: addr,
        in: make(chan []byte, common.QUEUE_SIZE),
        out: make(chan *Job, common.QUEUE_SIZE),
    }
    // reset abilities
    a.WriteJob(newJob(common.REQ, common.RESET_ABILITIES, nil))
    return
}

// outputing loop
func (a *agent) outLoop() {
    ok := true
    var job *Job
    for ok {
        if job, ok = <-a.out; ok {
            if err := a.write(job.Encode()); err != nil {
                a.worker.err(err)
            }
        }
    }
}

// inputing loop
func (a *agent) inLoop() {
    defer func() {
        if r := recover(); r != nil {
            a.worker.err(common.Errorf("Exiting: %s", r))
        }
        close(a.in)
        close(a.out)
        a.worker.removeAgent(a)
    }()
    for a.worker.running {
        a.WriteJob(newJob(common.REQ, common.PRE_SLEEP, nil))
        RESTART:
        // got noop msg and in queue is zero, grab job
        rel, err := a.read()
        if err != nil {
            if err == common.ErrConnection {
                for i:= 0; i < 3 && a.worker.running; i++ {
                    if conn, err := net.Dial(common.NETWORK, a.addr); err != nil {
                        a.worker.err(common.Errorf("Reconnection: %d faild", i))
                        continue
                    } else {
                        a.conn = conn
                        goto RESTART
                    }
                }
                a.worker.err(err)
                break
            }
            a.worker.err(err)
            continue
        }
        job, err := decodeJob(rel)
        if err != nil {
            a.worker.err(err)
            continue
        }
        switch job.DataType {
        case common.NOOP:
            a.WriteJob(newJob(common.REQ, common.GRAB_JOB_UNIQ, nil))
        case common.ERROR, common.ECHO_RES, common.JOB_ASSIGN_UNIQ, common.JOB_ASSIGN:
            job.agent = a
            a.worker.in <- job
        }
    }
}

func (a *agent) Close() {
    a.conn.Close()
}

func (a *agent) Work() {
    go a.outLoop()
    go a.inLoop()
}

// Internal read
func (a *agent) read() (data []byte, err error) {
    if len(a.in) > 0 {
        // in queue is not empty
        data = <-a.in
    } else {
        for {
            buf := make([]byte, common.BUFFER_SIZE)
            var n int
            if n, err = a.conn.Read(buf); err != nil {
                if err == io.EOF && n == 0 {
                    if data == nil {
                        err = common.ErrConnection
                        return
                    }
                    break
                }
                return
            }
            data = append(data, buf[0:n]...)
            if n < common.BUFFER_SIZE {
                break
            }
        }
    }
    // split package
    tl := len(data)
    start := 0
    for i := 0; i < tl; i++ {
        if string(data[start:start+4]) == common.RES_STR {
            l := int(common.BytesToUint32([4]byte{data[start+8],
                data[start+9], data[start+10], data[start+11]}))
            total := l + 12
            if total == tl { // data is what we want
                return
            } else if total < tl{ // data[:total] is what we want, data[total:] is the more
                a.in <- data[total:]
                data = data[:total]
                return
            } else { // ops!
                break
            }
        } else {
            start++
        }
    }
    return nil, common.Errorf("Invalid data: %V", data)
}

// Send a job to the job server.
func (a *agent) WriteJob(job *Job) {
    a.out <- job
}

// Internal write the encoded job.
func (a *agent) write(buf []byte) (err error) {
    var n int
    for i := 0; i < len(buf); i += n {
        n, err = a.conn.Write(buf[i:])
        if err != nil {
            return err
        }
    }
    return
}
<commit_msg>read more<commit_after>// Copyright 2011 Xing Xing <mikespook@gmail.com> All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package worker

import (
    "io"
    "net"
    "github.com/mikespook/gearman-go/common"
)

// The agent of job server.
type agent struct {
    conn        net.Conn
    worker      *Worker
    in chan     []byte
    out chan    *Job
    addr string
}

// Create the agent of job server.
func newAgent(addr string, worker *Worker) (a *agent, err error) {
    conn, err := net.Dial(common.NETWORK, addr)
    if err != nil {
        return
    }
    a = &agent{
        conn: conn,
        worker: worker,
        addr: addr,
        in: make(chan []byte, common.QUEUE_SIZE),
        out: make(chan *Job, common.QUEUE_SIZE),
    }
    // reset abilities
    a.WriteJob(newJob(common.REQ, common.RESET_ABILITIES, nil))
    return
}

// outputing loop
func (a *agent) outLoop() {
    ok := true
    var job *Job
    for ok {
        if job, ok = <-a.out; ok {
            if err := a.write(job.Encode()); err != nil {
                a.worker.err(err)
            }
        }
    }
}

// inputing loop
func (a *agent) inLoop() {
    defer func() {
        if r := recover(); r != nil {
            a.worker.err(common.Errorf("Exiting: %s", r))
        }
        close(a.in)
        close(a.out)
        a.worker.removeAgent(a)
    }()
    for a.worker.running {
        a.WriteJob(newJob(common.REQ, common.PRE_SLEEP, nil))
        RESTART:
        // got noop msg and in queue is zero, grab job
        rel, err := a.read()
        if err != nil {
            if err == common.ErrConnection {
                for i:= 0; i < 3 && a.worker.running; i++ {
                    if conn, err := net.Dial(common.NETWORK, a.addr); err != nil {
                        a.worker.err(common.Errorf("Reconnection: %d faild", i))
                        continue
                    } else {
                        a.conn = conn
                        goto RESTART
                    }
                }
                a.worker.err(err)
                break
            }
            a.worker.err(err)
            continue
        }
        job, err := decodeJob(rel)
        if err != nil {
            a.worker.err(err)
            continue
        }
        switch job.DataType {
        case common.NOOP:
            a.WriteJob(newJob(common.REQ, common.GRAB_JOB_UNIQ, nil))
        case common.ERROR, common.ECHO_RES, common.JOB_ASSIGN_UNIQ, common.JOB_ASSIGN:
            job.agent = a
            a.worker.in <- job
        }
    }
}

func (a *agent) Close() {
    a.conn.Close()
}

func (a *agent) Work() {
    go a.outLoop()
    go a.inLoop()
}

// Internal read
func (a *agent) read() (data []byte, err error) {
BEGIN:
    inlen := len(a.in)
    if inlen > 0 {
        // in queue is not empty
        for i := 0; i < inlen; i ++ {
            data = append(data, <-a.in...)
        }
    } else {
        for {
            buf := make([]byte, common.BUFFER_SIZE)
            var n int
            if n, err = a.conn.Read(buf); err != nil {
                if err == io.EOF && n == 0 {
                    if data == nil {
                        err = common.ErrConnection
                        return
                    }
                    break
                }
                return
            }
            data = append(data, buf[0:n]...)
            if n < common.BUFFER_SIZE {
                break
            }
        }
    }
    // split package
    tl := len(data)
    start := 0
    for i := 0; i < tl; i++ {
        if string(data[start:start+4]) == common.RES_STR {
            l := int(common.BytesToUint32([4]byte{data[start+8],
            data[start+9], data[start+10], data[start+11]}))
            total := l + 12
            if total == tl { // data is what we want
                return
            } else if total < tl{ // data[:total] is what we want, data[total:] is the more
                a.in <- data[total:]
                data = data[:total]
                return
            } else { // ops! It won't be possible.
                goto BEGIN
            }
        } else {
            start++
        }
    }
    return nil, common.Errorf("Invalid data: %V", data)
}

// Send a job to the job server.
func (a *agent) WriteJob(job *Job) {
    a.out <- job
}

// Internal write the encoded job.
func (a *agent) write(buf []byte) (err error) {
    var n int
    for i := 0; i < len(buf); i += n {
        n, err = a.conn.Write(buf[i:])
        if err != nil {
            return err
        }
    }
    return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"bytes"
	"io/ioutil"
	"crypto/rand"
	"io"
	"os"
	"os/exec"
	"strings"
	"flag"
	"unicode/utf8"
)

var (
	banner []byte
	outDir string
	staticDir string
	debugging bool
	rsyncHost string
)

const (
	colBlue = "\033[0;34m"
	colGreen = "\033[0;32m"
	colBGreen = "\033[1;32m"
	colCyan = "\033[0;36m"
	colBRed = "\033[1;31m"
	colBold = "\033[1;37m"
	noCol = "\033[0m"

	nameLen = 12

	hr = "————————————————————————————————————————————————————————————————————————————————"
)

func main() {
	// Get any arguments
	outDirPtr := flag.String("o", "/var/write", "Directory where text files will be stored.")
	staticDirPtr := flag.String("s", ".", "Directory where required static files exist.")
	rsyncHostPtr := flag.String("h", "", "Hostname of the server to rsync saved files to.")
	portPtr := flag.Int("p", 2323, "Port to listen on.")
	debugPtr := flag.Bool("debug", false, "Enables garrulous debug logging.")
	flag.Parse()

	outDir = *outDirPtr
	staticDir = *staticDirPtr
	rsyncHost = *rsyncHostPtr
	debugging = *debugPtr

	fmt.Print("\nCONFIG:\n")
	fmt.Printf("Output directory  : %s\n", outDir)
	fmt.Printf("Static directory  : %s\n", staticDir)
	fmt.Printf("rsync host        : %s\n", rsyncHost)
	fmt.Printf("Debugging enabled : %t\n\n", debugging)

	fmt.Print("Initializing...")
	var err error
	banner, err = ioutil.ReadFile(staticDir + "/banner.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("DONE")

	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *portPtr))
	if err != nil {
		panic(err)
	}
	fmt.Printf("Listening on localhost:%d\n", *portPtr)

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}

		go handleConnection(conn)
	}
}

func output(c net.Conn, m string) bool {
	_, err := c.Write([]byte(m))
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func outputBytes(c net.Conn, m []byte) bool {
	_, err := c.Write(m)
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func handleConnection(c net.Conn) {
	outputBytes(c, banner)
	output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol))
	output(c, fmt.Sprintf("If this is freaking you out, you can get notified of the %sbrowser-based%s launch\ninstead at https://write.as.\n\n", colBold, noCol))

	waitForEnter(c)

	c.Close()

	fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

func waitForEnter(c net.Conn) {
	b := make([]byte, 4)

	output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol))
	for {
		n, err := c.Read(b)

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if bytes.IndexRune(b[0:n], '\n') > -1 {
			break
		}
		if err != nil || n == 0 {
			c.Close()
			break
		}
	}

	output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr))
	readInput(c)
}

func checkExit(b []byte, n int) bool {
	return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1
}

func readInput(c net.Conn) {
	defer c.Close()

	b := make([]byte, 4096)

	var post bytes.Buffer

	for {
		n, err := c.Read(b)
		post.Write(b[0:n])

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if checkExit(b, n) {
			file, err := savePost(post.Bytes())
			if err != nil {
				fmt.Printf("There was an error saving: %s\n", err)
				output(c, "Something went terribly wrong, sorry. Try again later?\n\n")
				break
			}
			output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s", hr, colBlue, file, noCol))

			if rsyncHost != "" {
				output(c, "\nPosting to secure site...")
				exec.Command("rsync", "-ptgou", outDir + "/" + file, rsyncHost + ":").Run()
				output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s", colBlue, file, noCol))
			}

			output(c, "\nSee you later.\n\n")
			break
		}

		if err != nil || n == 0 {
			break
		}
	}
}

func savePost(post []byte) (string, error) {
	filename := generateFileName()
	f, err := os.Create(outDir + "/" + filename)

	defer f.Close()

	if err != nil {
		fmt.Println(err)
	}

	var decodedPost bytes.Buffer

	// Decode UTF-8
	for len(post) > 0 {
		r, size := utf8.DecodeRune(post)
		decodedPost.WriteRune(r)

		post = post[size:]
	}

	_, err = io.WriteString(f, stripCtlAndExtFromUTF8(string(decodedPost.Bytes())))

	return filename, err
}

func generateFileName() string {
	c := nameLen
	var dictionary string = "0123456789abcdefghijklmnopqrstuvwxyz"
	var bytes = make([]byte, c)
	rand.Read(bytes)
	for k, v := range bytes {
		 bytes[k] = dictionary[v%byte(len(dictionary))]
	}
	return string(bytes)
}

func stripCtlAndExtFromUTF8(str string) string {
	return strings.Map(func(r rune) rune {
		if r == 10 || r == 13 || r >= 32 {
			return r
		}
		return -1
	}, str)
}
<commit_msg>Strip terminating telnet characters from text file<commit_after>package main

import (
	"fmt"
	"net"
	"bytes"
	"io/ioutil"
	"crypto/rand"
	"io"
	"os"
	"os/exec"
	"strings"
	"flag"
	"unicode/utf8"
)

var (
	banner []byte
	outDir string
	staticDir string
	debugging bool
	rsyncHost string
)

const (
	colBlue = "\033[0;34m"
	colGreen = "\033[0;32m"
	colBGreen = "\033[1;32m"
	colCyan = "\033[0;36m"
	colBRed = "\033[1;31m"
	colBold = "\033[1;37m"
	noCol = "\033[0m"

	nameLen = 12

	hr = "————————————————————————————————————————————————————————————————————————————————"
)

func main() {
	// Get any arguments
	outDirPtr := flag.String("o", "/var/write", "Directory where text files will be stored.")
	staticDirPtr := flag.String("s", ".", "Directory where required static files exist.")
	rsyncHostPtr := flag.String("h", "", "Hostname of the server to rsync saved files to.")
	portPtr := flag.Int("p", 2323, "Port to listen on.")
	debugPtr := flag.Bool("debug", false, "Enables garrulous debug logging.")
	flag.Parse()

	outDir = *outDirPtr
	staticDir = *staticDirPtr
	rsyncHost = *rsyncHostPtr
	debugging = *debugPtr

	fmt.Print("\nCONFIG:\n")
	fmt.Printf("Output directory  : %s\n", outDir)
	fmt.Printf("Static directory  : %s\n", staticDir)
	fmt.Printf("rsync host        : %s\n", rsyncHost)
	fmt.Printf("Debugging enabled : %t\n\n", debugging)

	fmt.Print("Initializing...")
	var err error
	banner, err = ioutil.ReadFile(staticDir + "/banner.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("DONE")

	ln, err := net.Listen("tcp", fmt.Sprintf(":%d", *portPtr))
	if err != nil {
		panic(err)
	}
	fmt.Printf("Listening on localhost:%d\n", *portPtr)

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println(err)
			continue
		}

		go handleConnection(conn)
	}
}

func output(c net.Conn, m string) bool {
	_, err := c.Write([]byte(m))
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func outputBytes(c net.Conn, m []byte) bool {
	_, err := c.Write(m)
	if err != nil {
		c.Close()
		return false
	}
	return true
}

func handleConnection(c net.Conn) {
	outputBytes(c, banner)
	output(c, fmt.Sprintf("\n%sWelcome to write.as!%s\n", colBGreen, noCol))
	output(c, fmt.Sprintf("If this is freaking you out, you can get notified of the %sbrowser-based%s launch\ninstead at https://write.as.\n\n", colBold, noCol))

	waitForEnter(c)

	c.Close()

	fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

func waitForEnter(c net.Conn) {
	b := make([]byte, 4)

	output(c, fmt.Sprintf("%sPress Enter to continue...%s\n", colBRed, noCol))
	for {
		n, err := c.Read(b)

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if bytes.IndexRune(b[0:n], '\n') > -1 {
			break
		}
		if err != nil || n == 0 {
			c.Close()
			break
		}
	}

	output(c, fmt.Sprintf("Enter anything you like.\nPress %sCtrl-D%s to publish and quit.\n%s\n", colBold, noCol, hr))
	readInput(c)
}

func checkExit(b []byte, n int) bool {
	return n > 0 && bytes.IndexRune(b[0:n], '\n') == -1
}

func readInput(c net.Conn) {
	defer c.Close()

	b := make([]byte, 4096)

	var post bytes.Buffer

	for {
		n, err := c.Read(b)
		post.Write(b[0:n])

		if debugging {
			fmt.Print(b[0:n])
			fmt.Printf("\n%d: %s\n", n, b[0:n])
		}

		if checkExit(b, n) {
			file, err := savePost(post.Bytes())
			if err != nil {
				fmt.Printf("There was an error saving: %s\n", err)
				output(c, "Something went terribly wrong, sorry. Try again later?\n\n")
				break
			}
			output(c, fmt.Sprintf("\n%s\nPosted to %shttp://nerds.write.as/%s%s", hr, colBlue, file, noCol))

			if rsyncHost != "" {
				output(c, "\nPosting to secure site...")
				exec.Command("rsync", "-ptgou", outDir + "/" + file, rsyncHost + ":").Run()
				output(c, fmt.Sprintf("\nPosted! View at %shttps://write.as/%s%s", colBlue, file, noCol))
			}

			output(c, "\nSee you later.\n\n")
			break
		}

		if err != nil || n == 0 {
			break
		}
	}
}

func savePost(post []byte) (string, error) {
	filename := generateFileName()
	f, err := os.Create(outDir + "/" + filename)

	defer f.Close()

	if err != nil {
		fmt.Println(err)
	}

	var decodedPost bytes.Buffer

	// Decode UTF-8
	for len(post) > 0 {
		r, size := utf8.DecodeRune(post)
		decodedPost.WriteRune(r)

		post = post[size:]
	}

	_, err = io.WriteString(f, stripCtlAndExtFromUTF8(string(decodedPost.Bytes())))

	return filename, err
}

func generateFileName() string {
	c := nameLen
	var dictionary string = "0123456789abcdefghijklmnopqrstuvwxyz"
	var bytes = make([]byte, c)
	rand.Read(bytes)
	for k, v := range bytes {
		 bytes[k] = dictionary[v%byte(len(dictionary))]
	}
	return string(bytes)
}

func stripCtlAndExtFromUTF8(str string) string {
	return strings.Map(func(r rune) rune {
		if r == 10 || r == 13 || (r >= 32 && r < 65533) {
			return r
		}
		return -1
	}, str)
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
nYou 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 mysqlindexer

import (
	"camli/blobref"
	"camli/blobserver"

	"os"

	mysql "github.com/Philio/GoMySQL"
)

type blobRow struct {
	blobref string
	size int64
}

func (mi *Indexer) EnumerateBlobs(dest chan *blobref.SizedBlobRef, partition blobserver.Partition, after string, limit uint, waitSeconds int) (err os.Error) {
	var client *mysql.Client
	client, err = mi.getConnection()
	if err != nil {
		return
	}
	defer mi.releaseConnection(client)

	var stmt *mysql.Statement
	stmt, err = client.Prepare("SELECT * FROM blobs WHERE blobref > ? ORDER BY blobref LIMIT ?")
	if err != nil {
		return
	}
	err = stmt.BindParams(after, limit)
	if err != nil {
		return
	}
	err = stmt.Execute()
	if err != nil {
		return
	}

	var row blobRow
	stmt.BindResult(&row.blobref, &row.size)
	for {
		var done bool
		done, err = stmt.Fetch()
		if done {
			break
		}
		if err != nil {
			return
		}
		br := blobref.Parse(row.blobref)
		if br == nil {
			continue
		}
		dest <- &blobref.SizedBlobRef{
			BlobRef: br,
			Size: row.size,
		}
	}
	dest <- nil
	return
}
<commit_msg>gofmt<commit_after>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
nYou 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 mysqlindexer

import (
	"camli/blobref"
	"camli/blobserver"

	"os"

	mysql "github.com/Philio/GoMySQL"
)

type blobRow struct {
	blobref string
	size    int64
}

func (mi *Indexer) EnumerateBlobs(dest chan *blobref.SizedBlobRef, partition blobserver.Partition, after string, limit uint, waitSeconds int) (err os.Error) {
	var client *mysql.Client
	client, err = mi.getConnection()
	if err != nil {
		return
	}
	defer mi.releaseConnection(client)

	var stmt *mysql.Statement
	stmt, err = client.Prepare("SELECT * FROM blobs WHERE blobref > ? ORDER BY blobref LIMIT ?")
	if err != nil {
		return
	}
	err = stmt.BindParams(after, limit)
	if err != nil {
		return
	}
	err = stmt.Execute()
	if err != nil {
		return
	}

	var row blobRow
	stmt.BindResult(&row.blobref, &row.size)
	for {
		var done bool
		done, err = stmt.Fetch()
		if done {
			break
		}
		if err != nil {
			return
		}
		br := blobref.Parse(row.blobref)
		if br == nil {
			continue
		}
		dest <- &blobref.SizedBlobRef{
			BlobRef: br,
			Size:    row.size,
		}
	}
	dest <- nil
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	"k8s.io/kubernetes/pkg/apis/experimental"

	. "github.com/onsi/ginkgo"
)

const (
	kind        = "replicationController"
	subresource = "scale"
)

var _ = Describe("Horizontal pod autoscaling", func() {
	var rc *ResourceConsumer
	f := NewFramework("horizontal-pod-autoscaling")

	// CPU tests
	It("[Skipped][Autoscaling Suite] should scale from 1 pod to 3 pods (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.7")
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to maximum 5 pods (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.1")
		rc.WaitForReplicas(5)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 1 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(300)
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 5 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 250, 0, 400, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.1")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(700)
		rc.WaitForReplicas(5)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod and from 1 to 3 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 800, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(1)
		rc.ConsumeCPU(700)
		rc.WaitForReplicas(3)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 5 pods to 3 pods and from 3 to 1 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 5, 700, 0, 200, 100, f)
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(100)
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

	// Memory tests
	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 800, 100, 900, f)
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 100, f)
		createMemoryHorizontalPodAutoscaler(rc, "700")
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to maximum 5 pods (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 700, 100, 800, f)
		createMemoryHorizontalPodAutoscaler(rc, "100")
		rc.WaitForReplicas(5)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 1 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 700, 100, 800, f)
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(100)
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 5 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 500, 100, 1100, f)
		createMemoryHorizontalPodAutoscaler(rc, "200")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(1000)
		rc.WaitForReplicas(5)
		rc.CleanUp()
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod and from 1 to 3 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 800, f)
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(1)
		rc.ConsumeMem(700)
		rc.WaitForReplicas(3)
		rc.CleanUp()
	})
	It("[Skipped][Autoscaling Suite] should scale from 5 pods to 3 pods and from 3 to 1 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 5, 0, 700, 100, 800, f)
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(100)
		rc.WaitForReplicas(1)
		rc.CleanUp()
	})

})

func createCPUHorizontalPodAutoscaler(rc *ResourceConsumer, cpu string) {
	hpa := &experimental.HorizontalPodAutoscaler{
		ObjectMeta: api.ObjectMeta{
			Name:      rc.name,
			Namespace: rc.framework.Namespace.Name,
		},
		Spec: experimental.HorizontalPodAutoscalerSpec{
			ScaleRef: &experimental.SubresourceReference{
				Kind:        kind,
				Name:        rc.name,
				Namespace:   rc.framework.Namespace.Name,
				Subresource: subresource,
			},
			MinReplicas: 1,
			MaxReplicas: 5,
			Target:      experimental.ResourceConsumption{Resource: api.ResourceCPU, Quantity: resource.MustParse(cpu)},
		},
	}
	_, errHPA := rc.framework.Client.Experimental().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
	expectNoError(errHPA)
}

// argument memory is in megabytes
func createMemoryHorizontalPodAutoscaler(rc *ResourceConsumer, memory string) {
	hpa := &experimental.HorizontalPodAutoscaler{
		ObjectMeta: api.ObjectMeta{
			Name:      rc.name,
			Namespace: rc.framework.Namespace.Name,
		},
		Spec: experimental.HorizontalPodAutoscalerSpec{
			ScaleRef: &experimental.SubresourceReference{
				Kind:        kind,
				Name:        rc.name,
				Namespace:   rc.framework.Namespace.Name,
				Subresource: subresource,
			},
			MinReplicas: 1,
			MaxReplicas: 5,
			Target:      experimental.ResourceConsumption{Resource: api.ResourceMemory, Quantity: resource.MustParse(memory + "M")},
		},
	}
	_, errHPA := rc.framework.Client.Experimental().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
	expectNoError(errHPA)
}
<commit_msg>Fixed panic in autoscaling e2e tests<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 e2e

import (
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/resource"
	"k8s.io/kubernetes/pkg/apis/experimental"

	. "github.com/onsi/ginkgo"
)

const (
	kind        = "replicationController"
	subresource = "scale"
)

var _ = Describe("Horizontal pod autoscaling", func() {
	var rc *ResourceConsumer
	f := NewFramework("horizontal-pod-autoscaling")

	// CPU tests
	It("[Skipped][Autoscaling Suite] should scale from 1 pod to 3 pods (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.7")
		rc.WaitForReplicas(1)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to maximum 5 pods (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.1")
		rc.WaitForReplicas(5)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 1 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 700, 0, 800, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(300)
		rc.WaitForReplicas(1)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 5 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 250, 0, 400, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.1")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(700)
		rc.WaitForReplicas(5)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod and from 1 to 3 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 800, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(1)
		rc.ConsumeCPU(700)
		rc.WaitForReplicas(3)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 5 pods to 3 pods and from 3 to 1 (scale resource: CPU)", func() {
		rc = NewDynamicResourceConsumer("rc", 5, 700, 0, 200, 100, f)
		defer rc.CleanUp()
		createCPUHorizontalPodAutoscaler(rc, "0.3")
		rc.WaitForReplicas(3)
		rc.ConsumeCPU(100)
		rc.WaitForReplicas(1)
	})

	// Memory tests
	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 800, 100, 900, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 100, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "700")
		rc.WaitForReplicas(1)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to maximum 5 pods (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 700, 100, 800, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "100")
		rc.WaitForReplicas(5)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 1 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 700, 100, 800, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(100)
		rc.WaitForReplicas(1)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 1 pod to 3 pods and from 3 to 5 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 1, 0, 500, 100, 1100, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "200")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(1000)
		rc.WaitForReplicas(5)
	})

	It("[Skipped][Horizontal pod autoscaling Suite] should scale from 3 pods to 1 pod and from 1 to 3 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 3, 0, 0, 100, 800, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(1)
		rc.ConsumeMem(700)
		rc.WaitForReplicas(3)
	})
	It("[Skipped][Autoscaling Suite] should scale from 5 pods to 3 pods and from 3 to 1 (scale resource: Memory)", func() {
		rc = NewDynamicResourceConsumer("rc", 5, 0, 700, 100, 800, f)
		defer rc.CleanUp()
		createMemoryHorizontalPodAutoscaler(rc, "300")
		rc.WaitForReplicas(3)
		rc.ConsumeMem(100)
		rc.WaitForReplicas(1)
	})

})

func createCPUHorizontalPodAutoscaler(rc *ResourceConsumer, cpu string) {
	hpa := &experimental.HorizontalPodAutoscaler{
		ObjectMeta: api.ObjectMeta{
			Name:      rc.name,
			Namespace: rc.framework.Namespace.Name,
		},
		Spec: experimental.HorizontalPodAutoscalerSpec{
			ScaleRef: &experimental.SubresourceReference{
				Kind:        kind,
				Name:        rc.name,
				Namespace:   rc.framework.Namespace.Name,
				Subresource: subresource,
			},
			MinReplicas: 1,
			MaxReplicas: 5,
			Target:      experimental.ResourceConsumption{Resource: api.ResourceCPU, Quantity: resource.MustParse(cpu)},
		},
	}
	_, errHPA := rc.framework.Client.Experimental().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
	expectNoError(errHPA)
}

// argument memory is in megabytes
func createMemoryHorizontalPodAutoscaler(rc *ResourceConsumer, memory string) {
	hpa := &experimental.HorizontalPodAutoscaler{
		ObjectMeta: api.ObjectMeta{
			Name:      rc.name,
			Namespace: rc.framework.Namespace.Name,
		},
		Spec: experimental.HorizontalPodAutoscalerSpec{
			ScaleRef: &experimental.SubresourceReference{
				Kind:        kind,
				Name:        rc.name,
				Namespace:   rc.framework.Namespace.Name,
				Subresource: subresource,
			},
			MinReplicas: 1,
			MaxReplicas: 5,
			Target:      experimental.ResourceConsumption{Resource: api.ResourceMemory, Quantity: resource.MustParse(memory + "M")},
		},
	}
	_, errHPA := rc.framework.Client.Experimental().HorizontalPodAutoscalers(rc.framework.Namespace.Name).Create(hpa)
	expectNoError(errHPA)
}
<|endoftext|>