<commit_before>package main

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat"
	"github.com/loadimpact/speedboat/js"
	"github.com/loadimpact/speedboat/sampler"
	"github.com/loadimpact/speedboat/sampler/influxdb"
	"github.com/loadimpact/speedboat/sampler/stream"
	"github.com/loadimpact/speedboat/simple"
	"github.com/urfave/cli"
	"golang.org/x/net/context"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	stdlog "log"
	"os"
	"strings"
	"sync"
	"time"
)

// Configure the global logger.
func configureLogging(c *cli.Context) {
	log.SetLevel(log.InfoLevel)
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}

	if c.GlobalBool("json") {
		log.SetFormatter(&log.JSONFormatter{})
	}
}

// Configure the global sampler.
func configureSampler(c *cli.Context) {
	sampler.DefaultSampler.OnError = func(err error) {
		log.WithError(err).Error("[Sampler error]")
	}

	for _, output := range c.GlobalStringSlice("output") {
		parts := strings.SplitN(output, "+", 2)
		switch parts[0] {
		case "influxdb":
			out, err := influxdb.NewFromURL(parts[1])
			if err != nil {
				log.WithError(err).Fatal("Couldn't create InfluxDB client")
			}
			sampler.DefaultSampler.Outputs = append(sampler.DefaultSampler.Outputs, out)
		default:
			var writer io.WriteCloser
			switch output {
			case "stdout", "-":
				writer = os.Stdout
			default:
				file, err := os.Create(output)
				if err != nil {
					log.WithError(err).Fatal("Couldn't create output file")
				}
				writer = file
			}

			var out sampler.Output
			switch c.GlobalString("format") {
			case "json":
				out = &stream.JSONOutput{Output: writer}
			case "csv":
				out = &stream.CSVOutput{Output: writer}
			default:
				log.Fatal("Unknown output format")
			}
			sampler.DefaultSampler.Outputs = append(sampler.DefaultSampler.Outputs, out)
		}
	}
}

func parse(cc *cli.Context) (conf Config, err error) {
	switch len(cc.Args()) {
	case 0:
		if !cc.IsSet("script") && !cc.IsSet("url") {
			return conf, errors.New("No config file, script or URL")
		}
	case 1:
		bytes, err := ioutil.ReadFile(cc.Args()[0])
		if err != nil {
			return conf, errors.New("Couldn't read config file")
		}
		if err := yaml.Unmarshal(bytes, &conf); err != nil {
			return conf, errors.New("Couldn't parse config file")
		}
	default:
		return conf, errors.New("Too many arguments!")
	}

	// Let commandline flags override config files
	if cc.IsSet("script") {
		conf.Script = cc.String("script")
	}
	if cc.IsSet("url") {
		conf.URL = cc.String("url")
	}
	if cc.IsSet("vus") {
		conf.VUs = cc.Int("vus")
	}
	if cc.IsSet("duration") {
		conf.Duration = cc.Duration("duration").String()
	}

	return conf, nil
}

func dumpTest(t *speedboat.Test) {
	log.WithFields(log.Fields{
		"script": t.Script,
		"url":    t.URL,
	}).Info("General")
	for i, stage := range t.Stages {
		log.WithFields(log.Fields{
			"#":        i,
			"duration": stage.Duration,
			"start":    stage.StartVUs,
			"end":      stage.EndVUs,
		}).Info("Stage")
	}
}

func headlessController(c context.Context, t *speedboat.Test) <-chan int {
	ch := make(chan int)

	go func() {
		defer close(ch)

		select {
		case ch <- t.VUsAt(0):
		case <-c.Done():
			return
		}

		startTime := time.Now()
		ticker := time.NewTicker(100 * time.Millisecond)
		for {
			select {
			case <-ticker.C:
				ch <- t.VUsAt(time.Since(startTime))
			case <-c.Done():
				return
			}
		}
	}()

	return ch
}

func action(cc *cli.Context) error {
	conf, err := parse(cc)
	if err != nil {
		log.WithError(err).Fatal("Invalid arguments; see --help")
	}

	t, err := conf.MakeTest()
	if err != nil {
		log.WithError(err).Fatal("Configuration error")
	}

	if cc.Bool("dump") {
		dumpTest(&t)
		return nil
	}

	// Inspect the test to find a suitable runner; additional ones can easily be added
	var runner speedboat.Runner
	switch {
	case t.Script == "":
		runner = simple.New()
	case strings.HasSuffix(t.Script, ".js"):
		src, err := ioutil.ReadFile(t.Script)
		if err != nil {
			log.WithError(err).Fatal("Couldn't read script")
		}
		runner = js.New(t.Script, string(src))
	default:
		log.Fatal("No suitable runner found!")
	}

	// Context that expires at the end of the test
	ctx, cancel := context.WithTimeout(context.Background(), t.TotalDuration())

	// Configure the VU logger
	logger := &log.Logger{
		Out:       os.Stderr,
		Level:     log.DebugLevel,
		Formatter: &log.TextFormatter{},
	}
	if cc.GlobalBool("json") {
		logger.Formatter = &log.JSONFormatter{}
	}
	ctx = speedboat.WithLogger(ctx, logger)

	// Output metrics appropriately; use a mutex to prevent garbled output
	logMetrics := cc.Bool("log")
	if logMetrics {
		sampler.DefaultSampler.Accumulate = true
	}
	metricsLogger := stdlog.New(os.Stdout, "metrics: ", stdlog.Lmicroseconds)
	metricsMutex := sync.Mutex{}
	go func() {
		ticker := time.NewTicker(1 * time.Second)
		for {
			select {
			case <-ticker.C:
				if logMetrics {
					metricsMutex.Lock()
					printMetrics(metricsLogger)
					metricsMutex.Unlock()
				}
				commitMetrics()
			case <-ctx.Done():
				return
			}
		}
	}()

	// Use a "headless controller" to scale VUs by polling the test ramp
	mVUs := sampler.Gauge("vus")
	vus := []context.CancelFunc{}
	for scale := range headlessController(ctx, &t) {
		for i := len(vus); i < scale; i++ {
			log.WithField("id", i).Debug("Spawning VU")
			vuCtx, vuCancel := context.WithCancel(ctx)
			vus = append(vus, vuCancel)
			go func() {
				defer func() {
					if v := recover(); v != nil {
						switch err := v.(type) {
						case speedboat.FlowControl:
							switch err {
							case speedboat.AbortTest:
								log.Error("Test aborted")
								cancel()
							}
						default:
							log.WithFields(log.Fields{
								"id":    i,
								"error": err,
							}).Error("VU crashed!")
						}
					}
				}()
				runner.RunVU(vuCtx, t, len(vus))
			}()
		}
		for i := len(vus); i > scale; i-- {
			log.WithField("id", i-1).Debug("Dropping VU")
			vus[i-1]()
			vus = vus[:i-1]
		}
		mVUs.Int(len(vus))
	}

	// Wait until the end of the test
	<-ctx.Done()

	// Print final metrics
	if logMetrics {
		metricsMutex.Lock()
		printMetrics(metricsLogger)
		metricsMutex.Unlock()
	}
	commitMetrics()
	closeMetrics()

	return nil
}

func main() {
	// Free up -v and -h for our own flags
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help, ?"

	// Bootstrap using action-registered commandline flags
	app := cli.NewApp()
	app.Name = "speedboat"
	app.Usage = "A next-generation load generator"
	app.Version = "0.0.1a1"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "More verbose output",
		},
		cli.StringFlag{
			Name:  "script, s",
			Usage: "Script to run",
		},
		cli.StringFlag{
			Name:  "url",
			Usage: "URL to test",
		},
		cli.IntFlag{
			Name:  "vus, u",
			Usage: "Number of VUs to simulate",
			Value: 10,
		},
		cli.DurationFlag{
			Name:  "duration, d",
			Usage: "Test duration",
			Value: time.Duration(10) * time.Second,
		},
		cli.StringSliceFlag{
			Name:  "output, o",
			Usage: "Output metrics to a file or database",
		},
		cli.StringFlag{
			Name:  "format, f",
			Usage: "Metric output format (json or csv)",
			Value: "json",
		},
		cli.BoolFlag{
			Name:  "log, l",
			Usage: "Log metrics to stdout",
		},
		cli.BoolFlag{
			Name:  "json",
			Usage: "Format log messages as JSON",
		},
		cli.BoolFlag{
			Name:  "dump",
			Usage: "Dump parsed test and exit",
		},
	}
	app.Before = func(c *cli.Context) error {
		configureLogging(c)
		configureSampler(c)
		return nil
	}
	app.Action = action
	app.Run(os.Args)
}
<commit_msg>[feat] --script and --url replaced by positionals<commit_after>package main

import (
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat"
	"github.com/loadimpact/speedboat/js"
	"github.com/loadimpact/speedboat/sampler"
	"github.com/loadimpact/speedboat/sampler/influxdb"
	"github.com/loadimpact/speedboat/sampler/stream"
	"github.com/loadimpact/speedboat/simple"
	"github.com/urfave/cli"
	"golang.org/x/net/context"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	stdlog "log"
	"os"
	"strings"
	"sync"
	"time"
)

const (
	typeURL = "url"
	typeYML = "yml"
	typeJS  = "js"
)

// Configure the global logger.
func configureLogging(c *cli.Context) {
	log.SetLevel(log.InfoLevel)
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}

	if c.GlobalBool("json") {
		log.SetFormatter(&log.JSONFormatter{})
	}
}

// Configure the global sampler.
func configureSampler(c *cli.Context) {
	sampler.DefaultSampler.OnError = func(err error) {
		log.WithError(err).Error("[Sampler error]")
	}

	for _, output := range c.GlobalStringSlice("output") {
		parts := strings.SplitN(output, "+", 2)
		switch parts[0] {
		case "influxdb":
			out, err := influxdb.NewFromURL(parts[1])
			if err != nil {
				log.WithError(err).Fatal("Couldn't create InfluxDB client")
			}
			sampler.DefaultSampler.Outputs = append(sampler.DefaultSampler.Outputs, out)
		default:
			var writer io.WriteCloser
			switch output {
			case "stdout", "-":
				writer = os.Stdout
			default:
				file, err := os.Create(output)
				if err != nil {
					log.WithError(err).Fatal("Couldn't create output file")
				}
				writer = file
			}

			var out sampler.Output
			switch c.GlobalString("format") {
			case "json":
				out = &stream.JSONOutput{Output: writer}
			case "csv":
				out = &stream.CSVOutput{Output: writer}
			default:
				log.Fatal("Unknown output format")
			}
			sampler.DefaultSampler.Outputs = append(sampler.DefaultSampler.Outputs, out)
		}
	}
}

func guessType(arg string) string {
	switch {
	case strings.Contains(arg, "://"):
		return typeURL
	case strings.HasSuffix(arg, ".js"):
		return typeJS
	case strings.HasSuffix(arg, ".yml"):
		return typeYML
	}
	return ""
}

func parse(cc *cli.Context) (conf Config, err error) {
	if len(cc.Args()) == 0 {
		return conf, errors.New("Nothing to do!")
	}

	conf.VUs = cc.Int("vus")
	conf.Duration = cc.Duration("duration").String()

	arg := cc.Args()[0]
	argType := cc.String("type")
	if argType == "" {
		argType = guessType(arg)
	}

	switch argType {
	case typeYML:
		bytes, err := ioutil.ReadFile(cc.Args()[0])
		if err != nil {
			return conf, errors.New("Couldn't read config file")
		}
		if err := yaml.Unmarshal(bytes, &conf); err != nil {
			return conf, errors.New("Couldn't parse config file")
		}
	case typeURL:
		conf.URL = arg
	case typeJS:
		conf.Script = arg
	default:
		return conf, errors.New("Unsure of what to do, try specifying --type")
	}

	return conf, nil
}

func dumpTest(t *speedboat.Test) {
	log.WithFields(log.Fields{
		"script": t.Script,
		"url":    t.URL,
	}).Info("General")
	for i, stage := range t.Stages {
		log.WithFields(log.Fields{
			"#":        i,
			"duration": stage.Duration,
			"start":    stage.StartVUs,
			"end":      stage.EndVUs,
		}).Info("Stage")
	}
}

func headlessController(c context.Context, t *speedboat.Test) <-chan int {
	ch := make(chan int)

	go func() {
		defer close(ch)

		select {
		case ch <- t.VUsAt(0):
		case <-c.Done():
			return
		}

		startTime := time.Now()
		ticker := time.NewTicker(100 * time.Millisecond)
		for {
			select {
			case <-ticker.C:
				ch <- t.VUsAt(time.Since(startTime))
			case <-c.Done():
				return
			}
		}
	}()

	return ch
}

func action(cc *cli.Context) error {
	if len(cc.Args()) == 0 {
		cli.ShowAppHelp(cc)
		return nil
	}

	conf, err := parse(cc)
	if err != nil {
		log.WithError(err).Fatal("Invalid arguments; see --help")
	}

	t, err := conf.MakeTest()
	if err != nil {
		log.WithError(err).Fatal("Configuration error")
	}

	if cc.Bool("dump") {
		dumpTest(&t)
		return nil
	}

	// Inspect the test to find a suitable runner; additional ones can easily be added
	var runner speedboat.Runner
	switch {
	case t.Script == "":
		runner = simple.New()
	case strings.HasSuffix(t.Script, ".js"):
		src, err := ioutil.ReadFile(t.Script)
		if err != nil {
			log.WithError(err).Fatal("Couldn't read script")
		}
		runner = js.New(t.Script, string(src))
	default:
		log.Fatal("No suitable runner found!")
	}

	// Context that expires at the end of the test
	ctx, cancel := context.WithTimeout(context.Background(), t.TotalDuration())

	// Configure the VU logger
	logger := &log.Logger{
		Out:       os.Stderr,
		Level:     log.DebugLevel,
		Formatter: &log.TextFormatter{},
	}
	if cc.GlobalBool("json") {
		logger.Formatter = &log.JSONFormatter{}
	}
	ctx = speedboat.WithLogger(ctx, logger)

	// Output metrics appropriately; use a mutex to prevent garbled output
	logMetrics := cc.Bool("log")
	if logMetrics {
		sampler.DefaultSampler.Accumulate = true
	}
	metricsLogger := stdlog.New(os.Stdout, "metrics: ", stdlog.Lmicroseconds)
	metricsMutex := sync.Mutex{}
	go func() {
		ticker := time.NewTicker(1 * time.Second)
		for {
			select {
			case <-ticker.C:
				if logMetrics {
					metricsMutex.Lock()
					printMetrics(metricsLogger)
					metricsMutex.Unlock()
				}
				commitMetrics()
			case <-ctx.Done():
				return
			}
		}
	}()

	// Use a "headless controller" to scale VUs by polling the test ramp
	mVUs := sampler.Gauge("vus")
	vus := []context.CancelFunc{}
	for scale := range headlessController(ctx, &t) {
		for i := len(vus); i < scale; i++ {
			log.WithField("id", i).Debug("Spawning VU")
			vuCtx, vuCancel := context.WithCancel(ctx)
			vus = append(vus, vuCancel)
			go func() {
				defer func() {
					if v := recover(); v != nil {
						switch err := v.(type) {
						case speedboat.FlowControl:
							switch err {
							case speedboat.AbortTest:
								log.Error("Test aborted")
								cancel()
							}
						default:
							log.WithFields(log.Fields{
								"id":    i,
								"error": err,
							}).Error("VU crashed!")
						}
					}
				}()
				runner.RunVU(vuCtx, t, len(vus))
			}()
		}
		for i := len(vus); i > scale; i-- {
			log.WithField("id", i-1).Debug("Dropping VU")
			vus[i-1]()
			vus = vus[:i-1]
		}
		mVUs.Int(len(vus))
	}

	// Wait until the end of the test
	<-ctx.Done()

	// Print final metrics
	if logMetrics {
		metricsMutex.Lock()
		printMetrics(metricsLogger)
		metricsMutex.Unlock()
	}
	commitMetrics()
	closeMetrics()

	return nil
}

func main() {
	// Free up -v and -h for our own flags
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help, ?"

	// Bootstrap using action-registered commandline flags
	app := cli.NewApp()
	app.Name = "speedboat"
	app.Usage = "A next-generation load generator"
	app.Version = "0.0.1a1"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "type, t",
			Usage: "Input file type, if not evident (url, yml or js)",
		},
		cli.IntFlag{
			Name:  "vus, u",
			Usage: "Number of VUs to simulate",
			Value: 10,
		},
		cli.DurationFlag{
			Name:  "duration, d",
			Usage: "Test duration",
			Value: time.Duration(10) * time.Second,
		},
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "More verbose output",
		},
		cli.StringSliceFlag{
			Name:  "output, o",
			Usage: "Output metrics to a file or database",
		},
		cli.StringFlag{
			Name:  "format, f",
			Usage: "Metric output format (json or csv)",
			Value: "json",
		},
		cli.BoolFlag{
			Name:  "log, l",
			Usage: "Log metrics to stdout",
		},
		cli.BoolFlag{
			Name:  "json",
			Usage: "Format log messages as JSON",
		},
		cli.BoolFlag{
			Name:  "dump",
			Usage: "Dump parsed test and exit",
		},
	}
	app.Before = func(c *cli.Context) error {
		configureLogging(c)
		configureSampler(c)
		return nil
	}
	app.Action = action
	app.Run(os.Args)
}
<|endoftext|>


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

package main

import (
	"bytes"
	"github.com/globocom/tsuru/cmd"
	. "launchpad.net/gocheck"
	"net/http"
	"strings"
)

func (s *S) TestAppLog(c *C) {
	*appName = "appName"
	var stdout, stderr bytes.Buffer
	result := `[{"Date":"2012-06-20T11:17:22.75-03:00","Message":"creating app lost"},{"Date":"2012-06-20T11:17:22.753-03:00","Message":"app lost successfully created"}]`
	expected := `2012-06-20 11:17:22 - creating app lost
2012-06-20 11:17:22 - app lost successfully created
`
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	command := AppLog{}
	client := cmd.NewClient(&http.Client{Transport: &transport{msg: result, status: http.StatusOK}}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	got := stdout.String()
	got = strings.Replace(got, "-0300 -0300", "-0300 BRT", -1)
	c.Assert(got, Equals, expected)
}

func (s *S) TestAppLogWithoutTheFlag(c *C) {
	var stdout, stderr bytes.Buffer
	result := `[{"Date":"2012-06-20T11:17:22.75-03:00","Message":"creating app lost"},{"Date":"2012-06-20T11:17:22.753-03:00","Message":"app lost successfully created"}]`
	expected := `2012-06-20 11:17:22 - creating app lost
2012-06-20 11:17:22 - app lost successfully created
`
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	fake := &FakeGuesser{name: "hitthelights"}
	command := AppLog{GuessingCommand{g: fake}}
	trans := &conditionalTransport{
		transport{
			msg:    result,
			status: http.StatusOK,
		},
		func(req *http.Request) bool {
			return req.URL.Path == "/apps/hitthelights/log" && req.Method == "GET"
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	got := stdout.String()
	got = strings.Replace(got, "-0300 -0300", "-0300 BRT", -1)
	c.Assert(got, Equals, expected)
}

func (s *S) TestAppLogShouldReturnNilIfHasNoContent(c *C) {
	*appName = "appName"
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	command := AppLog{}
	client := cmd.NewClient(&http.Client{Transport: &transport{msg: "", status: http.StatusNoContent}}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	c.Assert(stdout.String(), Equals, "")
}

func (s *S) TestAppLogInfo(c *C) {
	expected := &cmd.Info{
		Name:  "log",
		Usage: "log [--app appname]",
		Desc: `show logs for an app.

If you don't provide the app name, tsuru will try to guess it.`,
		MinArgs: 0,
	}
	c.Assert((&AppLog{}).Info(), DeepEquals, expected)
}
<commit_msg>Added usage for number of lines in log command.<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"github.com/globocom/tsuru/cmd"
	. "launchpad.net/gocheck"
	"net/http"
	"strings"
)

func (s *S) TestAppLog(c *C) {
	*appName = "appName"
	var stdout, stderr bytes.Buffer
	result := `[{"Date":"2012-06-20T11:17:22.75-03:00","Message":"creating app lost"},{"Date":"2012-06-20T11:17:22.753-03:00","Message":"app lost successfully created"}]`
	expected := `2012-06-20 11:17:22 - creating app lost
2012-06-20 11:17:22 - app lost successfully created
`
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	command := AppLog{}
	client := cmd.NewClient(&http.Client{Transport: &transport{msg: result, status: http.StatusOK}}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	got := stdout.String()
	got = strings.Replace(got, "-0300 -0300", "-0300 BRT", -1)
	c.Assert(got, Equals, expected)
}

func (s *S) TestAppLogWithoutTheFlag(c *C) {
	var stdout, stderr bytes.Buffer
	result := `[{"Date":"2012-06-20T11:17:22.75-03:00","Message":"creating app lost"},{"Date":"2012-06-20T11:17:22.753-03:00","Message":"app lost successfully created"}]`
	expected := `2012-06-20 11:17:22 - creating app lost
2012-06-20 11:17:22 - app lost successfully created
`
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	fake := &FakeGuesser{name: "hitthelights"}
	command := AppLog{GuessingCommand{g: fake}}
	trans := &conditionalTransport{
		transport{
			msg:    result,
			status: http.StatusOK,
		},
		func(req *http.Request) bool {
			return req.URL.Path == "/apps/hitthelights/log" && req.Method == "GET"
		},
	}
	client := cmd.NewClient(&http.Client{Transport: trans}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	got := stdout.String()
	got = strings.Replace(got, "-0300 -0300", "-0300 BRT", -1)
	c.Assert(got, Equals, expected)
}

func (s *S) TestAppLogShouldReturnNilIfHasNoContent(c *C) {
	*appName = "appName"
	var stdout, stderr bytes.Buffer
	context := cmd.Context{
		Stdout: &stdout,
		Stderr: &stderr,
	}
	command := AppLog{}
	client := cmd.NewClient(&http.Client{Transport: &transport{msg: "", status: http.StatusNoContent}}, nil, "", "")
	err := command.Run(&context, client)
	c.Assert(err, IsNil)
	c.Assert(stdout.String(), Equals, "")
}

func (s *S) TestAppLogInfo(c *C) {
	expected := &cmd.Info{
		Name:  "log",
		Usage: "log [--app appname] [--lines numberOfLines]",
		Desc: `show logs for an app.

If you don't provide the app name, tsuru will try to guess it. The default number of lines is 10.`,
		MinArgs: 0,
	}
	c.Assert((&AppLog{}).Info(), DeepEquals, expected)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/brnstz/bus/internal/conf"
	"github.com/brnstz/bus/internal/etc"
	"github.com/brnstz/bus/models"
)

func init() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	conf.ConfigVar(&conf.APIAddr, ":8000", "BUS_API_ADDR", true)
	conf.ConfigVar(&conf.DBAddr, "localhost:5432", "BUS_DB_ADDR", true)
	conf.ConfigVar(&conf.DBUser, "postgres", "BUS_DB_USER", true)
	conf.ConfigVar(&conf.RedisAddr, "localhost:6379", "BUS_REDIS_ADDR", true)
	conf.ConfigVar(&conf.TmpDir, os.TempDir(), "BUS_TMP_DIR", true)
	conf.ConfigVar(&conf.BusAPIKey, "", "MTA_BUS_TIME_API_KEY", true)
	conf.ConfigVar(&conf.SubwayAPIKey, "", "MTA_SUBWAY_TIME_API_KEY", true)

	conf.DB = conf.MustDB()

}

func floatOrDie(w http.ResponseWriter, r *http.Request, name string) (f float64, err error) {

	val := r.FormValue(name)
	f, err = strconv.ParseFloat(val, 64)
	if err != nil {
		log.Println("bad float value", val, err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	return
}

func getStops(w http.ResponseWriter, r *http.Request) {
	lat, err := floatOrDie(w, r, "lat")
	if err != nil {
		return
	}

	lon, err := floatOrDie(w, r, "lon")
	if err != nil {
		return
	}

	miles, err := floatOrDie(w, r, "miles")
	if err != nil {
		return
	}

	filter := r.FormValue("filter")

	meters := etc.MileToMeter(miles)

	stops, err := models.GetStopsByLoc(conf.DB, lat, lon, meters, filter)
	if err != nil {
		log.Println("can't get stops", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(stops)
	if err != nil {
		log.Println("can't marshal to json", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(b)
}

func getUI(w http.ResponseWriter, r *http.Request) {
	ui := []byte(`
		<!DOCTYPE html>

		Latitude: <input type="text" id="lat" name="lat">

		Longitude: <input type="text" id="lon" name="lon">

		Filter:
			<select id="filter">
				<option value="">Subway and bus</option>
				<option value="subway">Subway only</option>
				<option value="bus">Bus only</option>
			</select>

		Radius: <input type="text" id="miles" value="0.2"> miles

		<button onclick="getLocation()">Detect location</button>

		<button onclick="setLocation(40.758895,-73.985131, 0.2)">Times Square</button>

		<button onclick="setLocation(40.7236448,-74.0006793, 0.2)">SoHo</button>

		<button onclick="setLocation(40.730198,-73.9542742, 0.2)">Greenpoint</button>

		<button onclick="setLocation(40.6825236,-73.9750134, 0.2)">Barclays Center</button>

		<button onclick="setLocation(40.84932,-73.877154, 0.2)">Bronx Zoo</button>

		<button onclick="setLocation(40.7501217,-73.8463344, 0.3)">US Open</button>

		<button onclick="setLocation(40.5031274,-74.253251, 0.3)">Conference House Park</button>

		<button onclick="getTrips()">Get upcoming trips</button>

	`)
	w.Write(ui)
}

func main() {
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)

	http.HandleFunc("/api/v1/stops", getStops)
	http.HandleFunc("/", getUI)

	log.Fatal(http.ListenAndServe(conf.APIAddr, nil))
}
<commit_msg>move init code to main<commit_after>package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/brnstz/bus/internal/conf"
	"github.com/brnstz/bus/internal/etc"
	"github.com/brnstz/bus/models"
)

func floatOrDie(w http.ResponseWriter, r *http.Request, name string) (f float64, err error) {

	val := r.FormValue(name)
	f, err = strconv.ParseFloat(val, 64)
	if err != nil {
		log.Println("bad float value", val, err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	return
}

func getStops(w http.ResponseWriter, r *http.Request) {
	lat, err := floatOrDie(w, r, "lat")
	if err != nil {
		return
	}

	lon, err := floatOrDie(w, r, "lon")
	if err != nil {
		return
	}

	miles, err := floatOrDie(w, r, "miles")
	if err != nil {
		return
	}

	filter := r.FormValue("filter")

	meters := etc.MileToMeter(miles)

	stops, err := models.GetStopsByLoc(conf.DB, lat, lon, meters, filter)
	if err != nil {
		log.Println("can't get stops", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(stops)
	if err != nil {
		log.Println("can't marshal to json", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(b)
}

func getUI(w http.ResponseWriter, r *http.Request) {
	ui := []byte(`
		<!DOCTYPE html>

		Latitude: <input type="text" id="lat" name="lat">

		Longitude: <input type="text" id="lon" name="lon">

		Filter:
			<select id="filter">
				<option value="">Subway and bus</option>
				<option value="subway">Subway only</option>
				<option value="bus">Bus only</option>
			</select>

		Radius: <input type="text" id="miles" value="0.2"> miles

		<button onclick="getLocation()">Detect location</button>

		<button onclick="setLocation(40.758895,-73.985131, 0.2)">Times Square</button>

		<button onclick="setLocation(40.7236448,-74.0006793, 0.2)">SoHo</button>

		<button onclick="setLocation(40.730198,-73.9542742, 0.2)">Greenpoint</button>

		<button onclick="setLocation(40.6825236,-73.9750134, 0.2)">Barclays Center</button>

		<button onclick="setLocation(40.84932,-73.877154, 0.2)">Bronx Zoo</button>

		<button onclick="setLocation(40.7501217,-73.8463344, 0.3)">US Open</button>

		<button onclick="setLocation(40.5031274,-74.253251, 0.3)">Conference House Park</button>

		<button onclick="getTrips()">Get upcoming trips</button>

	`)
	w.Write(ui)
}

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	conf.ConfigVar(&conf.APIAddr, ":8000", "BUS_API_ADDR", true)
	conf.ConfigVar(&conf.DBAddr, "localhost:5432", "BUS_DB_ADDR", true)
	conf.ConfigVar(&conf.DBUser, "postgres", "BUS_DB_USER", true)
	conf.ConfigVar(&conf.RedisAddr, "localhost:6379", "BUS_REDIS_ADDR", true)
	conf.ConfigVar(&conf.TmpDir, os.TempDir(), "BUS_TMP_DIR", true)
	conf.ConfigVar(&conf.BusAPIKey, "", "MTA_BUS_TIME_API_KEY", true)
	conf.ConfigVar(&conf.SubwayAPIKey, "", "MTA_SUBWAY_TIME_API_KEY", true)

	conf.DB = conf.MustDB()

	http.HandleFunc("/api/v1/stops", getStops)
	http.HandleFunc("/", getUI)

	log.Fatal(http.ListenAndServe(conf.APIAddr, nil))
}
<|endoftext|>


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

package http_test

import (
	"github.com/jacobsa/aws/s3/http"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	sys_http "net/http"
	"net/http/httptest"
	"net/url"
	"testing"
)

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

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

type localHandler struct {
	// Input seen.
	req *sys_http.Request

	// To be returned.
	statusCode int
	body       []byte
}

func (h *localHandler) ServeHTTP(w sys_http.ResponseWriter, r *sys_http.Request) {
	// Record the request.
	if h.req != nil {
		panic("Called twice.")
	}

	h.req = r

	// Write out the response.
	w.WriteHeader(h.statusCode)
	if _, err := w.Write(h.body); err != nil {
		panic(err)
	}
}

type ConnTest struct {
	handler  localHandler
	server   *httptest.Server
	endpoint *url.URL
}

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

func (t *ConnTest) SetUp(i *TestInfo) {
	t.server = httptest.NewServer(&t.handler)

	var err error
	t.endpoint, err = url.Parse(t.server.URL)
	AssertEq(nil, err)
}

func (t *ConnTest) TearDown() {
	t.server.Close()
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ConnTest) InvalidScheme() {
	// Connection
	_, err := http.NewConn(&url.URL{Scheme: "taco", Host: "localhost"})

	ExpectThat(err, Error(HasSubstr("scheme")))
	ExpectThat(err, Error(HasSubstr("taco")))
}

func (t *ConnTest) UnknownHost() {
	// Connection
	conn, err := http.NewConn(&url.URL{Scheme: "http", Host: "foo.sidofhdksjhf"})
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/foo",
		Headers: map[string]string{},
	}

	// Call
	_, err = conn.SendRequest(req)

	ExpectThat(err, Error(HasSubstr("foo.sidofhdksjhf")))
	ExpectThat(err, Error(HasSubstr("no such host")))
}

func (t *ConnTest) PassesOnRequestInfo() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb: "PUT",
		Path: "/foo/bar",
		Headers: map[string]string{
			"taco":      "burrito",
			"enchilada": "queso",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("PUT", sysReq.Method)
	ExpectEq("/foo/bar", sysReq.URL.Path)

	ExpectThat(sysReq.Header["Taco"], ElementsAre("burrito"))
	ExpectThat(sysReq.Header["Enchilada"], ElementsAre("queso"))
}

func (t *ConnTest) RequestContainsOneParameter() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/foo/bar",
		Headers: map[string]string{},
		Parameters: map[string]string{
			"baz": "qux",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("/foo/bar?baz=qux", sysReq.URL.Path)
}

func (t *ConnTest) PathAndParametersNeedEscaping() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/타코/bar",
		Headers: map[string]string{},
		Parameters: map[string]string{
			"b az": "qu?x",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("/타코/bar?b az=qu x", sysReq.URL.Path)
	ExpectEq("/%ED%83%80%EC%BD%94/bar?b%20az=qu%3Fx", sysReq.RequestURI)
}

func (t *ConnTest) ReturnsStatusCode() {
	// Handler
	t.handler.statusCode = 123

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectEq(123, resp.StatusCode)
}

func (t *ConnTest) ReturnsBody() {
	// Handler
	t.handler.body = []byte{0xde, 0xad, 0x00, 0xbe, 0xef}

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectThat(resp.Body, DeepEquals(t.handler.body))
}

func (t *ConnTest) ServerReturnsEmptyBody() {
	// Handler
	t.handler.body = []byte{}

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectThat(resp.Body, ElementsAre())
}

func (t *ConnTest) HttpsAllowed() {
	t.endpoint.Scheme = "https"

	// Connection
	_, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)
}
<commit_msg>ConnTest.RequestContainsMultipleParameters<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package http_test

import (
	"github.com/jacobsa/aws/s3/http"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	sys_http "net/http"
	"net/http/httptest"
	"net/url"
	"testing"
)

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

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

type localHandler struct {
	// Input seen.
	req *sys_http.Request

	// To be returned.
	statusCode int
	body       []byte
}

func (h *localHandler) ServeHTTP(w sys_http.ResponseWriter, r *sys_http.Request) {
	// Record the request.
	if h.req != nil {
		panic("Called twice.")
	}

	h.req = r

	// Write out the response.
	w.WriteHeader(h.statusCode)
	if _, err := w.Write(h.body); err != nil {
		panic(err)
	}
}

type ConnTest struct {
	handler  localHandler
	server   *httptest.Server
	endpoint *url.URL
}

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

func (t *ConnTest) SetUp(i *TestInfo) {
	t.server = httptest.NewServer(&t.handler)

	var err error
	t.endpoint, err = url.Parse(t.server.URL)
	AssertEq(nil, err)
}

func (t *ConnTest) TearDown() {
	t.server.Close()
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ConnTest) InvalidScheme() {
	// Connection
	_, err := http.NewConn(&url.URL{Scheme: "taco", Host: "localhost"})

	ExpectThat(err, Error(HasSubstr("scheme")))
	ExpectThat(err, Error(HasSubstr("taco")))
}

func (t *ConnTest) UnknownHost() {
	// Connection
	conn, err := http.NewConn(&url.URL{Scheme: "http", Host: "foo.sidofhdksjhf"})
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/foo",
		Headers: map[string]string{},
	}

	// Call
	_, err = conn.SendRequest(req)

	ExpectThat(err, Error(HasSubstr("foo.sidofhdksjhf")))
	ExpectThat(err, Error(HasSubstr("no such host")))
}

func (t *ConnTest) PassesOnRequestInfo() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb: "PUT",
		Path: "/foo/bar",
		Headers: map[string]string{
			"taco":      "burrito",
			"enchilada": "queso",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("PUT", sysReq.Method)
	ExpectEq("/foo/bar", sysReq.URL.Path)

	ExpectThat(sysReq.Header["Taco"], ElementsAre("burrito"))
	ExpectThat(sysReq.Header["Enchilada"], ElementsAre("queso"))
}

func (t *ConnTest) RequestContainsOneParameter() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/foo/bar",
		Headers: map[string]string{},
		Parameters: map[string]string{
			"baz": "qux",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("/foo/bar?baz=qux", sysReq.URL.Path)
}

func (t *ConnTest) RequestContainsMultipleParameters() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/foo/bar",
		Headers: map[string]string{},
		Parameters: map[string]string{
			"baz": "qux",
			"taco": "burrito",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("/foo/bar?baz=qux&taco=burrito", sysReq.URL.Path)
}

func (t *ConnTest) PathAndParametersNeedEscaping() {
	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/타코/&bar?",
		Headers: map[string]string{},
		Parameters: map[string]string{
			"b&az": "qu?x",
		},
	}

	// Call
	_, err = conn.SendRequest(req)
	AssertEq(nil, err)

	AssertNe(nil, t.handler.req)
	sysReq := t.handler.req

	ExpectEq("/타코/&bar??b az=qu x", sysReq.URL.Path)
	ExpectEq("/%ED%83%80%EC%BD%94/&bar%3F?b%26az=qu%3Fx", sysReq.RequestURI)
}

func (t *ConnTest) ReturnsStatusCode() {
	// Handler
	t.handler.statusCode = 123

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectEq(123, resp.StatusCode)
}

func (t *ConnTest) ReturnsBody() {
	// Handler
	t.handler.body = []byte{0xde, 0xad, 0x00, 0xbe, 0xef}

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectThat(resp.Body, DeepEquals(t.handler.body))
}

func (t *ConnTest) ServerReturnsEmptyBody() {
	// Handler
	t.handler.body = []byte{}

	// Connection
	conn, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)

	// Request
	req := &http.Request{
		Verb:    "GET",
		Path:    "/",
		Headers: map[string]string{},
	}

	// Call
	resp, err := conn.SendRequest(req)
	AssertEq(nil, err)

	ExpectThat(resp.Body, ElementsAre())
}

func (t *ConnTest) HttpsAllowed() {
	t.endpoint.Scheme = "https"

	// Connection
	_, err := http.NewConn(t.endpoint)
	AssertEq(nil, err)
}
<|endoftext|>


<commit_before>package handler

import (
	"sort"

	. "github.com/oursky/skygear/ourtest"
	. "github.com/smartystreets/goconvey/convey"
	"testing"

	"github.com/oursky/skygear/handler/handlertest"
	"github.com/oursky/skygear/router"
	"github.com/oursky/skygear/skydb"
)

type testRelationConn struct {
	UserInfo     []skydb.UserInfo
	RelationName string
	addedID      string
	removeID     string
	addErr       error
	removeErr    error
	skydb.Conn
}

func (conn *testRelationConn) GetUser(id string, userinfo *skydb.UserInfo) error {
	userinfo.ID = id
	userinfo.Username = "testRelationConn"
	return nil
}

type sortByID []skydb.UserInfo

func (a sortByID) Len() int           { return len(a) }
func (a sortByID) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a sortByID) Less(i, j int) bool { return a[i].ID < a[j].ID }

func (conn *testRelationConn) QueryRelation(user string, name string, direction string, config skydb.QueryConfig) []skydb.UserInfo {
	conn.RelationName = name
	if conn.UserInfo == nil {
		return []skydb.UserInfo{}
	}

	sort.Sort(sortByID(conn.UserInfo))
	if config.Limit == 0 {
		return conn.UserInfo[config.Offset:]
	}

	if config.Offset+config.Limit-1 > uint64(len(conn.UserInfo)) {
		return conn.UserInfo[config.Offset:]
	}
	return conn.UserInfo[config.Offset : config.Offset+config.Limit]
}

func (conn *testRelationConn) AddRelation(user string, name string, targetUser string) error {
	conn.RelationName = name
	conn.addedID = targetUser
	return nil
}

func (conn *testRelationConn) RemoveRelation(user string, name string, targetUser string) error {
	conn.RelationName = name
	conn.removeID = targetUser
	return nil
}

func (conn *testRelationConn) QueryRelationCount(user string, name string, direction string) (uint64, error) {
	conn.RelationName = name
	if conn.UserInfo == nil {
		return 0, nil
	}
	count := uint64(len(conn.UserInfo))
	return count, nil
}

func TestRelationHandler(t *testing.T) {
	Convey("RelationAddHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationAddHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("add new relation", func() {
			resp := r.POST(`{
    "name": "friend",
    "targets": [
        "some-friend"
    ]
}`)

			So(conn.addedID, ShouldEqual, "some-friend")
			So(conn.RelationName, ShouldEqual, "_friend")
			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "some-friend",
        "type": "user",
        "data": {
            "_id": "some-friend",
            "username": "testRelationConn"
        }
    }]
}`)
		})
	})

	Convey("RelationQueryHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationQueryHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("query outward relation", func() {
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [],
    "info": {
        "count": 0
    }
}`)
		})

		Convey("query inward relation with count", func() {
			users := []skydb.UserInfo{}
			users = append(users, skydb.UserInfo{
				ID:       "101",
				Username: "user101",
				Email:    "user101@skygear.io",
			})
			conn.UserInfo = users
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "101",
        "type": "user",
        "data":{
            "_id": "101",
            "email": "user101@skygear.io",
            "username": "user101"
        }
    }],
    "info": {
        "count": 1
    }
}`)
		})

		Convey("query relation with _follow", func() {
			resp := r.POST(`{
    "name": "_follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [],
    "info": {
        "count": 0
    }
}`)
		})

		Convey("query relation with pagination", func() {
			user1 := skydb.UserInfo{
				ID:       "101",
				Username: "user101",
				Email:    "user101@skygear.io",
			}
			user2 := skydb.UserInfo{
				ID:       "102",
				Username: "user102",
				Email:    "user102@skygear.io",
			}

			users := []skydb.UserInfo{}
			users = append(users, user1)
			users = append(users, user2)
			conn.UserInfo = users
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward",
	"limit": 1
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "101",
        "type": "user",
        "data":{
            "_id": "101",
            "email": "user101@skygear.io",
            "username": "user101"
        }
    }],
    "info": {
        "count": 2
    }
}`)

			resp = r.POST(`{
    "name": "follow",
    "direction": "outward",
	"limit": 1,
	"offset": 1
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "102",
        "type": "user",
        "data":{
            "_id": "102",
            "email": "user102@skygear.io",
            "username": "user102"
        }
    }],
    "info": {
        "count": 2
    }
}`)
		})

		Convey("query relation with wrong direction", func() {
			resp := r.POST(`{
    "name": "follow",
    "direction": "bidirection"
}`)

			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "error": {
        "code": 108,
        "message": "Only outward, inward and mutual direction is allowed",
		"name": "InvalidArgument"
    }
}`)
		})
	})

	Convey("RelationRemoveHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationRemoveHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("remove a relation", func() {
			resp := r.POST(`{
    "name": "friend",
    "targets": [
        "old-friend"
    ]
}`)

			So(conn.removeID, ShouldEqual, "old-friend")
			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "old-friend"
    }]
}`)
		})
	})
}
<commit_msg>Rename sortByID to sortableUserInfo<commit_after>package handler

import (
	"sort"

	. "github.com/oursky/skygear/ourtest"
	. "github.com/smartystreets/goconvey/convey"
	"testing"

	"github.com/oursky/skygear/handler/handlertest"
	"github.com/oursky/skygear/router"
	"github.com/oursky/skygear/skydb"
)

type testRelationConn struct {
	UserInfo     []skydb.UserInfo
	RelationName string
	addedID      string
	removeID     string
	addErr       error
	removeErr    error
	skydb.Conn
}

func (conn *testRelationConn) GetUser(id string, userinfo *skydb.UserInfo) error {
	userinfo.ID = id
	userinfo.Username = "testRelationConn"
	return nil
}

type sortableUserInfo []skydb.UserInfo

func (a sortableUserInfo) Len() int           { return len(a) }
func (a sortableUserInfo) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a sortableUserInfo) Less(i, j int) bool { return a[i].ID < a[j].ID }

func (conn *testRelationConn) QueryRelation(user string, name string, direction string, config skydb.QueryConfig) []skydb.UserInfo {
	conn.RelationName = name
	if conn.UserInfo == nil {
		return []skydb.UserInfo{}
	}

	sort.Sort(sortableUserInfo(conn.UserInfo))
	if config.Limit == 0 {
		return conn.UserInfo[config.Offset:]
	}

	if config.Offset+config.Limit-1 > uint64(len(conn.UserInfo)) {
		return conn.UserInfo[config.Offset:]
	}
	return conn.UserInfo[config.Offset : config.Offset+config.Limit]
}

func (conn *testRelationConn) AddRelation(user string, name string, targetUser string) error {
	conn.RelationName = name
	conn.addedID = targetUser
	return nil
}

func (conn *testRelationConn) RemoveRelation(user string, name string, targetUser string) error {
	conn.RelationName = name
	conn.removeID = targetUser
	return nil
}

func (conn *testRelationConn) QueryRelationCount(user string, name string, direction string) (uint64, error) {
	conn.RelationName = name
	if conn.UserInfo == nil {
		return 0, nil
	}
	count := uint64(len(conn.UserInfo))
	return count, nil
}

func TestRelationHandler(t *testing.T) {
	Convey("RelationAddHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationAddHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("add new relation", func() {
			resp := r.POST(`{
    "name": "friend",
    "targets": [
        "some-friend"
    ]
}`)

			So(conn.addedID, ShouldEqual, "some-friend")
			So(conn.RelationName, ShouldEqual, "_friend")
			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "some-friend",
        "type": "user",
        "data": {
            "_id": "some-friend",
            "username": "testRelationConn"
        }
    }]
}`)
		})
	})

	Convey("RelationQueryHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationQueryHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("query outward relation", func() {
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [],
    "info": {
        "count": 0
    }
}`)
		})

		Convey("query inward relation with count", func() {
			users := []skydb.UserInfo{}
			users = append(users, skydb.UserInfo{
				ID:       "101",
				Username: "user101",
				Email:    "user101@skygear.io",
			})
			conn.UserInfo = users
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "101",
        "type": "user",
        "data":{
            "_id": "101",
            "email": "user101@skygear.io",
            "username": "user101"
        }
    }],
    "info": {
        "count": 1
    }
}`)
		})

		Convey("query relation with _follow", func() {
			resp := r.POST(`{
    "name": "_follow",
    "direction": "outward"
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [],
    "info": {
        "count": 0
    }
}`)
		})

		Convey("query relation with pagination", func() {
			user1 := skydb.UserInfo{
				ID:       "101",
				Username: "user101",
				Email:    "user101@skygear.io",
			}
			user2 := skydb.UserInfo{
				ID:       "102",
				Username: "user102",
				Email:    "user102@skygear.io",
			}

			users := []skydb.UserInfo{}
			users = append(users, user1)
			users = append(users, user2)
			conn.UserInfo = users
			resp := r.POST(`{
    "name": "follow",
    "direction": "outward",
	"limit": 1
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "101",
        "type": "user",
        "data":{
            "_id": "101",
            "email": "user101@skygear.io",
            "username": "user101"
        }
    }],
    "info": {
        "count": 2
    }
}`)

			resp = r.POST(`{
    "name": "follow",
    "direction": "outward",
	"limit": 1,
	"offset": 1
}`)

			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "102",
        "type": "user",
        "data":{
            "_id": "102",
            "email": "user102@skygear.io",
            "username": "user102"
        }
    }],
    "info": {
        "count": 2
    }
}`)
		})

		Convey("query relation with wrong direction", func() {
			resp := r.POST(`{
    "name": "follow",
    "direction": "bidirection"
}`)

			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "error": {
        "code": 108,
        "message": "Only outward, inward and mutual direction is allowed",
		"name": "InvalidArgument"
    }
}`)
		})
	})

	Convey("RelationRemoveHandler", t, func() {
		conn := testRelationConn{}
		r := handlertest.NewSingleRouteRouter(RelationRemoveHandler, func(p *router.Payload) {
			p.DBConn = &conn
		})

		Convey("remove a relation", func() {
			resp := r.POST(`{
    "name": "friend",
    "targets": [
        "old-friend"
    ]
}`)

			So(conn.removeID, ShouldEqual, "old-friend")
			So(resp.Code, ShouldEqual, 200)
			So(resp.Body.Bytes(), ShouldEqualJSON, `{
    "result": [{
        "id": "old-friend"
    }]
}`)
		})
	})
}
<|endoftext|>


<commit_before>// +build cit

package network

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/guest-test-infra/imagetest/utils"
)

const (
	markerFile = "/boot-marker"
)

func TestAliases(t *testing.T) {
	if err := verifyIPAliases(); err != nil {
		t.Fatal(err)
	}
}

func TestAliasAfterReboot(t *testing.T) {
	_, err := os.Stat(markerFile)
	if os.IsNotExist(err) {
		// first boot
		if _, err := os.Create(markerFile); err != nil {
			t.Fatalf("failed creating marker file: %v", err)
		}
		t.Fatal("first boot")
	}
	// second boot
	if err := verifyIPAliases(); err != nil {
		t.Fatal(err)
	}
}

func verifyIPAliases() error {
	var networkInterface string

	image, err := utils.GetMetadata("image")
	if err != nil {
		return fmt.Errorf("couldn't get image from metadata: %v", err)
	}
	switch {
	case strings.Contains(image, "debian-10"), strings.Contains(image, "ubuntu"):
		networkInterface = defaultPredictableInterface
	default:
		networkInterface = defaultInterface
	}

	actualIPs, err := getGoogleRoutes(networkInterface)
	if err != nil {
		return err
	}
	if err := verifyIPExist(actualIPs); err != nil {
		return err
	}
	return nil
}

func getGoogleRoutes(networkInterface string) ([]string, error) {
	// First, we probably need to wait so the guest agent can add the
	// routes. If this is insufficient, we might need to add retries.
	time.Sleep(30 * time.Second)

	arguments := strings.Split(fmt.Sprintf("route list table local type local scope host dev %s proto 66", networkInterface), " ")
	cmd := exec.Command("ip", arguments...)
	b, err := cmd.Output()
	if err != nil {
		return nil, err
	}
	if len(b) == 0 {
		return nil, fmt.Errorf("alias IPs not configured")
	}
	var res []string
	for _, line := range strings.Split(string(b), "\n") {
		ip := strings.Split(line, " ")
		if len(ip) >= 2 {
			res = append(res, ip[1])
		}
	}
	return res, nil
}

func TestAliasAgentRestart(t *testing.T) {
	var networkInterface string

	image, err := utils.GetMetadata("image")
	if err != nil {
		t.Fatalf("couldn't get image from metadata")
	}

	switch {
	case strings.Contains(image, "debian-10"), strings.Contains(image, "ubuntu"):
		networkInterface = defaultPredictableInterface
	default:
		networkInterface = defaultInterface
	}

	beforeRestart, err := getGoogleRoutes(networkInterface)
	if err != nil {
		t.Fatal(err)
	}
	cmd := exec.Command("systemctl", "restart", "google-guest-agent")
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
	afterRestart, err := getGoogleRoutes(networkInterface)
	if err != nil {
		t.Fatal(err)
	}
	if !compare(beforeRestart, afterRestart) {
		t.Fatalf("routes are inconsistent after restart, before %v after %v", beforeRestart, afterRestart)
	}
	if err := verifyIPExist(afterRestart); err != nil {
		t.Fatal(err)
	}
}

func verifyIPExist(routes []string) error {
	expected, err := utils.GetMetadata("network-interfaces/0/ip-aliases/0")
	if err != nil {
		return fmt.Errorf("couldn't get first alias IP from metadata: %v", err)
	}
	for _, route := range routes {
		if route == expected {
			return nil
		}
	}
	return fmt.Errorf("alias ip %s is not exist after reboot", expected)
}

func compare(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<commit_msg>Support d11 in Alias IP test (#276)<commit_after>// +build cit

package network

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/guest-test-infra/imagetest/utils"
)

const (
	markerFile = "/boot-marker"
)

func TestAliases(t *testing.T) {
	if err := verifyIPAliases(); err != nil {
		t.Fatal(err)
	}
}

func TestAliasAfterReboot(t *testing.T) {
	_, err := os.Stat(markerFile)
	if os.IsNotExist(err) {
		// first boot
		if _, err := os.Create(markerFile); err != nil {
			t.Fatalf("failed creating marker file: %v", err)
		}
		t.Fatal("first boot")
	}
	// second boot
	if err := verifyIPAliases(); err != nil {
		t.Fatal(err)
	}
}

func verifyIPAliases() error {
	var networkInterface string

	image, err := utils.GetMetadata("image")
	if err != nil {
		return fmt.Errorf("couldn't get image from metadata: %v", err)
	}
	switch {
	case strings.Contains(image, "debian-10"), strings.Contains(image, "debian-11"), strings.Contains(image, "ubuntu"):
		networkInterface = defaultPredictableInterface
	default:
		networkInterface = defaultInterface
	}

	actualIPs, err := getGoogleRoutes(networkInterface)
	if err != nil {
		return err
	}
	if err := verifyIPExist(actualIPs); err != nil {
		return err
	}
	return nil
}

func getGoogleRoutes(networkInterface string) ([]string, error) {
	// First, we probably need to wait so the guest agent can add the
	// routes. If this is insufficient, we might need to add retries.
	time.Sleep(30 * time.Second)

	arguments := strings.Split(fmt.Sprintf("route list table local type local scope host dev %s proto 66", networkInterface), " ")
	cmd := exec.Command("ip", arguments...)
	b, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("error listing Google routes: %s", b)
	}
	if len(b) == 0 {
		return nil, fmt.Errorf("No Google routes found")
	}
	var res []string
	for _, line := range strings.Split(string(b), "\n") {
		ip := strings.Split(line, " ")
		if len(ip) >= 2 {
			res = append(res, ip[1])
		}
	}
	return res, nil
}

func TestAliasAgentRestart(t *testing.T) {
	var networkInterface string

	image, err := utils.GetMetadata("image")
	if err != nil {
		t.Fatalf("couldn't get image from metadata")
	}

	switch {
	case strings.Contains(image, "debian-10"), strings.Contains(image, "debian-11"), strings.Contains(image, "ubuntu"):
		networkInterface = defaultPredictableInterface
	default:
		networkInterface = defaultInterface
	}

	beforeRestart, err := getGoogleRoutes(networkInterface)
	if err != nil {
		t.Fatal(err)
	}
	cmd := exec.Command("systemctl", "restart", "google-guest-agent")
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}
	afterRestart, err := getGoogleRoutes(networkInterface)
	if err != nil {
		t.Fatal(err)
	}
	if !compare(beforeRestart, afterRestart) {
		t.Fatalf("routes are inconsistent after restart, before %v after %v", beforeRestart, afterRestart)
	}
	if err := verifyIPExist(afterRestart); err != nil {
		t.Fatal(err)
	}
}

func verifyIPExist(routes []string) error {
	expected, err := utils.GetMetadata("network-interfaces/0/ip-aliases/0")
	if err != nil {
		return fmt.Errorf("couldn't get first alias IP from metadata: %v", err)
	}
	for _, route := range routes {
		if route == expected {
			return nil
		}
	}
	return fmt.Errorf("alias ip %s is not exist after reboot", expected)
}

func compare(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the list manipulation primitive functions.

package golisp

import ()

func RegisterListManipulationPrimitives() {
	MakePrimitiveFunction("list", -1, MakeListImpl)
	MakePrimitiveFunction("length", 1, ListLengthImpl)
	MakePrimitiveFunction("cons", 2, ConsImpl)
	MakePrimitiveFunction("reverse", 1, ReverseImpl)
	MakePrimitiveFunction("flatten", 1, FlattenImpl)
	MakePrimitiveFunction("flatten*", 1, RecursiveFlattenImpl)
	MakePrimitiveFunction("append", 2, AppendImpl)
	MakePrimitiveFunction("append!", 2, AppendBangImpl)
	MakePrimitiveFunction("copy", 1, CopyImpl)
	MakePrimitiveFunction("partition", 2, PartitionImpl)
	MakePrimitiveFunction("sublist", 3, SublistImpl)
}

func MakeListImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var items []*Data = make([]*Data, 0, Length(args))
	var item *Data
	for cell := args; NotNilP(cell); cell = Cdr(cell) {
		item, err = Eval(Car(cell), env)
		if err != nil {
			return
		}
		items = append(items, item)
	}
	result = ArrayToList(items)
	return
}

func ListLengthImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	d, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	return IntegerWithValue(int64(Length(d))), nil
}

func ConsImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var car *Data
	car, err = Eval(Car(args), env)
	if err != nil {
		return
	}

	var cdr *Data
	cdr, err = Eval(Cadr(args), env)
	if err != nil {
		return
	}

	result = Cons(car, cdr)
	return
}

func ReverseImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result = Reverse(val)
	return
}

func FlattenImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result, err = Flatten(val)
	return
}

func RecursiveFlattenImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result, err = RecursiveFlatten(val)
	return
}

func AppendBangImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	firstList, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	second, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}

	if ListP(second) {
		result = AppendBangList(firstList, second)
	} else {
		result = AppendBang(firstList, second)
	}

	if SymbolP(Car(args)) {
		env.BindTo(Car(args), result)
	}

	return
}

func AppendImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	firstList, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	second, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}

	if ListP(second) {
		result = AppendList(Copy(firstList), second)
	} else {
		result = Append(Copy(firstList), second)
	}
	return
}

func CopyImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	d, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	return Copy(d), nil
}

func PartitionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	n, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("partition requires a number as it's first argument.", env)
	}
	size := int(IntegerValue(n))

	l, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !ListP(l) {
		err = ProcessError("partition requires a list as it's second argument.", env)
	}

	var pieces []*Data = make([]*Data, 0, 5)
	var chunk []*Data = make([]*Data, 0, 5)
	for c := l; NotNilP(c); c = Cdr(c) {
		if len(chunk) < size {
			chunk = append(chunk, Car(c))
		} else {
			pieces = append(pieces, ArrayToList(chunk))
			chunk = make([]*Data, 0, 5)
			chunk = append(chunk, Car(c))
		}
	}
	if len(chunk) > 0 {
		pieces = append(pieces, ArrayToList(chunk))
	}

	return ArrayToList(pieces), nil
}

func SublistImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	n, err := Eval(First(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("sublist requires a number as it's first argument.", env)
	}
	first := int(IntegerValue(n))

	n, err = Eval(Second(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("sublist requires a number as it's second argument.", env)
	}
	last := int(IntegerValue(n))

	if first >= last {
		result = nil
		return
	}

	l, err := Eval(Third(args), env)
	if err != nil {
		return
	}
	if !ListP(l) {
		err = ProcessError("sublist requires a list as it's third argument.", env)
	}

	var cell *Data
	var i int
	for i, cell = 1, l; i < first && NotNilP(cell); i, cell = i+1, Cdr(cell) {
	}

	var items []*Data = make([]*Data, 0, Length(args))
	for ; i <= last && NotNilP(cell); i, cell = i+1, Cdr(cell) {
		items = append(items, Car(cell))
	}
	result = ArrayToList(items)
	return
}
<commit_msg>Rewrite the implementation of append to take any number of things... putting them all into a list. As opposed to list, list aruments have their items added to the result individually.<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the list manipulation primitive functions.

package golisp

import ()

func RegisterListManipulationPrimitives() {
	MakePrimitiveFunction("list", -1, MakeListImpl)
	MakePrimitiveFunction("length", 1, ListLengthImpl)
	MakePrimitiveFunction("cons", 2, ConsImpl)
	MakePrimitiveFunction("reverse", 1, ReverseImpl)
	MakePrimitiveFunction("flatten", 1, FlattenImpl)
	MakePrimitiveFunction("flatten*", 1, RecursiveFlattenImpl)
	MakePrimitiveFunction("append", -1, AppendImpl)
	MakePrimitiveFunction("append!", 2, AppendBangImpl)
	MakePrimitiveFunction("copy", 1, CopyImpl)
	MakePrimitiveFunction("partition", 2, PartitionImpl)
	MakePrimitiveFunction("sublist", 3, SublistImpl)
}

func MakeListImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var items []*Data = make([]*Data, 0, Length(args))
	var item *Data
	for cell := args; NotNilP(cell); cell = Cdr(cell) {
		item, err = Eval(Car(cell), env)
		if err != nil {
			return
		}
		items = append(items, item)
	}
	result = ArrayToList(items)
	return
}

func ListLengthImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	d, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	return IntegerWithValue(int64(Length(d))), nil
}

func ConsImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var car *Data
	car, err = Eval(Car(args), env)
	if err != nil {
		return
	}

	var cdr *Data
	cdr, err = Eval(Cadr(args), env)
	if err != nil {
		return
	}

	result = Cons(car, cdr)
	return
}

func ReverseImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result = Reverse(val)
	return
}

func FlattenImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result, err = Flatten(val)
	return
}

func RecursiveFlattenImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var val *Data
	val, err = Eval(Car(args), env)
	if err != nil {
		return
	}
	result, err = RecursiveFlatten(val)
	return
}

func AppendBangImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	firstList, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	second, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}

	if ListP(second) {
		result = AppendBangList(firstList, second)
	} else {
		result = AppendBang(firstList, second)
	}

	if SymbolP(Car(args)) {
		env.BindTo(Car(args), result)
	}

	return
}

func AppendImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	// No args -> empty list
	if Length(args) == 0 {
		return
	}

	// step through args, accumulating elements
	var items []*Data = make([]*Data, 0, 10)
	var item *Data
	for cell := args; NotNilP(cell); cell = Cdr(cell) {
		item, err = Eval(Car(cell), env)
		if err != nil {
			return
		}
		if ListP(item) {
			for itemCell := item; NotNilP(itemCell); itemCell = Cdr(itemCell) {
				items = append(items, Car(itemCell))
			}
		} else {
			items = append(items, item)
		}
	}
	result = ArrayToList(items)
	return
}

func CopyImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	d, err := Eval(Car(args), env)
	if err != nil {
		return
	}

	return Copy(d), nil
}

func PartitionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	n, err := Eval(Car(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("partition requires a number as it's first argument.", env)
	}
	size := int(IntegerValue(n))

	l, err := Eval(Cadr(args), env)
	if err != nil {
		return
	}
	if !ListP(l) {
		err = ProcessError("partition requires a list as it's second argument.", env)
	}

	var pieces []*Data = make([]*Data, 0, 5)
	var chunk []*Data = make([]*Data, 0, 5)
	for c := l; NotNilP(c); c = Cdr(c) {
		if len(chunk) < size {
			chunk = append(chunk, Car(c))
		} else {
			pieces = append(pieces, ArrayToList(chunk))
			chunk = make([]*Data, 0, 5)
			chunk = append(chunk, Car(c))
		}
	}
	if len(chunk) > 0 {
		pieces = append(pieces, ArrayToList(chunk))
	}

	return ArrayToList(pieces), nil
}

func SublistImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	n, err := Eval(First(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("sublist requires a number as it's first argument.", env)
	}
	first := int(IntegerValue(n))

	n, err = Eval(Second(args), env)
	if err != nil {
		return
	}
	if !IntegerP(n) {
		err = ProcessError("sublist requires a number as it's second argument.", env)
	}
	last := int(IntegerValue(n))

	if first >= last {
		result = nil
		return
	}

	l, err := Eval(Third(args), env)
	if err != nil {
		return
	}
	if !ListP(l) {
		err = ProcessError("sublist requires a list as it's third argument.", env)
	}

	var cell *Data
	var i int
	for i, cell = 1, l; i < first && NotNilP(cell); i, cell = i+1, Cdr(cell) {
	}

	var items []*Data = make([]*Data, 0, Length(args))
	for ; i <= last && NotNilP(cell); i, cell = i+1, Cdr(cell) {
		items = append(items, Car(cell))
	}
	result = ArrayToList(items)
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
	"regexp"
	"github.com/k0kubun/go-ansi"
	"io/ioutil"
)

var (
	outputRegexp *regexp.Regexp
)

type builtinGet struct{}

// Apply to all "get" commands, ignoring flags
func (b builtinGet) filter(command string) bool {
	if outputRegexp == nil {
		outputRegexp, _ = regexp.Compile(`^([^|]*)(-o|--output)(\s*=\s*|\s+)(json|yaml)`)
	}

	return strings.HasPrefix(command, "get") && !outputRegexp.MatchString(command)
}

func (b builtinGet) run(command string) error {
	variableIndex := 0

	lines := make(map[string]int, 0)

	return shHandler(kubectl(command), func(line string) {
		firstColumn := strings.Split(line, " ")[0]
		lineOffset, lineDefined := lines[firstColumn]

		if lineDefined {
			ansi.CursorPreviousLine(lineOffset)
			ansi.EraseInLine(2) // clear entire line
			fmt.Printf("   \t%s\n", line)

		} else {
			if strings.HasPrefix(line, "NAME ") {
				fmt.Printf("   \t%s\n", line)

			} else {
				variableIndex++
				key := fmt.Sprintf("%d", variableIndex)

				// shift existing lines
				for k, _ := range lines {
					lines[k] += 1
				}

				lines[firstColumn] = 1
				printIndexedLine(key, line)
			}
		}

		ioutil.WriteFile("/dev/ttys012", []byte(fmt.Sprintf("%#v\n", lines)), 777)
		ansi.CursorNextLine(999) // reset cursor

		// save variable
		key := fmt.Sprintf("%d", variableIndex)
		variables[key] = firstColumn
	})
}
<commit_msg>remove dynamic update in watch mode<commit_after>package main

import (
	"fmt"
	"strings"
	"regexp"
)

var (
	outputRegexp *regexp.Regexp
)

type builtinGet struct{}

// Apply to all "get" commands, ignoring flags
func (b builtinGet) filter(command string) bool {
	if outputRegexp == nil {
		outputRegexp, _ = regexp.Compile(`^([^|]*)(-o|--output)(\s*=\s*|\s+)(json|yaml)`)
	}

	return strings.HasPrefix(command, "get") && !outputRegexp.MatchString(command)
}

func (b builtinGet) run(command string) error {
	variableIndex := 0
	return shHandler(kubectl(command), func(line string) {
		if strings.HasPrefix(line, "NAME ") {
			fmt.Printf("   \t%s\n", line)
		} else {
			variableIndex++
			key := fmt.Sprintf("%d", variableIndex)
			printIndexedLine(key, line)
		}
		key := fmt.Sprintf("%d", variableIndex)
		variables[key] = strings.Split(line, " ")[0]
	})
}
<|endoftext|>


<commit_before>package land

import (
	"github.com/Nyarum/noterius/core"

	"io"
	"log"
	"net"
)

// Application struct for project and his variables
type Application struct {
	Config       core.Config
	Database     core.Database
	ErrorHandler func(c net.Conn)
}

// Run function for starting server
func (a *Application) Run() (err error) {
	listen, err := net.Listen("tcp", a.Config.Base.IP+":"+a.Config.Base.Port)
	if err != nil {
		return
	}

	for {
		client, err := listen.Accept()
		if err != nil {
			log.Println(err)
			continue
		}

		go func(c net.Conn, conf core.Config) {
			defer a.ErrorHandler(c)

			log.Println("Client is connected:", c.RemoteAddr())

			var (
				bytesAlloc      []byte      = make([]byte, conf.Option.LenBuffer)
				readBytesSocket chan string = make(chan string)
			)
			defer close(readBytesSocket)

			go ClientLive(c, readBytesSocket, conf)

			for {
				if _, err := c.Read(bytesAlloc); err == io.EOF {
					log.Printf("Client [%v] is disconnected\n", c.RemoteAddr())
					break
				} else if err != nil {
					log.Printf("Client [%v] is error read packet, err - %v\n", c.RemoteAddr(), err)
				}

				readBytesSocket <- string(bytesAlloc)
			}
		}(client, a.Config)
	}
}
<commit_msg>Delete defer for close channel<commit_after>package land

import (
	"github.com/Nyarum/noterius/core"

	"io"
	"log"
	"net"
)

// Application struct for project and his variables
type Application struct {
	Config       core.Config
	Database     core.Database
	ErrorHandler func(c net.Conn)
}

// Run function for starting server
func (a *Application) Run() (err error) {
	listen, err := net.Listen("tcp", a.Config.Base.IP+":"+a.Config.Base.Port)
	if err != nil {
		return
	}

	for {
		client, err := listen.Accept()
		if err != nil {
			log.Println(err)
			continue
		}

		go func(c net.Conn, conf core.Config) {
			defer a.ErrorHandler(c)

			log.Println("Client is connected:", c.RemoteAddr())

			var (
				bytesAlloc      []byte      = make([]byte, conf.Option.LenBuffer)
				readBytesSocket chan string = make(chan string)
			)

			go ClientLive(c, readBytesSocket, conf)

			for {
				if _, err := c.Read(bytesAlloc); err == io.EOF {
					log.Printf("Client [%v] is disconnected\n", c.RemoteAddr())
					break
				} else if err != nil {
					log.Printf("Client [%v] is error read packet, err - %v\n", c.RemoteAddr(), err)
				}

				readBytesSocket <- string(bytesAlloc)
			}
		}(client, a.Config)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
	"os/exec"

	"v2ray.com/core"
	"v2ray.com/core/common/platform"
)

func jsonToProto(input io.Reader) (*core.Config, error) {
	v2ctl := platform.GetToolLocation("v2ctl")
	_, err := os.Stat(v2ctl)
	if err != nil {
		return nil, err
	}
	cmd := exec.Command(v2ctl, "config")
	cmd.Stdin = input
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = getSysProcAttr()

	stdoutReader, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	defer stdoutReader.Close()

	if err := cmd.Start(); err != nil {
		return nil, err
	}

	config, err := core.LoadConfig(core.ConfigFormat_Protobuf, stdoutReader)

	cmd.Wait()

	return config, err
}

func init() {
	core.RegisterConfigLoader(core.ConfigFormat_JSON, func(input io.Reader) (*core.Config, error) {
		config, err := jsonToProto(input)
		if err != nil {
			return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
		}
		return config, nil
	})
}
<commit_msg>fix loading of json config<commit_after>package main

import (
	"context"
	"io"
	"os"
	"os/exec"

	"v2ray.com/core"
	"v2ray.com/core/common"
	"v2ray.com/core/common/platform"
	"v2ray.com/core/common/signal"
)

type logWriter struct{}

func (*logWriter) Write(b []byte) (int, error) {
	n, err := os.Stderr.Write(b)
	if err == nil {
		os.Stderr.WriteString(platform.LineSeparator())
	}
	return n, err
}

func jsonToProto(input io.Reader) (*core.Config, error) {
	v2ctl := platform.GetToolLocation("v2ctl")
	if _, err := os.Stat(v2ctl); err != nil {
		return nil, err
	}
	cmd := exec.Command(v2ctl, "config")
	cmd.Stdin = input
	cmd.Stderr = &logWriter{}
	cmd.SysProcAttr = getSysProcAttr()

	stdoutReader, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	defer stdoutReader.Close()

	if err := cmd.Start(); err != nil {
		return nil, err
	}

	var config *core.Config

	loadTask := signal.ExecuteAsync(func() error {
		c, err := core.LoadConfig(core.ConfigFormat_Protobuf, stdoutReader)
		if err != nil {
			return err
		}
		config = c
		return nil
	})

	waitTask := signal.ExecuteAsync(func() error {
		return cmd.Wait()
	})

	if err := signal.ErrorOrFinish2(context.Background(), loadTask, waitTask); err != nil {
		return nil, err
	}

	return config, nil
}

func init() {
	common.Must(core.RegisterConfigLoader(core.ConfigFormat_JSON, func(input io.Reader) (*core.Config, error) {
		config, err := jsonToProto(input)
		if err != nil {
			return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
		}
		return config, nil
	}))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/Sirupsen/logrus"
)

const (
	ghRawUri = "https://raw.githubusercontent.com"
	head     = `#
# THIS FILE IS AUTOGENERATED; SEE "./maintainers"!
#
# Docker projects maintainers file
#
# This file describes who runs the Docker project and how.
# This is a living document - if you see something out of date or missing,
# speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant
# parser.
`
)

var (
	org      = "docker"
	projects = []string{
		"compose",
		"distribution",
		"docker",
		"dockercraft",
		"kitematic",
		"libcompose",
		"libnetwork",
		"machine",
		"notary",
		"swarm",
		"toolbox",
	}
)

//go:generate go run generate.go

func main() {
	// initialize the project MAINTAINERS file
	projectMaintainers := Maintainers{
		Org:    map[string]*Org{},
		People: map[string]Person{},
	}

	// parse the MAINTAINERS file for each repo
	for _, project := range projects {
		maintainers, err := getMaintainers(project)
		if err != nil {
			logrus.Errorf("%s: parsing MAINTAINERS file failed: %v", project, err)
			continue
		}

		// create the Org object for the project
		p := &Org{
			// Repo: fmt.Sprintf("https://github.com/%s/%s", org, project),
			// TODO: change this to:
			// People: maintainers.Org["Core maintainers"].People,
			// once MaintainersDepreciated is removed.
			People: maintainers.Organization.CoreMaintainers.People,
		}

		// lowercase all maintainers nicks for consistency
		for i, n := range p.People {
			p.People[i] = strings.ToLower(n)
		}

		projectMaintainers.Org[project] = p

		if maintainers.Organization.DocsMaintainers != nil {
			projectMaintainers.Org["Docs maintainers"] = maintainers.Organization.DocsMaintainers
		}

		if maintainers.Organization.Curators != nil {
			projectMaintainers.Org["Curators"] = maintainers.Organization.Curators
		}

		// iterate through the people and add them to compiled list
		for nick, person := range maintainers.People {
			projectMaintainers.People[strings.ToLower(nick)] = person
		}
	}

	// encode the result to a file
	buf := new(bytes.Buffer)
	t := toml.NewEncoder(buf)
	t.Indent = "    "
	if err := t.Encode(projectMaintainers); err != nil {
		logrus.Fatalf("TOML encoding error: %v", err)
	}

	file := append([]byte(head), []byte(rules)...)
	file = append(file, []byte(roles)...)
	file = append(file, buf.Bytes()...)

	if err := ioutil.WriteFile("MAINTAINERS", file, 0755); err != nil {
		logrus.Fatal(err)
	}

	logrus.Infof("Successfully wrote new combined MAINTAINERS file.")
}

func getMaintainers(project string) (maintainers MaintainersDepreciated, err error) {
	fileUrl := fmt.Sprintf("%s/%s/%s/master/MAINTAINERS", ghRawUri, org, project)
	resp, err := http.Get(fileUrl)
	if err != nil {
		return maintainers, fmt.Errorf("%s: %v", project, err)
	}
	defer resp.Body.Close()

	file, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return maintainers, fmt.Errorf("%s: %v", project, err)
	}

	if _, err := toml.Decode(string(file), &maintainers); err != nil {
		return maintainers, fmt.Errorf("%s: parsing MAINTAINERS file failed: %v", project, err)
	}

	return maintainers, nil
}
<commit_msg>Add spdystream<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/Sirupsen/logrus"
)

const (
	ghRawUri = "https://raw.githubusercontent.com"
	head     = `#
# THIS FILE IS AUTOGENERATED; SEE "./maintainers"!
#
# Docker projects maintainers file
#
# This file describes who runs the Docker project and how.
# This is a living document - if you see something out of date or missing,
# speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant
# parser.
`
)

var (
	org      = "docker"
	projects = []string{
		"compose",
		"distribution",
		"docker",
		"dockercraft",
		"kitematic",
		"libcompose",
		"libnetwork",
		"machine",
		"notary",
		"spdystream",
		"swarm",
		"toolbox",
	}
)

//go:generate go run generate.go

func main() {
	// initialize the project MAINTAINERS file
	projectMaintainers := Maintainers{
		Org:    map[string]*Org{},
		People: map[string]Person{},
	}

	// parse the MAINTAINERS file for each repo
	for _, project := range projects {
		maintainers, err := getMaintainers(project)
		if err != nil {
			logrus.Errorf("%s: parsing MAINTAINERS file failed: %v", project, err)
			continue
		}

		// create the Org object for the project
		p := &Org{
			// Repo: fmt.Sprintf("https://github.com/%s/%s", org, project),
			// TODO: change this to:
			// People: maintainers.Org["Core maintainers"].People,
			// once MaintainersDepreciated is removed.
			People: maintainers.Organization.CoreMaintainers.People,
		}

		// lowercase all maintainers nicks for consistency
		for i, n := range p.People {
			p.People[i] = strings.ToLower(n)
		}

		projectMaintainers.Org[project] = p

		if maintainers.Organization.DocsMaintainers != nil {
			projectMaintainers.Org["Docs maintainers"] = maintainers.Organization.DocsMaintainers
		}

		if maintainers.Organization.Curators != nil {
			projectMaintainers.Org["Curators"] = maintainers.Organization.Curators
		}

		// iterate through the people and add them to compiled list
		for nick, person := range maintainers.People {
			projectMaintainers.People[strings.ToLower(nick)] = person
		}
	}

	// encode the result to a file
	buf := new(bytes.Buffer)
	t := toml.NewEncoder(buf)
	t.Indent = "    "
	if err := t.Encode(projectMaintainers); err != nil {
		logrus.Fatalf("TOML encoding error: %v", err)
	}

	file := append([]byte(head), []byte(rules)...)
	file = append(file, []byte(roles)...)
	file = append(file, buf.Bytes()...)

	if err := ioutil.WriteFile("MAINTAINERS", file, 0755); err != nil {
		logrus.Fatal(err)
	}

	logrus.Infof("Successfully wrote new combined MAINTAINERS file.")
}

func getMaintainers(project string) (maintainers MaintainersDepreciated, err error) {
	fileUrl := fmt.Sprintf("%s/%s/%s/master/MAINTAINERS", ghRawUri, org, project)
	resp, err := http.Get(fileUrl)
	if err != nil {
		return maintainers, fmt.Errorf("%s: %v", project, err)
	}
	defer resp.Body.Close()

	file, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return maintainers, fmt.Errorf("%s: %v", project, err)
	}

	if _, err := toml.Decode(string(file), &maintainers); err != nil {
		return maintainers, fmt.Errorf("%s: parsing MAINTAINERS file failed: %v", project, err)
	}

	return maintainers, nil
}
<|endoftext|>


<commit_before>package process

// #cgo CFLAGS: -std=c99
// #include <libproc.h>
// #include <errno.h>
// #include <stdlib.h>
import "C"

import (
	"fmt"
	"path/filepath"
	"reflect"
	"unsafe"
)

func (p process) Name() (name string, harderror error, softerrors []error) {
	cname := C.malloc(C.PROC_PIDPATHINFO_MAXSIZE)
	defer C.free(cname)

	_, err := C.proc_pidpath(C.int(p.pid), cname, C.PROC_PIDPATHINFO_MAXSIZE)
	if err != nil {
		harderr := fmt.Errorf("Error while reading name of process %d: %v", p.pid, err)
		return "", harderr, nil
	}

	name, harderror = filepath.EvalSymlinks(C.GoString((*C.char)(cname)))
	return
}

func getAllPids() (pids []uint, harderror error, softerrors []error) {
	var pid C.pid_t
	pidSize := unsafe.Sizeof(pid)
	cpidsSize := pidSize * 1024 * 2
	cpids := C.malloc(C.size_t(cpidsSize))
	defer C.free(cpids)

	bytesUsed, err := C.proc_listpids(C.PROC_ALL_PIDS, 0, cpids, C.int(cpidsSize))
	if err != nil {
		return nil, err, nil
	}

	numberOfPids := uintptr(bytesUsed) / pidSize
	pids = make([]uint, numberOfPids)
	cpidsSlice := *(*[]C.pid_t)(unsafe.Pointer(
		&reflect.SliceHeader{
			Data: uintptr(unsafe.Pointer(cpids)),
			Len:  int(numberOfPids),
			Cap:  int(numberOfPids)}))

	for i, _ := range cpidsSlice {
		pids[i] = uint(cpidsSlice[i])
	}

	return pids, nil, nil
}
<commit_msg>[process/darwin] Fix getAllPids<commit_after>package process

// #cgo CFLAGS: -std=c99
// #include <libproc.h>
// #include <errno.h>
// #include <stdlib.h>
import "C"

import (
	"fmt"
	"path/filepath"
	"reflect"
	"unsafe"
)

func (p process) Name() (name string, harderror error, softerrors []error) {
	cname := C.malloc(C.PROC_PIDPATHINFO_MAXSIZE)
	defer C.free(cname)

	_, err := C.proc_pidpath(C.int(p.pid), cname, C.PROC_PIDPATHINFO_MAXSIZE)
	if err != nil {
		harderr := fmt.Errorf("Error while reading name of process %d: %v", p.pid, err)
		return "", harderr, nil
	}

	name, harderror = filepath.EvalSymlinks(C.GoString((*C.char)(cname)))
	return
}

func getAllPids() (pids []uint, harderror error, softerrors []error) {
	var pid C.pid_t
	pidSize := unsafe.Sizeof(pid)
	cpidsSize := pidSize * 1024 * 2
	cpids := C.malloc(C.size_t(cpidsSize))
	defer C.free(cpids)

	bytesUsed, err := C.proc_listpids(C.PROC_ALL_PIDS, 0, cpids, C.int(cpidsSize))
	if err != nil {
		return nil, err, nil
	}

	numberOfPids := uintptr(bytesUsed) / pidSize
	pids = make([]uint, 0, numberOfPids)
	cpidsSlice := *(*[]C.pid_t)(unsafe.Pointer(
		&reflect.SliceHeader{
			Data: uintptr(unsafe.Pointer(cpids)),
			Len:  int(numberOfPids),
			Cap:  int(numberOfPids)}))

	for i, _ := range cpidsSlice {
		if cpidsSlice[i] == 0 {
			continue
		}

		pids = append(pids, uint(cpidsSlice[i]))
	}

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


<commit_before>// The packer package contains the core components of Packer.
package packer

import (
	"errors"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
)

type BuilderFunc func(name string) (Builder, error)

type CommandFunc func(name string) (Command, error)

// The environment interface provides access to the configuration and
// state of a single Packer run.
//
// It allows for things such as executing CLI commands, getting the
// list of available builders, and more.
type Environment interface {
	Builder(name string) (Builder, error)
	Cli(args []string) (int, error)
	Ui() Ui
}

// An implementation of an Environment that represents the Packer core
// environment.
type coreEnvironment struct {
	builderFunc BuilderFunc
	commands []string
	commandFunc CommandFunc
	ui      Ui
}

// This struct configures new environments.
type EnvironmentConfig struct {
	BuilderFunc BuilderFunc
	CommandFunc CommandFunc
	Commands []string
	Ui      Ui
}

// DefaultEnvironmentConfig returns a default EnvironmentConfig that can
// be used to create a new enviroment with NewEnvironment with sane defaults.
func DefaultEnvironmentConfig() *EnvironmentConfig {
	config := &EnvironmentConfig{}
	config.BuilderFunc = func(string) (Builder, error) { return nil, nil }
	config.CommandFunc = func(string) (Command, error) { return nil, nil }
	config.Commands = make([]string, 0)
	config.Ui = &ReaderWriterUi{os.Stdin, os.Stdout}
	return config
}

// This creates a new environment
func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) {
	if config == nil {
		err = errors.New("config must be given to initialize environment")
		return
	}

	env := &coreEnvironment{}
	env.builderFunc = config.BuilderFunc
	env.commandFunc = config.CommandFunc
	env.commands = config.Commands
	env.ui = config.Ui

	resultEnv = env
	return
}

// Returns a builder of the given name that is registered with this
// environment.
func (e *coreEnvironment) Builder(name string) (b Builder, err error) {
	b, err = e.builderFunc(name)
	if err != nil {
		return
	}

	if b == nil {
		err = fmt.Errorf("No builder returned for name: %s", name)
	}

	return
}

// Executes a command as if it was typed on the command-line interface.
// The return value is the exit code of the command.
func (e *coreEnvironment) Cli(args []string) (result int, err error) {
	log.Printf("Environment.Cli: %#v\n", args)

	if len(args) == 0 || args[0] == "--help" || args[0] == "-h" {
		e.printHelp()
		return 1, nil
	}

	version := args[0] == "version"
	if !version {
		for _, arg := range args {
			if arg == "--version" || arg == "-v" {
				version = true
				break
			}
		}
	}

	var command Command
	if version {
		command = new(versionCommand)
	}

	if command == nil {
		command, err = e.commandFunc(args[0])
		if err != nil {
			return
		}

		// If we still don't have a command, show the help.
		if command == nil {
			log.Printf("Environment.CLI: command not found: %s\n", args[0])
			e.printHelp()
			return 1, nil
		}
	}

	log.Printf("Executing command: %s\n", args[0])
	return command.Run(e, args[1:]), nil
}

// Prints the CLI help to the UI.
func (e *coreEnvironment) printHelp() {
	// Created a sorted slice of the map keys and record the longest
	// command name so we can better format the output later.
	i := 0
	maxKeyLen := 0
	for _, command := range e.commands {
		if len(command) > maxKeyLen {
			maxKeyLen = len(command)
		}

		i++
	}

	// Sort the keys
	sort.Strings(e.commands)

	e.ui.Say("usage: packer [--version] [--help] <command> [<args>]\n\n")
	e.ui.Say("Available commands are:\n")
	for _, key := range e.commands {
		var synopsis string

		command, err := e.commandFunc(key)
		if err != nil {
			synopsis = fmt.Sprintf("Error loading command: %s", err.Error())
		} else if command == nil {
			continue
		} else {
			synopsis = command.Synopsis()
		}

		// Pad the key with spaces so that they're all the same width
		key = fmt.Sprintf("%v%v", key, strings.Repeat(" ", maxKeyLen-len(key)))

		// Output the command and the synopsis
		e.ui.Say("    %v     %v\n", key, synopsis)
	}
}

// Returns the UI for the environment. The UI is the interface that should
// be used for all communication with the outside world.
func (e *coreEnvironment) Ui() Ui {
	return e.ui
}
<commit_msg>packer: More comments/docs<commit_after>// The packer package contains the core components of Packer.
package packer

import (
	"errors"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
)

// The function type used to lookup Builder implementations.
type BuilderFunc func(name string) (Builder, error)

// The function type used to lookup Command implementations.
type CommandFunc func(name string) (Command, error)

// The environment interface provides access to the configuration and
// state of a single Packer run.
//
// It allows for things such as executing CLI commands, getting the
// list of available builders, and more.
type Environment interface {
	Builder(name string) (Builder, error)
	Cli(args []string) (int, error)
	Ui() Ui
}

// An implementation of an Environment that represents the Packer core
// environment.
type coreEnvironment struct {
	builderFunc BuilderFunc
	commands []string
	commandFunc CommandFunc
	ui      Ui
}

// This struct configures new environments.
type EnvironmentConfig struct {
	BuilderFunc BuilderFunc
	CommandFunc CommandFunc
	Commands []string
	Ui      Ui
}

// DefaultEnvironmentConfig returns a default EnvironmentConfig that can
// be used to create a new enviroment with NewEnvironment with sane defaults.
func DefaultEnvironmentConfig() *EnvironmentConfig {
	config := &EnvironmentConfig{}
	config.BuilderFunc = func(string) (Builder, error) { return nil, nil }
	config.CommandFunc = func(string) (Command, error) { return nil, nil }
	config.Commands = make([]string, 0)
	config.Ui = &ReaderWriterUi{os.Stdin, os.Stdout}
	return config
}

// This creates a new environment
func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) {
	if config == nil {
		err = errors.New("config must be given to initialize environment")
		return
	}

	env := &coreEnvironment{}
	env.builderFunc = config.BuilderFunc
	env.commandFunc = config.CommandFunc
	env.commands = config.Commands
	env.ui = config.Ui

	resultEnv = env
	return
}

// Returns a builder of the given name that is registered with this
// environment.
func (e *coreEnvironment) Builder(name string) (b Builder, err error) {
	b, err = e.builderFunc(name)
	if err != nil {
		return
	}

	if b == nil {
		err = fmt.Errorf("No builder returned for name: %s", name)
	}

	return
}

// Executes a command as if it was typed on the command-line interface.
// The return value is the exit code of the command.
func (e *coreEnvironment) Cli(args []string) (result int, err error) {
	log.Printf("Environment.Cli: %#v\n", args)

	if len(args) == 0 || args[0] == "--help" || args[0] == "-h" {
		e.printHelp()
		return 1, nil
	}

	version := args[0] == "version"
	if !version {
		for _, arg := range args {
			if arg == "--version" || arg == "-v" {
				version = true
				break
			}
		}
	}

	var command Command
	if version {
		command = new(versionCommand)
	}

	if command == nil {
		command, err = e.commandFunc(args[0])
		if err != nil {
			return
		}

		// If we still don't have a command, show the help.
		if command == nil {
			log.Printf("Environment.CLI: command not found: %s\n", args[0])
			e.printHelp()
			return 1, nil
		}
	}

	log.Printf("Executing command: %s\n", args[0])
	return command.Run(e, args[1:]), nil
}

// Prints the CLI help to the UI.
func (e *coreEnvironment) printHelp() {
	// Created a sorted slice of the map keys and record the longest
	// command name so we can better format the output later.
	i := 0
	maxKeyLen := 0
	for _, command := range e.commands {
		if len(command) > maxKeyLen {
			maxKeyLen = len(command)
		}

		i++
	}

	// Sort the keys
	sort.Strings(e.commands)

	e.ui.Say("usage: packer [--version] [--help] <command> [<args>]\n\n")
	e.ui.Say("Available commands are:\n")
	for _, key := range e.commands {
		var synopsis string

		command, err := e.commandFunc(key)
		if err != nil {
			synopsis = fmt.Sprintf("Error loading command: %s", err.Error())
		} else if command == nil {
			continue
		} else {
			synopsis = command.Synopsis()
		}

		// Pad the key with spaces so that they're all the same width
		key = fmt.Sprintf("%v%v", key, strings.Repeat(" ", maxKeyLen-len(key)))

		// Output the command and the synopsis
		e.ui.Say("    %v     %v\n", key, synopsis)
	}
}

// Returns the UI for the environment. The UI is the interface that should
// be used for all communication with the outside world.
func (e *coreEnvironment) Ui() Ui {
	return e.ui
}
<|endoftext|>