<commit_before>package digletts

import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
)

var tilesets *TilesetIndex

func TilesetRoutes(prefix, mbtPath string) (r *RouteHandler) {
	tilesets = ReadTilesets(mbtPath)
	r = &RouteHandler{prefix, []Route{
		//Route{"/io/{ts}", ioHandler},
		Route{"/rpc", rpcHandler},
		Route{"/{ts}/{z}/{x}/{y}", tileHandler},
		Route{"/{ts}", metadataHandler},
		Route{"/", listHandler},
	}}
	/*
		go func() {
			for event := range tilesets.Events {
				tilehub.broadcast <- event
				info("Tileset Change - %s", event.String())
			}
		}()
	*/
	return
}

// Reads the tile, dynamically determines enconding and content-type
func tileHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	vars := mux.Vars(r)
	x, err := atoi(vars["x"])
	if err != nil {
		panic(err)
		msg = ErrorMsg(http.StatusBadRequest, "Could not parse param x: "+vars["x"])
		return
	}
	y, err := atoi(vars["y"])
	if err != nil {
		msg = ErrorMsg(http.StatusBadRequest, "Could not parse param y: "+vars["y"])
		return
	}
	z, err := atoi(vars["z"])
	if err != nil {
		msg = ErrorMsg(http.StatusBadRequest, "Could not parse param z: "+vars["z"])
		return
	}
	method := GetTile
	params := map[string]interface{}{
		"tileset": vars["ts"],
		"x":       float64(x),
		"y":       float64(y),
		"z":       float64(z),
	}
	resp, rerr := methods.Execute(method, params)
	if rerr != nil {
		msg = ErrorMsg(http.StatusBadRequest, rerr.Message)
		return
	}
	tile, err := assertTile(resp.Result)
	if err != nil {
		msg = ErrorMsg(http.StatusInternalServerError, "Internal Error asserting tile")
		return
	}
	headers := formatEncoding[tile.SniffFormat()]
	for _, h := range headers {
		w.Header().Set(h.key, h.value)
	}
	w.Header().Set("Content-Length", sprintSizeOf(tile.Data))
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Write(tile.Data)
	return
}

// Get the metadatadata map from the tileset
func metadataHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	//TODO if there's a json field, try to deserialze that
	vars := mux.Vars(r)
	slug := vars["ts"]
	if ts, ok := tilesets.Tilesets[slug]; ok {
		msg = SuccessMsg(ts.Metadata().Attributes())
	} else {
		msg = ErrorMsg(http.StatusBadRequest, fmt.Sprintf("No tileset named %q", slug))
	}
	return
}

// List the tilesets available on the server
func listHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	tss := make(map[string]map[string]string)
	for name, ts := range tilesets.Tilesets {
		tss[name] = ts.Metadata().Attributes()
	}
	msg = SuccessMsg(tss)
	return
}

// From http://www.jsonrpc.org/specification
// Content-Type: MUST be application/json.
// Content-Length: MUST contain the correct length according to the HTTP-specification.
// Accept: MUST be application/json.
func rpcHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	switch {
	case r.Method != "POST":
		msg = ErrorMsg(http.StatusMethodNotAllowed, "Requires method: POST")
	case r.Header.Get("Content-Type") != "application/json":
		msg = ErrorMsg(http.StatusUnsupportedMediaType, "Requires Content-Type: application/json")
	case r.Header.Get("Accept") != "application/json":
		msg = ErrorMsg(http.StatusNotAcceptable, "Requires Accept: application/json")
	case r.Header.Get("Content-Length") == "":
		//TODO is it necessary to asset lenght is correct?
		msg = ErrorMsg(http.StatusLengthRequired, "Requires valid Content-Length")
	default:
		if req, rerr := ReadRequestMessage(r.Body); rerr != nil {
			msg = ErrorMsg(rerr.Code, rerr.Message)
		} else {
			msg = req.ExecuteMethod()
		}
	}
	return
}

/*
func ioHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	if r.Method != "GET" {
		msg = ErrorMsg(http.StatusMethodNotAllowed, "Only GET can be upgraded")
		return
	}
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		warn(err)
		msg = ErrorMsg(http.StatusInternalServerError, "Request can't be upgraded")
		return
	}
	vars := mux.Vars(r)
	slug := vars["ts"]
	if ts, ok := tilesets.Tilesets[slug]; !ok {
		msg = ErrorMsg(http.StatusBadRequest, fmt.Sprintf("No tileset named %q", slug))
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	h.register <- c
	go c.writePump()
	c.readPump()
}
*/
<commit_msg>gettile method<commit_after>package digletts

import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
)

var tilesets *TilesetIndex

func TilesetRoutes(prefix, mbtPath string) (r *RouteHandler) {
	tilesets = ReadTilesets(mbtPath)
	r = &RouteHandler{prefix, []Route{
		//Route{"/io/{ts}", ioHandler},
		Route{"/rpc", rpcHandler},
		Route{"/{ts}/{z}/{x}/{y}", tileHandler},
		Route{"/{ts}", metadataHandler},
		Route{"/", listHandler},
	}}
	/*
		go func() {
			for event := range tilesets.Events {
				tilehub.broadcast <- event
				info("Tileset Change - %s", event.String())
			}
		}()
	*/
	return
}

// Reads the tile, dynamically determines enconding and content-type
func tileHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	vars := mux.Vars(r)
	xyz := make([3]float64)
	for i, v := range []string{vars["x"], vars["y"], vars["z"]} {
		iv, err := atoi(vars["x"])
		if err != nil {
			msg = ErrorMsg(http.StatusBadRequest, "Could not parse url tile coordinate param: "+v)
			return
		}
		xyz[i] = float64(iv)
	}
	method := GetTile
	params := map[string]interface{}{
		"tileset": vars["ts"],
		"x":       xyz[0],
		"y":       xyz[1],
		"z":       xyz[2],
	}
	resp, rerr := methods.Execute(method, params)
	if rerr != nil {
		msg = ErrorMsg(http.StatusBadRequest, rerr.Message)
		return
	}
	tile, err := assertTile(resp.Result)
	if err != nil {
		msg = ErrorMsg(http.StatusInternalServerError, "Internal Error asserting tile")
		return
	}
	headers := formatEncoding[tile.SniffFormat()]
	for _, h := range headers {
		w.Header().Set(h.key, h.value)
	}
	w.Header().Set("Content-Length", sprintSizeOf(tile.Data))
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Write(tile.Data)
	return
}

// Get the metadatadata map from the tileset
func metadataHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	//TODO if there's a json field, try to deserialze that
	vars := mux.Vars(r)
	slug := vars["ts"]
	if ts, ok := tilesets.Tilesets[slug]; ok {
		msg = SuccessMsg(ts.Metadata().Attributes())
	} else {
		msg = ErrorMsg(http.StatusBadRequest, fmt.Sprintf("No tileset named %q", slug))
	}
	return
}

// List the tilesets available on the server
func listHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	tss := make(map[string]map[string]string)
	for name, ts := range tilesets.Tilesets {
		tss[name] = ts.Metadata().Attributes()
	}
	msg = SuccessMsg(tss)
	return
}

// From http://www.jsonrpc.org/specification
// Content-Type: MUST be application/json.
// Content-Length: MUST contain the correct length according to the HTTP-specification.
// Accept: MUST be application/json.
func rpcHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	switch {
	case r.Method != "POST":
		msg = ErrorMsg(http.StatusMethodNotAllowed, "Requires method: POST")
	case r.Header.Get("Content-Type") != "application/json":
		msg = ErrorMsg(http.StatusUnsupportedMediaType, "Requires Content-Type: application/json")
	case r.Header.Get("Accept") != "application/json":
		msg = ErrorMsg(http.StatusNotAcceptable, "Requires Accept: application/json")
	case r.Header.Get("Content-Length") == "":
		//TODO is it necessary to asset lenght is correct?
		msg = ErrorMsg(http.StatusLengthRequired, "Requires valid Content-Length")
	default:
		if req, rerr := ReadRequestMessage(r.Body); rerr != nil {
			msg = ErrorMsg(rerr.Code, rerr.Message)
		} else {
			msg = req.ExecuteMethod()
		}
	}
	return
}

/*
func ioHandler(w http.ResponseWriter, r *http.Request) (msg *ResponseMessage) {
	if r.Method != "GET" {
		msg = ErrorMsg(http.StatusMethodNotAllowed, "Only GET can be upgraded")
		return
	}
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		warn(err)
		msg = ErrorMsg(http.StatusInternalServerError, "Request can't be upgraded")
		return
	}
	vars := mux.Vars(r)
	slug := vars["ts"]
	if ts, ok := tilesets.Tilesets[slug]; !ok {
		msg = ErrorMsg(http.StatusBadRequest, fmt.Sprintf("No tileset named %q", slug))
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	h.register <- c
	go c.writePump()
	c.readPump()
}
*/
<|endoftext|>


<commit_before><commit_msg>Add unit tests for VMI filesystem usage metrics<commit_after><|endoftext|>


<commit_before>package config

import (
	"testing"

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

func TestConfig_Resolve_validation(t *testing.T) {
	o := struct {
		Concurrency int `name:"concurrency" desc:"some number" validate:"min=1,max=5"`
	}{}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--concurrency=0",
				},
			},
		},
	}

	err := c.Resolve()
	assert.EqualError(t, err, `Concurrency: less than min`)
}

func TestConfig_Resolve_default_name(t *testing.T) {
	o := struct {
		MaxInFlight int
	}{}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--max-in-flight=5",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, 5, o.MaxInFlight)
}

type Redis struct {
	Host string
	Port int
}

func TestConfig_Resolve_nested(t *testing.T) {
	o := struct {
		NSQ struct {
			Messages struct {
				MaxInFlight int
			}
		}
		Redis Redis
	}{
		Redis: Redis{
			Host: "localhost",
			Port: 6379,
		},
	}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--nsq-messages-max-in-flight=5",
					"--redis-host=0.0.0.0",
					"--redis-port=3000",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, 5, o.NSQ.Messages.MaxInFlight)
	assert.Equal(t, "0.0.0.0", o.Redis.Host)
	assert.Equal(t, 3000, o.Redis.Port)
}

type Foo struct {
	Bar *Bar
}

type Bar struct {
	Baz string
}

func TestConfig_Resolve_nested_pointers(t *testing.T) {
	o := struct {
		Foo *Foo
	}{
		Foo: &Foo{
			Bar: &Bar{
				Baz: "hello",
			},
		},
	}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--foo-bar-baz=world",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, "world", o.Foo.Bar.Baz)
}
<commit_msg>add test for explicit name<commit_after>package config

import (
	"testing"

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

func TestConfig_Resolve_validation(t *testing.T) {
	o := struct {
		Concurrency int `name:"concurrency" desc:"some number" validate:"min=1,max=5"`
	}{}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--concurrency=0",
				},
			},
		},
	}

	err := c.Resolve()
	assert.EqualError(t, err, `Concurrency: less than min`)
}

func TestConfig_Resolve_default_name(t *testing.T) {
	o := struct {
		MaxInFlight int
	}{}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--max-in-flight=5",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, 5, o.MaxInFlight)
}

func TestConfig_Resolve_tag_name(t *testing.T) {
	o := struct {
		MaxInFlight int `name:"concurrency"`
	}{}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--concurrency=5",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, 5, o.MaxInFlight)
}

type Redis struct {
	Host string
	Port int
}

func TestConfig_Resolve_nested(t *testing.T) {
	o := struct {
		NSQ struct {
			Messages struct {
				MaxInFlight int
			}
		}
		Redis Redis
	}{
		Redis: Redis{
			Host: "localhost",
			Port: 6379,
		},
	}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--nsq-messages-max-in-flight=5",
					"--redis-host=0.0.0.0",
					"--redis-port=3000",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, 5, o.NSQ.Messages.MaxInFlight)
	assert.Equal(t, "0.0.0.0", o.Redis.Host)
	assert.Equal(t, 3000, o.Redis.Port)
}

type Foo struct {
	Bar *Bar
}

type Bar struct {
	Baz string
}

func TestConfig_Resolve_nested_pointers(t *testing.T) {
	o := struct {
		Foo *Foo
	}{
		Foo: &Foo{
			Bar: &Bar{
				Baz: "hello",
			},
		},
	}

	c := Config{
		Options: &o,
		Resolvers: []Resolver{
			&FlagResolver{
				Args: []string{
					"program",
					"--foo-bar-baz=world",
				},
			},
		},
	}

	err := c.Resolve()
	assert.NoError(t, err)
	assert.Equal(t, "world", o.Foo.Bar.Baz)
}
<|endoftext|>


<commit_before>package git

import (
	"os"
	"testing"
)

func setupConfig() (*Config, error) {
	var (
		c   *Config
		err error
		p   string
	)

	p, err = ConfigFindGlobal()
	if err != nil {
		return nil, err
	}

	c, err = OpenOndisk(nil, p)
	if err != nil {
		return nil, err
	}

	c.SetString("foo.bar", "baz")

	return c, err
}

func cleanupConfig() {
	os.Remove(tempConfig)
}

func TestConfigLookupString(t *testing.T) {
	var (
		err error
		val string
		c   *Config
	)

	c, err = setupConfig()
	defer cleanupConfig()
	if err != nil {
		t.Errorf("Setup error: '%v'. Expected none\n", err)
		t.FailNow()
	}
	defer c.Free()

	val, err = c.LookupString("foo.bar")
	if err != nil {
		t.Errorf("Got error: '%v', expected none\n", err)
		t.FailNow()
	}

	if val != "baz" {
		t.Errorf("Got '%s', expected 'bar'\n", val)
	}
}
<commit_msg>Tests config lookup methods<commit_after>package git

import (
	"os"
	"testing"
)

var tempConfig = "./temp.gitconfig"

func setupConfig() (*Config, error) {
	var (
		c   *Config
		err error
	)

	c, err = OpenOndisk(nil, tempConfig)
	if err != nil {
		return nil, err
	}

	c.SetString("foo.bar", "baz")
	c.SetBool("foo.bool", true)
	c.SetInt32("foo.int32", 32)
	c.SetInt64("foo.int64", 64)

	return c, err
}

func cleanupConfig() {
	os.Remove(tempConfig)
}

type TestRunner func(*Config, *testing.T)

var tests = []TestRunner{
	// LookupString
	func(c *Config, t *testing.T) {
		val, err := c.LookupString("foo.bar")
		if err != nil {
			t.Errorf("Got LookupString error: '%v', expected none\n", err)
		}
		if val != "baz" {
			t.Errorf("Got '%s' from LookupString, expected 'bar'\n", val)
		}
	},
	// LookupBool
	func(c *Config, t *testing.T) {
		val, err := c.LookupBool("foo.bool")
		if err != nil {
			t.Errorf("Got LookupBool error: '%v', expected none\n", err)
		}
		if !val {
			t.Errorf("Got %b from LookupBool, expected 'false'\n", val)
		}
	},
	// LookupInt32
	func(c *Config, t *testing.T) {
		val, err := c.LookupInt32("foo.int32")
		if err != nil {
			t.Errorf("Got LookupInt32 error: '%v', expected none\n", err)
		}
		if val != 32 {
			t.Errorf("Got %v, expected 32\n", val)
		}
	},
	// LookupInt64
	func(c *Config, t *testing.T) {
		val, err := c.LookupInt64("foo.int64")
		if err != nil {
			t.Errorf("Got LookupInt64 error: '%v', expected none\n", err)
		}
		if val != 64 {
			t.Errorf("Got %v, expected 64\n", val)
		}
	},
}

func TestConfigLookups(t *testing.T) {
	var (
		err error
		c   *Config
	)

	c, err = setupConfig()
	defer cleanupConfig()

	if err != nil {
		t.Errorf("Setup error: '%v'. Expected none\n", err)
	}
	defer c.Free()

	for _, test := range tests {
		test(c, t)
	}
}
<|endoftext|>


<commit_before>package evaluation

import (
	"fmt"
	"strings"

	"github.com/Zac-Garby/pluto/ast"
)

type args map[string]Object
type builtinFn func(args, *Context) Object

type Builtin struct {
	Pattern []string
	Fn      builtinFn
}

func NewBuiltin(ptn string, fn builtinFn, types map[string]Type) Builtin {
	pattern := strings.Split(ptn, " ")

	typedFn := func(args args, ctx *Context) Object {
		for key, t := range types {
			val := args[key]

			if !is(val, t) {
				return Err(
					ctx,
					"the $%s parameter of %s must be of type %s, not %s",
					"TypeError",
					key, ptn,
					t, val.Type(),
				)
			}
		}

		return fn(args, ctx)
	}

	return Builtin{
		Pattern: pattern,
		Fn:      typedFn,
	}
}

var empty = make(map[string]Type)

var builtins = []Builtin{}

func GetBuiltins() []Builtin {
	if len(builtins) == 0 {
		builtins = []Builtin{
			NewBuiltin("print $obj", printObj, empty),

			NewBuiltin("do $block", doBlock, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("do $block with $args", doBlockWithArgs, map[string]Type{
				"block": BLOCK,
				"args":  COLLECTION,
			}),

			NewBuiltin("do $block on $arg", doBlockOnArg, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("map $block over $collection", mapBlockOverCollection, map[string]Type{
				"block":      BLOCK,
				"collection": COLLECTION,
			}),

			NewBuiltin("format $format with $args", formatWithArgs, map[string]Type{
				"format": STRING,
				"args":   COLLECTION,
			}),

			NewBuiltin("$start to $end", startToEnd, map[string]Type{
				"start": NUMBER,
				"end":   NUMBER,
			}),
		}
	}

	return builtins
}

// print $obj
func printObj(args args, ctx *Context) Object {
	fmt.Println(args["obj"])

	return O_NULL
}

// format $format with $args
func formatWithArgs(args args, ctx *Context) Object {
	var (
		format  = args["format"].(*String)
		formats = args["args"].(Collection)
	)

	// if format = "Hello, {}!" and args = ["world"]
	// the result will be "Hello, world!"

	result := format.Value

	for _, f := range formats.Elements() {
		result = strings.Replace(result, "{}", f.String(), 1)
	}

	return &String{Value: result}
}

func evalBlock(block *Block, args []Object, ctx *Context) Object {
	if len(block.Params) != len(args) {
		return err(
			ctx,
			"wrong number of arguments applied to a block. expected %d, got %d", "TypeError",
			len(block.Params),
			len(args),
		)
	}

	apArgs := make(map[string]Object)

	for i, param := range block.Params {
		apArgs[param.(*ast.Identifier).Value] = args[i]
	}

	return eval(block.Body, ctx.EncloseWith(apArgs))
}

// do $block
func doBlock(args args, ctx *Context) Object {
	block := args["block"].(*Block)

	return evalBlock(block, []Object{}, ctx)
}

// do $block with $args
func doBlockWithArgs(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["args"].(Collection)
	)

	return evalBlock(block, col.Elements(), ctx)
}

// do $block on $arg
func doBlockOnArg(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		arg   = args["arg"]
	)

	return evalBlock(block, []Object{arg}, ctx)
}

// map $block over $collection
func mapBlockOverCollection(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["collection"].(Collection)
	)

	var result []Object

	for i, item := range col.Elements() {
		mapped := evalBlock(block, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(mapped) {
			return mapped
		}

		result = append(result, mapped)
	}

	return MakeCollection(col.Type(), result, ctx)
}

// $start to $end
func startToEnd(args args, ctx *Context) Object {
	var (
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		sVal = int(start.Value)
		eVal = int(end.Value)
	)

	if eVal < sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i >= eVal; i-- {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	} else if eVal > sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i < eVal+1; i++ {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	}

	return &Array{Value: []Object{start}}
}
<commit_msg>Implement slicing builtins<commit_after>package evaluation

import (
	"fmt"
	"strings"

	"github.com/Zac-Garby/pluto/ast"
)

type args map[string]Object
type builtinFn func(args, *Context) Object

type Builtin struct {
	Pattern []string
	Fn      builtinFn
}

func NewBuiltin(ptn string, fn builtinFn, types map[string]Type) Builtin {
	pattern := strings.Split(ptn, " ")

	typedFn := func(args args, ctx *Context) Object {
		for key, t := range types {
			val := args[key]

			if !is(val, t) {
				return Err(
					ctx,
					"the $%s parameter of %s must be of type %s, not %s",
					"TypeError",
					key, ptn,
					t, val.Type(),
				)
			}
		}

		return fn(args, ctx)
	}

	return Builtin{
		Pattern: pattern,
		Fn:      typedFn,
	}
}

var empty = make(map[string]Type)

var builtins = []Builtin{}

func GetBuiltins() []Builtin {
	if len(builtins) == 0 {
		builtins = []Builtin{
			NewBuiltin("print $obj", printObj, empty),

			NewBuiltin("do $block", doBlock, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("do $block with $args", doBlockWithArgs, map[string]Type{
				"block": BLOCK,
				"args":  COLLECTION,
			}),

			NewBuiltin("do $block on $arg", doBlockOnArg, map[string]Type{
				"block": BLOCK,
			}),

			NewBuiltin("map $block over $collection", mapBlockOverCollection, map[string]Type{
				"block":      BLOCK,
				"collection": COLLECTION,
			}),

			NewBuiltin("format $format with $args", formatWithArgs, map[string]Type{
				"format": STRING,
				"args":   COLLECTION,
			}),

			NewBuiltin("$start to $end", startToEnd, map[string]Type{
				"start": NUMBER,
				"end":   NUMBER,
			}),

			NewBuiltin(
				"slice $collection from $start to $end",
				sliceCollectionFromStartToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
					"end":        NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection from $start",
				sliceCollectionFromStart,
				map[string]Type{
					"collection": COLLECTION,
					"start":      NUMBER,
				},
			),

			NewBuiltin(
				"slice $collection to $end",
				sliceCollectionToEnd,
				map[string]Type{
					"collection": COLLECTION,
					"end":        NUMBER,
				},
			),
		}
	}

	return builtins
}

// print $obj
func printObj(args args, ctx *Context) Object {
	fmt.Println(args["obj"])

	return O_NULL
}

// format $format with $args
func formatWithArgs(args args, ctx *Context) Object {
	var (
		format  = args["format"].(*String)
		formats = args["args"].(Collection)
	)

	// if format = "Hello, {}!" and args = ["world"]
	// the result will be "Hello, world!"

	result := format.Value

	for _, f := range formats.Elements() {
		result = strings.Replace(result, "{}", f.String(), 1)
	}

	return &String{Value: result}
}

func evalBlock(block *Block, args []Object, ctx *Context) Object {
	if len(block.Params) != len(args) {
		return err(
			ctx,
			"wrong number of arguments applied to a block. expected %d, got %d", "TypeError",
			len(block.Params),
			len(args),
		)
	}

	apArgs := make(map[string]Object)

	for i, param := range block.Params {
		apArgs[param.(*ast.Identifier).Value] = args[i]
	}

	return eval(block.Body, ctx.EncloseWith(apArgs))
}

// do $block
func doBlock(args args, ctx *Context) Object {
	block := args["block"].(*Block)

	return evalBlock(block, []Object{}, ctx)
}

// do $block with $args
func doBlockWithArgs(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["args"].(Collection)
	)

	return evalBlock(block, col.Elements(), ctx)
}

// do $block on $arg
func doBlockOnArg(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		arg   = args["arg"]
	)

	return evalBlock(block, []Object{arg}, ctx)
}

// map $block over $collection
func mapBlockOverCollection(args args, ctx *Context) Object {
	var (
		block = args["block"].(*Block)
		col   = args["collection"].(Collection)
	)

	var result []Object

	for i, item := range col.Elements() {
		mapped := evalBlock(block, []Object{
			&Number{Value: float64(i)},
			item,
		}, ctx)

		if isErr(mapped) {
			return mapped
		}

		result = append(result, mapped)
	}

	return MakeCollection(col.Type(), result, ctx)
}

// $start to $end
func startToEnd(args args, ctx *Context) Object {
	var (
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		sVal = int(start.Value)
		eVal = int(end.Value)
	)

	if eVal < sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i >= eVal; i-- {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	} else if eVal > sVal {
		result := &Array{Value: []Object{}}

		for i := sVal; i < eVal+1; i++ {
			result.Value = append(result.Value, &Number{Value: float64(i)})
		}

		return result
	}

	return &Array{Value: []Object{start}}
}

func sliceCollectionFromStartToEnd(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)
		end   = args["end"].(*Number)

		elems = col.Elements()
		sVal  = int(start.Value)
		eVal  = int(end.Value)
	)

	if sVal >= eVal {
		return err(ctx, "$start must be less than $end", "OutOfBoundsError")
	}

	if sVal < 0 || eVal < 0 {
		return err(ctx, "neither $start nor $end can be less than 0", "OutOfBoundsError")
	}

	if eVal >= len(elems) {
		return err(ctx, "$end must be contained by $collection", "OutOfBoundsError")
	}

	return &Array{Value: elems[sVal:eVal]}
}

func sliceCollectionFromStart(args args, ctx *Context) Object {
	var (
		col   = args["collection"].(Collection)
		start = args["start"].(*Number)

		elems = col.Elements()
		index = int(start.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$start is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[index:]}
}

func sliceCollectionToEnd(args args, ctx *Context) Object {
	var (
		col = args["collection"].(Collection)
		end = args["end"].(*Number)

		elems = col.Elements()
		index = int(end.Value)
	)

	if index < 0 || index >= len(elems) {
		return err(ctx, "$end is out of bounds", "OutOfBoundsError")
	}

	return &Array{Value: elems[:index]}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package samples_test

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

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/gcsfuse/timeutil"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
)

func TestHelloFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type HelloFSTest struct {
	clock timeutil.SimulatedClock
	mfs   *fuse.MountedFileSystem
}

var _ SetUpInterface = &HelloFSTest{}
var _ TearDownInterface = &HelloFSTest{}

func init() { RegisterTestSuite(&HelloFSTest{}) }

func (t *HelloFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a fixed, non-zero time.
	t.clock.SetTime(time.Now())

	// Set up a temporary directory for mounting.
	mountPoint, err := ioutil.TempDir("", "hello_fs_test")
	if err != nil {
		panic("ioutil.TempDir: " + err.Error())
	}

	// Mount a file system.
	fs := &samples.HelloFS{
		Clock: &t.clock,
	}

	if t.mfs, err = fuse.Mount(mountPoint, fs); err != nil {
		panic("Mount: " + err.Error())
	}

	if err = t.mfs.WaitForReady(context.Background()); err != nil {
		panic("MountedFileSystem.WaitForReady: " + err.Error())
	}
}

func (t *HelloFSTest) TearDown() {
	// Unmount the file system. Try again on "resource busy" errors.
	delay := 10 * time.Millisecond
	for {
		err := t.mfs.Unmount()
		if err == nil {
			break
		}

		if strings.Contains(err.Error(), "resource busy") {
			log.Println("Resource busy error while unmounting; trying again")
			time.Sleep(delay)
			delay = time.Duration(1.3 * float64(delay))
			continue
		}

		panic("MountedFileSystem.Unmount: " + err.Error())
	}

	if err := t.mfs.Join(context.Background()); err != nil {
		panic("MountedFileSystem.Join: " + err.Error())
	}
}

////////////////////////////////////////////////////////////////////////
// Test functions
////////////////////////////////////////////////////////////////////////

func (t *HelloFSTest) ReadDir_Root() {
	entries, err := ioutil.ReadDir(t.mfs.Dir())

	AssertEq(nil, err)
	AssertEq(2, len(entries))
	var fi os.FileInfo

	// dir
	fi = entries[0]
	ExpectEq("dir", fi.Name())
	ExpectEq(0, fi.Size())
	ExpectEq(os.ModeDir|0500, fi.Mode())
	ExpectEq(0, t.clock.Now().Sub(fi.ModTime()), "ModTime: %v", fi.ModTime())
	ExpectTrue(fi.IsDir())

	// hello
	fi = entries[1]
	ExpectEq("hello", fi.Name())
	ExpectEq(len("Hello, world!"), fi.Size())
	ExpectEq(0400, fi.Mode())
	ExpectEq(0, t.clock.Now().Sub(fi.ModTime()), "ModTime: %v", fi.ModTime())
	ExpectFalse(fi.IsDir())
}

func (t *HelloFSTest) ReadDir_Dir() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) ReadDir_NonExistent() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_Hello() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_Dir() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_World() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_NonExistent() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Read_Hello() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Read_World() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Open_NonExistent() {
	AssertTrue(false, "TODO")
}
<commit_msg>HelloFSTest.ReadDir_Dir<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package samples_test

import (
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
	"testing"
	"time"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/gcsfuse/timeutil"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
)

func TestHelloFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type HelloFSTest struct {
	clock timeutil.SimulatedClock
	mfs   *fuse.MountedFileSystem
}

var _ SetUpInterface = &HelloFSTest{}
var _ TearDownInterface = &HelloFSTest{}

func init() { RegisterTestSuite(&HelloFSTest{}) }

func (t *HelloFSTest) SetUp(ti *TestInfo) {
	var err error

	// Set up a fixed, non-zero time.
	t.clock.SetTime(time.Now())

	// Set up a temporary directory for mounting.
	mountPoint, err := ioutil.TempDir("", "hello_fs_test")
	if err != nil {
		panic("ioutil.TempDir: " + err.Error())
	}

	// Mount a file system.
	fs := &samples.HelloFS{
		Clock: &t.clock,
	}

	if t.mfs, err = fuse.Mount(mountPoint, fs); err != nil {
		panic("Mount: " + err.Error())
	}

	if err = t.mfs.WaitForReady(context.Background()); err != nil {
		panic("MountedFileSystem.WaitForReady: " + err.Error())
	}
}

func (t *HelloFSTest) TearDown() {
	// Unmount the file system. Try again on "resource busy" errors.
	delay := 10 * time.Millisecond
	for {
		err := t.mfs.Unmount()
		if err == nil {
			break
		}

		if strings.Contains(err.Error(), "resource busy") {
			log.Println("Resource busy error while unmounting; trying again")
			time.Sleep(delay)
			delay = time.Duration(1.3 * float64(delay))
			continue
		}

		panic("MountedFileSystem.Unmount: " + err.Error())
	}

	if err := t.mfs.Join(context.Background()); err != nil {
		panic("MountedFileSystem.Join: " + err.Error())
	}
}

////////////////////////////////////////////////////////////////////////
// Test functions
////////////////////////////////////////////////////////////////////////

func (t *HelloFSTest) ReadDir_Root() {
	entries, err := ioutil.ReadDir(t.mfs.Dir())

	AssertEq(nil, err)
	AssertEq(2, len(entries))
	var fi os.FileInfo

	// dir
	fi = entries[0]
	ExpectEq("dir", fi.Name())
	ExpectEq(0, fi.Size())
	ExpectEq(os.ModeDir|0500, fi.Mode())
	ExpectEq(0, t.clock.Now().Sub(fi.ModTime()), "ModTime: %v", fi.ModTime())
	ExpectTrue(fi.IsDir())

	// hello
	fi = entries[1]
	ExpectEq("hello", fi.Name())
	ExpectEq(len("Hello, world!"), fi.Size())
	ExpectEq(0400, fi.Mode())
	ExpectEq(0, t.clock.Now().Sub(fi.ModTime()), "ModTime: %v", fi.ModTime())
	ExpectFalse(fi.IsDir())
}

func (t *HelloFSTest) ReadDir_Dir() {
	entries, err := ioutil.ReadDir(path.Join(t.mfs.Dir(), "dir"))

	AssertEq(nil, err)
	AssertEq(1, len(entries))
	var fi os.FileInfo

	// world
	fi = entries[1]
	ExpectEq("world", fi.Name())
	ExpectEq(len("Hello, world!"), fi.Size())
	ExpectEq(0400, fi.Mode())
	ExpectEq(0, t.clock.Now().Sub(fi.ModTime()), "ModTime: %v", fi.ModTime())
	ExpectFalse(fi.IsDir())
}

func (t *HelloFSTest) ReadDir_NonExistent() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_Hello() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_Dir() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_World() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Stat_NonExistent() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Read_Hello() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Read_World() {
	AssertTrue(false, "TODO")
}

func (t *HelloFSTest) Open_NonExistent() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/miquella/mason-ci/datastore"
	"github.com/miquella/mason-ci/datastore/drivers/rethink"
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"golang.org/x/net/websocket"
)

var (
	Router = mux.NewRouter()
	Store  *datastore.Datastore
)

func init() {
	rethinkAddress := flag.String("rethink-address", "localhost:28015", "Rethink address")
	rethinkDatabase := flag.String("rethink-database", "mason_ci", "Rethink database name")
	flag.Parse()

	log.Printf("Connecting to datastore %s (%s)", *rethinkAddress, *rethinkDatabase)
	driver, err := rethink.NewRethinkDriver(*rethinkAddress, *rethinkDatabase)
	if err != nil {
		log.Fatalf("Failed to start rethinkdb driver: %s", err)
	}
	Store = datastore.NewDatastore(driver)
}

func main() {
	log.Printf("Listening on :9535")
	http.Handle("/", Router)
	err := http.ListenAndServe(":9535", nil)
	if err != nil {
		log.Panic(err.Error())
	}
}
<commit_msg>Fix move of slave routes<commit_after>package main

import (
	"flag"
	"github.com/miquella/mason-ci/datastore"
	"github.com/miquella/mason-ci/datastore/drivers/rethink"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

var (
	Router = mux.NewRouter()
	Store  *datastore.Datastore
)

func init() {
	rethinkAddress := flag.String("rethink-address", "localhost:28015", "Rethink address")
	rethinkDatabase := flag.String("rethink-database", "mason_ci", "Rethink database name")
	flag.Parse()

	log.Printf("Connecting to datastore %s (%s)", *rethinkAddress, *rethinkDatabase)
	driver, err := rethink.NewRethinkDriver(*rethinkAddress, *rethinkDatabase)
	if err != nil {
		log.Fatalf("Failed to start rethinkdb driver: %s", err)
	}
	Store = datastore.NewDatastore(driver)
}

func main() {
	log.Printf("Listening on :9535")
	http.Handle("/", Router)
	err := http.ListenAndServe(":9535", nil)
	if err != nil {
		log.Panic(err.Error())
	}
}
<|endoftext|>


<commit_before>package mbus

import (
	"encoding/json"
	"errors"
	"fmt"
	"math"
	"net"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"

	"github.com/nats-io/nats.go"

	"crypto/x509"
	"time"

	"crypto/tls"
	"regexp"

	boshhandler "github.com/cloudfoundry/bosh-agent/handler"
	boshplatform "github.com/cloudfoundry/bosh-agent/platform"
	boshsettings "github.com/cloudfoundry/bosh-agent/settings"
	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
)

const (
	responseMaxLength = 1024 * 1024
	natsHandlerLogTag = "NATS Handler"
	natsMinRetryWait  = 2
	//natsMaxReconnectWait should be lower than the setting we have in BOSH for https://github.com/cloudfoundry/bosh/blob/main/src/bosh-director/lib/bosh/director/agent_client.rb#L44.
	natsMaxReconnectWait = 10 * time.Second
)

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

type Handler interface {
	Run(boshhandler.Func) error
	Start(boshhandler.Func) error
	RegisterAdditionalFunc(boshhandler.Func)
	Send(target boshhandler.Target, topic boshhandler.Topic, message interface{}) error
	Stop()
}

type NatsConnector func(url string, options ...nats.Option) (NatsConnection, error)

//counterfeiter:generate . NatsConnection

type NatsConnection interface {
	Close()
	Publish(subj string, data []byte) error
	Subscribe(subj string, cb nats.MsgHandler) (*nats.Subscription, error)
}

type natsHandler struct {
	settingsService boshsettings.Service
	connector       NatsConnector
	connection      NatsConnection
	platform        boshplatform.Platform

	handlerFuncs     []boshhandler.Func
	handlerFuncsLock sync.Mutex

	logger      boshlog.Logger
	auditLogger boshplatform.AuditLogger
	logTag      string
}

type ConnectionInfo struct {
	Addr      string
	IP        string
	Dial      func(network, address string) (net.Conn, error)
	TLSConfig *tls.Config
}

type ConnectionTLSInfo struct {
	CertPool              *x509.CertPool
	ClientCert            *tls.Certificate
	VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
}

func NewNatsHandler(
	settingsService boshsettings.Service,
	client NatsConnector,
	logger boshlog.Logger,
	platform boshplatform.Platform,
) Handler {
	return &natsHandler{
		settingsService: settingsService,
		connector:       client,
		platform:        platform,
		logger:          logger,
		logTag:          natsHandlerLogTag,
		auditLogger:     platform.GetAuditLogger(),
	}
}
func (h *natsHandler) arpClean() {
	connectionInfo, err := h.getConnectionInfo()
	if err != nil {
		h.logger.Error(h.logTag, "%v", bosherr.WrapError(err, "Getting connection info"))
	}
	err = h.platform.DeleteARPEntryWithIP(connectionInfo.IP)
	if err != nil {
		h.logger.Error(h.logTag, "Cleaning ip-mac address cache for: %s. Error: %v", connectionInfo.IP, err)
	}

	h.logger.Debug(h.logTag, "Cleaned ip-mac address cache for: %s.", connectionInfo.IP)
}

func (h *natsHandler) Run(handlerFunc boshhandler.Func) error {
	err := h.Start(handlerFunc)
	defer h.Stop()

	if err != nil {
		return bosherr.WrapError(err, "Starting nats handler")
	}

	h.runUntilInterrupted()
	return nil
}
func (h *natsHandler) Start(handlerFunc boshhandler.Func) error {
	h.RegisterAdditionalFunc(handlerFunc)

	connectionInfo, err := h.getConnectionInfo()
	if err != nil {
		return bosherr.WrapError(err, "Getting connection info")
	}
	h.logger.Info(h.logTag, "Attempting to connect to NATS")
	if net.ParseIP(connectionInfo.IP) != nil {
		h.arpClean()
	}
	var natsOptions = []nats.Option{
		nats.RetryOnFailedConnect(true),
		nats.DisconnectErrHandler(func(c *nats.Conn, err error) {
			h.logger.Debug(natsHandlerLogTag, "Nats disconnected with Error: %v", err.Error())
			h.logger.Debug(natsHandlerLogTag, "Attempting to reconnect: %v", c.IsReconnecting())
			for c.IsReconnecting() {
				h.arpClean()
				h.logger.Debug(natsHandlerLogTag, "Waiting to reconnect to nats.. Current attempt: %v, Connected: %v", c.Reconnects, c.IsConnected())
				time.Sleep(5 * time.Second)
			}
		}),
		nats.ReconnectHandler(func(c *nats.Conn) {
			h.logger.Debug(natsHandlerLogTag, "Reconnected to %v", c.ConnectedAddr())
		}),
		nats.ClosedHandler(func(c *nats.Conn) {
			h.logger.Debug(natsHandlerLogTag, "Connection Closed with: %v", c.LastError().Error())
		}),
		nats.ErrorHandler(func(c *nats.Conn, s *nats.Subscription, err error) {
			h.logger.Debug(natsHandlerLogTag, err.Error())
		}),
		nats.CustomReconnectDelay(func(attempts int) time.Duration {
			exponentialReconnectWait := time.Duration(math.Pow(natsMinRetryWait, float64(attempts))) * time.Second
			if natsMaxReconnectWait > exponentialReconnectWait {
				h.logger.Debug(natsHandlerLogTag, "Increased reconnect to: %v", exponentialReconnectWait)
				return exponentialReconnectWait
			}
			h.logger.Debug(natsHandlerLogTag, "Increased reconnect to: %v", natsMaxReconnectWait)
			return natsMaxReconnectWait
		}),
		nats.MaxReconnects(-1),
		nats.Secure(connectionInfo.TLSConfig),
	}

	connection, err := h.connector(connectionInfo.Addr, natsOptions...)
	// just log this error. even if currently cannot connect to nats, we can eventually
	if err != nil {
		return bosherr.WrapError(err, "Connecting to NATS")
	}

	h.connection = connection

	settings := h.settingsService.GetSettings()

	subject := fmt.Sprintf("agent.%s", settings.AgentID)

	h.logger.Info(h.logTag, "Subscribing to %s", subject)

	_, err = h.connection.Subscribe(subject, func(natsMsg *nats.Msg) {
		// Do not lock handler funcs around possible network calls!
		h.handlerFuncsLock.Lock()
		handlerFuncs := h.handlerFuncs
		h.handlerFuncsLock.Unlock()

		for _, handlerFunc := range handlerFuncs {
			h.handleNatsMsg(natsMsg, handlerFunc)
		}
	})
	if err != nil {
		return bosherr.WrapErrorf(err, "Subscribing to %s", subject)
	}

	return nil
}

func (h *natsHandler) RegisterAdditionalFunc(handlerFunc boshhandler.Func) {
	// Currently not locking since RegisterAdditionalFunc
	// is not a primary way of adding handlerFunc.
	h.handlerFuncsLock.Lock()
	h.handlerFuncs = append(h.handlerFuncs, handlerFunc)
	h.handlerFuncsLock.Unlock()
}

func (h *natsHandler) Send(target boshhandler.Target, topic boshhandler.Topic, message interface{}) error {
	bytes, err := json.Marshal(message)
	if err != nil {
		return bosherr.WrapErrorf(err, "Marshalling message (target=%s, topic=%s): %#v", target, topic, message)
	}

	h.logger.Info(h.logTag, "Sending %s message '%s'", target, topic)
	h.logger.DebugWithDetails(h.logTag, "Message Payload", string(bytes))

	settings := h.settingsService.GetSettings()

	subject := fmt.Sprintf("%s.agent.%s.%s", target, topic, settings.AgentID)
	if h.connection != nil {
		return h.connection.Publish(subject, bytes)
	}
	return nil
}

func (h *natsHandler) Stop() {
	if h.connection != nil {
		h.connection.Close()
	}
}

func (h *natsHandler) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
	natsBoshInternalsRegexp := regexp.MustCompile(`^[a-zA-Z0-9*\-]*.nats.bosh-internal$`)
	for _, chain := range verifiedChains {
		if len(chain) == 0 {
			continue
		}
		commonName := chain[0].Subject.CommonName
		if natsBoshInternalsRegexp.MatchString(commonName) {
			return nil
		}
	}
	return errors.New("server Certificate CommonName does not match *.nats.bosh-internal")
}

func (h *natsHandler) handleNatsMsg(natsMsg *nats.Msg, handlerFunc boshhandler.Func) {
	respBytes, req, err := boshhandler.PerformHandlerWithJSON(
		natsMsg.Data,
		handlerFunc,
		responseMaxLength,
		h.logger,
	)

	if err != nil {
		h.logger.Error(h.logTag, "Running handler: %s", err)
		h.generateCEFLog(natsMsg, 7, err.Error())
		return
	}

	if len(respBytes) > 0 {
		err = h.connection.Publish(req.ReplyTo, respBytes)
		if err != nil {
			h.generateCEFLog(natsMsg, 7, err.Error())
			h.logger.Error(h.logTag, "Publishing to the client: %s", err.Error())
			return
		}
	}

	h.generateCEFLog(natsMsg, 1, "")
}

func (h *natsHandler) runUntilInterrupted() {
	defer h.connection.Close()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)

	keepRunning := true
	for keepRunning {
		<-c
		keepRunning = false
	}
}

func (h *natsHandler) getConnectionInfo() (*ConnectionInfo, error) {
	settings := h.settingsService.GetSettings()

	connInfo := new(ConnectionInfo)
	connInfo.Addr = settings.GetMbusURL()
	natsURL, err := url.Parse(connInfo.Addr)
	if err != nil {
		return nil, bosherr.WrapError(err, "Parsing Nats URL")
	}

	hostSplit := strings.Split(natsURL.Host, ":")
	connInfo.IP = hostSplit[0]

	connInfo.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}

	caCert := settings.GetMbusCerts().CA
	if caCert != "" {
		connInfo.TLSConfig.RootCAs = x509.NewCertPool()
		if ok := connInfo.TLSConfig.RootCAs.AppendCertsFromPEM([]byte(caCert)); !ok {
			return nil, bosherr.Error("Failed to load Mbus CA cert")
		}
	}

	connInfo.TLSConfig.VerifyPeerCertificate = h.VerifyPeerCertificate

	clientCertificate, err := tls.X509KeyPair([]byte(settings.GetMbusCerts().Certificate), []byte(settings.GetMbusCerts().PrivateKey))
	if err != nil {
		return nil, bosherr.WrapError(err, "Parsing certificate and private key")
	}
	connInfo.TLSConfig.Certificates = []tls.Certificate{clientCertificate}

	return connInfo, nil
}

func (h *natsHandler) generateCEFLog(natsMsg *nats.Msg, severity int, statusReason string) {
	cef := boshhandler.NewCommonEventFormat()

	settings := h.settingsService.GetSettings()

	natsURL, err := url.Parse(settings.GetMbusURL())
	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
		return
	}

	hostSplit := strings.Split(natsURL.Host, ":")
	ip := hostSplit[0]
	payload := struct {
		Method  string `json:"method"`
		ReplyTo string `json:"reply_to"`
	}{}
	err = json.Unmarshal(natsMsg.Data, &payload)
	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
	}
	cefString, err := cef.ProduceNATSRequestEventLog(ip, hostSplit[1], payload.ReplyTo, payload.Method, severity, natsMsg.Subject, statusReason)

	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
		return
	}

	if severity == 7 {
		h.auditLogger.Err(cefString)
		return
	}

	h.auditLogger.Debug(cefString)
}
<commit_msg>fix overflow bug in nats_handler.go / nats.CustomReconnectDelay()<commit_after>package mbus

import (
	"encoding/json"
	"errors"
	"fmt"
	"math"
	"net"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"

	"github.com/nats-io/nats.go"

	"crypto/x509"
	"time"

	"crypto/tls"
	"regexp"

	boshhandler "github.com/cloudfoundry/bosh-agent/handler"
	boshplatform "github.com/cloudfoundry/bosh-agent/platform"
	boshsettings "github.com/cloudfoundry/bosh-agent/settings"
	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"
)

const (
	responseMaxLength = 1024 * 1024
	natsHandlerLogTag = "NATS Handler"
	natsMinReconnectSeconds = 2.0
	//natsMaxReconnectSeconds should be lower than the setting we have in BOSH for https://github.com/cloudfoundry/bosh/blob/main/src/bosh-director/lib/bosh/director/agent_client.rb#L44.
	natsMaxReconnectSeconds = 10.0
)

//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate

type Handler interface {
	Run(boshhandler.Func) error
	Start(boshhandler.Func) error
	RegisterAdditionalFunc(boshhandler.Func)
	Send(target boshhandler.Target, topic boshhandler.Topic, message interface{}) error
	Stop()
}

type NatsConnector func(url string, options ...nats.Option) (NatsConnection, error)

//counterfeiter:generate . NatsConnection

type NatsConnection interface {
	Close()
	Publish(subj string, data []byte) error
	Subscribe(subj string, cb nats.MsgHandler) (*nats.Subscription, error)
}

type natsHandler struct {
	settingsService boshsettings.Service
	connector       NatsConnector
	connection      NatsConnection
	platform        boshplatform.Platform

	handlerFuncs     []boshhandler.Func
	handlerFuncsLock sync.Mutex

	logger      boshlog.Logger
	auditLogger boshplatform.AuditLogger
	logTag      string
}

type ConnectionInfo struct {
	Addr      string
	IP        string
	Dial      func(network, address string) (net.Conn, error)
	TLSConfig *tls.Config
}

type ConnectionTLSInfo struct {
	CertPool              *x509.CertPool
	ClientCert            *tls.Certificate
	VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
}

func NewNatsHandler(
	settingsService boshsettings.Service,
	client NatsConnector,
	logger boshlog.Logger,
	platform boshplatform.Platform,
) Handler {
	return &natsHandler{
		settingsService: settingsService,
		connector:       client,
		platform:        platform,
		logger:          logger,
		logTag:          natsHandlerLogTag,
		auditLogger:     platform.GetAuditLogger(),
	}
}
func (h *natsHandler) arpClean() {
	connectionInfo, err := h.getConnectionInfo()
	if err != nil {
		h.logger.Error(h.logTag, "%v", bosherr.WrapError(err, "Getting connection info"))
	}
	err = h.platform.DeleteARPEntryWithIP(connectionInfo.IP)
	if err != nil {
		h.logger.Error(h.logTag, "Cleaning ip-mac address cache for: %s. Error: %v", connectionInfo.IP, err)
	}

	h.logger.Debug(h.logTag, "Cleaned ip-mac address cache for: %s.", connectionInfo.IP)
}

func (h *natsHandler) Run(handlerFunc boshhandler.Func) error {
	err := h.Start(handlerFunc)
	defer h.Stop()

	if err != nil {
		return bosherr.WrapError(err, "Starting nats handler")
	}

	h.runUntilInterrupted()
	return nil
}
func (h *natsHandler) Start(handlerFunc boshhandler.Func) error {
	h.RegisterAdditionalFunc(handlerFunc)

	connectionInfo, err := h.getConnectionInfo()
	if err != nil {
		return bosherr.WrapError(err, "Getting connection info")
	}
	h.logger.Info(h.logTag, "Attempting to connect to NATS")
	if net.ParseIP(connectionInfo.IP) != nil {
		h.arpClean()
	}
	var natsOptions = []nats.Option{
		nats.RetryOnFailedConnect(true),
		nats.DisconnectErrHandler(func(c *nats.Conn, err error) {
			h.logger.Debug(natsHandlerLogTag, "Nats disconnected with Error: %v", err.Error())
			h.logger.Debug(natsHandlerLogTag, "Attempting to reconnect: %v", c.IsReconnecting())
			for c.IsReconnecting() {
				h.arpClean()
				h.logger.Debug(natsHandlerLogTag, "Waiting to reconnect to nats.. Current attempt: %v, Connected: %v", c.Reconnects, c.IsConnected())
				time.Sleep(5 * time.Second)
			}
		}),
		nats.ReconnectHandler(func(c *nats.Conn) {
			h.logger.Debug(natsHandlerLogTag, "Reconnected to %v", c.ConnectedAddr())
		}),
		nats.ClosedHandler(func(c *nats.Conn) {
			h.logger.Debug(natsHandlerLogTag, "Connection Closed with: %v", c.LastError().Error())
		}),
		nats.ErrorHandler(func(c *nats.Conn, s *nats.Subscription, err error) {
			h.logger.Debug(natsHandlerLogTag, err.Error())
		}),
		nats.CustomReconnectDelay(func(attempts int) time.Duration {
		    reconnectSeconds := natsMinReconnectSeconds * math.Pow(2.0, math.Min(20.0, float64(attempts - 1)))
		    if (reconnectSeconds > natsMaxReconnectSeconds || reconnectSeconds <= 0.0) {
		        reconnectSeconds = natsMaxReconnectSeconds
		    }
		    reconnectDelay := time.Duration(reconnectSeconds * float64(time.Second))
		    h.logger.Debug(natsHandlerLogTag, "Increased reconnect to: %v", reconnectDelay)
		    return reconnectDelay
		}),
		nats.MaxReconnects(-1),
		nats.Secure(connectionInfo.TLSConfig),
	}

	connection, err := h.connector(connectionInfo.Addr, natsOptions...)
	// just log this error. even if currently cannot connect to nats, we can eventually
	if err != nil {
		return bosherr.WrapError(err, "Connecting to NATS")
	}

	h.connection = connection

	settings := h.settingsService.GetSettings()

	subject := fmt.Sprintf("agent.%s", settings.AgentID)

	h.logger.Info(h.logTag, "Subscribing to %s", subject)

	_, err = h.connection.Subscribe(subject, func(natsMsg *nats.Msg) {
		// Do not lock handler funcs around possible network calls!
		h.handlerFuncsLock.Lock()
		handlerFuncs := h.handlerFuncs
		h.handlerFuncsLock.Unlock()

		for _, handlerFunc := range handlerFuncs {
			h.handleNatsMsg(natsMsg, handlerFunc)
		}
	})
	if err != nil {
		return bosherr.WrapErrorf(err, "Subscribing to %s", subject)
	}

	return nil
}

func (h *natsHandler) RegisterAdditionalFunc(handlerFunc boshhandler.Func) {
	// Currently not locking since RegisterAdditionalFunc
	// is not a primary way of adding handlerFunc.
	h.handlerFuncsLock.Lock()
	h.handlerFuncs = append(h.handlerFuncs, handlerFunc)
	h.handlerFuncsLock.Unlock()
}

func (h *natsHandler) Send(target boshhandler.Target, topic boshhandler.Topic, message interface{}) error {
	bytes, err := json.Marshal(message)
	if err != nil {
		return bosherr.WrapErrorf(err, "Marshalling message (target=%s, topic=%s): %#v", target, topic, message)
	}

	h.logger.Info(h.logTag, "Sending %s message '%s'", target, topic)
	h.logger.DebugWithDetails(h.logTag, "Message Payload", string(bytes))

	settings := h.settingsService.GetSettings()

	subject := fmt.Sprintf("%s.agent.%s.%s", target, topic, settings.AgentID)
	if h.connection != nil {
		return h.connection.Publish(subject, bytes)
	}
	return nil
}

func (h *natsHandler) Stop() {
	if h.connection != nil {
		h.connection.Close()
	}
}

func (h *natsHandler) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
	natsBoshInternalsRegexp := regexp.MustCompile(`^[a-zA-Z0-9*\-]*.nats.bosh-internal$`)
	for _, chain := range verifiedChains {
		if len(chain) == 0 {
			continue
		}
		commonName := chain[0].Subject.CommonName
		if natsBoshInternalsRegexp.MatchString(commonName) {
			return nil
		}
	}
	return errors.New("server Certificate CommonName does not match *.nats.bosh-internal")
}

func (h *natsHandler) handleNatsMsg(natsMsg *nats.Msg, handlerFunc boshhandler.Func) {
	respBytes, req, err := boshhandler.PerformHandlerWithJSON(
		natsMsg.Data,
		handlerFunc,
		responseMaxLength,
		h.logger,
	)

	if err != nil {
		h.logger.Error(h.logTag, "Running handler: %s", err)
		h.generateCEFLog(natsMsg, 7, err.Error())
		return
	}

	if len(respBytes) > 0 {
		err = h.connection.Publish(req.ReplyTo, respBytes)
		if err != nil {
			h.generateCEFLog(natsMsg, 7, err.Error())
			h.logger.Error(h.logTag, "Publishing to the client: %s", err.Error())
			return
		}
	}

	h.generateCEFLog(natsMsg, 1, "")
}

func (h *natsHandler) runUntilInterrupted() {
	defer h.connection.Close()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)

	keepRunning := true
	for keepRunning {
		<-c
		keepRunning = false
	}
}

func (h *natsHandler) getConnectionInfo() (*ConnectionInfo, error) {
	settings := h.settingsService.GetSettings()

	connInfo := new(ConnectionInfo)
	connInfo.Addr = settings.GetMbusURL()
	natsURL, err := url.Parse(connInfo.Addr)
	if err != nil {
		return nil, bosherr.WrapError(err, "Parsing Nats URL")
	}

	hostSplit := strings.Split(natsURL.Host, ":")
	connInfo.IP = hostSplit[0]

	connInfo.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}

	caCert := settings.GetMbusCerts().CA
	if caCert != "" {
		connInfo.TLSConfig.RootCAs = x509.NewCertPool()
		if ok := connInfo.TLSConfig.RootCAs.AppendCertsFromPEM([]byte(caCert)); !ok {
			return nil, bosherr.Error("Failed to load Mbus CA cert")
		}
	}

	connInfo.TLSConfig.VerifyPeerCertificate = h.VerifyPeerCertificate

	clientCertificate, err := tls.X509KeyPair([]byte(settings.GetMbusCerts().Certificate), []byte(settings.GetMbusCerts().PrivateKey))
	if err != nil {
		return nil, bosherr.WrapError(err, "Parsing certificate and private key")
	}
	connInfo.TLSConfig.Certificates = []tls.Certificate{clientCertificate}

	return connInfo, nil
}

func (h *natsHandler) generateCEFLog(natsMsg *nats.Msg, severity int, statusReason string) {
	cef := boshhandler.NewCommonEventFormat()

	settings := h.settingsService.GetSettings()

	natsURL, err := url.Parse(settings.GetMbusURL())
	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
		return
	}

	hostSplit := strings.Split(natsURL.Host, ":")
	ip := hostSplit[0]
	payload := struct {
		Method  string `json:"method"`
		ReplyTo string `json:"reply_to"`
	}{}
	err = json.Unmarshal(natsMsg.Data, &payload)
	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
	}
	cefString, err := cef.ProduceNATSRequestEventLog(ip, hostSplit[1], payload.ReplyTo, payload.Method, severity, natsMsg.Subject, statusReason)

	if err != nil {
		h.logger.Error(natsHandlerLogTag, err.Error())
		return
	}

	if severity == 7 {
		h.auditLogger.Err(cefString)
		return
	}

	h.auditLogger.Debug(cefString)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Christian Muehlhaeuser
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *	Authors:
 *		Christian Muehlhaeuser <muesli@gmail.com>
 *		Michael Wendland <michael@michiwend.com>
 */

package smartcrop

import (
	"errors"
	"fmt"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

var (
	testFile = "./samples/gopher.jpg"
)

type SubImager interface {
	SubImage(r image.Rectangle) image.Image
}

func TestCrop(t *testing.T) {
	fi, _ := os.Open(testFile)
	defer fi.Close()

	img, _, err := image.Decode(fi)
	if err != nil {
		t.Error(err)
	}

	topCrop, err := SmartCrop(img, 250, 250)
	if err != nil {
		t.Error(err)
	}
	want := image.Rect(196, 42, 580, 427)
	if topCrop != want {
		t.Fatalf("want %v, got %v", want, topCrop)
	}

	sub, ok := img.(SubImager)
	if ok {
		cropImage := sub.SubImage(topCrop)
		//		cropImage := sub.SubImage(image.Rect(topCrop.X, topCrop.Y, topCrop.Width+topCrop.X, topCrop.Height+topCrop.Y))
		writeImage("jpeg", cropImage, "./smartcrop.jpg")

	} else {
		t.Error(errors.New("No SubImage support"))
	}
}

func BenchmarkCrop(b *testing.B) {
	fi, err := os.Open(testFile)
	if err != nil {
		b.Fatal(err)
	}
	defer fi.Close()
	img, _, err := image.Decode(fi)
	if err != nil {
		b.Fatal(err)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		if _, err := SmartCrop(img, 250, 250); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkEdge(b *testing.B) {
	fname := "24391757.jpg"
	fi, _ := os.Open("./samples/" + fname)
	defer fi.Close()
	img, _, err := image.Decode(fi)
	if err != nil {
		b.Error(err)
	}

	rgbaImg := toRGBA(img)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		o := image.NewRGBA(img.Bounds())
		edgeDetect(rgbaImg, o)
	}
}

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

	files, err := ioutil.ReadDir("./samples/hatchet")
	if err != nil {
		b.Error(err)
	}

	b.StartTimer()
	for _, file := range files {
		if strings.Contains(file.Name(), ".jpg") {

			fi, _ := os.Open("./samples/hatchet/" + file.Name())
			defer fi.Close()

			img, _, err := image.Decode(fi)
			if err != nil {
				b.Error(err)
			}

			topCrop, err := SmartCrop(img, 220, 220)
			if err != nil {
				b.Error(err)
			}
			fmt.Printf("Top crop: %+v\n", topCrop)

			sub, ok := img.(SubImager)
			if ok {
				cropImage := sub.SubImage(topCrop)
				//				cropImage := sub.SubImage(image.Rect(topCrop.X, topCrop.Y, topCrop.Width+topCrop.X, topCrop.Height+topCrop.Y))
				writeImage("jpeg", cropImage, "/tmp/smartcrop/smartcrop-"+file.Name())
			} else {
				b.Error(errors.New("No SubImage support"))
			}
		}
	}
	//fmt.Println("average time/image:", b.t
}
<commit_msg>Fixed tests<commit_after>/*
 * Copyright (c) 2014 Christian Muehlhaeuser
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *	Authors:
 *		Christian Muehlhaeuser <muesli@gmail.com>
 *		Michael Wendland <michael@michiwend.com>
 */

package smartcrop

import (
	"errors"
	"fmt"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

var (
	testFile = "./examples/gopher.jpg"
)

type SubImager interface {
	SubImage(r image.Rectangle) image.Image
}

func TestCrop(t *testing.T) {
	fi, _ := os.Open(testFile)
	defer fi.Close()

	img, _, err := image.Decode(fi)
	if err != nil {
		t.Fatal(err)
	}

	topCrop, err := SmartCrop(img, 250, 250)
	if err != nil {
		t.Error(err)
	}
	want := image.Rect(717, 42, 1101, 427)
	if topCrop != want {
		t.Fatalf("want %v, got %v", want, topCrop)
	}

	sub, ok := img.(SubImager)
	if ok {
		cropImage := sub.SubImage(topCrop)
		// cropImage := sub.SubImage(image.Rect(topCrop.X, topCrop.Y, topCrop.Width+topCrop.X, topCrop.Height+topCrop.Y))
		writeImage("jpeg", cropImage, "./smartcrop.jpg")
	} else {
		t.Error(errors.New("No SubImage support"))
	}
}

func BenchmarkCrop(b *testing.B) {
	fi, err := os.Open(testFile)
	if err != nil {
		b.Fatal(err)
	}
	defer fi.Close()
	img, _, err := image.Decode(fi)
	if err != nil {
		b.Fatal(err)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		if _, err := SmartCrop(img, 250, 250); err != nil {
			b.Error(err)
		}
	}
}

func BenchmarkEdge(b *testing.B) {
	fi, _ := os.Open(testFile)
	defer fi.Close()
	img, _, err := image.Decode(fi)
	if err != nil {
		b.Fatal(err)
	}

	rgbaImg := toRGBA(img)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		o := image.NewRGBA(img.Bounds())
		edgeDetect(rgbaImg, o)
	}
}

func BenchmarkImageDir(b *testing.B) {
	files, err := ioutil.ReadDir("./examples")
	if err != nil {
		b.Error(err)
	}

	b.ResetTimer()
	for _, file := range files {
		if strings.Contains(file.Name(), ".jpg") {
			fi, _ := os.Open("./examples/" + file.Name())
			defer fi.Close()

			img, _, err := image.Decode(fi)
			if err != nil {
				b.Error(err)
			}

			topCrop, err := SmartCrop(img, 220, 220)
			if err != nil {
				b.Error(err)
			}
			fmt.Printf("Top crop: %+v\n", topCrop)

			sub, ok := img.(SubImager)
			if ok {
				cropImage := sub.SubImage(topCrop)
				// cropImage := sub.SubImage(image.Rect(topCrop.X, topCrop.Y, topCrop.Width+topCrop.X, topCrop.Height+topCrop.Y))
				writeImage("jpeg", cropImage, "/tmp/smartcrop/smartcrop-"+file.Name())
			} else {
				b.Error(errors.New("No SubImage support"))
			}
		}
	}
	// fmt.Println("average time/image:", b.t)
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    //"time"
    "runtime"
)

func main() {
    //Run with 4 CPUs
    parallelism := runtime.GOMAXPROCS(runtime.NumCPU())

    //var N int = 3
    c := make(chan int, parallelism)

    go func() {
        defer close(c)

        fmt.Println("Filling channel")
        c <- 3
        fmt.Println("Filling channel")
        c <- 2
        fmt.Println("Filling channel")
        c <- 1
    }()

    func() {
        lcm1 := len(c)
        k := 0

        for i := range c {
            k++
            fmt.Println("Draining channel of",i)

            if k == lcm1 {
                //close(c)
            }
        }
    }()

    //time.Sleep(5 * 1e9)
    //defer close(c)
    //fmt.Println(N, c)
}<commit_msg>Extracting loops into defined methods.<commit_after>package main

import (
    "fmt"
    "runtime"
)

func main() {
    //Run with max possible CPUs
    parallelism := 4
    runtime.GOMAXPROCS(runtime.NumCPU())

    var N int = 1e5 //Number of integers that will be in the channel

    c := make(chan int, parallelism) //Create our channel

    //In a separate thread, fill the channel
    go func() {
        defer close(c)
        fillChannel(c, N)
    }()

    //In this thread, drain the channel as it fills
    func() {
        drainChannel(c)
    }()

    fmt.Println(parallelism)
}

func fillChannel(c chan int, N int) {
    for i := 0; i < N; i++ {
        fmt.Println("Filling channel")
        c <- i
    }
}

func drainChannel(c chan int) {
    for i := range c {
        fmt.Println("Draining channel of",i)
    }
}<|endoftext|>


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

package client

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/cmd/cmdtest"
	check "gopkg.in/check.v1"
)

func (s *S) TestCertificateSetRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
		Args: []string{
			"./testdata/cert/server.crt",
			"./testdata/cert/server.key",
		},
	}
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{Status: http.StatusNoContent},
		CondFunc: func(req *http.Request) bool {
			url := strings.HasSuffix(req.URL.Path, "/apps/secret/certificate")
			method := req.Method == http.MethodPut
			cname := req.FormValue("cname") == "app.io"
			certificate := req.FormValue("certificate") == s.mustReadFileString(c, "./testdata/cert/server.crt")
			key := req.FormValue("key") == s.mustReadFileString(c, "./testdata/cert/server.key")
			return url && method && cname && certificate && key
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateSet{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, "Successfully created the certificated.\n")
}

func (s *S) TestCertificateSetRunCerticateNotFound(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
		Args: []string{
			"./testdata/cert/not-found.crt",
			"./testdata/cert/server.key",
		},
	}
	trans := &cmdtest.Transport{Status: http.StatusOK}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateSet{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(os.IsNotExist(err), check.Equals, true)
	c.Assert(stdout.String(), check.Equals, "")
}

func (s *S) TestCertificateUnsetRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{Status: http.StatusNoContent},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/secret/certificate")
			method := req.Method == http.MethodDelete
			cname := req.FormValue("cname") == "app.io"

			return url && method && cname
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateUnset{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, "Certificate removed.\n")
	c.Assert(requestCount, check.Equals, 1)
}

func (s *S) mustReadFileString(c *check.C, path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		c.Fatal(err)
		return ""
	}
	return string(data)
}

func (s *S) TestCertificateListRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	certMap := map[string]string{
		"myapp.io":       s.mustReadFileString(c, "./testdata/cert/server.crt"),
		"myapp.other.io": "",
	}
	data, err := json.Marshal(certMap)
	c.Assert(err, check.IsNil)
	expectedDate, err := time.Parse("2006-01-02 15:04:05", "2027-01-10 20:33:11")
	c.Assert(err, check.IsNil)
	datestr := expectedDate.Local().Format("2006-01-02 15:04:05")
	expected := `+----------------+---------------------+----------------------------+----------------------------+
| CName          | Expires             | Issuer                     | Subject                    |
+----------------+---------------------+----------------------------+----------------------------+
| myapp.io       | ` + datestr + ` | C=BR; ST=Rio de Janeiro;   | C=BR; ST=Rio de Janeiro;   |
|                |                     | L=Rio de Janeiro; O=Tsuru; | L=Rio de Janeiro; O=Tsuru; |
|                |                     | CN=app.io                  | CN=app.io                  |
+----------------+---------------------+----------------------------+----------------------------+
| myapp.other.io | -                   | -                          | -                          |
+----------------+---------------------+----------------------------+----------------------------+
`
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{
			Status:  http.StatusNoContent,
			Message: string(data),
		},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/myapp/certificate")
			method := req.Method == http.MethodGet
			return url && method
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "myapp"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateList{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{})
	err = command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, expected)
	c.Assert(requestCount, check.Equals, 1)
}

func (s *S) TestCertificateListRawRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	certData := s.mustReadFileString(c, "./testdata/cert/server.crt")
	certMap := map[string]string{
		"myapp.io":       certData,
		"myapp.other.io": "",
	}
	data, err := json.Marshal(certMap)
	c.Assert(err, check.IsNil)
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{
			Status:  http.StatusNoContent,
			Message: string(data),
		},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/myapp/certificate")
			method := req.Method == http.MethodGet
			return url && method
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "myapp"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateList{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-r"})
	err = command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(strings.Contains(stdout.String(), "myapp.other.io:\nNo certificate."), check.Equals, true)
	c.Assert(strings.Contains(stdout.String(), "myapp.io:\n"+certData), check.Equals, true)
	c.Assert(requestCount, check.Equals, 1)
}
<commit_msg>Fix certificate tests<commit_after>// Copyright 2017 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package client

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/cmd/cmdtest"
	check "gopkg.in/check.v1"
)

func (s *S) TestCertificateSetRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
		Args: []string{
			"./testdata/cert/server.crt",
			"./testdata/cert/server.key",
		},
	}
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{Status: http.StatusNoContent},
		CondFunc: func(req *http.Request) bool {
			url := strings.HasSuffix(req.URL.Path, "/apps/secret/certificate")
			method := req.Method == http.MethodPut
			cname := req.FormValue("cname") == "app.io"
			certificate := req.FormValue("certificate") == s.mustReadFileString(c, "./testdata/cert/server.crt")
			key := req.FormValue("key") == s.mustReadFileString(c, "./testdata/cert/server.key")
			return url && method && cname && certificate && key
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateSet{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, "Successfully created the certificated.\n")
}

func (s *S) TestCertificateSetRunCerticateNotFound(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
		Args: []string{
			"./testdata/cert/not-found.crt",
			"./testdata/cert/server.key",
		},
	}
	trans := &cmdtest.Transport{Status: http.StatusOK}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateSet{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(os.IsNotExist(err), check.Equals, true)
	c.Assert(stdout.String(), check.Equals, "")
}

func (s *S) TestCertificateUnsetRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{Status: http.StatusNoContent},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/secret/certificate")
			method := req.Method == http.MethodDelete
			cname := req.FormValue("cname") == "app.io"

			return url && method && cname
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "secret"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateUnset{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-c", "app.io"})
	c.Assert(command.cname, check.Equals, "app.io")
	err := command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, "Certificate removed.\n")
	c.Assert(requestCount, check.Equals, 1)
}

func (s *S) mustReadFileString(c *check.C, path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		c.Fatal(err)
		return ""
	}
	return string(data)
}

func (s *S) TestCertificateListRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	certMap := map[string]map[string]string{
		"ingress-router": {
			"myapp.io":       s.mustReadFileString(c, "./testdata/cert/server.crt"),
			"myapp.other.io": "",
		},
	}
	data, err := json.Marshal(certMap)
	c.Assert(err, check.IsNil)
	expectedDate, err := time.Parse("2006-01-02 15:04:05", "2027-01-10 20:33:11")
	c.Assert(err, check.IsNil)
	datestr := expectedDate.Local().Format("2006-01-02 15:04:05")
	expected := `+----------------+----------------+---------------------+----------------------------+----------------------------+
| Router         | CName          | Expires             | Issuer                     | Subject                    |
+----------------+----------------+---------------------+----------------------------+----------------------------+
| ingress-router | myapp.io       | ` + datestr + ` | C=BR; ST=Rio de Janeiro;   | C=BR; ST=Rio de Janeiro;   |
|                |                |                     | L=Rio de Janeiro; O=Tsuru; | L=Rio de Janeiro; O=Tsuru; |
|                |                |                     | CN=app.io                  | CN=app.io                  |
+----------------+----------------+---------------------+----------------------------+----------------------------+
| ingress-router | myapp.other.io | -                   | -                          | -                          |
+----------------+----------------+---------------------+----------------------------+----------------------------+
`
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{
			Status:  http.StatusNoContent,
			Message: string(data),
		},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/myapp/certificate")
			method := req.Method == http.MethodGet
			return url && method
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "myapp"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateList{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{})
	err = command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(stdout.String(), check.Equals, expected)
	c.Assert(requestCount, check.Equals, 1)
}

func (s *S) TestCertificateListRawRunSuccessfully(c *check.C) {
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	requestCount := 0
	certData := s.mustReadFileString(c, "./testdata/cert/server.crt")
	certMap := map[string]map[string]string{
		"ingress-router": {
			"myapp.io":       certData,
			"myapp.other.io": "",
		},
	}
	data, err := json.Marshal(certMap)
	c.Assert(err, check.IsNil)
	trans := &cmdtest.ConditionalTransport{
		Transport: cmdtest.Transport{
			Status:  http.StatusNoContent,
			Message: string(data),
		},
		CondFunc: func(req *http.Request) bool {
			requestCount++
			url := strings.HasSuffix(req.URL.Path, "/apps/myapp/certificate")
			method := req.Method == http.MethodGet
			return url && method
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager)
	fake := cmdtest.FakeGuesser{Name: "myapp"}
	guessCommand := cmd.GuessingCommand{G: &fake}
	command := CertificateList{GuessingCommand: guessCommand}
	command.Flags().Parse(true, []string{"-r"})
	err = command.Run(&context, client)
	c.Assert(err, check.IsNil)
	c.Assert(strings.Contains(stdout.String(), "myapp.other.io:\nNo certificate."), check.Equals, true)
	c.Assert(strings.Contains(stdout.String(), "myapp.io:\n"+certData), check.Equals, true)
	c.Assert(requestCount, check.Equals, 1)
}
<|endoftext|>


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

package orchestrator

import (
	"github.com/andreaskoch/allmark2/common/index"
	"github.com/andreaskoch/allmark2/common/paths"
	"github.com/andreaskoch/allmark2/common/route"
	"github.com/andreaskoch/allmark2/model"
	"github.com/andreaskoch/allmark2/services/conversion"
	"github.com/andreaskoch/allmark2/ui/web/view/viewmodel"
)

func NewViewModelOrchestrator(itemIndex *index.ItemIndex, converter conversion.Converter, navigationOrchestrator *NavigationOrchestrator, tagOrchestrator *TagsOrchestrator) ViewModelOrchestrator {
	return ViewModelOrchestrator{
		itemIndex:              itemIndex,
		converter:              converter,
		navigationOrchestrator: navigationOrchestrator,
		tagOrchestrator:        tagOrchestrator,
	}
}

type ViewModelOrchestrator struct {
	itemIndex              *index.ItemIndex
	converter              conversion.Converter
	navigationOrchestrator *NavigationOrchestrator
	tagOrchestrator        *TagsOrchestrator
}

func (orchestrator *ViewModelOrchestrator) GetViewModel(pathProvider paths.Pather, item *model.Item) viewmodel.Model {

	// convert content
	convertedContent, err := orchestrator.converter.Convert(pathProvider, item)
	if err != nil {
		return viewmodel.Model{}
	}

	// create a view model
	viewModel := viewmodel.Model{
		Base:    getBaseModel(item),
		Content: convertedContent,
		Childs:  orchestrator.getChildModels(item.Route()),

		// navigation
		ToplevelNavigation:   orchestrator.navigationOrchestrator.GetToplevelNavigation(),
		BreadcrumbNavigation: orchestrator.navigationOrchestrator.GetBreadcrumbNavigation(item),

		// documents
		TopDocs: orchestrator.getTopDocuments(5, pathProvider, item.Route()),

		// tags
		Tags:     orchestrator.tagOrchestrator.GetItemTags(item),
		TagCloud: orchestrator.tagOrchestrator.GetTagCloud(),
	}

	return viewModel
}

func (orchestrator *ViewModelOrchestrator) getTopDocuments(numberOfTopDocuments int, pathProvider paths.Pather, route *route.Route) []*viewmodel.Model {

	childItems := orchestrator.itemIndex.GetAllChilds(route)

	// determine the candidates for the top-documents
	candidateModels := make([]*viewmodel.Model, 0)

	for _, childItem := range childItems {

		if childItem.IsVirtual() {

			// the child is virtual: get the top documents of the child
			candidateModels = append(candidateModels, orchestrator.getTopDocuments(numberOfTopDocuments, pathProvider, childItem.Route())...)

		} else {

			// create viewmodel and append to list
			childModel := orchestrator.GetViewModel(pathProvider, childItem)
			candidateModels = append(candidateModels, &childModel)

		}

	}

	// sort the candidates
	viewmodel.SortModelBy(sortModelsByDateAndRoute).Sort(candidateModels)

	// take the top models only
	if len(candidateModels) <= numberOfTopDocuments {
		return candidateModels
	}

	return candidateModels[:numberOfTopDocuments]
}

func (orchestrator *ViewModelOrchestrator) getChildModels(route *route.Route) []*viewmodel.Base {
	childModels := make([]*viewmodel.Base, 0)

	childItems := orchestrator.itemIndex.GetChilds(route)
	for _, childItem := range childItems {
		baseModel := getBaseModel(childItem)
		childModels = append(childModels, &baseModel)
	}

	return childModels
}
<commit_msg>Don't recurse for Top Documents ... this takes too much performance<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package orchestrator

import (
	"github.com/andreaskoch/allmark2/common/index"
	"github.com/andreaskoch/allmark2/common/paths"
	"github.com/andreaskoch/allmark2/common/route"
	"github.com/andreaskoch/allmark2/model"
	"github.com/andreaskoch/allmark2/services/conversion"
	"github.com/andreaskoch/allmark2/ui/web/view/viewmodel"
)

func NewViewModelOrchestrator(itemIndex *index.ItemIndex, converter conversion.Converter, navigationOrchestrator *NavigationOrchestrator, tagOrchestrator *TagsOrchestrator) ViewModelOrchestrator {
	return ViewModelOrchestrator{
		itemIndex:              itemIndex,
		converter:              converter,
		navigationOrchestrator: navigationOrchestrator,
		tagOrchestrator:        tagOrchestrator,
	}
}

type ViewModelOrchestrator struct {
	itemIndex              *index.ItemIndex
	converter              conversion.Converter
	navigationOrchestrator *NavigationOrchestrator
	tagOrchestrator        *TagsOrchestrator
}

func (orchestrator *ViewModelOrchestrator) GetViewModel(pathProvider paths.Pather, item *model.Item) viewmodel.Model {

	// convert content
	convertedContent, err := orchestrator.converter.Convert(pathProvider, item)
	if err != nil {
		return viewmodel.Model{}
	}

	// create a view model
	viewModel := viewmodel.Model{
		Base:    getBaseModel(item),
		Content: convertedContent,
		Childs:  orchestrator.getChildModels(item.Route()),

		// navigation
		ToplevelNavigation:   orchestrator.navigationOrchestrator.GetToplevelNavigation(),
		BreadcrumbNavigation: orchestrator.navigationOrchestrator.GetBreadcrumbNavigation(item),

		// documents
		TopDocs: orchestrator.getTopDocuments(5, pathProvider, item.Route()),

		// tags
		Tags:     orchestrator.tagOrchestrator.GetItemTags(item),
		TagCloud: orchestrator.tagOrchestrator.GetTagCloud(),
	}

	return viewModel
}

func (orchestrator *ViewModelOrchestrator) getTopDocuments(numberOfTopDocuments int, pathProvider paths.Pather, route *route.Route) []*viewmodel.Model {

	baseRouteLevel := route.Level()
	nextRouteLevel := baseRouteLevel + 1
	childItems := orchestrator.itemIndex.GetAllChilds(route)

	// determine the candidates for the top-documents
	candidateModels := make([]*viewmodel.Model, 0)

	for len(candidateModels) == 0 && nextRouteLevel != baseRouteLevel+3 {

		for _, childItem := range childItems {

			if childItem.Route().Level() != nextRouteLevel {
				continue
			}

			// create viewmodel and append to list
			childModel := orchestrator.GetViewModel(pathProvider, childItem)
			candidateModels = append(candidateModels, &childModel)

		}

		nextRouteLevel++

	}

	// sort the candidates
	viewmodel.SortModelBy(sortModelsByDateAndRoute).Sort(candidateModels)

	// take the top models only
	if len(candidateModels) <= numberOfTopDocuments {
		return candidateModels
	}

	return candidateModels[:numberOfTopDocuments]
}

func (orchestrator *ViewModelOrchestrator) getChildModels(route *route.Route) []*viewmodel.Base {
	childModels := make([]*viewmodel.Base, 0)

	childItems := orchestrator.itemIndex.GetChilds(route)
	for _, childItem := range childItems {
		baseModel := getBaseModel(childItem)
		childModels = append(childModels, &baseModel)
	}

	return childModels
}
<|endoftext|>


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

//go:build ignore
// +build ignore

package main

var Time float
var Cursor vec2
var ScreenSize vec2

func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	const (
		BLURSCALEX  = 0.45
		LOWLUMSCAN  = 5.0
		HILUMSCAN   = 10.0
		BRIGHTBOOST = 1.25
		MASK_DARK   = 0.25
		MASK_FADE   = 0.8
	)

	pos := texCoord
	origin, size := imageDstRegionOnTexture()
	pos -= origin
	pos /= size

	maskFade := 0.3333 * MASK_FADE
	invDims := 1.0 / imageDstTextureSize().xy
	p := pos * imageDstTextureSize()
	i := floor(p) + 0.50
	f := p - i
	p = (i + 4.0*f*f*f) * invDims
	p.x = mix(p.x, pos.x, BLURSCALEX)
	Y := f.y * f.y
	YY := Y * Y
	whichmask := fract(pos.x * -0.4999)
	mask := 1.0
	if whichmask < 0.5 {
		mask -= MASK_DARK
	}

	clr := imageSrc2At(p*size + origin).rgb
	scanLineWeight := (BRIGHTBOOST - LOWLUMSCAN*(Y-2.05*YY))
	scanLineWeightB := 1.0 - HILUMSCAN*(YY-2.8*YY*Y)

	return vec4(clr.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(clr.rgb, vec3(maskFade))), 1.0)
}
<commit_msg>examples/shader: bug fix: wrong function usages<commit_after>// Copyright 2022 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build ignore
// +build ignore

package main

var Time float
var Cursor vec2
var ScreenSize vec2

func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	const (
		blurScaleX  = 0.45
		lowLumScan  = 5.0
		hiLumScan   = 10.0
		BrightBoost = 1.25
		maskDark    = 0.25
		maskFade    = 0.8
	)

	pos := texCoord
	origin, size := imageSrcRegionOnTexture()
	pos -= origin
	pos /= size

	maskFade := 0.3333 * maskFade
	invDims := 1.0 / imageSrcTextureSize().xy
	p := pos * imageSrcTextureSize()
	i := floor(p) + 0.50
	f := p - i
	p = (i + 4.0*f*f*f) * invDims
	p.x = mix(p.x, pos.x, blurScaleX)
	Y := f.y * f.y
	YY := Y * Y
	whichmask := fract(pos.x * -0.4999)
	mask := 1.0
	if whichmask < 0.5 {
		mask -= maskDark
	}

	clr := imageSrc2At(p*size + origin).rgb
	scanLineWeight := (BrightBoost - lowLumScan*(Y-2.05*YY))
	scanLineWeightB := 1.0 - hiLumScan*(YY-2.8*YY*Y)

	return vec4(clr.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(clr.rgb, vec3(maskFade))), 1.0)
}
<|endoftext|>


<commit_before>// Command merge-docker-save repacks output of docker save command called for
// single image to a tar stream with merged content of all image layers
//
// Usage:
//
// 	docker save image:tag | merge-docker-save > image-fs.tar
package main

import (
	"archive/tar"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/artyom/autoflags"
)

func main() {
	args := struct {
		File string `flag:"o,file to write output to instead of stdout"`
	}{}
	autoflags.Parse(&args)
	if err := do(args.File, os.Stdin); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func do(name string, input io.Reader) error {
	output, err := openOutput(name)
	if err != nil {
		return err
	}
	defer output.Close()
	if err := repack(output, input); err != nil {
		return err
	}
	return output.Close()
}

func repack(out io.Writer, input io.Reader) error {
	tr := tar.NewReader(input)
	tw := tar.NewWriter(out)
	var layers []string
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return tw.Close()
		}
		if err != nil {
			return err
		}
		if strings.HasSuffix(hdr.Name, "/layer.tar") {
			layers = append(layers, hdr.Name)
			if err := copyStream(tw, tar.NewReader(tr)); err != nil {
				return err
			}
			continue
		}
		if hdr.Name == "manifest.json" {
			mlayers, err := decodeLayerList(tr)
			if err != nil {
				return err
			}
			if err := compareLayers(layers, mlayers); err != nil {
				return err
			}
		}
		if _, err := io.Copy(ioutil.Discard, tr); err != nil {
			return err
		}
	}
}

func copyStream(tw *tar.Writer, tr *tar.Reader) error {
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		if err := tw.WriteHeader(hdr); err != nil {
			return err
		}
		if _, err := io.Copy(tw, tr); err != nil {
			return err
		}
	}
}

func decodeLayerList(r io.Reader) ([]string, error) {
	data := []struct {
		Layers []string
	}{}
	if err := json.NewDecoder(r).Decode(&data); err != nil {
		return nil, err
	}
	if l := len(data); l != 1 {
		return nil, fmt.Errorf("manifest has %d objects, want 1", l)
	}
	return data[0].Layers, nil
}

func compareLayers(layers, mlayers []string) error {
	err := fmt.Errorf("unpacked layers and listed in manifest.json differ")
	if len(layers) != len(mlayers) {
		return err
	}
	for i := range layers {
		if layers[i] != mlayers[i] {
			return err
		}
	}
	return nil
}

func openOutput(name string) (io.WriteCloser, error) {
	if name == "" {
		return os.Stdout, nil
	}
	return os.Create(name)
}

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: docker save image:tag | %s > image-fs.tar\n", filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}
}
<commit_msg>Make error text more clear<commit_after>// Command merge-docker-save repacks output of docker save command called for
// single image to a tar stream with merged content of all image layers
//
// Usage:
//
// 	docker save image:tag | merge-docker-save > image-fs.tar
package main

import (
	"archive/tar"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/artyom/autoflags"
)

func main() {
	args := struct {
		File string `flag:"o,file to write output to instead of stdout"`
	}{}
	autoflags.Parse(&args)
	if err := do(args.File, os.Stdin); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func do(name string, input io.Reader) error {
	output, err := openOutput(name)
	if err != nil {
		return err
	}
	defer output.Close()
	if err := repack(output, input); err != nil {
		return err
	}
	return output.Close()
}

func repack(out io.Writer, input io.Reader) error {
	tr := tar.NewReader(input)
	tw := tar.NewWriter(out)
	var layers []string
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return tw.Close()
		}
		if err != nil {
			return err
		}
		if strings.HasSuffix(hdr.Name, "/layer.tar") {
			layers = append(layers, hdr.Name)
			if err := copyStream(tw, tar.NewReader(tr)); err != nil {
				return err
			}
			continue
		}
		if hdr.Name == "manifest.json" {
			mlayers, err := decodeLayerList(tr)
			if err != nil {
				return err
			}
			if err := compareLayers(layers, mlayers); err != nil {
				return err
			}
		}
		if _, err := io.Copy(ioutil.Discard, tr); err != nil {
			return err
		}
	}
}

func copyStream(tw *tar.Writer, tr *tar.Reader) error {
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		if err := tw.WriteHeader(hdr); err != nil {
			return err
		}
		if _, err := io.Copy(tw, tr); err != nil {
			return err
		}
	}
}

func decodeLayerList(r io.Reader) ([]string, error) {
	data := []struct {
		Layers []string
	}{}
	if err := json.NewDecoder(r).Decode(&data); err != nil {
		return nil, err
	}
	if l := len(data); l != 1 {
		return nil, fmt.Errorf("manifest.json describes %d objects, call docker save for a single image", l)
	}
	return data[0].Layers, nil
}

func compareLayers(layers, mlayers []string) error {
	err := fmt.Errorf("layers unpacked and listed in manifest.json differ")
	if len(layers) != len(mlayers) {
		return err
	}
	for i := range layers {
		if layers[i] != mlayers[i] {
			return err
		}
	}
	return nil
}

func openOutput(name string) (io.WriteCloser, error) {
	if name == "" {
		return os.Stdout, nil
	}
	return os.Create(name)
}

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: docker save image:tag | %s > image-fs.tar\n", filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}
}
<|endoftext|>


<commit_before>package unix_uid_pool_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/vito/garden/backend/linux_backend/uid_pool"
)

var _ = Describe("Unix UID pool", func() {
	Describe("acquiring", func() {
		It("returns the next available UID from the pool", func() {
			pool := uid_pool.New(10000, 5)

			uid1, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())

			uid2, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())

			Expect(uid1).To(Equal(uint32(10000)))
			Expect(uid2).To(Equal(uint32(10001)))
		})

		Context("when the pool is exhausted", func() {
			It("returns an error", func() {
				pool := uid_pool.New(10000, 5)

				for i := 0; i < 5; i++ {
					_, err := pool.Acquire()
					Expect(err).ToNot(HaveOccured())
				}

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})
		})

		Context("when there is an existing user with the UID", func() {
			It("returns an error", func() {
				pool := uid_pool.New(0, 5)

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})

			It("moves the uid to the end of the pool", func() {
				pool := uid_pool.New(0, 2)

				_, err1 := pool.Acquire()
				Expect(err1).To(HaveOccured())

				_, err2 := pool.Acquire()
				Expect(err2).To(HaveOccured())

				Expect(err2).ToNot(Equal(err1))

				_, err3 := pool.Acquire()
				Expect(err3).To(HaveOccured())

				Expect(err3).To(Equal(err1))
			})
		})
	})

	Describe("releasing", func() {
		It("places a uid back at the end of the pool", func() {
			pool := uid_pool.New(10000, 2)

			uid1, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(uid1).To(Equal(uint32(10000)))

			pool.Release(uid1)

			uid2, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(uid2).To(Equal(uint32(10001)))

			nextUID, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(nextUID).To(Equal(uint32(10000)))
		})

		Context("when the released uid is out of the range", func() {
			It("does not add it to the pool", func() {
				pool := uid_pool.New(10000, 0)

				pool.Release(20000)

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})
		})
	})
})
<commit_msg>fix uid pool tests<commit_after>package unix_uid_pool_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/vito/garden/backend/linux_backend/unix_uid_pool"
)

var _ = Describe("Unix UID pool", func() {
	Describe("acquiring", func() {
		It("returns the next available UID from the pool", func() {
			pool := unix_uid_pool.New(10000, 5)

			uid1, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())

			uid2, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())

			Expect(uid1).To(Equal(uint32(10000)))
			Expect(uid2).To(Equal(uint32(10001)))
		})

		Context("when the pool is exhausted", func() {
			It("returns an error", func() {
				pool := unix_uid_pool.New(10000, 5)

				for i := 0; i < 5; i++ {
					_, err := pool.Acquire()
					Expect(err).ToNot(HaveOccured())
				}

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})
		})

		Context("when there is an existing user with the UID", func() {
			It("returns an error", func() {
				pool := unix_uid_pool.New(0, 5)

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})

			It("moves the uid to the end of the pool", func() {
				pool := unix_uid_pool.New(0, 2)

				_, err1 := pool.Acquire()
				Expect(err1).To(HaveOccured())

				_, err2 := pool.Acquire()
				Expect(err2).To(HaveOccured())

				Expect(err2).ToNot(Equal(err1))

				_, err3 := pool.Acquire()
				Expect(err3).To(HaveOccured())

				Expect(err3).To(Equal(err1))
			})
		})
	})

	Describe("releasing", func() {
		It("places a uid back at the end of the pool", func() {
			pool := unix_uid_pool.New(10000, 2)

			uid1, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(uid1).To(Equal(uint32(10000)))

			pool.Release(uid1)

			uid2, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(uid2).To(Equal(uint32(10001)))

			nextUID, err := pool.Acquire()
			Expect(err).ToNot(HaveOccured())
			Expect(nextUID).To(Equal(uint32(10000)))
		})

		Context("when the released uid is out of the range", func() {
			It("does not add it to the pool", func() {
				pool := unix_uid_pool.New(10000, 0)

				pool.Release(20000)

				_, err := pool.Acquire()
				Expect(err).To(HaveOccured())
			})
		})
	})
})
<|endoftext|>