<commit_before>package ringo

import "testing"

var actionName, id string

type usersController struct {
	Controller
}

type NetWorkController struct {
	Controller
}

type SECURYController struct {
	Controller
}

func (*usersController) New(c *Context) {
	actionName = "New"
	id = c.Params.ByName("id")
}
func (*usersController) Edit(c *Context) {
	actionName = "Edit"
	id = c.Params.ByName("id")
}
func (*usersController) List(c *Context) {
	actionName = "List"
	id = c.Params.ByName("id")
}
func (*usersController) Create(c *Context) {
	actionName = "Create"
	id = c.Params.ByName("id")
}
func (*usersController) Delete(c *Context) {
	actionName = "Delete"
	id = c.Params.ByName("id")
}
func (*usersController) Update(c *Context) {
	actionName = "Update"
	id = c.Params.ByName("id")
}
func (*usersController) Get(c *Context) {
	actionName = "Get"
	id = c.Params.ByName("id")
}
func (*usersController) MemberCustome(c *Context) {
	actionName = "MemberCustome"
	id = c.Params.ByName("id")
}
func (*usersController) CollectionCustome(c *Context) {
	actionName = "CollectionCustome"
	id = c.Params.ByName("id")
}

func TestController(t *testing.T) {

	// test controller name detective
	conrollerNamesMap := []struct {
		c    Controllerable
		name string
	}{
		{&usersController{}, "users"},
		{&NetWorkController{}, "net-work"},
		{&SECURYController{}, "secury"},
	}

	for _, cn := range conrollerNamesMap {
		if n := GetControllerName(cn.c); n != cn.name {
			t.Errorf("Controller name detect error, the name '%s' should be '%s'", n, cn.name)
		}
	}

	// test controller default actions
	cases := []struct {
		method, path, handler, id string
	}{
		{"GET", "/users", "List", ""},
		{"GET", "/users/tester", "Get", "tester"},
		{"GET", "/users/editor/edit", "Edit", "editor"},
		{"GET", "/new-users", "New", ""},
		{"POST", "/users", "Create", ""},
		{"PUT", "/users/1", "Update", "1"},
		{"PATCH", "/users/1", "Update", "1"},
		{"DELETE", "/users/2", "Delete", "2"},
		{"POST", "/users/2/custome", "MemberCustome", "2"},
		{"POST", "/user/custome", "CollectionCustome", ""},
	}

	r := NewApp()
	users := &usersController{}
	users.AddRoutes(
		ControllerRouteOption{Member: true, Path: "custome", Method: "POST", Handler: "MemberCustome"},
		ControllerRouteOption{Collection: true, Path: "custome", Name: "user", Method: "POST", Handler: "CollectionCustome"},
	)
	r.AddController(users, nil)
	context := NewContext()
	for i, c := range cases {
		id = "nil"
		actionName = "nil"
		h, _, _ := r.MatchRoute(c.path, c.method)
		if h != nil {
			h(context)
		}
		if h == nil || actionName != c.handler || id != c.id {
			t.Errorf("Test case %d failed, expect action: %s, id: %v; get handler %s, id: %v", i+1, c.handler, c.id, actionName, id)
		}
	}
}
<commit_msg>add controller test case<commit_after>package ringo

import "testing"

var actionName, id string

type usersController struct {
	Controller
}

type NetWorkController struct {
	Controller
}

type SECURYController struct {
	Controller
}

type anotherUsersController struct {
	Controller
}

func (*usersController) New(c *Context) {
	actionName = "New"
	id = c.Params.ByName("id")
}
func (*usersController) Edit(c *Context) {
	actionName = "Edit"
	id = c.Params.ByName("id")
}
func (*usersController) List(c *Context) {
	actionName = "List"
	id = c.Params.ByName("id")
}
func (*usersController) Create(c *Context) {
	actionName = "Create"
	id = c.Params.ByName("id")
}
func (*usersController) Delete(c *Context) {
	actionName = "Delete"
	id = c.Params.ByName("id")
}
func (*usersController) Update(c *Context) {
	actionName = "Update"
	id = c.Params.ByName("id")
}
func (*usersController) Get(c *Context) {
	actionName = "Get"
	id = c.Params.ByName("id")
}
func (*usersController) MemberCustome(c *Context) {
	actionName = "MemberCustome"
	id = c.Params.ByName("id")
}
func (*usersController) CollectionCustome(c *Context) {
	actionName = "CollectionCustome"
	id = c.Params.ByName("id")
}

func TestController(t *testing.T) {

	// test controller name detective
	conrollerNamesMap := []struct {
		c    Controllerable
		name string
	}{
		{&usersController{}, "users"},
		{&NetWorkController{}, "net-work"},
		{&SECURYController{}, "secury"},
	}

	for _, cn := range conrollerNamesMap {
		if n := GetControllerName(cn.c); n != cn.name {
			t.Errorf("Controller name detect error, the name '%s' should be '%s'", n, cn.name)
		}
	}

	// test controller default actions
	cases := []struct {
		method, path, handler, id string
	}{
		{"GET", "/users", "List", ""},
		{"GET", "/users/tester", "Get", "tester"},
		{"GET", "/users/editor/edit", "Edit", "editor"},
		{"GET", "/new-users", "New", ""},
		{"POST", "/users", "Create", ""},
		{"PUT", "/users/1", "Update", "1"},
		{"PATCH", "/users/1", "Update", "1"},
		{"DELETE", "/users/2", "Delete", "2"},
		{"POST", "/users/2/custome", "MemberCustome", "2"},
		{"POST", "/user/custome", "CollectionCustome", ""},
	}

	r := NewApp()
	users := &usersController{}
	users.AddRoutes(
		ControllerRouteOption{Member: true, Path: "custome", Method: "POST", Handler: "MemberCustome"},
		ControllerRouteOption{Collection: true, Path: "custome", Name: "user", Method: "POST", Handler: "CollectionCustome"},
	)
	r.AddController(users, nil)
	context := NewContext()
	for i, c := range cases {
		id = "nil"
		actionName = "nil"
		h, _, _ := r.MatchRoute(c.path, c.method)
		if h != nil {
			h(context)
		}
		if h == nil || actionName != c.handler || id != c.id {
			t.Errorf("Test case %d failed, expect action: %s, id: %v; get handler %s, id: %v", i+1, c.handler, c.id, actionName, id)
		}
	}

	func() {
		defer func() { recover() }()
		users.AddRoutes(ControllerRouteOption{Member: true, Collection: true, Path: "crash", Handler: "MemberCustome"})
		t.Errorf("RouteOption invalid should panic")
	}()

	func() {
		defer func() { recover() }()
		users := &anotherUsersController{}
		users.Name = "users"
		r.AddController(users, nil)
		t.Errorf("Add same name controller should panic")
	}()
}
<|endoftext|>


<commit_before>package controllers
import (
	"github.com/byrnedo/apibase/routes"
	"github.com/julienschmidt/httprouter"
	"encoding/json"
	. "github.com/byrnedo/apibase/logger"
	"net/http"
)

type WebController interface {
	GetRoutes() []*routes.WebRoute
}

// Registers an array of route handlers to gorilla/mux
func RegisterRoutes(rtr *httprouter.Router, controller WebController) {
	for _, route := range controller.GetRoutes() {
		rtr.Handle(route.GetMethod(), route.GetPath(), route.GetHandler())
	}
}

// Controller with json helpers
type JsonController struct {}

// Serve standard 200
func (jC *JsonController) Serve(w http.ResponseWriter, data interface{}) {
	jC.ServeWithStatus(w, data, 200)
}

// Serve with custom status
func (jC *JsonController) ServeWithStatus(w http.ResponseWriter, data interface{}, status int) {
	bytes, err := json.Marshal(data)
	if err != nil {
		Error.Println("Failed to encode json:" + err.Error())
		panic("Failed to encode payload:" + err.Error())
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(status)
	w.Write(bytes)
}
<commit_msg>Removed unnecesarry query map function. Added base controller<commit_after>package controllers
import (
	"github.com/byrnedo/apibase/routes"
	"github.com/julienschmidt/httprouter"
	"encoding/json"
	. "github.com/byrnedo/apibase/logger"
	"net/http"
	"strings"
	"strconv"
	"errors"
)

type WebController interface {
	GetRoutes() []*routes.WebRoute
}

// Registers an array of route handlers to gorilla/mux
func RegisterRoutes(rtr *httprouter.Router, controller WebController) {
	for _, route := range controller.GetRoutes() {
		rtr.Handle(route.GetMethod(), route.GetPath(), route.GetHandler())
	}
}

// Controller with json helpers
type JsonController struct {
	BaseController
}

// Serve standard 200
func (jC *JsonController) Serve(w http.ResponseWriter, data interface{}) {
	jC.ServeWithStatus(w, data, 200)
}

// Serve with custom status
func (jC *JsonController) ServeWithStatus(w http.ResponseWriter, data interface{}, status int) {
	bytes, err := json.Marshal(data)
	if err != nil {
		Error.Println("Failed to encode json:" + err.Error())
		panic("Failed to encode payload:" + err.Error())
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(status)
	w.Write(bytes)
}

type BaseController struct {}

// Gets first query string value as int
func (bC *BaseController) QueryInt(r *http.Request, param string) (int, error) {
	if vals := r.URL.Query()[param]; len(vals) > 0 {
		return strconv.Atoi(vals[0])
	}
	return 0, errors.New("Not found")
}

// Makes a map from a query string parameter formatted so that
// a query string like ?query=field:val&query=field:val2 becomes
// map[string]string{"field": {
// 		"val",
//		"val2",
// }
func (bC *BaseController) QueryMap(r *http.Request, param string) (map[string]string) {
	mapData := make(map[string]string,0)
	if vals := r.URL.Query()[param]; len(vals) > 0 {
		for _, unsplitKeyVal := range vals {
			keyVal := strings.SplitN(unsplitKeyVal, ":", 1)
			if len(keyVal) > 1 {
				mapData[keyVal[0]] = keyVal[1]
			} else {
				mapData[keyVal[0]] = ""
			}
		}
	}
	return mapData
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"time"
)

var maxSize = flag.Int64("maxSize", 20971520, "the maximum size in bytes a user is allowed to upload")
var addr = flag.String("addr", "localhost:8000", "host:port format IP address to listen on")
var subpath = flag.String("subpath", "/", "configure a subdirectory, for use with a reverse proxy (example: ./9000server -subpath=/image9000/)")
var logrequests = flag.Bool("logrequests", false, "print all HTTP requests to stdout")

var acceptedfmt = map[string]string{
	"image/jpeg":       "jpg",
	"image/png":        "png",
	"image/gif":        "gif",
	"video/webm":       "webm",
	"video/x-matroska": "mkv",
	"video/ogg":        "ogv",
	"application/ogg":  "ogg",
	"audio/ogg":        "ogg",
	"audio/mp3":        "mp3",
	"text/plain":       "txt",
}

func GenerateToken() string {
	const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"
	rand.Seed(time.Now().UTC().UnixNano())
	result := make([]byte, 14)
	for i := 0; i < 14; i++ {
		result[i] = alphanum[rand.Intn(len(alphanum))]
	}
	return string(result)
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if *logrequests {
			fmt.Printf("%s (%s) %s %s\n", r.RemoteAddr, r.UserAgent(), r.Method, r.URL)
		}
		handler.ServeHTTP(w, r)
	})
}

func UploadHandler(rw http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		r.ParseMultipartForm(*maxSize)
		file, _, _ := r.FormFile("file")
		if r.ContentLength > *maxSize {
			http.Error(rw, "File Too big!", http.StatusRequestEntityTooLarge)
			return
		}

		ImageReader := bufio.NewReader(file)
		ImageBuffer := make([]byte, r.ContentLength)
		_, err := ImageReader.Read(ImageBuffer)
		if err != nil {
			http.Error(rw, err.Error(), http.StatusInternalServerError)
			return
		}

		id := GenerateToken()
		ImageType := http.DetectContentType(ImageBuffer)
		if acceptedfmt[ImageType] != "" {
			err = ioutil.WriteFile("web/img/"+id+"."+acceptedfmt[ImageType], ImageBuffer, 0666)
			if err != nil {
				panic(err)
			}
			fmt.Println("redirecting to " + *subpath + "img/" + id + "." + acceptedfmt[ImageType])
			http.Redirect(rw, r, *subpath+"img/"+id+"."+acceptedfmt[ImageType], 301)
		} else {
			http.Error(rw, fmt.Sprintf("File type (%s) not supported.", ImageType), http.StatusBadRequest)
		}
	default:
		http.Error(rw, "Bad Request", http.StatusBadRequest)
	}
}

func main() {
	flag.Parse()

	if _, err := os.Stat("web/img"); os.IsNotExist(err) {
		os.Mkdir("web/img", 0666)
	}

	http.Handle("/", http.FileServer(http.Dir("web")))

	http.HandleFunc("/upload", UploadHandler)
	http.ListenAndServe(*addr, Log(http.DefaultServeMux))
}
<commit_msg>ghost is a bitch.<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"time"
)

var maxSize = flag.Int64("maxSize", 20971520, "the maximum size in bytes a user is allowed to upload")
var addr = flag.String("addr", "localhost:8000", "host:port format IP address to listen on")
var subpath = flag.String("subpath", "/", "configure a subdirectory, for use with a reverse proxy (example: ./9000server -subpath=/image9000/)")
var logrequests = flag.Bool("logrequests", false, "print all HTTP requests to stdout")

var acceptedfmt = map[string]string{
	"image/jpeg":       "jpg",
	"image/png":        "png",
	"image/gif":        "gif",
	"video/webm":       "webm",
	"video/x-matroska": "mkv",
	"video/ogg":        "ogv",
	"application/ogg":  "ogg",
	"audio/ogg":        "ogg",
	"audio/mp3":        "mp3",
}

func GenerateToken() string {
	const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"
	rand.Seed(time.Now().UTC().UnixNano())
	result := make([]byte, 14)
	for i := 0; i < 14; i++ {
		result[i] = alphanum[rand.Intn(len(alphanum))]
	}
	return string(result)
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if *logrequests {
			fmt.Printf("%s (%s) %s %s\n", r.RemoteAddr, r.UserAgent(), r.Method, r.URL)
		}
		handler.ServeHTTP(w, r)
	})
}

func UploadHandler(rw http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		r.ParseMultipartForm(*maxSize)
		file, _, _ := r.FormFile("file")
		if r.ContentLength > *maxSize {
			http.Error(rw, "File Too big!", http.StatusRequestEntityTooLarge)
			return
		}

		ImageReader := bufio.NewReader(file)
		ImageBuffer := make([]byte, r.ContentLength)
		_, err := ImageReader.Read(ImageBuffer)
		if err != nil {
			http.Error(rw, err.Error(), http.StatusInternalServerError)
			return
		}

		id := GenerateToken()
		ImageType := http.DetectContentType(ImageBuffer)
		if acceptedfmt[ImageType] != "" {
			err = ioutil.WriteFile("web/img/"+id+"."+acceptedfmt[ImageType], ImageBuffer, 0666)
			if err != nil {
				panic(err)
			}
			fmt.Println("redirecting to " + *subpath + "img/" + id + "." + acceptedfmt[ImageType])
			http.Redirect(rw, r, *subpath+"img/"+id+"."+acceptedfmt[ImageType], 301)
		} else {
			http.Error(rw, fmt.Sprintf("File type (%s) not supported.", ImageType), http.StatusBadRequest)
		}
	default:
		http.Error(rw, "Bad Request", http.StatusBadRequest)
	}
}

func main() {
	flag.Parse()

	if _, err := os.Stat("web/img"); os.IsNotExist(err) {
		os.Mkdir("web/img", 0666)
	}

	http.Handle("/", http.FileServer(http.Dir("web")))

	http.HandleFunc("/upload", UploadHandler)
	http.ListenAndServe(*addr, Log(http.DefaultServeMux))
}
<|endoftext|>


<commit_before>package main

import (
	"aricart/jars"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"sync"
	"time"
)

func usage() {
	fmt.Printf("patch -s <sourceDir> -t <targetDir>\n")
}

var wg sync.WaitGroup
var replaced int

func main() {
	// the arguments we require
	sourceDirPtr := flag.String("s", "", "the source directory")
	targetDirPtr := flag.String("t", "", "the target directory to patch.")

	flag.Parse()

	if "" == *sourceDirPtr || "" == *targetDirPtr {
		usage()
		return
	}

	start := time.Now()

	// build a map of filename->bundleid name on both the source and destination
	sourceJars, sourceCount := jars.FindBundles(*sourceDirPtr)
	targetJars, targetCount := jars.FindBundles(*targetDirPtr)

	// reorganize target bundles so they are indexed by bundleid to a list of files
	work := invert(*targetJars)

	// for each source file, if the file is on the destination replace it
	toReplace := 0
	replaced = 0
	for sourcePath, bundleID := range *sourceJars {
		var matches = work[bundleID]
		if matches != nil {
			patch(bundleID, sourcePath, matches)
			toReplace += len(matches)
		}
	}

	wg.Wait()

	elapsed := time.Since(start)

	fmt.Printf("Analyzed %d source file[s] and found %d bundle[s].\n", sourceCount, len(*sourceJars))
	fmt.Printf("Analyzed %d target file[s] and found %d bundle[s].\n", targetCount, len(*targetJars))
	fmt.Printf("Replaced %d/%d file[s].\n", replaced, toReplace)
	fmt.Printf("Elapsed time %s.\n", elapsed)

}

func patch(bundleID string, src string, targets []string) {
	data, err := ioutil.ReadFile(src)
	if err != nil {
		log.Fatal(err)
	}
	// add a wait for each of the copies
	wg.Add(len(targets))
	for _, target := range targets {
		// a closure here, that way we don't duplicate the data buffer
		// and also get access to the waitgroup
		go func() {
			err := ioutil.WriteFile(target, data, 0644)
			// update the waitgroup
			defer wg.Done()
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("[R] %s: %s\n", bundleID, target)
			replaced++
		}()
	}
}

// Takes a map of k and v, and returns a map of v to list of k
func invert(src map[string]string) map[string][]string {
	retVal := make(map[string][]string)
	for k, v := range src {
		var a = retVal[v]
		if a == nil {
			a = make([]string, 0, 0)
		}
		a = append(a, k)
		retVal[v] = a
	}
	return retVal
}
<commit_msg>Update jarpatcher.go<commit_after>package main

import (
	"github.com/aricart/jarpatcher/aricart/jars"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"sync"
	"time"
)

func usage() {
	fmt.Printf("patch -s <sourceDir> -t <targetDir>\n")
}

var wg sync.WaitGroup
var replaced int

func main() {
	// the arguments we require
	sourceDirPtr := flag.String("s", "", "the source directory")
	targetDirPtr := flag.String("t", "", "the target directory to patch.")

	flag.Parse()

	if "" == *sourceDirPtr || "" == *targetDirPtr {
		usage()
		return
	}

	start := time.Now()

	// build a map of filename->bundleid name on both the source and destination
	sourceJars, sourceCount := jars.FindBundles(*sourceDirPtr)
	targetJars, targetCount := jars.FindBundles(*targetDirPtr)

	// reorganize target bundles so they are indexed by bundleid to a list of files
	work := invert(*targetJars)

	// for each source file, if the file is on the destination replace it
	toReplace := 0
	replaced = 0
	for sourcePath, bundleID := range *sourceJars {
		var matches = work[bundleID]
		if matches != nil {
			patch(bundleID, sourcePath, matches)
			toReplace += len(matches)
		}
	}

	wg.Wait()

	elapsed := time.Since(start)

	fmt.Printf("Analyzed %d source file[s] and found %d bundle[s].\n", sourceCount, len(*sourceJars))
	fmt.Printf("Analyzed %d target file[s] and found %d bundle[s].\n", targetCount, len(*targetJars))
	fmt.Printf("Replaced %d/%d file[s].\n", replaced, toReplace)
	fmt.Printf("Elapsed time %s.\n", elapsed)

}

func patch(bundleID string, src string, targets []string) {
	data, err := ioutil.ReadFile(src)
	if err != nil {
		log.Fatal(err)
	}
	// add a wait for each of the copies
	wg.Add(len(targets))
	for _, target := range targets {
		// a closure here, that way we don't duplicate the data buffer
		// and also get access to the waitgroup
		go func() {
			err := ioutil.WriteFile(target, data, 0644)
			// update the waitgroup
			defer wg.Done()
			if err != nil {
				log.Fatal(err)
			}
			fmt.Printf("[R] %s: %s\n", bundleID, target)
			replaced++
		}()
	}
}

// Takes a map of k and v, and returns a map of v to list of k
func invert(src map[string]string) map[string][]string {
	retVal := make(map[string][]string)
	for k, v := range src {
		var a = retVal[v]
		if a == nil {
			a = make([]string, 0, 0)
		}
		a = append(a, k)
		retVal[v] = a
	}
	return retVal
}
<|endoftext|>


<commit_before>package hooks

import (
	"strings"
	"encoding/json"
)

// GitLabWebHook struct.
type GitLabWebHook struct {
	dataMap map[string]interface{}
	data string
}

// NewGitLabWebHook 创建一个对象.
func NewGitLabWebHook(value string) (*GitLabWebHook,error) {
	hook := &GitLabWebHook{}

	var dataMap map[string]interface{}

	if err := json.Unmarshal([]byte(value),&dataMap);err != nil {
		return hook,err
	}
	hook.data = value
	hook.dataMap = dataMap
	return hook,nil
}
// ServiceName 当前推送的服务名称.
func (p *GitLabWebHook) ServiceName() (string)  {
	return "GitLab"
}

// BeforeValue 获取推送钱的Hash值.
func (p *GitLabWebHook) BeforeValue() (string,error)  {

	return p.XPath("/before")
}

// AfterValue 获取当前的Hash值.
func (p *GitLabWebHook) AfterValue() (string,error)  {

	return p.XPath("/after")
}

// RepositoryName 获取仓库名称.
func (p *GitLabWebHook) RepositoryName()(string,error){
	return p.XPath("/project/name")
}

// BranchName 获取分支名称.
func (p *GitLabWebHook) BranchName()(string,error) {

	value,err := p.XPath("/ref")

	if err != nil {
		return "",err
	}

	return strings.TrimPrefix(value,"refs/heads/"),nil
}

// UserName 获取用户名称.
func (p *GitLabWebHook) UserName()(string,error){
	return p.XPath("/user_name")
}

// UserEmail 获取用户邮箱.
func (p *GitLabWebHook) UserEmail() (string,error){
	return p.XPath("/user_email")
}

// DefaultBranch 默认分支.
func (p *GitLabWebHook)DefaultBranch()(string,error){
	return p.XPath("/project/default_branch")
}

// XPath 读取指定路径下的值： /project/git_ssh_url 则表示读取从根目录开始project下的git_ssh_url的值
func (p *GitLabWebHook) XPath(xpath string)(string,error) {

	if strings.Trim(xpath," ") == "" {
		return "",ErrNotFound
	}
	paths := strings.Split(xpath,"/")

	if len(paths) <= 0 {
		return "",ErrNotFound
	}

	dataMap := p.dataMap

	for _,key := range paths  {
		if key == ""{
			continue
		}
		if data,ok := dataMap[key];ok {
			if data1,ok := data.(map[string]interface{}); ok {
				dataMap = data1
			}
		}
	}

	lastKey := paths[len(paths)-1]

	if v,ok := dataMap[lastKey];ok {

		if value,ok := v.(string);ok {
			return value,nil
		}
	}
	return "",ErrNotFound
}
<commit_msg>修复gitlab非master分支匹配报错<commit_after>package hooks

import (
	"encoding/json"
	"strings"
)

// GitLabWebHook struct.
type GitLabWebHook struct {
	dataMap map[string]interface{}
	data    string
}

// NewGitLabWebHook 创建一个对象.
func NewGitLabWebHook(value string) (*GitLabWebHook, error) {
	hook := &GitLabWebHook{}

	var dataMap map[string]interface{}

	if err := json.Unmarshal([]byte(value), &dataMap); err != nil {
		return hook, err
	}
	hook.data = value
	hook.dataMap = dataMap
	return hook, nil
}

// ServiceName 当前推送的服务名称.
func (p *GitLabWebHook) ServiceName() string {
	return "GitLab"
}

// BeforeValue 获取推送钱的Hash值.
func (p *GitLabWebHook) BeforeValue() (string, error) {

	return p.XPath("/before")
}

// AfterValue 获取当前的Hash值.
func (p *GitLabWebHook) AfterValue() (string, error) {

	return p.XPath("/after")
}

// RepositoryName 获取仓库名称.
func (p *GitLabWebHook) RepositoryName() (string, error) {
	return p.XPath("/project/name")
}

// BranchName 获取分支名称.
func (p *GitLabWebHook) BranchName() (string, error) {

	value, err := p.XPath("/ref")
	if err != nil {
		return "", err
	}

	// return strings.TrimLeft(value, "refs/heads/"), nil
	strs := strings.SplitAfterN(value, "/", 2)
	if len(strs) < 2 {
		return value, nil
	}
	return strs[1], nil

}

// UserName 获取用户名称.
func (p *GitLabWebHook) UserName() (string, error) {
	return p.XPath("/user_name")
}

// UserEmail 获取用户邮箱.
func (p *GitLabWebHook) UserEmail() (string, error) {
	return p.XPath("/user_email")
}

// DefaultBranch 默认分支.
func (p *GitLabWebHook) DefaultBranch() (string, error) {
	return p.XPath("/project/default_branch")
}

// XPath 读取指定路径下的值： /project/git_ssh_url 则表示读取从根目录开始project下的git_ssh_url的值
func (p *GitLabWebHook) XPath(xpath string) (string, error) {

	if strings.Trim(xpath, " ") == "" {
		return "", ErrNotFound
	}
	paths := strings.Split(xpath, "/")

	if len(paths) <= 0 {
		return "", ErrNotFound
	}

	dataMap := p.dataMap

	for _, key := range paths {
		if key == "" {
			continue
		}
		if data, ok := dataMap[key]; ok {
			if data1, ok := data.(map[string]interface{}); ok {
				dataMap = data1
			}
		}
	}

	lastKey := paths[len(paths)-1]

	if v, ok := dataMap[lastKey]; ok {

		if value, ok := v.(string); ok {
			return value, nil
		}
	}
	return "", ErrNotFound
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 core

import (
	"os"
	"os/signal"
)

// EventLoopWithInterrupt initializes Agent with plugins. Agent can be interrupted from outside using public CloseChannel.
func EventLoopWithInterrupt(agent *Agent, closeChan chan *struct{}) {
	err := agent.Start()
	if err != nil {
		agent.log.Error("Error loading core", err)
		os.Exit(1)
	}
	defer func() {
		err := agent.Stop()
		if err != nil {
			agent.log.Errorf("Agent stop error '%+v'", err)
			os.Exit(1)
		}
	}()

	sigChan := make(chan os.Signal, 1)

	signal.Notify(sigChan, os.Interrupt)
	select {
	case <-sigChan:
		agent.log.Println("Interrupt received, returning.")
		return
	case _, ok := <-closeChan:
		if ok {
			err := agent.Stop()
			if err != nil {
				agent.log.Errorf("Agent stop error '%v'", err)
				os.Exit(1)
			}
			os.Exit(0)
		}
	}
}
<commit_msg>core: use agent logger<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 core

import (
	"os"
	"os/signal"
)

// EventLoopWithInterrupt initializes Agent with plugins. Agent can be interrupted from outside using public CloseChannel.
func EventLoopWithInterrupt(agent *Agent, closeChan chan *struct{}) {
	err := agent.Start()
	if err != nil {
		agent.Error("Error loading core", err)
		os.Exit(1)
	}
	defer func() {
		err := agent.Stop()
		if err != nil {
			agent.Errorf("Agent stop error '%+v'", err)
			os.Exit(1)
		}
	}()

	sigChan := make(chan os.Signal, 1)

	signal.Notify(sigChan, os.Interrupt)
	select {
	case <-sigChan:
		agent.Println("Interrupt received, returning.")
		return
	case _, ok := <-closeChan:
		if ok {
			err := agent.Stop()
			if err != nil {
				agent.Errorf("Agent stop error '%v'", err)
				os.Exit(1)
			}
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package lib

// all supported options of ossutil
const (
	OptionConfigFile       string = "configFile"
	OptionEndpoint                = "endpoint"
	OptionAccessKeyID             = "accessKeyID"
	OptionAccessKeySecret         = "accessKeySecret"
	OptionSTSToken                = "stsToken"
    OptionACL                     = "acl"
	OptionShortFormat             = "shortFormat"
	OptionDirectory               = "directory"
	OptionRecursion               = "recursive"
	OptionBucket                  = "bucket"
	OptionForce                   = "force"
	OptionUpdate                  = "update"
	OptionDelete                  = "delete"
	OptionBigFileThreshold        = "bigfileThreshold"
	OptionCheckpointDir           = "checkpointDir"
	OptionRetryTimes              = "retryTimes"
	OptionRoutines                = "routines"
    OptionLanguage                = "language"
    OptionHashType                = "hashType"
	OptionVersion                 = "version"
)

// the elements show in stat object
const (
    StatName                string = "Name"
    StatLocation                   = "Location"
    StatCreationDate               = "CreationDate"
    StatExtranetEndpoint           = "ExtranetEndpoint"
    StatIntranetEndpoint           = "IntranetEndpoint"
    StatACL                        = "ACL"
    StatOwner                      = "Owner"
    StatLastModified               = "Last-Modified"
    StatContentMD5                 = "Content-Md5"
    StatCRC64                      = "X-Oss-Hash-Crc64ecma"
)

// the elements show in hash file
const (
    HashCRC64                   = "CRC64-ECMA"
    HashMD5                     = "MD5"
    HashContentMD5              = "Content-MD5"
)

const (
    updateEndpoint      string = "oss-cn-hangzhou.aliyuncs.com"
    updateBucket               = "ossutil-version-update"
    updateVersionObject        = "ossutilversion"
    updateBinaryLinux          = "ossutil"
    updateBinaryWindow32       = "ossutil32.exe"
    updateBinaryWindow64       = "ossutil64.exe"
    updateBinaryMac64          = "ossutilmac64"
    updateTmpVersionFile       = ".ossutil_tmp_vsersion"
)

// global public variable
const (
	Package                         string = "ossutil"
	ChannelBuf                      int    = 1000
	Version                         string = "1.0.0.Beta1"
	DefaultEndpoint                 string = "oss.aliyuncs.com"
	DefaultLanguage                        = "CH"
    EnglishLanguage                        = "EN"
	Scheme                          string = "oss"
    DefaultConfigFile                      = "~/.ossutilconfig"
	MaxUint                                = ^uint(0)
	MaxInt                                 = int(MaxUint >> 1)
	MaxUint64                              = ^uint64(0)
	MaxInt64                               = int64(MaxUint64 >> 1)
	CheckpointDir                          = ".ossutil_checkpoint"
	CheckpointSep                          = "---"
	MaxPartNum                             = 10000
	MaxIdealPartNum                        = MaxPartNum / 20
	MinIdealPartNum                        = MaxPartNum / 500
	MaxIdealPartSize                       = 524288000
	MinIdealPartSize                       = 10485760
	BigFileThreshold                       = 524288000
	MaxBigFileThreshold                    = MaxInt64
	MinBigFileThreshold                    = 0
	RetryTimes                      int    = 3
	MaxRetryTimes                   int64  = 500
	MinRetryTimes                   int64  = 1
	Routines                        int    = 1
	MaxRoutines                     int64  = 32
	MinRoutines                     int64  = 1
	DefaultHashType                 string = "crc64"
	MD5HashType                     string = "md5"
)
<commit_msg>modify case<commit_after>package lib

// all supported options of ossutil
const (
	OptionConfigFile       string = "configFile"
	OptionEndpoint                = "endpoint"
	OptionAccessKeyID             = "accessKeyID"
	OptionAccessKeySecret         = "accessKeySecret"
	OptionSTSToken                = "stsToken"
    OptionACL                     = "acl"
	OptionShortFormat             = "shortFormat"
	OptionDirectory               = "directory"
	OptionRecursion               = "recursive"
	OptionBucket                  = "bucket"
	OptionForce                   = "force"
	OptionUpdate                  = "update"
	OptionDelete                  = "delete"
	OptionBigFileThreshold        = "bigfileThreshold"
	OptionCheckpointDir           = "checkpointDir"
	OptionRetryTimes              = "retryTimes"
	OptionRoutines                = "routines"
    OptionLanguage                = "language"
    OptionHashType                = "hashType"
	OptionVersion                 = "version"
)

// the elements show in stat object
const (
    StatName                string = "Name"
    StatLocation                   = "Location"
    StatCreationDate               = "CreationDate"
    StatExtranetEndpoint           = "ExtranetEndpoint"
    StatIntranetEndpoint           = "IntranetEndpoint"
    StatACL                        = "ACL"
    StatOwner                      = "Owner"
    StatLastModified               = "Last-Modified"
    StatContentMD5                 = "Content-Md5"
    StatCRC64                      = "X-Oss-Hash-Crc64ecma"
)

// the elements show in hash file
const (
    HashCRC64                   = "CRC64-ECMA"
    HashMD5                     = "MD5"
    HashContentMD5              = "Content-MD5"
)

const (
    updateEndpoint      string = "oss-cn-hangzhou.aliyuncs.com"
    updateBucket               = "ossutil-version-update"
    updateVersionObject        = "ossutilversion"
    updateBinaryLinux          = "ossutil"
    updateBinaryWindow32       = "ossutil32.exe"
    updateBinaryWindow64       = "ossutil64.exe"
    updateBinaryMac64          = "ossutilmac64"
    updateTmpVersionFile       = ".ossutil_tmp_vsersion"
)

// global public variable
const (
	Package                         string = "ossutil"
	ChannelBuf                      int    = 1000
	Version                         string = "1.0.0.Beta1"
	DefaultEndpoint                 string = "oss.aliyuncs.com"
	DefaultLanguage                        = "CH"
    EnglishLanguage                        = "EN"
	Scheme                          string = "oss"
    DefaultConfigFile                      = "~/.ossutilconfig"
	MaxUint                                = ^uint(0)
	MaxInt                                 = int(MaxUint >> 1)
	MaxUint64                              = ^uint64(0)
	MaxInt64                               = int64(MaxUint64 >> 1)
	CheckpointDir                          = ".ossutil_checkpoint"
	CheckpointSep                          = "---"
	MaxPartNum                             = 10000
	MaxIdealPartNum                        = MaxPartNum / 20
	MinIdealPartNum                        = MaxPartNum / 500
	MaxIdealPartSize                       = 524288000
	MinIdealPartSize                       = 10485760
	BigFileThreshold                       = 524288000
	MaxBigFileThreshold                    = MaxInt64
	MinBigFileThreshold                    = 0
	RetryTimes                      int    = 1
	MaxRetryTimes                   int64  = 500
	MinRetryTimes                   int64  = 1
	Routines                        int    = 3
	MaxRoutines                     int64  = 32
	MinRoutines                     int64  = 1
	DefaultHashType                 string = "crc64"
	MD5HashType                     string = "md5"
)
<|endoftext|>


<commit_before>package integration

import (
	"fmt"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"google.golang.org/api/compute/v1"
)

var _ = Describe("VM", func() {
	FIt("creates a VM with an invalid configuration and receives an error message with logs", func() {
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-error"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		resp, err := execCPI(request)
		Expect(err).ToNot(HaveOccurred())
		Expect(resp.Error.Message).ToNot(BeEmpty())
		Expect(resp.Log).ToNot(BeEmpty())
	})

	It("executes the VM lifecycle", func() {
		var vmCID string
		By("creating a VM")
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("locating the VM")
		request = fmt.Sprintf(`{
			  "method": "has_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		exists := assertSucceedsWithResult(request).(bool)
		Expect(exists).To(Equal(true))

		By("rebooting the VM")
		request = fmt.Sprintf(`{
			  "method": "reboot_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)

	})

	It("executes the VM lifecycle with disk attachment hints", func() {
		By("creating two disks")
		var request, diskCID, diskCID2, vmCID string
		request = fmt.Sprintf(`{
			  "method": "create_disk",
			  "arguments": [32768, {}, ""]
			}`)
		diskCID = assertSucceedsWithResult(request).(string)
		diskCID2 = assertSucceedsWithResult(request).(string)

		By("creating a VM with the disk attachment hints")
		request = fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				["%v", "%v"],
				{}
			  ]
			}`, existingStemcell, networkName, diskCID, diskCID2)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the disks")
		request = fmt.Sprintf(`{
			  "method": "delete_disk",
			  "arguments": ["%v"]
			}`, diskCID)
		assertSucceeds(request)

		request = fmt.Sprintf(`{
			  "method": "delete_disk",
			  "arguments": ["%v"]
			}`, diskCID2)
		assertSucceeds(request)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with custom machine type", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "cpu": 2,
				  "ram": 5120
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle in a specific zone", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "zone": "us-central1-b"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with automatic restart disabled", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "automatic_restart": false
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("execute the VM lifecycle with OnHostMaintenance modified", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "on_host_maintenance": "TERMINATE"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)

		By("deleting the VM")
		vmCID = assertSucceedsWithResult(request).(string)
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("can execute the VM lifecycle with a preemptible VM", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "preemtible": true
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with scopes", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "service_scopes": ["devstorage.read_write"]
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	FIt("executes the VM lifecycle with a backend service", func() {
		justInstances := func(ig *compute.InstanceGroupsListInstances) []string {
			instances := make([]string, len(ig.Items))
			for _, i := range ig.Items {
				instances = append(instances, i.Instance)
			}
			return instances
		}
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "backend_service": "%v"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, backendService, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		ig, err := computeService.InstanceGroups.ListInstances(googleProject, zone, instanceGroup, &compute.InstanceGroupsListInstancesRequest{InstanceState: "RUNNING"}).Do()
		Expect(err).ToNot(HaveOccurred())
		Expect(justInstances(ig)).To(ContainElement(ContainSubstring(vmCID)))

		By("deleting the VM and confirming its removal from backend service instance group")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
		ig, err = computeService.InstanceGroups.ListInstances(googleProject, zone, instanceGroup, &compute.InstanceGroupsListInstancesRequest{InstanceState: "RUNNING"}).Do()
		Expect(err).ToNot(HaveOccurred())
		Expect(justInstances(ig)).ToNot(ContainElement(ContainSubstring(vmCID)))

	})

})
<commit_msg>bigger tests are better tests<commit_after>package integration

import (
	"fmt"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"google.golang.org/api/compute/v1"
)

var _ = Describe("VM", func() {
	It("creates a VM with an invalid configuration and receives an error message with logs", func() {
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-error"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		resp, err := execCPI(request)
		Expect(err).ToNot(HaveOccurred())
		Expect(resp.Error.Message).ToNot(BeEmpty())
		Expect(resp.Log).ToNot(BeEmpty())
	})

	It("executes the VM lifecycle", func() {
		var vmCID string
		By("creating a VM")
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("locating the VM")
		request = fmt.Sprintf(`{
			  "method": "has_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		exists := assertSucceedsWithResult(request).(bool)
		Expect(exists).To(Equal(true))

		By("rebooting the VM")
		request = fmt.Sprintf(`{
			  "method": "reboot_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)

	})

	It("executes the VM lifecycle with disk attachment hints", func() {
		By("creating two disks")
		var request, diskCID, diskCID2, vmCID string
		request = fmt.Sprintf(`{
			  "method": "create_disk",
			  "arguments": [32768, {}, ""]
			}`)
		diskCID = assertSucceedsWithResult(request).(string)
		diskCID2 = assertSucceedsWithResult(request).(string)

		By("creating a VM with the disk attachment hints")
		request = fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				["%v", "%v"],
				{}
			  ]
			}`, existingStemcell, networkName, diskCID, diskCID2)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the disks")
		request = fmt.Sprintf(`{
			  "method": "delete_disk",
			  "arguments": ["%v"]
			}`, diskCID)
		assertSucceeds(request)

		request = fmt.Sprintf(`{
			  "method": "delete_disk",
			  "arguments": ["%v"]
			}`, diskCID2)
		assertSucceeds(request)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with custom machine type", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "cpu": 2,
				  "ram": 5120
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle in a specific zone", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "zone": "us-central1-b"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with automatic restart disabled", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "automatic_restart": false
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("execute the VM lifecycle with OnHostMaintenance modified", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "on_host_maintenance": "TERMINATE"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)

		By("deleting the VM")
		vmCID = assertSucceedsWithResult(request).(string)
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("can execute the VM lifecycle with a preemptible VM", func() {
		By("creating a VM")
		var vmCID string

		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "preemtible": true
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with scopes", func() {
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "service_scopes": ["devstorage.read_write"]
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		By("deleting the VM")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
	})

	It("executes the VM lifecycle with a backend service", func() {
		justInstances := func(ig *compute.InstanceGroupsListInstances) []string {
			instances := make([]string, len(ig.Items))
			for _, i := range ig.Items {
				instances = append(instances, i.Instance)
			}
			return instances
		}
		By("creating a VM")
		var vmCID string
		request := fmt.Sprintf(`{
			  "method": "create_vm",
			  "arguments": [
				"agent",
				"%v",
				{
				  "machine_type": "n1-standard-1",
				  "backend_service": "%v"
				},
				{
				  "default": {
					"type": "dynamic",
					"cloud_properties": {
					  "tags": ["integration-delete"],
					  "network_name": "%v"
					}
				  }
				},
				[],
				{}
			  ]
			}`, existingStemcell, backendService, networkName)
		vmCID = assertSucceedsWithResult(request).(string)

		ig, err := computeService.InstanceGroups.ListInstances(googleProject, zone, instanceGroup, &compute.InstanceGroupsListInstancesRequest{InstanceState: "RUNNING"}).Do()
		Expect(err).ToNot(HaveOccurred())
		Expect(justInstances(ig)).To(ContainElement(ContainSubstring(vmCID)))

		By("deleting the VM and confirming its removal from backend service instance group")
		request = fmt.Sprintf(`{
			  "method": "delete_vm",
			  "arguments": ["%v"]
			}`, vmCID)
		assertSucceeds(request)
		ig, err = computeService.InstanceGroups.ListInstances(googleProject, zone, instanceGroup, &compute.InstanceGroupsListInstancesRequest{InstanceState: "RUNNING"}).Do()
		Expect(err).ToNot(HaveOccurred())
		Expect(justInstances(ig)).ToNot(ContainElement(ContainSubstring(vmCID)))

	})

})
<|endoftext|>


<commit_before>package ransac

import (
	"math"
	"math/rand"

	"github.com/gonum/matrix/mat64"
)

type calcError func(*mat64.Vector, *mat64.Vector) float64
type calcModel func([]*mat64.Vector) *mat64.Vector

// Problem is the formulation of the ransac problem.
type Problem struct {
	data       []*mat64.Vector
	dataLength int
	fit        calcError
	model      calcModel
}

func (p *Problem) sample(sampleSize int) []*mat64.Vector {
	sample := make([]*mat64.Vector, sampleSize)
	currentSample := 0

	for currentSample < sampleSize {
		randomIndex := random(0, p.dataLength)
		exists := existsInData(sample, p.data[randomIndex])
		if !exists {
			sample[currentSample] = p.data[randomIndex]
			currentSample++
		}
	}
	return sample
}

func (p *Problem) calcModelError(model *mat64.Vector) float64 {
	var ssd float64
	for _, point := range p.data {
		error := p.fit(model, point)
		ssd += error * error
	}
	return ssd
}

// SetModel sets a function which describes the mode.
func (p *Problem) SetModel(fn calcModel) {
	p.model = fn
}

// SetModelError sets the function, which calculates the error.
func (p *Problem) SetModelError(fn calcError) {
	p.fit = fn
}

// SetData sets the function, which sets the dataset.
func (p *Problem) SetData(data []*mat64.Vector) {
	p.data = data
	p.dataLength = len(data)
}

func (p *Problem) classifyInliers(model *mat64.Vector, sample []*mat64.Vector, maxError float64) ([]*mat64.Vector, []*mat64.Vector) {
	var inliers []*mat64.Vector
	var outliers []*mat64.Vector

	for _, point := range p.data {
		if !existsInData(sample, point) {
			error := p.fit(model, point)
			if error <= maxError {
				inliers = append(inliers, point)
			} else {
				outliers = append(outliers, point)
			}
		}
	}
	return inliers, outliers
}

// Estimate does the actual work of fitting.
func (p *Problem) Estimate(maxIterations, sampleSize int, inliersRatioLimit float64, maxError float64, improveWithConsensusSet bool) (*mat64.Vector, []*mat64.Vector, []*mat64.Vector, float64) {
	var bestInliers []*mat64.Vector
	var bestOutliers []*mat64.Vector
	var bestModel *mat64.Vector
	var bestError float64 = math.Inf(1)
	dataLength := float64(p.dataLength)

	for iteration := 0; iteration <= maxIterations; iteration++ {
		sample := p.sample(sampleSize)
		model := p.model(sample)
		inliers, outliers := p.classifyInliers(model, sample, maxError)
		inliersRatio := float64(len(inliers)) / dataLength
		if inliersRatio >= inliersRatioLimit {
			candidateModel := model
			if improveWithConsensusSet {
				candidateModel = p.model(inliers)
			}
			candidateError := p.calcModelError(candidateModel)
			if candidateError < bestError {
				bestInliers = inliers
				bestOutliers = outliers
				bestModel = candidateModel
				bestError = candidateError
			}
		}
	}

	return bestModel, bestInliers, bestOutliers, bestError
}

func random(min, max int) int {
	return rand.Intn(max-min) + min
}

func existsInData(data []*mat64.Vector, sample *mat64.Vector) bool {
	for _, point := range data {
		if point == sample {
			return true
		}
	}
	return false
}
<commit_msg>error handling sample size<commit_after>package ransac

import (
	"math"
	"math/rand"

	"github.com/gonum/matrix/mat64"
)

type calcError func(*mat64.Vector, *mat64.Vector) float64
type calcModel func([]*mat64.Vector) *mat64.Vector

// Problem is the formulation of the ransac problem.
type Problem struct {
	data       []*mat64.Vector
	dataLength int
	fit        calcError
	model      calcModel
}

func (p *Problem) sample(sampleSize int) []*mat64.Vector {
	sample := make([]*mat64.Vector, sampleSize)
	currentSample := 0

	for currentSample < sampleSize {
		randomIndex := random(0, p.dataLength)
		exists := existsInData(sample, p.data[randomIndex])
		if !exists {
			sample[currentSample] = p.data[randomIndex]
			currentSample++
		}
	}
	return sample
}

func (p *Problem) calcModelError(model *mat64.Vector) float64 {
	var ssd float64
	for _, point := range p.data {
		error := p.fit(model, point)
		ssd += error * error
	}
	return ssd
}

// SetModel sets a function which describes the mode.
func (p *Problem) SetModel(fn calcModel) {
	p.model = fn
}

// SetModelError sets the function, which calculates the error.
func (p *Problem) SetModelError(fn calcError) {
	p.fit = fn
}

// SetData sets the function, which sets the dataset.
func (p *Problem) SetData(data []*mat64.Vector) {
	p.data = data
	p.dataLength = len(data)
}

func (p *Problem) classifyInliers(model *mat64.Vector, sample []*mat64.Vector, maxError float64) ([]*mat64.Vector, []*mat64.Vector) {
	var inliers []*mat64.Vector
	var outliers []*mat64.Vector

	for _, point := range p.data {
		if !existsInData(sample, point) {
			error := p.fit(model, point)
			if error <= maxError {
				inliers = append(inliers, point)
			} else {
				outliers = append(outliers, point)
			}
		}
	}
	return inliers, outliers
}

// Estimate does the actual work of fitting.
func (p *Problem) Estimate(maxIterations, sampleSize int, inliersRatioLimit float64, maxError float64, improveWithConsensusSet bool) (*mat64.Vector, []*mat64.Vector, []*mat64.Vector, float64) {

	var bestInliers []*mat64.Vector
	var bestOutliers []*mat64.Vector
	var bestModel *mat64.Vector
	var bestError float64 = math.Inf(1)

	// Return Infinite Error, if datasize is smaller than sampleSize
	if p.dataLength < sampleSize {
		return bestModel, bestInliers, bestOutliers, bestError
	}

	dataLength := float64(p.dataLength)

	for iteration := 0; iteration <= maxIterations; iteration++ {
		sample := p.sample(sampleSize)
		model := p.model(sample)
		inliers, outliers := p.classifyInliers(model, sample, maxError)
		inliersRatio := float64(len(inliers)) / dataLength
		if inliersRatio >= inliersRatioLimit {
			candidateModel := model
			if improveWithConsensusSet {
				candidateModel = p.model(inliers)
			}
			candidateError := p.calcModelError(candidateModel)
			if candidateError < bestError {
				bestInliers = inliers
				bestOutliers = outliers
				bestModel = candidateModel
				bestError = candidateError
			}
		}
	}

	return bestModel, bestInliers, bestOutliers, bestError
}

func random(min, max int) int {
	return rand.Intn(max-min) + min
}

func existsInData(data []*mat64.Vector, sample *mat64.Vector) bool {
	for _, point := range data {
		if point == sample {
			return true
		}
	}
	return false
}
<|endoftext|>


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

package main

import (
	"os"

	"github.com/blevesearch/bleve"

	log "github.com/couchbaselabs/clog"
)

func (pindex *PIndex) Run(mgr PIndexManager) {
	close := true
	cleanup := true

	var err error = nil

	if pindex.IndexType == "bleve" {
		close, cleanup, err = RunBleveStream(mgr, pindex, pindex.Stream,
			pindex.Impl.(bleve.Index))
		if err != nil {
			log.Printf("error: RunBleveStream, close: %t, cleanup: %t, err: %v",
				close, cleanup, err)
		} else {
			log.Printf("done: RunBleveStream, close: %t, cleanup: %t",
				close, cleanup)
		}
	} else {
		log.Printf("error: PIndex.Run() saw unknown IndexType: %s", pindex.IndexType)
	}

	// NOTE: We expect the PIndexImpl to handle any inflight, concurrent
	// queries, access and Close() correctly with its own locking.
	if close {
		pindex.Impl.Close()
	}

	if cleanup {
		os.RemoveAll(pindex.Path)
	}
}

func RunBleveStream(mgr PIndexManager, pindex *PIndex, stream Stream,
	bindex bleve.Index) (bool, bool, error) {
	for req := range stream {
		// TODO: probably need things like stream reset/rollback
		// and snapshot kinds of ops here, too.

		// TODO: maybe need a more batchy API?  Perhaps, yet another
		// goroutine that clumps up up updates into bigger batches?

		switch req.Op {
		case STREAM_OP_UPDATE:
			bindex.Index(string(req.Key), req.Val)

		case STREAM_OP_DELETE:
			bindex.Delete(string(req.Key))

		case STREAM_OP_FLUSH:
			// TODO: Need to delete all records here.  So, why not
			// implement this the same as rollback to zero?

		case STREAM_OP_ROLLBACK:
			// TODO: Implement partial rollback one day.
			//
			// For now, always rollback to zero, in which we close the
			// pindex and have the janitor rebuild from scratch.
			pindex.Impl.Close()
			os.RemoveAll(pindex.Path)

			// First, respond to the stream source (example: the feed)
			// so that it can unblock.
			if req.DoneCh != nil {
				close(req.DoneCh)
			}

			// Because, here the manager/janitor will synchronously
			// ask the feed to close and we don't want a deadlock.
			mgr.ClosePIndex(pindex)

			return false, false, nil
		}

		if req.DoneCh != nil {
			close(req.DoneCh)
		}
	}

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

package main

import (
	"os"

	"github.com/blevesearch/bleve"

	log "github.com/couchbaselabs/clog"
)

func (pindex *PIndex) Run(mgr PIndexManager) {
	close := true
	cleanup := true

	var err error = nil

	if pindex.IndexType == "bleve" {
		close, cleanup, err = RunBleveStream(mgr, pindex, pindex.Stream,
			pindex.Impl.(bleve.Index))
		if err != nil {
			log.Printf("error: RunBleveStream, close: %t, cleanup: %t, err: %v",
				close, cleanup, err)
		} else {
			log.Printf("done: RunBleveStream, close: %t, cleanup: %t",
				close, cleanup)
		}
	} else {
		log.Printf("error: PIndex.Run() saw unknown IndexType: %s", pindex.IndexType)
	}

	// NOTE: We expect the PIndexImpl to handle any inflight, concurrent
	// queries, access and Close() correctly with its own locking.
	if close {
		pindex.Impl.Close()
	}

	if cleanup {
		os.RemoveAll(pindex.Path)
	}
}

func RunBleveStream(mgr PIndexManager, pindex *PIndex, stream Stream,
	bindex bleve.Index) (bool, bool, error) {
	for req := range stream {
		// TODO: probably need things like stream reset/rollback
		// and snapshot kinds of ops here, too.

		// TODO: maybe need a more batchy API?  Perhaps, yet another
		// goroutine that clumps up up updates into bigger batches?

		switch req.Op {
		case STREAM_OP_NOOP:
			// Do nothing, so stream source can use NOOP like a ping.

		case STREAM_OP_UPDATE:
			bindex.Index(string(req.Key), req.Val)

		case STREAM_OP_DELETE:
			bindex.Delete(string(req.Key))

		case STREAM_OP_FLUSH:
			// TODO: Need to delete all records here.  So, why not
			// implement this the same as rollback to zero?

		case STREAM_OP_ROLLBACK:
			// TODO: Implement partial rollback one day.
			//
			// For now, always rollback to zero, in which we close the
			// pindex and have the janitor rebuild from scratch.
			pindex.Impl.Close()
			os.RemoveAll(pindex.Path)

			// First, respond to the stream source (example: the feed)
			// so that it can unblock.
			if req.DoneCh != nil {
				close(req.DoneCh)
			}

			// Because, here the manager/janitor will synchronously
			// ask the feed to close and we don't want a deadlock.
			mgr.ClosePIndex(pindex)

			return false, false, nil
		}

		if req.DoneCh != nil {
			close(req.DoneCh)
		}
	}

	return true, true, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"math"
	"bytes"
	"strings"
	"encoding/gob"
	"sync"
	"log"
	_ "utils"
)

const (
	DEFAULT_DURATION = 24 * 60 * 60
	DEFAULT_DT = 60
)

type Storage struct {
	metrics map[string]*Metric
	split_metric_names map[string][]string
	duration int
	dt int
}

type Metric struct {
	sync.RWMutex
	array []float32
	dt int
	duration int
	latest_i int
	latest_ts_k int64 // == timestamp / dt
}

type StoredMetric struct {
	Array []float32
	Dt int
	Duration int
	Latest_i int
	Latest_ts_k int64
}

func NewStorage() *Storage {
	s := new(Storage)
	s.duration = DEFAULT_DURATION
	s.dt = DEFAULT_DT
	s.metrics = make(map[string]*Metric)
	s.split_metric_names = make(map[string][]string)
	return s
}

func NewMetric(duration int, dt int, starting_ts int64) *Metric {
	m := new(Metric)
	m.latest_i = 0
	m.duration = duration
	m.dt = dt
	m.array = make([]float32, duration / dt)
	m.latest_ts_k = starting_ts / int64(dt)
	return m
}

func (self *Storage) StoreMetric(metric_name string, value float64, ts int64) {
	metric, ok := self.metrics[metric_name]
	if !ok {
		metric = NewMetric(self.duration, self.dt, ts)
		self.metrics[metric_name] = metric
		self.split_metric_names[metric_name] = strings.Split(metric_name, ".")
	}
	metric.Store(float32(value), ts)
}

func (self *Storage) RemoveMetric(metric_name string) {
	delete(self.metrics, metric_name)
	delete(self.split_metric_names, metric_name)
}

func (self *Storage) MetricCount() int {
	return len(self.metrics)
}

func (self *Storage) SetStorageParams(duration_hours int, precision_seconds int) {
	if duration_hours <= 0 {
		log.Fatal("duration must be greater than zero")
	}
	if precision_seconds <= 0 {
		log.Fatal("precision must be greater than zero")
	}
	self.duration = duration_hours * 60 * 60
	self.dt = precision_seconds
}

func matchesPattern (s []string, pattern []string) bool {
	if len(s) != len(pattern) {
		return false
	}
	for i := range s {
		if pattern[i] != "*" && s[i] != pattern[i] {
			return false
		}
	}
	return true
}

func (self *Storage) SumByPeriodGroupingQuery(metric_group_patterns []string, periods []int64, now int64, interpolate bool) [][]float64 {
	sums := make([][]float64, len(metric_group_patterns))
	split_patterns := make([][]string, len(metric_group_patterns))
	for i := range metric_group_patterns {
		sums[i] = make([]float64, len(periods))
		split_patterns[i] = strings.Split(metric_group_patterns[i], ".")
	}

	for k := range self.metrics {
		split_k := self.split_metric_names[k]
		for i := range split_patterns {
			if matchesPattern(split_k, split_patterns[i]) {
				this_metric_sum := self.metrics[k].GetSumsPerPeriodUntilNowWithInterpolation(periods, now, interpolate)
				for j := range periods {
					sums[i][j] += this_metric_sum[j]
				}
				break // assume metric can match only one pattern
			}
		}
	}
	return sums
}

func (self *Storage) SaveToFile(filename string) error {
	temppath := filename + ".tmp"
	tempfile, err := os.Create(temppath)
	if err != nil {
		return err
	}

	enc := gob.NewEncoder(tempfile)
	err = enc.Encode(self.metrics)
	if err != nil {
		tempfile.Close()
		os.Remove(temppath)
		return err
	}
	tempfile.Close()
	err = os.Rename(temppath, filename)
	if err != nil {
		os.Remove(temppath)
		return err
	}
	return nil
}

func (self *Storage) LoadFromFile(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	dec := gob.NewDecoder(file)
	err = dec.Decode(&self.metrics)
	if err != nil {
		return err
	}
	for k := range self.metrics {
		self.split_metric_names[k] = strings.Split(k, ".")
	}
	return nil
}

func (self *Metric) Store(value float32, ts int64) {
	self.Lock()
	defer self.Unlock()
	dt_64 := int64(self.dt)
	ts_k := ts / dt_64
	/*log.Printf("(%f, %d) ts_k %d, latest_ts_k %d", value, ts, ts_k, self.latest_ts_k)*/
	if self.latest_ts_k > ts_k {
		// amend value in the past
		i := int64(self.latest_i) - (self.latest_ts_k - ts_k)
		if i < 0 {
			i += int64(len(self.array))
		}
		if i < 0 {
			// falls outside the storage period
			return
		}
		self.array[i] += value
		return
	}
	for self.latest_ts_k < ts_k {
		self.latest_i = (self.latest_i + 1) % len(self.array)
		self.array[self.latest_i] = 0.0
		self.latest_ts_k += 1
	}
	self.array[self.latest_i] += value
}

func (self *Metric) GetValueAt(ts int64) float64 {
	self.RLock()
	defer self.RUnlock()
	ts_k := ts / int64(self.dt)
	if ts_k <= self.latest_ts_k - int64(len(self.array)) || ts_k > self.latest_ts_k {
		return 0.0
	}
	d_ts_k := self.latest_ts_k - ts_k
	i := (self.latest_i - int(d_ts_k))
	if i < 0 {
		i += len(self.array)
	}
	/*log.Printf("ts %v, ts_k %v, self.latest_ts_k %v --> i %v", ts, ts_k, self.latest_ts_k, i)*/
	return float64(self.array[i])
}

func (self *Metric) GetSumBetween(ts1 int64, ts2 int64) float64 {
	self.RLock()
	defer self.RUnlock()
	ts1_k := ts1 / int64(self.dt)
	ts2_k := ts2 / int64(self.dt)
	if ts2_k <= self.latest_ts_k - int64(len(self.array)) || ts1_k > self.latest_ts_k {
		return 0.0
	}

	if ts1_k <= self.latest_ts_k - int64(len(self.array)) {
		ts1_k = self.latest_ts_k - int64(len(self.array)) + 1
	}
	if ts2_k > self.latest_ts_k {
		ts2_k = self.latest_ts_k
	}

	d_ts1_k := self.latest_ts_k - ts1_k
	i := (self.latest_i - int(d_ts1_k))
	if i < 0 {
		i += len(self.array)
	}

	sum := 0.0
	for ts1_k <= ts2_k {
		sum += float64(self.array[i])
		i = (i + 1) % len(self.array)
		ts1_k += 1
	}
	return sum
}

func (self *Metric) GetSumForLastNSeconds(seconds int64, now_ts int64) float64 {
	ts2 := now_ts + int64(self.dt)
	ts1 := now_ts - seconds
	return self.GetSumBetween(ts1, ts2)
}

func (self *Metric) GetSumsPerPeriodUntilNow(periods []int64, now int64) []float64 {
	return self.GetSumsPerPeriodUntilNowWithInterpolation(periods, now, false)
}

func (self *Metric) GetSumsPerPeriodUntilNowWithInterpolation(periods []int64, now int64, interpolate bool) []float64 {
	self.RLock()
	defer self.RUnlock()
	dt_64 := int64(self.dt)
	now_k := now / dt_64
	period_starts_k := make([]int64, len(periods))
	period_sums := make([]float64, len(periods))
	min_k := now_k
	k_intr := float64(now - now_k * dt_64) / float64(self.dt)
	/*log.Printf("now: %d, now_k * dt_64: %d, k_intr: %f", now, now_k * dt_64, k_intr)*/

	for i := range periods {
		period_starts_k[i] = int64(math.Ceil((float64(now) - float64(periods[i])) / float64(dt_64)))
		if i == 0 {
			/*log.Printf("[1]: %d, [1]_k * dt_64: %d", now - periods[i], period_starts_k[i])*/
		}
		/*if period_starts_k[i] > utils.Min(now_k, self.latest_ts_k) {*/
			/*// HACK*/
			/*log.Printf("amending period start: was %d, is now %d", period_starts_k[i], utils.Min(now_k, self.latest_ts_k))*/
			/*period_starts_k[i] = utils.Min(now_k, self.latest_ts_k)*/
		/*}*/
		if period_starts_k[i] < min_k {
			min_k = period_starts_k[i]
		}
		period_sums[i] = 0.0
	}

	if now_k <= self.latest_ts_k - int64(len(self.array)) || min_k > self.latest_ts_k {
		return period_sums
	}

	if min_k <= self.latest_ts_k - int64(len(self.array)) {
		min_k = self.latest_ts_k - int64(len(self.array)) + 1
	}
	//if now_k > self.latest_ts_k {
	//	log.Printf("Amending now_k from %d to %d", now_k, self.latest_ts_k)
	//	now_k = self.latest_ts_k
	//}

	d_min_k := self.latest_ts_k - min_k
	i := (self.latest_i - int(d_min_k))
	if i < 0 {
		i += len(self.array)
	}

	prev_val := 0.0
	/*log.Printf("min_k %d, now_k %d", min_k, now_k)*/
	for min_k <= now_k {
		var current_val float64
		if min_k <= self.latest_ts_k {
			current_val = float64(self.array[i])
		} else {
			current_val = 0.0
		}
		interpolated_val := current_val
		if interpolate {
			interpolated_val = (1 - k_intr) * prev_val
			interpolated_val += k_intr * current_val
			if min_k < now_k {
				interpolated_val += k_intr * current_val
			} else {
				interpolated_val += current_val
			}
		}
		/*log.Printf("min_k %d, interpval %f, period_starts_k[0] %d", min_k, interpolated_val, period_starts_k[0])*/
		for j := range periods {
			if period_starts_k[j] <= min_k {
				period_sums[j] += interpolated_val
				if j == 0 {
					/*log.Printf("prev %f, cur %f", prev_val, current_val)*/
				}
			}
		}
		prev_val = current_val
		i = (i + 1) % len(self.array)
		min_k += 1
	}
	return period_sums
}

func (self *Metric) GobEncode() ([]byte, error) {
	var sm StoredMetric
	var buf bytes.Buffer
	sm.Array = self.array
	sm.Dt = self.dt
	sm.Duration = self.duration
	sm.Latest_i = self.latest_i
	sm.Latest_ts_k = self.latest_ts_k
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(&sm)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (self *Metric) GobDecode(_bytes []byte) error {
	var sm StoredMetric
	buf := bytes.NewBuffer(_bytes)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&sm)
	if err != nil {
		return err
	}
	self.array = sm.Array
	self.dt = sm.Dt
	self.duration = sm.Duration
	self.latest_i = sm.Latest_i
	self.latest_ts_k = sm.Latest_ts_k
	return nil
}
<commit_msg>Fixed interpolation<commit_after>package main

import (
	"os"
	"math"
	"bytes"
	"strings"
	"encoding/gob"
	"sync"
	"log"
	_ "utils"
)

const (
	DEFAULT_DURATION = 24 * 60 * 60
	DEFAULT_DT = 60
)

type Storage struct {
	metrics map[string]*Metric
	split_metric_names map[string][]string
	duration int
	dt int
}

type Metric struct {
	sync.RWMutex
	array []float32
	dt int
	duration int
	latest_i int
	latest_ts_k int64 // == timestamp / dt
}

type StoredMetric struct {
	Array []float32
	Dt int
	Duration int
	Latest_i int
	Latest_ts_k int64
}

func NewStorage() *Storage {
	s := new(Storage)
	s.duration = DEFAULT_DURATION
	s.dt = DEFAULT_DT
	s.metrics = make(map[string]*Metric)
	s.split_metric_names = make(map[string][]string)
	return s
}

func NewMetric(duration int, dt int, starting_ts int64) *Metric {
	m := new(Metric)
	m.latest_i = 0
	m.duration = duration
	m.dt = dt
	m.array = make([]float32, duration / dt)
	m.latest_ts_k = starting_ts / int64(dt)
	return m
}

func (self *Storage) StoreMetric(metric_name string, value float64, ts int64) {
	metric, ok := self.metrics[metric_name]
	if !ok {
		metric = NewMetric(self.duration, self.dt, ts)
		self.metrics[metric_name] = metric
		self.split_metric_names[metric_name] = strings.Split(metric_name, ".")
	}
	metric.Store(float32(value), ts)
}

func (self *Storage) RemoveMetric(metric_name string) {
	delete(self.metrics, metric_name)
	delete(self.split_metric_names, metric_name)
}

func (self *Storage) MetricCount() int {
	return len(self.metrics)
}

func (self *Storage) SetStorageParams(duration_hours int, precision_seconds int) {
	if duration_hours <= 0 {
		log.Fatal("duration must be greater than zero")
	}
	if precision_seconds <= 0 {
		log.Fatal("precision must be greater than zero")
	}
	self.duration = duration_hours * 60 * 60
	self.dt = precision_seconds
}

func matchesPattern (s []string, pattern []string) bool {
	if len(s) != len(pattern) {
		return false
	}
	for i := range s {
		if pattern[i] != "*" && s[i] != pattern[i] {
			return false
		}
	}
	return true
}

func (self *Storage) SumByPeriodGroupingQuery(metric_group_patterns []string, periods []int64, now int64, interpolate bool) [][]float64 {
	sums := make([][]float64, len(metric_group_patterns))
	split_patterns := make([][]string, len(metric_group_patterns))
	for i := range metric_group_patterns {
		sums[i] = make([]float64, len(periods))
		split_patterns[i] = strings.Split(metric_group_patterns[i], ".")
	}

	for k := range self.metrics {
		split_k := self.split_metric_names[k]
		for i := range split_patterns {
			if matchesPattern(split_k, split_patterns[i]) {
				this_metric_sum := self.metrics[k].GetSumsPerPeriodUntilNowWithInterpolation(periods, now, interpolate)
				for j := range periods {
					sums[i][j] += this_metric_sum[j]
				}
				break // assume metric can match only one pattern
			}
		}
	}
	return sums
}

func (self *Storage) SaveToFile(filename string) error {
	temppath := filename + ".tmp"
	tempfile, err := os.Create(temppath)
	if err != nil {
		return err
	}

	enc := gob.NewEncoder(tempfile)
	err = enc.Encode(self.metrics)
	if err != nil {
		tempfile.Close()
		os.Remove(temppath)
		return err
	}
	tempfile.Close()
	err = os.Rename(temppath, filename)
	if err != nil {
		os.Remove(temppath)
		return err
	}
	return nil
}

func (self *Storage) LoadFromFile(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	dec := gob.NewDecoder(file)
	err = dec.Decode(&self.metrics)
	if err != nil {
		return err
	}
	for k := range self.metrics {
		self.split_metric_names[k] = strings.Split(k, ".")
	}
	return nil
}

func (self *Metric) Store(value float32, ts int64) {
	self.Lock()
	defer self.Unlock()
	dt_64 := int64(self.dt)
	ts_k := ts / dt_64
	/*log.Printf("(%f, %d) ts_k %d, latest_ts_k %d", value, ts, ts_k, self.latest_ts_k)*/
	if self.latest_ts_k > ts_k {
		// amend value in the past
		i := int64(self.latest_i) - (self.latest_ts_k - ts_k)
		if i < 0 {
			i += int64(len(self.array))
		}
		if i < 0 {
			// falls outside the storage period
			return
		}
		self.array[i] += value
		return
	}
	for self.latest_ts_k < ts_k {
		self.latest_i = (self.latest_i + 1) % len(self.array)
		self.array[self.latest_i] = 0.0
		self.latest_ts_k += 1
	}
	self.array[self.latest_i] += value
}

func (self *Metric) GetValueAt(ts int64) float64 {
	self.RLock()
	defer self.RUnlock()
	ts_k := ts / int64(self.dt)
	if ts_k <= self.latest_ts_k - int64(len(self.array)) || ts_k > self.latest_ts_k {
		return 0.0
	}
	d_ts_k := self.latest_ts_k - ts_k
	i := (self.latest_i - int(d_ts_k))
	if i < 0 {
		i += len(self.array)
	}
	/*log.Printf("ts %v, ts_k %v, self.latest_ts_k %v --> i %v", ts, ts_k, self.latest_ts_k, i)*/
	return float64(self.array[i])
}

func (self *Metric) GetSumBetween(ts1 int64, ts2 int64) float64 {
	self.RLock()
	defer self.RUnlock()
	ts1_k := ts1 / int64(self.dt)
	ts2_k := ts2 / int64(self.dt)
	if ts2_k <= self.latest_ts_k - int64(len(self.array)) || ts1_k > self.latest_ts_k {
		return 0.0
	}

	if ts1_k <= self.latest_ts_k - int64(len(self.array)) {
		ts1_k = self.latest_ts_k - int64(len(self.array)) + 1
	}
	if ts2_k > self.latest_ts_k {
		ts2_k = self.latest_ts_k
	}

	d_ts1_k := self.latest_ts_k - ts1_k
	i := (self.latest_i - int(d_ts1_k))
	if i < 0 {
		i += len(self.array)
	}

	sum := 0.0
	for ts1_k <= ts2_k {
		sum += float64(self.array[i])
		i = (i + 1) % len(self.array)
		ts1_k += 1
	}
	return sum
}

func (self *Metric) GetSumForLastNSeconds(seconds int64, now_ts int64) float64 {
	ts2 := now_ts + int64(self.dt)
	ts1 := now_ts - seconds
	return self.GetSumBetween(ts1, ts2)
}

func (self *Metric) GetSumsPerPeriodUntilNow(periods []int64, now int64) []float64 {
	return self.GetSumsPerPeriodUntilNowWithInterpolation(periods, now, false)
}

func (self *Metric) GetSumsPerPeriodUntilNowWithInterpolation(periods []int64, now int64, interpolate bool) []float64 {
	self.RLock()
	defer self.RUnlock()
	dt_64 := int64(self.dt)
	now_k := now / dt_64
	period_starts_k := make([]int64, len(periods))
	period_sums := make([]float64, len(periods))
	min_k := now_k
	k_intr := float64(now - now_k * dt_64) / float64(self.dt)
	if now == now_k * dt_64 {
		k_intr = 1.0
	}

	for i := range periods {
		period_start_ts := now - periods[i]
		period_starts_k[i] = int64(math.Ceil(float64(period_start_ts) / float64(dt_64)))
		if period_starts_k[i] < min_k {
			min_k = period_starts_k[i]
		}
		period_sums[i] = 0.0
		if interpolate {
			additional_piece := (1 - k_intr) * self.GetValueAt(period_start_ts)
			log.Printf("additional piece: %f, k_intr = %f", additional_piece, k_intr)
			period_sums[i] += additional_piece
		}
	}

	if now_k <= self.latest_ts_k - int64(len(self.array)) || min_k > self.latest_ts_k {
		return period_sums
	}

	if min_k <= self.latest_ts_k - int64(len(self.array)) {
		min_k = self.latest_ts_k - int64(len(self.array)) + 1
	}

	d_min_k := self.latest_ts_k - min_k
	i := (self.latest_i - int(d_min_k))
	if i < 0 {
		i += len(self.array)
	}

	for min_k <= now_k {
		var current_val float64
		if min_k <= self.latest_ts_k {
			current_val = float64(self.array[i])
		} else {
			current_val = 0.0
		}
		for j := range periods {
			if period_starts_k[j] <= min_k {
				period_sums[j] += current_val
			}
		}
		i = (i + 1) % len(self.array)
		min_k += 1
	}
	return period_sums
}

func (self *Metric) GobEncode() ([]byte, error) {
	var sm StoredMetric
	var buf bytes.Buffer
	sm.Array = self.array
	sm.Dt = self.dt
	sm.Duration = self.duration
	sm.Latest_i = self.latest_i
	sm.Latest_ts_k = self.latest_ts_k
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(&sm)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (self *Metric) GobDecode(_bytes []byte) error {
	var sm StoredMetric
	buf := bytes.NewBuffer(_bytes)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&sm)
	if err != nil {
		return err
	}
	self.array = sm.Array
	self.dt = sm.Dt
	self.duration = sm.Duration
	self.latest_i = sm.Latest_i
	self.latest_ts_k = sm.Latest_ts_k
	return nil
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"strconv"
	"sync/atomic"
)

var debug struct {
	// Print HTTP requests and responses to stderr.
	traceRequests bool
	// When tools issue concurrent GET requests, the normal behaviour is to
	// cancel pending requests as soon as one request fails. This option
	// restores the old behaviour or executing the remaning requests anyway.
	continueDownloading bool
	// When set to a number n, the n th HTTP request will fail.
	failRequestNum uint64

	requestNum uint64
}

func getBool(varName string) bool {
	v, _ := strconv.ParseBool(os.Getenv(varName))
	return v
}

func getUint(varName string, defaultValue uint64) uint64 {
	v, err := strconv.ParseUint(os.Getenv(varName), 10, 64)
	if err != nil {
		return defaultValue
	}
	return v
}

func init() {
	debug.traceRequests = getBool("NVD_TRACE_REQUESTS")
	debug.continueDownloading = getBool("NVD_CONTINUE_DOWNLOADING")
	debug.failRequestNum = getUint("NVD_FAIL_REQUEST", 0)
}

func obfuscateHeaders(req *http.Request) *http.Request {
	authHeaders := []string{
		"Authorization",
		// fireeye
		"X-Auth",
		"X-Auth-Hash",
		// idefense
		"Auth-Token",
	}

	headers := req.Header.Clone()
	for _, header := range authHeaders {
		if headers.Get(header) == "" {
			continue
		}
		headers.Set(header, "<obfuscated>")
	}

	// A shallow copy is enough for this usage.
	newReq := *req
	newReq.Header = headers
	return &newReq
}

func traceRequestStart(req *http.Request) uint64 {
	if !debug.traceRequests {
		return 0
	}
	id := atomic.AddUint64(&debug.requestNum, 1)
	data, _ := httputil.DumpRequest(obfuscateHeaders(req), false)
	fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data))
	return id
}

func traceRequestEnd(id uint64, resp *http.Response) {
	if !debug.traceRequests {
		return
	}
	if resp == nil {
		return
	}
	data, _ := httputil.DumpResponse(resp, false)
	fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data))
}

// StopOrContinue can help controlling the behaviour of concurrent GET requests
// when using an errgroup and encountering an error. Depending on the
// NVD_CONTINUE_DOWNLOADING env variable, this function will return the passed
// error (when we want to stop pending requests) or just log the error (when we
// want the pending requests to continue being processed).
func StopOrContinue(err error) error {
	if debug.continueDownloading {
		log.Println(err)
		return nil
	}
	return err
}
<commit_msg>client: Add missing copyright notice<commit_after>// Copyright (c) Facebook, Inc. and its affiliates.
//
// 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 client

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"strconv"
	"sync/atomic"
)

var debug struct {
	// Print HTTP requests and responses to stderr.
	traceRequests bool
	// When tools issue concurrent GET requests, the normal behaviour is to
	// cancel pending requests as soon as one request fails. This option
	// restores the old behaviour or executing the remaning requests anyway.
	continueDownloading bool
	// When set to a number n, the n th HTTP request will fail.
	failRequestNum uint64

	requestNum uint64
}

func getBool(varName string) bool {
	v, _ := strconv.ParseBool(os.Getenv(varName))
	return v
}

func getUint(varName string, defaultValue uint64) uint64 {
	v, err := strconv.ParseUint(os.Getenv(varName), 10, 64)
	if err != nil {
		return defaultValue
	}
	return v
}

func init() {
	debug.traceRequests = getBool("NVD_TRACE_REQUESTS")
	debug.continueDownloading = getBool("NVD_CONTINUE_DOWNLOADING")
	debug.failRequestNum = getUint("NVD_FAIL_REQUEST", 0)
}

func obfuscateHeaders(req *http.Request) *http.Request {
	authHeaders := []string{
		"Authorization",
		// fireeye
		"X-Auth",
		"X-Auth-Hash",
		// idefense
		"Auth-Token",
	}

	headers := req.Header.Clone()
	for _, header := range authHeaders {
		if headers.Get(header) == "" {
			continue
		}
		headers.Set(header, "<obfuscated>")
	}

	// A shallow copy is enough for this usage.
	newReq := *req
	newReq.Header = headers
	return &newReq
}

func traceRequestStart(req *http.Request) uint64 {
	if !debug.traceRequests {
		return 0
	}
	id := atomic.AddUint64(&debug.requestNum, 1)
	data, _ := httputil.DumpRequest(obfuscateHeaders(req), false)
	fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data))
	return id
}

func traceRequestEnd(id uint64, resp *http.Response) {
	if !debug.traceRequests {
		return
	}
	if resp == nil {
		return
	}
	data, _ := httputil.DumpResponse(resp, false)
	fmt.Fprintf(os.Stderr, "Req %d: %s", id, string(data))
}

// StopOrContinue can help controlling the behaviour of concurrent GET requests
// when using an errgroup and encountering an error. Depending on the
// NVD_CONTINUE_DOWNLOADING env variable, this function will return the passed
// error (when we want to stop pending requests) or just log the error (when we
// want the pending requests to continue being processed).
func StopOrContinue(err error) error {
	if debug.continueDownloading {
		log.Println(err)
		return nil
	}
	return err
}
<|endoftext|>


<commit_before>package selector

import (
	"errors"
	"testing"

	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/registry/mock"
)

func TestDefaultSelector(t *testing.T) {
	counts := map[string]int{}

	rs := newDefaultSelector(Registry(mock.NewRegistry()))

	next, err := rs.Select("foo")
	if err != nil {
		t.Errorf("Unexpected error calling default select: %v", err)
	}

	for i := 0; i < 100; i++ {
		node, err := next()
		if err != nil {
			t.Errorf("Expected node err, got err: %v", err)
		}
		counts[node.Id]++
	}

	t.Logf("Default Counts %v", counts)
}

func TestBlackList(t *testing.T) {
	r := mock.NewRegistry()

	r.Register(&registry.Service{
		Name: "test",
		Nodes: []*registry.Node{
			&registry.Node{
				Id:      "test-1",
				Address: "localhost",
				Port:    10001,
			},
			&registry.Node{
				Id:      "test-2",
				Address: "localhost",
				Port:    10002,
			},
			&registry.Node{
				Id:      "test-3",
				Address: "localhost",
				Port:    10002,
			},
		},
	})

	rs := newDefaultSelector(Registry(r))

	next, err := rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	node, err := next()
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < 4; i++ {
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	// still expecting 2 nodes
	seen := make(map[string]bool)

	for i := 0; i < 10; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		seen[node.Id] = true
	}

	if len(seen) != 2 {
		t.Fatalf("Expected seen to be 2 %+v", seen)
	}

	// blacklist all of it
	for i := 0; i < 9; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != ErrNoneAvailable {
		t.Fatalf("Expected %v got %v", ErrNoneAvailable, err)
	}

}
<commit_msg>Blacklist for longer to ensure it works<commit_after>package selector

import (
	"errors"
	"testing"

	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/registry/mock"
)

func TestDefaultSelector(t *testing.T) {
	counts := map[string]int{}

	rs := newDefaultSelector(Registry(mock.NewRegistry()))

	next, err := rs.Select("foo")
	if err != nil {
		t.Errorf("Unexpected error calling default select: %v", err)
	}

	for i := 0; i < 100; i++ {
		node, err := next()
		if err != nil {
			t.Errorf("Expected node err, got err: %v", err)
		}
		counts[node.Id]++
	}

	t.Logf("Default Counts %v", counts)
}

func TestBlackList(t *testing.T) {
	r := mock.NewRegistry()

	r.Register(&registry.Service{
		Name: "test",
		Nodes: []*registry.Node{
			&registry.Node{
				Id:      "test-1",
				Address: "localhost",
				Port:    10001,
			},
			&registry.Node{
				Id:      "test-2",
				Address: "localhost",
				Port:    10002,
			},
			&registry.Node{
				Id:      "test-3",
				Address: "localhost",
				Port:    10002,
			},
		},
	})

	rs := newDefaultSelector(Registry(r))

	next, err := rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	node, err := next()
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < 4; i++ {
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != nil {
		t.Fatal(err)
	}

	// still expecting 2 nodes
	seen := make(map[string]bool)

	for i := 0; i < 10; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		seen[node.Id] = true
	}

	if len(seen) != 2 {
		t.Fatalf("Expected seen to be 2 %+v", seen)
	}

	// blacklist all of it
	for i := 0; i < 20; i++ {
		node, err = next()
		if err != nil {
			t.Fatal(err)
		}
		rs.Mark("test", node, errors.New("error"))
	}

	next, err = rs.Select("test")
	if err != ErrNoneAvailable {
		t.Fatalf("Expected %v got %v", ErrNoneAvailable, err)
	}

}
<|endoftext|>


<commit_before>package space_test

import (
	. "cf/commands/space"
	"cf/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	testapi "testhelpers/api"
	testassert "testhelpers/assert"
	testcmd "testhelpers/commands"
	testconfig "testhelpers/configuration"
	testreq "testhelpers/requirements"
	testterm "testhelpers/terminal"
	"cf/configuration"
)

var _ = Describe("rename-space command", func() {
	var (
		ui *testterm.FakeUI
		configRepo configuration.ReadWriter
		reqFactory *testreq.FakeReqFactory
		spaceRepo *testapi.FakeSpaceRepository
	)

	BeforeEach(func() {
		ui = new(testterm.FakeUI)
		configRepo = testconfig.NewRepositoryWithDefaults()
		reqFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedOrgSuccess: true}
		spaceRepo = &testapi.FakeSpaceRepository{}
	})

	var callRenameSpace = func(args []string) {
		cmd := NewRenameSpace(ui, configRepo, spaceRepo)
		testcmd.RunCommand(cmd, testcmd.NewContext("create-space", args), reqFactory)
	}

	Describe("when the user is not logged in", func() {
		It("does not pass requirements", func() {
			reqFactory.LoginSuccess = false
			callRenameSpace([]string{"my-space", "my-new-space"})
			Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
		})
	})

	Describe("when the user has not targeted an org", func() {
		It("does not pass requirements", func() {
			reqFactory.TargetedOrgSuccess = false
			callRenameSpace([]string{"my-space", "my-new-space"})
			Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
		})
	})

	Describe("when the user provides fewer than two args", func() {
		It("fails with usage", func() {
			callRenameSpace([]string{"foo"})
			Expect(ui.FailedWithUsage).To(BeTrue())
		})
	})

	It("renames a space", func() {
		space := models.Space{}
		space.Name = "my-space"
		space.Guid = "my-space-guid"
		reqFactory.Space = space

		callRenameSpace([]string{"my-space", "my-new-space"})

		testassert.SliceContains(ui.Outputs, testassert.Lines{
			{"Renaming space", "my-space", "my-new-space", "my-org", "my-user"},
			{"OK"},
		})

		Expect(spaceRepo.RenameSpaceGuid).To(Equal("my-space-guid"))
		Expect(spaceRepo.RenameNewName).To(Equal("my-new-space"))
	})
})
<commit_msg>Backfill tests for rename-space with the currently targeted space<commit_after>package space_test

import (
	. "cf/commands/space"
	"cf/configuration"
	"cf/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	testapi "testhelpers/api"
	testassert "testhelpers/assert"
	testcmd "testhelpers/commands"
	testconfig "testhelpers/configuration"
	testreq "testhelpers/requirements"
	testterm "testhelpers/terminal"
)

var _ = Describe("rename-space command", func() {
	var (
		ui         *testterm.FakeUI
		configRepo configuration.ReadWriter
		reqFactory *testreq.FakeReqFactory
		spaceRepo  *testapi.FakeSpaceRepository
	)

	BeforeEach(func() {
		ui = new(testterm.FakeUI)
		configRepo = testconfig.NewRepositoryWithDefaults()
		reqFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedOrgSuccess: true}
		spaceRepo = &testapi.FakeSpaceRepository{}
	})

	var callRenameSpace = func(args []string) {
		cmd := NewRenameSpace(ui, configRepo, spaceRepo)
		testcmd.RunCommand(cmd, testcmd.NewContext("create-space", args), reqFactory)
	}

	Describe("when the user is not logged in", func() {
		It("does not pass requirements", func() {
			reqFactory.LoginSuccess = false
			callRenameSpace([]string{"my-space", "my-new-space"})
			Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
		})
	})

	Describe("when the user has not targeted an org", func() {
		It("does not pass requirements", func() {
			reqFactory.TargetedOrgSuccess = false
			callRenameSpace([]string{"my-space", "my-new-space"})
			Expect(testcmd.CommandDidPassRequirements).To(BeFalse())
		})
	})

	Describe("when the user provides fewer than two args", func() {
		It("fails with usage", func() {
			callRenameSpace([]string{"foo"})
			Expect(ui.FailedWithUsage).To(BeTrue())
		})
	})

	Describe("when the user is logged in and has provided an old and new space name", func() {
		BeforeEach(func() {
			space := models.Space{}
			space.Name = "the-old-space-name"
			space.Guid = "the-old-space-guid"
			reqFactory.Space = space
		})

		It("renames a space", func() {
			originalSpaceName := configRepo.SpaceFields().Name
			callRenameSpace([]string{"the-old-space-name", "my-new-space"})

			testassert.SliceContains(ui.Outputs, testassert.Lines{
				{"Renaming space", "the-old-space-name", "my-new-space", "my-org", "my-user"},
				{"OK"},
			})

			Expect(spaceRepo.RenameSpaceGuid).To(Equal("the-old-space-guid"))
			Expect(spaceRepo.RenameNewName).To(Equal("my-new-space"))
			Expect(configRepo.SpaceFields().Name).To(Equal(originalSpaceName))
		})

		Describe("renaming the space the user has targeted", func() {
			BeforeEach(func() {
				configRepo.SetSpaceFields(reqFactory.Space.SpaceFields)
			})

			It("renames the targeted space", func() {
				callRenameSpace([]string{"the-old-space-name", "my-new-space-name"})
				Expect(configRepo.SpaceFields().Name).To(Equal("my-new-space-name"))
			})
		})
	})
})
<|endoftext|>