<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 cloudruntests

import (
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/golang-samples/internal/cloudrunci"
	"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
)

func TestPubSubSinkService(t *testing.T) {
	tc := testutil.EndToEndTest(t)

	service := cloudrunci.NewService("pubsub", tc.ProjectID)
	service.Dir = "../pubsub"
	if err := service.Deploy(); err != nil {
		t.Fatalf("service.Deploy %q: %v", service.Name, err)
	}
	defer service.Clean()

	requestPath := "/"
	req, err := service.NewRequest("POST", requestPath)
	if err != nil {
		t.Fatalf("service.NewRequest: %v", err)
	}

	client := http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		t.Fatalf("client.Do: %v", err)
	}
	defer resp.Body.Close()
	fmt.Printf("client.Do: %s %s\n", req.Method, req.URL)

	if got := resp.StatusCode; got != http.StatusBadRequest {
		t.Errorf("response status: got %d, want %d", got, http.StatusBadRequest)
	}
}
<commit_msg>testing(eventarc): add HTTP test retry (#2636)<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 cloudruntests

import (
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/GoogleCloudPlatform/golang-samples/internal/cloudrunci"
	"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
)

func TestPubSubSinkService(t *testing.T) {
	tc := testutil.EndToEndTest(t)

	service := cloudrunci.NewService("pubsub", tc.ProjectID)
	service.Dir = "../pubsub"
	if err := service.Deploy(); err != nil {
		t.Fatalf("service.Deploy %q: %v", service.Name, err)
	}
	defer service.Clean()

	requestPath := "/"
	req, err := service.NewRequest("POST", requestPath)
	if err != nil {
		t.Fatalf("service.NewRequest: %v", err)
	}

	client := http.Client{Timeout: 10 * time.Second}

	testutil.Retry(t, 3, 5, func(r *testutil.R) {
		fmt.Printf("Attempt #%d: client.Do: %s %s\n", r.Attempt, req.Method, req.URL)
		resp, err := client.Do(req)
		if err != nil {
			t.Fatalf("client.Do: %v", err)
		}
		defer resp.Body.Close()

		if resp.StatusCode == http.StatusInternalServerError {
			r.Errorf("Cloud Run service not ready")
		} else if got := resp.StatusCode; got != http.StatusBadRequest {
			t.Errorf("response status: got %d, want %d", got, http.StatusBadRequest)
		}
	})
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package reflectcodec

import (
	"fmt"
	"reflect"
	"strconv"
	"sync"
	"unicode"
)

const (
	// SliceLenTagName that specifies the length of a slice.
	SliceLenTagName = "len"

	// TagValue is the value the tag must have to be serialized.
	TagValue = "true"
)

type FieldDesc struct {
	Index       int
	MaxSliceLen int
}

// StructFielder handles discovery of serializable fields in a struct.
type StructFielder interface {
	GetSerializedFields(t reflect.Type) ([]FieldDesc, error)
}

func NewStructFielder(tagName string, maxSliceLen int) StructFielder {
	return &structFielder{
		tagName:                tagName,
		maxSliceLen:            maxSliceLen,
		serializedFieldIndices: make(map[reflect.Type][]FieldDesc),
	}
}

type structFielder struct {
	lock        sync.Mutex
	tagName     string
	maxSliceLen int

	// Key: a struct type
	// Value: Slice where each element is index in the struct type of a field
	// that is serialized/deserialized e.g. Foo --> [1,5,8] means Foo.Field(1),
	// etc. are to be serialized/deserialized. We assume this cache is pretty
	// small (a few hundred keys at most) and doesn't take up much memory.
	serializedFieldIndices map[reflect.Type][]FieldDesc
}

// Returns the fields that have been marked as serializable in [t], which is a
// struct type. Returns an error if a field has tag "[tagName]: [TagValue]" but
// the field is un-exported. e.g. GetSerializedField(Foo) --> [1,5,8] means
// Foo.Field(1), Foo.Field(5), Foo.Field(8) are to be serialized/deserialized
func (s *structFielder) GetSerializedFields(t reflect.Type) ([]FieldDesc, error) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.serializedFieldIndices == nil {
		s.serializedFieldIndices = make(map[reflect.Type][]FieldDesc)
	}
	if serializedFields, ok := s.serializedFieldIndices[t]; ok { // use pre-computed result
		return serializedFields, nil
	}
	numFields := t.NumField()
	serializedFields := make([]FieldDesc, 0, numFields)
	for i := 0; i < numFields; i++ { // Go through all fields of this struct
		field := t.Field(i)
		if field.Tag.Get(s.tagName) != TagValue { // Skip fields we don't need to serialize
			continue
		}
		if unicode.IsLower(rune(field.Name[0])) { // Can only marshal exported fields
			return nil, fmt.Errorf("can't marshal un-exported field %s", field.Name)
		}
		sliceLenField := field.Tag.Get(SliceLenTagName)
		maxSliceLen := s.maxSliceLen
		if newLen, err := strconv.Atoi(sliceLenField); err == nil {
			maxSliceLen = newLen
		}
		serializedFields = append(serializedFields, FieldDesc{
			Index:       i,
			MaxSliceLen: maxSliceLen,
		})
	}
	s.serializedFieldIndices[t] = serializedFields // cache result
	return serializedFields, nil
}
<commit_msg>Moved GetSerializedFields comment<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package reflectcodec

import (
	"fmt"
	"reflect"
	"strconv"
	"sync"
	"unicode"
)

const (
	// SliceLenTagName that specifies the length of a slice.
	SliceLenTagName = "len"

	// TagValue is the value the tag must have to be serialized.
	TagValue = "true"
)

type FieldDesc struct {
	Index       int
	MaxSliceLen int
}

// StructFielder handles discovery of serializable fields in a struct.
type StructFielder interface {
	// Returns the fields that have been marked as serializable in [t], which is
	// a struct type. Additionally, returns the custom maximum length slice that
	// may be serialized into the field, if any.
	// Returns an error if a field has tag "[tagName]: [TagValue]" but the field
	// is un-exported.
	// GetSerializedField(Foo) --> [1,5,8] means Foo.Field(1), Foo.Field(5),
	// Foo.Field(8) are to be serialized/deserialized.
	GetSerializedFields(t reflect.Type) ([]FieldDesc, error)
}

func NewStructFielder(tagName string, maxSliceLen int) StructFielder {
	return &structFielder{
		tagName:                tagName,
		maxSliceLen:            maxSliceLen,
		serializedFieldIndices: make(map[reflect.Type][]FieldDesc),
	}
}

type structFielder struct {
	lock        sync.Mutex
	tagName     string
	maxSliceLen int

	// Key: a struct type
	// Value: Slice where each element is index in the struct type of a field
	// that is serialized/deserialized e.g. Foo --> [1,5,8] means Foo.Field(1),
	// etc. are to be serialized/deserialized. We assume this cache is pretty
	// small (a few hundred keys at most) and doesn't take up much memory.
	serializedFieldIndices map[reflect.Type][]FieldDesc
}

func (s *structFielder) GetSerializedFields(t reflect.Type) ([]FieldDesc, error) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.serializedFieldIndices == nil {
		s.serializedFieldIndices = make(map[reflect.Type][]FieldDesc)
	}
	if serializedFields, ok := s.serializedFieldIndices[t]; ok { // use pre-computed result
		return serializedFields, nil
	}
	numFields := t.NumField()
	serializedFields := make([]FieldDesc, 0, numFields)
	for i := 0; i < numFields; i++ { // Go through all fields of this struct
		field := t.Field(i)
		if field.Tag.Get(s.tagName) != TagValue { // Skip fields we don't need to serialize
			continue
		}
		if unicode.IsLower(rune(field.Name[0])) { // Can only marshal exported fields
			return nil, fmt.Errorf("can't marshal un-exported field %s", field.Name)
		}
		sliceLenField := field.Tag.Get(SliceLenTagName)
		maxSliceLen := s.maxSliceLen
		if newLen, err := strconv.Atoi(sliceLenField); err == nil {
			maxSliceLen = newLen
		}
		serializedFields = append(serializedFields, FieldDesc{
			Index:       i,
			MaxSliceLen: maxSliceLen,
		})
	}
	s.serializedFieldIndices[t] = serializedFields // cache result
	return serializedFields, nil
}
<|endoftext|>


<commit_before>package work

import (
	"github.com/garyburd/redigo/redis"
	"time"
)

// Enqueuer can enqueue jobs.
type Enqueuer struct {
	Namespace string // eg, "myapp-work"
	Pool      *redis.Pool

	queuePrefix           string // eg, "myapp-work:jobs:"
	knownJobs             map[string]int64
	enqueueUniqueScript   *redis.Script
	enqueueUniqueInScript *redis.Script
}

// NewEnqueuer creates a new enqueuer with the specified Redis namespace and Redis pool.
func NewEnqueuer(namespace string, pool *redis.Pool) *Enqueuer {
	if pool == nil {
		panic("NewEnqueuer needs a non-nil *redis.Pool")
	}

	return &Enqueuer{
		Namespace:             namespace,
		Pool:                  pool,
		queuePrefix:           redisKeyJobsPrefix(namespace),
		knownJobs:             make(map[string]int64),
		enqueueUniqueScript:   redis.NewScript(2, redisLuaEnqueueUnique),
		enqueueUniqueInScript: redis.NewScript(2, redisLuaEnqueueUniqueIn),
	}
}

// Enqueue will enqueue the specified job name and arguments. The args param can be nil if no args ar needed.
// Example: e.Enqueue("send_email", work.Q{"addr": "test@example.com"})
func (e *Enqueuer) Enqueue(jobName string, args map[string]interface{}) (*Job, error) {
	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if _, err := conn.Do("LPUSH", e.queuePrefix+jobName, rawJSON); err != nil {
		return nil, err
	}

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return job, err
	}

	return job, nil
}

// EnqueueIn enqueues a job in the scheduled job queue for execution in secondsFromNow seconds.
func (e *Enqueuer) EnqueueIn(jobName string, secondsFromNow int64, args map[string]interface{}) (*ScheduledJob, error) {
	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	scheduledJob := &ScheduledJob{
		RunAt: nowEpochSeconds() + secondsFromNow,
		Job:   job,
	}

	_, err = conn.Do("ZADD", redisKeyScheduled(e.Namespace), scheduledJob.RunAt, rawJSON)
	if err != nil {
		return nil, err
	}

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return scheduledJob, err
	}

	return scheduledJob, nil
}

// EnqueueUnique enqueues a job unless a job is already enqueued with the same name and arguments. The already-enqueued job can be in the normal work queue or in the scheduled job queue. Once a worker begins processing a job, another job with the same name and arguments can be enqueued again. Any failed jobs in the retry queue or dead queue don't count against the uniqueness -- so if a job fails and is retried, two unique jobs with the same name and arguments can be enqueued at once.
// In order to add robustness to the system, jobs are only unique for 24 hours after they're enqueued. This is mostly relevant for scheduled jobs.
// EnqueueUnique returns the job if it was enqueued and nil if it wasn't
func (e *Enqueuer) EnqueueUnique(jobName string, args map[string]interface{}) (*Job, error) {
	uniqueKey, err := redisKeyUniqueJob(e.Namespace, jobName, args)
	if err != nil {
		return nil, err
	}

	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
		Unique:     true,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return nil, err
	}

	scriptArgs := make([]interface{}, 0, 3)
	scriptArgs = append(scriptArgs, e.queuePrefix+jobName) // KEY[1]
	scriptArgs = append(scriptArgs, uniqueKey)             // KEY[2]
	scriptArgs = append(scriptArgs, rawJSON)               // ARGV[1]

	res, err := redis.String(e.enqueueUniqueScript.Do(conn, scriptArgs...))
	if res == "ok" && err == nil {
		return job, nil
	}
	return nil, err
}

// EnqueueUniqueIn enqueues a unique job in the scheduled job queue for execution in secondsFromNow seconds. See EnqueueUnique for the semantics of unique jobs.
func (e *Enqueuer) EnqueueUniqueIn(jobName string, secondsFromNow int64, args map[string]interface{}) (*ScheduledJob, error) {
	uniqueKey, err := redisKeyUniqueJob(e.Namespace, jobName, args)
	if err != nil {
		return nil, err
	}

	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
		Unique:     true,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return nil, err
	}

	scheduledJob := &ScheduledJob{
		RunAt: nowEpochSeconds() + secondsFromNow,
		Job:   job,
	}

	scriptArgs := make([]interface{}, 0, 4)
	scriptArgs = append(scriptArgs, redisKeyScheduled(e.Namespace)) // KEY[1]
	scriptArgs = append(scriptArgs, uniqueKey)                      // KEY[2]
	scriptArgs = append(scriptArgs, rawJSON)                        // ARGV[1]
	scriptArgs = append(scriptArgs, scheduledJob.RunAt)             // ARGV[2]

	res, err := redis.String(e.enqueueUniqueInScript.Do(conn, scriptArgs...))

	if res == "ok" && err == nil {
		return scheduledJob, nil
	}
	return nil, err
}

func (e *Enqueuer) addToKnownJobs(conn redis.Conn, jobName string) error {
	needSadd := true
	now := time.Now().Unix()
	t, ok := e.knownJobs[jobName]
	if ok {
		if now < t {
			needSadd = false
		}
	}
	if needSadd {
		if _, err := conn.Do("SADD", redisKeyKnownJobs(e.Namespace), jobName); err != nil {
			return err
		}
		e.knownJobs[jobName] = now + 300
	}

	return nil
}
<commit_msg>BUGFIX: Corrected race condition on concurrent enqueue<commit_after>package work

import (
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
)

// Enqueuer can enqueue jobs.
type Enqueuer struct {
	Namespace string // eg, "myapp-work"
	Pool      *redis.Pool

	queuePrefix           string // eg, "myapp-work:jobs:"
	knownJobs             map[string]int64
	enqueueUniqueScript   *redis.Script
	enqueueUniqueInScript *redis.Script
	mtx                   sync.RWMutex
}

// NewEnqueuer creates a new enqueuer with the specified Redis namespace and Redis pool.
func NewEnqueuer(namespace string, pool *redis.Pool) *Enqueuer {
	if pool == nil {
		panic("NewEnqueuer needs a non-nil *redis.Pool")
	}

	return &Enqueuer{
		Namespace:             namespace,
		Pool:                  pool,
		queuePrefix:           redisKeyJobsPrefix(namespace),
		knownJobs:             make(map[string]int64),
		enqueueUniqueScript:   redis.NewScript(2, redisLuaEnqueueUnique),
		enqueueUniqueInScript: redis.NewScript(2, redisLuaEnqueueUniqueIn),
	}
}

// Enqueue will enqueue the specified job name and arguments. The args param can be nil if no args ar needed.
// Example: e.Enqueue("send_email", work.Q{"addr": "test@example.com"})
func (e *Enqueuer) Enqueue(jobName string, args map[string]interface{}) (*Job, error) {
	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if _, err := conn.Do("LPUSH", e.queuePrefix+jobName, rawJSON); err != nil {
		return nil, err
	}

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return job, err
	}

	return job, nil
}

// EnqueueIn enqueues a job in the scheduled job queue for execution in secondsFromNow seconds.
func (e *Enqueuer) EnqueueIn(jobName string, secondsFromNow int64, args map[string]interface{}) (*ScheduledJob, error) {
	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	scheduledJob := &ScheduledJob{
		RunAt: nowEpochSeconds() + secondsFromNow,
		Job:   job,
	}

	_, err = conn.Do("ZADD", redisKeyScheduled(e.Namespace), scheduledJob.RunAt, rawJSON)
	if err != nil {
		return nil, err
	}

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return scheduledJob, err
	}

	return scheduledJob, nil
}

// EnqueueUnique enqueues a job unless a job is already enqueued with the same name and arguments. The already-enqueued job can be in the normal work queue or in the scheduled job queue. Once a worker begins processing a job, another job with the same name and arguments can be enqueued again. Any failed jobs in the retry queue or dead queue don't count against the uniqueness -- so if a job fails and is retried, two unique jobs with the same name and arguments can be enqueued at once.
// In order to add robustness to the system, jobs are only unique for 24 hours after they're enqueued. This is mostly relevant for scheduled jobs.
// EnqueueUnique returns the job if it was enqueued and nil if it wasn't
func (e *Enqueuer) EnqueueUnique(jobName string, args map[string]interface{}) (*Job, error) {
	uniqueKey, err := redisKeyUniqueJob(e.Namespace, jobName, args)
	if err != nil {
		return nil, err
	}

	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
		Unique:     true,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return nil, err
	}

	scriptArgs := make([]interface{}, 0, 3)
	scriptArgs = append(scriptArgs, e.queuePrefix+jobName) // KEY[1]
	scriptArgs = append(scriptArgs, uniqueKey)             // KEY[2]
	scriptArgs = append(scriptArgs, rawJSON)               // ARGV[1]

	res, err := redis.String(e.enqueueUniqueScript.Do(conn, scriptArgs...))
	if res == "ok" && err == nil {
		return job, nil
	}
	return nil, err
}

// EnqueueUniqueIn enqueues a unique job in the scheduled job queue for execution in secondsFromNow seconds. See EnqueueUnique for the semantics of unique jobs.
func (e *Enqueuer) EnqueueUniqueIn(jobName string, secondsFromNow int64, args map[string]interface{}) (*ScheduledJob, error) {
	uniqueKey, err := redisKeyUniqueJob(e.Namespace, jobName, args)
	if err != nil {
		return nil, err
	}

	job := &Job{
		Name:       jobName,
		ID:         makeIdentifier(),
		EnqueuedAt: nowEpochSeconds(),
		Args:       args,
		Unique:     true,
	}

	rawJSON, err := job.serialize()
	if err != nil {
		return nil, err
	}

	conn := e.Pool.Get()
	defer conn.Close()

	if err := e.addToKnownJobs(conn, jobName); err != nil {
		return nil, err
	}

	scheduledJob := &ScheduledJob{
		RunAt: nowEpochSeconds() + secondsFromNow,
		Job:   job,
	}

	scriptArgs := make([]interface{}, 0, 4)
	scriptArgs = append(scriptArgs, redisKeyScheduled(e.Namespace)) // KEY[1]
	scriptArgs = append(scriptArgs, uniqueKey)                      // KEY[2]
	scriptArgs = append(scriptArgs, rawJSON)                        // ARGV[1]
	scriptArgs = append(scriptArgs, scheduledJob.RunAt)             // ARGV[2]

	res, err := redis.String(e.enqueueUniqueInScript.Do(conn, scriptArgs...))

	if res == "ok" && err == nil {
		return scheduledJob, nil
	}
	return nil, err
}

func (e *Enqueuer) addToKnownJobs(conn redis.Conn, jobName string) error {
	needSadd := true
	now := time.Now().Unix()

	e.mtx.RLock()
	t, ok := e.knownJobs[jobName]
	e.mtx.RUnlock()

	if ok {
		if now < t {
			needSadd = false
		}
	}
	if needSadd {
		if _, err := conn.Do("SADD", redisKeyKnownJobs(e.Namespace), jobName); err != nil {
			return err
		}

		e.mtx.Lock()
		e.knownJobs[jobName] = now + 300
		e.mtx.Unlock()
	}

	return nil
}
<|endoftext|>


<commit_before>package env

import (
	"os"
	"strings"
)

type Env struct{}

const name = "env"

func (self *Env) Name() string {
	return name
}

func (self *Env) Collect() (result interface{}, err error) {
	result, err = self.getEnvironmentVariables()
	return
}

func (self *Env) getEnvironmentVariables() (result map[string]string, err error) {
	result = make(map[string]string)

	for _, env := range os.Environ() {
		pair := strings.SplitN(env, "=", 2)
		if strings.HasPrefix(pair[0], "VERITY_") {
			key := strings.ToLower(strings.SplitAfterN(pair[0], "VERITY_", 2)[1])
			result[key] = pair[1]
		}
	}

	return
}
<commit_msg>Refactor env collector<commit_after>package env

import (
	"os"
	"strings"
)

type Env struct{}

const name = "env"

func (self *Env) Name() string {
	return name
}

func (self *Env) Collect() (result interface{}, err error) {
	result, err = self.getEnvironmentVariables()
	return
}

func (self *Env) getEnvironmentVariables() (envs map[string]string, err error) {
	envs = make(map[string]string)

	for _, env := range os.Environ() {
		pair := strings.SplitN(env, "=", 2)
		if strings.HasPrefix(pair[0], "VERITY_") {
			key := strings.ToLower(strings.SplitAfterN(pair[0], "VERITY_", 2)[1])
			envs[key] = pair[1]
		}
	}

	return
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 config

import (
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	pkgConfig "k8s.io/minikube/pkg/minikube/config" //TODO:Medyagh have consistent naming everywhere pk_config
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/kubeconfig"
	"k8s.io/minikube/pkg/minikube/out"
)

// ProfileCmd represents the profile command
var ProfileCmd = &cobra.Command{
	Use:   "profile [MINIKUBE_PROFILE_NAME].  You can return to the default minikube profile by running `minikube profile default`",
	Short: "Profile gets or sets the current minikube profile",
	Long:  "profile sets the current minikube profile, or gets the current profile if no arguments are provided.  This is used to run and manage multiple minikube instance.  You can return to the default minikube profile by running `minikube profile default`",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			profile := viper.GetString(pkgConfig.MachineProfile)
			out.T(out.Empty, profile)
			os.Exit(0)
		}

		if len(args) > 1 {
			exit.UsageT("usage: minikube profile [MINIKUBE_PROFILE_NAME]")
		}

		profile := args[0]
		if profile == "default" {
			profile = "minikube"
		}

		if !pkgConfig.ProfileExists(profile) {
			err := pkgConfig.CreateEmptyProfile(profile)
			if err != nil {
				exit.WithError("Creating a new profile failed", err)
			}
			out.SuccessT("Created a new profile : {{.profile_name}}", out.V{"profile_name": profile})
		}

		err := Set(pkgConfig.MachineProfile, profile)
		if err != nil {
			exit.WithError("Setting profile failed", err)
		}
		cc, err := pkgConfig.Load()
		// might err when loading older version of cfg file that doesn't have KeepContext field
		if err != nil && !os.IsNotExist(err) {
			out.ErrT(out.Sad, `Error loading profile config: {{.error}}`, out.V{"error": err})
		}
		if err == nil {
			if cc.MachineConfig.KeepContext {
				out.SuccessT("Skipped switching kubectl context for {{.profile_name}} , because --keep-context", out.V{"profile_name": profile})
				out.SuccessT("To connect to this cluster, use: kubectl --context={{.profile_name}}", out.V{"profile_name": profile})
			} else {
				err := kubeconfig.SetCurrentContext(constants.KubeconfigPath, profile)
				if err != nil {
					out.ErrT(out.Sad, `Error while setting kubectl current context :  {{.error}}`, out.V{"error": err})
				}
			}
		}
		out.SuccessT("minikube profile was successfully set to {{.profile_name}}", out.V{"profile_name": profile})
	},
}
<commit_msg>remove TODO comment<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 config

import (
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	pkgConfig "k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/constants"
	"k8s.io/minikube/pkg/minikube/exit"
	"k8s.io/minikube/pkg/minikube/kubeconfig"
	"k8s.io/minikube/pkg/minikube/out"
)

// ProfileCmd represents the profile command
var ProfileCmd = &cobra.Command{
	Use:   "profile [MINIKUBE_PROFILE_NAME].  You can return to the default minikube profile by running `minikube profile default`",
	Short: "Profile gets or sets the current minikube profile",
	Long:  "profile sets the current minikube profile, or gets the current profile if no arguments are provided.  This is used to run and manage multiple minikube instance.  You can return to the default minikube profile by running `minikube profile default`",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			profile := viper.GetString(pkgConfig.MachineProfile)
			out.T(out.Empty, profile)
			os.Exit(0)
		}

		if len(args) > 1 {
			exit.UsageT("usage: minikube profile [MINIKUBE_PROFILE_NAME]")
		}

		profile := args[0]
		if profile == "default" {
			profile = "minikube"
		}

		if !pkgConfig.ProfileExists(profile) {
			err := pkgConfig.CreateEmptyProfile(profile)
			if err != nil {
				exit.WithError("Creating a new profile failed", err)
			}
			out.SuccessT("Created a new profile : {{.profile_name}}", out.V{"profile_name": profile})
		}

		err := Set(pkgConfig.MachineProfile, profile)
		if err != nil {
			exit.WithError("Setting profile failed", err)
		}
		cc, err := pkgConfig.Load()
		// might err when loading older version of cfg file that doesn't have KeepContext field
		if err != nil && !os.IsNotExist(err) {
			out.ErrT(out.Sad, `Error loading profile config: {{.error}}`, out.V{"error": err})
		}
		if err == nil {
			if cc.MachineConfig.KeepContext {
				out.SuccessT("Skipped switching kubectl context for {{.profile_name}} , because --keep-context", out.V{"profile_name": profile})
				out.SuccessT("To connect to this cluster, use: kubectl --context={{.profile_name}}", out.V{"profile_name": profile})
			} else {
				err := kubeconfig.SetCurrentContext(constants.KubeconfigPath, profile)
				if err != nil {
					out.ErrT(out.Sad, `Error while setting kubectl current context :  {{.error}}`, out.V{"error": err})
				}
			}
		}
		out.SuccessT("minikube profile was successfully set to {{.profile_name}}", out.V{"profile_name": profile})
	},
}
<|endoftext|>


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

// This file implements string-to-Float conversion functions.

package big

import (
	"fmt"
	"io"
	"strings"
)

var floatZero Float

// SetString sets z to the value of s and returns z and a boolean indicating
// success. s must be a floating-point number of the same format as accepted
// by Parse, with base argument 0. The entire string (not just a prefix) must
// be valid for success. If the operation failed, the value of z is undefined
// but the returned value is nil.
func (z *Float) SetString(s string) (*Float, bool) {
	if f, _, err := z.Parse(s, 0); err == nil {
		return f, true
	}
	return nil, false
}

// scan is like Parse but reads the longest possible prefix representing a valid
// floating point number from an io.ByteScanner rather than a string. It serves
// as the implementation of Parse. It does not recognize ±Inf and does not expect
// EOF at the end.
func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
	prec := z.prec
	if prec == 0 {
		prec = 64
	}

	// A reasonable value in case of an error.
	z.form = zero

	// sign
	z.neg, err = scanSign(r)
	if err != nil {
		return
	}

	// mantissa
	var fcount int // fractional digit count; valid if <= 0
	z.mant, b, fcount, err = z.mant.scan(r, base, true)
	if err != nil {
		return
	}

	// exponent
	var exp int64
	var ebase int
	exp, ebase, err = scanExponent(r, true)
	if err != nil {
		return
	}

	// special-case 0
	if len(z.mant) == 0 {
		z.prec = prec
		z.acc = Exact
		z.form = zero
		f = z
		return
	}
	// len(z.mant) > 0

	// The mantissa may have a decimal point (fcount <= 0) and there
	// may be a nonzero exponent exp. The decimal point amounts to a
	// division by b**(-fcount). An exponent means multiplication by
	// ebase**exp. Finally, mantissa normalization (shift left) requires
	// a correcting multiplication by 2**(-shiftcount). Multiplications
	// are commutative, so we can apply them in any order as long as there
	// is no loss of precision. We only have powers of 2 and 10, and
	// we split powers of 10 into the product of the same powers of
	// 2 and 5. This reduces the size of the multiplication factor
	// needed for base-10 exponents.

	// normalize mantissa and determine initial exponent contributions
	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
	exp5 := int64(0)

	// determine binary or decimal exponent contribution of decimal point
	if fcount < 0 {
		// The mantissa has a "decimal" point ddd.dddd; and
		// -fcount is the number of digits to the right of '.'.
		// Adjust relevant exponent accordingly.
		d := int64(fcount)
		switch b {
		case 10:
			exp5 = d
			fallthrough // 10**e == 5**e * 2**e
		case 2:
			exp2 += d
		case 16:
			exp2 += d * 4 // hexadecimal digits are 4 bits each
		default:
			panic("unexpected mantissa base")
		}
		// fcount consumed - not needed anymore
	}

	// take actual exponent into account
	switch ebase {
	case 10:
		exp5 += exp
		fallthrough
	case 2:
		exp2 += exp
	default:
		panic("unexpected exponent base")
	}
	// exp consumed - not needed anymore

	// apply 2**exp2
	if MinExp <= exp2 && exp2 <= MaxExp {
		z.prec = prec
		z.form = finite
		z.exp = int32(exp2)
		f = z
	} else {
		err = fmt.Errorf("exponent overflow")
		return
	}

	if exp5 == 0 {
		// no decimal exponent contribution
		z.round(0)
		return
	}
	// exp5 != 0

	// apply 5**exp5
	p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
	if exp5 < 0 {
		z.Quo(z, p.pow5(uint64(-exp5)))
	} else {
		z.Mul(z, p.pow5(uint64(exp5)))
	}

	return
}

// These powers of 5 fit into a uint64.
//
//	for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
//		fmt.Println(q)
//	}
//
var pow5tab = [...]uint64{
	1,
	5,
	25,
	125,
	625,
	3125,
	15625,
	78125,
	390625,
	1953125,
	9765625,
	48828125,
	244140625,
	1220703125,
	6103515625,
	30517578125,
	152587890625,
	762939453125,
	3814697265625,
	19073486328125,
	95367431640625,
	476837158203125,
	2384185791015625,
	11920928955078125,
	59604644775390625,
	298023223876953125,
	1490116119384765625,
	7450580596923828125,
}

// pow5 sets z to 5**n and returns z.
// n must not be negative.
func (z *Float) pow5(n uint64) *Float {
	const m = uint64(len(pow5tab) - 1)
	if n <= m {
		return z.SetUint64(pow5tab[n])
	}
	// n > m

	z.SetUint64(pow5tab[m])
	n -= m

	// use more bits for f than for z
	// TODO(gri) what is the right number?
	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)

	for n > 0 {
		if n&1 != 0 {
			z.Mul(z, f)
		}
		f.Mul(f, f)
		n >>= 1
	}

	return z
}

// Parse parses s which must contain a text representation of a floating-
// point number with a mantissa in the given conversion base (the exponent
// is always a decimal number), or a string representing an infinite value.
//
// It sets z to the (possibly rounded) value of the corresponding floating-
// point value, and returns z, the actual base b, and an error err, if any.
// The entire string (not just a prefix) must be consumed for success.
// If z's precision is 0, it is changed to 64 before rounding takes effect.
// The number must be of the form:
//
//	number   = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
//	sign     = "+" | "-" .
//      prefix   = "0" ( "x" | "X" | "b" | "B" ) .
//	mantissa = digits | digits "." [ digits ] | "." digits .
//	exponent = ( "E" | "e" | "p" ) [ sign ] digits .
//	digits   = digit { digit } .
//	digit    = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
//      infinity = [ sign ] ( "inf" | "Inf" ) .
//
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
// argument will lead to a run-time panic.
//
// For base 0, the number prefix determines the actual base: A prefix of
// "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
// base 2; otherwise, the actual base is 10 and no prefix is accepted.
// The octal prefix "0" is not supported (a leading "0" is simply
// considered a "0").
//
// A "p" exponent indicates a binary (rather then decimal) exponent;
// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
// maximum float64 value. For hexadecimal mantissae, the exponent must
// be binary, if present (an "e" or "E" exponent indicator cannot be
// distinguished from a mantissa digit).
//
// The returned *Float f is nil and the value of z is valid but not
// defined if an error is reported.
//
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
	// scan doesn't handle ±Inf
	if len(s) == 3 && (s == "Inf" || s == "inf") {
		f = z.SetInf(false)
		return
	}
	if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
		f = z.SetInf(s[0] == '-')
		return
	}

	r := strings.NewReader(s)
	if f, b, err = z.scan(r, base); err != nil {
		return
	}

	// entire string must have been consumed
	if ch, err2 := r.ReadByte(); err2 == nil {
		err = fmt.Errorf("expected end of string, found %q", ch)
	} else if err2 != io.EOF {
		err = err2
	}

	return
}

// ParseFloat is like f.Parse(s, base) with f set to the given precision
// and rounding mode.
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
	return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}

var _ fmt.Scanner = &floatZero // *Float must implement fmt.Scanner

// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts formats whose verbs are supported by
// fmt.Scan for floating point values, which are:
// 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'.
// Scan doesn't handle ±Inf.
func (z *Float) Scan(s fmt.ScanState, ch rune) error {
	s.SkipSpace()
	_, _, err := z.scan(byteReader{s}, 0)
	return err
}
<commit_msg>math/big: fix alignment in Float.Parse docs<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements string-to-Float conversion functions.

package big

import (
	"fmt"
	"io"
	"strings"
)

var floatZero Float

// SetString sets z to the value of s and returns z and a boolean indicating
// success. s must be a floating-point number of the same format as accepted
// by Parse, with base argument 0. The entire string (not just a prefix) must
// be valid for success. If the operation failed, the value of z is undefined
// but the returned value is nil.
func (z *Float) SetString(s string) (*Float, bool) {
	if f, _, err := z.Parse(s, 0); err == nil {
		return f, true
	}
	return nil, false
}

// scan is like Parse but reads the longest possible prefix representing a valid
// floating point number from an io.ByteScanner rather than a string. It serves
// as the implementation of Parse. It does not recognize ±Inf and does not expect
// EOF at the end.
func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
	prec := z.prec
	if prec == 0 {
		prec = 64
	}

	// A reasonable value in case of an error.
	z.form = zero

	// sign
	z.neg, err = scanSign(r)
	if err != nil {
		return
	}

	// mantissa
	var fcount int // fractional digit count; valid if <= 0
	z.mant, b, fcount, err = z.mant.scan(r, base, true)
	if err != nil {
		return
	}

	// exponent
	var exp int64
	var ebase int
	exp, ebase, err = scanExponent(r, true)
	if err != nil {
		return
	}

	// special-case 0
	if len(z.mant) == 0 {
		z.prec = prec
		z.acc = Exact
		z.form = zero
		f = z
		return
	}
	// len(z.mant) > 0

	// The mantissa may have a decimal point (fcount <= 0) and there
	// may be a nonzero exponent exp. The decimal point amounts to a
	// division by b**(-fcount). An exponent means multiplication by
	// ebase**exp. Finally, mantissa normalization (shift left) requires
	// a correcting multiplication by 2**(-shiftcount). Multiplications
	// are commutative, so we can apply them in any order as long as there
	// is no loss of precision. We only have powers of 2 and 10, and
	// we split powers of 10 into the product of the same powers of
	// 2 and 5. This reduces the size of the multiplication factor
	// needed for base-10 exponents.

	// normalize mantissa and determine initial exponent contributions
	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
	exp5 := int64(0)

	// determine binary or decimal exponent contribution of decimal point
	if fcount < 0 {
		// The mantissa has a "decimal" point ddd.dddd; and
		// -fcount is the number of digits to the right of '.'.
		// Adjust relevant exponent accordingly.
		d := int64(fcount)
		switch b {
		case 10:
			exp5 = d
			fallthrough // 10**e == 5**e * 2**e
		case 2:
			exp2 += d
		case 16:
			exp2 += d * 4 // hexadecimal digits are 4 bits each
		default:
			panic("unexpected mantissa base")
		}
		// fcount consumed - not needed anymore
	}

	// take actual exponent into account
	switch ebase {
	case 10:
		exp5 += exp
		fallthrough
	case 2:
		exp2 += exp
	default:
		panic("unexpected exponent base")
	}
	// exp consumed - not needed anymore

	// apply 2**exp2
	if MinExp <= exp2 && exp2 <= MaxExp {
		z.prec = prec
		z.form = finite
		z.exp = int32(exp2)
		f = z
	} else {
		err = fmt.Errorf("exponent overflow")
		return
	}

	if exp5 == 0 {
		// no decimal exponent contribution
		z.round(0)
		return
	}
	// exp5 != 0

	// apply 5**exp5
	p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
	if exp5 < 0 {
		z.Quo(z, p.pow5(uint64(-exp5)))
	} else {
		z.Mul(z, p.pow5(uint64(exp5)))
	}

	return
}

// These powers of 5 fit into a uint64.
//
//	for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
//		fmt.Println(q)
//	}
//
var pow5tab = [...]uint64{
	1,
	5,
	25,
	125,
	625,
	3125,
	15625,
	78125,
	390625,
	1953125,
	9765625,
	48828125,
	244140625,
	1220703125,
	6103515625,
	30517578125,
	152587890625,
	762939453125,
	3814697265625,
	19073486328125,
	95367431640625,
	476837158203125,
	2384185791015625,
	11920928955078125,
	59604644775390625,
	298023223876953125,
	1490116119384765625,
	7450580596923828125,
}

// pow5 sets z to 5**n and returns z.
// n must not be negative.
func (z *Float) pow5(n uint64) *Float {
	const m = uint64(len(pow5tab) - 1)
	if n <= m {
		return z.SetUint64(pow5tab[n])
	}
	// n > m

	z.SetUint64(pow5tab[m])
	n -= m

	// use more bits for f than for z
	// TODO(gri) what is the right number?
	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)

	for n > 0 {
		if n&1 != 0 {
			z.Mul(z, f)
		}
		f.Mul(f, f)
		n >>= 1
	}

	return z
}

// Parse parses s which must contain a text representation of a floating-
// point number with a mantissa in the given conversion base (the exponent
// is always a decimal number), or a string representing an infinite value.
//
// It sets z to the (possibly rounded) value of the corresponding floating-
// point value, and returns z, the actual base b, and an error err, if any.
// The entire string (not just a prefix) must be consumed for success.
// If z's precision is 0, it is changed to 64 before rounding takes effect.
// The number must be of the form:
//
//	number   = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
//	sign     = "+" | "-" .
//	prefix   = "0" ( "x" | "X" | "b" | "B" ) .
//	mantissa = digits | digits "." [ digits ] | "." digits .
//	exponent = ( "E" | "e" | "p" ) [ sign ] digits .
//	digits   = digit { digit } .
//	digit    = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
//	infinity = [ sign ] ( "inf" | "Inf" ) .
//
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
// argument will lead to a run-time panic.
//
// For base 0, the number prefix determines the actual base: A prefix of
// "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
// base 2; otherwise, the actual base is 10 and no prefix is accepted.
// The octal prefix "0" is not supported (a leading "0" is simply
// considered a "0").
//
// A "p" exponent indicates a binary (rather then decimal) exponent;
// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
// maximum float64 value. For hexadecimal mantissae, the exponent must
// be binary, if present (an "e" or "E" exponent indicator cannot be
// distinguished from a mantissa digit).
//
// The returned *Float f is nil and the value of z is valid but not
// defined if an error is reported.
//
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
	// scan doesn't handle ±Inf
	if len(s) == 3 && (s == "Inf" || s == "inf") {
		f = z.SetInf(false)
		return
	}
	if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
		f = z.SetInf(s[0] == '-')
		return
	}

	r := strings.NewReader(s)
	if f, b, err = z.scan(r, base); err != nil {
		return
	}

	// entire string must have been consumed
	if ch, err2 := r.ReadByte(); err2 == nil {
		err = fmt.Errorf("expected end of string, found %q", ch)
	} else if err2 != io.EOF {
		err = err2
	}

	return
}

// ParseFloat is like f.Parse(s, base) with f set to the given precision
// and rounding mode.
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
	return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}

var _ fmt.Scanner = &floatZero // *Float must implement fmt.Scanner

// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts formats whose verbs are supported by
// fmt.Scan for floating point values, which are:
// 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'.
// Scan doesn't handle ±Inf.
func (z *Float) Scan(s fmt.ScanState, ch rune) error {
	s.SkipSpace()
	_, _, err := z.scan(byteReader{s}, 0)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"flag"

	"sync"

	"math/rand"
	"time"

	"github.com/xiaonanln/goTimer"
	"github.com/xiaonanln/goworld/config"
)

const (
	NR_CLIENTS     = 1
	SPACE_KIND_MIN = 1
	SPACE_KIND_MAX = 100
)

var (
	configFile string
)

func parseArgs() {
	flag.StringVar(&configFile, "configfile", "", "set config file path")
	flag.Parse()
}

func main() {
	rand.Seed(time.Now().UnixNano())
	parseArgs()
	if configFile != "" {
		config.SetConfigFile(configFile)
	}

	var wait sync.WaitGroup
	wait.Add(NR_CLIENTS)
	for i := 0; i < NR_CLIENTS; i++ {
		bot := newClientBot(i+1, &wait)
		go bot.run()
	}
	timer.StartTicks(time.Millisecond * 100)
	wait.Wait()
}
<commit_msg>multi-threads for spaces<commit_after>package main

import (
	"flag"

	"sync"

	"math/rand"
	"time"

	"github.com/xiaonanln/goTimer"
	"github.com/xiaonanln/goworld/config"
)

const (
	NR_CLIENTS     = 10
	SPACE_KIND_MIN = 1
	SPACE_KIND_MAX = 100
)

var (
	configFile string
)

func parseArgs() {
	flag.StringVar(&configFile, "configfile", "", "set config file path")
	flag.Parse()
}

func main() {
	rand.Seed(time.Now().UnixNano())
	parseArgs()
	if configFile != "" {
		config.SetConfigFile(configFile)
	}

	var wait sync.WaitGroup
	wait.Add(NR_CLIENTS)
	for i := 0; i < NR_CLIENTS; i++ {
		bot := newClientBot(i+1, &wait)
		go bot.run()
	}
	timer.StartTicks(time.Millisecond * 100)
	wait.Wait()
}
<|endoftext|>


<commit_before>package gobot

type eventChannel chan *Event

type eventer struct {
	// map of valid Event names
	eventnames map[string]string

	// new events get put in to the event channel
	in eventChannel

	// slice of out channels used by subscribers
	outs []eventChannel
}

// Eventer is the interface which describes how a Driver or Adaptor
// handles events.
type Eventer interface {
	// Events returns the map of valid Event names.
	Events() (eventnames map[string]string)
	// Event returns an event string from map of valid Event names.
	// Mostly used to validate that an Event name is valid.
	Event(name string) string
	// AddEvent registers a new Event name.
	AddEvent(name string)
	// DeleteEvent removes a previously registered Event name.
	DeleteEvent(name string)
	// Publish new events to anyone listening
	Publish(name string, data interface{})
	// Subscribe to any events from this eventer
	Subscribe() (events eventChannel)
	// Event handler
	On(name string, f func(s interface{})) (err error)
	// Event handler, only exectues one time
	Once(name string, f func(s interface{})) (err error)
}

// NewEventer returns a new Eventer.
func NewEventer() Eventer {
	evtr := &eventer{
		eventnames: make(map[string]string),
		in:         make(eventChannel, 1),
		outs:       make([]eventChannel, 1),
	}

	// goroutine to cascade in events to all out event channels
	go func() {
		for {
			select {
			case evt := <-evtr.in:
				for _, out := range evtr.outs[1:] {
					out <- evt
				}
			}
		}
	}()

	return evtr
}

func (e *eventer) Events() map[string]string {
	return e.eventnames
}

func (e *eventer) Event(name string) string {
	return e.eventnames[name]
}

func (e *eventer) AddEvent(name string) {
	e.eventnames[name] = name
}

func (e *eventer) DeleteEvent(name string) {
	delete(e.eventnames, name)
}

func (e *eventer) Publish(name string, data interface{}) {
	evt := NewEvent(name, data)
	e.in <- evt
}

func (e *eventer) Subscribe() eventChannel {
	out := make(eventChannel)
	e.outs = append(e.outs, out)
	return out
}

// On executes f when e is Published to. Returns ErrUnknownEvent if Event
// does not exist.
func (e *eventer) On(n string, f func(s interface{})) (err error) {
	out := e.Subscribe()
	go func() {
		for {
			select {
			case evt := <-out:
				if evt.Name == n {
					f(evt.Data)
				}
			}
		}
	}()

	return
}

// Once is similar to On except that it only executes f one time. Returns
//ErrUnknownEvent if Event does not exist.
func (e *eventer) Once(n string, f func(s interface{})) (err error) {
	out := e.Subscribe()
	go func() {
		for {
			select {
			case evt := <-out:
				if evt.Name == n {
					f(evt.Data)
					break
				}
			}
		}
	}()

	return
}
<commit_msg>core: cleanup comments on Eventer interface<commit_after>package gobot

type eventChannel chan *Event

type eventer struct {
	// map of valid Event names
	eventnames map[string]string

	// new events get put in to the event channel
	in eventChannel

	// slice of out channels used by subscribers
	outs []eventChannel
}

// Eventer is the interface which describes how a Driver or Adaptor
// handles events.
type Eventer interface {
	// Events returns the map of valid Event names.
	Events() (eventnames map[string]string)
	// Event returns an Event string from map of valid Event names.
	// Mostly used to validate that an Event name is valid.
	Event(name string) string
	// AddEvent registers a new Event name.
	AddEvent(name string)
	// DeleteEvent removes a previously registered Event name.
	DeleteEvent(name string)
	// Publish new events to anyone listening
	Publish(name string, data interface{})
	// Subscribe to any events from this eventer
	Subscribe() (events eventChannel)
	// Event handler
	On(name string, f func(s interface{})) (err error)
	// Event handler, only exectues one time
	Once(name string, f func(s interface{})) (err error)
}

// NewEventer returns a new Eventer.
func NewEventer() Eventer {
	evtr := &eventer{
		eventnames: make(map[string]string),
		in:         make(eventChannel, 1),
		outs:       make([]eventChannel, 1),
	}

	// goroutine to cascade in events to all out event channels
	go func() {
		for {
			select {
			case evt := <-evtr.in:
				for _, out := range evtr.outs[1:] {
					out <- evt
				}
			}
		}
	}()

	return evtr
}

func (e *eventer) Events() map[string]string {
	return e.eventnames
}

func (e *eventer) Event(name string) string {
	return e.eventnames[name]
}

func (e *eventer) AddEvent(name string) {
	e.eventnames[name] = name
}

func (e *eventer) DeleteEvent(name string) {
	delete(e.eventnames, name)
}

func (e *eventer) Publish(name string, data interface{}) {
	evt := NewEvent(name, data)
	e.in <- evt
}

func (e *eventer) Subscribe() eventChannel {
	out := make(eventChannel)
	e.outs = append(e.outs, out)
	return out
}

// On executes f when e is Published to. Returns ErrUnknownEvent if Event
// does not exist.
func (e *eventer) On(n string, f func(s interface{})) (err error) {
	out := e.Subscribe()
	go func() {
		for {
			select {
			case evt := <-out:
				if evt.Name == n {
					f(evt.Data)
				}
			}
		}
	}()

	return
}

// Once is similar to On except that it only executes f one time. Returns
//ErrUnknownEvent if Event does not exist.
func (e *eventer) Once(n string, f func(s interface{})) (err error) {
	out := e.Subscribe()
	go func() {
		for {
			select {
			case evt := <-out:
				if evt.Name == n {
					f(evt.Data)
					break
				}
			}
		}
	}()

	return
}
<|endoftext|>


<commit_before><commit_msg>implemented the TestHackerone function<commit_after>package sources

import (
	"testing"

	"github.com/OWASP/Amass/requests"
	"github.com/OWASP/Amass/resolvers"
)

func TestHackerone(t *testing.T) {
	if *networkTest == false || *configPath == "" {
		return
	}

	domainTest = "twitter.com"

	cfg := setupConfig(domainTest)

	bus, out := setupEventBus(requests.NewNameTopic)
	defer bus.Stop()

	pool := resolvers.NewResolverPool(nil)
	defer pool.Stop()

	srv := NewHackerOne(cfg, bus, pool)

	result := testService(srv, out)
	if result < expectedTest {
		t.Errorf("Found %d names, expected at least %d instead", result, expectedTest)
	}
}<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"time"
)

const (
	EXPIRY_DELAY   = time.Hour * 8
	UP_POOL_SIZE   = 1
	DOWN_POOL_SIZE = 1
)

// Router represents a concrete router of TTN architecture. Use the New() method to create a new
// one and then connect it to its adapters.
type Router struct {
	brokers       []core.BrokerAddress // Brokers known by the router
	Logger        log.Logger           // Specify a logger for the router. NOTE Having this exported isn't thread-safe.
	addressKeeper addressKeeper        // Local storage that maps end-device addresses to broker addresses
	up            chan upMsg           // Internal communication channel which sends data to the up adapter
	down          chan downMsg         // Internal communication channel which sends data to the down adapter
}

// upMsg materializes messages that flow along the up channel
type upMsg struct {
	packet  semtech.Packet      // The packet to transfer
	gateway core.GatewayAddress // The recipient gateway to reach
}

// downMsg materializes messages that flow along the down channel
type downMsg struct {
	payload semtech.Payload      // The payload to transfer
	brokers []core.BrokerAddress // The recipient broker to reach. If nil or empty, assume that all broker should be reached
}

// NewRouter constructs a Router and setup its internal structure
func NewRouter(brokers ...core.BrokerAddress) (*Router, error) {
	localDB, err := NewLocalDB(EXPIRY_DELAY)

	if err != nil {
		return nil, err
	}

	if len(brokers) == 0 {
		return nil, fmt.Errorf("The router should be connected to at least one broker")
	}

	return &Router{
		brokers:       brokers,
		addressKeeper: localDB,
		up:            make(chan upMsg),
		down:          make(chan downMsg),
		Logger:        log.VoidLogger{},
	}, nil
}

// HandleUplink implements the core.Router interface
func (r *Router) HandleUplink(packet semtech.Packet, gateway core.GatewayAddress) {
	r.ensure()

	switch packet.Identifier {
	case semtech.PULL_DATA:
		r.log("receives PULL_DATA, sending ack")
		r.up <- upMsg{
			packet: semtech.Packet{
				Version:    semtech.VERSION,
				Identifier: semtech.PULL_ACK,
				Token:      packet.Token,
			},
			gateway: gateway,
		}
	case semtech.PUSH_DATA:
		// 1. Send an ack
		r.log("receives PUSH_DATA, sending ack")
		r.up <- upMsg{
			packet: semtech.Packet{
				Version:    semtech.VERSION,
				Identifier: semtech.PUSH_ACK,
				Token:      packet.Token,
			},
			gateway: gateway,
		}

		// 2. Determine payloads related to different end-devices present in the packet
		// NOTE So far, Stats are ignored.
		if packet.Payload == nil || len(packet.Payload.RXPK) == 0 {
			r.log("Ignores inconsistent PUSH_DATA packet")
			return
		}

		payloads := make(map[semtech.DeviceAddress]*semtech.Payload)
		for _, rxpk := range packet.Payload.RXPK {
			devAddr := rxpk.DevAddr()
			if devAddr == nil {
				r.log("Unable to determine end-device address for rxpk: %+v", rxpk)
				continue
			}

			if _, ok := payloads[*devAddr]; !ok {
				payloads[*devAddr] = &semtech.Payload{
					RXPK: make([]semtech.RXPK, 0),
				}
			}

			payload := payloads[*devAddr]
			(*payload).RXPK = append(payloads[*devAddr].RXPK, rxpk)
		}

		// 3. Broadcast or Forward payloads depending wether or not the brokers are known
		for devAddr, payload := range payloads {
			brokers, err := r.addressKeeper.lookup(devAddr)
			if err != nil {
				r.log("Forward payload to known brokers %+v", payload)
				r.down <- downMsg{
					payload: *payload,
					brokers: brokers,
				}
				continue
			}

			r.log("Broadcast payload to all brokers %+v", payload)
			r.down <- downMsg{payload: *payload}
		}
	default:
		r.log("Unexpected packet receive from uplink %+v", packet)

	}
}

// HandleDownlink implements the core.Router interface
func (r *Router) HandleDownlink(payload semtech.Payload, broker core.BrokerAddress) {
	// TODO MileStone 4
}

// RegisterDevice implements the core.Router interface
func (r *Router) RegisterDevice(devAddr semtech.DeviceAddress, broAddrs ...core.BrokerAddress) {
	r.ensure()
	r.addressKeeper.store(devAddr, broAddrs...) // TODO handle the error
}

// RegisterDevice implements the core.Router interface
func (r *Router) HandleError(err interface{}) {
	r.ensure()

	switch err.(type) {
	case core.ErrAck:
	case core.ErrDownlink:
	case core.ErrForward:
	case core.ErrBroadcast:
	case core.ErrUplink:
	default:
		fmt.Println(err) // Wow, much handling, very reliable
	}
}

// Connect implements the core.Router interface
func (r *Router) Connect(upAdapter core.GatewayRouterAdapter, downAdapter core.RouterBrokerAdapter) {
	r.ensure()

	for i := 0; i < UP_POOL_SIZE; i += 1 {
		go r.connectUpAdapter(upAdapter)
	}

	for i := 0; i < DOWN_POOL_SIZE; i += 1 {
		go r.connectDownAdapter(downAdapter)
	}
}

// Consume messages sent to r.up channel
func (r *Router) connectUpAdapter(upAdapter core.GatewayRouterAdapter) {
	for msg := range r.up {
		upAdapter.Ack(r, msg.packet, msg.gateway)
	}
}

// Consume messages sent to r.down channel
func (r *Router) connectDownAdapter(downAdapter core.RouterBrokerAdapter) {
	for msg := range r.down {
		if len(msg.brokers) == 0 {
			downAdapter.Broadcast(r, msg.payload, r.brokers...)
			continue
		}
		downAdapter.Forward(r, msg.payload, msg.brokers...)
	}
}

// ensure checks whether or not the current Router has been created via New(). It panics if not.
func (r *Router) ensure() {
	if r == nil || r.addressKeeper == nil {
		panic("Call method on non-initialized Router")
	}
}

// log is a shortcut to access the router logger
func (r *Router) log(format string, a ...interface{}) {
	if r.Logger == nil {
		return
	}
	r.Logger.Log(format, a...)
}
<commit_msg>[router] Remove old references to errors in router<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package components

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"time"
)

const (
	EXPIRY_DELAY   = time.Hour * 8
	UP_POOL_SIZE   = 1
	DOWN_POOL_SIZE = 1
)

// Router represents a concrete router of TTN architecture. Use the New() method to create a new
// one and then connect it to its adapters.
type Router struct {
	brokers       []core.BrokerAddress // Brokers known by the router
	Logger        log.Logger           // Specify a logger for the router. NOTE Having this exported isn't thread-safe.
	addressKeeper addressKeeper        // Local storage that maps end-device addresses to broker addresses
	up            chan upMsg           // Internal communication channel which sends data to the up adapter
	down          chan downMsg         // Internal communication channel which sends data to the down adapter
}

// upMsg materializes messages that flow along the up channel
type upMsg struct {
	packet  semtech.Packet      // The packet to transfer
	gateway core.GatewayAddress // The recipient gateway to reach
}

// downMsg materializes messages that flow along the down channel
type downMsg struct {
	payload semtech.Payload      // The payload to transfer
	brokers []core.BrokerAddress // The recipient broker to reach. If nil or empty, assume that all broker should be reached
}

// NewRouter constructs a Router and setup its internal structure
func NewRouter(brokers ...core.BrokerAddress) (*Router, error) {
	localDB, err := NewLocalDB(EXPIRY_DELAY)

	if err != nil {
		return nil, err
	}

	if len(brokers) == 0 {
		return nil, fmt.Errorf("The router should be connected to at least one broker")
	}

	return &Router{
		brokers:       brokers,
		addressKeeper: localDB,
		up:            make(chan upMsg),
		down:          make(chan downMsg),
		Logger:        log.VoidLogger{},
	}, nil
}

// HandleUplink implements the core.Router interface
func (r *Router) HandleUplink(packet semtech.Packet, gateway core.GatewayAddress) {
	r.ensure()

	switch packet.Identifier {
	case semtech.PULL_DATA:
		r.log("receives PULL_DATA, sending ack")
		r.up <- upMsg{
			packet: semtech.Packet{
				Version:    semtech.VERSION,
				Identifier: semtech.PULL_ACK,
				Token:      packet.Token,
			},
			gateway: gateway,
		}
	case semtech.PUSH_DATA:
		// 1. Send an ack
		r.log("receives PUSH_DATA, sending ack")
		r.up <- upMsg{
			packet: semtech.Packet{
				Version:    semtech.VERSION,
				Identifier: semtech.PUSH_ACK,
				Token:      packet.Token,
			},
			gateway: gateway,
		}

		// 2. Determine payloads related to different end-devices present in the packet
		// NOTE So far, Stats are ignored.
		if packet.Payload == nil || len(packet.Payload.RXPK) == 0 {
			r.log("Ignores inconsistent PUSH_DATA packet")
			return
		}

		payloads := make(map[semtech.DeviceAddress]*semtech.Payload)
		for _, rxpk := range packet.Payload.RXPK {
			devAddr := rxpk.DevAddr()
			if devAddr == nil {
				r.log("Unable to determine end-device address for rxpk: %+v", rxpk)
				continue
			}

			if _, ok := payloads[*devAddr]; !ok {
				payloads[*devAddr] = &semtech.Payload{
					RXPK: make([]semtech.RXPK, 0),
				}
			}

			payload := payloads[*devAddr]
			(*payload).RXPK = append(payloads[*devAddr].RXPK, rxpk)
		}

		// 3. Broadcast or Forward payloads depending wether or not the brokers are known
		for devAddr, payload := range payloads {
			brokers, err := r.addressKeeper.lookup(devAddr)
			if err != nil {
				r.log("Forward payload to known brokers %+v", payload)
				r.down <- downMsg{
					payload: *payload,
					brokers: brokers,
				}
				continue
			}

			r.log("Broadcast payload to all brokers %+v", payload)
			r.down <- downMsg{payload: *payload}
		}
	default:
		r.log("Unexpected packet receive from uplink %+v", packet)

	}
}

// HandleDownlink implements the core.Router interface
func (r *Router) HandleDownlink(payload semtech.Payload, broker core.BrokerAddress) {
	// TODO MileStone 4
}

// RegisterDevice implements the core.Router interface
func (r *Router) RegisterDevice(devAddr semtech.DeviceAddress, broAddrs ...core.BrokerAddress) {
	r.ensure()
	r.addressKeeper.store(devAddr, broAddrs...) // TODO handle the error
}

// RegisterDevice implements the core.Router interface
func (r *Router) HandleError(err interface{}) {
	r.ensure()

	switch err.(type) {
	default:
		fmt.Println(err) // Wow, much handling, very reliable
	}
}

// Connect implements the core.Router interface
func (r *Router) Connect(upAdapter core.GatewayRouterAdapter, downAdapter core.RouterBrokerAdapter) {
	r.ensure()

	for i := 0; i < UP_POOL_SIZE; i += 1 {
		go r.connectUpAdapter(upAdapter)
	}

	for i := 0; i < DOWN_POOL_SIZE; i += 1 {
		go r.connectDownAdapter(downAdapter)
	}
}

// Consume messages sent to r.up channel
func (r *Router) connectUpAdapter(upAdapter core.GatewayRouterAdapter) {
	for msg := range r.up {
		upAdapter.Ack(r, msg.packet, msg.gateway)
	}
}

// Consume messages sent to r.down channel
func (r *Router) connectDownAdapter(downAdapter core.RouterBrokerAdapter) {
	for msg := range r.down {
		if len(msg.brokers) == 0 {
			downAdapter.Broadcast(r, msg.payload, r.brokers...)
			continue
		}
		downAdapter.Forward(r, msg.payload, msg.brokers...)
	}
}

// ensure checks whether or not the current Router has been created via New(). It panics if not.
func (r *Router) ensure() {
	if r == nil || r.addressKeeper == nil {
		panic("Call method on non-initialized Router")
	}
}

// log is a shortcut to access the router logger
func (r *Router) log(format string, a ...interface{}) {
	if r.Logger == nil {
		return
	}
	r.Logger.Log(format, a...)
}
<|endoftext|>


<commit_before>// Wrapper around rollbar.com api.
package rollbar

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const v1Endpoint = "https://api.rollbar.com/api/1"

type Client struct {
	HttpClient *http.Client
	Token      string
	Endpoint   *url.URL
}

func NewClient(token string) *Client {
	rel, err := url.Parse(v1Endpoint)
	if err != nil {
		panic(err)
	}

	client := &Client{
		HttpClient: http.DefaultClient,
		Token:      token,
		Endpoint:   rel,
	}

	return client
}

func (c *Client) Request(verb, url string) (io.ReadCloser, error) {
	url = c.BuildUrl(url)
	req, err := http.NewRequest(verb, url, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.HttpClient.Do(req)
	if err != nil {
		return nil, err
	}

	return resp.Body, nil
}

func (c *Client) BuildUrl(url string) string {
	return fmt.Sprintf("%v/%v?access_token=%v", c.Endpoint, url, c.Token)
}
<commit_msg>rollbar: work around bug in Rollbar api<commit_after>// Wrapper around rollbar.com api.
package rollbar

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const v1Endpoint = "https://api.rollbar.com/api/1"

type Client struct {
	HttpClient *http.Client
	Token      string
	Endpoint   *url.URL
}

func NewClient(token string) *Client {
	rel, err := url.Parse(v1Endpoint)
	if err != nil {
		panic(err)
	}

	client := &Client{
		HttpClient: http.DefaultClient,
		Token:      token,
		Endpoint:   rel,
	}

	return client
}

func (c *Client) Request(verb, url string) (io.ReadCloser, error) {
	url = c.BuildUrl(url)
	req, err := http.NewRequest(verb, url, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.HttpClient.Do(req)
	if err != nil {
		return nil, err
	}

	return resp.Body, nil
}

func (c *Client) BuildUrl(url string) string {
	return fmt.Sprintf("%v/%v/?access_token=%v", c.Endpoint, url, c.Token)
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"errors"
	"koding/db/models"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

func GetGroupById(id string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"_id": bson.ObjectIdHex(id)}).One(&group)
	}

	return group, Mongo.Run("jGroups", query)
}

func GetGroup(slugName string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(Selector{"slug": slugName}).One(&group)
	}

	return group, Mongo.Run("jGroups", query)
}

func GetGroupOwner(group *models.Group) (*models.Account, error) {
	if !group.Id.Valid() {
		return nil, errors.New("group id is not valid")
	}

	rel, err := GetRelationship(Selector{
		"sourceId": group.Id,
		"as":       "owner",
	})

	if err != nil {
		return nil, err
	}

	return GetAccountById(rel.TargetId.Hex())
}

func CheckGroupExistence(groupname string) (bool, error) {
	var count int
	query := func(c *mgo.Collection) error {
		var err error
		count, err = c.Find(Selector{"slug": groupname}).Count()
		if err != nil {
			return err
		}
		return nil
	}

	return count > 0, Mongo.Run("jGroups", query)
}

func UpdateGroup(g *models.Group) error {
	query := updateByIdQuery(g.Id.Hex(), g)
	return Mongo.Run("jGroups", query)
}

func UpdateGroupPartial(selector, options Selector) error {
	query := func(c *mgo.Collection) error {
		return c.Update(selector, options)
	}

	return Mongo.Run("jGroups", query)
}
<commit_msg>Go: implement group creation method<commit_after>package modelhelper

import (
	"errors"
	"koding/db/models"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

const GroupsCollectionName = "jGroups"

func GetGroupById(id string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"_id": bson.ObjectIdHex(id)}).One(&group)
	}

	return group, Mongo.Run(GroupsCollectionName, query)
}

func GetGroup(slugName string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(Selector{"slug": slugName}).One(&group)
	}

	return group, Mongo.Run(GroupsCollectionName, query)
}

func GetGroupOwner(group *models.Group) (*models.Account, error) {
	if !group.Id.Valid() {
		return nil, errors.New("group id is not valid")
	}

	rel, err := GetRelationship(Selector{
		"sourceId": group.Id,
		"as":       "owner",
	})

	if err != nil {
		return nil, err
	}

	return GetAccountById(rel.TargetId.Hex())
}

func CheckGroupExistence(groupname string) (bool, error) {
	var count int
	query := func(c *mgo.Collection) error {
		var err error
		count, err = c.Find(Selector{"slug": groupname}).Count()
		if err != nil {
			return err
		}
		return nil
	}

	return count > 0, Mongo.Run(GroupsCollectionName, query)
}

func UpdateGroup(g *models.Group) error {
	query := updateByIdQuery(g.Id.Hex(), g)
	return Mongo.Run(GroupsCollectionName, query)
}

func UpdateGroupPartial(selector, options Selector) error {
	query := func(c *mgo.Collection) error {
		return c.Update(selector, options)
	}

	return Mongo.Run(GroupsCollectionName, query)
}

func CreateGroup(m *models.Group) error {

	query := func(c *mgo.Collection) error {
		return c.Insert(m)
	}

	return Mongo.Run(GroupsCollectionName, query)
}
<|endoftext|>


<commit_before>/*
Package fileseq is a library for parsing file sequence strings commonly
used in VFX and animation applications.

Frame Range Shorthand

Support for:

    Standard: 1-10
    Comma Delimited: 1-10,10-20
    Chunked: 1-100x5
    Filled: 1-100y5
    Staggered: 1-100:3 (1-100x3, 1-100x2, 1-100)
    Negative frame numbers: -10-100
    Padding: #=4 padded, @=single pad
	Printf Syntax Padding: %04d=4 padded, %01d=1 padded
	Houdini Syntax Padding: $F4=4 padding, $F=1 padded

*/
package fileseq

import (
	"errors"
	"fmt"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

const Version = "2.9.1"

var (
	// Regular expression patterns for matching frame set strings.
	// Examples:
	//     1-100
	//     100
	//     1-100x5
	rangePatterns = []*regexp.Regexp{
		// Frame range:  1-10
		regexp.MustCompile(`^(-?\d+)-(-?\d+)$`),
		// Single frame:  10
		regexp.MustCompile(`^(-?\d+)$`),
		// Complex range:  1-10x2
		regexp.MustCompile(`^(-?\d+)-(-?\d+)([:xy])(-?\d+)$`),
	}

	extPatternStr = `` +
		`(?P<ext>` +
		// multiple extension parts:
		`(?:\.\w*[a-zA-Z]\w)*` + // optional leading alnum ext prefix (.foo.1bar)
		`(?:\.[a-zA-Z0-9]+)?` + // ext suffix
		`)`

	// Regular expression for matching a file sequence string.
	// Example:
	//     /film/shot/renders/hero_bty.1-100#.exr
	//     /film/shot/renders/hero_bty.@@.exr
	//     /film/shot/renders/hero_bty.1-100%04d.exr
	//     /film/shot/renders/hero_bty.1-100$F04.exr
	splitPattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<range>[\d-][:xy\d,-]*)?` +
			// padding options
			`(?P<pad>` +
			`[#@]+` + // standard pad chars
			`|%\d*d` + // or printf padding
			`|\$F\d*` + // or houdini padding
			`)` + // end <pad>
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching single file path names containing a frame.
	// Example:
	//     /film/shot/renders/hero_bty.100.exr
	singleFramePattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<frame>-?\d+)` +
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching single file path names where the
	// frame may be optional.
	// Example:
	//     /film/shot/renders/hero_bty.exr
	optionalFramePattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<frame>-?\d+)?` +
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching padding against a
	// printf syntax padding string E.g. %04d
	printfPattern = regexp.MustCompile(`^%(\d*)d$`)

	// Regular expression pattern for matching padding against
	// houdini syntax. E.g. $F04
	houdiniPattern = regexp.MustCompile(`^\$F(\d*)$`)
)

// IsFrameRange returns true if the given string is a valid frame
// range format.  Any padding characters, such as '#' and '@' are ignored.
func IsFrameRange(frange string) bool {
	_, err := frameRangeMatches(frange)
	if err == nil {
		return true
	}
	return false
}

// FramesToFrameRange takes a slice of frame numbers and
// compresses them into a frame range string.
//
// If sorted == true, pre-sort the frames instead of respecting
// their current order in the range.
//
// If zfill > 1, then pad out each number with "0" to the given
// total width.
func FramesToFrameRange(frames []int, sorted bool, zfill int) string {
	count := len(frames)
	if count == 0 {
		return ""
	}

	if count == 1 {
		return zfillInt(frames[0], zfill)
	}

	if sorted {
		sort.Ints(frames)
	}

	var i, frame, step int
	var start, end string
	var buf strings.Builder

	// Keep looping until all frames are consumed
	for len(frames) > 0 {
		count = len(frames)
		// If we get to the last element, just write it
		// and end
		if count <= 2 {
			for _, frame = range frames {
				if buf.Len() > 0 {
					buf.WriteString(",")
				}
				buf.WriteString(zfillInt(frame, zfill))
			}
			break
		}
		// At this point, we have 3 or more frames to check.
		// Scan the current window of the slice to see how
		// many frames we can consume into a group
		step = frames[1] - frames[0]
		for i = 0; i < len(frames)-1; i++ {
			// We have scanned as many frames as we can
			// for this group. Now write them and stop
			// looping on this window
			if (frames[i+1] - frames[i]) != step {
				break
			}
		}

		// Subsequent groups are comma-separated
		if buf.Len() > 0 {
			buf.WriteString(",")
		}

		// We only have a single frame to write for this group
		if i == 0 {
			buf.WriteString(zfillInt(frames[0], zfill))
			frames = frames[1:]
			continue
		}

		// First do a check to see if we could have gotten a larger range
		// out of subsequent values with a different step size
		if i == 1 && count > 3 {
			// Check if the next two pairwise frames have the same step.
			// If so, then it is better than our current grouping.
			if (frames[2] - frames[1]) == (frames[3] - frames[2]) {
				// Just consume the first frame, and allow the next
				// loop to scan the new stepping
				buf.WriteString(zfillInt(frames[0], zfill))
				frames = frames[1:]
				continue
			}
		}

		// Otherwise write out this step range
		start = zfillInt(frames[0], zfill)
		end = zfillInt(frames[i], zfill)
		buf.WriteString(fmt.Sprintf("%s-%s", start, end))
		if step > 1 {
			buf.WriteString(fmt.Sprintf("x%d", step))
		}
		frames = frames[i+1:]
	}

	return buf.String()
}

// frameRangeMatches breaks down the string frame range
// into groups of range matches, for further processing.
func frameRangeMatches(frange string) ([][]string, error) {
	for _, k := range defaultPadding.AllChars() {
		frange = strings.Replace(frange, k, "", -1)
	}

	var (
		matched bool
		match   []string
		rx      *regexp.Regexp
	)

	frange = strings.Replace(frange, " ", "", -1)

	// For each comma-sep component, we will parse a frame range
	parts := strings.Split(frange, ",")
	size := len(parts)
	matches := make([][]string, size, size)

	for i, part := range parts {

		matched = false

		// Build up frames for all comma-sep components
		for _, rx = range rangePatterns {
			if match = rx.FindStringSubmatch(part); match == nil {
				continue
			}
			matched = true
			matches[i] = match[1:]
		}

		// If any component of the comma-sep frame range fails to
		// parse, we bail out
		if !matched {
			err := fmt.Errorf("Failed to parse frame range: %s on part %q", frange, part)
			return nil, err
		}
	}

	return matches, nil
}

// Expands a start, end, and stepping value
// into the full range of int values.
func toRange(start, end, step int) []int {
	nums := []int{}
	if step < 1 {
		step = 1
	}
	if start <= end {
		for i := start; i <= end; {
			nums = append(nums, i)
			i += step
		}
	} else {
		for i := start; i >= end; {
			nums = append(nums, i)
			i -= step
		}
	}
	return nums
}

// Parse an int from a specific part of a frame
// range string component
var parseIntErr error = errors.New("Failed to parse int from part of range string")

func parseInt(s string) (int, error) {
	val, err := strconv.Atoi(s)
	if err != nil {
		return 0, parseIntErr
	}
	return val, nil
}

// Return whether a string component from a frame
// range string is a valid modifier symbol
func isModifier(s string) bool {
	return len(s) == 1 && strings.ContainsAny(s, "xy:")
}

// Return the min/max frames from an unsorted list
func minMaxFrame(frames []int) (int, int) {
	srcframes := make([]int, len(frames), len(frames))
	copy(srcframes, frames)
	sort.Ints(srcframes)
	min, max := srcframes[0], srcframes[len(srcframes)-1]
	return min, max
}
<commit_msg>bump v2.10.0<commit_after>/*
Package fileseq is a library for parsing file sequence strings commonly
used in VFX and animation applications.

Frame Range Shorthand

Support for:

    Standard: 1-10
    Comma Delimited: 1-10,10-20
    Chunked: 1-100x5
    Filled: 1-100y5
    Staggered: 1-100:3 (1-100x3, 1-100x2, 1-100)
    Negative frame numbers: -10-100
    Padding: #=4 padded, @=single pad
	Printf Syntax Padding: %04d=4 padded, %01d=1 padded
	Houdini Syntax Padding: $F4=4 padding, $F=1 padded

*/
package fileseq

import (
	"errors"
	"fmt"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

const Version = "2.10.0"

var (
	// Regular expression patterns for matching frame set strings.
	// Examples:
	//     1-100
	//     100
	//     1-100x5
	rangePatterns = []*regexp.Regexp{
		// Frame range:  1-10
		regexp.MustCompile(`^(-?\d+)-(-?\d+)$`),
		// Single frame:  10
		regexp.MustCompile(`^(-?\d+)$`),
		// Complex range:  1-10x2
		regexp.MustCompile(`^(-?\d+)-(-?\d+)([:xy])(-?\d+)$`),
	}

	extPatternStr = `` +
		`(?P<ext>` +
		// multiple extension parts:
		`(?:\.\w*[a-zA-Z]\w)*` + // optional leading alnum ext prefix (.foo.1bar)
		`(?:\.[a-zA-Z0-9]+)?` + // ext suffix
		`)`

	// Regular expression for matching a file sequence string.
	// Example:
	//     /film/shot/renders/hero_bty.1-100#.exr
	//     /film/shot/renders/hero_bty.@@.exr
	//     /film/shot/renders/hero_bty.1-100%04d.exr
	//     /film/shot/renders/hero_bty.1-100$F04.exr
	splitPattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<range>[\d-][:xy\d,-]*)?` +
			// padding options
			`(?P<pad>` +
			`[#@]+` + // standard pad chars
			`|%\d*d` + // or printf padding
			`|\$F\d*` + // or houdini padding
			`)` + // end <pad>
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching single file path names containing a frame.
	// Example:
	//     /film/shot/renders/hero_bty.100.exr
	singleFramePattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<frame>-?\d+)` +
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching single file path names where the
	// frame may be optional.
	// Example:
	//     /film/shot/renders/hero_bty.exr
	optionalFramePattern = regexp.MustCompile(
		`^` +
			`(?P<name>.*?)` +
			`(?P<frame>-?\d+)?` +
			extPatternStr +
			`$`,
	)

	// Regular expression pattern for matching padding against a
	// printf syntax padding string E.g. %04d
	printfPattern = regexp.MustCompile(`^%(\d*)d$`)

	// Regular expression pattern for matching padding against
	// houdini syntax. E.g. $F04
	houdiniPattern = regexp.MustCompile(`^\$F(\d*)$`)
)

// IsFrameRange returns true if the given string is a valid frame
// range format.  Any padding characters, such as '#' and '@' are ignored.
func IsFrameRange(frange string) bool {
	_, err := frameRangeMatches(frange)
	if err == nil {
		return true
	}
	return false
}

// FramesToFrameRange takes a slice of frame numbers and
// compresses them into a frame range string.
//
// If sorted == true, pre-sort the frames instead of respecting
// their current order in the range.
//
// If zfill > 1, then pad out each number with "0" to the given
// total width.
func FramesToFrameRange(frames []int, sorted bool, zfill int) string {
	count := len(frames)
	if count == 0 {
		return ""
	}

	if count == 1 {
		return zfillInt(frames[0], zfill)
	}

	if sorted {
		sort.Ints(frames)
	}

	var i, frame, step int
	var start, end string
	var buf strings.Builder

	// Keep looping until all frames are consumed
	for len(frames) > 0 {
		count = len(frames)
		// If we get to the last element, just write it
		// and end
		if count <= 2 {
			for _, frame = range frames {
				if buf.Len() > 0 {
					buf.WriteString(",")
				}
				buf.WriteString(zfillInt(frame, zfill))
			}
			break
		}
		// At this point, we have 3 or more frames to check.
		// Scan the current window of the slice to see how
		// many frames we can consume into a group
		step = frames[1] - frames[0]
		for i = 0; i < len(frames)-1; i++ {
			// We have scanned as many frames as we can
			// for this group. Now write them and stop
			// looping on this window
			if (frames[i+1] - frames[i]) != step {
				break
			}
		}

		// Subsequent groups are comma-separated
		if buf.Len() > 0 {
			buf.WriteString(",")
		}

		// We only have a single frame to write for this group
		if i == 0 {
			buf.WriteString(zfillInt(frames[0], zfill))
			frames = frames[1:]
			continue
		}

		// First do a check to see if we could have gotten a larger range
		// out of subsequent values with a different step size
		if i == 1 && count > 3 {
			// Check if the next two pairwise frames have the same step.
			// If so, then it is better than our current grouping.
			if (frames[2] - frames[1]) == (frames[3] - frames[2]) {
				// Just consume the first frame, and allow the next
				// loop to scan the new stepping
				buf.WriteString(zfillInt(frames[0], zfill))
				frames = frames[1:]
				continue
			}
		}

		// Otherwise write out this step range
		start = zfillInt(frames[0], zfill)
		end = zfillInt(frames[i], zfill)
		buf.WriteString(fmt.Sprintf("%s-%s", start, end))
		if step > 1 {
			buf.WriteString(fmt.Sprintf("x%d", step))
		}
		frames = frames[i+1:]
	}

	return buf.String()
}

// frameRangeMatches breaks down the string frame range
// into groups of range matches, for further processing.
func frameRangeMatches(frange string) ([][]string, error) {
	for _, k := range defaultPadding.AllChars() {
		frange = strings.Replace(frange, k, "", -1)
	}

	var (
		matched bool
		match   []string
		rx      *regexp.Regexp
	)

	frange = strings.Replace(frange, " ", "", -1)

	// For each comma-sep component, we will parse a frame range
	parts := strings.Split(frange, ",")
	size := len(parts)
	matches := make([][]string, size, size)

	for i, part := range parts {

		matched = false

		// Build up frames for all comma-sep components
		for _, rx = range rangePatterns {
			if match = rx.FindStringSubmatch(part); match == nil {
				continue
			}
			matched = true
			matches[i] = match[1:]
		}

		// If any component of the comma-sep frame range fails to
		// parse, we bail out
		if !matched {
			err := fmt.Errorf("Failed to parse frame range: %s on part %q", frange, part)
			return nil, err
		}
	}

	return matches, nil
}

// Expands a start, end, and stepping value
// into the full range of int values.
func toRange(start, end, step int) []int {
	nums := []int{}
	if step < 1 {
		step = 1
	}
	if start <= end {
		for i := start; i <= end; {
			nums = append(nums, i)
			i += step
		}
	} else {
		for i := start; i >= end; {
			nums = append(nums, i)
			i -= step
		}
	}
	return nums
}

// Parse an int from a specific part of a frame
// range string component
var parseIntErr error = errors.New("Failed to parse int from part of range string")

func parseInt(s string) (int, error) {
	val, err := strconv.Atoi(s)
	if err != nil {
		return 0, parseIntErr
	}
	return val, nil
}

// Return whether a string component from a frame
// range string is a valid modifier symbol
func isModifier(s string) bool {
	return len(s) == 1 && strings.ContainsAny(s, "xy:")
}

// Return the min/max frames from an unsorted list
func minMaxFrame(frames []int) (int, int) {
	srcframes := make([]int, len(frames), len(frames))
	copy(srcframes, frames)
	sort.Ints(srcframes)
	min, max := srcframes[0], srcframes[len(srcframes)-1]
	return min, max
}
<|endoftext|>


<commit_before>package filterutils

// Taken from the golang source code and modified
func Search(n int, f func(int) bool, g func(int) bool) bool {
    /*
    Do a binary search over a slice for an element.

    For large sets a bloom filter is more effective
    */
    // Define f(-1) == false and f(n) == true.
    // Invariant: f(i-1) == false, f(j) == true.
    i, j := 0, n
    for i < j {
        h := i + (j-i)/2 // avoid overflow when computing h
        if g(h) {
            return true
        } else if !f(h) { // i ≤ h < j
            i = h + 1 // preserves f(i-1) == false
        } else {
            j = h // preserves f(j) == true
        }
    }
    // i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
    return false
}

func StringInSortedSlice(a []string, x string) bool {
    /*
    Returns true if a string is in a slice, otherwise return false.

    Must be implemented with a sorted slice. Runtime is O(lg(n))
    */
    return Search(
        len(a),
        func(i int) bool { return a[i] > x},
        func(i int) bool { return a[i] == x},
    )
}

func Filter(a []string, f func(int) bool) []string {
    /*
    Iterate over a slice and pick only elements which hold under function f

    Runtime is O(n)
    */
    b := make([]string, 0)
    for i, _ := range a {
        if f(i) {
            b = append(b, a[i])
            a[i] = a[len(a)-1]
            a = a[0:len(a)-1]
        }
    }
    return b
}
<commit_msg>Bug fixes  * Fixed filters.go where you would get an end of index error<commit_after>package filterutils

// Taken from the golang source code and modified
func Search(n int, f func(int) bool, g func(int) bool) bool {
    /*
    Do a binary search over a slice for an element.

    For large sets a bloom filter is more effective
    */
    // Define f(-1) == false and f(n) == true.
    // Invariant: f(i-1) == false, f(j) == true.
    i, j := 0, n
    for i < j {
        h := i + (j-i)/2 // avoid overflow when computing h
        if g(h) {
            return true
        } else if !f(h) { // i ≤ h < j
            i = h + 1 // preserves f(i-1) == false
        } else {
            j = h // preserves f(j) == true
        }
    }
    // i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
    return false
}

func StringInSortedSlice(a []string, x string) bool {
    /*
    Returns true if a string is in a slice, otherwise return false.

    Must be implemented with a sorted slice. Runtime is O(lg(n))
    */
    return Search(
        len(a),
        func(i int) bool { return a[i] > x},
        func(i int) bool { return a[i] == x},
    )
}

func Filter(a []string, f func(int) bool) []string {
    /*
    Iterate over a slice and pick only elements which hold under function f

    Runtime is O(n)
    */
    b := make([]string, 0)
    for i, _ := range a {
        if f(i) {
            b = append(b, a[i])
        }
    }
    return b
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/cucumber/godog"
	"github.com/cucumber/godog/colors"
	"github.com/ii/xds-test-harness/internal/types"
	"github.com/rs/zerolog/log"
)

func init() {
	godog.Format("xds", "Progress formatter with emojis", xdsFormatterFunc)
}

func xdsFormatterFunc(suite string, out io.Writer) godog.Formatter {
	return newxdsFmt(suite, out)
}

type xdsFmt struct {
	*godog.ProgressFmt
	out     io.Writer
	results types.VariantResults
}

func newxdsFmt(suite string, out io.Writer) *xdsFmt {
	return &xdsFmt{
		ProgressFmt: godog.NewProgressFmt(suite, out),
		out:         out,
		results:     types.VariantResults{},
	}
}

func (f *xdsFmt) Passed(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Passed(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Passed++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Skipped(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Skipped(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Skipped++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Undefined(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Undefined(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Undefined++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Failed(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition, err error) {
	f.ProgressFmt.Base.Failed(scenario, step, match, err)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Failed++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Pending(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Pending(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Pending++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Summary() {
	f.results.FailedScenarios = f.gatherFailedScenarios()
	data, err := json.MarshalIndent(f.results, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Fprintf(f.out, "%s\n", string(data))
}

func (f *xdsFmt) step(pickleStepID string, scenario *godog.Scenario) {
	pickleStepResult := f.Storage.MustGetPickleStepResult(pickleStepID)
	printStatusEmoji(pickleStepResult.Status)

	lastStep := isLastStep(pickleStepID, scenario)
	if lastStep {
		failed, failedStep := f.didScenarioFail(scenario)
		if failed {
			log.Info().
				Str("failed step", failedStep).
				Msgf("[%v]%v", colors.Red("FAILED"), scenario.Name)
		} else {
			log.Info().
				Msgf("[%v]%v", colors.Green("PASSED"), scenario.Name)
		}
	}
	*f.Steps++
}

func (f *xdsFmt) didScenarioFail(scenario *godog.Scenario) (failed bool, failedStep string) {
	failed = false
	results := f.Storage.MustGetPickleStepResultsByPickleID(scenario.Id)
	for _, result := range results {
		if result.Status.String() == "failed" {
			feature := f.Storage.MustGetFeature(scenario.Uri)
			pickleStep := f.Storage.MustGetPickleStep(result.PickleStepID)
			step := feature.FindStep(pickleStep.AstNodeIds[0])
			failed = true
			failedStep = step.Text
		}
	}
	return failed, failedStep
}

func (f *xdsFmt) gatherFailedScenarios() (failedScenarios []types.FailedScenario) {
	failedSteps := f.Storage.MustGetPickleStepResultsByStatus(1)
	for _, failure := range failedSteps {
		scenario := f.Storage.MustGetPickle(failure.PickleID)
		feature := f.Storage.MustGetFeature(scenario.Uri)
		pickleStep := f.Storage.MustGetPickleStep(failure.PickleStepID)
		step := feature.FindStep(pickleStep.AstNodeIds[0])

		fs := types.FailedScenario{
			Name:       scenario.Name,
			FailedStep: step.Text,
			Line:       fmt.Sprintf("%v:%v", feature.Uri, step.Location.Line),
		}

		failedScenarios = append(failedScenarios, fs)
	}
	return failedScenarios
}

func printStatusEmoji(status godog.StepResultStatus) {
	switch status {
	case godog.StepPassed:
		fmt.Printf(" %s", "✅")
	case godog.StepSkipped:
		fmt.Printf(" %s", "➖")
	case godog.StepFailed:
		fmt.Printf(" %s", "❌")
	case godog.StepUndefined:
		fmt.Printf(" %s", "❓")
	case godog.StepPending:
		fmt.Printf(" %s", "🚧")
	}
}

func isLastStep(stepId string, scenario *godog.Scenario) bool {
	stepIds := []string{}
	lastIndex := len(scenario.Steps) - 1
	for _, step := range scenario.Steps {
		stepIds = append(stepIds, step.Id)
	}
	index := indexOf(stepId, stepIds)
	return index == lastIndex
}

func indexOf(val string, arr []string) int {
	for i, v := range arr {
		if v == val {
			return i
		}
	}
	return -1
}
<commit_msg>add separator for readability<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/cucumber/godog"
	"github.com/cucumber/godog/colors"
	"github.com/ii/xds-test-harness/internal/types"
	"github.com/rs/zerolog/log"
)

func init() {
	godog.Format("xds", "Progress formatter with emojis", xdsFormatterFunc)
}

func xdsFormatterFunc(suite string, out io.Writer) godog.Formatter {
	return newxdsFmt(suite, out)
}

type xdsFmt struct {
	*godog.ProgressFmt
	out     io.Writer
	results types.VariantResults
}

func newxdsFmt(suite string, out io.Writer) *xdsFmt {
	return &xdsFmt{
		ProgressFmt: godog.NewProgressFmt(suite, out),
		out:         out,
		results:     types.VariantResults{},
	}
}

func (f *xdsFmt) Passed(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Passed(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Passed++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Skipped(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Skipped(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Skipped++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Undefined(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Undefined(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Undefined++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Failed(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition, err error) {
	f.ProgressFmt.Base.Failed(scenario, step, match, err)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Failed++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Pending(scenario *godog.Scenario, step *godog.Step, match *godog.StepDefinition) {
	f.ProgressFmt.Base.Pending(scenario, step, match)
	f.ProgressFmt.Base.Lock.Lock()
	defer f.ProgressFmt.Base.Lock.Unlock()
	f.results.Total++
	f.results.Pending++
	f.step(step.Id, scenario)
}

func (f *xdsFmt) Summary() {
	f.results.FailedScenarios = f.gatherFailedScenarios()
	data, err := json.MarshalIndent(f.results, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Fprintf(f.out, "%s\n", string(data))
}

func (f *xdsFmt) step(pickleStepID string, scenario *godog.Scenario) {
	pickleStepResult := f.Storage.MustGetPickleStepResult(pickleStepID)
	printStatusEmoji(pickleStepResult.Status)

	lastStep := isLastStep(pickleStepID, scenario)
	if lastStep {
		failed, failedStep := f.didScenarioFail(scenario)
		if failed {
			log.Info().
				Str("failed step", failedStep).
				Msgf("| [%v]%v", colors.Red("FAILED"), scenario.Name)
		} else {
			log.Info().
				Msgf("| [%v]%v", colors.Green("PASSED"), scenario.Name)
		}
	}
	*f.Steps++
}

func (f *xdsFmt) didScenarioFail(scenario *godog.Scenario) (failed bool, failedStep string) {
	failed = false
	results := f.Storage.MustGetPickleStepResultsByPickleID(scenario.Id)
	for _, result := range results {
		if result.Status.String() == "failed" {
			feature := f.Storage.MustGetFeature(scenario.Uri)
			pickleStep := f.Storage.MustGetPickleStep(result.PickleStepID)
			step := feature.FindStep(pickleStep.AstNodeIds[0])
			failed = true
			failedStep = step.Text
		}
	}
	return failed, failedStep
}

func (f *xdsFmt) gatherFailedScenarios() (failedScenarios []types.FailedScenario) {
	failedSteps := f.Storage.MustGetPickleStepResultsByStatus(1)
	for _, failure := range failedSteps {
		scenario := f.Storage.MustGetPickle(failure.PickleID)
		feature := f.Storage.MustGetFeature(scenario.Uri)
		pickleStep := f.Storage.MustGetPickleStep(failure.PickleStepID)
		step := feature.FindStep(pickleStep.AstNodeIds[0])

		fs := types.FailedScenario{
			Name:       scenario.Name,
			FailedStep: step.Text,
			Line:       fmt.Sprintf("%v:%v", feature.Uri, step.Location.Line),
		}

		failedScenarios = append(failedScenarios, fs)
	}
	return failedScenarios
}

func printStatusEmoji(status godog.StepResultStatus) {
	switch status {
	case godog.StepPassed:
		fmt.Printf(" %s", "✅")
	case godog.StepSkipped:
		fmt.Printf(" %s", "➖")
	case godog.StepFailed:
		fmt.Printf(" %s", "❌")
	case godog.StepUndefined:
		fmt.Printf(" %s", "❓")
	case godog.StepPending:
		fmt.Printf(" %s", "🚧")
	}
}

func isLastStep(stepId string, scenario *godog.Scenario) bool {
	stepIds := []string{}
	lastIndex := len(scenario.Steps) - 1
	for _, step := range scenario.Steps {
		stepIds = append(stepIds, step.Id)
	}
	index := indexOf(stepId, stepIds)
	return index == lastIndex
}

func indexOf(val string, arr []string) int {
	for i, v := range arr {
		if v == val {
			return i
		}
	}
	return -1
}
<|endoftext|>