<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"

	"github.com/clbanning/mxj"
)

const (
	version = "0.8.1"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] DIR\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Server to test\n"
		h += "  -h, --help		Print usage\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suiteDir    string
	hostFlag    string
	debugFlag   bool
	helpFlag    bool
	versionFlag bool
	junitFlag   bool
)

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.StringVar(&hostFlag, "H", "http://localhost:8080", "Test server address")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")

	flag.Parse()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	src := flag.Arg(0)

	if src == "" {
		fmt.Print("You must specify a directory or file with tests.\n\n")
		flag.Usage()
		return
	}

	var ch <-chan TestSuite
	if filepath.Ext(src) == "" {
		debugMsg("Loading from directory...")
		suiteDir = src
		ch = NewDirLoader(suiteDir)
	} else {
		debugMsg("Loading from file...")
		suiteDir = filepath.Dir(src)
		ch = NewFileLoader(src)
	}

	reporters := []Reporter{NewConsoleReporter()}
	if junitFlag {
		path, _ := filepath.Abs("./report")
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)

	// test case runner?
	for suite := range ch {
		for _, testCase := range suite.Cases {

			rememberedMap := make(map[string]interface{})

			for _, c := range testCase.Calls {
				addAll(c.Args, rememberedMap)
				tr := call(suite, testCase, c, rememberedMap)
				tr.Suite = suite
				reporter.Report(*tr)
			}
		}
	}

	reporter.Flush()
}

func addAll(src, target map[string]interface{}) {
	for key, val := range src {
		target[key] = val
	}
}

func call(testSuite TestSuite, testCase TestCase, call Call, rememberMap map[string]interface{}) (result *TestResult) {
	debugMsg("--- Starting call ...") // TODO add call description
	start := time.Now()
	result = &TestResult{Case: testCase}

	on := call.On

	dat := []byte(on.Body)
	if on.BodyFile != "" {
		uri, err := toAbsPath(testSuite.Dir, on.BodyFile)
		if err != nil {
			result.Cause = err
			return
		}

		if d, err := ioutil.ReadFile(uri); err == nil {
			dat = d
		} else {
			result.Cause = fmt.Errorf("Can't read body file: %s", err.Error())
			return
		}
	}

	req, err := populateRequest(on, string(dat), rememberMap)
	if err != nil {
		result.Cause = err
		return
	}
	debugMsg("Request: ", req)

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debugMsg("Error when sending request", err)
		result.Cause = err
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debugMsg("Error reading response")
		result.Cause = err
		return
	}

	end := time.Now()

	testResp := Response{http: *resp, body: body}
	result.Resp = testResp
	result.Duration = end.Sub(start)

	debugMsg(testResp.ToString())

	exps, err := expectations(call, testSuite.Dir)
	if err != nil {
		result.Cause = err
		return
	}

	for _, exp := range exps {
		checkErr := exp.check(testResp)
		if checkErr != nil {
			result.Cause = checkErr
			return
		}
	}

	m, err := testResp.bodyAsMap()
	if err != nil {
		debugMsg("Can't parse response body to Map for [remember]")
		result.Cause = err
		return
	}

	err = remember(m, call.Remember, rememberMap)
	debugMsg("Remember: ", rememberMap)
	if err != nil {
		debugMsg("Error remember")
		result.Cause = err
		return
	}

	return result
}

func populateRequest(on On, body string, rememberMap map[string]interface{}) (*http.Request, error) {

	url, err := urlPrefix(on.URL)
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	body = populateRememberedVars(body, rememberMap)
	dat := []byte(body)

	req, _ := http.NewRequest(on.Method, url, bytes.NewBuffer(dat))

	for key, value := range on.Headers {
		req.Header.Add(key, populateRememberedVars(value, rememberMap))
	}

	q := req.URL.Query()
	for key, value := range on.Params {
		q.Add(key, populateRememberedVars(value, rememberMap))
	}
	req.URL.RawQuery = q.Encode()

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func populateRememberedVars(str string, rememberMap map[string]interface{}) string {
	res := str
	for varName, val := range rememberMap {
		placeholder := "{" + varName + "}"
		res = strings.Replace(res, placeholder, fmt.Sprintf("%v", val), -1)
	}
	return res
}

func expectations(call Call, srcDir string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if call.Expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: call.Expect.StatusCode})
	}

	if call.Expect.hasSchema() {
		var (
			schemeURI string
			err       error
		)

		if call.Expect.BodySchemaFile != "" {
			schemeURI, err = toAbsPath(srcDir, call.Expect.BodySchemaFile)
			if err != nil {
				return nil, err
			}
			schemeURI = "file:///" + schemeURI
		}

		if call.Expect.BodySchemaURI != "" {
			isHTTP := strings.HasPrefix(call.Expect.BodySchemaURI, "http://")
			isHTTPS := strings.HasPrefix(call.Expect.BodySchemaURI, "https://")
			if !(isHTTP || isHTTPS) {
				schemeURI = hostFlag + call.Expect.BodySchemaURI
			} else {
				schemeURI = call.Expect.BodySchemaURI
			}
		}
		exps = append(exps, BodySchemaExpectation{schemaURI: schemeURI})
	}

	if len(call.Expect.Body) > 0 {
		exps = append(exps, BodyExpectation{pathExpectations: call.Expect.Body})
	}

	if len(call.Expect.Headers) > 0 {
		for k, v := range call.Expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if call.Expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{call.Expect.ContentType})
	}

	// and so on
	return exps, nil
}

func toAbsPath(srcDir string, assetPath string) (string, error) {
	if filepath.IsAbs(assetPath) {
		// ignore srcDir
		return assetPath, nil
	}

	uri, err := filepath.Abs(filepath.Join(suiteDir, srcDir, assetPath))
	if err != nil {
		return "", errors.New("Invalid file path: " + assetPath)
	}

	return filepath.ToSlash(uri), nil
}

func remember(bodyMap map[string]interface{}, remember map[string]string, rememberedMap map[string]interface{}) (err error) {

	for varName, path := range remember {

		splitPath := strings.Split(path, ".")

		if rememberVar, err := getByPath(bodyMap, splitPath...); err == nil {
			rememberedMap[varName] = rememberVar
		} else {
			strErr := fmt.Sprintf("Remembered value not found, path: %v", path)
			err = errors.New(strErr)
		}
		//fmt.Printf("v: %v\n", getByPath(bodyMap, b...))
	}

	return err
}

func (e Response) bodyAsMap() (map[string]interface{}, error) {
	var bodyMap map[string]interface{}
	var err error

	contentType, _, _ := mime.ParseMediaType(e.http.Header.Get("content-type"))
	if contentType == "application/xml" || contentType == "text/xml" {
		m, err := mxj.NewMapXml(e.body)
		if err == nil {
			bodyMap = m.Old() // cast to map
		}
	}

	if contentType == "application/json" {
		err = json.Unmarshal(e.body, &bodyMap)
	}

	return bodyMap, err
}

func debugMsg(a ...interface{}) {
	if !debugFlag {
		return
	}
	fmt.Println(a...)
}

func debugMsgF(tpl string, a ...interface{}) {
	if !debugFlag {
		return
	}
	fmt.Printf(tpl, a...)
}

// TODO finilize suite schema

// optional/under discussion
// TODO matchers: not() ?
// TODO rename remember > keep or memo ?
// TODO full body expectation from file (security testing)
// TODO concurrent tests run
<commit_msg>new version 0.8.2<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"

	"github.com/clbanning/mxj"
)

const (
	version = "0.8.2"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] DIR\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Server to test\n"
		h += "  -h, --help		Print usage\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suiteDir    string
	hostFlag    string
	debugFlag   bool
	helpFlag    bool
	versionFlag bool
	junitFlag   bool
)

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.StringVar(&hostFlag, "H", "http://localhost:8080", "Test server address")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")

	flag.Parse()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	src := flag.Arg(0)

	if src == "" {
		fmt.Print("You must specify a directory or file with tests.\n\n")
		flag.Usage()
		return
	}

	var ch <-chan TestSuite
	if filepath.Ext(src) == "" {
		debugMsg("Loading from directory...")
		suiteDir = src
		ch = NewDirLoader(suiteDir)
	} else {
		debugMsg("Loading from file...")
		suiteDir = filepath.Dir(src)
		ch = NewFileLoader(src)
	}

	reporters := []Reporter{NewConsoleReporter()}
	if junitFlag {
		path, _ := filepath.Abs("./report")
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)

	// test case runner?
	for suite := range ch {
		for _, testCase := range suite.Cases {

			rememberedMap := make(map[string]interface{})

			for _, c := range testCase.Calls {
				addAll(c.Args, rememberedMap)
				tr := call(suite, testCase, c, rememberedMap)
				tr.Suite = suite
				reporter.Report(*tr)
			}
		}
	}

	reporter.Flush()
}

func addAll(src, target map[string]interface{}) {
	for key, val := range src {
		target[key] = val
	}
}

func call(testSuite TestSuite, testCase TestCase, call Call, rememberMap map[string]interface{}) (result *TestResult) {
	debugMsg("--- Starting call ...") // TODO add call description
	start := time.Now()
	result = &TestResult{Case: testCase}

	on := call.On

	dat := []byte(on.Body)
	if on.BodyFile != "" {
		uri, err := toAbsPath(testSuite.Dir, on.BodyFile)
		if err != nil {
			result.Cause = err
			return
		}

		if d, err := ioutil.ReadFile(uri); err == nil {
			dat = d
		} else {
			result.Cause = fmt.Errorf("Can't read body file: %s", err.Error())
			return
		}
	}

	req, err := populateRequest(on, string(dat), rememberMap)
	if err != nil {
		result.Cause = err
		return
	}
	debugMsg("Request: ", req)

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debugMsg("Error when sending request", err)
		result.Cause = err
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debugMsg("Error reading response")
		result.Cause = err
		return
	}

	end := time.Now()

	testResp := Response{http: *resp, body: body}
	result.Resp = testResp
	result.Duration = end.Sub(start)

	debugMsg(testResp.ToString())

	exps, err := expectations(call, testSuite.Dir)
	if err != nil {
		result.Cause = err
		return
	}

	for _, exp := range exps {
		checkErr := exp.check(testResp)
		if checkErr != nil {
			result.Cause = checkErr
			return
		}
	}

	m, err := testResp.bodyAsMap()
	if err != nil {
		debugMsg("Can't parse response body to Map for [remember]")
		result.Cause = err
		return
	}

	err = remember(m, call.Remember, rememberMap)
	debugMsg("Remember: ", rememberMap)
	if err != nil {
		debugMsg("Error remember")
		result.Cause = err
		return
	}

	return result
}

func populateRequest(on On, body string, rememberMap map[string]interface{}) (*http.Request, error) {

	url, err := urlPrefix(on.URL)
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	body = populateRememberedVars(body, rememberMap)
	dat := []byte(body)

	req, _ := http.NewRequest(on.Method, url, bytes.NewBuffer(dat))

	for key, value := range on.Headers {
		req.Header.Add(key, populateRememberedVars(value, rememberMap))
	}

	q := req.URL.Query()
	for key, value := range on.Params {
		q.Add(key, populateRememberedVars(value, rememberMap))
	}
	req.URL.RawQuery = q.Encode()

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func populateRememberedVars(str string, rememberMap map[string]interface{}) string {
	res := str
	for varName, val := range rememberMap {
		placeholder := "{" + varName + "}"
		res = strings.Replace(res, placeholder, fmt.Sprintf("%v", val), -1)
	}
	return res
}

func expectations(call Call, srcDir string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if call.Expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: call.Expect.StatusCode})
	}

	if call.Expect.hasSchema() {
		var (
			schemeURI string
			err       error
		)

		if call.Expect.BodySchemaFile != "" {
			schemeURI, err = toAbsPath(srcDir, call.Expect.BodySchemaFile)
			if err != nil {
				return nil, err
			}
			schemeURI = "file:///" + schemeURI
		}

		if call.Expect.BodySchemaURI != "" {
			isHTTP := strings.HasPrefix(call.Expect.BodySchemaURI, "http://")
			isHTTPS := strings.HasPrefix(call.Expect.BodySchemaURI, "https://")
			if !(isHTTP || isHTTPS) {
				schemeURI = hostFlag + call.Expect.BodySchemaURI
			} else {
				schemeURI = call.Expect.BodySchemaURI
			}
		}
		exps = append(exps, BodySchemaExpectation{schemaURI: schemeURI})
	}

	if len(call.Expect.Body) > 0 {
		exps = append(exps, BodyExpectation{pathExpectations: call.Expect.Body})
	}

	if len(call.Expect.Headers) > 0 {
		for k, v := range call.Expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if call.Expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{call.Expect.ContentType})
	}

	// and so on
	return exps, nil
}

func toAbsPath(srcDir string, assetPath string) (string, error) {
	if filepath.IsAbs(assetPath) {
		// ignore srcDir
		return assetPath, nil
	}

	uri, err := filepath.Abs(filepath.Join(suiteDir, srcDir, assetPath))
	if err != nil {
		return "", errors.New("Invalid file path: " + assetPath)
	}

	return filepath.ToSlash(uri), nil
}

func remember(bodyMap map[string]interface{}, remember map[string]string, rememberedMap map[string]interface{}) (err error) {

	for varName, path := range remember {

		splitPath := strings.Split(path, ".")

		if rememberVar, err := getByPath(bodyMap, splitPath...); err == nil {
			rememberedMap[varName] = rememberVar
		} else {
			strErr := fmt.Sprintf("Remembered value not found, path: %v", path)
			err = errors.New(strErr)
		}
		//fmt.Printf("v: %v\n", getByPath(bodyMap, b...))
	}

	return err
}

func (e Response) bodyAsMap() (map[string]interface{}, error) {
	var bodyMap map[string]interface{}
	var err error

	contentType, _, _ := mime.ParseMediaType(e.http.Header.Get("content-type"))
	if contentType == "application/xml" || contentType == "text/xml" {
		m, err := mxj.NewMapXml(e.body)
		if err == nil {
			bodyMap = m.Old() // cast to map
		}
	}

	if contentType == "application/json" {
		err = json.Unmarshal(e.body, &bodyMap)
	}

	return bodyMap, err
}

func debugMsg(a ...interface{}) {
	if !debugFlag {
		return
	}
	fmt.Println(a...)
}

func debugMsgF(tpl string, a ...interface{}) {
	if !debugFlag {
		return
	}
	fmt.Printf(tpl, a...)
}

// TODO finilize suite schema

// optional/under discussion
// TODO matchers: not() ?
// TODO rename remember > keep or memo ?
// TODO full body expectation from file (security testing)
// TODO concurrent tests run
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"strings"
)

const BUFFERSIZE = 1024

var oneGigabytePerSecond = 1000000 // expressed as kbps

type Flags struct {
	Relay               bool
	Debug               bool
	DontEncrypt         bool
	Server              string
	File                string
	Code                string
	Rate                int
	NumberOfConnections int
}

var version string

func main() {
	fmt.Println(`
         /\_/\
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

croc version ` + version + `
`)
	flags := new(Flags)
	flag.BoolVar(&flags.Relay, "relay", false, "run as relay")
	flag.BoolVar(&flags.Debug, "debug", false, "debug mode")
	flag.StringVar(&flags.Server, "server", "cowyo.com", "address of relay server")
	flag.StringVar(&flags.File, "send", "", "file to send")
	flag.StringVar(&flags.Code, "code", "", "use your own code phrase")
	flag.IntVar(&flags.Rate, "rate", oneGigabytePerSecond, "throttle down to speed in kbps")
	flag.BoolVar(&flags.DontEncrypt, "no-encrypt", false, "turn off encryption")
	flag.IntVar(&flags.NumberOfConnections, "threads", 4, "number of threads to use")
	flag.Parse()

	if flags.Relay {
		r := NewRelay(flags)
		r.Run()
	} else {
		c := NewConnection(flags)
		err := c.Run()
		if err != nil {
			fmt.Printf("Error! Please submit the following error to https://github.com/schollz/croc/issues:\n\n'%s'\n\n", err.Error())
		}
	}
}

func getInput(prompt string) string {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print(prompt)
	text, _ := reader.ReadString('\n')
	return strings.TrimSpace(text)
}
<commit_msg>gofmt<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"strings"
)

const BUFFERSIZE = 1024

var oneGigabytePerSecond = 1000000 // expressed as kbps

type Flags struct {
	Relay               bool
	Debug               bool
	DontEncrypt         bool
	Server              string
	File                string
	Code                string
	Rate                int
	NumberOfConnections int
}

var version string

func main() {
	fmt.Println(`
         /\_/\
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

croc version ` + version + `
`)
	flags := new(Flags)
	flag.BoolVar(&flags.Relay, "relay", false, "run as relay")
	flag.BoolVar(&flags.Debug, "debug", false, "debug mode")
	flag.StringVar(&flags.Server, "server", "cowyo.com", "address of relay server")
	flag.StringVar(&flags.File, "send", "", "file to send")
	flag.StringVar(&flags.Code, "code", "", "use your own code phrase")
	flag.IntVar(&flags.Rate, "rate", oneGigabytePerSecond, "throttle down to speed in kbps")
	flag.BoolVar(&flags.DontEncrypt, "no-encrypt", false, "turn off encryption")
	flag.IntVar(&flags.NumberOfConnections, "threads", 4, "number of threads to use")
	flag.Parse()

	if flags.Relay {
		r := NewRelay(flags)
		r.Run()
	} else {
		c := NewConnection(flags)
		err := c.Run()
		if err != nil {
			fmt.Printf("Error! Please submit the following error to https://github.com/schollz/croc/issues:\n\n'%s'\n\n", err.Error())
		}
	}
}

func getInput(prompt string) string {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print(prompt)
	text, _ := reader.ReadString('\n')
	return strings.TrimSpace(text)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"path/filepath"

	"github.com/codegangsta/cli"
	"github.com/gobuild/gobuild2/pkg/cmd/pack"
	"github.com/gobuild/gobuild2/pkg/cmd/runinit"
	"github.com/gobuild/gobuild2/pkg/cmd/slave"
	"github.com/gobuild/gobuild2/pkg/cmd/web"
)

const VERSION = "0.0.1.0508"

var app = cli.NewApp()

func init() {
	cwd, _ := os.Getwd()
	program := filepath.Base(cwd)

	app.Name = "gobuild"
	app.Usage = "[COMMANDS]"
	app.Version = VERSION
	app.Commands = append(app.Commands,
		cli.Command{
			Name:   "slave",
			Usage:  "start gobuild compile slave",
			Action: slave.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"webaddr,w", "localhost:8010", "gobuild2 web address"},
			},
		},
		cli.Command{
			Name:   "init",
			Usage:  "initial gobuild.yml file",
			Action: runinit.Action,
		},
		cli.Command{
			Name:   "pack",
			Usage:  "build and pack file into tgz or zip",
			Action: pack.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"os", os.Getenv("GOOS"), "operation system"},
				cli.StringFlag{"arch", os.Getenv("GOARCH"), "arch"},
				cli.StringFlag{"depth", "3", "depth of file to walk"},
				cli.StringFlag{"output,o", program + ".zip", "target file"},
				cli.StringFlag{"gom", "go", "go package manage program"},
			},
		},
		cli.Command{
			Name:   "web",
			Usage:  "start gobuild web server",
			Action: web.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"conf,f", "conf/app.ini", "config file"},
			},
		},
	)
}

func main() {
	app.Run(os.Args)
}
<commit_msg>trigger test<commit_after>package main

import (
	"os"
	"path/filepath"

	"github.com/codegangsta/cli"
	"github.com/gobuild/gobuild2/pkg/cmd/pack"
	"github.com/gobuild/gobuild2/pkg/cmd/runinit"
	"github.com/gobuild/gobuild2/pkg/cmd/slave"
	"github.com/gobuild/gobuild2/pkg/cmd/web"
)

const VERSION = "0.0.1.0522"

var app = cli.NewApp()

func init() {
	cwd, _ := os.Getwd()
	program := filepath.Base(cwd)

	app.Name = "gobuild"
	app.Usage = "[COMMANDS]"
	app.Version = VERSION
	app.Commands = append(app.Commands,
		cli.Command{
			Name:   "slave",
			Usage:  "start gobuild compile slave",
			Action: slave.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"webaddr,w", "localhost:8010", "gobuild2 web address"},
			},
		},
		cli.Command{
			Name:   "init",
			Usage:  "initial gobuild.yml file",
			Action: runinit.Action,
		},
		cli.Command{
			Name:   "pack",
			Usage:  "build and pack file into tgz or zip",
			Action: pack.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"os", os.Getenv("GOOS"), "operation system"},
				cli.StringFlag{"arch", os.Getenv("GOARCH"), "arch"},
				cli.StringFlag{"depth", "3", "depth of file to walk"},
				cli.StringFlag{"output,o", program + ".zip", "target file"},
				cli.StringFlag{"gom", "go", "go package manage program"},
			},
		},
		cli.Command{
			Name:   "web",
			Usage:  "start gobuild web server",
			Action: web.Action,
			Flags: []cli.Flag{
				cli.StringFlag{"conf,f", "conf/app.ini", "config file"},
			},
		},
	)
}

func main() {
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"

	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	timeFormat   = "2006-01-02T15:04:05"
	follow       = kingpin.Flag("follow", "don't stop when the end of stream is reached").Short('f').Default("false").Bool()
	logGroupName = kingpin.Arg("group", "log group name").Required().String()
	startTime    = kingpin.Arg("start", "start time").Default(time.Now().Format(timeFormat)).String()
	streamName   = kingpin.Arg("stream", "Stream name").String()
)

func parseTime(timeStr string) time.Time {
	loc, _ := time.LoadLocation("UTC")
	t, _ := time.ParseInLocation(timeFormat, timeStr, loc)

	return t
}

func formatTimestamp(ts int64) string {
	return time.Unix(ts, 0).Format(timeFormat)
}

func params(logGroupName string, streamName string, epochStartTime int64) *cloudwatchlogs.FilterLogEventsInput {
	startTimeInt64 := epochStartTime * 1000
	params := &cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &logGroupName,
		Interleaved:  aws.Bool(true),
		StartTime:    &startTimeInt64}

	if streamName != "" {
		params.LogStreamNames = []*string{aws.String(streamName)}
	}
	return params
}

func main() {
	kingpin.Version("0.0.1")
	kingpin.Parse()
	sess, err := session.NewSession()
	if err != nil {
		panic(err)
	}
	cwl := cloudwatchlogs.New(sess, aws.NewConfig().WithRegion("eu-west-1"))

	lastTimestamp := parseTime(*startTime).Unix()
	pageHandler := func(res *cloudwatchlogs.FilterLogEventsOutput, lastPage bool) bool {
		for _, event := range res.Events {
			lastTimestamp = *event.Timestamp / 1000
			fmt.Println(*event.Message)
		}
		return true
	}

	for *follow {
		logParam := params(*logGroupName, *streamName, lastTimestamp)
		error := cwl.FilterLogEventsPages(logParam, pageHandler)

		if error != nil {
			panic(error)
		}
	}
}
<commit_msg>Basic log group listing<commit_after>package main

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"

	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	timeFormat = "2006-01-02T15:04:05"

	tailCommand     = kingpin.Command("tail", "Tail a log group")
	lsCommand       = kingpin.Command("ls", "show all log groups")
	logGroupPattern = lsCommand.Arg("group", "the log group name").String()
	follow          = tailCommand.Flag("follow", "don't stop when the end of stream is reached").Short('f').Default("false").Bool()
	logGroupName    = tailCommand.Arg("group", "The log group name").Required().String()
	startTime       = tailCommand.Arg("start", "The start time").Default(time.Now().Format(timeFormat)).String()
	streamName      = tailCommand.Arg("stream", "Stream name").String()
)

func parseTime(timeStr string) time.Time {
	loc, _ := time.LoadLocation("UTC")
	t, _ := time.ParseInLocation(timeFormat, timeStr, loc)

	return t
}

func formatTimestamp(ts int64) string {
	return time.Unix(ts, 0).Format(timeFormat)
}

func params(logGroupName string, streamName string, epochStartTime int64) *cloudwatchlogs.FilterLogEventsInput {
	startTimeInt64 := epochStartTime * 1000
	params := &cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &logGroupName,
		Interleaved:  aws.Bool(true),
		StartTime:    &startTimeInt64}

	if streamName != "" {
		params.LogStreamNames = []*string{aws.String(streamName)}
	}
	return params
}

func tail(cwl *cloudwatchlogs.CloudWatchLogs) {
	lastTimestamp := parseTime(*startTime).Unix()
	pageHandler := func(res *cloudwatchlogs.FilterLogEventsOutput, lastPage bool) bool {
		for _, event := range res.Events {
			lastTimestamp = *event.Timestamp / 1000
			fmt.Println(*event.Message)
		}
		return true
	}

	for *follow || (lastTimestamp == parseTime(*startTime).Unix()) {
		logParam := params(*logGroupName, *streamName, lastTimestamp)
		error := cwl.FilterLogEventsPages(logParam, pageHandler)

		if error != nil {
			panic(error)

		}
	}
}

func ls(cwl *cloudwatchlogs.CloudWatchLogs) {
	params := &cloudwatchlogs.DescribeLogGroupsInput{
	//		LogGroupNamePrefix: aws.String("LogGroupName"),
	}

	handler := func(res *cloudwatchlogs.DescribeLogGroupsOutput, lastPage bool) bool {
		for _, logGroup := range res.LogGroups {
			fmt.Println(*logGroup.LogGroupName)
		}
		return true
	}
	err := cwl.DescribeLogGroupsPages(params, handler)
	if err != nil {
		panic(err)
	}
}

func main() {
	kingpin.Version("0.0.1")
	command := kingpin.Parse()

	sess, err := session.NewSession()
	if err != nil {
		panic(err)
	}
	cwl := cloudwatchlogs.New(sess, aws.NewConfig().WithRegion("eu-west-1"))

	switch command {
	case "ls":
		ls(cwl)
	case "tail":
		tail(cwl)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"runtime"
	"runtime/debug"
	"strings"

	"github.com/anaminus/cobra"
	"github.com/anaminus/pflag"
)

func init() {
	var c VersionCommand
	var cmd = &cobra.Command{
		Use: "version",
		Run: c.Run,
	}
	c.SetFlags(cmd.PersistentFlags())
	Program.AddCommand(cmd)
}

func VersionString() string {
	s := Version
	if Prerelease != "" {
		s += "-" + Prerelease
	}
	if Build != "" {
		s += "+" + Build
	}
	return s
}

func writeModuleString(s *strings.Builder, mod debug.Module, prefix string) {
	s.WriteString("\t")
	s.WriteString(prefix)
	s.WriteString("\t")
	s.WriteString(mod.Path)
	if mod.Version != "" {
		s.WriteString("\t")
		s.WriteString(mod.Version)
	}
	if mod.Sum != "" {
		s.WriteString("\t")
		s.WriteString(mod.Sum)
	}
	s.WriteString("\n")
	if mod.Replace != nil {
		writeModuleString(s, *mod.Replace, "=>")
	}
}

func DetailedInfoString() string {
	var s strings.Builder
	fmt.Fprintf(&s, "rbxmk version: %s\n", Version)
	if Prerelease != "" {
		fmt.Fprintf(&s, "rbxmk prerelease: %s\n", Prerelease)
	}
	if Build != "" {
		fmt.Fprintf(&s, "rbxmk build: %s\n", Build)
	}
	if sslKeyLogFileEnvVar != "" {
		fmt.Fprintf(&s, "ssl log var: %s\n", sslKeyLogFileEnvVar)
	}
	fmt.Fprintf(&s, "go version: %s\n", runtime.Version())
	fmt.Fprintf(&s, "go compiler: %s\n", runtime.Compiler)
	fmt.Fprintf(&s, "go target: %s/%s\n", runtime.GOOS, runtime.GOARCH)
	if info, ok := debug.ReadBuildInfo(); ok {
		fmt.Fprintf(&s, "package: %s\n", info.Path)
		fmt.Fprintf(&s, "modules:\n")
		writeModuleString(&s, info.Main, "mod")
		for _, dep := range info.Deps {
			writeModuleString(&s, *dep, "dep")
		}
	}
	return s.String()
}

type VersionCommand struct {
	Verbose bool
}

func (c *VersionCommand) SetFlags(flags *pflag.FlagSet) {
	flags.BoolVarP(&c.Verbose, "verbose", "v", false, DocFlag("Commands/version:Flags/verbose"))
}

func (c *VersionCommand) Run(cmd *cobra.Command, args []string) {
	if c.Verbose {
		cmd.Println(DetailedInfoString())
	} else {
		cmd.Println(VersionString())
	}
}
<commit_msg>Use path instead of package as field name.<commit_after>package main

import (
	"fmt"
	"runtime"
	"runtime/debug"
	"strings"

	"github.com/anaminus/cobra"
	"github.com/anaminus/pflag"
)

func init() {
	var c VersionCommand
	var cmd = &cobra.Command{
		Use: "version",
		Run: c.Run,
	}
	c.SetFlags(cmd.PersistentFlags())
	Program.AddCommand(cmd)
}

func VersionString() string {
	s := Version
	if Prerelease != "" {
		s += "-" + Prerelease
	}
	if Build != "" {
		s += "+" + Build
	}
	return s
}

func writeModuleString(s *strings.Builder, mod debug.Module, prefix string) {
	s.WriteString("\t")
	s.WriteString(prefix)
	s.WriteString("\t")
	s.WriteString(mod.Path)
	if mod.Version != "" {
		s.WriteString("\t")
		s.WriteString(mod.Version)
	}
	if mod.Sum != "" {
		s.WriteString("\t")
		s.WriteString(mod.Sum)
	}
	s.WriteString("\n")
	if mod.Replace != nil {
		writeModuleString(s, *mod.Replace, "=>")
	}
}

func DetailedInfoString() string {
	var s strings.Builder
	fmt.Fprintf(&s, "rbxmk version: %s\n", Version)
	if Prerelease != "" {
		fmt.Fprintf(&s, "rbxmk prerelease: %s\n", Prerelease)
	}
	if Build != "" {
		fmt.Fprintf(&s, "rbxmk build: %s\n", Build)
	}
	if sslKeyLogFileEnvVar != "" {
		fmt.Fprintf(&s, "ssl log var: %s\n", sslKeyLogFileEnvVar)
	}
	fmt.Fprintf(&s, "go version: %s\n", runtime.Version())
	fmt.Fprintf(&s, "go compiler: %s\n", runtime.Compiler)
	fmt.Fprintf(&s, "go target: %s/%s\n", runtime.GOOS, runtime.GOARCH)
	if info, ok := debug.ReadBuildInfo(); ok {
		fmt.Fprintf(&s, "path: %s\n", info.Path)
		fmt.Fprintf(&s, "modules:\n")
		writeModuleString(&s, info.Main, "mod")
		for _, dep := range info.Deps {
			writeModuleString(&s, *dep, "dep")
		}
	}
	return s.String()
}

type VersionCommand struct {
	Verbose bool
}

func (c *VersionCommand) SetFlags(flags *pflag.FlagSet) {
	flags.BoolVarP(&c.Verbose, "verbose", "v", false, DocFlag("Commands/version:Flags/verbose"))
}

func (c *VersionCommand) Run(cmd *cobra.Command, args []string) {
	if c.Verbose {
		cmd.Println(DetailedInfoString())
	} else {
		cmd.Println(VersionString())
	}
}
<|endoftext|>


<commit_before>package nomad

import (
	"fmt"
	"math/rand"
	"net"
	"sync/atomic"
	"time"

	testing "github.com/mitchellh/go-testing-interface"

	"github.com/hashicorp/consul/lib/freeport"
	"github.com/hashicorp/nomad/command/agent/consul"
	"github.com/hashicorp/nomad/helper/pluginutils/catalog"
	"github.com/hashicorp/nomad/helper/pluginutils/singleton"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/hashicorp/nomad/nomad/mock"
	"github.com/hashicorp/nomad/nomad/structs"
)

var (
	nodeNumber uint32 = 0
)

func TestACLServer(t testing.T, cb func(*Config)) (*Server, *structs.ACLToken) {
	server := TestServer(t, func(c *Config) {
		c.ACLEnabled = true
		if cb != nil {
			cb(c)
		}
	})
	token := mock.ACLManagementToken()
	err := server.State().BootstrapACLTokens(1, 0, token)
	if err != nil {
		t.Fatalf("failed to bootstrap ACL token: %v", err)
	}
	return server, token
}

func TestServer(t testing.T, cb func(*Config)) *Server {
	// Setup the default settings
	config := DefaultConfig()
	config.Logger = testlog.HCLogger(t)
	config.Build = "0.8.0+unittest"
	config.DevMode = true
	nodeNum := atomic.AddUint32(&nodeNumber, 1)
	config.NodeName = fmt.Sprintf("nomad-%03d", nodeNum)

	// Tighten the Serf timing
	config.SerfConfig.MemberlistConfig.BindAddr = "127.0.0.1"
	config.SerfConfig.MemberlistConfig.SuspicionMult = 2
	config.SerfConfig.MemberlistConfig.RetransmitMult = 2
	config.SerfConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond
	config.SerfConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond
	config.SerfConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond

	// Tighten the Raft timing
	config.RaftConfig.LeaderLeaseTimeout = 50 * time.Millisecond
	config.RaftConfig.HeartbeatTimeout = 50 * time.Millisecond
	config.RaftConfig.ElectionTimeout = 50 * time.Millisecond
	config.RaftTimeout = 500 * time.Millisecond

	// Disable Vault
	f := false
	config.VaultConfig.Enabled = &f

	// Squelch output when -v isn't specified
	config.LogOutput = testlog.NewWriter(t)

	// Tighten the autopilot timing
	config.AutopilotConfig.ServerStabilizationTime = 100 * time.Millisecond
	config.ServerHealthInterval = 50 * time.Millisecond
	config.AutopilotInterval = 100 * time.Millisecond

	// Set the plugin loaders
	config.PluginLoader = catalog.TestPluginLoader(t)
	config.PluginSingletonLoader = singleton.NewSingletonLoader(config.Logger, config.PluginLoader)

	// Invoke the callback if any
	if cb != nil {
		cb(config)
	}

	// Enable raft as leader if we have bootstrap on
	config.RaftConfig.StartAsLeader = !config.DevDisableBootstrap

	catalog := consul.NewMockCatalog(config.Logger)

	for i := 10; i >= 0; i-- {
		// Get random ports
		ports := freeport.GetT(t, 2)
		config.RPCAddr = &net.TCPAddr{
			IP:   []byte{127, 0, 0, 1},
			Port: ports[0],
		}
		config.SerfConfig.MemberlistConfig.BindPort = ports[1]

		// Create server
		server, err := NewServer(config, catalog)
		if err == nil {
			return server
		} else if i == 0 {
			t.Fatalf("err: %v", err)
		} else {
			if server != nil {
				server.Shutdown()
			}
			wait := time.Duration(rand.Int31n(2000)) * time.Millisecond
			time.Sleep(wait)
		}
	}

	return nil
}

func TestJoin(t testing.T, s1 *Server, other ...*Server) {
	addr := fmt.Sprintf("127.0.0.1:%d",
		s1.config.SerfConfig.MemberlistConfig.BindPort)
	for _, s2 := range other {
		if num, err := s2.Join([]string{addr}); err != nil {
			t.Fatalf("err: %v", err)
		} else if num != 1 {
			t.Fatalf("bad: %d", num)
		}
	}
}
<commit_msg>use current nomad version in testing<commit_after>package nomad

import (
	"fmt"
	"math/rand"
	"net"
	"sync/atomic"
	"time"

	testing "github.com/mitchellh/go-testing-interface"

	"github.com/hashicorp/consul/lib/freeport"
	"github.com/hashicorp/nomad/command/agent/consul"
	"github.com/hashicorp/nomad/helper/pluginutils/catalog"
	"github.com/hashicorp/nomad/helper/pluginutils/singleton"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/hashicorp/nomad/nomad/mock"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/hashicorp/nomad/version"
)

var (
	nodeNumber uint32 = 0
)

func TestACLServer(t testing.T, cb func(*Config)) (*Server, *structs.ACLToken) {
	server := TestServer(t, func(c *Config) {
		c.ACLEnabled = true
		if cb != nil {
			cb(c)
		}
	})
	token := mock.ACLManagementToken()
	err := server.State().BootstrapACLTokens(1, 0, token)
	if err != nil {
		t.Fatalf("failed to bootstrap ACL token: %v", err)
	}
	return server, token
}

func TestServer(t testing.T, cb func(*Config)) *Server {
	// Setup the default settings
	config := DefaultConfig()
	config.Logger = testlog.HCLogger(t)
	config.Build = version.Version + "+unittest"
	config.DevMode = true
	nodeNum := atomic.AddUint32(&nodeNumber, 1)
	config.NodeName = fmt.Sprintf("nomad-%03d", nodeNum)

	// Tighten the Serf timing
	config.SerfConfig.MemberlistConfig.BindAddr = "127.0.0.1"
	config.SerfConfig.MemberlistConfig.SuspicionMult = 2
	config.SerfConfig.MemberlistConfig.RetransmitMult = 2
	config.SerfConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond
	config.SerfConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond
	config.SerfConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond

	// Tighten the Raft timing
	config.RaftConfig.LeaderLeaseTimeout = 50 * time.Millisecond
	config.RaftConfig.HeartbeatTimeout = 50 * time.Millisecond
	config.RaftConfig.ElectionTimeout = 50 * time.Millisecond
	config.RaftTimeout = 500 * time.Millisecond

	// Disable Vault
	f := false
	config.VaultConfig.Enabled = &f

	// Squelch output when -v isn't specified
	config.LogOutput = testlog.NewWriter(t)

	// Tighten the autopilot timing
	config.AutopilotConfig.ServerStabilizationTime = 100 * time.Millisecond
	config.ServerHealthInterval = 50 * time.Millisecond
	config.AutopilotInterval = 100 * time.Millisecond

	// Set the plugin loaders
	config.PluginLoader = catalog.TestPluginLoader(t)
	config.PluginSingletonLoader = singleton.NewSingletonLoader(config.Logger, config.PluginLoader)

	// Invoke the callback if any
	if cb != nil {
		cb(config)
	}

	// Enable raft as leader if we have bootstrap on
	config.RaftConfig.StartAsLeader = !config.DevDisableBootstrap

	catalog := consul.NewMockCatalog(config.Logger)

	for i := 10; i >= 0; i-- {
		// Get random ports
		ports := freeport.GetT(t, 2)
		config.RPCAddr = &net.TCPAddr{
			IP:   []byte{127, 0, 0, 1},
			Port: ports[0],
		}
		config.SerfConfig.MemberlistConfig.BindPort = ports[1]

		// Create server
		server, err := NewServer(config, catalog)
		if err == nil {
			return server
		} else if i == 0 {
			t.Fatalf("err: %v", err)
		} else {
			if server != nil {
				server.Shutdown()
			}
			wait := time.Duration(rand.Int31n(2000)) * time.Millisecond
			time.Sleep(wait)
		}
	}

	return nil
}

func TestJoin(t testing.T, s1 *Server, other ...*Server) {
	addr := fmt.Sprintf("127.0.0.1:%d",
		s1.config.SerfConfig.MemberlistConfig.BindPort)
	for _, s2 := range other {
		if num, err := s2.Join([]string{addr}); err != nil {
			t.Fatalf("err: %v", err)
		} else if num != 1 {
			t.Fatalf("bad: %d", num)
		}
	}
}
<|endoftext|>


<commit_before>package match

import (
	"reflect"
	"testing"
)

func TestMatch(t *testing.T) {
	res := Match(t, nil)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestIsNil(t *testing.T) {
	res := IsNil(t, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestIsNotNil(t *testing.T) {
	res := IsNotNil(t, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestEquals(t *testing.T) {
	res := Equals(t, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestNotEquals(t *testing.T) {
	res := NotEquals(t, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestLessThan(t *testing.T) {
	res := LessThan(t, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestGreaterThan(t *testing.T) {
	res := GreaterThan(t, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestContains(t *testing.T) {
	res := Contains(t, "", "")
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestMatches(t *testing.T) {
	res := Matches(t, "", ".*")
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestKindOf(t *testing.T) {
	res := KindOf(t, 0, reflect.Int32)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}
<commit_msg>Use a blank testing.T in match.go tests<commit_after>package match

import (
	"reflect"
	"testing"
)

func TestMatch(t *testing.T) {
	test := &testing.T{}
	res := Match(test, nil)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestIsNil(t *testing.T) {
	test := &testing.T{}
	res := IsNil(test, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestIsNotNil(t *testing.T) {
	test := &testing.T{}
	res := IsNotNil(test, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestEquals(t *testing.T) {
	test := &testing.T{}
	res := Equals(test, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestNotEquals(t *testing.T) {
	test := &testing.T{}
	res := NotEquals(test, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestLessThan(t *testing.T) {
	test := &testing.T{}
	res := LessThan(test, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestGreaterThan(t *testing.T) {
	test := &testing.T{}
	res := GreaterThan(test, 0, 0)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestContains(t *testing.T) {
	test := &testing.T{}
	res := Contains(test, "", "")
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestMatches(t *testing.T) {
	test := &testing.T{}
	res := Matches(test, "", ".*")
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}

func TestKindOf(t *testing.T) {
	test := &testing.T{}
	res := KindOf(test, 0, reflect.Int32)
	if res == nil {
		t.Errorf("Expected a value, got nil")
	}
}
<|endoftext|>


<commit_before>package etcd

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"path"
	"time"

	"github.com/coreos/etcd/config"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/store"
)

const (
	defaultHeartbeat = 1
	defaultElection  = 5

	defaultTickDuration = time.Millisecond * 100

	v2machineKVPrefix  = "/_etcd/machines"
	v2Prefix           = "/v2/keys"
	v2machinePrefix    = "/v2/machines"
	v2peersPrefix      = "/v2/peers"
	v2LeaderPrefix     = "/v2/leader"
	v2StoreStatsPrefix = "/v2/stats/store"

	raftPrefix = "/raft"
)

type Server struct {
	config *config.Config

	id           int64
	pubAddr      string
	raftPubAddr  string
	nodes        map[string]bool
	tickDuration time.Duration

	proposal chan v2Proposal
	node     *v2Raft
	t        *transporter

	store.Store

	stop chan struct{}

	http.Handler
}

func New(c *config.Config, id int64) *Server {
	if err := c.Sanitize(); err != nil {
		log.Fatalf("failed sanitizing configuration: %v", err)
	}

	tc := &tls.Config{
		InsecureSkipVerify: true,
	}
	var err error
	if c.PeerTLSInfo().Scheme() == "https" {
		tc, err = c.PeerTLSInfo().ClientConfig()
		if err != nil {
			log.Fatal("failed to create raft transporter tls:", err)
		}
	}

	s := &Server{
		config:       c,
		id:           id,
		pubAddr:      c.Addr,
		raftPubAddr:  c.Peer.Addr,
		nodes:        make(map[string]bool),
		tickDuration: defaultTickDuration,
		proposal:     make(chan v2Proposal),
		node: &v2Raft{
			Node:   raft.New(id, defaultHeartbeat, defaultElection),
			result: make(map[wait]chan interface{}),
		},
		t: newTransporter(tc),

		Store: store.New(),

		stop: make(chan struct{}),
	}

	for _, seed := range c.Peers {
		s.nodes[seed] = true
	}

	m := http.NewServeMux()
	//m.Handle("/HEAD", handlerErr(s.serveHead))
	m.Handle(v2Prefix+"/", handlerErr(s.serveValue))
	m.Handle(v2machinePrefix, handlerErr(s.serveMachines))
	m.Handle(v2peersPrefix, handlerErr(s.serveMachines))
	m.Handle(v2LeaderPrefix, handlerErr(s.serveLeader))
	m.Handle(v2StoreStatsPrefix, handlerErr(s.serveStoreStats))
	s.Handler = m
	return s
}

func (s *Server) SetTick(d time.Duration) {
	s.tickDuration = d
}

func (s *Server) RaftHandler() http.Handler {
	return s.t
}

func (s *Server) Run() {
	if len(s.config.Peers) == 0 {
		s.Bootstrap()
	} else {
		s.Join()
	}
}

func (s *Server) Stop() {
	close(s.stop)
	s.t.stop()
}

func (s *Server) Bootstrap() {
	log.Println("starting a bootstrap node")
	s.node.Campaign()
	s.node.Add(s.id, s.raftPubAddr, []byte(s.pubAddr))
	s.apply(s.node.Next())
	s.run()
}

func (s *Server) Join() {
	log.Println("joining cluster via peers", s.config.Peers)
	d, err := json.Marshal(&raft.Config{s.id, s.raftPubAddr, []byte(s.pubAddr)})
	if err != nil {
		panic(err)
	}

	b, err := json.Marshal(&raft.Message{From: s.id, Type: 2, Entries: []raft.Entry{{Type: 1, Data: d}}})
	if err != nil {
		panic(err)
	}

	for seed := range s.nodes {
		if err := s.t.send(seed+raftPrefix, b); err != nil {
			log.Println(err)
			continue
		}
		// todo(xiangli) WAIT for join to be committed or retry...
		break
	}
	s.run()
}

func (s *Server) run() {
	node := s.node
	recv := s.t.recv
	ticker := time.NewTicker(s.tickDuration)
	v2SyncTicker := time.NewTicker(time.Millisecond * 500)

	var proposal chan v2Proposal
	for {
		if node.HasLeader() {
			proposal = s.proposal
		} else {
			proposal = nil
		}
		select {
		case p := <-proposal:
			node.Propose(p)
		case msg := <-recv:
			node.Step(*msg)
		case <-ticker.C:
			node.Tick()
		case <-v2SyncTicker.C:
			node.Sync()
		case <-s.stop:
			log.Printf("Node: %d stopped\n", s.id)
			return
		}
		s.apply(node.Next())
		s.send(node.Msgs())
	}
}

func (s *Server) apply(ents []raft.Entry) {
	offset := s.node.Applied() - int64(len(ents)) + 1
	for i, ent := range ents {
		switch ent.Type {
		// expose raft entry type
		case raft.Normal:
			if len(ent.Data) == 0 {
				continue
			}
			s.v2apply(offset+int64(i), ent)
		case raft.AddNode:
			cfg := new(raft.Config)
			if err := json.Unmarshal(ent.Data, cfg); err != nil {
				log.Println(err)
				break
			}
			if err := s.t.set(cfg.NodeId, cfg.Addr); err != nil {
				log.Println(err)
				break
			}
			log.Printf("Add Node %x %v %v\n", cfg.NodeId, cfg.Addr, string(cfg.Context))
			s.nodes[cfg.Addr] = true
			p := path.Join(v2machineKVPrefix, fmt.Sprint(cfg.NodeId))
			s.Store.Set(p, false, fmt.Sprintf("raft=%v&etcd=%v", cfg.Addr, string(cfg.Context)), store.Permanent)
		default:
			panic("unimplemented")
		}
	}
}

func (s *Server) send(msgs []raft.Message) {
	for i := range msgs {
		data, err := json.Marshal(msgs[i])
		if err != nil {
			// todo(xiangli): error handling
			log.Fatal(err)
		}
		// todo(xiangli): reuse routines and limit the number of sending routines
		// sync.Pool?
		go func(i int) {
			var err error
			if err = s.t.sendTo(msgs[i].To, data); err == nil {
				return
			}
			if err == errUnknownNode {
				err = s.fetchAddr(msgs[i].To)
			}
			if err == nil {
				err = s.t.sendTo(msgs[i].To, data)
			}
			if err != nil {
				log.Println(err)
			}
		}(i)
	}
}

func (s *Server) fetchAddr(nodeId int64) error {
	for seed := range s.nodes {
		if err := s.t.fetchAddr(seed, nodeId); err == nil {
			return nil
		}
	}
	return fmt.Errorf("cannot fetch the address of node %d", nodeId)
}
<commit_msg>etcd: fake standby<commit_after>package etcd

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"path"
	"time"

	"github.com/coreos/etcd/config"
	"github.com/coreos/etcd/raft"
	"github.com/coreos/etcd/store"
)

const (
	defaultHeartbeat = 1
	defaultElection  = 5

	defaultTickDuration = time.Millisecond * 100

	v2machineKVPrefix  = "/_etcd/machines"
	v2Prefix           = "/v2/keys"
	v2machinePrefix    = "/v2/machines"
	v2peersPrefix      = "/v2/peers"
	v2LeaderPrefix     = "/v2/leader"
	v2StoreStatsPrefix = "/v2/stats/store"

	raftPrefix = "/raft"
)

const (
	participant = iota
	standby
	stop
)

type Server struct {
	config *config.Config

	mode int

	id           int64
	pubAddr      string
	raftPubAddr  string
	nodes        map[string]bool
	tickDuration time.Duration

	proposal chan v2Proposal
	node     *v2Raft
	t        *transporter

	store.Store

	stop chan struct{}

	http.Handler
}

func New(c *config.Config, id int64) *Server {
	if err := c.Sanitize(); err != nil {
		log.Fatalf("failed sanitizing configuration: %v", err)
	}

	tc := &tls.Config{
		InsecureSkipVerify: true,
	}
	var err error
	if c.PeerTLSInfo().Scheme() == "https" {
		tc, err = c.PeerTLSInfo().ClientConfig()
		if err != nil {
			log.Fatal("failed to create raft transporter tls:", err)
		}
	}

	s := &Server{
		config:       c,
		id:           id,
		pubAddr:      c.Addr,
		raftPubAddr:  c.Peer.Addr,
		nodes:        make(map[string]bool),
		tickDuration: defaultTickDuration,
		proposal:     make(chan v2Proposal),
		node: &v2Raft{
			Node:   raft.New(id, defaultHeartbeat, defaultElection),
			result: make(map[wait]chan interface{}),
		},
		t: newTransporter(tc),

		Store: store.New(),

		stop: make(chan struct{}),
	}

	for _, seed := range c.Peers {
		s.nodes[seed] = true
	}

	m := http.NewServeMux()
	m.Handle(v2Prefix+"/", handlerErr(s.serveValue))
	m.Handle(v2machinePrefix, handlerErr(s.serveMachines))
	m.Handle(v2peersPrefix, handlerErr(s.serveMachines))
	m.Handle(v2LeaderPrefix, handlerErr(s.serveLeader))
	m.Handle(v2StoreStatsPrefix, handlerErr(s.serveStoreStats))
	s.Handler = m
	return s
}

func (s *Server) SetTick(d time.Duration) {
	s.tickDuration = d
}

func (s *Server) RaftHandler() http.Handler {
	return s.t
}

func (s *Server) Run() {
	if len(s.config.Peers) == 0 {
		s.Bootstrap()
	} else {
		s.Join()
	}
}

func (s *Server) Stop() {
	close(s.stop)
	s.t.stop()
}

func (s *Server) Bootstrap() {
	log.Println("starting a bootstrap node")
	s.node.Campaign()
	s.node.Add(s.id, s.raftPubAddr, []byte(s.pubAddr))
	s.apply(s.node.Next())
	s.run()
}

func (s *Server) Join() {
	log.Println("joining cluster via peers", s.config.Peers)
	d, err := json.Marshal(&raft.Config{s.id, s.raftPubAddr, []byte(s.pubAddr)})
	if err != nil {
		panic(err)
	}

	b, err := json.Marshal(&raft.Message{From: s.id, Type: 2, Entries: []raft.Entry{{Type: 1, Data: d}}})
	if err != nil {
		panic(err)
	}

	for seed := range s.nodes {
		if err := s.t.send(seed+raftPrefix, b); err != nil {
			log.Println(err)
			continue
		}
		// todo(xiangli) WAIT for join to be committed or retry...
		break
	}
	s.run()
}

func (s *Server) run() {
	for {
		switch s.mode {
		case participant:
			s.runParticipant()
		case standby:
			s.runStandby()
		case stop:
			return
		default:
			panic("unsupport mode")
		}
	}
}

func (s *Server) runParticipant() {
	node := s.node
	recv := s.t.recv
	ticker := time.NewTicker(s.tickDuration)
	v2SyncTicker := time.NewTicker(time.Millisecond * 500)

	var proposal chan v2Proposal
	for {
		if node.HasLeader() {
			proposal = s.proposal
		} else {
			proposal = nil
		}
		select {
		case p := <-proposal:
			node.Propose(p)
		case msg := <-recv:
			node.Step(*msg)
		case <-ticker.C:
			node.Tick()
		case <-v2SyncTicker.C:
			node.Sync()
		case <-s.stop:
			log.Printf("Node: %d stopped\n", s.id)
			s.mode = stop
			return
		}
		s.apply(node.Next())
		s.send(node.Msgs())
	}
}

func (s *Server) runStandby() {
	panic("unimplemented")
}

func (s *Server) apply(ents []raft.Entry) {
	offset := s.node.Applied() - int64(len(ents)) + 1
	for i, ent := range ents {
		switch ent.Type {
		// expose raft entry type
		case raft.Normal:
			if len(ent.Data) == 0 {
				continue
			}
			s.v2apply(offset+int64(i), ent)
		case raft.AddNode:
			cfg := new(raft.Config)
			if err := json.Unmarshal(ent.Data, cfg); err != nil {
				log.Println(err)
				break
			}
			if err := s.t.set(cfg.NodeId, cfg.Addr); err != nil {
				log.Println(err)
				break
			}
			log.Printf("Add Node %x %v %v\n", cfg.NodeId, cfg.Addr, string(cfg.Context))
			s.nodes[cfg.Addr] = true
			p := path.Join(v2machineKVPrefix, fmt.Sprint(cfg.NodeId))
			s.Store.Set(p, false, fmt.Sprintf("raft=%v&etcd=%v", cfg.Addr, string(cfg.Context)), store.Permanent)
		default:
			panic("unimplemented")
		}
	}
}

func (s *Server) send(msgs []raft.Message) {
	for i := range msgs {
		data, err := json.Marshal(msgs[i])
		if err != nil {
			// todo(xiangli): error handling
			log.Fatal(err)
		}
		// todo(xiangli): reuse routines and limit the number of sending routines
		// sync.Pool?
		go func(i int) {
			var err error
			if err = s.t.sendTo(msgs[i].To, data); err == nil {
				return
			}
			if err == errUnknownNode {
				err = s.fetchAddr(msgs[i].To)
			}
			if err == nil {
				err = s.t.sendTo(msgs[i].To, data)
			}
			if err != nil {
				log.Println(err)
			}
		}(i)
	}
}

func (s *Server) fetchAddr(nodeId int64) error {
	for seed := range s.nodes {
		if err := s.t.fetchAddr(seed, nodeId); err == nil {
			return nil
		}
	}
	return fmt.Errorf("cannot fetch the address of node %d", nodeId)
}
<|endoftext|>


<commit_before>// +build OMIT

package main

import (
	"fmt"
	"net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(
	w http.ResponseWriter,
	r *http.Request) {
	fmt.Fprint(w, "Hello!")
}

func main() {
	var h Hello
	http.ListenAndServe("localhost:4000", h)
}
<commit_msg>go-tour: handle error from ListenAndServe<commit_after>// +build OMIT

package main

import (
	"fmt"
	"log"
	"net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(
	w http.ResponseWriter,
	r *http.Request) {
	fmt.Fprint(w, "Hello!")
}

func main() {
	var h Hello
	err := http.ListenAndServe("localhost:4000", h)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package ohaus

import (
	"bufio"
	"encoding/json"
	serial "github.com/tarm/serial"
	"log"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

type Scale struct {
	PortName string
}

type Datum struct {
	Time   time.Time `json:"time"`
	Weight float64   `json:"weight"`
	Unit   string    `json:"unit"`
}

func (scale Scale) Open() (port *serial.Port, err error) {
	c := &serial.Config{Name: scale.PortName, Baud: 9600}
	port, err = serial.OpenPort(c)
	return
}

func (scale Scale) Read(port *serial.Port) (value string, err error) {
	port.Write([]byte("IP\r\n"))
	scanner := bufio.NewScanner(port)
	scanner.Scan()
	value = scanner.Text()
	err = scanner.Err()
	return
}

func (scale Scale) TestReader(c chan Datum) {
	var d Datum
	d.Unit = "kg"
	for {
		d.Time = time.Now()
		d.Weight = rand.Float64()
		c <- d
		time.Sleep(2 * time.Second)
	}
}

func (scale Scale) Reader(c chan Datum) {
	f, err := os.OpenFile("backup-data.json", os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		panic(err)
	}

	defer f.Close()

	var d Datum
	for {
		port, err := scale.Open()

		if err != nil {
			log.Println(err)
			time.Sleep(2 * time.Second)
			continue
		}
		for {
			current_time := time.Now()
			v, err := scale.Read(port)
			if err != nil {
				port.Close()
				log.Println(err)
				break
			}
			value := strings.Split(strings.Trim(v, " "), " ")
			weight, err := strconv.ParseFloat(value[0], 64)
			if err != nil || len(value) < 2 {
				port.Close()
				log.Println(err)
				break
			}

			d.Time = current_time
			d.Weight = weight
			d.Unit = value[1]

			c <- d

			text, err := json.Marshal(d)
			if err != nil {
				log.Println(err)
				continue
			}
			if _, err = f.WriteString(string(text)); err != nil {
				log.Println(err)
				continue
			}

			time.Sleep(60 * time.Second)
		}

	}
}
<commit_msg>moved to regex for more robust parsing<commit_after>package ohaus

import (
	"bufio"
	"encoding/json"
	serial "github.com/tarm/serial"
	"log"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
  "regexp"
  "fmt"
)

type Scale struct {
	PortName string
}

type Datum struct {
	Time   time.Time `json:"time"`
	Weight float64   `json:"weight"`
	Unit   string    `json:"unit"`
}

func (scale Scale) Open() (port *serial.Port, err error) {
	c := &serial.Config{Name: scale.PortName, Baud: 9600}
	port, err = serial.OpenPort(c)
	return
}

func (scale Scale) Read(port *serial.Port) (value string, err error) {
	port.Write([]byte("IP\r\n"))
	scanner := bufio.NewScanner(port)
	scanner.Scan()
	value = scanner.Text()
	err = scanner.Err()
	return
}

func (scale Scale) TestReader(c chan Datum) {
	var d Datum
	d.Unit = "kg"
	for {
		d.Time = time.Now()
		d.Weight = rand.Float64()
		c <- d
		time.Sleep(2 * time.Second)
	}
}

func (scale Scale) Reader(c chan Datum) {
	f, err := os.OpenFile("backup-data.json", os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		panic(err)
	}

  r , err := regexp.Compile("^(.{11}) {5}([a-z])")
  if err != nil {
    panic(err)
  }

	defer f.Close()

	var d Datum
	for {
		port, err := scale.Open()

		if err != nil {
			log.Println(err)
			time.Sleep(2 * time.Second)
			continue
		}
		for {
			current_time := time.Now()
			v, err := scale.Read(port)
			if err != nil {
				port.Close()
				log.Println(err)
				break
			}
      log.Println(v)

      match := r.FindStringSubmatch(v)
      if (match == nil) {
        port.Close()
        // log.Println("no match")
        break
      }
      if len(match[1]) != 11 {
				port.Close()
				log.Println("short value")
        log.Println(match)
				break
      }

			weight, err := strconv.ParseFloat(strings.Trim(match[1]," "), 64)
			if err != nil {
				port.Close()
				log.Println(err)
				break
			}

			d.Time = current_time
			d.Weight = weight
			d.Unit = match[2]

			c <- d

			text, err := json.Marshal(d)
			if err != nil {
				log.Println(err)
				continue
			}
			if _, err = f.WriteString(string(text)); err != nil {
				log.Println(err)
				continue
			}

			time.Sleep(10 * time.Second)
		}

	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/spf13/cobra"

	// Used by cgo
	_ "github.com/lxc/lxd/lxd/include"
)

/*
#include "config.h"

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fsuid.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>

#include "lxd.h"
#include "error_utils.h"
#include "file_utils.h"
#include "macro.h"
#include "memory_utils.h"
#include "mount_utils.h"
#include "process_utils.h"
#include "syscall_numbers.h"
#include "syscall_wrappers.h"

#ifndef PIPEFS_MAGIC
#define PIPEFS_MAGIC 0x50495045
#endif

#define FD_PIPE_UIDMAP 3
#define FD_PIPE_GIDMAP 4

#define MAP_SIZE ((ssize_t)4096)

typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic;
static bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val)
{
	return (fs->f_type == (fs_type_magic)magic_val);
}

static bool fhas_fs_type(int fd, fs_type_magic magic_val)
{
	int ret;
	struct statfs sb;

	ret = fstatfs(fd, &sb);
	if (ret < 0)
		return false;

	return is_fs_type(&sb, magic_val);
}

static inline bool drop_groups(void)
{
	return setgroups(0, NULL) == 0;
}

static inline bool switch_resids(uid_t uid, gid_t gid)
{
	if (setresgid(gid, gid, gid))
		return false;

	if (setresuid(uid, uid, uid))
		return false;

	if (setfsgid(-1) != gid)
		return false;

	if (setfsuid(-1) != uid)
		return false;

	return true;
}

static int write_id_mapping(bool is_uid)
{
	__do_close int fd_idmap = -EBADF;
	ssize_t bytes_read, ret;
	char buf[PROC_PID_IDMAP_LEN], idmap[LXC_IDMAPLEN];

	if (is_uid)
		ret = strnprintf(buf, sizeof(buf), "/proc/%d/uid_map", getppid());
	else
		ret = strnprintf(buf, sizeof(buf), "/proc/%d/gid_map", getppid());
	if (ret < 0)
		return -errno;

	fd_idmap = open(buf, O_WRONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
	if (fd_idmap < 0)
		return -1;

	if (is_uid)
		bytes_read = read_nointr(FD_PIPE_UIDMAP, idmap, sizeof(idmap));
	else
		bytes_read = read_nointr(FD_PIPE_GIDMAP, idmap, sizeof(idmap));
	if (bytes_read < 0 || bytes_read >= sizeof(idmap))
		return -errno;

	ret = write_nointr(fd_idmap, idmap, bytes_read);
	if (ret < 0 || ret != bytes_read)
		return -errno;

	return 0;
}

static int write_id_mappings(void)
{
	int ret;

	ret = write_id_mapping(true);
	if (!ret)
		ret = write_id_mapping(false);
	return ret;
}

static int safe_uint(const char *numstr, unsigned int *converted)
{
	char *err = NULL;
	unsigned long int uli;

	while (isspace(*numstr))
		numstr++;

	if (*numstr == '-')
		return -EINVAL;

	errno = 0;
	uli = strtoul(numstr, &err, 0);
	if (errno == ERANGE && uli == ULONG_MAX)
		return -ERANGE;

	if (err == numstr || *err != '\0')
		return -EINVAL;

	if (uli > UINT_MAX)
		return -ERANGE;

	*converted = (unsigned int)uli;
	return 0;
}

__attribute__ ((noinline)) int __forkusernsexec(void)
{
	__do_free_string_list char **argvp = NULL;
	pid_t pid;
	ssize_t ret;
	int fd_socket[2];
	char c;
	char *cur;
	unsigned int keep_fd_up_to = STDERR_FILENO;

	if (geteuid() != 0)
		return log_error(EXIT_FAILURE, "Error: forkexec requires root privileges");

	cur = advance_arg(false);
	if (!cur || (strcmp(cur, "--help") == 0 ||
	     strcmp(cur, "--version") == 0 || strcmp(cur, "-h") == 0))
		return EXIT_SUCCESS;

	if (strncmp(cur, "--keep-fd-up-to=", STRLITERALLEN("--keep-fd-up-to=")) == 0) {
		cur += STRLITERALLEN("--keep-fd-up-to=");
		ret = safe_uint(cur, &keep_fd_up_to);
		if (ret)
			return log_error(EXIT_FAILURE, "Invalid fd number %s specified", cur);
	}

	if (!fhas_fs_type(FD_PIPE_UIDMAP, PIPEFS_MAGIC))
		return log_error(EXIT_FAILURE, "Error: Missing UID map FD");

	if (!fhas_fs_type(FD_PIPE_GIDMAP, PIPEFS_MAGIC))
		return log_error(EXIT_FAILURE, "Error: Missing GID map FD");

	ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fd_socket);
	if (ret < 0)
		return EXIT_FAILURE;

	pid = fork();
	if (pid < 0)
		return EXIT_FAILURE;

	if (pid == 0) {
		close_prot_errno_disarm(fd_socket[0]);

		ret = read_nointr(fd_socket[1], &c, 1);
		if (ret != 1)
			_exit(EXIT_FAILURE);

		ret = write_id_mappings();
		if (ret < 0)
			_exit(EXIT_FAILURE);

		ret = write_nointr(fd_socket[1], &c, 1);
		if (ret != 1)
			_exit(EXIT_FAILURE);

		_exit(EXIT_SUCCESS);
	}

	close_prot_errno_disarm(fd_socket[1]);

	ret = unshare(CLONE_NEWUSER);
	if (ret) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	ret = write_nointr(fd_socket[0], &c, 1);
	if (ret == 1)
		ret = read_nointr(fd_socket[0], &c, 1);
	if (ret != 1) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	if (!drop_groups()) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	if (!switch_resids(0, 0)) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	close_prot_errno_disarm(fd_socket[0]);

out_reap:
	ret = wait_for_pid(pid);
	if (ret)
		return EXIT_FAILURE;

	ret = push_vargs(&argvp, cur);
	if (ret < 0)
		return log_error(EXIT_FAILURE, "Failed to add %s to arg array", cur);

	for (cur = NULL; (cur = advance_arg(false)); ) {
		ret = push_vargs(&argvp, cur);
		if (ret < 0)
			return log_error(EXIT_FAILURE, "Failed to add %s to arg array", cur);
	}

	if (!argvp || !*argvp)
		return log_error(EXIT_FAILURE, "No command specified");

	ret = lxd_close_range(keep_fd_up_to + 1, UINT_MAX, CLOSE_RANGE_CLOEXEC);
	if (ret && !IN_SET(errno, ENOSYS, EINVAL))
		return log_error(EXIT_FAILURE, "Aborting forkusernsexec to prevent leaking file descriptors");

	execvp(argvp[0], argvp);
	return EXIT_FAILURE;
}

void forkusernsexec(void)
{
	_exit(__forkusernsexec());
}
*/
import "C"

type cmdForkusernsexec struct {
	global     *cmdGlobal
	keepFdUpTo int
}

func (c *cmdForkusernsexec) Command() *cobra.Command {
	// Main subcommand
	cmd := &cobra.Command{}
	cmd.Use = "forkusernsexec <cmd> <args>"
	cmd.Short = "Run command in user namespace"
	cmd.Flags().IntVar(&c.keepFdUpTo, "keep-fd-up-to", (1 << 31), fmt.Sprintf("Keep all fds below and including this one and close all the ones above it"))
	cmd.Long = `Description:
  Run command in user namespace

  This command is used to execute a program in a new user namespace.
`
	cmd.RunE = c.Run
	cmd.Hidden = true

	return cmd
}

func (c *cmdForkusernsexec) Run(cmd *cobra.Command, args []string) error {
	return fmt.Errorf("This command should have been intercepted in cgo")
}
<commit_msg>forkusernsexec: parse command section correctly<commit_after>package main

import (
	"fmt"

	"github.com/spf13/cobra"

	// Used by cgo
	_ "github.com/lxc/lxd/lxd/include"
)

/*
#include "config.h"

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fsuid.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>

#include "lxd.h"
#include "error_utils.h"
#include "file_utils.h"
#include "macro.h"
#include "memory_utils.h"
#include "mount_utils.h"
#include "process_utils.h"
#include "syscall_numbers.h"
#include "syscall_wrappers.h"

#ifndef PIPEFS_MAGIC
#define PIPEFS_MAGIC 0x50495045
#endif

#define FD_PIPE_UIDMAP 3
#define FD_PIPE_GIDMAP 4

#define MAP_SIZE ((ssize_t)4096)

typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic;
static bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val)
{
	return (fs->f_type == (fs_type_magic)magic_val);
}

static bool fhas_fs_type(int fd, fs_type_magic magic_val)
{
	int ret;
	struct statfs sb;

	ret = fstatfs(fd, &sb);
	if (ret < 0)
		return false;

	return is_fs_type(&sb, magic_val);
}

static inline bool drop_groups(void)
{
	return setgroups(0, NULL) == 0;
}

static inline bool switch_resids(uid_t uid, gid_t gid)
{
	if (setresgid(gid, gid, gid))
		return false;

	if (setresuid(uid, uid, uid))
		return false;

	if (setfsgid(-1) != gid)
		return false;

	if (setfsuid(-1) != uid)
		return false;

	return true;
}

static int write_id_mapping(bool is_uid)
{
	__do_close int fd_idmap = -EBADF;
	ssize_t bytes_read, ret;
	char buf[PROC_PID_IDMAP_LEN], idmap[LXC_IDMAPLEN];

	if (is_uid)
		ret = strnprintf(buf, sizeof(buf), "/proc/%d/uid_map", getppid());
	else
		ret = strnprintf(buf, sizeof(buf), "/proc/%d/gid_map", getppid());
	if (ret < 0)
		return -errno;

	fd_idmap = open(buf, O_WRONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
	if (fd_idmap < 0)
		return -1;

	if (is_uid)
		bytes_read = read_nointr(FD_PIPE_UIDMAP, idmap, sizeof(idmap));
	else
		bytes_read = read_nointr(FD_PIPE_GIDMAP, idmap, sizeof(idmap));
	if (bytes_read < 0 || bytes_read >= sizeof(idmap))
		return -errno;

	ret = write_nointr(fd_idmap, idmap, bytes_read);
	if (ret < 0 || ret != bytes_read)
		return -errno;

	return 0;
}

static int write_id_mappings(void)
{
	int ret;

	ret = write_id_mapping(true);
	if (!ret)
		ret = write_id_mapping(false);
	return ret;
}

static int safe_uint(const char *numstr, unsigned int *converted)
{
	char *err = NULL;
	unsigned long int uli;

	while (isspace(*numstr))
		numstr++;

	if (*numstr == '-')
		return -EINVAL;

	errno = 0;
	uli = strtoul(numstr, &err, 0);
	if (errno == ERANGE && uli == ULONG_MAX)
		return -ERANGE;

	if (err == numstr || *err != '\0')
		return -EINVAL;

	if (uli > UINT_MAX)
		return -ERANGE;

	*converted = (unsigned int)uli;
	return 0;
}

__attribute__ ((noinline)) int __forkusernsexec(void)
{
	__do_free_string_list char **argvp = NULL;
	pid_t pid;
	ssize_t ret;
	int fd_socket[2];
	char c;
	char *cur;
	unsigned int keep_fd_up_to = STDERR_FILENO;

	if (geteuid() != 0)
		return log_error(EXIT_FAILURE, "Error: forkexec requires root privileges");

	cur = advance_arg(false);
	if (!cur || (strcmp(cur, "--help") == 0 ||
	     strcmp(cur, "--version") == 0 || strcmp(cur, "-h") == 0))
		return EXIT_SUCCESS;

	if (strncmp(cur, "--keep-fd-up-to=", STRLITERALLEN("--keep-fd-up-to=")) == 0) {
		cur += STRLITERALLEN("--keep-fd-up-to=");
		ret = safe_uint(cur, &keep_fd_up_to);
		if (ret)
			return log_error(EXIT_FAILURE, "Invalid fd number %s specified", cur);

		cur = advance_arg(true);
	}

	if (!fhas_fs_type(FD_PIPE_UIDMAP, PIPEFS_MAGIC))
		return log_error(EXIT_FAILURE, "Error: Missing UID map FD");

	if (!fhas_fs_type(FD_PIPE_GIDMAP, PIPEFS_MAGIC))
		return log_error(EXIT_FAILURE, "Error: Missing GID map FD");

	ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fd_socket);
	if (ret < 0)
		return EXIT_FAILURE;

	pid = fork();
	if (pid < 0)
		return EXIT_FAILURE;

	if (pid == 0) {
		close_prot_errno_disarm(fd_socket[0]);

		ret = read_nointr(fd_socket[1], &c, 1);
		if (ret != 1)
			_exit(EXIT_FAILURE);

		ret = write_id_mappings();
		if (ret < 0)
			_exit(EXIT_FAILURE);

		ret = write_nointr(fd_socket[1], &c, 1);
		if (ret != 1)
			_exit(EXIT_FAILURE);

		_exit(EXIT_SUCCESS);
	}

	close_prot_errno_disarm(fd_socket[1]);

	ret = unshare(CLONE_NEWUSER);
	if (ret) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	ret = write_nointr(fd_socket[0], &c, 1);
	if (ret == 1)
		ret = read_nointr(fd_socket[0], &c, 1);
	if (ret != 1) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	if (!drop_groups()) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	if (!switch_resids(0, 0)) {
		kill(pid, SIGKILL);
		goto out_reap;
	}

	close_prot_errno_disarm(fd_socket[0]);

out_reap:
	ret = wait_for_pid(pid);
	if (ret)
		return EXIT_FAILURE;

	for (; cur; cur = advance_arg(false)) {
		ret = push_vargs(&argvp, cur);
		if (ret < 0)
			return log_error(EXIT_FAILURE, "Failed to add %s to arg array", cur);
	}

	if (!argvp || !*argvp)
		return log_error(EXIT_FAILURE, "No command specified");

	ret = lxd_close_range(keep_fd_up_to + 1, UINT_MAX, CLOSE_RANGE_CLOEXEC);
	if (ret && !IN_SET(errno, ENOSYS, EINVAL))
		return log_error(EXIT_FAILURE, "Aborting forkusernsexec to prevent leaking file descriptors");

	execvp(argvp[0], argvp);
	return EXIT_FAILURE;
}

void forkusernsexec(void)
{
	_exit(__forkusernsexec());
}
*/
import "C"

type cmdForkusernsexec struct {
	global     *cmdGlobal
	keepFdUpTo int
}

func (c *cmdForkusernsexec) Command() *cobra.Command {
	// Main subcommand
	cmd := &cobra.Command{}
	cmd.Use = "forkusernsexec <cmd> <args>"
	cmd.Short = "Run command in user namespace"
	cmd.Flags().IntVar(&c.keepFdUpTo, "keep-fd-up-to", (1 << 31), fmt.Sprintf("Keep all fds below and including this one and close all the ones above it"))
	cmd.Long = `Description:
  Run command in user namespace

  This command is used to execute a program in a new user namespace.
`
	cmd.RunE = c.Run
	cmd.Hidden = true

	return cmd
}

func (c *cmdForkusernsexec) Run(cmd *cobra.Command, args []string) error {
	return fmt.Errorf("This command should have been intercepted in cgo")
}
<|endoftext|>


<commit_before>package bzulip

import (
	"encoding/json"
	"io/ioutil"
	"strconv"
	"sync"
	"time"

	"github.com/42wim/matterbridge/bridge"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/bridge/helper"
	gzb "github.com/matterbridge/gozulipbot"
)

type Bzulip struct {
	q       *gzb.Queue
	bot     *gzb.Bot
	streams map[int]string
	*bridge.Config
	channelToTopic map[string]string
	sync.RWMutex
}

func New(cfg *bridge.Config) bridge.Bridger {
	return &Bzulip{Config: cfg, streams: make(map[int]string), channelToTopic: make(map[string]string)}
}

func (b *Bzulip) Connect() error {
	bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login")}
	bot.Init()
	q, err := bot.RegisterAll()
	b.q = q
	b.bot = &bot
	if err != nil {
		b.Log.Errorf("Connect() %#v", err)
		return err
	}
	// init stream
	b.getChannel(0)
	b.Log.Info("Connection succeeded")
	go b.handleQueue()
	return nil
}

func (b *Bzulip) Disconnect() error {
	return nil
}

func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
	b.Lock()
	defer b.Unlock()
	b.channelToTopic[channel.Name] = channel.Options.Topic
	return nil
}

func (b *Bzulip) Send(msg config.Message) (string, error) {
	b.Log.Debugf("=> Receiving %#v", msg)

	// Delete message
	if msg.Event == config.EventMsgDelete {
		if msg.ID == "" {
			return "", nil
		}
		_, err := b.bot.UpdateMessage(msg.ID, "")
		return "", err
	}

	// Upload a file if it exists
	if msg.Extra != nil {
		for _, rmsg := range helper.HandleExtra(&msg, b.General) {
			b.sendMessage(rmsg)
		}
		if len(msg.Extra["file"]) > 0 {
			return b.handleUploadFile(&msg)
		}
	}

	// edit the message if we have a msg ID
	if msg.ID != "" {
		_, err := b.bot.UpdateMessage(msg.ID, msg.Username+msg.Text)
		return "", err
	}

	// Post normal message
	return b.sendMessage(msg)
}

func (b *Bzulip) getChannel(id int) string {
	if name, ok := b.streams[id]; ok {
		return name
	}
	streams, err := b.bot.GetRawStreams()
	if err != nil {
		b.Log.Errorf("getChannel: %#v", err)
		return ""
	}
	for _, stream := range streams.Streams {
		b.streams[stream.StreamID] = stream.Name
	}
	if name, ok := b.streams[id]; ok {
		return name
	}
	return ""
}

func (b *Bzulip) handleQueue() error {
	for {
		messages, err := b.q.GetEvents()
		switch err {
		case gzb.BackoffError:
			time.Sleep(time.Second * 5)
		case gzb.NoJSONError:
			b.Log.Error("Response wasn't JSON, server down or restarting? sleeping 10 seconds")
			time.Sleep(time.Second * 10)
		case gzb.BadEventQueueError:
			b.Log.Info("got a bad event queue id error, reconnecting")
			b.bot.Queues = nil
			b.q, err = b.bot.RegisterAll()
			if err != nil {
				b.Log.Errorf("reconnecting failed: %s. Sleeping 10 seconds", err)
				time.Sleep(time.Second * 10)
				continue
			}
		case gzb.HeartbeatError:
			b.Log.Debug("heartbeat received.")
		default:
			b.Log.Debugf("receiving error: %#v", err)
		}
		if err != nil {
			continue
		}
		for _, m := range messages {
			b.Log.Debugf("== Receiving %#v", m)
			// ignore our own messages
			if m.SenderEmail == b.GetString("login") {
				continue
			}
			rmsg := config.Message{Username: m.SenderFullName, Text: m.Content, Channel: b.getChannel(m.StreamID), Account: b.Account, UserID: strconv.Itoa(m.SenderID), Avatar: m.AvatarURL}
			b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
			b.Log.Debugf("<= Message is %#v", rmsg)
			b.Remote <- rmsg
			b.q.LastEventID = m.ID
		}
		time.Sleep(time.Second * 3)
	}
}

func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
	topic := "matterbridge"
	if b.GetString("topic") != "" {
		topic = b.GetString("topic")
	}
	if res := b.getTopic(msg.Channel); res != "" {
		topic = res
	}
	m := gzb.Message{
		Stream:  msg.Channel,
		Topic:   topic,
		Content: msg.Username + msg.Text,
	}
	resp, err := b.bot.Message(m)
	if err != nil {
		return "", err
	}
	if resp != nil {
		defer resp.Body.Close()
		res, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}
		var jr struct {
			ID int `json:"id"`
		}
		err = json.Unmarshal(res, &jr)
		if err != nil {
			return "", err
		}
		return strconv.Itoa(jr.ID), nil
	}
	return "", nil
}

func (b *Bzulip) handleUploadFile(msg *config.Message) (string, error) {
	for _, f := range msg.Extra["file"] {
		fi := f.(config.FileInfo)
		if fi.Comment != "" {
			msg.Text += fi.Comment + ": "
		}
		if fi.URL != "" {
			msg.Text = fi.URL
			if fi.Comment != "" {
				msg.Text = fi.Comment + ": " + fi.URL
			}
		}
		_, err := b.sendMessage(*msg)
		if err != nil {
			return "", err
		}
	}
	return "", nil
}

func (b *Bzulip) getTopic(channel string) string {
	b.RLock()
	defer b.RUnlock()
	return b.channelToTopic[channel]
}
<commit_msg>Keep reconnecting until succeed (zulip) (#737)<commit_after>package bzulip

import (
	"encoding/json"
	"io/ioutil"
	"strconv"
	"sync"
	"time"

	"github.com/42wim/matterbridge/bridge"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/bridge/helper"
	gzb "github.com/matterbridge/gozulipbot"
)

type Bzulip struct {
	q       *gzb.Queue
	bot     *gzb.Bot
	streams map[int]string
	*bridge.Config
	channelToTopic map[string]string
	sync.RWMutex
}

func New(cfg *bridge.Config) bridge.Bridger {
	return &Bzulip{Config: cfg, streams: make(map[int]string), channelToTopic: make(map[string]string)}
}

func (b *Bzulip) Connect() error {
	bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login")}
	bot.Init()
	q, err := bot.RegisterAll()
	b.q = q
	b.bot = &bot
	if err != nil {
		b.Log.Errorf("Connect() %#v", err)
		return err
	}
	// init stream
	b.getChannel(0)
	b.Log.Info("Connection succeeded")
	go b.handleQueue()
	return nil
}

func (b *Bzulip) Disconnect() error {
	return nil
}

func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
	b.Lock()
	defer b.Unlock()
	b.channelToTopic[channel.Name] = channel.Options.Topic
	return nil
}

func (b *Bzulip) Send(msg config.Message) (string, error) {
	b.Log.Debugf("=> Receiving %#v", msg)

	// Delete message
	if msg.Event == config.EventMsgDelete {
		if msg.ID == "" {
			return "", nil
		}
		_, err := b.bot.UpdateMessage(msg.ID, "")
		return "", err
	}

	// Upload a file if it exists
	if msg.Extra != nil {
		for _, rmsg := range helper.HandleExtra(&msg, b.General) {
			b.sendMessage(rmsg)
		}
		if len(msg.Extra["file"]) > 0 {
			return b.handleUploadFile(&msg)
		}
	}

	// edit the message if we have a msg ID
	if msg.ID != "" {
		_, err := b.bot.UpdateMessage(msg.ID, msg.Username+msg.Text)
		return "", err
	}

	// Post normal message
	return b.sendMessage(msg)
}

func (b *Bzulip) getChannel(id int) string {
	if name, ok := b.streams[id]; ok {
		return name
	}
	streams, err := b.bot.GetRawStreams()
	if err != nil {
		b.Log.Errorf("getChannel: %#v", err)
		return ""
	}
	for _, stream := range streams.Streams {
		b.streams[stream.StreamID] = stream.Name
	}
	if name, ok := b.streams[id]; ok {
		return name
	}
	return ""
}

func (b *Bzulip) handleQueue() error {
	for {
		messages, err := b.q.GetEvents()
		switch err {
		case gzb.BackoffError:
			time.Sleep(time.Second * 5)
		case gzb.NoJSONError:
			b.Log.Error("Response wasn't JSON, server down or restarting? sleeping 10 seconds")
			time.Sleep(time.Second * 10)
		case gzb.BadEventQueueError:
			b.Log.Info("got a bad event queue id error, reconnecting")
			b.bot.Queues = nil
			for {
				b.q, err = b.bot.RegisterAll()
				if err != nil {
					b.Log.Errorf("reconnecting failed: %s. Sleeping 10 seconds", err)
					time.Sleep(time.Second * 10)
				}
				break
			}
		case gzb.HeartbeatError:
			b.Log.Debug("heartbeat received.")
		default:
			b.Log.Debugf("receiving error: %#v", err)
		}
		if err != nil {
			continue
		}
		for _, m := range messages {
			b.Log.Debugf("== Receiving %#v", m)
			// ignore our own messages
			if m.SenderEmail == b.GetString("login") {
				continue
			}
			rmsg := config.Message{Username: m.SenderFullName, Text: m.Content, Channel: b.getChannel(m.StreamID), Account: b.Account, UserID: strconv.Itoa(m.SenderID), Avatar: m.AvatarURL}
			b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
			b.Log.Debugf("<= Message is %#v", rmsg)
			b.Remote <- rmsg
			b.q.LastEventID = m.ID
		}
		time.Sleep(time.Second * 3)
	}
}

func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
	topic := "matterbridge"
	if b.GetString("topic") != "" {
		topic = b.GetString("topic")
	}
	if res := b.getTopic(msg.Channel); res != "" {
		topic = res
	}
	m := gzb.Message{
		Stream:  msg.Channel,
		Topic:   topic,
		Content: msg.Username + msg.Text,
	}
	resp, err := b.bot.Message(m)
	if err != nil {
		return "", err
	}
	if resp != nil {
		defer resp.Body.Close()
		res, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}
		var jr struct {
			ID int `json:"id"`
		}
		err = json.Unmarshal(res, &jr)
		if err != nil {
			return "", err
		}
		return strconv.Itoa(jr.ID), nil
	}
	return "", nil
}

func (b *Bzulip) handleUploadFile(msg *config.Message) (string, error) {
	for _, f := range msg.Extra["file"] {
		fi := f.(config.FileInfo)
		if fi.Comment != "" {
			msg.Text += fi.Comment + ": "
		}
		if fi.URL != "" {
			msg.Text = fi.URL
			if fi.Comment != "" {
				msg.Text = fi.Comment + ": " + fi.URL
			}
		}
		_, err := b.sendMessage(*msg)
		if err != nil {
			return "", err
		}
	}
	return "", nil
}

func (b *Bzulip) getTopic(channel string) string {
	b.RLock()
	defer b.RUnlock()
	return b.channelToTopic[channel]
}
<|endoftext|>


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

package formatifier

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

// Format the provided string as a Phone Number.  Only supports
// US numbers currently.
func ToPhone(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	var buffer bytes.Buffer
	count := 0

	if len(f.theString) == 10 {
		buffer.WriteString("(")
		for _, i := range f.theString {
			count++

			buffer.WriteString(string(i))

			if count == 3 {
				buffer.WriteString(") ")
			} else if count == 6 {
				buffer.WriteString(fmt.Sprintf("%s", delimiter))
			}
		}
	} else if len(f.theString) == 11 {
		for _, i := range f.theString {
			count++

			buffer.WriteString(string(i))

			if count == 1 {
				buffer.WriteString(" (")
			} else if count == 4 {
				buffer.WriteString(") ")
			} else if count == 7 {
				buffer.WriteString(fmt.Sprintf("%s", delimiter))
			}
		}
	}
	return buffer.String(), nil
}

// Format the provided string as a URL.  HTTP and HTTPS
// are the only supported protocols at this time.
func ToURL(theString string, secure bool, subdomain string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	if secure {
		if len(subdomain) > 0 {
			return fmt.Sprintf("https://%s.%s", subdomain, f.theString), nil
		}
		return fmt.Sprintf("https://%s", f.theString), nil
	}

	if len(subdomain) > 0 {
		return fmt.Sprintf("http://%s.%s", subdomain, f.theString), nil
	}
	return fmt.Sprintf("http://%s", f.theString), nil
}

// Format the provided string as a SSN.
func ToSSN(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 9 digits for Social Security Numbers")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 5 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string as a Lock Combo.
func ToLockCombo(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 6 digits for Lock Combo format")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 2 || count == 4 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in International Standard Book Number
// (ISBN) format.
func ToISBN(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 13 {
		return "", errors.New("ERROR: string must be 13 characters")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 4 || count == 6 || count == 12 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Morse Code.
func ToMorseCode(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := string(i)
		if _, ok := morse[key]; ok {
			buffer.WriteString(morse[key])
		} else if key == " " {
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Pirate Speak.
func ToPirateSpeak(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.urlEncodeSpaces()

	response, err := http.Get(fmt.Sprintf(pirateLink, f.theString))
	if err != nil {
		return "", errors.New("ERROR: Unable to convert.")
	}
	defer response.Body.Close()

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", err
	}
	return string(contents), nil
}

// Format the provided string in IRSA.
// International Radio-Telephony Spelling Alphabet
func ToIRSA(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := strings.ToLower(string(i))
		if _, ok := irsa[key]; ok {
			buffer.WriteString(irsa[key] + " ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Leet Speak.
// TODO(bdowns328) Make select post match random.
func ToLeet(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()
	rand.Seed(time.Now().UTC().UnixNano())

	words := strings.Fields(f.theString)
	var buffer bytes.Buffer

	for _, word := range words {
		key := string(word)
		if _, ok := leet[word]; ok {
			buffer.WriteString(leet[key][0] + " ")
		} else {
			for _, i := range word {
				letter := string(i)
				if _, ok := leet[letter]; ok {
					buffer.WriteString(leet[letter][0])
				}
			}
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}
<commit_msg>Updates per Lint feedback.<commit_after>// Copyright 2014 Brian J. Downs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package formatifier

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

/*
 Format the provided string as a Phone Number.  Only supports
 US numbers currently.
*/
func ToPhone(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	var buffer bytes.Buffer
	count := 0

	if len(f.theString) == 10 {
		buffer.WriteString("(")
		for _, i := range f.theString {
			count++

			buffer.WriteString(string(i))

			if count == 3 {
				buffer.WriteString(") ")
			} else if count == 6 {
				buffer.WriteString(fmt.Sprintf("%s", delimiter))
			}
		}
	} else if len(f.theString) == 11 {
		for _, i := range f.theString {
			count++

			buffer.WriteString(string(i))

			if count == 1 {
				buffer.WriteString(" (")
			} else if count == 4 {
				buffer.WriteString(") ")
			} else if count == 7 {
				buffer.WriteString(fmt.Sprintf("%s", delimiter))
			}
		}
	}
	return buffer.String(), nil
}

/*
 Format the provided string as a URL.  HTTP and HTTPS
 are the only supported protocols at this time.
*/
func ToURL(theString string, secure bool, subdomain string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	if secure {
		if len(subdomain) > 0 {
			return fmt.Sprintf("https://%s.%s", subdomain, f.theString), nil
		}
		return fmt.Sprintf("https://%s", f.theString), nil
	}

	if len(subdomain) > 0 {
		return fmt.Sprintf("http://%s.%s", subdomain, f.theString), nil
	}
	return fmt.Sprintf("http://%s", f.theString), nil
}

// Format the provided string as a SSN.
func ToSSN(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 9 digits for Social Security Numbers")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 5 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string as a Lock Combo.
func ToLockCombo(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 9 {
		return "", errors.New("ERROR: String needs to be 6 digits for Lock Combo format")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 2 || count == 4 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in International Standard Book Number
// (ISBN) format.
func ToISBN(theString string, delimiter string) (string, error) {
	f := New(theString)

	f.removeNonDigits()

	if len(f.theString) != 13 {
		return "", errors.New("ERROR: string must be 13 characters")
	}

	var buffer bytes.Buffer
	count := 0

	for _, i := range f.theString {
		count++

		buffer.WriteString(string(i))

		if count == 3 || count == 4 || count == 6 || count == 12 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Morse Code.
func ToMorseCode(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := string(i)
		if _, ok := morse[key]; ok {
			buffer.WriteString(morse[key])
		} else if key == " " {
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Pirate Speak.
func ToPirateSpeak(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.urlEncodeSpaces()

	response, err := http.Get(fmt.Sprintf(pirateLink, f.theString))
	if err != nil {
		return "", errors.New("ERROR: Unable to convert.")
	}
	defer response.Body.Close()

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return "", err
	}
	return string(contents), nil
}

// Format the provided string in IRSA.
// International Radio-Telephony Spelling Alphabet
func ToIRSA(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()

	var buffer bytes.Buffer

	for _, i := range f.theString {
		key := strings.ToLower(string(i))
		if _, ok := irsa[key]; ok {
			buffer.WriteString(irsa[key] + " ")
		}
	}
	return buffer.String(), nil
}

// Format the provided string in Leet Speak.
// TODO(bdowns328) Make select post match random.
func ToLeet(theString string) (string, error) {
	f := New(theString)

	if len(f.theString) < 1 {
		return "", errors.New(lengthError)
	}

	f.makeLower()
	rand.Seed(time.Now().UTC().UnixNano())

	words := strings.Fields(f.theString)
	var buffer bytes.Buffer

	for _, word := range words {
		key := string(word)
		if _, ok := leet[word]; ok {
			buffer.WriteString(leet[key][0] + " ")
		} else {
			for _, i := range word {
				letter := string(i)
				if _, ok := leet[letter]; ok {
					buffer.WriteString(leet[letter][0])
				}
			}
			buffer.WriteString(" ")
		}
	}
	return buffer.String(), nil
}
<|endoftext|>