<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"

	. "github.com/matzoe/xunlei/api"
	"github.com/zyxar/taipei"
)

type Term interface {
	ReadLine() (string, error)
	Restore()
}

func _find(req string) (map[string]*Task, error) {
	if t, ok := M.Tasks[req]; ok {
		return map[string]*Task{req: t}, nil
	}
	if ok, _ := regexp.MatchString(`(.+=.+)+`, req); ok {
		return FindTasks(req)
	}
	return FindTasks("name=" + req)
}

func find(req []string) (map[string]*Task, error) {
	if len(req) == 0 {
		return nil, errors.New("Empty find query.")
	} else if len(req) == 1 {
		return _find(req[0])
	}
	return _find("name=" + strings.Join(req, "|"))
}

func fixedLengthName(name string, size int) string {
	l := utf8.RuneCountInString(name)
	var b bytes.Buffer
	var i int = 0
	for i < l && i < size {
		r, s := utf8.DecodeRuneInString(name)
		b.WriteRune(r)
		name = name[s:]
		if s > 1 {
			i += 2
		} else {
			i++
		}
	}
	for i < size {
		b.WriteByte(' ')
		i++
	}
	return b.String()
}

func main() {
	initConf()
	f, _ := ioutil.ReadFile(conf_file)
	json.Unmarshal(f, &conf)
	flag.StringVar(&conf.Id, "login", conf.Id, "login account")
	flag.StringVar(&conf.Pass, "pass", conf.Pass, "password/passhash")
	flag.BoolVar(&printVer, "version", false, "print version")
	flag.Parse()
	if printVer {
		printVersion()
		return
	}
	if err := ResumeSession(cookie_file); err != nil {
		log.Println(err)
		if err = Login(conf.Id, conf.Pass); err != nil {
			log.Println(err)
			os.Exit(1)
		}
		if err = SaveSession(cookie_file); err != nil {
			log.Println(err)
		}
	}
	GetGdriveId()

	term := newTerm()
	defer term.Restore()
	{
		var err error
		insufficientArgErr := errors.New("Insufficient arguments.")
		noTasksMatchesErr := errors.New("No task matches.")
		var line string
		var cmds []string
		clearscr()
	LOOP:
		for {
			line, err = term.ReadLine()
			if err != nil {
				break
			}
			cmds = strings.Fields(line)
			if len(cmds) == 0 {
				continue
			}
			switch cmds[0] {
			case "ison":
				log.Println(IsOn())
			case "relogin":
				if !IsOn() {
					err = Login(conf.Id, conf.Pass)
				} else {
					fmt.Println("Already log on.")
				}
			case "cls", "clear":
				clearscr()
			case "ls":
				ts, err := GetTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "ld":
				ts, err := GetDeletedTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "le":
				ts, err := GetExpiredTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "lc":
				ts, err := GetCompletedTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "ll":
				ts, err := GetTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Repr())
						k++
					}
				}
			case "info":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						j := 0
						for i, _ := range ts {
							if ts[i].IsBt() {
								m, err := ts[i].FillBtList()
								fmt.Printf("#%d %v\n", j, ts[i].Repr())
								if err == nil {
									fmt.Printf("%v\n", m)
								}
							} else {
								fmt.Printf("#%d %v\n", j, ts[i].Repr())
							}
							j++
						}
					}
				}
			case "dl", "download":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					pay := make(map[string]*struct {
						t *Task
						s string
					})
					del := false
					check := conf.CheckHash
					for i, _ := range cmds[1:] {
						if strings.HasPrefix(cmds[1:][i], "--") {
							switch cmds[1:][i][2:] {
							case "delete":
								del = true
							case "check":
								check = true
							case "no-check", "nocheck":
								check = false
							}
						} else {
							p := strings.Split(cmds[1:][i], "/")
							m, err := _find(p[0])
							if err == nil {
								for i, _ := range m {
									var filter string
									if len(p) == 1 {
										filter = `.*`
									} else {
										filter = p[1]
									}
									pay[m[i].Id] = &struct {
										t *Task
										s string
									}{m[i], filter}
								}
							}
						}
					}
					for i, _ := range pay {
						if err = download(pay[i].t, pay[i].s, true, check); err != nil {
							fmt.Println(err)
						} else if del {
							if err = pay[i].t.Remove(); err != nil {
								fmt.Println(err)
							}
						}
					}
					err = nil
				}
			case "dt":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil { // TODO: improve find query
						for i, _ := range ts {
							if ts[i].IsBt() {
								if err = GetTorrentFileByHash(ts[i].Cid, ts[i].TaskName+".torrent"); err != nil {
									fmt.Println(err)
								}
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "ti":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil { // TODO: improve find query
						for i, _ := range ts {
							if ts[i].IsBt() {
								if b, err := GetTorrentByHash(ts[i].Cid); err != nil {
									fmt.Println(err)
								} else {
									if m, err := taipei.DecodeMetaInfo(b); err != nil {
										fmt.Println(err)
									} else {
										taipei.Iconv(m)
										fmt.Println(m)
									}
								}
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "add":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					req := cmds[1:]
					for j, _ := range req {
						if err = AddTask(req[j]); err != nil {
							fmt.Println(err)
						}
					}
					err = nil
				}
			case "rm", "delete":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Remove(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "purge":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Purge(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "readd":
				// re-add tasks from deleted or expired
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						ReAddTasks(ts)
					}
				} else {
					err = insufficientArgErr
				}
			case "pause":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Pause(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "resume":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Resume(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "rename", "mv":
				if len(cmds) == 3 {
					// must be task id here
					if t, ok := M.Tasks[cmds[1]]; ok {
						t.Rename(cmds[2])
					} else {
						err = noTasksMatchesErr
					}
				} else {
					err = insufficientArgErr
				}
			case "delay":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Delay(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "link":
				if len(cmds) == 2 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						k := 0
						for i, _ := range ts {
							if !ts[i].IsBt() {
								fmt.Printf("#%d %s: %v\n", k, ts[i].Id, ts[i].LixianURL)
							} else {
								m, err := ts[i].FillBtList()
								if err == nil {
									fmt.Printf("#%d %s:\n", k, ts[i].Id)
									for j, _ := range m.Record {
										fmt.Printf("  #%d %s\n", m.Record[j].Id, m.Record[j].DownURL)
									}
								}
							}
							k++
						}
					}
				} else {
					err = insufficientArgErr
				}
			case "find":
				if len(cmds) == 2 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						k := 0
						for i, _ := range ts {
							fmt.Printf("#%d %v\n", k, ts[i].Coloring())
							k++
						}
					}
				} else {
					err = insufficientArgErr
				}
			case "version":
				printVersion()
			case "update":
				err = ProcessTask(func(t *Task) {
					log.Printf("%s %s %sB/s %.2f%%\n", t.Id, fixedLengthName(t.TaskName, 32), t.Speed, t.Progress)
				})
			case "quit", "exit":
				break LOOP
			case "help":
				// TODO
			default:
				err = fmt.Errorf("Unrecognised command: %s", cmds[0])
			}
			if err != nil {
				fmt.Println(err)
			}
		}
	}
}
<commit_msg>save session after relogin<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
	"unicode/utf8"

	. "github.com/matzoe/xunlei/api"
	"github.com/zyxar/taipei"
)

type Term interface {
	ReadLine() (string, error)
	Restore()
}

func _find(req string) (map[string]*Task, error) {
	if t, ok := M.Tasks[req]; ok {
		return map[string]*Task{req: t}, nil
	}
	if ok, _ := regexp.MatchString(`(.+=.+)+`, req); ok {
		return FindTasks(req)
	}
	return FindTasks("name=" + req)
}

func find(req []string) (map[string]*Task, error) {
	if len(req) == 0 {
		return nil, errors.New("Empty find query.")
	} else if len(req) == 1 {
		return _find(req[0])
	}
	return _find("name=" + strings.Join(req, "|"))
}

func fixedLengthName(name string, size int) string {
	l := utf8.RuneCountInString(name)
	var b bytes.Buffer
	var i int = 0
	for i < l && i < size {
		r, s := utf8.DecodeRuneInString(name)
		b.WriteRune(r)
		name = name[s:]
		if s > 1 {
			i += 2
		} else {
			i++
		}
	}
	for i < size {
		b.WriteByte(' ')
		i++
	}
	return b.String()
}

func main() {
	initConf()
	f, _ := ioutil.ReadFile(conf_file)
	json.Unmarshal(f, &conf)
	flag.StringVar(&conf.Id, "login", conf.Id, "login account")
	flag.StringVar(&conf.Pass, "pass", conf.Pass, "password/passhash")
	flag.BoolVar(&printVer, "version", false, "print version")
	flag.Parse()
	if printVer {
		printVersion()
		return
	}
	if err := ResumeSession(cookie_file); err != nil {
		log.Println(err)
		if err = Login(conf.Id, conf.Pass); err != nil {
			log.Println(err)
			os.Exit(1)
		}
		if err = SaveSession(cookie_file); err != nil {
			log.Println(err)
		}
	}
	GetGdriveId()

	term := newTerm()
	defer term.Restore()
	{
		var err error
		insufficientArgErr := errors.New("Insufficient arguments.")
		noTasksMatchesErr := errors.New("No task matches.")
		var line string
		var cmds []string
		clearscr()
	LOOP:
		for {
			line, err = term.ReadLine()
			if err != nil {
				break
			}
			cmds = strings.Fields(line)
			if len(cmds) == 0 {
				continue
			}
			switch cmds[0] {
			case "ison":
				log.Println(IsOn())
			case "relogin":
				if !IsOn() {
					if err = Login(conf.Id, conf.Pass); err != nil {
						log.Println(err)
					} else if err = SaveSession(cookie_file); err != nil {
						log.Println(err)
					}
				} else {
					fmt.Println("Already log on.")
				}
			case "cls", "clear":
				clearscr()
			case "ls":
				ts, err := GetTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "ld":
				ts, err := GetDeletedTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "le":
				ts, err := GetExpiredTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "lc":
				ts, err := GetCompletedTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Coloring())
						k++
					}
				}
			case "ll":
				ts, err := GetTasks()
				if err == nil {
					k := 0
					for i, _ := range ts {
						fmt.Printf("#%d %v\n", k, ts[i].Repr())
						k++
					}
				}
			case "info":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						j := 0
						for i, _ := range ts {
							if ts[i].IsBt() {
								m, err := ts[i].FillBtList()
								fmt.Printf("#%d %v\n", j, ts[i].Repr())
								if err == nil {
									fmt.Printf("%v\n", m)
								}
							} else {
								fmt.Printf("#%d %v\n", j, ts[i].Repr())
							}
							j++
						}
					}
				}
			case "dl", "download":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					pay := make(map[string]*struct {
						t *Task
						s string
					})
					del := false
					check := conf.CheckHash
					for i, _ := range cmds[1:] {
						if strings.HasPrefix(cmds[1:][i], "--") {
							switch cmds[1:][i][2:] {
							case "delete":
								del = true
							case "check":
								check = true
							case "no-check", "nocheck":
								check = false
							}
						} else {
							p := strings.Split(cmds[1:][i], "/")
							m, err := _find(p[0])
							if err == nil {
								for i, _ := range m {
									var filter string
									if len(p) == 1 {
										filter = `.*`
									} else {
										filter = p[1]
									}
									pay[m[i].Id] = &struct {
										t *Task
										s string
									}{m[i], filter}
								}
							}
						}
					}
					for i, _ := range pay {
						if err = download(pay[i].t, pay[i].s, true, check); err != nil {
							fmt.Println(err)
						} else if del {
							if err = pay[i].t.Remove(); err != nil {
								fmt.Println(err)
							}
						}
					}
					err = nil
				}
			case "dt":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil { // TODO: improve find query
						for i, _ := range ts {
							if ts[i].IsBt() {
								if err = GetTorrentFileByHash(ts[i].Cid, ts[i].TaskName+".torrent"); err != nil {
									fmt.Println(err)
								}
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "ti":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil { // TODO: improve find query
						for i, _ := range ts {
							if ts[i].IsBt() {
								if b, err := GetTorrentByHash(ts[i].Cid); err != nil {
									fmt.Println(err)
								} else {
									if m, err := taipei.DecodeMetaInfo(b); err != nil {
										fmt.Println(err)
									} else {
										taipei.Iconv(m)
										fmt.Println(m)
									}
								}
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "add":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					req := cmds[1:]
					for j, _ := range req {
						if err = AddTask(req[j]); err != nil {
							fmt.Println(err)
						}
					}
					err = nil
				}
			case "rm", "delete":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Remove(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "purge":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Purge(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "readd":
				// re-add tasks from deleted or expired
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						ReAddTasks(ts)
					}
				} else {
					err = insufficientArgErr
				}
			case "pause":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Pause(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "resume":
				if len(cmds) > 1 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Resume(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				} else {
					err = insufficientArgErr
				}
			case "rename", "mv":
				if len(cmds) == 3 {
					// must be task id here
					if t, ok := M.Tasks[cmds[1]]; ok {
						t.Rename(cmds[2])
					} else {
						err = noTasksMatchesErr
					}
				} else {
					err = insufficientArgErr
				}
			case "delay":
				if len(cmds) < 2 {
					err = insufficientArgErr
				} else {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							if err = ts[i].Delay(); err != nil {
								fmt.Println(err)
							}
						}
						err = nil
					}
				}
			case "link":
				if len(cmds) == 2 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						k := 0
						for i, _ := range ts {
							if !ts[i].IsBt() {
								fmt.Printf("#%d %s: %v\n", k, ts[i].Id, ts[i].LixianURL)
							} else {
								m, err := ts[i].FillBtList()
								if err == nil {
									fmt.Printf("#%d %s:\n", k, ts[i].Id)
									for j, _ := range m.Record {
										fmt.Printf("  #%d %s\n", m.Record[j].Id, m.Record[j].DownURL)
									}
								}
							}
							k++
						}
					}
				} else {
					err = insufficientArgErr
				}
			case "find":
				if len(cmds) == 2 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						k := 0
						for i, _ := range ts {
							fmt.Printf("#%d %v\n", k, ts[i].Coloring())
							k++
						}
					}
				} else {
					err = insufficientArgErr
				}
			case "play":
				if len(cmds) == 2 {
					var ts map[string]*Task
					if ts, err = find(cmds[1:]); err == nil {
						for i, _ := range ts {
							b := ts[i].GetPlayURL()
							fmt.Printf("%s\n", b)
						}
					}
				} else {
					err = insufficientArgErr
				}
			case "version":
				printVersion()
			case "update":
				err = ProcessTask(func(t *Task) {
					log.Printf("%s %s %sB/s %.2f%%\n", t.Id, fixedLengthName(t.TaskName, 32), t.Speed, t.Progress)
				})
			case "quit", "exit":
				break LOOP
			case "help":
				// TODO
			default:
				err = fmt.Errorf("Unrecognised command: %s", cmds[0])
			}
			if err != nil {
				fmt.Println(err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package logstash

import (
	"encoding/json"
	"errors"
	"log"
	"net"
	"os"

	"github.com/gliderlabs/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewLogstashAdapter, "logstash")
}

// LogstashAdapter is an adapter that streams TCP JSON to Logstash.
type LogstashAdapter struct {
	conn  net.Conn
	route *router.Route
}

// NewLogstashAdapter creates a LogstashAdapter with TCP as the default transport.
func NewLogstashAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("tcp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &LogstashAdapter{
		route: route,
		conn:  conn,
	}, nil
}

// Stream implements the router.LogAdapter interface.
func (a *LogstashAdapter) Stream(logstream chan *router.Message) {
	for m := range logstream {
		msg := LogstashMessage{
			Message:  m.Data,
			Name:     m.Container.Name,
			ID:       m.Container.ID,
			Image:    m.Container.Config.Image,
			Hostname: m.Container.Config.Hostname,
			Labels:   m.Container.Config.Labels,
		}
		js, err := json.Marshal(msg)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
		toWrite := ""
		toWrite += js
		toWrite += "\n"
		_, err = a.conn.Write(toWrite)
		if err != nil {
			log.Println("fatal logstash:", err)
			os.Exit(3)
		}
	}
}

// LogstashMessage is a simple JSON input to Logstash.
type LogstashMessage struct {
	Message  string            `json:"message"`
	Name     string            `json:"docker.name"`
	ID       string            `json:"docker.id"`
	Image    string            `json:"docker.image"`
	Hostname string            `json:"docker.hostname"`
	Labels   map[string]string `json:"docker.labels,omitempty"`
}
<commit_msg>use toWrite<commit_after>package logstash

import (
	"encoding/json"
	"errors"
	"log"
	"net"
	"os"

	"github.com/gliderlabs/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewLogstashAdapter, "logstash")
}

// LogstashAdapter is an adapter that streams TCP JSON to Logstash.
type LogstashAdapter struct {
	conn  net.Conn
	route *router.Route
}

// NewLogstashAdapter creates a LogstashAdapter with TCP as the default transport.
func NewLogstashAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("tcp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &LogstashAdapter{
		route: route,
		conn:  conn,
	}, nil
}

// Stream implements the router.LogAdapter interface.
func (a *LogstashAdapter) Stream(logstream chan *router.Message) {
	for m := range logstream {
		msg := LogstashMessage{
			Message:  m.Data,
			Name:     m.Container.Name,
			ID:       m.Container.ID,
			Image:    m.Container.Config.Image,
			Hostname: m.Container.Config.Hostname,
			Labels:   m.Container.Config.Labels,
		}
		js, err := json.Marshal(msg)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
		js.WriteString("\n")
		_, err = a.conn.Write(js)
		if err != nil {
			log.Println("fatal logstash:", err)
			os.Exit(3)
		}
	}
}

// LogstashMessage is a simple JSON input to Logstash.
type LogstashMessage struct {
	Message  string            `json:"message"`
	Name     string            `json:"docker.name"`
	ID       string            `json:"docker.id"`
	Image    string            `json:"docker.image"`
	Hostname string            `json:"docker.hostname"`
	Labels   map[string]string `json:"docker.labels,omitempty"`
}
<|endoftext|>


<commit_before>package logstash

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"

	"github.com/gliderlabs/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewLogstashAdapter, "logstash")
}

// LogstashAdapter is an adapter that streams UDP JSON to Logstash.
type LogstashAdapter struct {
	conn  net.Conn
	route *router.Route
}

func getopt(name, dfault string) string {
	value := os.Getenv(name)
	if value == "" {
		value = dfault
	}
	return value
}

// NewLogstashAdapter creates a LogstashAdapter with UDP as the default transport.
func NewLogstashAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &LogstashAdapter{
		route: route,
		conn:  conn,
	}, nil
}

// Stream implements the router.LogAdapter interface.
func (a *LogstashAdapter) Stream(logstream chan *router.Message) {

	opt_string := getopt("OPTIONS", "")
	var options map[string]string

	if opt_string != "" {
		b := []byte(opt_string)

		json.Unmarshal(b, &options)
	}

	resp, err := http.Get("http://169.254.169.254/latest/meta-data/instance-id")
	var instance_id string
	if err == nil {
		instance_id, err := ioutil.ReadAll(resp.Body)
	}
	resp.Body.Close()

	for m := range logstream {
		msg := LogstashMessage{
			Message:    m.Data,
			Name:       m.Container.Name,
			ID:         m.Container.ID,
			Image:      m.Container.Config.Image,
			Hostname:   m.Container.Config.Hostname,
			Args:       m.Container.Args,
			InstanceId: instance_id,
			Options:    options,
		}
		js, err := json.Marshal(msg)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
		_, err = a.conn.Write(js)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
	}
}

// LogstashMessage is a simple JSON input to Logstash.
type LogstashMessage struct {
	Message    string            `json:"message"`
	Name       string            `json:"docker.name"`
	ID         string            `json:"docker.id"`
	Image      string            `json:"docker.image"`
	Hostname   string            `json:"docker.hostname"`
	Args       []string          `json:"docker.args,omitempty"`
	Options    map[string]string `json:"options,omitempty"`
	InstanceId string            `json:"instance-id"`
}
<commit_msg>setting var value<commit_after>package logstash

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"

	"github.com/gliderlabs/logspout/router"
)

func init() {
	router.AdapterFactories.Register(NewLogstashAdapter, "logstash")
}

// LogstashAdapter is an adapter that streams UDP JSON to Logstash.
type LogstashAdapter struct {
	conn  net.Conn
	route *router.Route
}

func getopt(name, dfault string) string {
	value := os.Getenv(name)
	if value == "" {
		value = dfault
	}
	return value
}

// NewLogstashAdapter creates a LogstashAdapter with UDP as the default transport.
func NewLogstashAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &LogstashAdapter{
		route: route,
		conn:  conn,
	}, nil
}

// Stream implements the router.LogAdapter interface.
func (a *LogstashAdapter) Stream(logstream chan *router.Message) {

	opt_string := getopt("OPTIONS", "")
	var options map[string]string

	if opt_string != "" {
		b := []byte(opt_string)

		json.Unmarshal(b, &options)
	}

	resp, err := http.Get("http://169.254.169.254/latest/meta-data/instance-id")
	instance_id := ""
	if err == nil {
		value, err := ioutil.ReadAll(resp.Body)
		if err == nil {
			instance_id = instance_id
		}
	}
	resp.Body.Close()

	for m := range logstream {
		msg := LogstashMessage{
			Message:    m.Data,
			Name:       m.Container.Name,
			ID:         m.Container.ID,
			Image:      m.Container.Config.Image,
			Hostname:   m.Container.Config.Hostname,
			Args:       m.Container.Args,
			InstanceId: instance_id,
			Options:    options,
		}
		js, err := json.Marshal(msg)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
		_, err = a.conn.Write(js)
		if err != nil {
			log.Println("logstash:", err)
			continue
		}
	}
}

// LogstashMessage is a simple JSON input to Logstash.
type LogstashMessage struct {
	Message    string            `json:"message"`
	Name       string            `json:"docker.name"`
	ID         string            `json:"docker.id"`
	Image      string            `json:"docker.image"`
	Hostname   string            `json:"docker.hostname"`
	Args       []string          `json:"docker.args,omitempty"`
	Options    map[string]string `json:"options,omitempty"`
	InstanceId string            `json:"instance-id,omitempty"`
}
<|endoftext|>


<commit_before>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on the QRDecomposition class from Jama 1.0.3.

package mat64

import (
	"math"

	"github.com/gonum/blas"
	"github.com/gonum/blas/blas64"
	"github.com/gonum/lapack/lapack64"
	"github.com/gonum/matrix"
)

// QR is a type for creating and using the QR factorization of a matrix.
type QR struct {
	qr   *Dense
	tau  []float64
	cond float64
}

func (qr *QR) updateCond() {
	// A = QR, where Q is orthonormal. Orthonormal multiplications do not change
	// the condition number. Thus, ||A|| = ||Q|| ||R|| = ||R||.
	n := qr.qr.mat.Cols
	work := make([]float64, 3*n)
	iwork := make([]int, n)
	r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper)
	v := lapack64.Trcon(matrix.CondNorm, r.mat, work, iwork)
	qr.cond = 1 / v
}

// Factorize computes the QR factorization of an m×n matrix a where m >= n. The QR
// factorization always exists even if A is singular.
//
// The QR decomposition is a factorization of the matrix A such that A = Q * R.
// The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix.
// Q and R can be extracted from the QFromQR and RFromQR methods on Dense.
func (qr *QR) Factorize(a Matrix) {
	m, n := a.Dims()
	if m < n {
		panic(matrix.ErrShape)
	}
	k := min(m, n)
	if qr.qr == nil {
		qr.qr = &Dense{}
	}
	qr.qr.Clone(a)
	work := make([]float64, 1)
	qr.tau = make([]float64, k)
	lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1)

	work = make([]float64, int(work[0]))
	lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work))
	qr.updateCond()
}

// TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal
// and upper triangular matrices.

// RFromQR extracts the m×n upper trapezoidal matrix from a QR decomposition.
func (m *Dense) RFromQR(qr *QR) {
	r, c := qr.qr.Dims()
	m.reuseAs(r, c)

	// Disguise the QR as an upper triangular
	t := &TriDense{
		mat: blas64.Triangular{
			N:      c,
			Stride: qr.qr.mat.Stride,
			Data:   qr.qr.mat.Data,
			Uplo:   blas.Upper,
			Diag:   blas.NonUnit,
		},
		cap: qr.qr.capCols,
	}
	m.Copy(t)

	// Zero below the triangular.
	for i := r; i < c; i++ {
		zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c])
	}
}

// QFromQR extracts the m×m orthonormal matrix Q from a QR decomposition.
func (m *Dense) QFromQR(qr *QR) {
	r, c := qr.qr.Dims()
	m.reuseAs(r, r)

	// Set Q = I.
	for i := 0; i < r; i++ {
		v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+r]
		zero(v)
		v[i] = 1
	}

	// Construct Q from the elementary reflectors.
	h := blas64.General{
		Rows:   r,
		Cols:   r,
		Stride: r,
		Data:   make([]float64, r*r),
	}
	qCopy := getWorkspace(r, r, false)
	v := blas64.Vector{
		Inc:  1,
		Data: make([]float64, r),
	}
	for i := 0; i < c; i++ {
		// Set h = I.
		zero(h.Data)
		for j := 0; j < len(h.Data); j += r + 1 {
			h.Data[j] = 1
		}

		// Set the vector data as the elementary reflector.
		for j := 0; j < i; j++ {
			v.Data[j] = 0
		}
		v.Data[i] = 1
		for j := i + 1; j < r; j++ {
			v.Data[j] = qr.qr.mat.Data[j*qr.qr.mat.Stride+i]
		}

		// Compute the multiplication matrix.
		blas64.Ger(-qr.tau[i], v, v, h)
		qCopy.Copy(m)
		blas64.Gemm(blas.NoTrans, blas.NoTrans,
			1, qCopy.mat, h,
			0, m.mat)
	}
}

// SolveQR solves a minimum-norm solution to a system of linear equations defined
// by the matrices A and b, where A is an m×n matrix represented in its QR factorized
// form. If A is singular or near-singular a Condition error is returned. Please
// see the documentation for Condition for more information.
//
// The minimization problem solved depends on the input parameters.
//  If trans == false, find X such that ||A*X - b||_2 is minimized.
//  If trans == true, find the minimum norm solution of A^T * X = b.
// The solution matrix, X, is stored in place into the receiver.
func (m *Dense) SolveQR(qr *QR, trans bool, b Matrix) error {
	r, c := qr.qr.Dims()
	br, bc := b.Dims()

	// The QR solve algorithm stores the result in-place into the right hand side.
	// The storage for the answer must be large enough to hold both b and x.
	// However, this method's receiver must be the size of x. Copy b, and then
	// copy the result into m at the end.
	if trans {
		if c != br {
			panic(matrix.ErrShape)
		}
		m.reuseAs(r, bc)
	} else {
		if r != br {
			panic(matrix.ErrShape)
		}
		m.reuseAs(c, bc)
	}
	// Do not need to worry about overlap between m and b because x has its own
	// independent storage.
	x := getWorkspace(max(r, c), bc, false)
	x.Copy(b)
	t := qr.qr.asTriDense(qr.qr.mat.Cols, blas.NonUnit, blas.Upper).mat
	if trans {
		ok := lapack64.Trtrs(blas.Trans, t, x.mat)
		if !ok {
			return matrix.Condition(math.Inf(1))
		}
		for i := c; i < r; i++ {
			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc])
		}
		work := make([]float64, 1)
		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1)
		work = make([]float64, int(work[0]))
		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work))
	} else {
		work := make([]float64, 1)
		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1)
		work = make([]float64, int(work[0]))
		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work))

		ok := lapack64.Trtrs(blas.NoTrans, t, x.mat)
		if !ok {
			return matrix.Condition(math.Inf(1))
		}
	}
	// M was set above to be the correct size for the result.
	m.Copy(x)
	putWorkspace(x)
	if qr.cond > matrix.ConditionTolerance {
		return matrix.Condition(qr.cond)
	}
	return nil
}

// SolveQRVec solves a minimum-norm solution to a system of linear equations.
// Please see Dense.SolveQR for the full documentation.
func (v *Vector) SolveQRVec(qr *QR, trans bool, b *Vector) error {
	r, c := qr.qr.Dims()
	// The Solve implementation is non-trivial, so rather than duplicate the code,
	// instead recast the Vectors as Dense and call the matrix code.
	if trans {
		v.reuseAs(r)
	} else {
		v.reuseAs(c)
	}
	m := vecAsDense(v)
	bm := vecAsDense(b)
	return m.SolveQR(qr, trans, bm)
}

// vecAsDense returns the vector as a Dense matrix with the same underlying data.
func vecAsDense(v *Vector) *Dense {
	return &Dense{
		mat: blas64.General{
			Rows:   v.n,
			Cols:   1,
			Stride: v.mat.Inc,
			Data:   v.mat.Data,
		},
		capRows: v.n,
		capCols: 1,
	}
}
<commit_msg>mat64: clean up comment for Dense.SolveQR and Vector.SolveQRVec<commit_after>// Copyright ©2013 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on the QRDecomposition class from Jama 1.0.3.

package mat64

import (
	"math"

	"github.com/gonum/blas"
	"github.com/gonum/blas/blas64"
	"github.com/gonum/lapack/lapack64"
	"github.com/gonum/matrix"
)

// QR is a type for creating and using the QR factorization of a matrix.
type QR struct {
	qr   *Dense
	tau  []float64
	cond float64
}

func (qr *QR) updateCond() {
	// A = QR, where Q is orthonormal. Orthonormal multiplications do not change
	// the condition number. Thus, ||A|| = ||Q|| ||R|| = ||R||.
	n := qr.qr.mat.Cols
	work := make([]float64, 3*n)
	iwork := make([]int, n)
	r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper)
	v := lapack64.Trcon(matrix.CondNorm, r.mat, work, iwork)
	qr.cond = 1 / v
}

// Factorize computes the QR factorization of an m×n matrix a where m >= n. The QR
// factorization always exists even if A is singular.
//
// The QR decomposition is a factorization of the matrix A such that A = Q * R.
// The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix.
// Q and R can be extracted from the QFromQR and RFromQR methods on Dense.
func (qr *QR) Factorize(a Matrix) {
	m, n := a.Dims()
	if m < n {
		panic(matrix.ErrShape)
	}
	k := min(m, n)
	if qr.qr == nil {
		qr.qr = &Dense{}
	}
	qr.qr.Clone(a)
	work := make([]float64, 1)
	qr.tau = make([]float64, k)
	lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1)

	work = make([]float64, int(work[0]))
	lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work))
	qr.updateCond()
}

// TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal
// and upper triangular matrices.

// RFromQR extracts the m×n upper trapezoidal matrix from a QR decomposition.
func (m *Dense) RFromQR(qr *QR) {
	r, c := qr.qr.Dims()
	m.reuseAs(r, c)

	// Disguise the QR as an upper triangular
	t := &TriDense{
		mat: blas64.Triangular{
			N:      c,
			Stride: qr.qr.mat.Stride,
			Data:   qr.qr.mat.Data,
			Uplo:   blas.Upper,
			Diag:   blas.NonUnit,
		},
		cap: qr.qr.capCols,
	}
	m.Copy(t)

	// Zero below the triangular.
	for i := r; i < c; i++ {
		zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c])
	}
}

// QFromQR extracts the m×m orthonormal matrix Q from a QR decomposition.
func (m *Dense) QFromQR(qr *QR) {
	r, c := qr.qr.Dims()
	m.reuseAs(r, r)

	// Set Q = I.
	for i := 0; i < r; i++ {
		v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+r]
		zero(v)
		v[i] = 1
	}

	// Construct Q from the elementary reflectors.
	h := blas64.General{
		Rows:   r,
		Cols:   r,
		Stride: r,
		Data:   make([]float64, r*r),
	}
	qCopy := getWorkspace(r, r, false)
	v := blas64.Vector{
		Inc:  1,
		Data: make([]float64, r),
	}
	for i := 0; i < c; i++ {
		// Set h = I.
		zero(h.Data)
		for j := 0; j < len(h.Data); j += r + 1 {
			h.Data[j] = 1
		}

		// Set the vector data as the elementary reflector.
		for j := 0; j < i; j++ {
			v.Data[j] = 0
		}
		v.Data[i] = 1
		for j := i + 1; j < r; j++ {
			v.Data[j] = qr.qr.mat.Data[j*qr.qr.mat.Stride+i]
		}

		// Compute the multiplication matrix.
		blas64.Ger(-qr.tau[i], v, v, h)
		qCopy.Copy(m)
		blas64.Gemm(blas.NoTrans, blas.NoTrans,
			1, qCopy.mat, h,
			0, m.mat)
	}
}

// SolveQR finds a minimum-norm solution to a system of linear equations defined
// by the matrices A and b, where A is an m×n matrix represented in its QR factorized
// form. If A is singular or near-singular a Condition error is returned. Please
// see the documentation for Condition for more information.
//
// The minimization problem solved depends on the input parameters.
//  If trans == false, find X such that ||A*X - b||_2 is minimized.
//  If trans == true, find the minimum norm solution of A^T * X = b.
// The solution matrix, X, is stored in place into the receiver.
func (m *Dense) SolveQR(qr *QR, trans bool, b Matrix) error {
	r, c := qr.qr.Dims()
	br, bc := b.Dims()

	// The QR solve algorithm stores the result in-place into the right hand side.
	// The storage for the answer must be large enough to hold both b and x.
	// However, this method's receiver must be the size of x. Copy b, and then
	// copy the result into m at the end.
	if trans {
		if c != br {
			panic(matrix.ErrShape)
		}
		m.reuseAs(r, bc)
	} else {
		if r != br {
			panic(matrix.ErrShape)
		}
		m.reuseAs(c, bc)
	}
	// Do not need to worry about overlap between m and b because x has its own
	// independent storage.
	x := getWorkspace(max(r, c), bc, false)
	x.Copy(b)
	t := qr.qr.asTriDense(qr.qr.mat.Cols, blas.NonUnit, blas.Upper).mat
	if trans {
		ok := lapack64.Trtrs(blas.Trans, t, x.mat)
		if !ok {
			return matrix.Condition(math.Inf(1))
		}
		for i := c; i < r; i++ {
			zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc])
		}
		work := make([]float64, 1)
		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1)
		work = make([]float64, int(work[0]))
		lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work))
	} else {
		work := make([]float64, 1)
		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1)
		work = make([]float64, int(work[0]))
		lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work))

		ok := lapack64.Trtrs(blas.NoTrans, t, x.mat)
		if !ok {
			return matrix.Condition(math.Inf(1))
		}
	}
	// M was set above to be the correct size for the result.
	m.Copy(x)
	putWorkspace(x)
	if qr.cond > matrix.ConditionTolerance {
		return matrix.Condition(qr.cond)
	}
	return nil
}

// SolveQRVec finds a minimum-norm solution to a system of linear equations.
// Please see Dense.SolveQR for the full documentation.
func (v *Vector) SolveQRVec(qr *QR, trans bool, b *Vector) error {
	r, c := qr.qr.Dims()
	// The Solve implementation is non-trivial, so rather than duplicate the code,
	// instead recast the Vectors as Dense and call the matrix code.
	if trans {
		v.reuseAs(r)
	} else {
		v.reuseAs(c)
	}
	m := vecAsDense(v)
	bm := vecAsDense(b)
	return m.SolveQR(qr, trans, bm)
}

// vecAsDense returns the vector as a Dense matrix with the same underlying data.
func vecAsDense(v *Vector) *Dense {
	return &Dense{
		mat: blas64.General{
			Rows:   v.n,
			Cols:   1,
			Stride: v.mat.Inc,
			Data:   v.mat.Data,
		},
		capRows: v.n,
		capCols: 1,
	}
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "log"
  "strings"
  "errors"
  "github.com/Jeffail/gabs"
)

// Name
// Traits
// Tags/Groups
type Person struct {
  Name string
  Json *gabs.Container
}

func new_person(name_in string) *Person {
  p := new(Person)
  p.Name = name_in
  jsonObj := gabs.New()
  jsonObj.Set(name_in, "person", "name")
  // jsonObj.Set("c", "person", "traits")
  // jsonObj.ArrayAppend("", "person", "tags")
  jsonObj.Array("person", "tags")
  p.Json = jsonObj
  return p
}

// See about comparing input to what already exists
func (p Person) add_trait(trait_path, trait_name, trait_text string) {
  current_json := p.Json

  // Get the full dotted path to use for all operations
  path := create_path(trait_path, trait_name)

  // 2 situations, the trait already exists or it doesnt
  // If it exists array it (there is a check for the array also)
  // If it doesnt exist add it

  // There are 2 additional situations if the trait exists
  // The array already exists (add to it)
  // The array doesn't already exist (make it and add to it)

  // It it exists, else it does not
  if current_json.ExistsP(path) {

    // Get an error if there is no array
    _, err := current_json.Path(path).Children()

    // If there is an error we need to make the array
    if err != nil {
      // Get the original value (that isnt an array)
      current_val := current_json.Path(path).Data()
      // Create an array
      current_json.ArrayP(path)
      // Add the original value to the array
      current_json.ArrayAppendP(current_val, path)
    }

    // Add the value we had originally wanted to add
    current_json.ArrayAppendP(trait_text, path)
  } else {
    current_json.SetP(trait_text, path)
  }
}

// If the name will be unique it will change
func (p Person) change_name(name string) error {
  if acceptable_person_name(name) {
    p.Name = name
    return nil
  } else {
    return errors.New("This name has been previously assinged, try another.")
  }
}

// This will have some content at some point to ensure uniquity among names
func acceptable_person_name(name string) bool {
  if true != false {
    return true
  } else {
    return false
  }
}

// See about comparing input to what already exists
func (p Person) add_tag(tag_name string) error {
  current_json := p.Json
  if p.acceptable_tag_name(tag_name) {
    current_json.ArrayAppend(tag_name, "person", "tags")
    return nil
  } else {
    return errors.New("This tag has been previously assinged, try another.")
  }

}

// This will have some content at some point to ensure uniquity among tags
func (p Person) acceptable_tag_name(name string) bool {

  tag_set := p.get_person_tags()

  // If the tag is currently associated with the person do not add it again
  // If the statement is true then the tag is associated with the person
  if tag_set[name] == false {
    return true
  } else {
    return false
  }
}

func get_all_people_with_tag(tag_name string) {

}

func (p Person) get_person_tags() map[string]bool {
  // _, err := current_json.Path(path).Children()
  current_json := p.Json
  tags := make(map[string]bool)
  children, err := current_json.Path("person.tags").Children()
  check_err(err)
  for _, child := range children {
  	tags[child.Data().(string)] = true
  }
  return tags
}

func (p Person) get_person_trails() {
  children, err := p.Json.S("tags").ChildrenMap()
  check_err(err)
  for key, child := range children {
  	fmt.Printf("key: %v, value: %v\n", key, child.Data().(string))
  }
}

func (p Person) t_delete_trait(trait_name string) {
  err := p.Json.DeleteP("person.traits.relative")
  check_err(err)
}

func main() {

  traits_path := "person.traits"

  p1 := new_person("ben")
  p1.add_tag("friend")
  p1.add_tag("geog 1000")

  p2 := new_person("steve")
  p2.add_trait(traits_path, "relative.brother", "uno")
  // p2.add_trait(traits_path, "relative.sister", "dos")
  p2.add_trait(traits_path, "relative.brother", "tres")
  p2.add_trait(traits_path, "relative.brother", "quad")
  p2.add_trait(traits_path, "location.current", "md")

  p1.add_tag("dog person")
  p1.add_tag("cat person")
  p1.add_tag("cat person")
  //p2.add_trait(traits_path, "relative", "tre")

  // fmt.Println(p2.Json.ExistsP("person.traits.relative"))

  // p2.t_delete_trait("bob")

  // fmt.Println(p1.Name, "->", p2.Name)
  fmt.Println(p1.Json.String())
  fmt.Println(p2.Json.String())
  //
  //
  //
  // p2.get_person_trails()

}

// Support methods

// Import people json objects from a file
func import_people_from_file() {

}

// Export people json objects to a file
func export_people_to_file() {

}

// Create a path to a particular location within the json
func create_path(path, addition string) string {
  if !strings.HasSuffix(path, ".") {
    path = path + "."
  }
  if strings.HasPrefix(addition, ".") {
    addition = addition[1:]
  }
  return (path + addition)
}

// Break if there is an error passed in
func check_err(err error) {
  if err != nil {
    log.Fatal(err)
  }
}
<commit_msg>Investigate storage<commit_after>package main

import (
  "fmt"
  "log"
  "strings"
  "errors"
  "github.com/Jeffail/gabs"
)

// Name
// Traits
// Tags/Groups
type Person struct {
  Name string
  Json *gabs.Container
}

var (
  people_map = make(map[string]Person)
)

func new_person(name_in string) *Person {
  p := new(Person)
  p.Name = name_in
  jsonObj := gabs.New()
  jsonObj.Set(name_in, "person", "name")
  // jsonObj.Set("c", "person", "traits")
  // jsonObj.ArrayAppend("", "person", "tags")
  jsonObj.Array("person", "tags")
  p.Json = jsonObj
  return p
}

// See about comparing input to what already exists
func (p Person) add_trait(trait_path, trait_name, trait_text string) {
  current_json := p.Json

  // Get the full dotted path to use for all operations
  path := create_path(trait_path, trait_name)

  // 2 situations, the trait already exists or it doesnt
  // If it exists array it (there is a check for the array also)
  // If it doesnt exist add it

  // There are 2 additional situations if the trait exists
  // The array already exists (add to it)
  // The array doesn't already exist (make it and add to it)

  // It it exists, else it does not
  if current_json.ExistsP(path) {

    // Get an error if there is no array
    _, err := current_json.Path(path).Children()

    // If there is an error we need to make the array
    if err != nil {
      // Get the original value (that isnt an array)
      current_val := current_json.Path(path).Data()
      // Create an array
      current_json.ArrayP(path)
      // Add the original value to the array
      current_json.ArrayAppendP(current_val, path)
    }

    // Add the value we had originally wanted to add
    current_json.ArrayAppendP(trait_text, path)
  } else {
    current_json.SetP(trait_text, path)
  }
}

// If the name will be unique it will change
func (p Person) change_name(name string) error {
  if acceptable_person_name(name) {
    p.Name = name
    return nil
  } else {
    return errors.New("This name has been previously assinged, try another.")
  }
}

// This will have some content at some point to ensure uniquity among names
func acceptable_person_name(name string) bool {
  if true != false {
    return true
  } else {
    return false
  }
}

// See about comparing input to what already exists
func (p Person) add_tag(tag_name string) error {
  current_json := p.Json
  if p.acceptable_tag_name(tag_name) {
    current_json.ArrayAppend(tag_name, "person", "tags")
    return nil
  } else {
    return errors.New("This tag has been previously assinged, try another.")
  }

}

// This will have some content at some point to ensure uniquity among tags
func (p Person) acceptable_tag_name(name string) bool {

  tag_set := p.get_person_tags()

  // If the tag is currently associated with the person do not add it again
  // If the statement is true then the tag is associated with the person
  if tag_set[name] == false {
    return true
  } else {
    return false
  }
}

func get_all_people_with_tag(tag_name string) {

}

func (p Person) get_person_tags() map[string]bool {
  // _, err := current_json.Path(path).Children()
  current_json := p.Json
  tags := make(map[string]bool)
  children, err := current_json.Path("person.tags").Children()
  check_err(err)
  for _, child := range children {
  	tags[child.Data().(string)] = true
  }
  return tags
}

func (p Person) get_person_trails() {
  children, err := p.Json.S("tags").ChildrenMap()
  check_err(err)
  for key, child := range children {
  	fmt.Printf("key: %v, value: %v\n", key, child.Data().(string))
  }
}

func (p Person) get_name() string {
  return p.Json.Path("person.name").Data().(string)
}

// This may be un-needed and we may just store directly to map
// More investigation is required
func (p Person) add_to_people_map() {
  if _, exists := people_map[p.get_name()]; !exists {
    people_map[p.get_name()] = p
  }
}

func (p Person) t_delete_trait(trait_name string) {
  err := p.Json.DeleteP("person.traits.relative")
  check_err(err)
}

func main() {

  traits_path := "person.traits"

  p1 := new_person("ben")
  p1.add_tag("friend")
  p1.add_tag("geog 1000")

  p2 := new_person("steve")
  p2.add_trait(traits_path, "relative.brother", "uno")
  // p2.add_trait(traits_path, "relative.sister", "dos")
  p2.add_trait(traits_path, "relative.brother", "tres")
  p2.add_trait(traits_path, "relative.brother", "quad")
  p2.add_trait(traits_path, "location.current", "md")

  p1.add_tag("dog person")
  p1.add_tag("cat person")
  p1.add_tag("cat person")
  //p2.add_trait(traits_path, "relative", "tre")

  // fmt.Println(p2.Json.ExistsP("person.traits.relative"))

  // p2.t_delete_trait("bob")

  // fmt.Println(p1.Name, "->", p2.Name)
  fmt.Println(p1.Json.String())
  fmt.Println(p2.Json.String())
  //
  //
  //
  // p2.get_person_trails()
  p1.add_to_people_map()

}

// Support methods

// Import people json objects from a file
func import_people_from_file() {

}

// Export people json objects to a file
func export_people_to_file() {

}

// Create a path to a particular location within the json
func create_path(path, addition string) string {
  if !strings.HasSuffix(path, ".") {
    path = path + "."
  }
  if strings.HasPrefix(addition, ".") {
    addition = addition[1:]
  }
  return (path + addition)
}

// Break if there is an error passed in
func check_err(err error) {
  if err != nil {
    log.Fatal(err)
  }
}
<|endoftext|>


<commit_before>package rps

import (
	"math/rand"
	"testing"
	"time"
)

func TestRandomHand(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	if v := RandomHand(); v > 2 || v < 0 {
		t.Error("expected an int value between 0 and 2, got", v)
	}
}

func TestPlay(t *testing.T) {
	var testcases = []struct {
		p1, p2   int
		expected int
	}{
		// tie
		{Rock, Rock, Tie},
		{Paper, Paper, Tie},
		{Scissors, Scissors, Tie},

		// p1 wins
		{Rock, Scissors, WinP1},
		{Paper, Rock, WinP1},
		{Scissors, Paper, WinP1},

		// p2 wins
		{Rock, Paper, WinP2},
		{Paper, Scissors, WinP2},
		{Scissors, Rock, WinP2},
	}

	for _, c := range testcases {
		r := Play(c.p1, c.p2)
		if r != c.expected {
			t.Errorf("expected: %v, got: %v", c.expected, r)
		}
	}
}
<commit_msg>Move rand.Seed() to init()<commit_after>package rps

import (
	"math/rand"
	"testing"
	"time"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func TestRandomHand(t *testing.T) {
	if v := RandomHand(); v > 2 || v < 0 {
		t.Error("expected an int value between 0 and 2, got", v)
	}
}

func TestPlay(t *testing.T) {
	var testcases = []struct {
		p1, p2   int
		expected int
	}{
		// tie
		{Rock, Rock, Tie},
		{Paper, Paper, Tie},
		{Scissors, Scissors, Tie},

		// p1 wins
		{Rock, Scissors, WinP1},
		{Paper, Rock, WinP1},
		{Scissors, Paper, WinP1},

		// p2 wins
		{Rock, Paper, WinP2},
		{Paper, Scissors, WinP2},
		{Scissors, Rock, WinP2},
	}

	for _, c := range testcases {
		r := Play(c.p1, c.p2)
		if r != c.expected {
			t.Errorf("expected: %v, got: %v", c.expected, r)
		}
	}
}
<|endoftext|>


<commit_before>// This is a library to manage Microchip MCP23008 This chip is used on onion.io Omega2 relay expension
package mcp23008

import (
	"golang.org/x/exp/io/i2c"
	"math"
)

const (
	iodirReg 	= 0x00
	ipolReg     = 0x01
	gpintenReg  = 0x02
	defvalReg   = 0x03
	intconReg   = 0x04
	ioconReg    = 0x05
	gppuReg  	= 0x06
	intfReg     = 0x07
	intcapReg   = 0x08
	gpioReg     = 0x09
	olatReg     = 0x0A
)

// McpInit function initialize MCP28003 after boot or restart of device
func McpInit(d *i2c.Device) error {
	// SetAllDirection
	err := d.WriteReg(iodirReg, []byte{0})
	if err != nil {
		return err
	}

	// SetAllPullUp
	err = d.WriteReg(gppuReg, []byte{0})
	return err
}

// McpGpioToggle change state of selected GPIO other one are unchanged
func McpGpioToggle(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write ON to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg,[]byte{regValue[0] ^ mask})
}

// McpGpioOn set GPIO to ON/High state other one are unchanged
func McpGpioOn(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write ON to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg,[]byte{mask | regValue[0]})
}

// Set all GPIO to ON/High state
func McpGpioAllOn(d *i2c.Device) {
	// Write ON to all GPIO
	d.WriteReg(gpioReg,[]byte{0xf})
}

// McpGpioOff set GPIO to OFF/Low state other one are unchanged
func McpGpioOff(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 0 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio))) ^ 0xf

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write OFF to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg,[]byte{mask & regValue[0]})
}

// Set all GPIO to OFF/Low state
func McpGpioAllOff(d *i2c.Device) {
	// Write ON to all GPIO
	d.WriteReg(gpioReg,[]byte{0x0})
}

// This function return state of selected GPIO 1 for ON/High or 0 for OFF/Low state
func McpReadGpio(d *i2c.Device, gpio byte) byte {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	d.ReadReg(gpioReg, regValue)
	return (regValue[0] & mask) >> gpio
}
<commit_msg>Update name function refactoring Create type Mcp23008 Create New function Update Init function to open device<commit_after>// This is a library to manage Microchip MCP23008 This chip is used on onion.io Omega2 relay expension
package mcp23008

import (
	"golang.org/x/exp/io/i2c"
	"math"
)

type Mcp23008 struct {
	Device      *i2c.Device
	Name        string `json:"name"`
	Address     int    `json:"address"`
	Count       byte   `json:"count"`
	Description string `json:"description"`
	Gpios       []int8 `json:"gpios"` //Using int8 array instead byte for enconding with json.Marshall....
}

const (
	iodirReg   = 0x00
	ipolReg    = 0x01
	gpintenReg = 0x02
	defvalReg  = 0x03
	intconReg  = 0x04
	ioconReg   = 0x05
	gppuReg    = 0x06
	intfReg    = 0x07
	intcapReg  = 0x08
	gpioReg    = 0x09
	olatReg    = 0x0A
)

func New(device string, name string, address int, count byte, description string) (Mcp23008, error) {
	var err error
	module := Mcp23008{nil, name, address, count, description, nil}
	if count < 1 && count > 8 {
		count = 8
	}
	if device != "" {
		err = Init(device, module.Address, &module)
	}
	return module, err
}

// Init function initialize MCP28003 after boot or restart of device
func Init(device string, add int, module *Mcp23008) error {

	var err error

	module.Device, err = i2c.Open(&i2c.Devfs{Dev: device}, add)
	if err != nil {
		module.Device = nil
		return err
	}

	if module.Count > 0 && module.Count <= 8 {
		module.Gpios = make([]int8, module.Count)
		for g := range module.Gpios {
			module.Gpios[g] = int8(McpReadGpio(module.Device, byte(g)))
		}
	}

	// SetAllDirection
	err = module.Device.WriteReg(iodirReg, []byte{0})
	if err != nil {
		return err
	}

	// SetAllPullUp
	err = module.Device.WriteReg(gppuReg, []byte{0})
	return err
}

// McpGpioToggle change state of selected GPIO other one are unchanged
func McpGpioToggle(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write ON to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg, []byte{regValue[0] ^ mask})
}

// McpGpioOn set GPIO to ON/High state other one are unchanged
func McpGpioOn(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write ON to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg, []byte{mask | regValue[0]})
}

// Set all GPIO to ON/High state
func McpGpioAllOn(d *i2c.Device) {
	// Write ON to all GPIO
	d.WriteReg(gpioReg, []byte{0xf})
}

// McpGpioOff set GPIO to OFF/Low state other one are unchanged
func McpGpioOff(d *i2c.Device, gpio byte) {
	regValue := []byte{0}

	// Set 0 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio))) ^ 0xf

	// Read current state of all GPIO's
	d.ReadReg(gpioReg, regValue)

	// Write OFF to selected GPIO other one keep unchanged
	d.WriteReg(gpioReg, []byte{mask & regValue[0]})
}

// Set all GPIO to OFF/Low state
func McpGpioAllOff(d *i2c.Device) {
	// Write ON to all GPIO
	d.WriteReg(gpioReg, []byte{0x0})
}

// This function return state of selected GPIO 1 for ON/High or 0 for OFF/Low state
func McpReadGpio(d *i2c.Device, gpio byte) byte {
	regValue := []byte{0}

	// Set 1 to corresponding BIT of GPIO
	mask := byte(math.Pow(2, float64(gpio)))

	d.ReadReg(gpioReg, regValue)
	return (regValue[0] & mask) >> gpio
}
<|endoftext|>


<commit_before>// +build mage

package main

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps
	"github.com/magefile/mage/sh" // mg contains helpful utility functions, like Deps
)

const WORK_DIR = "./sparta"

var header = strings.Repeat("-", 80)

var ignoreSubdirectoryPaths = []string{
	".vendor",
	".sparta",
	".vscode",
	"/resources/describe",
}

// Default target to run when none is specified
// If not set, running mage will list available targets
// var Default = Build

func mageScript(commands [][]string) error {
	for _, eachCommand := range commands {
		var commandErr error
		if len(eachCommand) <= 1 {
			commandErr = sh.Run(eachCommand[0])
		} else {
			commandErr = sh.Run(eachCommand[0], eachCommand[1:]...)
		}
		if commandErr != nil {
			return commandErr
		}
	}
	return nil
}
func mageLog(formatSpecifier string, args ...interface{}) {
	if mg.Verbose() {
		if len(args) != 0 {
			log.Printf(formatSpecifier, args...)
		} else {
			log.Printf(formatSpecifier)
		}
	}
}

func sourceFilesOfType(extension string) ([]string, error) {
	testExtension := strings.TrimPrefix(extension, ".")
	testExtension = fmt.Sprintf(".%s", testExtension)

	files := make([]string, 0)
	walker := func(path string, info os.FileInfo, err error) error {
		contains := false
		for _, eachComponent := range ignoreSubdirectoryPaths {
			contains = strings.Contains(path, eachComponent)
			if contains {
				break
			}
		}
		if !contains && (filepath.Ext(path) == testExtension) {
			files = append(files, path)
		}
		return nil
	}
	goSourceFilesErr := filepath.Walk(".", walker)
	return files, goSourceFilesErr
}

func applyToSource(fileExtension string, commandParts ...string) error {
	if len(commandParts) <= 0 {
		return errors.New("applyToSource requires a command to apply to source files")
	}
	eligibleSourceFiles, eligibleSourceFilesErr := sourceFilesOfType(fileExtension)
	if eligibleSourceFilesErr != nil {
		return eligibleSourceFilesErr
	}

	mageLog(header)
	mageLog("Applying `%s` to %d `*.%s` source files", commandParts[0], len(eligibleSourceFiles), fileExtension)
	mageLog(header)

	commandArgs := []string{}
	if len(commandParts) > 1 {
		for _, eachPart := range commandParts[1:] {
			commandArgs = append(commandArgs, eachPart)
		}
	}
	for _, eachFile := range eligibleSourceFiles {
		applyArgs := append(commandArgs, eachFile)
		applyErr := sh.Run(commandParts[0], applyArgs...)
		if applyErr != nil {
			return applyErr
		}
	}
	return nil
}

func markdownSourceApply(commandParts ...string) error {
	return applyToSource("md", commandParts...)
}
func goSourceApply(commandParts ...string) error {
	return applyToSource("go", commandParts...)
}

// GenerateBuildInfo creates the automatic buildinfo.go file so that we can
// stamp the SHA into the binaries we build...
func GenerateBuildInfo() error {
	// The first thing we need is the `git` SHA
	cmd := exec.Command("git", "rev-parse", "HEAD")
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		return err
	}
	stdOutResult := strings.TrimSpace(string(stdout.Bytes()))

	// Super = update the buildinfo data
	buildInfoTemplate := `package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: %s

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "%s"
`
	updatedInfo := fmt.Sprintf(buildInfoTemplate, time.Now().UTC(), stdOutResult)
	// Write it to the output location...
	return ioutil.WriteFile("./buildinfo.go", []byte(updatedInfo), os.ModePerm)
}

// GenerateConstants runs the set of commands that update the embedded CONSTANTS
// for both local and AWS Lambda execution
func GenerateConstants() error {
	generateCommands := [][]string{
		// Create the embedded version
		{"go", "run", "$GOPATH/src/github.com/mjibson/esc/main.go", "-o", "./CONSTANTS.go", "-private", "-pkg", "sparta", "./resources"},
		//Create a secondary CONSTANTS_AWSBINARY.go file with empty content.
		{"go", "run", "$GOPATH/src/github.com/mjibson/esc/main.go", "-o", "./CONSTANTS_AWSBINARY.go", "-private", "-pkg", "sparta", "./resources/awsbinary/README.md"},
		//The next step will insert the
		// build tags at the head of each file so that they are mutually exclusive
		{"go", "run", "./cmd/insertTags/main.go", "./CONSTANTS", "!lambdabinary"},
		{"go", "run", "./cmd/insertTags/main.go", "./CONSTANTS_AWSBINARY", "lambdabinary"},
		{"git", "commit", "-a", "-m", "Autogenerated constants"},
	}
	return mageScript(generateCommands)
}

// InstallBuildRequirements installs or updates the dependent
// packages that aren't referenced by the source, but are needed
// to build the Sparta source
func InstallBuildRequirements() error {
	mageLog("`go get` update flags (env.GO_GET_FLAG): %s", os.Getenv("GO_GET_FLAG"))

	requirements := []string{
		"github.com/golang/dep/...",
		"honnef.co/go/tools/cmd/megacheck",
		"honnef.co/go/tools/cmd/gosimple",
		"honnef.co/go/tools/cmd/unused",
		"honnef.co/go/tools/cmd/staticcheck",
		"golang.org/x/tools/cmd/goimports",
		"github.com/fzipp/gocyclo",
		"github.com/golang/lint/golint",
		"github.com/mjibson/esc",
		"github.com/securego/gosec/cmd/gosec/...",
		"github.com/client9/misspell/cmd/misspell",
	}
	for _, eachDep := range requirements {
		cmdErr := sh.Run("go",
			"get",
			os.Getenv("GO_GET_FLAG"),
			eachDep)

		// cmdErr := exec.Command(.Run()
		if cmdErr != nil {
			return cmdErr
		}
	}
	return nil
}

// EnsureSpelling ensures that there are no misspellings in the source
func EnsureSpelling() error {
	goSpelling := func() error {
		return goSourceApply("misspell", "-error")
	}
	mdSpelling := func() error {
		return markdownSourceApply("misspell", "-error")
	}
	mg.SerialDeps(
		goSpelling,
		mdSpelling)
	return nil
}

// EnsureVet ensures that the source has been `go vet`ted
func EnsureVet() error {
	return goSourceApply("go", "tool", "vet")
}

// EnsureLint ensures that the source is `golint`ed
func EnsureLint() error {
	return goSourceApply("golint")
}

// EnsureFormatted ensures that the source code is formatted with goimports
func EnsureFormatted() error {
	return goSourceApply("goimports", "-d")
}

// EnsureStaticChecks ensures that the source code passes static code checks
func EnsureStaticChecks() error {
	// Megacheck
	megacheckErr := sh.Run("megacheck",
		"-ignore",
		"github.com/mweagle/Sparta/CONSTANTS.go:*")
	if megacheckErr != nil {
		return megacheckErr
	}
	// Gosec
	return sh.Run("gosec",
		"-exclude=G204,G505,G401",
		"./...")
}

// EnsureAllPreconditions ensures that the source passes *ALL* static `ensure*`
// precondition steps
func EnsureAllPreconditions() error {
	mg.SerialDeps(
		InstallBuildRequirements,
		EnsureVet,
		EnsureLint,
		EnsureFormatted,
		EnsureStaticChecks,
		EnsureSpelling,
	)
	return nil
}

// EnsureTravisBuildEnvironment is the command that sets up the Travis
// environment to run the build.
func EnsureTravisBuildEnvironment() error {
	mg.SerialDeps(InstallBuildRequirements)

	// Super run some commands
	travisComands := [][]string{
		[]string{"dep", "version"},
		[]string{"dep", "ensure"},
		[]string{"rsync", "-a", "--quiet", "--remove-source-files", "./vendor/", "$GOPATH/src"},
	}
	return mageScript(travisComands)
}

// Build the application
func Build() error {
	mg.Deps(EnsureAllPreconditions)
	return sh.Run("go", "build", ".")
}

// Clean the working directory
func Clean() error {
	cleanCommands := [][]string{
		[]string{"go", "clean", "."},
		[]string{"rm", "-rf", "./graph.html"},
		[]string{"rsync", "-a", "--quiet", "--remove-source-files", "./vendor/", "$GOPATH/src"},
	}
	return mageScript(cleanCommands)
}

// Describe runs the `TestDescribe` test to generate a describe HTML output
// file at graph.html
func Describe() error {
	describeCommands := [][]string{
		[]string{"rm", "-rf", "./graph.html"},
		[]string{"go", "test", "-v", "-run", "TestDescribe"},
	}
	return mageScript(describeCommands)
}

// Publish the latest source
func Publish() error {
	mg.SerialDeps(GenerateBuildInfo)

	describeCommands := [][]string{
		[]string{"echo", "Checking `git` tree status"},
		[]string{"git", "diff", "--exit-code"},
		// TODO - migrate to Go
		[]string{"./buildinfo.sh"},
		[]string{"git", "commit", "-a", "-m", "Tagging Sparta commit"},
		[]string{"git", "push", "origin"},
	}
	return mageScript(describeCommands)
}

// Test runs the Sparta tests
func Test() {
	testCommand := func() error {
		return sh.Run("go",
			"test",
			"-cover",
			"-race",
			"./...")
	}
	mg.SerialDeps(
		EnsureAllPreconditions,
		testCommand,
	)
}

// TestCover runs the test and opens up the resulting report
func TestCover() error {
	// mg.SerialDeps(
	// 	EnsureAllPreconditions,
	// )
	coverageReport := fmt.Sprintf("%s/cover.out", WORK_DIR)
	testCoverCommands := [][]string{
		[]string{"go", "test", fmt.Sprintf("-coverprofile=%s", coverageReport), "."},
		[]string{"go", "tool", "cover", fmt.Sprintf("-html=%s", coverageReport)},
		[]string{"rm", coverageReport},
		[]string{"open", fmt.Sprintf("%s/cover.html", WORK_DIR)},
	}
	return mageScript(testCoverCommands)
}

// TravisBuild is the task to build in the context of a Travis CI pipeline
func TravisBuild() error {
	mg.SerialDeps(EnsureTravisBuildEnvironment,
		Build,
		Test)
	return nil
}
<commit_msg>Update magefile to pass `mage test`<commit_after>// +build mage

package main

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps
	"github.com/magefile/mage/sh" // mg contains helpful utility functions, like Deps
)

const localWorkDir = "./sparta"

var header = strings.Repeat("-", 80)

var ignoreSubdirectoryPaths = []string{
	".vendor",
	".sparta",
	".vscode",
	"/resources/describe",
}

// Default target to run when none is specified
// If not set, running mage will list available targets
// var Default = Build

func mageScript(commands [][]string) error {
	for _, eachCommand := range commands {
		var commandErr error
		if len(eachCommand) <= 1 {
			commandErr = sh.Run(eachCommand[0])
		} else {
			commandErr = sh.Run(eachCommand[0], eachCommand[1:]...)
		}
		if commandErr != nil {
			return commandErr
		}
	}
	return nil
}
func mageLog(formatSpecifier string, args ...interface{}) {
	if mg.Verbose() {
		if len(args) != 0 {
			log.Printf(formatSpecifier, args...)
		} else {
			log.Printf(formatSpecifier)
		}
	}
}

func sourceFilesOfType(extension string) ([]string, error) {
	testExtension := strings.TrimPrefix(extension, ".")
	testExtension = fmt.Sprintf(".%s", testExtension)

	files := make([]string, 0)
	walker := func(path string, info os.FileInfo, err error) error {
		contains := false
		for _, eachComponent := range ignoreSubdirectoryPaths {
			contains = strings.Contains(path, eachComponent)
			if contains {
				break
			}
		}
		if !contains && (filepath.Ext(path) == testExtension) {
			files = append(files, path)
		}
		return nil
	}
	goSourceFilesErr := filepath.Walk(".", walker)
	return files, goSourceFilesErr
}

func applyToSource(fileExtension string, commandParts ...string) error {
	if len(commandParts) <= 0 {
		return errors.New("applyToSource requires a command to apply to source files")
	}
	eligibleSourceFiles, eligibleSourceFilesErr := sourceFilesOfType(fileExtension)
	if eligibleSourceFilesErr != nil {
		return eligibleSourceFilesErr
	}

	mageLog(header)
	mageLog("Applying `%s` to %d `*.%s` source files", commandParts[0], len(eligibleSourceFiles), fileExtension)
	mageLog(header)

	commandArgs := []string{}
	if len(commandParts) > 1 {
		for _, eachPart := range commandParts[1:] {
			commandArgs = append(commandArgs, eachPart)
		}
	}
	for _, eachFile := range eligibleSourceFiles {
		applyArgs := append(commandArgs, eachFile)
		applyErr := sh.Run(commandParts[0], applyArgs...)
		if applyErr != nil {
			return applyErr
		}
	}
	return nil
}

func markdownSourceApply(commandParts ...string) error {
	return applyToSource("md", commandParts...)
}
func goSourceApply(commandParts ...string) error {
	return applyToSource("go", commandParts...)
}

// GenerateBuildInfo creates the automatic buildinfo.go file so that we can
// stamp the SHA into the binaries we build...
func GenerateBuildInfo() error {
	// The first thing we need is the `git` SHA
	cmd := exec.Command("git", "rev-parse", "HEAD")
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		return err
	}
	stdOutResult := strings.TrimSpace(string(stdout.Bytes()))

	// Super = update the buildinfo data
	buildInfoTemplate := `package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: %s

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "%s"
`
	updatedInfo := fmt.Sprintf(buildInfoTemplate, time.Now().UTC(), stdOutResult)
	// Write it to the output location...
	return ioutil.WriteFile("./buildinfo.go", []byte(updatedInfo), os.ModePerm)
}

// GenerateConstants runs the set of commands that update the embedded CONSTANTS
// for both local and AWS Lambda execution
func GenerateConstants() error {
	generateCommands := [][]string{
		// Create the embedded version
		{"go", "run", "$GOPATH/src/github.com/mjibson/esc/main.go", "-o", "./CONSTANTS.go", "-private", "-pkg", "sparta", "./resources"},
		//Create a secondary CONSTANTS_AWSBINARY.go file with empty content.
		{"go", "run", "$GOPATH/src/github.com/mjibson/esc/main.go", "-o", "./CONSTANTS_AWSBINARY.go", "-private", "-pkg", "sparta", "./resources/awsbinary/README.md"},
		//The next step will insert the
		// build tags at the head of each file so that they are mutually exclusive
		{"go", "run", "./cmd/insertTags/main.go", "./CONSTANTS", "!lambdabinary"},
		{"go", "run", "./cmd/insertTags/main.go", "./CONSTANTS_AWSBINARY", "lambdabinary"},
		{"git", "commit", "-a", "-m", "Autogenerated constants"},
	}
	return mageScript(generateCommands)
}

// InstallBuildRequirements installs or updates the dependent
// packages that aren't referenced by the source, but are needed
// to build the Sparta source
func InstallBuildRequirements() error {
	mageLog("`go get` update flags (env.GO_GET_FLAG): %s", os.Getenv("GO_GET_FLAG"))

	requirements := []string{
		"github.com/golang/dep/...",
		"honnef.co/go/tools/cmd/megacheck",
		"honnef.co/go/tools/cmd/gosimple",
		"honnef.co/go/tools/cmd/unused",
		"honnef.co/go/tools/cmd/staticcheck",
		"golang.org/x/tools/cmd/goimports",
		"github.com/fzipp/gocyclo",
		"github.com/golang/lint/golint",
		"github.com/mjibson/esc",
		"github.com/securego/gosec/cmd/gosec/...",
		"github.com/client9/misspell/cmd/misspell",
	}
	for _, eachDep := range requirements {
		cmdErr := sh.Run("go",
			"get",
			os.Getenv("GO_GET_FLAG"),
			eachDep)

		// cmdErr := exec.Command(.Run()
		if cmdErr != nil {
			return cmdErr
		}
	}
	return nil
}

// EnsureSpelling ensures that there are no misspellings in the source
func EnsureSpelling() error {
	goSpelling := func() error {
		return goSourceApply("misspell", "-error")
	}
	mdSpelling := func() error {
		return markdownSourceApply("misspell", "-error")
	}
	mg.SerialDeps(
		goSpelling,
		mdSpelling)
	return nil
}

// EnsureVet ensures that the source has been `go vet`ted
func EnsureVet() error {
	return goSourceApply("go", "tool", "vet")
}

// EnsureLint ensures that the source is `golint`ed
func EnsureLint() error {
	return goSourceApply("golint")
}

// EnsureFormatted ensures that the source code is formatted with goimports
func EnsureFormatted() error {
	return goSourceApply("goimports", "-d")
}

// EnsureStaticChecks ensures that the source code passes static code checks
func EnsureStaticChecks() error {
	// Megacheck
	megacheckErr := sh.Run("megacheck",
		"-ignore",
		"github.com/mweagle/Sparta/CONSTANTS.go:*")
	if megacheckErr != nil {
		return megacheckErr
	}
	// Gosec
	return sh.Run("gosec",
		"-exclude=G204,G505,G401",
		"./...")
}

// EnsureAllPreconditions ensures that the source passes *ALL* static `ensure*`
// precondition steps
func EnsureAllPreconditions() error {
	mg.SerialDeps(
		InstallBuildRequirements,
		EnsureVet,
		EnsureLint,
		EnsureFormatted,
		EnsureStaticChecks,
		EnsureSpelling,
	)
	return nil
}

// EnsureTravisBuildEnvironment is the command that sets up the Travis
// environment to run the build.
func EnsureTravisBuildEnvironment() error {
	mg.SerialDeps(InstallBuildRequirements)

	// Super run some commands
	travisComands := [][]string{
		[]string{"dep", "version"},
		[]string{"dep", "ensure"},
		[]string{"rsync", "-a", "--quiet", "--remove-source-files", "./vendor/", "$GOPATH/src"},
	}
	return mageScript(travisComands)
}

// Build the application
func Build() error {
	mg.Deps(EnsureAllPreconditions)
	return sh.Run("go", "build", ".")
}

// Clean the working directory
func Clean() error {
	cleanCommands := [][]string{
		[]string{"go", "clean", "."},
		[]string{"rm", "-rf", "./graph.html"},
		[]string{"rsync", "-a", "--quiet", "--remove-source-files", "./vendor/", "$GOPATH/src"},
	}
	return mageScript(cleanCommands)
}

// Describe runs the `TestDescribe` test to generate a describe HTML output
// file at graph.html
func Describe() error {
	describeCommands := [][]string{
		[]string{"rm", "-rf", "./graph.html"},
		[]string{"go", "test", "-v", "-run", "TestDescribe"},
	}
	return mageScript(describeCommands)
}

// Publish the latest source
func Publish() error {
	mg.SerialDeps(GenerateBuildInfo)

	describeCommands := [][]string{
		[]string{"echo", "Checking `git` tree status"},
		[]string{"git", "diff", "--exit-code"},
		// TODO - migrate to Go
		[]string{"./buildinfo.sh"},
		[]string{"git", "commit", "-a", "-m", "Tagging Sparta commit"},
		[]string{"git", "push", "origin"},
	}
	return mageScript(describeCommands)
}

// Test runs the Sparta tests
func Test() {
	testCommand := func() error {
		return sh.Run("go",
			"test",
			"-cover",
			"-race",
			"./...")
	}
	mg.SerialDeps(
		EnsureAllPreconditions,
		testCommand,
	)
}

// TestCover runs the test and opens up the resulting report
func TestCover() error {
	// mg.SerialDeps(
	// 	EnsureAllPreconditions,
	// )
	coverageReport := fmt.Sprintf("%s/cover.out", localWorkDir)
	testCoverCommands := [][]string{
		[]string{"go", "test", fmt.Sprintf("-coverprofile=%s", coverageReport), "."},
		[]string{"go", "tool", "cover", fmt.Sprintf("-html=%s", coverageReport)},
		[]string{"rm", coverageReport},
		[]string{"open", fmt.Sprintf("%s/cover.html", localWorkDir)},
	}
	return mageScript(testCoverCommands)
}

// TravisBuild is the task to build in the context of a Travis CI pipeline
func TravisBuild() error {
	mg.SerialDeps(EnsureTravisBuildEnvironment,
		Build,
		Test)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"syscall"

	"github.com/gosexy/gettext"
	"github.com/lxc/lxd"
	"github.com/lxc/lxd/internal/gnuflag"
	"golang.org/x/crypto/ssh/terminal"
)

type execCmd struct{}

func (c *execCmd) showByDefault() bool {
	return true
}

func (c *execCmd) usage() string {
	return gettext.Gettext(
		"Execute the specified command in a container.\n" +
			"\n" +
			"lxc exec container [--env EDITOR=/usr/bin/vim]... <command>\n")
}

type envFlag []string

func (f *envFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *envFlag) Set(value string) error {
	if f == nil {
		*f = make(envFlag, 1)
	} else {
		*f = append(*f, value)
	}
	return nil
}

var envArgs envFlag

func (c *execCmd) flags() {
	gnuflag.Var(&envArgs, "env", "An environment variable of the form HOME=/home/foo")
}

func (c *execCmd) run(config *lxd.Config, args []string) error {
	if len(args) < 2 {
		return errArgs
	}

	remote, name := config.ParseRemoteAndContainer(args[0])
	d, err := lxd.NewClient(config, remote)
	if err != nil {
		return err
	}

	env := map[string]string{"HOME": "/root"}
	myEnv := os.Environ()
	for _, ent := range myEnv {
		if strings.HasPrefix(ent, "TERM=") {
			env["TERM"] = ent[len("TERM="):]
		}
	}

	for _, arg := range envArgs {
		pieces := strings.SplitN(arg, "=", 2)
		value := ""
		if len(pieces) > 1 {
			value = pieces[1]
		}
		env[pieces[0]] = value
	}

	cfd := syscall.Stdout
	var oldttystate *terminal.State
	if terminal.IsTerminal(cfd) {
		oldttystate, err = terminal.MakeRaw(cfd)
		if err != nil {
			return err
		}
		defer terminal.Restore(cfd, oldttystate)
	}

	ret, err := d.Exec(name, args[1:], env, os.Stdin, os.Stdout, os.Stderr)
	if err != nil {
		return err
	}

	if oldttystate != nil {
		/* A bit of a special case here: we want to exit with the same code as
		 * the process inside the container, so we explicitly exit here
		 * instead of returning an error.
		 *
		 * Additionally, since os.Exit() exits without running deferred
		 * functions, we restore the terminal explicitly.
		 */
		terminal.Restore(cfd, oldttystate)
	}

	/* we get the result of waitpid() here so we need to transform it */
	os.Exit(ret >> 8)
	return fmt.Errorf(gettext.Gettext("unreachable return reached"))
}
<commit_msg>Set USER in the environment<commit_after>package main

import (
	"fmt"
	"os"
	"strings"
	"syscall"

	"github.com/gosexy/gettext"
	"github.com/lxc/lxd"
	"github.com/lxc/lxd/internal/gnuflag"
	"golang.org/x/crypto/ssh/terminal"
)

type execCmd struct{}

func (c *execCmd) showByDefault() bool {
	return true
}

func (c *execCmd) usage() string {
	return gettext.Gettext(
		"Execute the specified command in a container.\n" +
			"\n" +
			"lxc exec container [--env EDITOR=/usr/bin/vim]... <command>\n")
}

type envFlag []string

func (f *envFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *envFlag) Set(value string) error {
	if f == nil {
		*f = make(envFlag, 1)
	} else {
		*f = append(*f, value)
	}
	return nil
}

var envArgs envFlag

func (c *execCmd) flags() {
	gnuflag.Var(&envArgs, "env", "An environment variable of the form HOME=/home/foo")
}

func (c *execCmd) run(config *lxd.Config, args []string) error {
	if len(args) < 2 {
		return errArgs
	}

	remote, name := config.ParseRemoteAndContainer(args[0])
	d, err := lxd.NewClient(config, remote)
	if err != nil {
		return err
	}

	env := map[string]string{"HOME": "/root", "USER": "root"}
	myEnv := os.Environ()
	for _, ent := range myEnv {
		if strings.HasPrefix(ent, "TERM=") {
			env["TERM"] = ent[len("TERM="):]
		}
	}

	for _, arg := range envArgs {
		pieces := strings.SplitN(arg, "=", 2)
		value := ""
		if len(pieces) > 1 {
			value = pieces[1]
		}
		env[pieces[0]] = value
	}

	cfd := syscall.Stdout
	var oldttystate *terminal.State
	if terminal.IsTerminal(cfd) {
		oldttystate, err = terminal.MakeRaw(cfd)
		if err != nil {
			return err
		}
		defer terminal.Restore(cfd, oldttystate)
	}

	ret, err := d.Exec(name, args[1:], env, os.Stdin, os.Stdout, os.Stderr)
	if err != nil {
		return err
	}

	if oldttystate != nil {
		/* A bit of a special case here: we want to exit with the same code as
		 * the process inside the container, so we explicitly exit here
		 * instead of returning an error.
		 *
		 * Additionally, since os.Exit() exits without running deferred
		 * functions, we restore the terminal explicitly.
		 */
		terminal.Restore(cfd, oldttystate)
	}

	/* we get the result of waitpid() here so we need to transform it */
	os.Exit(ret >> 8)
	return fmt.Errorf(gettext.Gettext("unreachable return reached"))
}
<|endoftext|>


<commit_before>package memalpha

import (
	"bytes"
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"testing"
	"time"

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

func freePort() (int, error) {
	l, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return 0, err
	}
	defer func() { _ = l.Close() }()

	return l.Addr().(*net.TCPAddr).Port, nil
}

type server struct {
	cmd    *exec.Cmd
	client *Client
}

func newServer() *server {
	return &server{}
}

func (s *server) Start() error {
	port, err := freePort()
	if err != nil {
		return err
	}

	s.cmd = exec.Command("memcached", "-p", strconv.Itoa(port))
	if err = s.cmd.Start(); err != nil {
		return err
	}

	s.client = NewClient(fmt.Sprintf("localhost:%d", port))

	// Wait a bit for the socket to appear.
	for i := 0; i < 10; i++ {
		s.client.ensureConnected()
		err = s.client.Err()
		if err == nil {
			return nil
		}
		time.Sleep(time.Duration(25*i) * time.Millisecond)
	}

	return err
}

func (s *server) Shutdown() error {
	_ = s.cmd.Process.Kill()
	return s.cmd.Wait()
}

func TestLocalhost(t *testing.T) {
	memd := newServer()
	err := memd.Start()

	if err != nil {
		t.Skipf("skipping test; couldn't start memcached: %s", err)
	}
	defer func() { _ = memd.Shutdown() }()

	c := memd.client

	mustSet := func(key string, value []byte) {
		err := c.Set(key, value, 0, 0, true)
		assert.NoError(t, err, fmt.Sprintf("must Set(%q, %q)", key, value))
	}

	assertItem := func(key string, expected []byte) {
		value, _, err := c.Get(key)
		assert.Nil(t, err)
		assert.NoError(t, err, fmt.Sprintf("must Get(%q)", key))
		assert.Equal(t, string(expected), string(value))
	}

	// Set
	err = c.Set("foo", []byte("fooval"), 0, 0, false)
	assert.NoError(t, err, "first set(foo)")

	err = c.Set("foo", []byte("fooval"), 0, 0, false)
	assert.NoError(t, err, "second set(foo)")

	// Get
	value, _, err := c.Get("foo")
	assert.NoError(t, err, "get(foo)")
	assert.Equal(t, []byte("fooval"), value, "get(fool)")

	// Set large item
	largeKey := string(bytes.Repeat([]byte("A"), 250))
	largeValue := bytes.Repeat([]byte("A"), 1023*1024)
	err = c.Set(largeKey, largeValue, 0, 0, false)
	assert.NoError(t, err, "set(largeKey)")

	// Get large item
	value, _, err = c.Get(largeKey)
	assert.NoError(t, err, "get(largeKey)")
	assert.Equal(t, largeValue, value, "get(largeKey)")

	// Set noreply
	err = c.Set("set_norep", []byte("val"), 0, 0, true)
	assert.NoError(t, err, "set(set_norep, val, noreply)")
	assertItem("set_norep", []byte("val"))

	// Gets
	mustSet("bar", []byte("barval"))
	m, err := c.Gets([]string{"foo", "bar"})
	assert.NoError(t, err, "gets(foo, bar)")
	keyToValue := make(map[string]string)
	for key, response := range m {
		keyToValue[key] = string(response.Value)
	}
	expected := map[string]string{"foo": "fooval", "bar": "barval"}
	assert.Equal(t, expected, keyToValue, "gets(foo, bar)")

	// Add
	err = c.Add("baz", []byte("baz1"), 0, 0, false)
	assert.NoError(t, err, "first add(baz)")
	err = c.Add("baz", []byte("baz2"), 0, 0, false)
	assert.Equal(t, ErrNotStored, err, "second add(baz)")

	// Add noreply
	err = c.Add("add_norep", []byte("val"), 0, 0, true)
	assert.NoError(t, err, "add(add_norep, noreply)")
	assertItem("add_norep", []byte("val"))

	// Replace
	mustSet("foo", []byte("fooval"))
	err = c.Replace("foo", []byte("fooval2"), 0, 0, false)
	assert.NoError(t, err, "replace(foo, fooval2)")
	assertItem("foo", []byte("fooval2"))

	// Replace noreply
	err = c.Replace("foo", []byte("fooval3"), 0, 0, true)
	assert.NoError(t, err, "replace(foo, fooval3, noreply)")
	assertItem("foo", []byte("fooval3"))

	// Append
	err = c.Append("foo", []byte("suffix"), false)
	assert.NoError(t, err, "append(foo, suffix)")
	assertItem("foo", []byte("fooval3suffix"))

	// Append noreply
	mustSet("bar", []byte("fooval"))
	err = c.Append("bar", []byte("app"), true)
	assert.NoError(t, err, "replace(bar, app)")
	assertItem("bar", []byte("foovalapp"))

	// Prepend
	err = c.Prepend("foo", []byte("prefix"), false)
	assert.NoError(t, err, "prepend(foo, prefix)")
	assertItem("foo", []byte("prefixfooval3suffix"))

	// Prepend noreply
	err = c.Prepend("foo", []byte("pre"), true)
	assert.NoError(t, err, "prepend(foo, pre)")
	assertItem("foo", []byte("preprefixfooval3suffix"))

	// CompareAndSwap
	m, err = c.Gets([]string{"foo"})
	assert.NoError(t, err, "gets(foo)")
	err = c.CompareAndSwap("foo", []byte("swapped"), m["foo"].CasID, 0, 0, false)
	assert.NoError(t, err, "cas(foo, swapped, casid)")
	err = c.CompareAndSwap("foo", []byte("swapped_failed"), m["foo"].CasID, 0, 0, false)
	assert.Equal(t, ErrCasConflict, err, "cas(foo, swapped_faile, casid)")
	assertItem("foo", []byte("swapped"))

	// CompareAndSwap noreply
	m, err = c.Gets([]string{"foo"})
	assert.NoError(t, err, "gets(foo)")
	err = c.CompareAndSwap("foo", []byte("swapped_norep"), m["foo"].CasID, 0, 0, true)
	assert.NoError(t, err, "cas(foo, swapped_norep, casid)")
	assertItem("foo", []byte("swapped_norep"))

	// CompareAndSwap raises ErrNotFound
	err = c.CompareAndSwap("not_exists", []byte("ignored"), 42, 0, 0, false)
	assert.Equal(t, ErrNotFound, err, "cas(not_exists)")

	// Delete
	err = c.Delete("foo", false)
	assert.NoError(t, err, "delete(foo)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Delete noreply
	mustSet("foo", []byte("exist"))
	err = c.Delete("foo", true)
	assert.NoError(t, err, "delete(foo, noreply)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Delete raises ErrNotFound
	err = c.Delete("not_exists", false)
	assert.Equal(t, ErrNotFound, err, "delete(not_exists)")

	// Increment
	mustSet("foo", []byte("35"))
	num, err := c.Increment("foo", 7, false)
	assert.NoError(t, err, "incr(foo, 7)")
	assert.EqualValues(t, 42, num, "incr(foo, 7)")

	// Increment noreply
	num, err = c.Increment("foo", 2, true)
	assert.NoError(t, err, "incr(foo, 2, noreply)")
	assertItem("foo", []byte("44"))

	// Increment raises ErrNotFound
	_, err = c.Increment("not_exists", 10, false)
	assert.Equal(t, ErrNotFound, err, "incr(not_exists, 10)")

	// Decrement
	num, err = c.Decrement("foo", 2, false)
	assert.NoError(t, err, "decr(foo, 2)")
	assert.EqualValues(t, 42, num, "decr(foo, 2)")
	assertItem("foo", []byte("42"))

	// Touch
	err = c.Touch("foo", 2, false)
	assert.NoError(t, err, "touch(foo, 2)")
	assertItem("foo", []byte("42"))
	time.Sleep(2 * time.Second)
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Touch noreply
	mustSet("foo", []byte("val"))
	err = c.Touch("foo", 2, true)
	assert.NoError(t, err, "touch(foo, 2, noreply)")

	// Touch raises ErrNotFound
	err = c.Touch("not_exists", 10, false)
	assert.Equal(t, ErrNotFound, err, "touch(not_exists)")

	// Stats
	stats, err := c.Stats()
	assert.NoError(t, err, "stats()")
	if len(stats) < 2 {
		t.Fatalf("stats(): len(Value) = %q, want len(value) > 2", stats)
	}

	// StatsArg
	stats, err = c.StatsArg("slabs")
	assert.NoError(t, err, "stats(slabs)")
	if len(stats) < 2 {
		t.Fatalf("stats(): len(Value) = %q, want len(value) > 2", stats)
	}

	// FlushAll
	mustSet("foo", []byte("bar"))
	err = c.FlushAll(0, false)
	assert.NoError(t, err, "flush_all(0)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// FlushAll delayed
	mustSet("foo", []byte("val"))
	err = c.FlushAll(1, false)
	assert.NoError(t, err, "flush_all(1)")
	time.Sleep(1 * time.Second)
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// FlushAll non optional delayed
	err = c.FlushAll(-1, false)
	assert.NoError(t, err, "flush_all(-1)")

	// FlushAll noreply
	err = c.FlushAll(0, true)
	assert.NoError(t, err, "flush_all(0, noreply)")

	// Version
	ver, err := c.Version()
	assert.NoError(t, err, "version()")
	assert.NotEmpty(t, ver, "version()")

	// Quit
	err = c.Quit()
	assert.NoError(t, err, "quit()")
	if c.conn == nil {
		t.Fatalf("net.Conn = %q, want nil", c.conn)
	}

	// Close
	err = c.Close()
	assert.NoError(t, err, "c.Close()")

	// Close again
	err = c.Close()
	assert.NoError(t, err, "retry c.Close()")
}
<commit_msg>Add test of flags and exptime<commit_after>package memalpha

import (
	"bytes"
	"fmt"
	"net"
	"os/exec"
	"strconv"
	"testing"
	"time"

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

func freePort() (int, error) {
	l, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return 0, err
	}
	defer func() { _ = l.Close() }()

	return l.Addr().(*net.TCPAddr).Port, nil
}

type server struct {
	cmd    *exec.Cmd
	client *Client
}

func newServer() *server {
	return &server{}
}

func (s *server) Start() error {
	port, err := freePort()
	if err != nil {
		return err
	}

	s.cmd = exec.Command("memcached", "-p", strconv.Itoa(port))
	if err = s.cmd.Start(); err != nil {
		return err
	}

	s.client = NewClient(fmt.Sprintf("localhost:%d", port))

	// Wait a bit for the socket to appear.
	for i := 0; i < 10; i++ {
		s.client.ensureConnected()
		err = s.client.Err()
		if err == nil {
			return nil
		}
		time.Sleep(time.Duration(25*i) * time.Millisecond)
	}

	return err
}

func (s *server) Shutdown() error {
	_ = s.cmd.Process.Kill()
	return s.cmd.Wait()
}

func TestLocalhost(t *testing.T) {
	memd := newServer()
	err := memd.Start()

	if err != nil {
		t.Skipf("skipping test; couldn't start memcached: %s", err)
	}
	defer func() { _ = memd.Shutdown() }()

	c := memd.client

	mustSet := func(key string, value []byte) {
		err := c.Set(key, value, 0, 0, true)
		assert.NoError(t, err, fmt.Sprintf("must Set(%q, %q)", key, value))
	}

	assertItem := func(key string, expected []byte) {
		value, _, err := c.Get(key)
		assert.Nil(t, err)
		assert.NoError(t, err, fmt.Sprintf("must Get(%q)", key))
		assert.Equal(t, string(expected), string(value))
	}

	// Set
	err = c.Set("foo", []byte("fooval"), 0, 0, false)
	assert.NoError(t, err, "first set(foo)")

	err = c.Set("foo", []byte("fooval"), 0, 0, false)
	assert.NoError(t, err, "second set(foo)")

	// Get
	value, _, err := c.Get("foo")
	assert.NoError(t, err, "get(foo)")
	assert.Equal(t, []byte("fooval"), value, "get(fool)")

	// Set large item
	largeKey := string(bytes.Repeat([]byte("A"), 250))
	largeValue := bytes.Repeat([]byte("A"), 1023*1024)
	err = c.Set(largeKey, largeValue, 0, 0, false)
	assert.NoError(t, err, "set(largeKey)")

	// Get large item
	value, _, err = c.Get(largeKey)
	assert.NoError(t, err, "get(largeKey)")
	assert.Equal(t, largeValue, value, "get(largeKey)")

	// Set noreply
	err = c.Set("set_norep", []byte("val"), 0, 0, true)
	assert.NoError(t, err, "set(set_norep, val, noreply)")
	assertItem("set_norep", []byte("val"))

	// Set with flags
	err = c.Set("set_flags", []byte("val"), 42, 0, false)
	assert.NoError(t, err, "set(set_flags, val, flags = 42)")
	value, flags, err := c.Get("set_flags")
	assert.NoError(t, err, "get(set_flags)")
	assert.EqualValues(t, 42, flags, "get(set_flags)")

	// Set with exptime
	err = c.Set("set_exptime", []byte("val"), 0, 1, false)
	assert.NoError(t, err, "set(set_exptime, val, exptime = 1)")
	assertItem("set_exptime", []byte("val"))
	time.Sleep(time.Second)
	value, _, err = c.Get("set_exptime")
	assert.Equal(t, ErrCacheMiss, err, "get(set_exptime)")

	// Gets
	mustSet("bar", []byte("barval"))
	m, err := c.Gets([]string{"foo", "bar"})
	assert.NoError(t, err, "gets(foo, bar)")
	keyToValue := make(map[string]string)
	for key, response := range m {
		keyToValue[key] = string(response.Value)
	}
	expected := map[string]string{"foo": "fooval", "bar": "barval"}
	assert.Equal(t, expected, keyToValue, "gets(foo, bar)")

	// Add
	err = c.Add("baz", []byte("baz1"), 0, 0, false)
	assert.NoError(t, err, "first add(baz)")
	err = c.Add("baz", []byte("baz2"), 0, 0, false)
	assert.Equal(t, ErrNotStored, err, "second add(baz)")

	// Add noreply
	err = c.Add("add_norep", []byte("val"), 0, 0, true)
	assert.NoError(t, err, "add(add_norep, noreply)")
	assertItem("add_norep", []byte("val"))

	// Replace
	mustSet("foo", []byte("fooval"))
	err = c.Replace("foo", []byte("fooval2"), 0, 0, false)
	assert.NoError(t, err, "replace(foo, fooval2)")
	assertItem("foo", []byte("fooval2"))

	// Replace noreply
	err = c.Replace("foo", []byte("fooval3"), 0, 0, true)
	assert.NoError(t, err, "replace(foo, fooval3, noreply)")
	assertItem("foo", []byte("fooval3"))

	// Append
	err = c.Append("foo", []byte("suffix"), false)
	assert.NoError(t, err, "append(foo, suffix)")
	assertItem("foo", []byte("fooval3suffix"))

	// Append noreply
	mustSet("bar", []byte("fooval"))
	err = c.Append("bar", []byte("app"), true)
	assert.NoError(t, err, "replace(bar, app)")
	assertItem("bar", []byte("foovalapp"))

	// Prepend
	err = c.Prepend("foo", []byte("prefix"), false)
	assert.NoError(t, err, "prepend(foo, prefix)")
	assertItem("foo", []byte("prefixfooval3suffix"))

	// Prepend noreply
	err = c.Prepend("foo", []byte("pre"), true)
	assert.NoError(t, err, "prepend(foo, pre)")
	assertItem("foo", []byte("preprefixfooval3suffix"))

	// CompareAndSwap
	m, err = c.Gets([]string{"foo"})
	assert.NoError(t, err, "gets(foo)")
	err = c.CompareAndSwap("foo", []byte("swapped"), m["foo"].CasID, 0, 0, false)
	assert.NoError(t, err, "cas(foo, swapped, casid)")
	err = c.CompareAndSwap("foo", []byte("swapped_failed"), m["foo"].CasID, 0, 0, false)
	assert.Equal(t, ErrCasConflict, err, "cas(foo, swapped_faile, casid)")
	assertItem("foo", []byte("swapped"))

	// CompareAndSwap noreply
	m, err = c.Gets([]string{"foo"})
	assert.NoError(t, err, "gets(foo)")
	err = c.CompareAndSwap("foo", []byte("swapped_norep"), m["foo"].CasID, 0, 0, true)
	assert.NoError(t, err, "cas(foo, swapped_norep, casid)")
	assertItem("foo", []byte("swapped_norep"))

	// CompareAndSwap raises ErrNotFound
	err = c.CompareAndSwap("not_exists", []byte("ignored"), 42, 0, 0, false)
	assert.Equal(t, ErrNotFound, err, "cas(not_exists)")

	// Delete
	err = c.Delete("foo", false)
	assert.NoError(t, err, "delete(foo)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Delete noreply
	mustSet("foo", []byte("exist"))
	err = c.Delete("foo", true)
	assert.NoError(t, err, "delete(foo, noreply)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Delete raises ErrNotFound
	err = c.Delete("not_exists", false)
	assert.Equal(t, ErrNotFound, err, "delete(not_exists)")

	// Increment
	mustSet("foo", []byte("35"))
	num, err := c.Increment("foo", 7, false)
	assert.NoError(t, err, "incr(foo, 7)")
	assert.EqualValues(t, 42, num, "incr(foo, 7)")

	// Increment noreply
	num, err = c.Increment("foo", 2, true)
	assert.NoError(t, err, "incr(foo, 2, noreply)")
	assertItem("foo", []byte("44"))

	// Increment raises ErrNotFound
	_, err = c.Increment("not_exists", 10, false)
	assert.Equal(t, ErrNotFound, err, "incr(not_exists, 10)")

	// Decrement
	num, err = c.Decrement("foo", 2, false)
	assert.NoError(t, err, "decr(foo, 2)")
	assert.EqualValues(t, 42, num, "decr(foo, 2)")
	assertItem("foo", []byte("42"))

	// Touch
	err = c.Touch("foo", 2, false)
	assert.NoError(t, err, "touch(foo, 2)")
	assertItem("foo", []byte("42"))
	time.Sleep(2 * time.Second)
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// Touch noreply
	mustSet("foo", []byte("val"))
	err = c.Touch("foo", 2, true)
	assert.NoError(t, err, "touch(foo, 2, noreply)")

	// Touch raises ErrNotFound
	err = c.Touch("not_exists", 10, false)
	assert.Equal(t, ErrNotFound, err, "touch(not_exists)")

	// Stats
	stats, err := c.Stats()
	assert.NoError(t, err, "stats()")
	if len(stats) < 2 {
		t.Fatalf("stats(): len(Value) = %q, want len(value) > 2", stats)
	}

	// StatsArg
	stats, err = c.StatsArg("slabs")
	assert.NoError(t, err, "stats(slabs)")
	if len(stats) < 2 {
		t.Fatalf("stats(): len(Value) = %q, want len(value) > 2", stats)
	}

	// FlushAll
	mustSet("foo", []byte("bar"))
	err = c.FlushAll(0, false)
	assert.NoError(t, err, "flush_all(0)")
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// FlushAll delayed
	mustSet("foo", []byte("val"))
	err = c.FlushAll(1, false)
	assert.NoError(t, err, "flush_all(1)")
	time.Sleep(1 * time.Second)
	_, _, err = c.Get("foo")
	assert.Equal(t, ErrCacheMiss, err, "get(foo)")

	// FlushAll non optional delayed
	err = c.FlushAll(-1, false)
	assert.NoError(t, err, "flush_all(-1)")

	// FlushAll noreply
	err = c.FlushAll(0, true)
	assert.NoError(t, err, "flush_all(0, noreply)")

	// Version
	ver, err := c.Version()
	assert.NoError(t, err, "version()")
	assert.NotEmpty(t, ver, "version()")

	// Quit
	err = c.Quit()
	assert.NoError(t, err, "quit()")
	if c.conn == nil {
		t.Fatalf("net.Conn = %q, want nil", c.conn)
	}

	// Close
	err = c.Close()
	assert.NoError(t, err, "c.Close()")

	// Close again
	err = c.Close()
	assert.NoError(t, err, "retry c.Close()")
}
<|endoftext|>