<commit_before>package irckit

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
	"unicode"

	"github.com/mattermost/platform/model"
)

type CommandHandler interface {
	handle(u *User, c *Command, args []string, service string)
}

type Command struct {
	handler   func(u *User, toUser *User, args []string, service string)
	minParams int
	maxParams int
	login     bool
}

func logout(u *User, toUser *User, args []string, service string) {
	switch service {
	case "mattermost":
		u.logoutFromMattermost()
	case "slack":
		u.logoutFromSlack()
	}
}

func login(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		var err error
		if len(args) != 1 {
			u.MsgUser(toUser, "need LOGIN <token>")
			return
		}
		u.Token = args[len(args)-1]
		if u.sc != nil {
			fmt.Println("login, starting logout")
			err := u.logoutFromSlack()
			if err != nil {
				u.MsgUser(toUser, err.Error())
				return
			}
		}
		if u.mc != nil {
			err := u.logoutFromMattermost()
			if err != nil {
				u.MsgUser(toUser, err.Error())
				return
			}
		}
		u.sc, err = u.loginToSlack()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
		u.MsgUser(toUser, "login OK")
		return
	}

	cred := &MmCredentials{}
	datalen := 4
	if u.Cfg.DefaultTeam != "" {
		cred.Team = u.Cfg.DefaultTeam
		datalen--
	}
	if u.Cfg.DefaultServer != "" {
		cred.Server = u.Cfg.DefaultServer
		datalen--
	}
	if len(args) == datalen {
		cred.Pass = args[len(args)-1]
		cred.Login = args[len(args)-2]
		// no default server or team specified
		if cred.Server == "" && cred.Team == "" {
			cred.Server = args[len(args)-4]
		}
		if cred.Team == "" {
			cred.Team = args[len(args)-3]
		}
		if cred.Server == "" {
			cred.Server = args[len(args)-3]
		}

	}

	// incorrect arguments
	if len(args) != datalen {
		// no server or team
		if cred.Team != "" && cred.Server != "" {
			u.MsgUser(toUser, "need LOGIN <login> <pass>")
			return
		}
		// server missing
		if cred.Team != "" {
			u.MsgUser(toUser, "need LOGIN <server> <login> <pass>")
			return
		}
		// team missing
		if cred.Server != "" {
			u.MsgUser(toUser, "need LOGIN <team> <login> <pass>")
			return
		}
		u.MsgUser(toUser, "need LOGIN <server> <team> <login> <pass>")
		return
	}

	if !u.isValidMMServer(cred.Server) {
		u.MsgUser(toUser, "not allowed to connect to "+cred.Server)
		return
	}

	if u.sc != nil {
		fmt.Println("login, starting logout")
		err := u.logoutFromSlack()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
	}
	if u.mc != nil {
		err := u.logoutFromMattermost()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
	}
	u.Credentials = cred
	var err error
	u.mc, err = u.loginToMattermost()
	if err != nil {
		u.MsgUser(toUser, err.Error())
		return
	}
	u.mc.OnWsConnect = u.addUsersToChannels
	go u.mc.StatusLoop()
	u.MsgUser(toUser, "login OK")
	// set nick to mattermost nickname or username if nick empty
	if u.mc.User.Nickname != "" {
		if !u.Srv.RenameUser(u, u.mc.User.Nickname) {
			u.Srv.RenameUser(u, u.mc.User.Username)
		}
	} else {
		u.Srv.RenameUser(u, u.mc.User.Username)
	}
}

func search(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	postlist := u.mc.SearchPosts(strings.Join(args, " "))
	if postlist == nil || len(postlist.Order) == 0 {
		u.MsgUser(toUser, "no results")
		return
	}
	for i := len(postlist.Order) - 1; i >= 0; i-- {
		timestamp := time.Unix(postlist.Posts[postlist.Order[i]].CreateAt/1000, 0).Format("January 02, 2006 15:04")
		channelname := u.mc.GetChannelName(postlist.Posts[postlist.Order[i]].ChannelId)
		u.MsgUser(toUser, "#"+channelname+" <"+u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username+"> "+timestamp)
		u.MsgUser(toUser, strings.Repeat("=", len("#"+channelname+" <"+u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username+"> "+timestamp)))
		for _, post := range strings.Split(postlist.Posts[postlist.Order[i]].Message, "\n") {
			if post != "" {
				u.MsgUser(toUser, post)
			}
		}
		if len(postlist.Posts[postlist.Order[i]].FileIds) > 0 {
			for _, fname := range u.mc.GetFileLinks(postlist.Posts[postlist.Order[i]].FileIds) {
				u.MsgUser(toUser, "download file - "+fname)
			}
		}
		u.MsgUser(toUser, "")
		u.MsgUser(toUser, "")
	}
}

func searchUsers(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	users, resp := u.mc.Client.SearchUsers(&model.UserSearch{Term: strings.Join(args, " ")})
	if resp.Error != nil {
		u.MsgUser(toUser, fmt.Sprint("Error", resp.Error))
		return
	}
	for _, user := range users {
		u.MsgUser(toUser, fmt.Sprint(user.Nickname, user.FirstName, user.LastName))
	}
}

func scrollback(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	if len(args) != 2 {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	limit, err := strconv.Atoi(args[1])
	if err != nil {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	if !strings.Contains(args[0], "#") {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	args[0] = strings.Replace(args[0], "#", "", -1)
	postlist := u.mc.GetPosts(u.mc.GetChannelId(args[0], u.mc.Team.Id), limit)
	if postlist == nil || len(postlist.Order) == 0 {
		u.MsgUser(toUser, "no results")
		return
	}
	for i := len(postlist.Order) - 1; i >= 0; i-- {
		nick := u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username
		for _, post := range strings.Split(postlist.Posts[postlist.Order[i]].Message, "\n") {
			if post != "" {
				u.MsgUser(toUser, "<"+nick+"> "+post)
			}
		}
		if len(postlist.Posts[postlist.Order[i]].FileIds) > 0 {
			for _, fname := range u.mc.GetFileLinks(postlist.Posts[postlist.Order[i]].FileIds) {
				u.MsgUser(toUser, "<"+nick+"> download file - "+fname)
			}
		}
	}

}

var cmds = map[string]Command{
	"logout":      {handler: logout, login: true, minParams: 0, maxParams: 0},
	"login":       {handler: login, minParams: 2, maxParams: 4},
	"search":      {handler: search, login: true, minParams: 1, maxParams: -1},
	"searchusers": {handler: searchUsers, login: true, minParams: 1, maxParams: -1},
	"scrollback":  {handler: scrollback, login: true, minParams: 2, maxParams: 2},
}

func (u *User) handleServiceBot(service string, toUser *User, msg string) {

	//func (u *User) handleMMServiceBot(toUser *User, msg string) {
	commands, err := parseCommandString(msg)
	if err != nil {
		u.MsgUser(toUser, fmt.Sprintf("\"%s\" is improperly formatted", msg))
		return
	}
	cmd, ok := cmds[strings.ToLower(commands[0])]
	if !ok {
		keys := make([]string, 0)
		for k := range cmds {
			keys = append(keys, k)
		}
		u.MsgUser(toUser, "possible commands: "+strings.Join(keys, ", "))
		u.MsgUser(toUser, "<command> help for more info")
		return
	}
	if cmd.login {
		switch service {
		case "mattermost":
			if u.mc == nil {
				u.MsgUser(toUser, "You're not logged in. Use LOGIN first.")
				return
			}
		case "slack":
			if u.sc == nil {
				u.MsgUser(toUser, "You're not logged in. Use LOGIN first.")
				return
			}
		}
	}
	/*
		if cmd.minParams > len(commands[1:]) {
			u.MsgUser(toUser, fmt.Sprintf("%s requires at least %v arguments", commands[0], cmd.minParams))
			return
		}
	*/
	if cmd.maxParams > -1 && len(commands[1:]) > cmd.maxParams {
		u.MsgUser(toUser, fmt.Sprintf("%s takes at most %v arguments", commands[0], cmd.maxParams))
		return
	}
	cmd.handler(u, toUser, commands[1:], service)
}

func parseCommandString(line string) ([]string, error) {
	args := []string{}
	buf := ""
	var escaped, doubleQuoted, singleQuoted bool

	got := false

	for _, r := range line {

		// If the string is escaped
		if escaped {
			buf += string(r)
			escaped = false
			continue
		}

		// If "\"
		if r == '\\' {
			if singleQuoted {
				buf += string(r)
			} else {
				escaped = true
			}
			continue
		}

		// If it is whitespace
		if unicode.IsSpace(r) {
			if singleQuoted || doubleQuoted {
				buf += string(r)
			} else if got {
				args = append(args, buf)
				buf = ""
				got = false
			}
			continue
		}
		// If Quoted
		switch r {
		case '"':
			if !singleQuoted {
				doubleQuoted = !doubleQuoted
				continue
			}
		case '\'':
			if !doubleQuoted {
				singleQuoted = !singleQuoted
				continue
			}
		}
		got = true
		buf += string(r)
	}

	if got {
		args = append(args, buf)
	}
	if escaped || singleQuoted || doubleQuoted {
		return nil, errors.New("invalid command line string")
	}

	return args, nil
}
<commit_msg>Revert "Set nickname to mattermost nickname or username. 42wim/matterircd#120"<commit_after>package irckit

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
	"unicode"

	"github.com/mattermost/platform/model"
)

type CommandHandler interface {
	handle(u *User, c *Command, args []string, service string)
}

type Command struct {
	handler   func(u *User, toUser *User, args []string, service string)
	minParams int
	maxParams int
	login     bool
}

func logout(u *User, toUser *User, args []string, service string) {
	switch service {
	case "mattermost":
		u.logoutFromMattermost()
	case "slack":
		u.logoutFromSlack()
	}
}

func login(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		var err error
		if len(args) != 1 {
			u.MsgUser(toUser, "need LOGIN <token>")
			return
		}
		u.Token = args[len(args)-1]
		if u.sc != nil {
			fmt.Println("login, starting logout")
			err := u.logoutFromSlack()
			if err != nil {
				u.MsgUser(toUser, err.Error())
				return
			}
		}
		if u.mc != nil {
			err := u.logoutFromMattermost()
			if err != nil {
				u.MsgUser(toUser, err.Error())
				return
			}
		}
		u.sc, err = u.loginToSlack()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
		u.MsgUser(toUser, "login OK")
		return
	}

	cred := &MmCredentials{}
	datalen := 4
	if u.Cfg.DefaultTeam != "" {
		cred.Team = u.Cfg.DefaultTeam
		datalen--
	}
	if u.Cfg.DefaultServer != "" {
		cred.Server = u.Cfg.DefaultServer
		datalen--
	}
	if len(args) == datalen {
		cred.Pass = args[len(args)-1]
		cred.Login = args[len(args)-2]
		// no default server or team specified
		if cred.Server == "" && cred.Team == "" {
			cred.Server = args[len(args)-4]
		}
		if cred.Team == "" {
			cred.Team = args[len(args)-3]
		}
		if cred.Server == "" {
			cred.Server = args[len(args)-3]
		}

	}

	// incorrect arguments
	if len(args) != datalen {
		// no server or team
		if cred.Team != "" && cred.Server != "" {
			u.MsgUser(toUser, "need LOGIN <login> <pass>")
			return
		}
		// server missing
		if cred.Team != "" {
			u.MsgUser(toUser, "need LOGIN <server> <login> <pass>")
			return
		}
		// team missing
		if cred.Server != "" {
			u.MsgUser(toUser, "need LOGIN <team> <login> <pass>")
			return
		}
		u.MsgUser(toUser, "need LOGIN <server> <team> <login> <pass>")
		return
	}

	if !u.isValidMMServer(cred.Server) {
		u.MsgUser(toUser, "not allowed to connect to "+cred.Server)
		return
	}

	if u.sc != nil {
		fmt.Println("login, starting logout")
		err := u.logoutFromSlack()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
	}
	if u.mc != nil {
		err := u.logoutFromMattermost()
		if err != nil {
			u.MsgUser(toUser, err.Error())
			return
		}
	}
	u.Credentials = cred
	var err error
	u.mc, err = u.loginToMattermost()
	if err != nil {
		u.MsgUser(toUser, err.Error())
		return
	}
	u.mc.OnWsConnect = u.addUsersToChannels
	go u.mc.StatusLoop()
	u.MsgUser(toUser, "login OK")

}

func search(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	postlist := u.mc.SearchPosts(strings.Join(args, " "))
	if postlist == nil || len(postlist.Order) == 0 {
		u.MsgUser(toUser, "no results")
		return
	}
	for i := len(postlist.Order) - 1; i >= 0; i-- {
		timestamp := time.Unix(postlist.Posts[postlist.Order[i]].CreateAt/1000, 0).Format("January 02, 2006 15:04")
		channelname := u.mc.GetChannelName(postlist.Posts[postlist.Order[i]].ChannelId)
		u.MsgUser(toUser, "#"+channelname+" <"+u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username+"> "+timestamp)
		u.MsgUser(toUser, strings.Repeat("=", len("#"+channelname+" <"+u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username+"> "+timestamp)))
		for _, post := range strings.Split(postlist.Posts[postlist.Order[i]].Message, "\n") {
			if post != "" {
				u.MsgUser(toUser, post)
			}
		}
		if len(postlist.Posts[postlist.Order[i]].FileIds) > 0 {
			for _, fname := range u.mc.GetFileLinks(postlist.Posts[postlist.Order[i]].FileIds) {
				u.MsgUser(toUser, "download file - "+fname)
			}
		}
		u.MsgUser(toUser, "")
		u.MsgUser(toUser, "")
	}
}

func searchUsers(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	users, resp := u.mc.Client.SearchUsers(&model.UserSearch{Term: strings.Join(args, " ")})
	if resp.Error != nil {
		u.MsgUser(toUser, fmt.Sprint("Error", resp.Error))
		return
	}
	for _, user := range users {
		u.MsgUser(toUser, fmt.Sprint(user.Nickname, user.FirstName, user.LastName))
	}
}

func scrollback(u *User, toUser *User, args []string, service string) {
	if service == "slack" {
		u.MsgUser(toUser, "not implemented")
	}
	if len(args) != 2 {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	limit, err := strconv.Atoi(args[1])
	if err != nil {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	if !strings.Contains(args[0], "#") {
		u.MsgUser(toUser, "need SCROLLBACK <channel> <lines>")
		u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)")
		return
	}
	args[0] = strings.Replace(args[0], "#", "", -1)
	postlist := u.mc.GetPosts(u.mc.GetChannelId(args[0], u.mc.Team.Id), limit)
	if postlist == nil || len(postlist.Order) == 0 {
		u.MsgUser(toUser, "no results")
		return
	}
	for i := len(postlist.Order) - 1; i >= 0; i-- {
		nick := u.mc.GetUser(postlist.Posts[postlist.Order[i]].UserId).Username
		for _, post := range strings.Split(postlist.Posts[postlist.Order[i]].Message, "\n") {
			if post != "" {
				u.MsgUser(toUser, "<"+nick+"> "+post)
			}
		}
		if len(postlist.Posts[postlist.Order[i]].FileIds) > 0 {
			for _, fname := range u.mc.GetFileLinks(postlist.Posts[postlist.Order[i]].FileIds) {
				u.MsgUser(toUser, "<"+nick+"> download file - "+fname)
			}
		}
	}

}

var cmds = map[string]Command{
	"logout":      {handler: logout, login: true, minParams: 0, maxParams: 0},
	"login":       {handler: login, minParams: 2, maxParams: 4},
	"search":      {handler: search, login: true, minParams: 1, maxParams: -1},
	"searchusers": {handler: searchUsers, login: true, minParams: 1, maxParams: -1},
	"scrollback":  {handler: scrollback, login: true, minParams: 2, maxParams: 2},
}

func (u *User) handleServiceBot(service string, toUser *User, msg string) {

	//func (u *User) handleMMServiceBot(toUser *User, msg string) {
	commands, err := parseCommandString(msg)
	if err != nil {
		u.MsgUser(toUser, fmt.Sprintf("\"%s\" is improperly formatted", msg))
		return
	}
	cmd, ok := cmds[strings.ToLower(commands[0])]
	if !ok {
		keys := make([]string, 0)
		for k := range cmds {
			keys = append(keys, k)
		}
		u.MsgUser(toUser, "possible commands: "+strings.Join(keys, ", "))
		u.MsgUser(toUser, "<command> help for more info")
		return
	}
	if cmd.login {
		switch service {
		case "mattermost":
			if u.mc == nil {
				u.MsgUser(toUser, "You're not logged in. Use LOGIN first.")
				return
			}
		case "slack":
			if u.sc == nil {
				u.MsgUser(toUser, "You're not logged in. Use LOGIN first.")
				return
			}
		}
	}
	/*
		if cmd.minParams > len(commands[1:]) {
			u.MsgUser(toUser, fmt.Sprintf("%s requires at least %v arguments", commands[0], cmd.minParams))
			return
		}
	*/
	if cmd.maxParams > -1 && len(commands[1:]) > cmd.maxParams {
		u.MsgUser(toUser, fmt.Sprintf("%s takes at most %v arguments", commands[0], cmd.maxParams))
		return
	}
	cmd.handler(u, toUser, commands[1:], service)
}

func parseCommandString(line string) ([]string, error) {
	args := []string{}
	buf := ""
	var escaped, doubleQuoted, singleQuoted bool

	got := false

	for _, r := range line {

		// If the string is escaped
		if escaped {
			buf += string(r)
			escaped = false
			continue
		}

		// If "\"
		if r == '\\' {
			if singleQuoted {
				buf += string(r)
			} else {
				escaped = true
			}
			continue
		}

		// If it is whitespace
		if unicode.IsSpace(r) {
			if singleQuoted || doubleQuoted {
				buf += string(r)
			} else if got {
				args = append(args, buf)
				buf = ""
				got = false
			}
			continue
		}
		// If Quoted
		switch r {
		case '"':
			if !singleQuoted {
				doubleQuoted = !doubleQuoted
				continue
			}
		case '\'':
			if !doubleQuoted {
				singleQuoted = !singleQuoted
				continue
			}
		}
		got = true
		buf += string(r)
	}

	if got {
		args = append(args, buf)
	}
	if escaped || singleQuoted || doubleQuoted {
		return nil, errors.New("invalid command line string")
	}

	return args, nil
}
<|endoftext|>


<commit_before>package output

import (
	"fmt"
	"github.com/freeformz/shh/config"
	"github.com/freeformz/shh/mm"
	"github.com/freeformz/shh/utils"
	"net"
)

type Statsd struct {
	measurements <-chan *mm.Measurement
}

func NewStatsdOutputter(measurements <-chan *mm.Measurement) Statsd {
	return Statsd{measurements}
}

func (out Statsd) Start() {
	go out.Output()
}

func (out Statsd) Connect(host string) net.Conn {
	ctx := utils.Slog{"fn": "Connect", "outputter": "statsd"}

	conn, err := net.Dial(config.StatsdProto, host)
	if err != nil {
		ctx.FatalError(err, "Connecting to statsd host")
	}

	return conn
}

func (s Statsd) Encode(measurement *mm.Measurement) string {
	switch measurement.Value.(type) {
	case uint64:
		return fmt.Sprintf("%s:%s|c", measurement.Measured(), measurement.SValue())
	case float64:
		return fmt.Sprintf("%s:%s|g", measurement.Measured(), measurement.SValue())
	}
	return ""
}

func (out Statsd) Output() {

	conn := out.Connect(config.StatsdHost)

	for measurement := range out.measurements {
		fmt.Fprintf(conn, out.Encode(measurement))
	}
}
<commit_msg>Fix statsd outputter for counters to send count diff instead of actual val<commit_after>package output

import (
	"fmt"
	"github.com/freeformz/shh/config"
	"github.com/freeformz/shh/mm"
	"github.com/freeformz/shh/utils"
	"net"
	"strconv"
)

type Statsd struct {
	measurements <-chan *mm.Measurement
	last map[string]*mm.Measurement
}

func NewStatsdOutputter(measurements <-chan *mm.Measurement) Statsd {
	return Statsd{measurements, make(map[string]*mm.Measurement)}
}

func (out Statsd) Start() {
	go out.Output()
}

func (out Statsd) Connect(host string) net.Conn {
	ctx := utils.Slog{"fn": "Connect", "outputter": "statsd"}

	conn, err := net.Dial(config.StatsdProto, host)
	if err != nil {
		ctx.FatalError(err, "Connecting to statsd host")
	}

	return conn
}

func (s Statsd) Encode(measurement *mm.Measurement) string {
	switch measurement.Value.(type) {
	case uint64:
		key := measurement.Measured()
		last, ok := s.last[key]
		s.last[key] = measurement
		if ok {
			return fmt.Sprintf("%s:%s|c", key, strconv.FormatUint(measurement.Difference(last),10))
		} else {
			return fmt.Sprintf("%s:0|c", key)
		}
	case float64:
		return fmt.Sprintf("%s:%s|g", measurement.Measured(), measurement.SValue())
	}
	return ""
}

func (out Statsd) Output() {

	conn := out.Connect(config.StatsdHost)

	for measurement := range out.measurements {
		fmt.Fprintf(conn, out.Encode(measurement))
	}
}
<|endoftext|>


<commit_before>package rabbus

import (
	"strconv"
	"sync"
	"testing"
	"time"
)

const (
	RABBUS_DSN = "amqp://localhost:5672"
)

var (
	timeout = time.After(3 * time.Second)
)

func TestRabbus(t *testing.T) {
	t.Parallel()

	tests := []struct {
		scenario string
		function func(*testing.T)
	}{
		{
			scenario: "rabbus listen",
			function: testRabbusListen,
		},
		{
			scenario: "rabbus listen validate",
			function: testRabbusListenValidate,
		},
		{
			scenario: "rabbus close",
			function: testRabbusClose,
		},
	}

	for _, test := range tests {
		t.Run(test.scenario, func(t *testing.T) {
			test.function(t)
		})
	}
}

func BenchmarkRabbus(b *testing.B) {
	tests := []struct {
		scenario string
		function func(*testing.B)
	}{
		{
			scenario: "rabbus emit async benchmark",
			function: benchmarkEmitAsync,
		},
	}

	for _, test := range tests {
		b.Run(test.scenario, func(b *testing.B) {
			test.function(b)
		})
	}
}

func testRabbusListen(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn:     RABBUS_DSN,
		Durable: true,
		Retry: Retry{
			Attempts: 1,
		},
		Breaker: Breaker{
			Timeout: time.Second * 2,
		},
	})
	if err != nil {
		t.Errorf("Expected to init rabbus %s", err)
	}

	defer func(r Rabbus) {
		if err = r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	messages, err := r.Listen(ListenConfig{
		Exchange: "test_ex",
		Kind:     "direct",
		Key:      "test_key",
		Queue:    "test_q",
	})
	if err != nil {
		t.Errorf("Expected to listen message %s", err)
	}

	var wg sync.WaitGroup
	wg.Add(1)

	go func(messages chan ConsumerMessage) {
		for m := range messages {
			m.Ack(false)
			close(messages)
			wg.Done()
		}
	}(messages)

	msg := Message{
		Exchange:     "test_ex",
		Kind:         "direct",
		Key:          "test_key",
		Payload:      []byte(`foo`),
		DeliveryMode: Persistent,
	}

	r.EmitAsync() <- msg

outer:
	for {
		select {
		case <-r.EmitOk():
			wg.Wait()
			break outer
		case <-r.EmitErr():
			t.Errorf("Expected to emit message")
			break outer
		case <-timeout:
			t.Errorf("parallel.Run() failed, got timeout error")
			break outer
		}
	}
}

func testRabbusListenValidate(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn: RABBUS_DSN,
		Retry: Retry{
			Attempts: 1,
		},
		Breaker: Breaker{
			Timeout: time.Second * 2,
		},
	})
	if err != nil {
		t.Errorf("Expected to init rabbus %s", err)
	}

	defer func(r Rabbus) {
		if err = r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	configs := []struct {
		config ListenConfig
		errMsg string
	}{
		{
			config: ListenConfig{},
			errMsg: "Expected to validate Exchange",
		},
		{
			config: ListenConfig{Exchange: "foo"},
			errMsg: "Expected to validate Kind",
		},
		{
			config: ListenConfig{Exchange: "foo", Kind: "direct"},
			errMsg: "Expected to validate Queue",
		},
	}

	for _, c := range configs {
		_, err := r.Listen(c.config)
		if err == nil {
			t.Errorf(c.errMsg)
		}
	}
}

func testRabbusClose(t *testing.T) {
	r, err := NewRabbus(Config{
		Dsn: RABBUS_DSN,
		Retry: Retry{
			Attempts: 1,
		},
		Breaker: Breaker{
			Timeout: time.Second * 2,
		},
	})
	if err != nil {
		t.Errorf("Expected to init rabbus %s", err)
	}

	if err = r.Close(); err != nil {
		t.Errorf("Expected to close rabbus %s", err)
	}
}

func benchmarkEmitAsync(b *testing.B) {
	r, err := NewRabbus(Config{
		Dsn:     RABBUS_DSN,
		Durable: false,
		Retry: Retry{
			Attempts: 1,
		},
		Breaker: Breaker{
			Timeout: time.Second * 2,
		},
	})
	if err != nil {
		b.Errorf("Expected to init rabbus %s", err)
	}

	defer func(r Rabbus) {
		if err := r.Close(); err != nil {
			b.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	var wg sync.WaitGroup
	wg.Add(b.N)

	go func(r Rabbus) {
		for {
			select {
			case _, ok := <-r.EmitOk():
				if ok {
					wg.Done()
				}
			case _, ok := <-r.EmitErr():
				if ok {
					b.Fatalf("Expected to emit message, receive error: %v", err)
				}
			}
		}
	}(r)

	for n := 0; n < b.N; n++ {
		msg := Message{
			Exchange:     "test_bench_ex" + strconv.Itoa(n%10),
			Kind:         "direct",
			Key:          "test_key",
			Payload:      []byte(`foo`),
			DeliveryMode: Persistent,
		}

		r.EmitAsync() <- msg
	}

	wg.Wait()
}
<commit_msg>Add happy path unit tests<commit_after>package rabbus

import (
	"testing"
	"time"

	"github.com/streadway/amqp"
)

const (
	RABBUS_DSN = "amqp://localhost:5672"
)

var (
	timeout = time.After(3 * time.Second)
)

func TestRabbus(t *testing.T) {
	t.Parallel()

	tests := []struct {
		scenario string
		function func(*testing.T)
	}{
		{
			scenario: "validate new rabbus constructor args size",
			function: testValidateNewRabbusConstructorArgsSize,
		},
		{
			scenario: "create new rabbus specifying amqp provider",
			function: testCreateNewRabbusSpecifyingAmqpProvider,
		},
		{
			scenario: "validate rabbus listener",
			function: testValidateRabbusListener,
		},
		{
			scenario: "create new rabbus listener",
			function: testCreateNewRabbusListener,
		},
		{
			scenario: "emit async message",
			function: testEmitAsyncMessage,
		},
	}

	for _, test := range tests {
		t.Run(test.scenario, func(t *testing.T) {
			test.function(t)
		})
	}
}

func testValidateNewRabbusConstructorArgsSize(t *testing.T) {
	amqpWrapper := newAmqpMock()
	r, err := NewRabbus(Config{}, amqpWrapper, amqpWrapper)
	if r != nil {
		t.Error("Expected to not create new rabbus")
	}

	if err != ErrUnsupportedArguments {
		t.Errorf("Expected to have ErrUnsupportedArguments, got %s", err)
	}
}

func testCreateNewRabbusSpecifyingAmqpProvider(t *testing.T) {
	amqpWrapper := newAmqpMock()
	config := Config{
		Qos: Qos{
			PrefetchCount: 1,
			PrefetchSize:  10,
			Global:        true,
		},
	}
	r, err := NewRabbus(config, amqpWrapper)
	if err != nil {
		t.Errorf("Expected to create new rabbus, got %s", err)
	}

	defer func(r Rabbus) {
		if err := r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	qosPrefetchCount, ok := amqpWrapper.withQosCaller["count"]
	if !ok {
		t.Error("Expected to have called withQos prefetch count")
	}

	if qosPrefetchCount != config.Qos.PrefetchCount {
		t.Errorf("Expected to have called withQos prefetch count with %v, got %v", config.Qos.PrefetchCount, qosPrefetchCount)
	}

	qosPrefetchSize, ok := amqpWrapper.withQosCaller["size"]
	if !ok {
		t.Error("Expected to have called withQos prefetch size")
	}

	if qosPrefetchSize != config.Qos.PrefetchSize {
		t.Errorf("Expected to have called withQos prefetch size with %v, got %v", config.Qos.PrefetchSize, qosPrefetchSize)
	}

	qosGlobal, ok := amqpWrapper.withQosCaller["global"]
	if !ok {
		t.Error("Expected to have called withQos prefetch size")
	}

	if qosGlobal != config.Qos.Global {
		t.Errorf("Expected to have called withQos global with %v, got %v", config.Qos.Global, qosGlobal)
	}
}

func testValidateRabbusListener(t *testing.T) {
	amqpWrapper := newAmqpMock()
	r, err := NewRabbus(Config{}, amqpWrapper)
	if err != nil {
		t.Error("Expected to not create new rabbus")
	}

	defer func(r Rabbus) {
		if err := r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	configs := []struct {
		config ListenConfig
		errMsg string
	}{
		{
			config: ListenConfig{},
			errMsg: "Expected to validate exchange",
		},
		{
			config: ListenConfig{Exchange: "ex"},
			errMsg: "Expected to validate kind",
		},
		{
			config: ListenConfig{Exchange: "ex", Kind: "topic"},
			errMsg: "Expected to validate queue",
		},
	}

	for _, c := range configs {
		_, err := r.Listen(c.config)
		if err == nil {
			t.Errorf(c.errMsg)
		}
	}
}

func testCreateNewRabbusListener(t *testing.T) {
	amqpWrapper := newAmqpMock()
	c := Config{Durable: true}
	r, err := NewRabbus(c, amqpWrapper)
	if err != nil {
		t.Error("Expected to not create new rabbus")
	}

	defer func(r Rabbus) {
		if err := r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	config := ListenConfig{
		Exchange: "exchange",
		Kind:     "direct",
		Key:      "key",
		Queue:    "queue",
	}

	if _, err = r.Listen(config); err != nil {
		t.Errorf("Expected to create listener, got %s", err)
	}

	exchange, ok := amqpWrapper.createConsumerCaller["exchange"]
	if !ok {
		t.Error("Expected to have called createConsumer with exchange value")
	}

	if exchange != config.Exchange {
		t.Errorf("Expected to have called createConsumer exchange with %v, got %v", config.Exchange, exchange)
	}

	kind, ok := amqpWrapper.createConsumerCaller["kind"]
	if !ok {
		t.Error("Expected to have called createConsumer with kind value")
	}

	if kind != config.Kind {
		t.Errorf("Expected to have called createConsumer kind with %v, got %v", config.Kind, kind)
	}

	queue, ok := amqpWrapper.createConsumerCaller["queue"]
	if !ok {
		t.Error("Expected to have called createConsumer with queue value")
	}

	if queue != config.Queue {
		t.Errorf("Expected to have called createConsumer queue with %v, got %v", config.Queue, queue)
	}

	durable, ok := amqpWrapper.createConsumerCaller["durable"]
	if !ok {
		t.Error("Expected to have called createConsumer with durable value")
	}

	if durable != c.Durable {
		t.Errorf("Expected to have called createConsumer durable with %v, got %v", c.Durable, durable)
	}
}

func testEmitAsyncMessage(t *testing.T) {
	amqpWrapper := newAmqpMock()
	c := Config{Durable: true}
	r, err := NewRabbus(c, amqpWrapper)
	if err != nil {
		t.Error("Expected to not create new rabbus")
	}

	defer func(r Rabbus) {
		if err := r.Close(); err != nil {
			t.Errorf("Expected to close rabbus %s", err)
		}
	}(r)

	msg := Message{
		Exchange: "exchange",
		Kind:     "direct",
		Key:      "key",
		Payload:  []byte(`foo`),
	}

	r.EmitAsync() <- msg

outer:
	for {
		select {
		case <-r.EmitOk():
			exchange, ok := amqpWrapper.withExchangeCaller["exchange"]
			if !ok {
				t.Error("Expected to have called withExchange with exchange value")
			}

			if exchange != msg.Exchange {
				t.Errorf("Expected to have called withExchange exchange with %v, got %v", msg.Exchange, exchange)
			}

			kind, ok := amqpWrapper.withExchangeCaller["kind"]
			if !ok {
				t.Error("Expected to have called withExchange with kind value")
			}

			if kind != msg.Kind {
				t.Errorf("Expected to have called withExchange kind with %v, got %v", msg.Kind, kind)
			}

			durable, ok := amqpWrapper.withExchangeCaller["durable"]
			if !ok {
				t.Error("Expected to have called withExchange with durable value")
			}

			if durable != c.Durable {
				t.Errorf("Expected to have called withExchange durable with %v, got %v", c.Durable, durable)
			}

			exchange, ok = amqpWrapper.publishCaller["exchange"]
			if !ok {
				t.Error("Expected to have called publish with exchange value")
			}

			key, ok := amqpWrapper.publishCaller["key"]
			if !ok {
				t.Error("Expected to have called publish with key value")
			}

			if key != msg.Key {
				t.Errorf("Expected to have called publish key with %v, got %v", msg.Key, key)
			}

			opts, ok := amqpWrapper.publishCaller["opts"]
			if !ok {
				t.Error("Expected to have called publish with opts value")
			}

			o := opts.(amqp.Publishing)
			payload := string(o.Body)
			expectedPayload := string(msg.Payload)
			if payload != expectedPayload {
				t.Errorf("Expected to have called publish payload with %v, got %v", expectedPayload, payload)
			}

			break outer
		case <-r.EmitErr():
			t.Errorf("Expected to emit message")
			break outer
		case <-timeout:
			t.Errorf("Got timeout error during emit async")
			break outer
		}
	}
}

type amqpMock struct {
	publishCaller        map[string]interface{}
	createConsumerCaller map[string]interface{}
	withExchangeCaller   map[string]interface{}
	withQosCaller        map[string]interface{}
}

func newAmqpMock() *amqpMock {
	return &amqpMock{
		publishCaller:        make(map[string]interface{}),
		createConsumerCaller: make(map[string]interface{}),
		withExchangeCaller:   make(map[string]interface{}),
		withQosCaller:        make(map[string]interface{}),
	}
}

func (m *amqpMock) Publish(exchange, key string, opts amqp.Publishing) error {
	m.publishCaller["exchange"] = exchange
	m.publishCaller["key"] = key
	m.publishCaller["opts"] = opts
	return nil
}

func (m *amqpMock) CreateConsumer(exchange, key, kind, queue string, durable bool) (<-chan amqp.Delivery, error) {
	m.createConsumerCaller["exchange"] = exchange
	m.createConsumerCaller["key"] = key
	m.createConsumerCaller["kind"] = kind
	m.createConsumerCaller["queue"] = queue
	m.createConsumerCaller["durable"] = durable
	return make(<-chan amqp.Delivery), nil
}

func (m *amqpMock) WithExchange(exchange, kind string, durable bool) error {
	m.withExchangeCaller["exchange"] = exchange
	m.withExchangeCaller["kind"] = kind
	m.withExchangeCaller["durable"] = durable
	return nil
}

func (m *amqpMock) WithQos(count, size int, global bool) error {
	m.withQosCaller["count"] = count
	m.withQosCaller["size"] = size
	m.withQosCaller["global"] = global
	return nil
}

func (m *amqpMock) NotifyClose(c chan *amqp.Error) chan *amqp.Error { return nil }
func (m *amqpMock) Close() error                                    { return nil }
<|endoftext|>


<commit_before>package margelet_test

import (
	"github.com/zhulik/margelet"
	"gopkg.in/telegram-bot-api.v2"
)

type BotMock struct {
	Updates chan tgbotapi.Update
}

func (bot BotMock) Send(c tgbotapi.Chattable) (tgbotapi.Message, error) {
	return tgbotapi.Message{}, nil
}

func (bot BotMock) GetFileDirectURL(fileID string) (string, error) {
	return "https://example.com/test.txt", nil
}

func (bot BotMock) IsMessageToMe(message tgbotapi.Message) bool {
	return false
}

func (bot BotMock) GetUpdatesChan(config tgbotapi.UpdateConfig) (<-chan tgbotapi.Update, error) {
	return bot.Updates, nil
}

var (
	botMock = BotMock{}
)

func getMargelet() *margelet.Margelet {
	botMock.Updates = make(chan tgbotapi.Update, 10)
	m, _ := margelet.NewMargeletFromBot("test", "127.0.0.1:6379", "", 10, &botMock)

	m.Redis.FlushDb()
	return m
}

func ExampleMargelet() {
	bot, err := margelet.NewMargelet("<your awesome bot name>", "<redis addr>", "<redis password>", 0, "your bot token", false)

	if err != nil {
		panic(err)
	}

	bot.Run()
}
<commit_msg>tests fixed<commit_after>package margelet_test

import (
	"github.com/zhulik/margelet"
	"gopkg.in/telegram-bot-api.v2"
)

type BotMock struct {
	Updates chan tgbotapi.Update
}

func (bot BotMock) Send(c tgbotapi.Chattable) (tgbotapi.Message, error) {
	return tgbotapi.Message{}, nil
}

func (bot BotMock) AnswerInlineQuery(config tgbotapi.InlineConfig) (tgbotapi.APIResponse, error) {
	return tgbotapi.APIResponse{}, nil
}

func (bot BotMock) GetFileDirectURL(fileID string) (string, error) {
	return "https://example.com/test.txt", nil
}

func (bot BotMock) IsMessageToMe(message tgbotapi.Message) bool {
	return false
}

func (bot BotMock) GetUpdatesChan(config tgbotapi.UpdateConfig) (<-chan tgbotapi.Update, error) {
	return bot.Updates, nil
}

var (
	botMock = BotMock{}
)

func getMargelet() *margelet.Margelet {
	botMock.Updates = make(chan tgbotapi.Update, 10)
	m, _ := margelet.NewMargeletFromBot("test", "127.0.0.1:6379", "", 10, &botMock)

	m.Redis.FlushDb()
	return m
}

func ExampleMargelet() {
	bot, err := margelet.NewMargelet("<your awesome bot name>", "<redis addr>", "<redis password>", 0, "your bot token", false)

	if err != nil {
		panic(err)
	}

	bot.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"flag"
	"os"
	"reflect"

	"github.com/ivanilves/lstags/auth"
	"github.com/ivanilves/lstags/tag/registry"
)

var runIntegrationTests = flag.Bool("integration", false, "run integration tests")

const dockerHub = "registry.hub.docker.com"

var registryTags = map[string]string{
	"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	"v1.2":   "sha256:9b618bebfbce63619fcd6c9e00967ffa3bf075d8d331be931012e1ba3472d4d1",
	"latest": "sha256:33fa8a96ed94cd7580c812891e7771be3a0ad510828ea76351162e5781456da2",
}

var localTags = map[string]string{
	"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	"v1.2.1": "sha256:3c7f921d1301bc662e18643190f9404679ee28326f2b6d68d3c721466fc3c6c2",
	"latest": "sha256:d23eba72cd72037b1106b73c6e7c11a101bc7ba09cb25f9ee7157b792c528f09",
}

func TestShortify(t *testing.T) {
	const cutToLength = 10

	shortString := "so short!"
	longString := "size does matter after all!"

	var resultString string

	resultString = shortify(shortString, cutToLength)
	if resultString != shortString {
		t.Fatalf(
			"String with length <= %d should not be modified (We got: %s => %s)",
			cutToLength,
			shortString,
			resultString,
		)
	}

	resultString = shortify(longString, cutToLength)
	if len(resultString) != cutToLength {
		t.Fatalf(
			"String with length > %d should be cut exactly to this length (We got: %s => %s, length: %d)",
			cutToLength,
			longString,
			resultString,
			len(resultString),
		)
	}
	if resultString != longString[0:cutToLength] {
		t.Fatalf(
			"Should return first %d characters of the passed string (We got: %s => %s)",
			cutToLength,
			longString,
			resultString,
		)
	}
}

func TestConcatTagNames(t *testing.T) {
	tagNames := concatTagNames(registryTags, localTags)

	expectedTagNames := []string{"latest", "v1.1", "v1.2", "v1.2.1"}

	if !reflect.DeepEqual(tagNames, expectedTagNames) {
		t.Fatalf(
			"Should merge and sort registry and local tag names (Expected: %v / Got: %v)\nregistry: %v\nlocal: %v",
			expectedTagNames,
			tagNames,
			registryTags,
			localTags,
		)
	}
}

func TestGetShortImageID(t *testing.T) {
	const imageID = "sha256:57848d7a78d09ac3991b067a6e10ad89f40fbb09c4bdf6e1029fc5141dd3f07e"
	const expectedShortImageID = "57848d7a78d0"

	shortImageID := getShortImageID(imageID)

	if shortImageID != expectedShortImageID {
		t.Fatalf(
			"Should return first %d characters of the image ID (Expected: %s / Got: %s)",
			len(expectedShortImageID),
			expectedShortImageID,
			shortImageID,
		)
	}
}

func TestFormatImageIDs(t *testing.T) {
	localImageIDs := map[string]string{
		"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
		"latest": "sha256:33fa8a96ed94cd7580c812891e7771be3a0ad510828ea76351162e5781456da2",
	}

	tagNames := []string{"v1.0", "v1.1", "v1.2", "latest"}

	expectedImageIDs := map[string]string{
		"v1.0":   "n/a",
		"v1.1":   "7abd16433f3b",
		"v1.2":   "n/a",
		"latest": "33fa8a96ed94",
	}

	imageIDs := formatImageIDs(localImageIDs, tagNames)

	if !reflect.DeepEqual(imageIDs, expectedImageIDs) {
		t.Fatalf(
			"Should format image IDs for givent tags correctly:\n* Expected: %#v\n* Got: %#v",
			expectedImageIDs,
			imageIDs,
		)
	}
}

func TestGetDigest(t *testing.T) {
	expectedDigests := map[string]string{
		"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
		"v1.2":   "sha256:9b618bebfbce63619fcd6c9e00967ffa3bf075d8d331be931012e1ba3472d4d1",
		"v1.2.1": "sha256:3c7f921d1301bc662e18643190f9404679ee28326f2b6d68d3c721466fc3c6c2",
		"latest": "sha256:33fa8a96ed94cd7580c812891e7771be3a0ad510828ea76351162e5781456da2",
	}

	for tag, expectedDigest := range expectedDigests {
		digest := getDigest(tag, registryTags, localTags)

		if digest != expectedDigest {
			t.Fatalf(
				"Should get correct image digest for tag %s:\n* Expected: %s\n* Got: %s",
				tag,
				expectedDigest,
				digest,
			)
		}
	}
}

func TestGetState(t *testing.T) {
	expectedStates := map[string]string{
		"v1.1":   "PRESENT",
		"v1.2":   "ABSENT",
		"v1.2.1": "LOCAL-ONLY",
		"latest": "CHANGED",
	}

	for tag, expectedState := range expectedStates {
		state := getState(tag, registryTags, localTags)

		if state != expectedState {
			t.Fatalf(
				"Should get correct image state for tag %s:\n* Expected: %s\n* Got: %s",
				tag,
				expectedState,
				state,
			)
		}
	}
}

func TestGetRepoRegistryName(t *testing.T) {
	const registry = "registry.nerd.io"

	expectations := map[string]string{
		"nginx": "library/nginx",
		"registry.nerd.io/hype/cube": "hype/cube",
		"observability/metrix":       "observability/metrix",
	}

	for input, expected := range expectations {
		output := getRepoRegistryName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected registry repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestGetRepoLocalNameForPublicRegistry(t *testing.T) {
	const registry = "registry.hub.docker.com"

	expectations := map[string]string{
		"library/nginx": "nginx",
		"hype/cube":     "hype/cube",
	}

	for input, expected := range expectations {
		output := getRepoLocalName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected local repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestGetRepoLocalNameForPrivateRegistry(t *testing.T) {
	const registry = "registry.nerd.io"

	expectations := map[string]string{
		"empollon/nginx":             "registry.nerd.io/empollon/nginx",
		"registry.nerd.io/hype/cube": "registry.nerd.io/hype/cube",
	}

	for input, expected := range expectations {
		output := getRepoLocalName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected registry repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestDockerHubWithPublicRepo(t *testing.T) {
	flag.Parse()
	if !*runIntegrationTests {
		t.SkipNow()
	}

	const repo = "library/alpine"

	tresp, err := auth.NewToken(dockerHub, repo, "", "")
	if err != nil {
		t.Fatalf("Failed to get DockerHub public repo token: %s", err.Error())
	}

	authorization := getAuthorization(tresp)

	tags, err := registry.FetchTags(dockerHub, repo, authorization, 128)
	if err != nil {
		t.Fatalf("Failed to list DockerHub public repo (%s) tags: %s", repo, err.Error())
	}

	_, defined := tags["latest"]
	if !defined {
		t.Fatalf("DockerHub public repo (%s) tag 'latest' not found: %#v", repo, tags)
	}
}

func TestDockerHubWithPrivateRepo(t *testing.T) {
	flag.Parse()
	if !*runIntegrationTests {
		t.SkipNow()
	}

	if os.Getenv("DOCKERHUB_USERNAME") == "" {
		t.Skipf("DOCKERHUB_USERNAME environment variable not set!")
	}
	if os.Getenv("DOCKERHUB_PASSWORD") == "" {
		t.Skipf("DOCKERHUB_PASSWORD environment variable not set!")
	}
	if os.Getenv("DOCKERHUB_PRIVATE_REPO") == "" {
		t.Skipf("DOCKERHUB_PRIVATE_REPO environment variable not set!")
	}

	user := os.Getenv("DOCKERHUB_USERNAME")
	pass := os.Getenv("DOCKERHUB_PASSWORD")
	repo := os.Getenv("DOCKERHUB_PRIVATE_REPO")

	tresp, err := auth.NewToken(dockerHub, repo, user, pass)
	if err != nil {
		t.Fatalf("Failed to get DockerHub private repo token: %s", err.Error())
	}

	authorization := getAuthorization(tresp)

	tags, err := registry.FetchTags(dockerHub, repo, authorization, 128)
	if err != nil {
		t.Fatalf("Failed to list DockerHub private repo (%s) tags: %s", repo, err.Error())
	}

	_, defined := tags["latest"]
	if !defined {
		t.Fatalf("DockerHub private repo (%s) tag 'latest' not found: %#v", repo, tags)
	}
}
<commit_msg>:warning: Removed obsolete tests :warning:<commit_after>package main

import (
	"testing"

	"flag"
	"os"

	"github.com/ivanilves/lstags/auth"
	"github.com/ivanilves/lstags/tag/registry"
)

var runIntegrationTests = flag.Bool("integration", false, "run integration tests")

const dockerHub = "registry.hub.docker.com"

var registryTags = map[string]string{
	"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	"v1.2":   "sha256:9b618bebfbce63619fcd6c9e00967ffa3bf075d8d331be931012e1ba3472d4d1",
	"latest": "sha256:33fa8a96ed94cd7580c812891e7771be3a0ad510828ea76351162e5781456da2",
}

var localTags = map[string]string{
	"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	"v1.2.1": "sha256:3c7f921d1301bc662e18643190f9404679ee28326f2b6d68d3c721466fc3c6c2",
	"latest": "sha256:d23eba72cd72037b1106b73c6e7c11a101bc7ba09cb25f9ee7157b792c528f09",
}

func TestShortify(t *testing.T) {
	const cutToLength = 10

	shortString := "so short!"
	longString := "size does matter after all!"

	var resultString string

	resultString = shortify(shortString, cutToLength)
	if resultString != shortString {
		t.Fatalf(
			"String with length <= %d should not be modified (We got: %s => %s)",
			cutToLength,
			shortString,
			resultString,
		)
	}

	resultString = shortify(longString, cutToLength)
	if len(resultString) != cutToLength {
		t.Fatalf(
			"String with length > %d should be cut exactly to this length (We got: %s => %s, length: %d)",
			cutToLength,
			longString,
			resultString,
			len(resultString),
		)
	}
	if resultString != longString[0:cutToLength] {
		t.Fatalf(
			"Should return first %d characters of the passed string (We got: %s => %s)",
			cutToLength,
			longString,
			resultString,
		)
	}
}

func TestGetRepoRegistryName(t *testing.T) {
	const registry = "registry.nerd.io"

	expectations := map[string]string{
		"nginx": "library/nginx",
		"registry.nerd.io/hype/cube": "hype/cube",
		"observability/metrix":       "observability/metrix",
	}

	for input, expected := range expectations {
		output := getRepoRegistryName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected registry repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestGetRepoLocalNameForPublicRegistry(t *testing.T) {
	const registry = "registry.hub.docker.com"

	expectations := map[string]string{
		"library/nginx": "nginx",
		"hype/cube":     "hype/cube",
	}

	for input, expected := range expectations {
		output := getRepoLocalName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected local repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestGetRepoLocalNameForPrivateRegistry(t *testing.T) {
	const registry = "registry.nerd.io"

	expectations := map[string]string{
		"empollon/nginx":             "registry.nerd.io/empollon/nginx",
		"registry.nerd.io/hype/cube": "registry.nerd.io/hype/cube",
	}

	for input, expected := range expectations {
		output := getRepoLocalName(input, registry)

		if output != expected {
			t.Fatalf(
				"Got unexpected registry repo name: %s => %s\n* Expected: %s",
				input,
				output,
				expected,
			)
		}
	}
}

func TestDockerHubWithPublicRepo(t *testing.T) {
	flag.Parse()
	if !*runIntegrationTests {
		t.SkipNow()
	}

	const repo = "library/alpine"

	tresp, err := auth.NewToken(dockerHub, repo, "", "")
	if err != nil {
		t.Fatalf("Failed to get DockerHub public repo token: %s", err.Error())
	}

	authorization := getAuthorization(tresp)

	tags, err := registry.FetchTags(dockerHub, repo, authorization, 128)
	if err != nil {
		t.Fatalf("Failed to list DockerHub public repo (%s) tags: %s", repo, err.Error())
	}

	_, defined := tags["latest"]
	if !defined {
		t.Fatalf("DockerHub public repo (%s) tag 'latest' not found: %#v", repo, tags)
	}
}

func TestDockerHubWithPrivateRepo(t *testing.T) {
	flag.Parse()
	if !*runIntegrationTests {
		t.SkipNow()
	}

	if os.Getenv("DOCKERHUB_USERNAME") == "" {
		t.Skipf("DOCKERHUB_USERNAME environment variable not set!")
	}
	if os.Getenv("DOCKERHUB_PASSWORD") == "" {
		t.Skipf("DOCKERHUB_PASSWORD environment variable not set!")
	}
	if os.Getenv("DOCKERHUB_PRIVATE_REPO") == "" {
		t.Skipf("DOCKERHUB_PRIVATE_REPO environment variable not set!")
	}

	user := os.Getenv("DOCKERHUB_USERNAME")
	pass := os.Getenv("DOCKERHUB_PASSWORD")
	repo := os.Getenv("DOCKERHUB_PRIVATE_REPO")

	tresp, err := auth.NewToken(dockerHub, repo, user, pass)
	if err != nil {
		t.Fatalf("Failed to get DockerHub private repo token: %s", err.Error())
	}

	authorization := getAuthorization(tresp)

	tags, err := registry.FetchTags(dockerHub, repo, authorization, 128)
	if err != nil {
		t.Fatalf("Failed to list DockerHub private repo (%s) tags: %s", repo, err.Error())
	}

	_, defined := tags["latest"]
	if !defined {
		t.Fatalf("DockerHub private repo (%s) tag 'latest' not found: %#v", repo, tags)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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.
//
// An integration test that uses a real S3 account. Run as follows:
//
//     go run integration_test/*.go \
//         -key_id <key ID> \
//         -bucket <bucket> \
//         -region s3-ap-northeast-1.amazonaws.com
//
// Before doing this, create an empty bucket (or delete the contents of an
// existing bucket) using the S3 management console.

package main

import (
	"bytes"
	"flag"
	"fmt"
	. "github.com/jacobsa/ogletest"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/s3"
	"os"
	"regexp"
	"strings"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

var keyId = flag.String("key_id", "", "Access key ID.")
var bucketName = flag.String("bucket", "", "Bucket name.")
var region = flag.String("region", "", "Region endpoint server.")
var accessKey aws.AccessKey

type integrationTest struct {
}

////////////////////////////////////////////////////////////////////////
// Bucket
////////////////////////////////////////////////////////////////////////

type BucketTest struct {
	integrationTest
	bucket s3.Bucket
}

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

func (t *BucketTest) SetUp(i *TestInfo) {
	var err error

	// Open a bucket.
	t.bucket, err = s3.OpenBucket(*bucketName, s3.Region(*region), accessKey)
	AssertEq(nil, err)
}

func (t *BucketTest) TodoRefactorMe() {
	// Attempt to create an object.
	objectName := "타코&burrito?enchilada"
	data := []byte("taco")
	data = append(data, 0x00)
	data = append(data, []byte("burrito")...)

	if err := t.bucket.StoreObject(objectName, data); err != nil {
		fmt.Println("StoreObject:", err)
		os.Exit(1)
	}

	// TODO(jacobsa): Test ListKeys.

	// Read the object back.
	dataRead, err := t.bucket.GetObject(objectName)
	if err != nil {
		fmt.Println("GetObject:", err)
		os.Exit(1)
	}

	// Make sure the result is identical.
	if !bytes.Equal(data, dataRead) {
		fmt.Printf("Mismatch; %x vs. %x\n", data, dataRead)
		os.Exit(1)
	}

	// Attempt to load a non-existent object. We should get a 404 back.
	_, err = t.bucket.GetObject("other_name")
	if err == nil || strings.Count(err.Error(), "404") != 1 {
		fmt.Println("Unexpected 404 error:", err)
		os.Exit(1)
	}
}

////////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////////

func main() {
	flag.Parse()

	if *keyId == "" {
		fmt.Println("You must set the -key_id flag.")
		fmt.Println("Find a key ID here:")
		fmt.Println("    https://portal.aws.amazon.com/gp/aws/securityCredentials")
		os.Exit(1)
	}

	if *bucketName == "" {
		fmt.Println("You must set the -bucket flag.")
		fmt.Println("Manage your buckets here:")
		fmt.Println("    http://aws.amazon.com/console/")
		os.Exit(1)
	}

	if *region == "" {
		fmt.Println("You must set the -region flag. See region.go.")
		os.Exit(1)
	}

	// Read in the access key.
	accessKey.Id = *keyId
	accessKey.Secret = readPassword("Access key secret: ")

	// Run the tests.
	matchString := func (pat, str string) (bool, error) {
		re, err := regexp.Compile(pat)
		if err != nil {
			return false, err
		}

		return re.MatchString(str), nil
	}

	testing.Main(
		matchString,
		[]testing.InternalTest{
			testing.InternalTest{
				Name: "IntegrationTest",
				F: func (t *testing.T) { RunTests(t) },
			},
		},
		[]testing.InternalBenchmark{},
		[]testing.InternalExample{},
	)
}
<commit_msg>Added test names.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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.
//
// An integration test that uses a real S3 account. Run as follows:
//
//     go run integration_test/*.go \
//         -key_id <key ID> \
//         -bucket <bucket> \
//         -region s3-ap-northeast-1.amazonaws.com
//
// Before doing this, create an empty bucket (or delete the contents of an
// existing bucket) using the S3 management console.

package main

import (
	"bytes"
	"flag"
	"fmt"
	. "github.com/jacobsa/ogletest"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/s3"
	"os"
	"regexp"
	"strings"
	"testing"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

var keyId = flag.String("key_id", "", "Access key ID.")
var bucketName = flag.String("bucket", "", "Bucket name.")
var region = flag.String("region", "", "Region endpoint server.")
var accessKey aws.AccessKey

type integrationTest struct {
}

////////////////////////////////////////////////////////////////////////
// Bucket
////////////////////////////////////////////////////////////////////////

type BucketTest struct {
	integrationTest
	bucket s3.Bucket
}

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

func (t *BucketTest) SetUp(i *TestInfo) {
	var err error

	// Open a bucket.
	t.bucket, err = s3.OpenBucket(*bucketName, s3.Region(*region), accessKey)
	AssertEq(nil, err)
}

func (t *BucketTest) TodoRefactorMe() {
	// Attempt to create an object.
	objectName := "타코&burrito?enchilada"
	data := []byte("taco")
	data = append(data, 0x00)
	data = append(data, []byte("burrito")...)

	if err := t.bucket.StoreObject(objectName, data); err != nil {
		fmt.Println("StoreObject:", err)
		os.Exit(1)
	}

	// TODO(jacobsa): Test ListKeys.

	// Read the object back.
	dataRead, err := t.bucket.GetObject(objectName)
	if err != nil {
		fmt.Println("GetObject:", err)
		os.Exit(1)
	}

	// Make sure the result is identical.
	if !bytes.Equal(data, dataRead) {
		fmt.Printf("Mismatch; %x vs. %x\n", data, dataRead)
		os.Exit(1)
	}

	// Attempt to load a non-existent object. We should get a 404 back.
	_, err = t.bucket.GetObject("other_name")
	if err == nil || strings.Count(err.Error(), "404") != 1 {
		fmt.Println("Unexpected 404 error:", err)
		os.Exit(1)
	}
}

////////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////////

func main() {
	flag.Parse()

	if *keyId == "" {
		fmt.Println("You must set the -key_id flag.")
		fmt.Println("Find a key ID here:")
		fmt.Println("    https://portal.aws.amazon.com/gp/aws/securityCredentials")
		os.Exit(1)
	}

	if *bucketName == "" {
		fmt.Println("You must set the -bucket flag.")
		fmt.Println("Manage your buckets here:")
		fmt.Println("    http://aws.amazon.com/console/")
		os.Exit(1)
	}

	if *region == "" {
		fmt.Println("You must set the -region flag. See region.go.")
		os.Exit(1)
	}

	// Read in the access key.
	accessKey.Id = *keyId
	accessKey.Secret = readPassword("Access key secret: ")

	// Run the tests.
	matchString := func (pat, str string) (bool, error) {
		re, err := regexp.Compile(pat)
		if err != nil {
			return false, err
		}

		return re.MatchString(str), nil
	}

	testing.Main(
		matchString,
		[]testing.InternalTest{
			testing.InternalTest{
				Name: "IntegrationTest",
				F: func (t *testing.T) { RunTests(t) },
			},
		},
		[]testing.InternalBenchmark{},
		[]testing.InternalExample{},
	)
}

func (t *BucketTest) ListEmptyBucket() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListWithEmptyMinimum() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListWithInvalidUtf8Minimum() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListWithLongMinimum() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListWithNullByteInMinimum() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListFewKeys() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) ListManyKeys() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) GetNonExistentObject() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) StoreThenGetObject() {
	ExpectFalse(true, "TODO")
}

func (t *BucketTest) StoreThenDeleteObject() {
	ExpectFalse(true, "TODO")
}
<|endoftext|>


<commit_before>package raster

import (
	"image"
	"image/color"
	"unsafe"
)
// Renders the mask to the canvas
func DrawSolidRGBA(dest *image.RGBA, mask *image.Alpha, rgba color.RGBA) {
	rect := dest.Bounds().Intersect(mask.Bounds())
	minX := uint32(rect.Min.X)
	minY := uint32(rect.Min.Y)
	maxX := uint32(rect.Max.X)
	maxY := uint32(rect.Max.Y)

	pixColor := *(*uint32)(unsafe.Pointer(&rgba))

	cs1 := pixColor & 0xff00ff
	cs2 := pixColor >> 8 & 0xff00ff

	stride1 := uint32(dest.Stride)
	stride2 := uint32(mask.Stride)

	maxY *= stride1
	var pix, pixm []uint8
	var pixelx uint32
	var x, y1, y2 uint32
	for y1, y2 = minY*stride1, minY*stride2; y1 < maxY; y1, y2 = y1+stride1, y2+stride2 {
		pix = dest.Pix[y1:]
		pixm = mask.Pix[y2:]
		pixelx = minX * 4
		for x = minX; x < maxX; x++ {
			alpha := uint32(pixm[x])
			p := (*uint32)(unsafe.Pointer(&pix[pixelx]))
			if alpha == 0xff {
				*p = pixColor
			} else if alpha != 0 {
				invAlpha := 0xff - alpha
				ct1 := *p & 0xff00ff * invAlpha
				ct2 := *p >> 8 & 0xff00ff * invAlpha

				ct1 = (ct1 + cs1*alpha) >> 3 & 0xff00ff
				ct2 = (ct2 + cs2*alpha) << 5 & 0xff00ff00

				*p = ct1 + ct2
			}
			pixelx += 4
		}
	}
}
<commit_msg>resolve bug on blending function<commit_after>package raster

import (
	"image"
	"image/color"
	"unsafe"
)
// Renders the mask to the canvas
func DrawSolidRGBA(dest *image.RGBA, mask *image.Alpha, rgba color.RGBA) {
	rect := dest.Bounds().Intersect(mask.Bounds())
	minX := uint32(rect.Min.X)
	minY := uint32(rect.Min.Y)
	maxX := uint32(rect.Max.X)
	maxY := uint32(rect.Max.Y)

	pixColor := *(*uint32)(unsafe.Pointer(&rgba))

	cs1 := pixColor & 0xff00ff
	cs2 := (pixColor >> 8) & 0xff00ff

	stride1 := uint32(dest.Stride)
	stride2 := uint32(mask.Stride)

	maxY *= stride1
	var pix, pixm []uint8
	var pixelx uint32
	var x, y1, y2 uint32
	for y1, y2 = minY*stride1, minY*stride2; y1 < maxY; y1, y2 = y1+stride1, y2+stride2 {
		pix = dest.Pix[y1:]
		pixm = mask.Pix[y2:]
		pixelx = minX * 4
		for x = minX; x < maxX; x++ {
			alpha := uint32(pixm[x])
			p := (*uint32)(unsafe.Pointer(&pix[pixelx]))
			if alpha != 0 {
				invAlpha := 0xff - alpha
				ct1 := (*p & 0xff00ff) * invAlpha
				ct2 := ((*p >> 8) & 0xff00ff) * invAlpha

				ct1 = ((ct1 + cs1*alpha) >> 8) & 0xff00ff
				ct2 = (ct2 + cs2*alpha) & 0xff00ff00
				*p = ct1 + ct2
			}
			pixelx += 4
		}
	}
}
<|endoftext|>


<commit_before>package bot

import (
	"fmt"

	"github.com/bwmarrin/discordgo"
)

func (cs *CommandSet) help(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	switch len(parv) {
	case 1:

		result := formHelp()

		authorChannel, err := s.UserChannelCreate(m.Author.ID)
		s.ChannelMessageSend(authorChannel.ID, result)

		s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("@%s check direct messages, help is there!", m.Author.Username))

	default:
		return ErrParvCountMismatch
	}

	return nil
}

func formHelp() string {
	result := "Bot commands: \n"

	for verb, cmd := range cs.cmds {
		result += fmt.Sprintf("%s%s: %s\n", cs.Prefix, verb, cmd.Helptext())
	}

	return (result + "If there's any problems please don't hesitate to ask a server admin for help.")
}
<commit_msg>Update help.go<commit_after>package bot

import (
	"fmt"

	"github.com/bwmarrin/discordgo"
)

func (cs *CommandSet) help(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	switch len(parv) {
	case 1:

		result := formHelp()

		authorChannel, err := s.UserChannelCreate(m.Author.ID)
		s.ChannelMessageSend(authorChannel.ID, result)

		s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("@<%s> check direct messages, help is there!", m.Author.ID))

	default:
		return ErrParvCountMismatch
	}

	return nil
}

func formHelp() string {
	result := "Bot commands: \n"

	for verb, cmd := range cs.cmds {
		result += fmt.Sprintf("%s%s: %s\n", cs.Prefix, verb, cmd.Helptext())
	}

	return (result + "If there's any problems please don't hesitate to ask a server admin for help.")
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	//_ "expvar"
	"flag"
	"log"
	"net/http"
	//_ "net/http/pprof"
	"os"
	"strconv"
	"time"

	redigo "github.com/garyburd/redigo/redis"
	"github.com/pierrre/imageserver"
	imageserver_cache "github.com/pierrre/imageserver/cache"
	imageserver_cache_async "github.com/pierrre/imageserver/cache/async"
	imageserver_cache_list "github.com/pierrre/imageserver/cache/list"
	imageserver_cache_memory "github.com/pierrre/imageserver/cache/memory"
	imageserver_cache_redis "github.com/pierrre/imageserver/cache/redis"
	imageserver_http "github.com/pierrre/imageserver/http"
	imageserver_http_parser_graphicsmagick "github.com/pierrre/imageserver/http/parser/graphicsmagick"
	imageserver_http_parser_list "github.com/pierrre/imageserver/http/parser/list"
	imageserver_http_parser_source "github.com/pierrre/imageserver/http/parser/source"
	imageserver_processor "github.com/pierrre/imageserver/processor"
	imageserver_processor_graphicsmagick "github.com/pierrre/imageserver/processor/graphicsmagick"
	imageserver_processor_limit "github.com/pierrre/imageserver/processor/limit"
	imageserver_provider "github.com/pierrre/imageserver/provider"
	imageserver_provider_cache "github.com/pierrre/imageserver/provider/cache"
	imageserver_provider_http "github.com/pierrre/imageserver/provider/http"
)

func main() {
	var verbose bool
	var httpAddr string
	flag.BoolVar(&verbose, "verbose", false, "Verbose")
	flag.StringVar(&httpAddr, "http", ":8080", "Http")
	flag.Parse()

	log.Println("Start")

	hostname, err := os.Hostname()
	if err != nil {
		panic(err)
	}

	var cache imageserver_cache.Cache
	cache = &imageserver_cache_redis.RedisCache{
		Pool: &redigo.Pool{
			Dial: func() (redigo.Conn, error) {
				return redigo.Dial("tcp", "localhost:6379")
			},
			MaxIdle: 50,
		},
		Expire: time.Duration(7 * 24 * time.Hour),
	}
	cache = &imageserver_cache_async.AsyncCache{
		Cache: cache,
		ErrFunc: func(err error, key string, image *imageserver.Image, parameters imageserver.Parameters) {
			if verbose {
				log.Println("Cache error:", err)
			}
		},
	}
	cache = imageserver_cache_list.ListCache{
		imageserver_cache_memory.New(10 * 1024 * 1024),
		cache,
	}

	provider := &imageserver_provider_cache.CacheProvider{
		Provider:     &imageserver_provider_http.HTTPProvider{},
		Cache:        cache,
		KeyGenerator: imageserver_provider_cache.NewSourceHashKeyGenerator(sha256.New),
	}

	var processor imageserver_processor.Processor
	processor = &imageserver_processor_graphicsmagick.GraphicsMagickProcessor{
		Executable: "gm",
		Timeout:    time.Duration(10 * time.Second),
		AllowedFormats: []string{
			"jpeg",
			"png",
			"bmp",
			"gif",
		},
	}
	processor = imageserver_processor_limit.New(processor, 16)

	var imageServer imageserver.ImageServer
	imageServer = &imageserver_provider.ProviderImageServer{
		Provider: provider,
	}
	imageServer = &imageserver_processor.ProcessorImageServer{
		ImageServer: imageServer,
		Processor:   processor,
	}
	imageServer = &imageserver_cache.CacheImageServer{
		ImageServer:  imageServer,
		Cache:        cache,
		KeyGenerator: imageserver_cache.NewParametersHashKeyGenerator(sha256.New),
	}

	imageHTTPHandler := &imageserver_http.ImageHTTPHandler{
		Parser: &imageserver_http_parser_list.ListParser{
			&imageserver_http_parser_source.SourceParser{},
			&imageserver_http_parser_graphicsmagick.GraphicsMagickParser{},
		},
		ImageServer: imageServer,
		ETagFunc:    imageserver_http.NewParametersHashETagFunc(sha256.New),
		Expire:      time.Duration(7 * 24 * time.Hour),
		RequestFunc: func(request *http.Request) error {
			if verbose {
				log.Println("Request:", strconv.Quote(request.URL.String()))
			}
			return nil
		},
		HeaderFunc: func(header http.Header, request *http.Request, err error) {
			header.Set("X-Hostname", hostname)
		},
		ErrorFunc: func(err error, request *http.Request) {
			if verbose {
				log.Println("Error:", err)
			}
		},
		ResponseFunc: func(request *http.Request, statusCode int, contentSize int64, err error) {
			if verbose {
				var errString string
				if err != nil {
					errString = err.Error()
				}
				log.Println("Response:", request.RemoteAddr, request.Method, strconv.Quote(request.URL.String()), statusCode, contentSize, strconv.Quote(errString))
			}
		},
	}
	http.Handle("/", imageHTTPHandler)

	err = http.ListenAndServe(httpAddr, nil)
	if err != nil {
		log.Panic(err)
	}
}
<commit_msg>remove "verbose" option in advanced example<commit_after>package main

import (
	"crypto/sha256"
	//_ "expvar"
	"flag"
	"log"
	"net/http"
	//_ "net/http/pprof"
	"os"
	"strconv"
	"time"

	redigo "github.com/garyburd/redigo/redis"
	"github.com/pierrre/imageserver"
	imageserver_cache "github.com/pierrre/imageserver/cache"
	imageserver_cache_async "github.com/pierrre/imageserver/cache/async"
	imageserver_cache_list "github.com/pierrre/imageserver/cache/list"
	imageserver_cache_memory "github.com/pierrre/imageserver/cache/memory"
	imageserver_cache_redis "github.com/pierrre/imageserver/cache/redis"
	imageserver_http "github.com/pierrre/imageserver/http"
	imageserver_http_parser_graphicsmagick "github.com/pierrre/imageserver/http/parser/graphicsmagick"
	imageserver_http_parser_list "github.com/pierrre/imageserver/http/parser/list"
	imageserver_http_parser_source "github.com/pierrre/imageserver/http/parser/source"
	imageserver_processor "github.com/pierrre/imageserver/processor"
	imageserver_processor_graphicsmagick "github.com/pierrre/imageserver/processor/graphicsmagick"
	imageserver_processor_limit "github.com/pierrre/imageserver/processor/limit"
	imageserver_provider "github.com/pierrre/imageserver/provider"
	imageserver_provider_cache "github.com/pierrre/imageserver/provider/cache"
	imageserver_provider_http "github.com/pierrre/imageserver/provider/http"
)

func main() {
	var httpAddr string
	flag.StringVar(&httpAddr, "http", ":8080", "Http")
	flag.Parse()

	log.Println("Start")

	hostname, err := os.Hostname()
	if err != nil {
		panic(err)
	}

	var cache imageserver_cache.Cache
	cache = &imageserver_cache_redis.RedisCache{
		Pool: &redigo.Pool{
			Dial: func() (redigo.Conn, error) {
				return redigo.Dial("tcp", "localhost:6379")
			},
			MaxIdle: 50,
		},
		Expire: time.Duration(7 * 24 * time.Hour),
	}
	cache = &imageserver_cache_async.AsyncCache{
		Cache: cache,
		ErrFunc: func(err error, key string, image *imageserver.Image, parameters imageserver.Parameters) {
			log.Println("Cache error:", err)
		},
	}
	cache = imageserver_cache_list.ListCache{
		imageserver_cache_memory.New(10 * 1024 * 1024),
		cache,
	}

	provider := &imageserver_provider_cache.CacheProvider{
		Provider:     &imageserver_provider_http.HTTPProvider{},
		Cache:        cache,
		KeyGenerator: imageserver_provider_cache.NewSourceHashKeyGenerator(sha256.New),
	}

	var processor imageserver_processor.Processor
	processor = &imageserver_processor_graphicsmagick.GraphicsMagickProcessor{
		Executable: "gm",
		Timeout:    time.Duration(10 * time.Second),
		AllowedFormats: []string{
			"jpeg",
			"png",
			"bmp",
			"gif",
		},
	}
	processor = imageserver_processor_limit.New(processor, 16)

	var imageServer imageserver.ImageServer
	imageServer = &imageserver_provider.ProviderImageServer{
		Provider: provider,
	}
	imageServer = &imageserver_processor.ProcessorImageServer{
		ImageServer: imageServer,
		Processor:   processor,
	}
	imageServer = &imageserver_cache.CacheImageServer{
		ImageServer:  imageServer,
		Cache:        cache,
		KeyGenerator: imageserver_cache.NewParametersHashKeyGenerator(sha256.New),
	}

	imageHTTPHandler := &imageserver_http.ImageHTTPHandler{
		Parser: &imageserver_http_parser_list.ListParser{
			&imageserver_http_parser_source.SourceParser{},
			&imageserver_http_parser_graphicsmagick.GraphicsMagickParser{},
		},
		ImageServer: imageServer,
		ETagFunc:    imageserver_http.NewParametersHashETagFunc(sha256.New),
		Expire:      time.Duration(7 * 24 * time.Hour),
		RequestFunc: func(request *http.Request) error {
			log.Println("Request:", strconv.Quote(request.URL.String()))
			return nil
		},
		HeaderFunc: func(header http.Header, request *http.Request, err error) {
			header.Set("X-Hostname", hostname)
		},
		ErrorFunc: func(err error, request *http.Request) {
			log.Println("Error:", err)
		},
		ResponseFunc: func(request *http.Request, statusCode int, contentSize int64, err error) {
			var errString string
			if err != nil {
				errString = err.Error()
			}
			log.Println("Response:", request.RemoteAddr, request.Method, strconv.Quote(request.URL.String()), statusCode, contentSize, strconv.Quote(errString))
		},
	}
	http.Handle("/", imageHTTPHandler)

	err = http.ListenAndServe(httpAddr, nil)
	if err != nil {
		log.Panic(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016, 2017 Florian Pigorsch. All rights reserved.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package sm

import "fmt"

// TileProvider encapsulates all infos about a map tile provider service (name, url scheme, attribution, etc.)
type TileProvider struct {
	Name           string
	Attribution    string
	IgnoreNotFound bool
	TileSize       int
	URLPattern     string // "%[1]s" => shard, "%[2]d" => zoom, "%[3]d" => x, "%[4]d" => y
	Shards         []string
}

func (t *TileProvider) getURL(shard string, zoom, x, y int) string {
	return fmt.Sprintf(t.URLPattern, shard, zoom, x, y)
}

// NewTileProviderOpenStreetMaps creates a TileProvider struct for OSM's tile service
func NewTileProviderOpenStreetMaps() *TileProvider {
	t := new(TileProvider)
	t.Name = "osm"
	t.Attribution = "Maps and Data (c) openstreetmap.org and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.openstreetmap.org/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

func newTileProviderThunderforest(name string) *TileProvider {
	t := new(TileProvider)
	t.Name = fmt.Sprintf("thunderforest-%s", name)
	t.Attribution = "Maps (c) Thundeforest; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "https://%[1]s.tile.thunderforest.com/" + name + "/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

// NewTileProviderThunderforestLandscape creates a TileProvider struct for thundeforests's 'landscape' tile service
func NewTileProviderThunderforestLandscape() *TileProvider {
	return newTileProviderThunderforest("landscape")
}

// NewTileProviderThunderforestOutdoors creates a TileProvider struct for thundeforests's 'outdoors' tile service
func NewTileProviderThunderforestOutdoors() *TileProvider {
	return newTileProviderThunderforest("outdoors")
}

// NewTileProviderThunderforestTransport creates a TileProvider struct for thundeforests's 'transport' tile service
func NewTileProviderThunderforestTransport() *TileProvider {
	return newTileProviderThunderforest("transport")
}

// NewTileProviderStamenToner creates a TileProvider struct for stamens' 'toner' tile service
func NewTileProviderStamenToner() *TileProvider {
	t := new(TileProvider)
	t.Name = "stamen-toner"
	t.Attribution = "Maps (c) Stamen; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.stamen.com/toner/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderStamenTerrain creates a TileProvider struct for stamens' 'terrain' tile service
func NewTileProviderStamenTerrain() *TileProvider {
	t := new(TileProvider)
	t.Name = "stamen-terrain"
	t.Attribution = "Maps (c) Stamen; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.stamen.com/terrain/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderOpenTopoMap creates a TileProvider struct for opentopomap's tile service
func NewTileProviderOpenTopoMap() *TileProvider {
	t := new(TileProvider)
	t.Name = "opentopomap"
	t.Attribution = "Maps (c) OpenTopoMap [CC-BY-SA]; Data (c) OSM and contributors [ODbL]; Data (c) SRTM"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.opentopomap.org/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

// NewTileProviderWikimedia creates a TileProvider struct for Wikimedia's tile service
func NewTileProviderWikimedia() *TileProvider {
	t := new(TileProvider)
	t.Name = "wikimedia"
	t.Attribution = "Map (c) Wikimedia; Data (c) OSM and contributors, ODbL."
	t.TileSize = 256
	t.URLPattern = "https://maps.wikimedia.org/osm-intl/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{}
	return t
}

// NewTileProviderOpenCycleMap creates a TileProvider struct for OpenCycleMap's tile service
func NewTileProviderOpenCycleMap() *TileProvider {
	t := new(TileProvider)
	t.Name = "cycle"
	t.Attribution = "Maps and Data (c) openstreetmaps.org and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.opencyclemap.org/cycle/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b"}
	return t
}

func newTileProviderCarto(name string) *TileProvider {
	t := new(TileProvider)
	t.Name = fmt.Sprintf("carto-%s", name)
	t.Attribution = "Map (c) Carto [CC BY 3.0] Data (c) OSM and contributors, ODbL."
	t.TileSize = 256
	t.URLPattern = "https://cartodb-basemaps-%[1]s.global.ssl.fastly.net/" + name + "_all/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderCartoLight creates a TileProvider struct for Carto's tile service (light variant)
func NewTileProviderCartoLight() *TileProvider {
	return newTileProviderCarto("light")
}

// NewTileProviderCartoDark creates a TileProvider struct for Carto's tile service (dark variant)
func NewTileProviderCartoDark() *TileProvider {
	return newTileProviderCarto("dark")
}

// NewTileProviderArcgisWorldImagery creates a TileProvider struct for Arcgis' WorldImagery tiles
func NewTileProviderArcgisWorldImagery() *TileProvider {
	t := new(TileProvider)
	t.Name = "arcgis-worldimagery"
	t.Attribution = "Source: Esri, Maxar, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community"
	t.TileSize = 256
	t.URLPattern = "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/%[2]d/%[4]d/%[3]d"
	t.Shards = []string{}
	return t
}

// GetTileProviders returns a map of all available TileProviders
func GetTileProviders() map[string]*TileProvider {
	m := make(map[string]*TileProvider)

	list := []*TileProvider{
		NewTileProviderOpenStreetMaps(),
		NewTileProviderOpenCycleMap(),
		NewTileProviderThunderforestLandscape(),
		NewTileProviderThunderforestOutdoors(),
		NewTileProviderThunderforestTransport(),
		NewTileProviderStamenToner(),
		NewTileProviderStamenTerrain(),
		NewTileProviderOpenTopoMap(),
		NewTileProviderOpenStreetMaps(),
		NewTileProviderOpenCycleMap(),
		NewTileProviderCartoLight(),
		NewTileProviderCartoDark(),
		NewTileProviderArcgisWorldImagery(),
	}

	for _, tp := range list {
		m[tp.Name] = tp
	}

	return m
}
<commit_msg>Added tile to GetTileProviders map (#54)<commit_after>// Copyright 2016, 2017 Florian Pigorsch. All rights reserved.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package sm

import "fmt"

// TileProvider encapsulates all infos about a map tile provider service (name, url scheme, attribution, etc.)
type TileProvider struct {
	Name           string
	Attribution    string
	IgnoreNotFound bool
	TileSize       int
	URLPattern     string // "%[1]s" => shard, "%[2]d" => zoom, "%[3]d" => x, "%[4]d" => y
	Shards         []string
}

func (t *TileProvider) getURL(shard string, zoom, x, y int) string {
	return fmt.Sprintf(t.URLPattern, shard, zoom, x, y)
}

// NewTileProviderOpenStreetMaps creates a TileProvider struct for OSM's tile service
func NewTileProviderOpenStreetMaps() *TileProvider {
	t := new(TileProvider)
	t.Name = "osm"
	t.Attribution = "Maps and Data (c) openstreetmap.org and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.openstreetmap.org/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

func newTileProviderThunderforest(name string) *TileProvider {
	t := new(TileProvider)
	t.Name = fmt.Sprintf("thunderforest-%s", name)
	t.Attribution = "Maps (c) Thundeforest; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "https://%[1]s.tile.thunderforest.com/" + name + "/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

// NewTileProviderThunderforestLandscape creates a TileProvider struct for thundeforests's 'landscape' tile service
func NewTileProviderThunderforestLandscape() *TileProvider {
	return newTileProviderThunderforest("landscape")
}

// NewTileProviderThunderforestOutdoors creates a TileProvider struct for thundeforests's 'outdoors' tile service
func NewTileProviderThunderforestOutdoors() *TileProvider {
	return newTileProviderThunderforest("outdoors")
}

// NewTileProviderThunderforestTransport creates a TileProvider struct for thundeforests's 'transport' tile service
func NewTileProviderThunderforestTransport() *TileProvider {
	return newTileProviderThunderforest("transport")
}

// NewTileProviderStamenToner creates a TileProvider struct for stamens' 'toner' tile service
func NewTileProviderStamenToner() *TileProvider {
	t := new(TileProvider)
	t.Name = "stamen-toner"
	t.Attribution = "Maps (c) Stamen; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.stamen.com/toner/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderStamenTerrain creates a TileProvider struct for stamens' 'terrain' tile service
func NewTileProviderStamenTerrain() *TileProvider {
	t := new(TileProvider)
	t.Name = "stamen-terrain"
	t.Attribution = "Maps (c) Stamen; Data (c) OSM and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.stamen.com/terrain/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderOpenTopoMap creates a TileProvider struct for opentopomap's tile service
func NewTileProviderOpenTopoMap() *TileProvider {
	t := new(TileProvider)
	t.Name = "opentopomap"
	t.Attribution = "Maps (c) OpenTopoMap [CC-BY-SA]; Data (c) OSM and contributors [ODbL]; Data (c) SRTM"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.opentopomap.org/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c"}
	return t
}

// NewTileProviderWikimedia creates a TileProvider struct for Wikimedia's tile service
func NewTileProviderWikimedia() *TileProvider {
	t := new(TileProvider)
	t.Name = "wikimedia"
	t.Attribution = "Map (c) Wikimedia; Data (c) OSM and contributors, ODbL."
	t.TileSize = 256
	t.URLPattern = "https://maps.wikimedia.org/osm-intl/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{}
	return t
}

// NewTileProviderOpenCycleMap creates a TileProvider struct for OpenCycleMap's tile service
func NewTileProviderOpenCycleMap() *TileProvider {
	t := new(TileProvider)
	t.Name = "cycle"
	t.Attribution = "Maps and Data (c) openstreetmaps.org and contributors, ODbL"
	t.TileSize = 256
	t.URLPattern = "http://%[1]s.tile.opencyclemap.org/cycle/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b"}
	return t
}

func newTileProviderCarto(name string) *TileProvider {
	t := new(TileProvider)
	t.Name = fmt.Sprintf("carto-%s", name)
	t.Attribution = "Map (c) Carto [CC BY 3.0] Data (c) OSM and contributors, ODbL."
	t.TileSize = 256
	t.URLPattern = "https://cartodb-basemaps-%[1]s.global.ssl.fastly.net/" + name + "_all/%[2]d/%[3]d/%[4]d.png"
	t.Shards = []string{"a", "b", "c", "d"}
	return t
}

// NewTileProviderCartoLight creates a TileProvider struct for Carto's tile service (light variant)
func NewTileProviderCartoLight() *TileProvider {
	return newTileProviderCarto("light")
}

// NewTileProviderCartoDark creates a TileProvider struct for Carto's tile service (dark variant)
func NewTileProviderCartoDark() *TileProvider {
	return newTileProviderCarto("dark")
}

// NewTileProviderArcgisWorldImagery creates a TileProvider struct for Arcgis' WorldImagery tiles
func NewTileProviderArcgisWorldImagery() *TileProvider {
	t := new(TileProvider)
	t.Name = "arcgis-worldimagery"
	t.Attribution = "Source: Esri, Maxar, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community"
	t.TileSize = 256
	t.URLPattern = "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/%[2]d/%[4]d/%[3]d"
	t.Shards = []string{}
	return t
}

// GetTileProviders returns a map of all available TileProviders
func GetTileProviders() map[string]*TileProvider {
	m := make(map[string]*TileProvider)

	list := []*TileProvider{
		NewTileProviderOpenStreetMaps(),
		NewTileProviderOpenCycleMap(),
		NewTileProviderThunderforestLandscape(),
		NewTileProviderThunderforestOutdoors(),
		NewTileProviderThunderforestTransport(),
		NewTileProviderStamenToner(),
		NewTileProviderStamenTerrain(),
		NewTileProviderOpenTopoMap(),
		NewTileProviderOpenStreetMaps(),
		NewTileProviderOpenCycleMap(),
		NewTileProviderCartoLight(),
		NewTileProviderCartoDark(),
		NewTileProviderArcgisWorldImagery(),
		NewTileProviderWikimedia(),
	}

	for _, tp := range list {
		m[tp.Name] = tp
	}

	return m
}
<|endoftext|>


<commit_before>// Package calc is calucrator.
package calc

import "errors"

// Divison is division two ints.
func Division(a int, b int) (div int, err error) {
	if b <= 0 {
		return div, errors.New("Cannot use zero in second argument.")
	}

	div = a / b
	return
}
<commit_msg>fixed.<commit_after>// Package calc is calucrator.
package calc

import "errors"

// Divison is division two ints.
func Division(a int, b int) (div int, err error) {
	if b == 0 {
		return div, errors.New("Cannot use zero in second argument.")
	}

	div = a / b
	return
}
<|endoftext|>


<commit_before>// Copyright 2012 The go-gl 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 glfw

//#include "callback.h"
import "C"

// =============================================================================

type WindowSizeHandler func(width, height int)

var windowSize WindowSizeHandler

//export goWindowSizeCB
func goWindowSizeCB(width, height C.int) {
	if windowSize == nil {
		return
	}
	windowSize(int(width), int(height))
}

// SetWindowSizeCallback sets the callback for window size change events.
func SetWindowSizeCallback(f WindowSizeHandler) {
	windowSize = f
	C.glfwSetWindowSizeCB()
}

// =============================================================================

type WindowCloseHandler func() int

var windowClose WindowCloseHandler

//export goWindowCloseCB
func goWindowCloseCB() C.int {
	if windowClose == nil {
		return 0
	}
	return C.int(windowClose())
}

// SetWindowCloseCallback sets the callback for window close events.
// A window has to be opened for this function to have any effect.
func SetWindowCloseCallback(f WindowCloseHandler) {
	windowClose = f
	C.glfwSetWindowCloseCB()
}

// =============================================================================

type WindowRefreshHandler func()

var windowRefresh WindowRefreshHandler

//export goWindowRefreshCB
func goWindowRefreshCB() {
	if windowRefresh == nil {
		return
	}
	windowRefresh()
}

// SetWindowRefreshCallback sets the callback for window refresh events, which
// occurs when any part of the window client area has been damaged, and needs to
// be repainted (for instance, if a part of the window that was previously
// occluded by another window has become visible).
func SetWindowRefreshCallback(f WindowRefreshHandler) {
	windowRefresh = f
	C.glfwSetWindowRefreshCB()
}

// =============================================================================

type MouseButtonHandler func(button, state int)

var mouseButton []MouseButtonHandler

//export goMouseButtonCB
func goMouseButtonCB(button, state C.int) {
	for _, f := range mouseButton {
		f(int(button), int(state))
	}
}

// SetMouseButtonCallback sets the callback for mouse button events.
// There can be more than one handler.
func SetMouseButtonCallback(f MouseButtonHandler) {
	mouseButton = append(mouseButton, f)
	C.glfwSetMouseButtonCB()
}

// =============================================================================

type MousePosHandler func(x, y int)

var mousePos []MousePosHandler

//export goMousePosCB
func goMousePosCB(x, y C.int) {
	for _, f := range mousePos {
		f(int(x), int(y))
	}
}

// SetMousePosCallback sets a callback for mouse motion events.
// There can be more than one handler.
func SetMousePosCallback(f MousePosHandler) {
	mousePos = append(mousePos, f)
	C.glfwSetMousePosCB()
}

// =============================================================================

type MouseWheelHandler func(delta int)

var mouseWheel []MouseWheelHandler

//export goMouseWheelCB
func goMouseWheelCB(delta C.int) {
	for _, f := range mouseWheel {
		f(int(delta))
	}
}

// This function sets the callback for mouse wheel events.
// There can be more than one handler.
func SetMouseWheelCallback(f MouseWheelHandler) {
	mouseWheel = append(mouseWheel, f)
	C.glfwSetMouseWheelCB()
}

// =============================================================================

type KeyHandler func(key, state int)

var key []KeyHandler

//export goKeyCB
func goKeyCB(k, state C.int) {
	for _, f := range key {
		f(int(k), int(state))
	}
}

// SetKeyCallback sets the callback for keyboard key events. The callback
// function is called every time the state of a single key is changed (from
// released to pressed or vice versa). The reported keys are unaffected by any
// modifiers (such as shift or alt) and each modifier is reported as a separate key.
//
// There can be more than one handler.
func SetKeyCallback(f KeyHandler) {
	key = append(key, f)
	C.glfwSetKeyCB()
}

// =============================================================================

type CharHandler func(int, int)

var char []CharHandler

//export goCharCB
func goCharCB(x, y C.int) {
	for _, f := range char {
		f(int(x), int(y))
	}
}

// SetCharCallback sets the callback for keyboard character events. The callback
// function is called every time a key that results in a printable Unicode
// character is pressed or released. Characters are affected by modifiers
// (such as shift or alt).
func SetCharCallback(f CharHandler) {
	char = append(char, f)
	C.glfwSetCharCB()
}
<commit_msg>Changed argument name for MouseWheelHandler<commit_after>// Copyright 2012 The go-gl 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 glfw

//#include "callback.h"
import "C"

// =============================================================================

type WindowSizeHandler func(width, height int)

var windowSize WindowSizeHandler

//export goWindowSizeCB
func goWindowSizeCB(width, height C.int) {
	if windowSize == nil {
		return
	}
	windowSize(int(width), int(height))
}

// SetWindowSizeCallback sets the callback for window size change events.
func SetWindowSizeCallback(f WindowSizeHandler) {
	windowSize = f
	C.glfwSetWindowSizeCB()
}

// =============================================================================

type WindowCloseHandler func() int

var windowClose WindowCloseHandler

//export goWindowCloseCB
func goWindowCloseCB() C.int {
	if windowClose == nil {
		return 0
	}
	return C.int(windowClose())
}

// SetWindowCloseCallback sets the callback for window close events.
// A window has to be opened for this function to have any effect.
func SetWindowCloseCallback(f WindowCloseHandler) {
	windowClose = f
	C.glfwSetWindowCloseCB()
}

// =============================================================================

type WindowRefreshHandler func()

var windowRefresh WindowRefreshHandler

//export goWindowRefreshCB
func goWindowRefreshCB() {
	if windowRefresh == nil {
		return
	}
	windowRefresh()
}

// SetWindowRefreshCallback sets the callback for window refresh events, which
// occurs when any part of the window client area has been damaged, and needs to
// be repainted (for instance, if a part of the window that was previously
// occluded by another window has become visible).
func SetWindowRefreshCallback(f WindowRefreshHandler) {
	windowRefresh = f
	C.glfwSetWindowRefreshCB()
}

// =============================================================================

type MouseButtonHandler func(button, state int)

var mouseButton []MouseButtonHandler

//export goMouseButtonCB
func goMouseButtonCB(button, state C.int) {
	for _, f := range mouseButton {
		f(int(button), int(state))
	}
}

// SetMouseButtonCallback sets the callback for mouse button events.
// There can be more than one handler.
func SetMouseButtonCallback(f MouseButtonHandler) {
	mouseButton = append(mouseButton, f)
	C.glfwSetMouseButtonCB()
}

// =============================================================================

type MousePosHandler func(x, y int)

var mousePos []MousePosHandler

//export goMousePosCB
func goMousePosCB(x, y C.int) {
	for _, f := range mousePos {
		f(int(x), int(y))
	}
}

// SetMousePosCallback sets a callback for mouse motion events.
// There can be more than one handler.
func SetMousePosCallback(f MousePosHandler) {
	mousePos = append(mousePos, f)
	C.glfwSetMousePosCB()
}

// =============================================================================

type MouseWheelHandler func(pos int)

var mouseWheel []MouseWheelHandler

//export goMouseWheelCB
func goMouseWheelCB(pos C.int) {
	for _, f := range mouseWheel {
		f(int(pos))
	}
}

// This function sets the callback for mouse wheel events.
// There can be more than one handler.
func SetMouseWheelCallback(f MouseWheelHandler) {
	mouseWheel = append(mouseWheel, f)
	C.glfwSetMouseWheelCB()
}

// =============================================================================

type KeyHandler func(key, state int)

var key []KeyHandler

//export goKeyCB
func goKeyCB(k, state C.int) {
	for _, f := range key {
		f(int(k), int(state))
	}
}

// SetKeyCallback sets the callback for keyboard key events. The callback
// function is called every time the state of a single key is changed (from
// released to pressed or vice versa). The reported keys are unaffected by any
// modifiers (such as shift or alt) and each modifier is reported as a separate key.
//
// There can be more than one handler.
func SetKeyCallback(f KeyHandler) {
	key = append(key, f)
	C.glfwSetKeyCB()
}

// =============================================================================

type CharHandler func(int, int)

var char []CharHandler

//export goCharCB
func goCharCB(x, y C.int) {
	for _, f := range char {
		f(int(x), int(y))
	}
}

// SetCharCallback sets the callback for keyboard character events. The callback
// function is called every time a key that results in a printable Unicode
// character is pressed or released. Characters are affected by modifiers
// (such as shift or alt).
func SetCharCallback(f CharHandler) {
	char = append(char, f)
	C.glfwSetCharCB()
}
<|endoftext|>