<commit_before>// trybot_updater is an application that updates a repo's buildbucket.config file.
package main

import (
	"bytes"
	"context"
	"flag"
	"sort"
	"strings"
	"text/template"
	"time"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/gerrit"
	"go.skia.org/infra/go/gitiles"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/task_scheduler/go/specs"
)

const (
	// The format of this file is that of a gerrit extension config (not a proto).
	// The buildbucket extension parses the config like this:
	// https://chromium.googlesource.com/infra/gerrit-plugins/buildbucket/+/refs/heads/master/src/main/java/com/googlesource/chromium/plugins/buildbucket/GetConfig.java
	bbCfgFileName = "buildbucket.config"
	// Branch buildbucket.config lies in. Hopefully this will change one day, see b/38258213.
	bbCfgBranch = "refs/meta/config"
	// Template used to create buildbucket.config content.
	bbCfgTemplate = `
{{- range .EmptyBuckets}}[bucket "{{.}}"]{{end}}
[bucket "{{.BucketName}}"]
{{- range .Jobs}}
	builder = {{.}}
{{- end}}
`
)

var (
	// Flags.
	repoUrl       = flag.String("repo_url", common.REPO_SKIA, "Repo that needs buildbucket.config updated from it's tasks.json file.")
	bucketName    = flag.String("bucket_name", "luci.skia.skia.primary", "Name of the bucket to update in buildbucket.config.")
	emptyBuckets  = common.NewMultiStringFlag("empty_bucket", nil, "Empty buckets to specify in buildbucket.config. Eg: luci.chromium.try. See skbug.com/9639 for why these buckets are empty.")
	pollingPeriod = flag.Duration("polling_period", 10*time.Minute, "How often to poll tasks.json.")
	submit        = flag.Bool("submit", false, "If set, automatically submit the Gerrit change to update buildbucket.config")
	local         = flag.Bool("local", false, "Running locally if true. As opposed to in production.")
	promPort      = flag.String("prom_port", ":20000", "Metrics service address (e.g., ':20000')")

	bbCfgTemplateParsed = template.Must(template.New("buildbucket_config").Parse(bbCfgTemplate))
)

// getBuildbucketCfgFromJobs reads tasks.json from the specified repository and returns
// contents of what the new buildbucket.config file should be.
func getBuildbucketCfgFromJobs(ctx context.Context, repo *gitiles.Repo) (string, error) {
	// Read tasks.json from the specified repository.
	var tasksBuf bytes.Buffer
	if err := repo.ReadFileAtRef(ctx, specs.TASKS_CFG_FILE, "master", &tasksBuf); err != nil {
		return "", skerr.Fmt("Could not read %s: %s", specs.TASKS_CFG_FILE, err)
	}
	tasksCfg, err := specs.ParseTasksCfg(tasksBuf.String())
	if err != nil {
		return "", skerr.Fmt("Could not parse %s: %s", specs.TASKS_CFG_FILE, err)
	}

	// Create a sorted slice of jobs.
	jobs := make([]string, 0, len(tasksCfg.Jobs))
	for j := range tasksCfg.Jobs {
		jobs = append(jobs, j)
	}
	sort.Strings(jobs)

	// Use jobs to create content of buildbucket.config.
	bbCfg := new(bytes.Buffer)
	if err := bbCfgTemplateParsed.Execute(bbCfg, struct {
		EmptyBuckets []string
		BucketName   string
		Jobs         []string
	}{
		EmptyBuckets: *emptyBuckets,
		BucketName:   *bucketName,
		Jobs:         jobs,
	}); err != nil {
		return "", skerr.Fmt("Failed to execute bbCfg template: %s", err)
	}
	return bbCfg.String(), nil
}

// getCurrentBuildbucketCfg returns the current contents of buildbucket.config for the
// specified repository.
func getCurrentBuildbucketCfg(ctx context.Context, repo *gitiles.Repo) (string, error) {
	var buf bytes.Buffer
	if err := repo.ReadFileAtRef(ctx, bbCfgFileName, bbCfgBranch, &buf); err != nil {
		return "", skerr.Fmt("Could not read %s: %s", bbCfgFileName, err)
	}
	return buf.String(), nil
}

// updateBuildbucketCfg creates a Gerrit CL to update buildbucket.config. If submit flag is true then that CL
// is automatically self-approved and submitted.
func updateBuildbucketCfg(ctx context.Context, g *gerrit.Gerrit, repo *gitiles.Repo, cfgContents string) error {
	commitMsg := "Update buildbucket.config"
	repoSplit := strings.Split(*repoUrl, "/")
	project := strings.TrimSuffix(repoSplit[len(repoSplit)-1], ".git")
	baseCommitInfo, err := repo.Details(ctx, bbCfgBranch)
	if err != nil {
		return skerr.Fmt("Could not get details of %s: %s", bbCfgBranch, err)
	}
	baseCommit := baseCommitInfo.Hash
	ci, err := gerrit.CreateAndEditChange(ctx, g, project, bbCfgBranch, commitMsg, baseCommit, func(ctx context.Context, g gerrit.GerritInterface, ci *gerrit.ChangeInfo) error {
		if err := g.EditFile(ctx, ci, bbCfgFileName, cfgContents); err != nil {
			return skerr.Fmt("Could not edit %s: %s", bbCfgFileName, err)
		}
		return nil
	})
	if err != nil {
		return skerr.Fmt("Could not create Gerrit change: %s", err)
	}
	sklog.Infof("Uploaded change https://%s-review.googlesource.com/%d", project, ci.Issue)

	if *submit {
		// TODO(rmistry): Change reviewer to be the trooper after verifying that things work.
		reviewers := []string{"rmistry@google.com"}
		if err := g.SetReview(ctx, ci, "", gerrit.CONFIG_CHROMIUM.SelfApproveLabels, reviewers); err != nil {
			return abandonGerritChange(ctx, g, ci, err)
		}
		if err := g.Submit(ctx, ci); err != nil {
			return abandonGerritChange(ctx, g, ci, err)
		}
		sklog.Infof("Submitted change https://%s-review.googlesource.com/%d", project, ci.Issue)
	}

	return nil
}

// abandonGerritChange abandons the specified CL and returns the specified err after abandoning.
// If abandoning fails then that error is wrapped with the specified err.
func abandonGerritChange(ctx context.Context, g *gerrit.Gerrit, issue *gerrit.ChangeInfo, err error) error {
	if abandonErr := g.Abandon(ctx, issue, ""); abandonErr != nil {
		return skerr.Wrapf(err, "failed to abandon CL with %s", abandonErr)
	}
	return err
}

func main() {
	common.InitWithMust("trybot_updater", common.PrometheusOpt(promPort))
	defer sklog.Flush()
	ctx := context.Background()

	// OAuth2.0 TokenSource.
	ts, err := auth.NewDefaultTokenSource(false, auth.SCOPE_USERINFO_EMAIL, auth.SCOPE_GERRIT)
	if err != nil {
		sklog.Fatal(err)
	}
	// Authenticated HTTP client.
	httpClient := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()

	// Instantiate Gerrit.
	gUrl := strings.Split(*repoUrl, ".googlesource.com")[0] + "-review.googlesource.com"
	g, err := gerrit.NewGerrit(gUrl, httpClient)
	if err != nil {
		sklog.Fatal(err)
	}

	// Instantiate Gitiles using the specified repo URL.
	repo := gitiles.NewRepo(*repoUrl, httpClient)

	// TODO(rmistry): Use pubsub instead of polling.
	go util.RepeatCtx(ctx, *pollingPeriod, func(ctx context.Context) {
		existingCfg, err := getCurrentBuildbucketCfg(ctx, repo)
		if err != nil {
			sklog.Errorf("Could not get contents of buildbucket.config from %s: %s", repo, err)
		}

		newCfg, err := getBuildbucketCfgFromJobs(ctx, repo)
		if err != nil {
			sklog.Errorf("Could not get list of jobs from %s: %s", repo, err)
		}

		// Only update buildbucket.config if the config is different.
		if newCfg != existingCfg {
			if err := updateBuildbucketCfg(ctx, g, repo, newCfg); err != nil {
				sklog.Errorf("Could not update buildbucket.config: %s", err)
				sklog.Info("Sleep for 10 mins since there was a error with Gerrit to give it time to recover.")
				time.Sleep(10 * time.Minute)
			}
		} else {
			sklog.Info("Config has not changed")
		}
	})

	select {}
}
<commit_msg>[trybot-updater] Fix CL links<commit_after>// trybot_updater is an application that updates a repo's buildbucket.config file.
package main

import (
	"bytes"
	"context"
	"flag"
	"sort"
	"strings"
	"text/template"
	"time"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/gerrit"
	"go.skia.org/infra/go/gitiles"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/task_scheduler/go/specs"
)

const (
	// The format of this file is that of a gerrit extension config (not a proto).
	// The buildbucket extension parses the config like this:
	// https://chromium.googlesource.com/infra/gerrit-plugins/buildbucket/+/refs/heads/master/src/main/java/com/googlesource/chromium/plugins/buildbucket/GetConfig.java
	bbCfgFileName = "buildbucket.config"
	// Branch buildbucket.config lies in. Hopefully this will change one day, see b/38258213.
	bbCfgBranch = "refs/meta/config"
	// Template used to create buildbucket.config content.
	bbCfgTemplate = `
{{- range .EmptyBuckets}}[bucket "{{.}}"]{{end}}
[bucket "{{.BucketName}}"]
{{- range .Jobs}}
	builder = {{.}}
{{- end}}
`
)

var (
	// Flags.
	repoUrl       = flag.String("repo_url", common.REPO_SKIA, "Repo that needs buildbucket.config updated from it's tasks.json file.")
	bucketName    = flag.String("bucket_name", "luci.skia.skia.primary", "Name of the bucket to update in buildbucket.config.")
	emptyBuckets  = common.NewMultiStringFlag("empty_bucket", nil, "Empty buckets to specify in buildbucket.config. Eg: luci.chromium.try. See skbug.com/9639 for why these buckets are empty.")
	pollingPeriod = flag.Duration("polling_period", 10*time.Minute, "How often to poll tasks.json.")
	submit        = flag.Bool("submit", false, "If set, automatically submit the Gerrit change to update buildbucket.config")
	local         = flag.Bool("local", false, "Running locally if true. As opposed to in production.")
	promPort      = flag.String("prom_port", ":20000", "Metrics service address (e.g., ':20000')")

	bbCfgTemplateParsed = template.Must(template.New("buildbucket_config").Parse(bbCfgTemplate))
)

// getBuildbucketCfgFromJobs reads tasks.json from the specified repository and returns
// contents of what the new buildbucket.config file should be.
func getBuildbucketCfgFromJobs(ctx context.Context, repo *gitiles.Repo) (string, error) {
	// Read tasks.json from the specified repository.
	var tasksBuf bytes.Buffer
	if err := repo.ReadFileAtRef(ctx, specs.TASKS_CFG_FILE, "master", &tasksBuf); err != nil {
		return "", skerr.Fmt("Could not read %s: %s", specs.TASKS_CFG_FILE, err)
	}
	tasksCfg, err := specs.ParseTasksCfg(tasksBuf.String())
	if err != nil {
		return "", skerr.Fmt("Could not parse %s: %s", specs.TASKS_CFG_FILE, err)
	}

	// Create a sorted slice of jobs.
	jobs := make([]string, 0, len(tasksCfg.Jobs))
	for j := range tasksCfg.Jobs {
		jobs = append(jobs, j)
	}
	sort.Strings(jobs)

	// Use jobs to create content of buildbucket.config.
	bbCfg := new(bytes.Buffer)
	if err := bbCfgTemplateParsed.Execute(bbCfg, struct {
		EmptyBuckets []string
		BucketName   string
		Jobs         []string
	}{
		EmptyBuckets: *emptyBuckets,
		BucketName:   *bucketName,
		Jobs:         jobs,
	}); err != nil {
		return "", skerr.Fmt("Failed to execute bbCfg template: %s", err)
	}
	return bbCfg.String(), nil
}

// getCurrentBuildbucketCfg returns the current contents of buildbucket.config for the
// specified repository.
func getCurrentBuildbucketCfg(ctx context.Context, repo *gitiles.Repo) (string, error) {
	var buf bytes.Buffer
	if err := repo.ReadFileAtRef(ctx, bbCfgFileName, bbCfgBranch, &buf); err != nil {
		return "", skerr.Fmt("Could not read %s: %s", bbCfgFileName, err)
	}
	return buf.String(), nil
}

// updateBuildbucketCfg creates a Gerrit CL to update buildbucket.config. If submit flag is true then that CL
// is automatically self-approved and submitted.
func updateBuildbucketCfg(ctx context.Context, g *gerrit.Gerrit, repo *gitiles.Repo, cfgContents string) error {
	commitMsg := "Update buildbucket.config"
	repoSplit := strings.Split(*repoUrl, "/")
	project := strings.TrimSuffix(repoSplit[len(repoSplit)-1], ".git")
	baseCommitInfo, err := repo.Details(ctx, bbCfgBranch)
	if err != nil {
		return skerr.Fmt("Could not get details of %s: %s", bbCfgBranch, err)
	}
	baseCommit := baseCommitInfo.Hash
	ci, err := gerrit.CreateAndEditChange(ctx, g, project, bbCfgBranch, commitMsg, baseCommit, func(ctx context.Context, g gerrit.GerritInterface, ci *gerrit.ChangeInfo) error {
		if err := g.EditFile(ctx, ci, bbCfgFileName, cfgContents); err != nil {
			return skerr.Fmt("Could not edit %s: %s", bbCfgFileName, err)
		}
		return nil
	})
	if err != nil {
		return skerr.Fmt("Could not create Gerrit change: %s", err)
	}
	sklog.Infof("Uploaded change https://skia-review.googlesource.com/c/%s/+/%d", project, ci.Issue)

	if *submit {
		// TODO(rmistry): Change reviewer to be the trooper after verifying that things work.
		reviewers := []string{"rmistry@google.com"}
		if err := g.SetReview(ctx, ci, "", gerrit.CONFIG_CHROMIUM.SelfApproveLabels, reviewers); err != nil {
			return abandonGerritChange(ctx, g, ci, err)
		}
		if err := g.Submit(ctx, ci); err != nil {
			return abandonGerritChange(ctx, g, ci, err)
		}
		sklog.Infof("Submitted change https://skia-review.googlesource.com/c/%s/+/%d", project, ci.Issue)
	}

	return nil
}

// abandonGerritChange abandons the specified CL and returns the specified err after abandoning.
// If abandoning fails then that error is wrapped with the specified err.
func abandonGerritChange(ctx context.Context, g *gerrit.Gerrit, issue *gerrit.ChangeInfo, err error) error {
	if abandonErr := g.Abandon(ctx, issue, ""); abandonErr != nil {
		return skerr.Wrapf(err, "failed to abandon CL with %s", abandonErr)
	}
	return err
}

func main() {
	common.InitWithMust("trybot_updater", common.PrometheusOpt(promPort))
	defer sklog.Flush()
	ctx := context.Background()

	// OAuth2.0 TokenSource.
	ts, err := auth.NewDefaultTokenSource(false, auth.SCOPE_USERINFO_EMAIL, auth.SCOPE_GERRIT)
	if err != nil {
		sklog.Fatal(err)
	}
	// Authenticated HTTP client.
	httpClient := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()

	// Instantiate Gerrit.
	gUrl := strings.Split(*repoUrl, ".googlesource.com")[0] + "-review.googlesource.com"
	g, err := gerrit.NewGerrit(gUrl, httpClient)
	if err != nil {
		sklog.Fatal(err)
	}

	// Instantiate Gitiles using the specified repo URL.
	repo := gitiles.NewRepo(*repoUrl, httpClient)

	// TODO(rmistry): Use pubsub instead of polling.
	go util.RepeatCtx(ctx, *pollingPeriod, func(ctx context.Context) {
		existingCfg, err := getCurrentBuildbucketCfg(ctx, repo)
		if err != nil {
			sklog.Errorf("Could not get contents of buildbucket.config from %s: %s", repo, err)
		}

		newCfg, err := getBuildbucketCfgFromJobs(ctx, repo)
		if err != nil {
			sklog.Errorf("Could not get list of jobs from %s: %s", repo, err)
		}

		// Only update buildbucket.config if the config is different.
		if newCfg != existingCfg {
			if err := updateBuildbucketCfg(ctx, g, repo, newCfg); err != nil {
				sklog.Errorf("Could not update buildbucket.config: %s", err)
				sklog.Info("Sleep for 10 mins since there was a error with Gerrit to give it time to recover.")
				time.Sleep(10 * time.Minute)
			}
		} else {
			sklog.Info("Config has not changed")
		}
	})

	select {}
}
<|endoftext|>


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

package txtdirect

import (
	"log"
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"

	"github.com/caddyserver/caddy"
	"github.com/caddyserver/caddy/caddyhttp/httpserver"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Prometheus contains Prometheus's configuration
type Prometheus struct {
	Enable  bool
	Address string
	Path    string

	next    httpserver.Handler
	handler http.Handler
}

var (
	// RequestsCount counts the total requests per host
	RequestsCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_count_total",
		Help:      "Total requests per host",
	}, []string{"host"})

	// RequestsByStatus counts the total returned statuses per host
	RequestsByStatus = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_status_count_total",
		Help:      "Total returned statuses per host",
	}, []string{"host", "status"})

	// RequestsCountBasedOnType counts the total requests for each host based on type
	RequestsCountBasedOnType = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_type_count_total",
		Help:      "Total requests for each host based on type",
	}, []string{"host", "type"})

	// FallbacksCount counts the total fallbacks triggered for each type
	FallbacksCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "fallback_type_count_total",
		Help:      "Total fallbacks triggered for each type",
	}, []string{"host", "type", "fallback"})

	// PathRedirectCount counts the total redirects per path for each host
	PathRedirectCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_path_count_total",
		Help:      "Total redirects per path for each host",
	}, []string{"host", "path"})

	once sync.Once
)

const (
	shutdownTimeout time.Duration = time.Second * 5
	// prometheusAddr is the address the where the metrics are exported by default.
	prometheusAddr string = "localhost:9183"
	prometheusPath string = "/metrics"
)

// SetDefaults sets the default values for prometheus config
// if the fields are empty
func (p *Prometheus) SetDefaults() {
	if p.Address == "" {
		p.Address = prometheusAddr
	}
	if p.Path == "" {
		p.Path = prometheusPath
	}
}

func (p *Prometheus) start() error {
	once.Do(func() {
		prometheus.MustRegister(RequestsCount)
		prometheus.MustRegister(RequestsByStatus)
		prometheus.MustRegister(RequestsCountBasedOnType)
		prometheus.MustRegister(FallbacksCount)
		prometheus.MustRegister(PathRedirectCount)
		http.Handle(p.Path, p.handler)
		go func() {
			err := http.ListenAndServe(p.Address, nil)
			if err != nil {
				log.Printf("[txtdirect]: Couldn't start http handler for prometheus metrics. %s", err.Error())
			}
		}()
	})
	return nil
}

// Setup registers the metrics on startup and creates the promethues request handler
func (p *Prometheus) Setup(c *caddy.Controller) {
	p.handler = promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
		ErrorHandling: promhttp.HTTPErrorOnError,
		ErrorLog:      log.New(os.Stderr, "", log.LstdFlags),
	})

	once.Do(func() {
		c.OnStartup(p.start)
	})

	cfg := httpserver.GetConfig(c)
	cfg.AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
		p.next = next
		return p
	})
}

func (p *Prometheus) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	next := p.next

	rw := httpserver.NewResponseRecorder(w)

	status, err := next.ServeHTTP(rw, r)

	return status, err
}

// ParsePrometheus parses the txtdirect config for Prometheus
func (p *Prometheus) ParsePrometheus(c *caddy.Controller, key, value string) error {
	switch key {
	case "enable":
		value, err := strconv.ParseBool(value)
		if err != nil {
			return c.ArgErr()
		}
		p.Enable = value
	case "address":
		// TODO: validate the given address
		p.Address = value
	case "path":
		p.Path = value
	default:
		return c.ArgErr() // unhandled option for prometheus
	}
	return nil
}
<commit_msg>[prometheus]: Fix register bug<commit_after>/*
Copyright 2019 - The TXTDirect Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package txtdirect

import (
	"log"
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"

	"github.com/caddyserver/caddy"
	"github.com/caddyserver/caddy/caddyhttp/httpserver"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Prometheus contains Prometheus's configuration
type Prometheus struct {
	Enable  bool
	Address string
	Path    string

	next    httpserver.Handler
	handler http.Handler
}

var (
	// RequestsCount counts the total requests per host
	RequestsCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_count_total",
		Help:      "Total requests per host",
	}, []string{"host"})

	// RequestsByStatus counts the total returned statuses per host
	RequestsByStatus = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_status_count_total",
		Help:      "Total returned statuses per host",
	}, []string{"host", "status"})

	// RequestsCountBasedOnType counts the total requests for each host based on type
	RequestsCountBasedOnType = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_type_count_total",
		Help:      "Total requests for each host based on type",
	}, []string{"host", "type"})

	// FallbacksCount counts the total fallbacks triggered for each type
	FallbacksCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "fallback_type_count_total",
		Help:      "Total fallbacks triggered for each type",
	}, []string{"host", "type", "fallback"})

	// PathRedirectCount counts the total redirects per path for each host
	PathRedirectCount = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: "txtdirect",
		Name:      "redirect_path_count_total",
		Help:      "Total redirects per path for each host",
	}, []string{"host", "path"})

	once sync.Once
)

const (
	shutdownTimeout time.Duration = time.Second * 5
	// prometheusAddr is the address the where the metrics are exported by default.
	prometheusAddr string = "localhost:9183"
	prometheusPath string = "/metrics"
)

// SetDefaults sets the default values for prometheus config
// if the fields are empty
func (p *Prometheus) SetDefaults() {
	if p.Address == "" {
		p.Address = prometheusAddr
	}
	if p.Path == "" {
		p.Path = prometheusPath
	}
}

func (p *Prometheus) start() error {
	prometheus.MustRegister(RequestsCount)
	prometheus.MustRegister(RequestsByStatus)
	prometheus.MustRegister(RequestsCountBasedOnType)
	prometheus.MustRegister(FallbacksCount)
	prometheus.MustRegister(PathRedirectCount)
	http.Handle(p.Path, p.handler)
	go func() {
		err := http.ListenAndServe(p.Address, nil)
		if err != nil {
			log.Printf("[txtdirect]: Couldn't start http handler for prometheus metrics. %s", err.Error())
		}
	}()
	return nil
}

// Setup registers the metrics on startup and creates the promethues request handler
func (p *Prometheus) Setup(c *caddy.Controller) {
	p.handler = promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
		ErrorHandling: promhttp.HTTPErrorOnError,
		ErrorLog:      log.New(os.Stderr, "", log.LstdFlags),
	})

	once.Do(func() {
		c.OnStartup(p.start)
	})

	cfg := httpserver.GetConfig(c)
	cfg.AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
		p.next = next
		return p
	})
}

func (p *Prometheus) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	next := p.next

	rw := httpserver.NewResponseRecorder(w)

	status, err := next.ServeHTTP(rw, r)

	return status, err
}

// ParsePrometheus parses the txtdirect config for Prometheus
func (p *Prometheus) ParsePrometheus(c *caddy.Controller, key, value string) error {
	switch key {
	case "enable":
		value, err := strconv.ParseBool(value)
		if err != nil {
			return c.ArgErr()
		}
		p.Enable = value
	case "address":
		// TODO: validate the given address
		p.Address = value
	case "path":
		p.Path = value
	default:
		return c.ArgErr() // unhandled option for prometheus
	}
	return nil
}
<|endoftext|>


<commit_before>package fads

import (
	"math"
	"reflect"

	"github.com/go-hep/fmom"
	"github.com/go-hep/fwk"
)

type ParticlePropagator struct {
	fwk.TaskBase

	radius  float64
	radius2 float64
	halflen float64
	bz      float64

	input  string
	output string

	hadrons string
	eles    string
	muons   string
}

func (tsk *ParticlePropagator) Configure(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	tsk.radius2 = tsk.radius * tsk.radius
	if tsk.radius < 1.0e-2 {
		return fwk.Errorf("%s: too small radius value (%v)", tsk.Name(), tsk.radius)
	}

	if tsk.halflen < 1.0e-2 {
		return fwk.Errorf("%s: too small 1/2-length value (%v)", tsk.Name(), tsk.halflen)
	}

	err = tsk.DeclInPort(tsk.input, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.output, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.hadrons, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.eles, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.muons, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	return err
}

func (tsk *ParticlePropagator) StartTask(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	return err
}

func (tsk *ParticlePropagator) StopTask(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	return err
}

func (tsk *ParticlePropagator) Process(ctx fwk.Context) fwk.Error {
	var err fwk.Error
	store := ctx.Store()
	msg := ctx.Msg()

	v, err := store.Get(tsk.input)
	if err != nil {
		return err
	}

	input := v.([]Candidate)
	msg.Debugf(">>> candidates: %v\n", len(input))

	output := make([]Candidate, 0)
	defer func() {
		err = store.Put(tsk.output, output)
	}()

	hadrons := make([]Candidate, 0)
	eles := make([]Candidate, 0)
	muons := make([]Candidate, 0)
	defer func() {
		err = store.Put(tsk.hadrons, hadrons)
		if err != nil {
			return
		}
		err = store.Put(tsk.eles, eles)
		if err != nil {
			return
		}
		err = store.Put(tsk.muons, muons)
		if err != nil {
			return
		}
	}()

	const (
		cLight  = 2.99792458E8
		cLight2 = cLight * cLight
	)

	for i := range input {
		cand := &input[i]
		x := cand.Pos.X() * 1e-3
		y := cand.Pos.Y() * 1e-3
		z := cand.Pos.Z() * 1e-3

		// is particle inside cylinder ?
		if math.Hypot(x, y) > tsk.radius || math.Abs(z) > tsk.halflen {
			continue
		}

		px := cand.Mom.Px()
		py := cand.Mom.Py()
		pt2 := px*px + py*py
		if pt2 < 1e-9 {
			continue
		}

		q := float64(cand.Charge())
		if math.Abs(q) < 1e-9 || math.Abs(tsk.bz) < 1e-9 {
			// solve pt2*t^2 + 2(px.x + py.y)*t + (radius2 - x.x - y.y) = 0
			v := px*y - py*x
			discr2 := pt2*tsk.radius2 - v*v
			if discr2 < 0 {
				// no solution
				continue
			}

			v = px*x + py*y
			discr := math.Sqrt(discr2)
			t1 := (-v + discr) / pt2
			t2 := (-v - discr) / pt2
			t := 0.0
			switch t1 < 0 {
			case true:
				t = t2
			case false:
				t = t1
			}

			pz := cand.Mom.Pz()
			e := cand.Mom.E()

			zt := z + pz*t
			if math.Abs(zt) > tsk.halflen {
				invpz := 1.0 / pz
				t3 := (+tsk.halflen - z) * invpz
				t4 := (-tsk.halflen - z) * invpz
				if t3 < 0 {
					t = t4
				} else {
					t = t3
				}
			}

			xt := x + px*t
			yt := y + py*t
			zt = z + pz*t

			mother := cand
			c := cand.Clone()
			c.Pos = fmom.NewPxPyPzE(xt*1e3, yt*1e3, zt*1e3, cand.Pos.T()+t*e*1e3)
			c.Add(mother)

			output = append(output, *c)
			if math.Abs(q) > 1e-9 {
				pid := c.Pid
				if pid < 0 {
					pid = 0
				}
				switch pid {
				case 11:
					eles = append(eles, *c)
				case 13:
					muons = append(muons, *c)
				default:
					hadrons = append(hadrons, *c)
				}
			}
		} else {
			// 1.  initial transverse momentum p_{T0} : Part->pt
			//     initial transverse momentum direction \phi_0 = -atan(p_X0/p_Y0)
			//     relativistic gamma : gamma = E/mc² ; gammam = gamma \times m
			//     giration frequency \omega = q/(gamma m) fBz
			//     helix radius r = p_T0 / (omega gamma m)

			e := cand.Mom.E()
			pt := cand.Mom.Pt()
			pz := cand.Mom.Pz()

			gammam := e * 1e9 / cLight2  // in eV/c^2
			omega := q * tsk.bz / gammam // omega is in [89875518 / s]
			r := pt / (q * tsk.bz) * 1e9 / cLight

			phi0 := math.Atan2(py, px) // [rad] in [-pi,pi)

			// 2. helix axis coordinates
			xc := x + r*math.Sin(phi0)
			yc := y - r*math.Cos(phi0)
			rc := math.Hypot(xc, yc)
			phic := math.Atan2(yc, xc)
			phi := phic
			if xc < 0 {
				phi += math.Pi
			}

			// 3. time evaluation t = TMath::Min(t_r, t_z)
			//    t_r : time to exit from the sides
			//    t_z : time to exit from the front or the back
			tr := 0.0 // in [ns]
			signpz := -1.0
			if pz > 0 {
				signpz = +1.0
			}

			tz := 0.0
			if pz == 0 {
				tz = 1e99
			} else {
				tz = gammam / (pz * 1e9 / cLight) * (-z + tsk.halflen*signpz)
			}

			absr := math.Abs(r)
			t := 0.0
			if rc+absr < tsk.radius {
				// helix does not cross the cylinder sides
				t = tz
			} else {
				asinrho := math.Asin((tsk.radius*tsk.radius - rc*rc - r*r) * 0.5 / (absr * rc))
				delta := phi0 - phi
				if delta < -math.Pi {
					delta += 2.0 * math.Pi
				}
				if delta > math.Pi {
					delta -= 2.0 * math.Pi
				}

				t1 := (delta + asinrho) / omega
				t2 := (delta + math.Pi - asinrho) / omega
				t3 := (delta + math.Pi + asinrho) / omega
				t4 := (delta - asinrho) / omega
				t5 := (delta - math.Pi - asinrho) / omega
				t6 := (delta - math.Pi + asinrho) / omega

				if t1 < 0 {
					t1 = 1.0E99
				}
				if t2 < 0 {
					t2 = 1.0E99
				}
				if t3 < 0 {
					t3 = 1.0E99
				}
				if t4 < 0 {
					t4 = 1.0E99
				}
				if t5 < 0 {
					t5 = 1.0E99
				}
				if t6 < 0 {
					t6 = 1.0E99
				}

				tra := math.Min(t1, math.Min(t2, t3))
				trb := math.Min(t4, math.Min(t5, t6))
				tr = math.Min(tra, trb)
				t = math.Min(tr, tz)
			}

			// 4. position in terms of x(t), y(t), z(t)
			xt := xc + r*math.Sin(omega*t-phi0)
			yt := yc + r*math.Cos(omega*t-phi0)
			zt := z + pz*1.0E9/cLight/gammam*t
			rt := math.Hypot(xt, yt)

			if rt > 0.0 {
				mother := cand
				c := cand.Clone()
				c.Pos = fmom.NewPxPyPzE(xt*1e3, yt*1e3, zt*1e3, cand.Pos.T()+t*cLight*1e3)
				c.Add(mother)

				output = append(output, *c)
				if math.Abs(q) > 1e-9 {
					pid := c.Pid
					if pid < 0 {
						pid = 0
					}
					switch pid {
					case 11:
						eles = append(eles, *c)
					case 13:
						muons = append(muons, *c)
					default:
						hadrons = append(hadrons, *c)
					}
				}

			}

		}
	}

	msg.Debugf(">>> output:     %v\n", len(output))
	return err
}

func init() {
	fwk.Register(reflect.TypeOf(ParticlePropagator{}),
		func(typ, name string, mgr fwk.App) (fwk.Component, fwk.Error) {
			var err fwk.Error
			tsk := &ParticlePropagator{
				TaskBase: fwk.NewTask(typ, name, mgr),
			}
			tsk.radius = 1.0
			err = tsk.DeclProp("Radius", &tsk.radius)
			if err != nil {
				return nil, err
			}
			tsk.radius2 = tsk.radius * tsk.radius

			tsk.halflen = 3.0
			err = tsk.DeclProp("HalfLength", &tsk.halflen)
			if err != nil {
				return nil, err
			}

			tsk.bz = 0.0
			err = tsk.DeclProp("Bz", &tsk.bz)
			if err != nil {
				return nil, err
			}

			tsk.input = "/fads/StableParticles"
			err = tsk.DeclProp("Input", &tsk.input)
			if err != nil {
				return nil, err
			}

			tsk.output = "StableParticles"
			err = tsk.DeclProp("Output", &tsk.output)
			if err != nil {
				return nil, err
			}

			tsk.hadrons = "ChargedHadrons"
			err = tsk.DeclProp("ChargedHadrons", &tsk.hadrons)
			if err != nil {
				return nil, err
			}

			tsk.eles = "Electrons"
			err = tsk.DeclProp("Electrons", &tsk.eles)
			if err != nil {
				return nil, err
			}

			tsk.muons = "Muons"
			err = tsk.DeclProp("Muons", &tsk.muons)
			if err != nil {
				return nil, err
			}

			return tsk, err
		},
	)
}

// EOF
<commit_msg>propagator: sort particles by descending-pt<commit_after>package fads

import (
	"math"
	"reflect"
	"sort"

	"github.com/go-hep/fmom"
	"github.com/go-hep/fwk"
)

type ParticlePropagator struct {
	fwk.TaskBase

	radius  float64
	radius2 float64
	halflen float64
	bz      float64

	input  string
	output string

	hadrons string
	eles    string
	muons   string
}

func (tsk *ParticlePropagator) Configure(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	tsk.radius2 = tsk.radius * tsk.radius
	if tsk.radius < 1.0e-2 {
		return fwk.Errorf("%s: too small radius value (%v)", tsk.Name(), tsk.radius)
	}

	if tsk.halflen < 1.0e-2 {
		return fwk.Errorf("%s: too small 1/2-length value (%v)", tsk.Name(), tsk.halflen)
	}

	err = tsk.DeclInPort(tsk.input, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.output, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.hadrons, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.eles, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	err = tsk.DeclOutPort(tsk.muons, reflect.TypeOf([]Candidate{}))
	if err != nil {
		return err
	}

	return err
}

func (tsk *ParticlePropagator) StartTask(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	return err
}

func (tsk *ParticlePropagator) StopTask(ctx fwk.Context) fwk.Error {
	var err fwk.Error

	return err
}

func (tsk *ParticlePropagator) Process(ctx fwk.Context) fwk.Error {
	var err fwk.Error
	store := ctx.Store()
	msg := ctx.Msg()

	v, err := store.Get(tsk.input)
	if err != nil {
		return err
	}

	input := v.([]Candidate)
	msg.Debugf(">>> candidates: %v\n", len(input))

	output := make([]Candidate, 0)
	defer func() {
		err = store.Put(tsk.output, output)
	}()

	hadrons := make([]Candidate, 0)
	eles := make([]Candidate, 0)
	muons := make([]Candidate, 0)
	defer func() {
		err = store.Put(tsk.hadrons, hadrons)
		if err != nil {
			return
		}
		err = store.Put(tsk.eles, eles)
		if err != nil {
			return
		}
		err = store.Put(tsk.muons, muons)
		if err != nil {
			return
		}
	}()

	const (
		cLight  = 2.99792458E8
		cLight2 = cLight * cLight
	)

	for i := range input {
		cand := &input[i]
		x := cand.Pos.X() * 1e-3
		y := cand.Pos.Y() * 1e-3
		z := cand.Pos.Z() * 1e-3

		// is particle inside cylinder ?
		if math.Hypot(x, y) > tsk.radius || math.Abs(z) > tsk.halflen {
			continue
		}

		px := cand.Mom.Px()
		py := cand.Mom.Py()
		pt2 := px*px + py*py
		if pt2 < 1e-9 {
			continue
		}

		q := float64(cand.Charge())
		if math.Abs(q) < 1e-9 || math.Abs(tsk.bz) < 1e-9 {
			// solve pt2*t^2 + 2(px.x + py.y)*t + (radius2 - x.x - y.y) = 0
			v := px*y - py*x
			discr2 := pt2*tsk.radius2 - v*v
			if discr2 < 0 {
				// no solution
				continue
			}

			v = px*x + py*y
			discr := math.Sqrt(discr2)
			t1 := (-v + discr) / pt2
			t2 := (-v - discr) / pt2
			t := 0.0
			switch t1 < 0 {
			case true:
				t = t2
			case false:
				t = t1
			}

			pz := cand.Mom.Pz()
			e := cand.Mom.E()

			zt := z + pz*t
			if math.Abs(zt) > tsk.halflen {
				invpz := 1.0 / pz
				t3 := (+tsk.halflen - z) * invpz
				t4 := (-tsk.halflen - z) * invpz
				if t3 < 0 {
					t = t4
				} else {
					t = t3
				}
			}

			xt := x + px*t
			yt := y + py*t
			zt = z + pz*t

			mother := cand
			c := cand.Clone()
			c.Pos = fmom.NewPxPyPzE(xt*1e3, yt*1e3, zt*1e3, cand.Pos.T()+t*e*1e3)
			c.Add(mother)

			output = append(output, *c)
			if math.Abs(q) > 1e-9 {
				pid := c.Pid
				if pid < 0 {
					pid = 0
				}
				switch pid {
				case 11:
					eles = append(eles, *c)
				case 13:
					muons = append(muons, *c)
				default:
					hadrons = append(hadrons, *c)
				}
			}
		} else {
			// 1.  initial transverse momentum p_{T0} : Part->pt
			//     initial transverse momentum direction \phi_0 = -atan(p_X0/p_Y0)
			//     relativistic gamma : gamma = E/mc² ; gammam = gamma \times m
			//     giration frequency \omega = q/(gamma m) fBz
			//     helix radius r = p_T0 / (omega gamma m)

			e := cand.Mom.E()
			pt := cand.Mom.Pt()
			pz := cand.Mom.Pz()

			gammam := e * 1e9 / cLight2  // in eV/c^2
			omega := q * tsk.bz / gammam // omega is in [89875518 / s]
			r := pt / (q * tsk.bz) * 1e9 / cLight

			phi0 := math.Atan2(py, px) // [rad] in [-pi,pi)

			// 2. helix axis coordinates
			xc := x + r*math.Sin(phi0)
			yc := y - r*math.Cos(phi0)
			rc := math.Hypot(xc, yc)
			phic := math.Atan2(yc, xc)
			phi := phic
			if xc < 0 {
				phi += math.Pi
			}

			// 3. time evaluation t = TMath::Min(t_r, t_z)
			//    t_r : time to exit from the sides
			//    t_z : time to exit from the front or the back
			tr := 0.0 // in [ns]
			signpz := -1.0
			if pz > 0 {
				signpz = +1.0
			}

			tz := 0.0
			if pz == 0 {
				tz = 1e99
			} else {
				tz = gammam / (pz * 1e9 / cLight) * (-z + tsk.halflen*signpz)
			}

			absr := math.Abs(r)
			t := 0.0
			if rc+absr < tsk.radius {
				// helix does not cross the cylinder sides
				t = tz
			} else {
				asinrho := math.Asin((tsk.radius*tsk.radius - rc*rc - r*r) * 0.5 / (absr * rc))
				delta := phi0 - phi
				if delta < -math.Pi {
					delta += 2.0 * math.Pi
				}
				if delta > math.Pi {
					delta -= 2.0 * math.Pi
				}

				t1 := (delta + asinrho) / omega
				t2 := (delta + math.Pi - asinrho) / omega
				t3 := (delta + math.Pi + asinrho) / omega
				t4 := (delta - asinrho) / omega
				t5 := (delta - math.Pi - asinrho) / omega
				t6 := (delta - math.Pi + asinrho) / omega

				if t1 < 0 {
					t1 = 1.0E99
				}
				if t2 < 0 {
					t2 = 1.0E99
				}
				if t3 < 0 {
					t3 = 1.0E99
				}
				if t4 < 0 {
					t4 = 1.0E99
				}
				if t5 < 0 {
					t5 = 1.0E99
				}
				if t6 < 0 {
					t6 = 1.0E99
				}

				tra := math.Min(t1, math.Min(t2, t3))
				trb := math.Min(t4, math.Min(t5, t6))
				tr = math.Min(tra, trb)
				t = math.Min(tr, tz)
			}

			// 4. position in terms of x(t), y(t), z(t)
			xt := xc + r*math.Sin(omega*t-phi0)
			yt := yc + r*math.Cos(omega*t-phi0)
			zt := z + pz*1.0E9/cLight/gammam*t
			rt := math.Hypot(xt, yt)

			if rt > 0.0 {
				mother := cand
				c := cand.Clone()
				c.Pos = fmom.NewPxPyPzE(xt*1e3, yt*1e3, zt*1e3, cand.Pos.T()+t*cLight*1e3)
				c.Add(mother)

				output = append(output, *c)
				if math.Abs(q) > 1e-9 {
					pid := c.Pid
					if pid < 0 {
						pid = 0
					}
					switch pid {
					case 11:
						eles = append(eles, *c)
					case 13:
						muons = append(muons, *c)
					default:
						hadrons = append(hadrons, *c)
					}
				}

			}

		}
	}

	sort.Sort(sort.Reverse(ByPt(output)))
	msg.Debugf(">>> output:     %v\n", len(output))
	return err
}

func init() {
	fwk.Register(reflect.TypeOf(ParticlePropagator{}),
		func(typ, name string, mgr fwk.App) (fwk.Component, fwk.Error) {
			var err fwk.Error
			tsk := &ParticlePropagator{
				TaskBase: fwk.NewTask(typ, name, mgr),
			}
			tsk.radius = 1.0
			err = tsk.DeclProp("Radius", &tsk.radius)
			if err != nil {
				return nil, err
			}
			tsk.radius2 = tsk.radius * tsk.radius

			tsk.halflen = 3.0
			err = tsk.DeclProp("HalfLength", &tsk.halflen)
			if err != nil {
				return nil, err
			}

			tsk.bz = 0.0
			err = tsk.DeclProp("Bz", &tsk.bz)
			if err != nil {
				return nil, err
			}

			tsk.input = "/fads/StableParticles"
			err = tsk.DeclProp("Input", &tsk.input)
			if err != nil {
				return nil, err
			}

			tsk.output = "StableParticles"
			err = tsk.DeclProp("Output", &tsk.output)
			if err != nil {
				return nil, err
			}

			tsk.hadrons = "ChargedHadrons"
			err = tsk.DeclProp("ChargedHadrons", &tsk.hadrons)
			if err != nil {
				return nil, err
			}

			tsk.eles = "Electrons"
			err = tsk.DeclProp("Electrons", &tsk.eles)
			if err != nil {
				return nil, err
			}

			tsk.muons = "Muons"
			err = tsk.DeclProp("Muons", &tsk.muons)
			if err != nil {
				return nil, err
			}

			return tsk, err
		},
	)
}

// EOF
<|endoftext|>


<commit_before>/*
http://www.apache.org/licenses/LICENSE-2.0.txt

Copyright 2015 Intel Corporation

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 psutil

import (
	"fmt"
	"net"
	"strconv"
	"time"

	"github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin"
	psutilnet "github.com/shirou/gopsutil/net"
)

var netIOCounterLabels = map[string]label{
	"bytes_sent": label{
		unit:        "",
		description: "",
	},
	"bytes_recv": label{
		unit:        "",
		description: "",
	},
	"packets_sent": label{
		unit:        "",
		description: "",
	},
	"packets_recv": label{
		unit:        "",
		description: "",
	},
	"errin": label{
		unit:        "",
		description: "",
	},
	"errout": label{
		unit:        "",
		description: "",
	},
	"dropin": label{
		unit:        "",
		description: "",
	},
	"dropout": label{
		unit:        "",
		description: "",
	},
}

func netIOCounters(nss []plugin.Namespace) ([]plugin.Metric, error) {
	defer timeSpent(time.Now(), "netIOCounters")
	// gather accumulated metrics for all interfaces
	netsAll, err := psutilnet.IOCounters(false)
	if err != nil {
		return nil, err
	}

	// gather metrics per nic
	netsNic, err := psutilnet.IOCounters(true)
	if err != nil {
		return nil, err
	}

	results := []plugin.Metric{}

	for _, ns := range nss {
		// set requested metric name from last namespace element
		metricName := ns.Element(len(ns) - 1).Value
		// check if requested metric is dynamic (requesting metrics for all nics)
		if ns[3].Value == "*" {
			for _, nic := range netsNic {
				// prepare namespace copy to update value
				// this will allow to keep namespace as dynamic (name != "")
				dyn := make([]plugin.NamespaceElement, len(ns))
				copy(dyn, ns)
				dyn[3].Value = nic.Name
				// get requested metric value
				val, err := getNetIOCounterValue(&nic, metricName)
				if err != nil {
					return nil, err
				}
				tags, err := getInterfaceConfiguration(nic.Name)
				if err != nil {
					return nil, err
				}

				metric := plugin.Metric{
					Namespace: dyn,
					Data:      val,
					Timestamp: time.Now(),
					Tags:      tags,
					Unit:      netIOCounterLabels[metricName].unit,
				}
				results = append(results, metric)
			}
		} else {
			stats := append(netsAll, netsNic...)
			// find stats for interface name or all nics
			stat := findNetIOStats(stats, ns[3].Value)
			if stat == nil {
				return nil, fmt.Errorf("Requested interface %s not found", ns[3].Value)
			}
			// get value for requested metric
			val, err := getNetIOCounterValue(stat, metricName)
			if err != nil {
				return nil, err
			}

			tags, err := getInterfaceConfiguration(ns[3].Value)
			if err != nil {
				return nil, err
			}

			metric := plugin.Metric{
				Namespace: ns,
				Data:      val,
				Tags:      tags,
				Timestamp: time.Now(),
				Unit:      netIOCounterLabels[metricName].unit,
			}
			results = append(results, metric)
		}
	}

	return results, nil
}

func findNetIOStats(nets []psutilnet.IOCountersStat, name string) *psutilnet.IOCountersStat {
	for _, net := range nets {
		if net.Name == name {
			return &net
		}
	}
	return nil
}

func getNetIOCounterValue(stat *psutilnet.IOCountersStat, name string) (uint64, error) {
	switch name {
	case "bytes_sent":
		return stat.BytesSent, nil
	case "bytes_recv":
		return stat.BytesRecv, nil
	case "packets_sent":
		return stat.PacketsSent, nil
	case "packets_recv":
		return stat.PacketsRecv, nil
	case "errin":
		return stat.Errin, nil
	case "errout":
		return stat.Errout, nil
	case "dropin":
		return stat.Dropin, nil
	case "dropout":
		return stat.Dropout, nil
	default:
		return 0, fmt.Errorf("Requested NetIOCounter statistic %s is not available", name)
	}
}

func getNetIOCounterMetricTypes() ([]plugin.Metric, error) {
	defer timeSpent(time.Now(), "getNetIOCounterMetricTypes")
	mts := make([]plugin.Metric, 0)

	for name, label := range netIOCounterLabels {
		//metrics which are the sum for all available nics
		mts = append(mts, plugin.Metric{
			Namespace:   plugin.NewNamespace("intel", "psutil", "net", "all", name),
			Description: label.description,
			Unit:        label.unit,
		})
		//dynamic metrics representing any nic
		mts = append(mts, plugin.Metric{
			Namespace: plugin.NewNamespace("intel", "psutil", "net").
				AddDynamicElement("interface_name", "network interface name").AddStaticElement(name),
			Description: label.description,
			Unit:        label.unit,
		})
	}

	return mts, nil
}

func getInterfaceConfiguration(ifaceName string) (map[string]string, error) {

	interfaceConfig, err := net.InterfaceByName(ifaceName)
	if err != nil {
		return nil, err
	}
	tags := make(map[string]string)
	tags["hardware_addr"] = string(interfaceConfig.HardwareAddr)
	tags["mtu"] = strconv.Itoa(interfaceConfig.MTU)
	return tags, nil
}
<commit_msg>Bug fix: metrics net ALL interface has no configuration<commit_after>/*
http://www.apache.org/licenses/LICENSE-2.0.txt

Copyright 2015 Intel Corporation

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 psutil

import (
	"fmt"
	"net"
	"strconv"
	"time"

	"github.com/intelsdi-x/snap-plugin-lib-go/v1/plugin"
	psutilnet "github.com/shirou/gopsutil/net"
)

var netIOCounterLabels = map[string]label{
	"bytes_sent": label{
		unit:        "",
		description: "",
	},
	"bytes_recv": label{
		unit:        "",
		description: "",
	},
	"packets_sent": label{
		unit:        "",
		description: "",
	},
	"packets_recv": label{
		unit:        "",
		description: "",
	},
	"errin": label{
		unit:        "",
		description: "",
	},
	"errout": label{
		unit:        "",
		description: "",
	},
	"dropin": label{
		unit:        "",
		description: "",
	},
	"dropout": label{
		unit:        "",
		description: "",
	},
}

func netIOCounters(nss []plugin.Namespace) ([]plugin.Metric, error) {
	defer timeSpent(time.Now(), "netIOCounters")
	// gather accumulated metrics for all interfaces
	netsAll, err := psutilnet.IOCounters(false)
	if err != nil {
		return nil, err
	}

	// gather metrics per nic
	netsNic, err := psutilnet.IOCounters(true)
	if err != nil {
		return nil, err
	}

	results := []plugin.Metric{}

	for _, ns := range nss {
		// set requested metric name from last namespace element
		metricName := ns.Element(len(ns) - 1).Value
		// check if requested metric is dynamic (requesting metrics for all nics)
		if ns[3].Value == "*" {
			for _, nic := range netsNic {

				// prepare namespace copy to update value
				// this will allow to keep namespace as dynamic (name != "")
				dyn := make([]plugin.NamespaceElement, len(ns))
				copy(dyn, ns)
				dyn[3].Value = nic.Name
				// get requested metric value
				val, err := getNetIOCounterValue(&nic, metricName)
				if err != nil {
					return nil, err
				}
				tags, err := getInterfaceConfiguration(nic.Name)
				if err != nil {
					return nil, err
				}

				metric := plugin.Metric{
					Namespace: dyn,
					Data:      val,
					Timestamp: time.Now(),
					Tags:      tags,
					Unit:      netIOCounterLabels[metricName].unit,
				}
				results = append(results, metric)
			}
		} else {
			stats := append(netsAll, netsNic...)

			fmt.Printf("stats: %#v \n \n \n", stats)
			// find stats for interface name or all nics
			stat := findNetIOStats(stats, ns[3].Value)
			fmt.Printf("stat: %#v \n \n \n ", stat)
			if stat == nil {
				return nil, fmt.Errorf("Requested interface %s not found", ns[3].Value)
			}
			// get value for requested metric
			val, err := getNetIOCounterValue(stat, metricName)
			if err != nil {
				return nil, err
			}

			var tags map[string]string

			//for "all" interface there is no configuration
			if ns[3].Value != "all" {
				tags, err = getInterfaceConfiguration(ns[3].Value)
				if err != nil {
					return nil, err
				}
			}

			metric := plugin.Metric{
				Namespace: ns,
				Data:      val,
				Tags:      tags,
				Timestamp: time.Now(),
				Unit:      netIOCounterLabels[metricName].unit,
			}
			results = append(results, metric)

			fmt.Printf("results: %#v \n ", results)
		}
	}

	return results, nil
}

func findNetIOStats(nets []psutilnet.IOCountersStat, name string) *psutilnet.IOCountersStat {
	for _, net := range nets {
		if net.Name == name {
			return &net
		}
	}
	return nil
}

func getNetIOCounterValue(stat *psutilnet.IOCountersStat, name string) (uint64, error) {
	switch name {
	case "bytes_sent":
		return stat.BytesSent, nil
	case "bytes_recv":
		return stat.BytesRecv, nil
	case "packets_sent":
		return stat.PacketsSent, nil
	case "packets_recv":
		return stat.PacketsRecv, nil
	case "errin":
		return stat.Errin, nil
	case "errout":
		return stat.Errout, nil
	case "dropin":
		return stat.Dropin, nil
	case "dropout":
		return stat.Dropout, nil
	default:
		return 0, fmt.Errorf("Requested NetIOCounter statistic %s is not available", name)
	}
}

func getNetIOCounterMetricTypes() ([]plugin.Metric, error) {
	defer timeSpent(time.Now(), "getNetIOCounterMetricTypes")
	mts := make([]plugin.Metric, 0)

	for name, label := range netIOCounterLabels {
		//metrics which are the sum for all available nics
		mts = append(mts, plugin.Metric{
			Namespace:   plugin.NewNamespace("intel", "psutil", "net", "all", name),
			Description: label.description,
			Unit:        label.unit,
		})
		//dynamic metrics representing any nic
		mts = append(mts, plugin.Metric{
			Namespace: plugin.NewNamespace("intel", "psutil", "net").
				AddDynamicElement("interface_name", "network interface name").AddStaticElement(name),
			Description: label.description,
			Unit:        label.unit,
		})
	}

	return mts, nil
}

func getInterfaceConfiguration(ifaceName string) (map[string]string, error) {

	interfaceConfig, err := net.InterfaceByName(ifaceName)
	if err != nil {
		return nil, err
	}
	tags := make(map[string]string)
	tags["hardware_addr"] = string(interfaceConfig.HardwareAddr)
	tags["mtu"] = strconv.Itoa(interfaceConfig.MTU)
	return tags, nil
}
<|endoftext|>


<commit_before>package storable

import (
	. "gopkg.in/check.v1"
	"gopkg.in/mgo.v2/bson"
)

func (s *BaseSuite) TestBaseQuery_AddCriteria(c *C) {
	q := NewBaseQuery()
	q.AddCriteria(bson.M{"foo": "foo"})
	q.AddCriteria(bson.M{"qux": "qux"})

	c.Assert(q.GetCriteria(), DeepEquals, bson.M{
		"$and": []bson.M{
			bson.M{"foo": "foo"},
			bson.M{"qux": "qux"},
		},
	})
}

func (s *BaseSuite) TestBaseQuery_String(c *C) {
	q := NewBaseQuery()
	q.AddCriteria(bson.M{"foo": "foo"})
	q.AddCriteria(bson.M{"qux": "qux"})

	c.Assert(q.String(), Equals, "{\"$and\":[{\"foo\":\"foo\"},{\"qux\":\"qux\"}]}")
}
<commit_msg>Substitute escaping for raw string. NBC.<commit_after>package storable

import (
	. "gopkg.in/check.v1"
	"gopkg.in/mgo.v2/bson"
)

func (s *BaseSuite) TestBaseQuery_AddCriteria(c *C) {
	q := NewBaseQuery()
	q.AddCriteria(bson.M{"foo": "foo"})
	q.AddCriteria(bson.M{"qux": "qux"})

	c.Assert(q.GetCriteria(), DeepEquals, bson.M{
		"$and": []bson.M{
			bson.M{"foo": "foo"},
			bson.M{"qux": "qux"},
		},
	})
}

func (s *BaseSuite) TestBaseQuery_String(c *C) {
	q := NewBaseQuery()
	q.AddCriteria(bson.M{"foo": "foo"})
	q.AddCriteria(bson.M{"qux": "qux"})

	c.Assert(q.String(), Equals, `{"$and":[{"foo":"foo"},{"qux":"qux"}]}`)
}
<|endoftext|>


<commit_before>package bbolt_test

import (
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"os"
	"reflect"
	"testing"
	"testing/quick"
	"time"
)

// testing/quick defaults to 5 iterations and a random seed.
// You can override these settings from the command line:
//
//   -quick.count     The number of iterations to perform.
//   -quick.seed      The seed to use for randomizing.
//   -quick.maxitems  The maximum number of items to insert into a DB.
//   -quick.maxksize  The maximum size of a key.
//   -quick.maxvsize  The maximum size of a value.
//

var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int

func TestMain(m *testing.M) {
	flag.IntVar(&qcount, "quick.count", 5, "")
	flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "")
	flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "")
	flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "")
	flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "")
	flag.Parse()
	fmt.Fprintln(os.Stderr, "seed:", qseed)
	fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize)

	m.Run()
}

func qconfig() *quick.Config {
	return &quick.Config{
		MaxCount: qcount,
		Rand:     rand.New(rand.NewSource(int64(qseed))),
	}
}

type testdata []testdataitem

func (t testdata) Len() int           { return len(t) }
func (t testdata) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 }

func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value {
	n := rand.Intn(qmaxitems-1) + 1
	items := make(testdata, n)
	used := make(map[string]bool)
	for i := 0; i < n; i++ {
		item := &items[i]
		// Ensure that keys are unique by looping until we find one that we have not already used.
		for {
			item.Key = randByteSlice(rand, 1, qmaxksize)
			if !used[string(item.Key)] {
				used[string(item.Key)] = true
				break
			}
		}
		item.Value = randByteSlice(rand, 0, qmaxvsize)
	}
	return reflect.ValueOf(items)
}

type revtestdata []testdataitem

func (t revtestdata) Len() int           { return len(t) }
func (t revtestdata) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 }

type testdataitem struct {
	Key   []byte
	Value []byte
}

func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte {
	n := rand.Intn(maxSize-minSize) + minSize
	b := make([]byte, n)
	for i := 0; i < n; i++ {
		b[i] = byte(rand.Intn(255))
	}
	return b
}
<commit_msg>Make sure failed tests report their exit code (#240)<commit_after>package bbolt_test

import (
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"os"
	"reflect"
	"testing"
	"testing/quick"
	"time"
)

// testing/quick defaults to 5 iterations and a random seed.
// You can override these settings from the command line:
//
//   -quick.count     The number of iterations to perform.
//   -quick.seed      The seed to use for randomizing.
//   -quick.maxitems  The maximum number of items to insert into a DB.
//   -quick.maxksize  The maximum size of a key.
//   -quick.maxvsize  The maximum size of a value.
//

var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int

func TestMain(m *testing.M) {
	flag.IntVar(&qcount, "quick.count", 5, "")
	flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "")
	flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "")
	flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "")
	flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "")
	flag.Parse()
	fmt.Fprintln(os.Stderr, "seed:", qseed)
	fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize)

	os.Exit(m.Run())
}

func qconfig() *quick.Config {
	return &quick.Config{
		MaxCount: qcount,
		Rand:     rand.New(rand.NewSource(int64(qseed))),
	}
}

type testdata []testdataitem

func (t testdata) Len() int           { return len(t) }
func (t testdata) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 }

func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value {
	n := rand.Intn(qmaxitems-1) + 1
	items := make(testdata, n)
	used := make(map[string]bool)
	for i := 0; i < n; i++ {
		item := &items[i]
		// Ensure that keys are unique by looping until we find one that we have not already used.
		for {
			item.Key = randByteSlice(rand, 1, qmaxksize)
			if !used[string(item.Key)] {
				used[string(item.Key)] = true
				break
			}
		}
		item.Value = randByteSlice(rand, 0, qmaxvsize)
	}
	return reflect.ValueOf(items)
}

type revtestdata []testdataitem

func (t revtestdata) Len() int           { return len(t) }
func (t revtestdata) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 }

type testdataitem struct {
	Key   []byte
	Value []byte
}

func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte {
	n := rand.Intn(maxSize-minSize) + minSize
	b := make([]byte, n)
	for i := 0; i < n; i++ {
		b[i] = byte(rand.Intn(255))
	}
	return b
}
<|endoftext|>


<commit_before>package main

/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -lcwiid -Lcwiid/libcwiid/libcwiid.a
#include "racerwiigo.h"
#include <stdlib.h>
#include <cwiid.h>
#include <time.h>
#include <bluetooth/bluetooth.h>
*/
import "C"

import (
	"fmt"
	"os"
	"reflect"
	"time"
	"unsafe"
)

var buttons = []_Ctype_uint16_t{ // only HOME and A buttons are used for this program
	C.CWIID_BTN_A,
	//C.CWIID_BTN_B,
	//C.CWIID_BTN_1,
	//C.CWIID_BTN_2,
	//C.CWIID_BTN_MINUS,
	C.CWIID_BTN_HOME,
	//C.CWIID_BTN_LEFT,
	//C.CWIID_BTN_RIGHT,
	//C.CWIID_BTN_DOWN,
	//C.CWIID_BTN_UP,
	//C.CWIID_BTN_PLUS,
}

var buttonStatus []bool

var buttonChan chan _Ctype_uint16_t
var exit chan bool
var callback = goCwiidCallback // so it's not garbage collected
var errCallback = goErrCallback
var start *time.Time
var runners []time.Duration

//export goCwiidCallback
func goCwiidCallback(wm unsafe.Pointer, a int, mesg *C.struct_cwiid_btn_mesg, tp unsafe.Pointer) {
	//defer C.free(unsafe.Pointer(mesg))
	var messages []C.struct_cwiid_btn_mesg
	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&messages)))
	sliceHeader.Cap = a
	sliceHeader.Len = a
	sliceHeader.Data = uintptr(unsafe.Pointer(mesg))
	for _, m := range messages {
		if m._type != C.CWIID_MESG_BTN {
			exit <- true
			continue
		}
		//fmt.Printf("Received message - %#v\n", m)
		for x, button := range buttons {
			if m.buttons&button == button {
				if !buttonStatus[x] {
					buttonChan <- button
					buttonStatus[x] = true
				}
			} else {
				buttonStatus[x] = false
			}
		}
	}
}

//export goErrCallback
func goErrCallback(wm unsafe.Pointer, char *C.char, ap unsafe.Pointer) {
	//func goErrCallback(wm *C.cwiid_wiimote_t, char *C.char, ap C.va_list) {s
	str := C.GoString(char)
	switch str {
	case "No Bluetooth interface found":
		fallthrough
	case "no such device":
		fmt.Printf("No Bluetooth device found\n")
		os.Exit(1)
	case "Socket connect error (control channel)":
		fallthrough
	case "No wiimotes found":
		exit <- true
	default:
		fmt.Printf("Inside error calback - %s\n", str)
	}
}

func main() {
	buttonStatus = make([]bool, len(buttons))
	var bdaddr C.bdaddr_t
	var wm *C.struct_cwiid_wiimote_t
	buttonChan = make(chan _Ctype_uint16_t, 1)
	exit = make(chan bool, 1)
	ticker := time.NewTicker(time.Second)
	runners = make([]time.Duration, 0, 1024)
	val, err := C.cwiid_set_err(C.getErrCallback())
	if val != 0 || err != nil {
		fmt.Printf("Error setting the callback to catch errors - %d - %v", val, err)
		os.Exit(1)
	}
	for {
	outer:
		for {
			// clear both channels
			select {
			case <-buttonChan:
			case <-exit:
			default:
				break outer
			}
		}
		fmt.Println("Press 1&2 on the Wiimote now")
		wm, err = C.cwiid_open(&bdaddr, 0)
		if err != nil {
			fmt.Errorf("cwiid_open: %v\n", err)
			continue
		}

		res, err := C.cwiid_command(wm, C.CWIID_CMD_RPT_MODE, C.CWIID_RPT_BTN)
		if res != 0 || err != nil {
			fmt.Printf("Result of command = %d - %v\n", res, err)
		}

		res, err = C.cwiid_set_mesg_callback(wm, C.getCwiidCallback())
		if res != 0 || err != nil {
			fmt.Printf("Result of callback = %d - %v\n", res, err)
		}
		res, err = C.cwiid_enable(wm, C.CWIID_FLAG_MESG_IFC)
		if res != 0 || err != nil {
			fmt.Printf("Result of enable = %d - %v\n", res, err)
		}

		res, err = C.cwiid_set_led(wm, C.CWIID_LED4_ON)
		if res != 0 || err != nil {
			fmt.Printf("Set led result = %d\n", res)
			fmt.Errorf("Err = %v", err)
		}
	loop:
		for {
			select {
			case <-exit:
				fmt.Println("Wiimote lost connection!")
				break loop
			case button := <-buttonChan:
				switch button {
				case C.CWIID_BTN_A:
					if start == nil {
						start = new(time.Time)
						*start = time.Now()
						fmt.Printf("Race started @ %s\n", start.Format("3:04:05"))
						runners = runners[:0]
					} else {
						runners = append(runners, time.Now().Sub(*start))
						diff := runners[len(runners)-1]
						fmt.Printf("#%d - %s\n", len(runners), diff)
					}
				//case C.CWIID_BTN_B:
				//	fmt.Println("B")
				//case C.CWIID_BTN_1:
				//	fmt.Println("1")
				//case C.CWIID_BTN_2:
				//	fmt.Println("2")
				//case C.CWIID_BTN_MINUS:
				//	fmt.Println("Minus")
				case C.CWIID_BTN_HOME:
					fmt.Println("Race finished!")
					return
					//case C.CWIID_BTN_LEFT:
					//	fmt.Println("Left")
					//case C.CWIID_BTN_RIGHT:
					//	fmt.Println("Right")
					//case C.CWIID_BTN_DOWN:
					//	fmt.Println("Down")
					//case C.CWIID_BTN_UP:
					//	fmt.Println("Up")
					//case C.CWIID_BTN_PLUS:
					//	fmt.Println("Plus")
				}
			case now := <-ticker.C:
				if start != nil {
					diff := now.Sub(*start)
					fmt.Printf("%00f:%00f:%00f\n", diff.Hours(), diff.Minutes(), diff.Seconds())
				}
				// update the clock
			}
		}
	}
}
<commit_msg>added http handler to output required data format of race<commit_after>package main

/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -lcwiid -Lcwiid/libcwiid/libcwiid.a
#include "racerwiigo.h"
#include <stdlib.h>
#include <cwiid.h>
#include <time.h>
#include <bluetooth/bluetooth.h>
*/
import "C"

import (
	"fmt"
	"html/template"
	"net/http"
	"os"
	"reflect"
	"time"
	"unsafe"
)

var buttons = []_Ctype_uint16_t{ // only HOME and A buttons are used for this program
	C.CWIID_BTN_A,
	//C.CWIID_BTN_B,
	//C.CWIID_BTN_1,
	//C.CWIID_BTN_2,
	//C.CWIID_BTN_MINUS,
	C.CWIID_BTN_HOME,
	//C.CWIID_BTN_LEFT,
	//C.CWIID_BTN_RIGHT,
	//C.CWIID_BTN_DOWN,
	//C.CWIID_BTN_UP,
	//C.CWIID_BTN_PLUS,
}

var buttonStatus []bool

var buttonChan chan _Ctype_uint16_t
var exit chan bool
var callback = goCwiidCallback // so it's not garbage collected
var errCallback = goErrCallback
var start *time.Time
var runners []HumanDuration
var raceResultsTemplate *template.Template

type HumanDuration time.Duration

func (hd HumanDuration) String() string {
	return fmt.Sprintf("%#02.0f:%#02.0f:%#02.2f\n", time.Duration(hd).Hours(), time.Duration(hd).Minutes(), time.Duration(hd).Seconds())
}

//export goCwiidCallback
func goCwiidCallback(wm unsafe.Pointer, a int, mesg *C.struct_cwiid_btn_mesg, tp unsafe.Pointer) {
	//defer C.free(unsafe.Pointer(mesg))
	var messages []C.struct_cwiid_btn_mesg
	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&messages)))
	sliceHeader.Cap = a
	sliceHeader.Len = a
	sliceHeader.Data = uintptr(unsafe.Pointer(mesg))
	for _, m := range messages {
		if m._type != C.CWIID_MESG_BTN {
			exit <- true
			continue
		}
		//fmt.Printf("Received message - %#v\n", m)
		for x, button := range buttons {
			if m.buttons&button == button {
				if !buttonStatus[x] {
					buttonChan <- button
					buttonStatus[x] = true
				}
			} else {
				buttonStatus[x] = false
			}
		}
	}
}

//export goErrCallback
func goErrCallback(wm unsafe.Pointer, char *C.char, ap unsafe.Pointer) {
	//func goErrCallback(wm *C.cwiid_wiimote_t, char *C.char, ap C.va_list) {s
	str := C.GoString(char)
	switch str {
	case "No Bluetooth interface found":
		fallthrough
	case "no such device":
		fmt.Printf("No Bluetooth device found\n")
		os.Exit(1)
	case "Socket connect error (control channel)":
		fallthrough
	case "No wiimotes found":
		exit <- true
	default:
		fmt.Printf("Inside error calback - %s\n", str)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	raceResultsTemplate.Execute(w, runners)
}

func main() {
	var err error
	raceResultsTemplate, err = template.ParseFiles("raceResults.template")
	if err != nil {
		fmt.Printf("Error parsing template! - %s\n", err)
		return
	}
	go raceFunc()
	http.HandleFunc("/", handler)
	err = http.ListenAndServe(":80", nil)
	if err != nil {
		fmt.Printf("Error starting http server! - %s\n", err)
		err = http.ListenAndServe(":8080", nil)
		if err != nil {
			fmt.Printf("Error starting http server! - %s\n", err)
			return
		}
	}
}

func raceFunc() {
	buttonStatus = make([]bool, len(buttons))
	var bdaddr C.bdaddr_t
	var wm *C.struct_cwiid_wiimote_t
	buttonChan = make(chan _Ctype_uint16_t, 1)
	exit = make(chan bool, 1)
	ticker := time.NewTicker(time.Second)
	runners = make([]HumanDuration, 0, 1024)
	val, err := C.cwiid_set_err(C.getErrCallback())
	if val != 0 || err != nil {
		fmt.Printf("Error setting the callback to catch errors - %d - %v", val, err)
		os.Exit(1)
	}
	for {
	outer:
		for {
			// clear both channels
			select {
			case <-buttonChan:
			case <-exit:
			default:
				break outer
			}
		}
		fmt.Println("Press 1&2 on the Wiimote now")
		wm,
			err = C.cwiid_open(&bdaddr, 0)
		if err != nil {
			fmt.Errorf("cwiid_open: %v\n", err)
			continue
		}

		res, err := C.cwiid_command(wm, C.CWIID_CMD_RPT_MODE, C.CWIID_RPT_BTN)
		if res != 0 || err != nil {
			fmt.Printf("Result of command = %d - %v\n", res, err)
		}

		res, err = C.cwiid_set_mesg_callback(wm, C.getCwiidCallback())
		if res != 0 || err != nil {
			fmt.Printf("Result of callback = %d - %v\n", res, err)
		}
		res, err = C.cwiid_enable(wm, C.CWIID_FLAG_MESG_IFC)
		if res != 0 || err != nil {
			fmt.Printf("Result of enable = %d - %v\n", res, err)
		}

		res, err = C.cwiid_set_led(wm, C.CWIID_LED4_ON)
		if res != 0 || err != nil {
			fmt.Printf("Set led result = %d\n", res)
			fmt.Errorf("Err = %v", err)
		}
	loop:
		for {
			select {
			case <-exit:
				fmt.Println("Wiimote lost connection!")
				break loop
			case button := <-buttonChan:
				switch button {
				case C.CWIID_BTN_A:
					if start == nil {
						start = new(time.Time)
						*start = time.Now()
						fmt.Printf("Race started @ %s\n", start.Format("3:04:05"))
						runners = runners[:0]
					} else {
						runners = append(runners, HumanDuration(time.Now().Sub(*start)))
						diff := runners[len(runners)-1]
						fmt.Printf("#%d - %s\n", len(runners), diff)
					}
				//case C.CWIID_BTN_B:
				//	fmt.Println("B")
				//case C.CWIID_BTN_1:
				//	fmt.Println("1")
				//case C.CWIID_BTN_2:
				//	fmt.Println("2")
				//case C.CWIID_BTN_MINUS:
				//	fmt.Println("Minus")
				case C.CWIID_BTN_HOME:
					fmt.Println("Race finished!")
					return
					//case C.CWIID_BTN_LEFT:
					//	fmt.Println("Left")
					//case C.CWIID_BTN_RIGHT:
					//	fmt.Println("Right")
					//case C.CWIID_BTN_DOWN:
					//	fmt.Println("Down")
					//case C.CWIID_BTN_UP:
					//	fmt.Println("Up")
					//case C.CWIID_BTN_PLUS:
					//	fmt.Println("Plus")
				}
			case now := <-ticker.C:
				if start != nil {
					diff := HumanDuration(now.Sub(*start))
					fmt.Println(diff)
				}
				// update the clock
			}
		}
	}
}
<|endoftext|>


<commit_before>package randomtext

import (
	"bufio"
	"io"
	"math/rand"
)

//go:generate go-bindata -pkg $GOPACKAGE -o assets.go assets/

// Generate text of given type for a given size and writes it to the given writer
func Generate(sizeInBytes int, generate func() string, writer io.Writer) {
	bufferedWriter := bufio.NewWriter(writer)
	defer bufferedWriter.Flush()
	bytesSent := 0
	for bytesSent < sizeInBytes {
		content := generate()
		noOfBytesWritten, _ := bufferedWriter.WriteString(content)
		bytesSent += noOfBytesWritten
	}
}

func randomGenerator(sourceData []string) func() string {
	sourceDataSize := len(sourceData)
	return func() string {
		return sourceData[rand.Intn(sourceDataSize)]
	}
}
<commit_msg>Performance improvements<commit_after>package randomtext

import (
	"bufio"
	"io"
	"math/rand"
)

//go:generate go-bindata -pkg $GOPACKAGE -o assets.go assets/

// Generate text of given type for a given size and writes it to the given writer
func Generate(sizeInBytes int, generate func() string, writer io.Writer) {
	bufferedWriter := bufio.NewWriter(writer)
	defer bufferedWriter.Flush()
	bytesSent := 0
	for bytesSent < sizeInBytes {
		content := generate()
		noOfBytesWritten, _ := bufferedWriter.WriteString(content)
		bytesSent += noOfBytesWritten
	}
}

func randomGenerator(sourceData []string) func() string {
	sourceDataSize := len(sourceData)
	randomArrayIndexes := rand.Perm(sourceDataSize)
	i := -1
	return func() string {
		i = (i + 1) % sourceDataSize
		return sourceData[randomArrayIndexes[i]]
	}
}
<|endoftext|>


<commit_before>package semver

import (
	"fmt"
	"testing"
)

var rangeTestBattery = map[string]map[string]bool{
	"^1.3.4": {
		"1.3.4":  true,
		"1.1.0":  false,
		"1.3.3":  false,
		"1.3.5":  true,
		"1.6.7":  true,
		"1.13.0": true,
		"2.0.0":  false,
	},
	"^0.3.1": {
		"0.3.0":    false,
		"0.2.1":    false,
		"0.3.1":    true,
		"1.2.3":    false,
		"0.4.0":    false,
		"0.3.9999": true,
	},
	"^0.0.2": {
		"1.0.1":   false,
		"0.1.0":   false,
		"0.0.2":   true,
		"0.0.999": false,
	},
	"~1.3.4": {
		"0.0.1":    false,
		"1.3.4":    true,
		"1.1.0":    false,
		"1.3.3":    false,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    false,
		"1.6.7":    false,
		"1.13.0":   false,
		"2.0.0":    false,
	},
	"~1.3": {
		"0.0.1":    false,
		"1.3.0":    true,
		"1.3.4":    true,
		"1.1.0":    false,
		"1.3.3":    true,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    false,
		"1.6.7":    false,
		"1.13.0":   false,
		"2.0.0":    false,
	},
	"~1": {
		"0.0.1":    false,
		"1.3.0":    true,
		"1.3.4":    true,
		"1.1.0":    true,
		"1.3.3":    true,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    true,
		"1.6.7":    true,
		"1.13.0":   true,
		"2.0.0":    false,
	},
	"=1.3.4": {
		"1.3.4": true,
		"1.3.0": false,
		"1.3":   false,
		"1.3.1": false,
		"2.4.2": false,
	},
	"=1.3": {
		"1.3.0": true,
		"1.3":   true,
		"1.3.1": false,
		"2.3":   false,
	},
	"1.3": {
		"1.3.0": true,
		"1.3":   true,
		"1.3.1": false,
		"2.3":   false,
	},
	"1.3.2 - 1.4.1": {
		"1.3.0": false,
		"1.3":   false,
		"1.3.2": true,
		"1.3.6": true,
		"1.4.0": true,
		"1.4.1": true,
		"1.4.2": false,
		"1.5.0": false,
	},
	"1.3.2 - 1.4": {
		"1.3.0":  false,
		"1.3":    false,
		"1.3.2":  true,
		"1.3.6":  true,
		"1.4.0":  true,
		"1.4.1":  true,
		"1.4.2":  true,
		"1.4.45": true,
		"1.5.0":  false,
	},
	"1.3.2 - 1": {
		"1.3.0":  false,
		"1.3":    false,
		"1.3.2":  true,
		"1.3.6":  true,
		"1.4.0":  true,
		"1.4.1":  true,
		"1.4.2":  true,
		"1.4.45": true,
		"1.5.0":  true,
		"2.0.0":  false,
	},
	"1.3.*": {
		"1.3.0":    true,
		"1.3.1":    true,
		"1.3.9999": true,
		"1.3":      true,
	},
	"*.*.*": {
		"1.0.2": true,
		"0.0.0": true,
		"0":     true,
	},
	"<*.*.*": {
		"1.0.2": false,
		"0.0.0": false,
		"0":     false,
	},
	"<1.*.*": {
		"2.0.0": false,
		"1.0.2": false,
		"1.0.0": false,
		"0.0.0": true,
		"0":     true,
	},
	">=1.2.7": {
		"1.2.7": true,
		"1.2.8": true,
		"2.5.3": true,
		"1.3.9": true,
		"1.2.6": false,
		"1.1.0": false,
	},
	">*.*.*": {
		"1.0.2": false,
		"0.0.0": false,
		"0":     false,
	},
	"^1.*.*": {
		"1.0.2": true,
		"0.0.0": false,
		"0":     false,
	},
	"*": {
		"1.3.4": true,
		"3.4":   true,
		"0":     true,
		"0.0.1": true,
	},
}

func TestRangeOperator(t *testing.T) {
	for rangeStr, data := range rangeTestBattery {
		r := MustParseRange(rangeStr)
		re := r.RegExp()
		for v, result := range data {
			if r.Contains(MustParseVersion(v)) != result {
				t.Errorf("Expected %v of %v to evaluate to %v", rangeStr, v, result)
			}
			nv := MustParseVersion(v)

			if re[0].MatchString(fmt.Sprintf(`%d.%d.%d`, nv.Major, nv.Minor, nv.Patch)) &&
				re[1].MatchString(fmt.Sprintf(`%d.%d.%d`, nv.Major, nv.Minor, nv.Patch)) != result {
				fmt.Println(re[0], re[1])
				fmt.Println("WTF", fmt.Sprintf(`%d.%d.%d`, nv.Major, nv.Minor, nv.Patch), rangeStr, result)
			}
		}
	}
}

func TestRangeOperatorRe(t *testing.T) {
	for rangeStr, data := range rangeTestBattery {
		r := MustParseRange(rangeStr)
		re := r.RegExp()
		for v, result := range data {
			nv := MustParseVersion(v)
			if re[0].MatchString(fmt.Sprintf(`%d.%d.%d`, nv.Major, nv.Minor, nv.Patch)) &&
				re[1].MatchString(fmt.Sprintf(`%d.%d.%d`, nv.Major, nv.Minor, nv.Patch)) != result {
				t.Errorf("Expected %v of %v to evaluate to %v", rangeStr, v, result)
			}
		}
	}
}
<commit_msg>Cleanup test<commit_after>package semver

import "testing"

var rangeTestBattery = map[string]map[string]bool{
	"^1.3.4": {
		"1.3.4":  true,
		"1.1.0":  false,
		"1.3.3":  false,
		"1.3.5":  true,
		"1.6.7":  true,
		"1.13.0": true,
		"2.0.0":  false,
	},
	"^0.3.1": {
		"0.3.0":    false,
		"0.2.1":    false,
		"0.3.1":    true,
		"1.2.3":    false,
		"0.4.0":    false,
		"0.3.9999": true,
	},
	"^0.0.2": {
		"1.0.1":   false,
		"0.1.0":   false,
		"0.0.2":   true,
		"0.0.999": false,
	},
	"~1.3.4": {
		"0.0.1":    false,
		"1.3.4":    true,
		"1.1.0":    false,
		"1.3.3":    false,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    false,
		"1.6.7":    false,
		"1.13.0":   false,
		"2.0.0":    false,
	},
	"~1.3": {
		"0.0.1":    false,
		"1.3.0":    true,
		"1.3.4":    true,
		"1.1.0":    false,
		"1.3.3":    true,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    false,
		"1.6.7":    false,
		"1.13.0":   false,
		"2.0.0":    false,
	},
	"~1": {
		"0.0.1":    false,
		"1.3.0":    true,
		"1.3.4":    true,
		"1.1.0":    true,
		"1.3.3":    true,
		"1.3.5":    true,
		"1.3.9999": true,
		"1.4.0":    true,
		"1.6.7":    true,
		"1.13.0":   true,
		"2.0.0":    false,
	},
	"=1.3.4": {
		"1.3.4": true,
		"1.3.0": false,
		"1.3":   false,
		"1.3.1": false,
		"2.4.2": false,
	},
	"=1.3": {
		"1.3.0": true,
		"1.3":   true,
		"1.3.1": false,
		"2.3":   false,
	},
	"1.3": {
		"1.3.0": true,
		"1.3":   true,
		"1.3.1": false,
		"2.3":   false,
	},
	"1.3.2 - 1.4.1": {
		"1.3.0": false,
		"1.3":   false,
		"1.3.2": true,
		"1.3.6": true,
		"1.4.0": true,
		"1.4.1": true,
		"1.4.2": false,
		"1.5.0": false,
	},
	"1.3.2 - 1.4": {
		"1.3.0":  false,
		"1.3":    false,
		"1.3.2":  true,
		"1.3.6":  true,
		"1.4.0":  true,
		"1.4.1":  true,
		"1.4.2":  true,
		"1.4.45": true,
		"1.5.0":  false,
	},
	"1.3.2 - 1": {
		"1.3.0":  false,
		"1.3":    false,
		"1.3.2":  true,
		"1.3.6":  true,
		"1.4.0":  true,
		"1.4.1":  true,
		"1.4.2":  true,
		"1.4.45": true,
		"1.5.0":  true,
		"2.0.0":  false,
	},
	"1.3.*": {
		"1.3.0":    true,
		"1.3.1":    true,
		"1.3.9999": true,
		"1.3":      true,
	},
	"*.*.*": {
		"1.0.2": true,
		"0.0.0": true,
		"0":     true,
	},
	"<*.*.*": {
		"1.0.2": false,
		"0.0.0": false,
		"0":     false,
	},
	"<1.*.*": {
		"2.0.0": false,
		"1.0.2": false,
		"1.0.0": false,
		"0.0.0": true,
		"0":     true,
	},
	">=1.2.7": {
		"1.2.7": true,
		"1.2.8": true,
		"2.5.3": true,
		"1.3.9": true,
		"1.2.6": false,
		"1.1.0": false,
	},
	">*.*.*": {
		"1.0.2": false,
		"0.0.0": false,
		"0":     false,
	},
	"^1.*.*": {
		"1.0.2": true,
		"0.0.0": false,
		"0":     false,
	},
	"*": {
		"1.3.4": true,
		"3.4":   true,
		"0":     true,
		"0.0.1": true,
	},
}

func TestRangeOperator(t *testing.T) {
	for rangeStr, data := range rangeTestBattery {
		r := MustParseRange(rangeStr)
		for v, result := range data {
			if r.Contains(MustParseVersion(v)) != result {
				t.Errorf("Expected %v of %v to evaluate to %v", rangeStr, v, result)
			}
		}
	}
}

func TestRangeOperatorRe(t *testing.T) {
	for rangeStr, data := range rangeTestBattery {
		r := MustParseRange(rangeStr)
		re := r.RegExp()
		for v, result := range data {
			nv := MustParseVersion(v)
			if re[0].MatchString(nv.String()) &&
				re[1].MatchString(nv.String()) != result {
				t.Errorf("Expected %v of %v to evaluate to %v", rangeStr, v, result)
			}
		}
	}
}
<|endoftext|>


<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"encoding/json"
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
)

var lexParseTests LexTests

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, testName string) (tree *Tree, err error) {
	if lexParseTests == nil {
		lexParseTests, err = ParseTestData("../testdata/test_lex_sections.dat")
		if err != nil {
			t.Fatal(err)
		}
	}
	test := lexParseTests.SearchByName(testName)
	if test != nil {
		log.Debugf("Test Name: %s\n", test.name)
		log.Debugf("Description: %s\n", test.description)
		log.Debugf("Test Input:\n-----------\n%s\n----------\n", test.data)
		tree, err = Parse(test.name, test.data)
		if err != nil {
			t.Fatal(err)
		}
	} else {
		t.Fatal("Missing #items for", testName)
	}
	return
}

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, c.testName, c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, c.testName,
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func (c *checkNode) updateState(pVal reflect.Value, eVal interface{}, field int) bool {
	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = pVal.Type().Field(field).Name
	c.pFieldVal = pVal.Field(field).Interface()
	c.pFieldType = pVal.Type().Field(field).Type
	c.id = pVal.FieldByName("Id").Interface().(int)

	// Expected parser metadata
	c.eFieldName = strings.ToLower(string(c.pFieldName[0])) + c.pFieldName[1:]
	c.eFieldVal = eVal.(map[string]interface{})[c.eFieldName]
	c.eFieldType = reflect.TypeOf(c.eFieldVal)

	pField := pVal.Field(field)
	if pField.Kind() == reflect.Ptr && pField.IsNil() {
		// Overline adornment nodes can be null
		if c.pFieldName == "OverLine" {
			return false
		} else {
			c.dError()
			return false
		}
	} else if c.pFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(pNode Node, expect interface{}) {
	pVal := reflect.ValueOf(pNode).Elem()
	for i := 0; i < pVal.NumField(); i++ {

		if c.updateState(pVal, expect, i) == false {
			continue
		}

		switch c.pFieldName {
		case "Type":
			if c.pFieldVal.(NodeType).String() != c.eFieldVal {
				c.dError()
			}
		case "Id", "Level", "Length":
			if float64(c.pFieldVal.(int)) != c.eFieldVal {
				c.dError()
			}
		case "Line":
			if float64(c.pFieldVal.(Line)) != c.eFieldVal {
				c.dError()
			}
		case "StartPosition":
			if float64(c.pFieldVal.(StartPosition)) != c.eFieldVal {
				c.dError()
			}
		case "OverLine", "UnderLine":
			c.checkFields(c.pFieldVal.(Node), c.eFieldVal)
		case "NodeList":
			for num, node := range c.pFieldVal.(NodeList) {
				// A little hackery to make our recursion easy
				eFieldVal := c.eFieldVal
				c.checkFields(node.(Node), eFieldVal.([]interface{})[num])
				c.eFieldVal = eFieldVal
			}
		case "Rune":
			if string(c.pFieldVal.(rune)) != c.eFieldVal {
				c.dError()
			}
		default:
			if c.pFieldVal != c.eFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, pNodes *NodeList, testName string) {
	test := lexParseTests.SearchByName(testName)
	if len(strings.Trim(test.expectTree, "\n")) == 0 {
		t.Fatal("#parse-tree not found for", testName)
	}
	var nodeList []interface{}
	err := json.Unmarshal([]byte(test.expectTree), &nodeList)
	if err != nil {
		t.Fatal(err)
	}
	state := &checkNode{t: t, testName: testName}
	for pNum, pNode := range *pNodes {
		state.checkFields(pNode, nodeList[pNum])
	}
	return
}

func TestParseSectionTitlePara(t *testing.T) {
	testName := "SectionTitlePara"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}
<commit_msg>parse_test.go: Reword fatal error<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

// To enable debug output when testing, use "go test -debug"

package parse

import (
	"encoding/json"
	"github.com/demizer/go-elog"
	"reflect"
	"strings"
	"testing"
)

var lexParseTests LexTests

func TestSectionLevelsAdd(t *testing.T) {
	var p sectionLevels
	lvl := p.Add('=', true, 5)
	if lvl != 1 {
		t.Errorf("Improper level on first add, Got level: %d, expected: %d", lvl, 1)
	}
}

func TestSectionLevelsString(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	out := p.String()
	expect := "level: 1, rune: '=', overline: true, length: 5\nlevel: 2, rune: '-', " +
		"overline: true, length: 8\nlevel: 3, rune: '~', overline: false, length: 6\n"
	if out != expect {
		t.Errorf("String output mismatch!\nExpect:\n\n\t%q,\nGot:\n\n\t%q\n", expect, out)
	}
}

func TestSectionLevelsFind(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Find('-')
	if lvl == -1 {
		t.Errorf("Level not found!\nExpect:\n\n\t%d\nGot:\n\n\t%t\n", 2, lvl)
	}
	if lvl != 2 {
		t.Errorf("Level not correct!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 2, lvl)
	}
}

func TestSectionLevelsFindNoResult(t *testing.T) {
	var p sectionLevels
	lvl := p.Find('-')
	if lvl > 0 {
		t.Errorf("Should not find any levels!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", -1, lvl)
	}
}

func TestSectionLevelsLevelEmpty(t *testing.T) {
	var p sectionLevels
	lvl := p.Level()
	expect := 0
	if lvl != expect {
		t.Errorf("Empty sectionLevels should return \"%d\"!\nExpect:\t%d\nGot:\t%d\n",
			expect, expect, lvl)
	}

}

func TestSectionLevelsLevel(t *testing.T) {
	var p sectionLevels
	p.Add('=', true, 5)
	p.Add('-', true, 8)
	p.Add('~', false, 6)
	lvl := p.Level()
	if lvl != 3 {
		t.Errorf("Level() returned incorrect level!\nExpect:\n\n\t%d\nGot:\n\n\t%d\n", 3, lvl)
	}
}

func parseTest(t *testing.T, testName string) (tree *Tree, err error) {
	if lexParseTests == nil {
		lexParseTests, err = ParseTestData("../testdata/test_lex_sections.dat")
		if err != nil {
			t.Fatal(err)
		}
	}
	test := lexParseTests.SearchByName(testName)
	if test != nil {
		log.Debugf("Test Name: %s\n", test.name)
		log.Debugf("Description: %s\n", test.description)
		log.Debugf("Test Input:\n-----------\n%s\n----------\n", test.data)
		tree, err = Parse(test.name, test.data)
		if err != nil {
			t.Fatal(err)
		}
	} else {
		t.Fatal("#items not found for", testName)
	}
	return
}

type checkNode struct {
	t          *testing.T
	testName   string
	pNodeName  string
	pFieldName string
	pFieldVal  interface{}
	pFieldType reflect.Type
	eFieldName string
	eFieldVal  interface{}
	eFieldType reflect.Type
	id         int
}

func (c *checkNode) error(args ...interface{}) {
	c.t.Error(args...)
}

func (c *checkNode) errorf(format string, args ...interface{}) {
	c.t.Errorf(format, args...)
}

func (c *checkNode) dError() {
	if c.pFieldName == "Rune" {
		c.t.Errorf("Got: %s.%s = %#v (%v) (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
			c.pNodeName, c.pFieldName, c.pFieldVal, string(c.pFieldVal.(int32)),
			c.pFieldType, c.id, c.testName, c.eFieldName, c.eFieldVal, c.eFieldType)
		return
	}
	c.t.Errorf("Got: %s.%s = %#v (%v) (Id: %d),\n\tExpect: %s.%s = %#v (%v)\n",
		c.pNodeName, c.pFieldName, c.pFieldVal, c.pFieldType, c.id, c.testName,
		c.eFieldName, c.eFieldVal, c.eFieldType)
}

func (c *checkNode) updateState(pVal reflect.Value, eVal interface{}, field int) bool {
	// Actual parsed metadata
	c.pNodeName = pVal.Type().Name()
	c.pFieldName = pVal.Type().Field(field).Name
	c.pFieldVal = pVal.Field(field).Interface()
	c.pFieldType = pVal.Type().Field(field).Type
	c.id = pVal.FieldByName("Id").Interface().(int)

	// Expected parser metadata
	c.eFieldName = strings.ToLower(string(c.pFieldName[0])) + c.pFieldName[1:]
	c.eFieldVal = eVal.(map[string]interface{})[c.eFieldName]
	c.eFieldType = reflect.TypeOf(c.eFieldVal)

	pField := pVal.Field(field)
	if pField.Kind() == reflect.Ptr && pField.IsNil() {
		// Overline adornment nodes can be null
		if c.pFieldName == "OverLine" {
			return false
		} else {
			c.dError()
			return false
		}
	} else if c.pFieldVal == nil {
		c.dError()
		return false
	}

	return true
}

func (c *checkNode) checkFields(pNode Node, expect interface{}) {
	pVal := reflect.ValueOf(pNode).Elem()
	for i := 0; i < pVal.NumField(); i++ {

		if c.updateState(pVal, expect, i) == false {
			continue
		}

		switch c.pFieldName {
		case "Type":
			if c.pFieldVal.(NodeType).String() != c.eFieldVal {
				c.dError()
			}
		case "Id", "Level", "Length":
			if float64(c.pFieldVal.(int)) != c.eFieldVal {
				c.dError()
			}
		case "Line":
			if float64(c.pFieldVal.(Line)) != c.eFieldVal {
				c.dError()
			}
		case "StartPosition":
			if float64(c.pFieldVal.(StartPosition)) != c.eFieldVal {
				c.dError()
			}
		case "OverLine", "UnderLine":
			c.checkFields(c.pFieldVal.(Node), c.eFieldVal)
		case "NodeList":
			for num, node := range c.pFieldVal.(NodeList) {
				// A little hackery to make our recursion easy
				eFieldVal := c.eFieldVal
				c.checkFields(node.(Node), eFieldVal.([]interface{})[num])
				c.eFieldVal = eFieldVal
			}
		case "Rune":
			if string(c.pFieldVal.(rune)) != c.eFieldVal {
				c.dError()
			}
		default:
			if c.pFieldVal != c.eFieldVal {
				c.dError()
			}
		}
	}

}

func checkParseNodes(t *testing.T, pNodes *NodeList, testName string) {
	test := lexParseTests.SearchByName(testName)
	if len(strings.Trim(test.expectTree, "\n")) == 0 {
		t.Fatal("#parse-tree not found for", testName)
	}
	var nodeList []interface{}
	err := json.Unmarshal([]byte(test.expectTree), &nodeList)
	if err != nil {
		t.Fatal(err)
	}
	state := &checkNode{t: t, testName: testName}
	for pNum, pNode := range *pNodes {
		state.checkFields(pNode, nodeList[pNum])
	}
	return
}

func TestParseSectionTitlePara(t *testing.T) {
	testName := "SectionTitlePara"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionTitleParaNoBlankLine(t *testing.T) {
	testName := "SectionTitleParaNoBlankLine"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionParaHeadPara(t *testing.T) {
	testName := "SectionParaHeadPara"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionUnexpectedTitles(t *testing.T) {
	testName := "SectionUnexpectedTitles"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}

func TestParseSectionLevelTest1(t *testing.T) {
	testName := "SectionLevelTest1"
	tree, err := parseTest(t, testName)
	if err != nil {
		t.Error(err)
	}
	checkParseNodes(t, tree.Nodes, testName)
}
<|endoftext|>


<commit_before>// Implements the Chacha RNG
package pqcrypto

import (
	"errors"

	rand "github.com/DeveloppSoft/go-rand"
	log "github.com/inconshreveable/log15"
)

var logger_rng = log.New("pqcrypto", "rng")

// Return 'nb' random bytes, thanks to chacha20
func GetRandom(nb int ) ([]byte, error) {
	var seed [32]byte

	r, err := rand.New(seed[:])
	if err != nil {
		logger_rng.Error(err.Error())
		return nil, err
	}

	var buffer = make([]byte, nb)
	n, err := r.Read(buffer[:])
	if err != nil {
		logger_rng.Error(err.Error())
		return nil, err
	}

	if n != len(buffer) {
		err = errors.New("didn't got enough bytes")
		logger_rng.Error(err.Error())
		return nil, err
	}

	return buffer, nil
}
<commit_msg>[pqcrypto] Go fmt RNG<commit_after>// Implements the Chacha RNG
package pqcrypto

import (
	"errors"

	rand "github.com/DeveloppSoft/go-rand"
	log "github.com/inconshreveable/log15"
)

var logger_rng = log.New("pqcrypto", "rng")

// Return 'nb' random bytes, thanks to chacha20
func GetRandom(nb int) ([]byte, error) {
	var seed [32]byte

	r, err := rand.New(seed[:])
	if err != nil {
		logger_rng.Error(err.Error())
		return nil, err
	}

	var buffer = make([]byte, nb)
	n, err := r.Read(buffer[:])
	if err != nil {
		logger_rng.Error(err.Error())
		return nil, err
	}

	if n != len(buffer) {
		err = errors.New("didn't got enough bytes")
		logger_rng.Error(err.Error())
		return nil, err
	}

	return buffer, nil
}
<|endoftext|>