<commit_before>package core

import (
	"bytes"
	"reflect"
	"strings"
	"time"
)

type LogicalOperator int
type ComparisonOperator int
type Type int

const (
	OR LogicalOperator = iota
	AND
	UnknownLogical

	Equals ComparisonOperator = iota
	NotEquals
	LessThan
	GreaterThan
	LessThanOrEqual
	GreaterThanOrEqual
	Contains
	NotContains
	Unary
	NotUnary
	UnknownComparator

	String Type = iota
	Nil
	Int
	Int64
	Uint
	Float64
	Complex128
	Bool
	Time
	Today
	Array
	Unknown
)

var KindToType = map[reflect.Kind]Type{
	reflect.String:     String,
	reflect.Int:        Int,
	reflect.Int64:      Int64,
	reflect.Uint:       Uint,
	reflect.Float64:    Float64,
	reflect.Complex128: Complex128,
	reflect.Bool:       Bool,
	reflect.Array:      Array,
	reflect.Slice:      Array,
	reflect.Map:        Array,
}

var TypeOperations = map[Type]map[ComparisonOperator]ConditionResolver{
	String: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(string) == right.(string) },
		LessThan: func(left, right interface{}) bool { return left.(string) < right.(string) },
	},
	Nil: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left == nil && right == nil },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Int: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(int) == right.(int) },
		LessThan: func(left, right interface{}) bool { return left.(int) < right.(int) },
	},
	Int64: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(int64) == right.(int64) },
		LessThan: func(left, right interface{}) bool { return left.(int64) < right.(int64) },
	},
	Uint: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(uint) == right.(uint) },
		LessThan: func(left, right interface{}) bool { return left.(uint) < right.(uint) },
	},
	Float64: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(float64) == right.(float64) },
		LessThan: func(left, right interface{}) bool { return left.(float64) < right.(float64) },
	},
	Complex128: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(complex128) == right.(complex128) },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Bool: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(bool) == right.(bool) },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Time: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(time.Time).Unix() == right.(time.Time).Unix() },
		LessThan: func(left, right interface{}) bool { return left.(time.Time).Unix() < right.(time.Time).Unix() },
	},
	Today: map[ComparisonOperator]ConditionResolver{
		Equals: func(left, right interface{}) bool {
			l, r := left.(time.Time), right.(time.Time)
			return l.YearDay() == r.YearDay() && l.Year() == r.Year()
		},
		LessThan: func(left, right interface{}) bool {
			l, r := left.(time.Time), right.(time.Time)
			if l.Year() > r.Year() {
				return false
			}
			if l.Year() < r.Year() {
				return true
			}
			return l.YearDay() < r.YearDay()
		},
	},
	Array: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return reflect.DeepEqual(left, right) },
		LessThan: func(left, right interface{}) bool { return reflect.ValueOf(left).Len() < reflect.ValueOf(right).Len() },
	},
}

// Resolves a condition
type ConditionResolver func(left, right interface{}) bool

var ConditionLookup = map[ComparisonOperator]ConditionResolver{
	Unary:              UnaryComparison,
	NotUnary:           NotUnaryComparison,
	Equals:             EqualsComparison,
	NotEquals:          NotEqualsComparison,
	LessThan:           LessThanComparison,
	GreaterThan:        GreaterThanComparison,
	LessThanOrEqual:    LessThanOrEqualComparison,
	GreaterThanOrEqual: GreaterThanOrEqualComparison,
	Contains:           ContainsComparison,
}

type Completable interface {
	Complete(value Value, operator ComparisonOperator)
	Verifiable
}

type Verifiable interface {
	IsTrue(data map[string]interface{}) bool
	Inverse()
}

// represents a group of conditions
type ConditionGroup struct {
	conditions []*Condition
	joins      []LogicalOperator
	inverse    bool
}

func (g *ConditionGroup) Inverse() {
	g.inverse = true
}

func (g ConditionGroup) Complete(value Value, operator ComparisonOperator) {
	for _, condition := range g.conditions {
		condition.right = value
		condition.operator = operator
	}
}

func (g *ConditionGroup) IsTrue(data map[string]interface{}) bool {
	l := len(g.conditions) - 1
	if l == 0 {
		return g.realReturn(g.conditions[0].IsTrue(data))
	}

	for i := 0; i <= l; i++ {
		if g.conditions[i].IsTrue(data) {
			if i == l || g.joins[i] == OR {
				return g.realReturn(true)
			}
		} else if i != l && g.joins[i] == AND {
			for ; i < l; i++ {
				if g.joins[i] == OR {
					break
				}
			}
		}
	}
	return g.realReturn(false)
}

func (g *ConditionGroup) realReturn(b bool) bool {
	if g.inverse {
		return !b
	}
	return b
}

type TrueCondition struct {
	inverse bool
}

func (t *TrueCondition) IsTrue(data map[string]interface{}) bool {
	if t.inverse {
		return false
	}
	return true
}

func (t *TrueCondition) Inverse() {
	t.inverse = true
}

// represents a conditions (such as x == y)
type Condition struct {
	left     Value
	operator ComparisonOperator
	right    Value
}

func (c *Condition) IsTrue(data map[string]interface{}) bool {
	left := c.left.ResolveWithNil(data)
	var right interface{}
	if c.right != nil {
		right = c.right.ResolveWithNil(data)
	}
	return ConditionLookup[c.operator](left, right)
}

func UnaryComparison(left, right interface{}) bool {
	if left == nil {
		return false
	}
	switch typed := left.(type) {
	case bool:
		return typed
	case string:
		return len(typed) > 0
	case []byte:
		return len(typed) > 0
	}
	return true
}

func NotUnaryComparison(left, right interface{}) bool {
	return !UnaryComparison(left, right)
}

func EqualsComparison(left, right interface{}) bool {
	if s, ok := right.(string); ok && s == "liquid:empty" {
		if n, ok := ToLength(left); ok {
			return n == 0
		}
		return false
	}

	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][Equals](left, right)
}

func NotEqualsComparison(left, right interface{}) bool {
	return !EqualsComparison(left, right)
}

func LessThanComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][LessThan](left, right)
}

func LessThanOrEqualComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][Equals](left, right) || TypeOperations[t][LessThan](left, right)
}

func GreaterThanComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return !TypeOperations[t][Equals](left, right) && !TypeOperations[t][LessThan](left, right)
}

func GreaterThanOrEqualComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return !TypeOperations[t][LessThan](left, right)
}

// I think most of this sucks
func ContainsComparison(left, right interface{}) bool {
	if s, ok := left.(string); ok {
		return strings.Contains(s, ToString(right))
	}
	if b, ok := left.([]byte); ok {
		return bytes.Contains(b, ToBytes(right))
	}

	if n, ok := left.([]int); ok {
		needle, ok := ToInt(right)
		if ok == false {
			return false
		}
		for i, l := 0, len(n); i < l; i++ {
			if n[i] == needle {
				return true
			}
		}
		return false
	}

	value := reflect.ValueOf(left)
	kind := value.Kind()
	if kind == reflect.Array || kind == reflect.Slice {
		l := value.Len()
		if l == 0 {
			return false
		}
		needle := ToBytes(right)
		for i := 0; i < l; i++ {
			if bytes.Equal(needle, ToBytes(value.Index(i).Interface())) {
				return true
			}
		}
		return false
	}
	if kind == reflect.Map {
		if value.Len() == 0 {
			return false
		}
		if b, ok := right.([]byte); ok {
			right = string(b)
		}
		rightValue := reflect.ValueOf(right)
		if rightValue.Type() == value.Type().Key() {
			return value.MapIndex(rightValue).IsValid()
		}
		return false
	}
	return false
}

func NotContainsComparison(left, right interface{}) bool {
	return !ContainsComparison(left, right)
}

func convertToSameType(left, right interface{}) (interface{}, interface{}, Type) {
	//rely on the above code to handle this properly
	if left == nil || right == nil {
		return left, right, Nil
	}

	if s, ok := left.(string); ok {
		return convertStringsToSameType(s, right)
	} else if s, ok := right.(string); ok {
		return convertStringsToSameType(s, left)
	}
	if b, ok := left.([]byte); ok {
		return convertStringsToSameType(string(b), right)
	} else if b, ok := right.([]byte); ok {
		return convertStringsToSameType(string(b), left)
	}

	leftValue, rightValue := reflect.ValueOf(left), reflect.ValueOf(right)
	leftKind, rightKind := leftValue.Kind(), rightValue.Kind()
	if leftKind == rightKind {
		if t, ok := KindToType[leftKind]; ok {
			return left, right, t
		}
	}
	if left, right, t := convertNumbersToSameType(leftValue, leftKind, rightValue, rightKind); t != Unknown {
		return left, right, t
	}
	return left, right, Unknown
}

func convertStringsToSameType(a string, b interface{}) (interface{}, interface{}, Type) {
	if a == "today" {
		if t, ok := b.(time.Time); ok {
			return Now(), t, Today
		}
	} else if a == "now" {
		if t, ok := b.(time.Time); ok {
			return Now(), t, Time
		}
	}
	return a, ToString(b), String
}

func convertNumbersToSameType(leftValue reflect.Value, leftKind reflect.Kind, rightValue reflect.Value, rightKind reflect.Kind) (interface{}, interface{}, Type) {
	if isInt(leftKind) {
		if isInt(rightKind) {
			return leftValue.Int(), rightValue.Int(), Int64
		} else if isFloat(rightKind) {
			return float64(leftValue.Int()), rightValue.Float(), Float64
		}
	} else if isFloat(leftKind) {
		if isInt(rightKind) {
			return leftValue.Float(), float64(rightValue.Int()), Float64
		} else if isFloat(rightKind) {
			return leftValue.Float(), rightValue.Float(), Float64
		}
	} else if isComplex(leftKind) && isComplex(rightKind) {
		return leftValue.Complex(), rightValue.Complex(), Complex128
	}
	return nil, nil, Unknown
}

func isInt(kind reflect.Kind) bool {
	return kind == reflect.Int || kind == reflect.Int8 || kind == reflect.Int16 || kind == reflect.Int32 || kind == reflect.Int64
}

func isFloat(kind reflect.Kind) bool {
	return kind == reflect.Float64 || kind == reflect.Float32
}

func isComplex(kind reflect.Kind) bool {
	return kind == reflect.Complex128 || kind == reflect.Complex64
}
<commit_msg>Special case []string for Contains check.<commit_after>package core

import (
	"bytes"
	"reflect"
	"strings"
	"time"
)

type LogicalOperator int
type ComparisonOperator int
type Type int

const (
	OR LogicalOperator = iota
	AND
	UnknownLogical

	Equals ComparisonOperator = iota
	NotEquals
	LessThan
	GreaterThan
	LessThanOrEqual
	GreaterThanOrEqual
	Contains
	NotContains
	Unary
	NotUnary
	UnknownComparator

	String Type = iota
	Nil
	Int
	Int64
	Uint
	Float64
	Complex128
	Bool
	Time
	Today
	Array
	Unknown
)

var KindToType = map[reflect.Kind]Type{
	reflect.String:     String,
	reflect.Int:        Int,
	reflect.Int64:      Int64,
	reflect.Uint:       Uint,
	reflect.Float64:    Float64,
	reflect.Complex128: Complex128,
	reflect.Bool:       Bool,
	reflect.Array:      Array,
	reflect.Slice:      Array,
	reflect.Map:        Array,
}

var TypeOperations = map[Type]map[ComparisonOperator]ConditionResolver{
	String: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(string) == right.(string) },
		LessThan: func(left, right interface{}) bool { return left.(string) < right.(string) },
	},
	Nil: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left == nil && right == nil },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Int: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(int) == right.(int) },
		LessThan: func(left, right interface{}) bool { return left.(int) < right.(int) },
	},
	Int64: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(int64) == right.(int64) },
		LessThan: func(left, right interface{}) bool { return left.(int64) < right.(int64) },
	},
	Uint: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(uint) == right.(uint) },
		LessThan: func(left, right interface{}) bool { return left.(uint) < right.(uint) },
	},
	Float64: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(float64) == right.(float64) },
		LessThan: func(left, right interface{}) bool { return left.(float64) < right.(float64) },
	},
	Complex128: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(complex128) == right.(complex128) },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Bool: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(bool) == right.(bool) },
		LessThan: func(left, right interface{}) bool { return false },
	},
	Time: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return left.(time.Time).Unix() == right.(time.Time).Unix() },
		LessThan: func(left, right interface{}) bool { return left.(time.Time).Unix() < right.(time.Time).Unix() },
	},
	Today: map[ComparisonOperator]ConditionResolver{
		Equals: func(left, right interface{}) bool {
			l, r := left.(time.Time), right.(time.Time)
			return l.YearDay() == r.YearDay() && l.Year() == r.Year()
		},
		LessThan: func(left, right interface{}) bool {
			l, r := left.(time.Time), right.(time.Time)
			if l.Year() > r.Year() {
				return false
			}
			if l.Year() < r.Year() {
				return true
			}
			return l.YearDay() < r.YearDay()
		},
	},
	Array: map[ComparisonOperator]ConditionResolver{
		Equals:   func(left, right interface{}) bool { return reflect.DeepEqual(left, right) },
		LessThan: func(left, right interface{}) bool { return reflect.ValueOf(left).Len() < reflect.ValueOf(right).Len() },
	},
}

// Resolves a condition
type ConditionResolver func(left, right interface{}) bool

var ConditionLookup = map[ComparisonOperator]ConditionResolver{
	Unary:              UnaryComparison,
	NotUnary:           NotUnaryComparison,
	Equals:             EqualsComparison,
	NotEquals:          NotEqualsComparison,
	LessThan:           LessThanComparison,
	GreaterThan:        GreaterThanComparison,
	LessThanOrEqual:    LessThanOrEqualComparison,
	GreaterThanOrEqual: GreaterThanOrEqualComparison,
	Contains:           ContainsComparison,
}

type Completable interface {
	Complete(value Value, operator ComparisonOperator)
	Verifiable
}

type Verifiable interface {
	IsTrue(data map[string]interface{}) bool
	Inverse()
}

// represents a group of conditions
type ConditionGroup struct {
	conditions []*Condition
	joins      []LogicalOperator
	inverse    bool
}

func (g *ConditionGroup) Inverse() {
	g.inverse = true
}

func (g ConditionGroup) Complete(value Value, operator ComparisonOperator) {
	for _, condition := range g.conditions {
		condition.right = value
		condition.operator = operator
	}
}

func (g *ConditionGroup) IsTrue(data map[string]interface{}) bool {
	l := len(g.conditions) - 1
	if l == 0 {
		return g.realReturn(g.conditions[0].IsTrue(data))
	}

	for i := 0; i <= l; i++ {
		if g.conditions[i].IsTrue(data) {
			if i == l || g.joins[i] == OR {
				return g.realReturn(true)
			}
		} else if i != l && g.joins[i] == AND {
			for ; i < l; i++ {
				if g.joins[i] == OR {
					break
				}
			}
		}
	}
	return g.realReturn(false)
}

func (g *ConditionGroup) realReturn(b bool) bool {
	if g.inverse {
		return !b
	}
	return b
}

type TrueCondition struct {
	inverse bool
}

func (t *TrueCondition) IsTrue(data map[string]interface{}) bool {
	if t.inverse {
		return false
	}
	return true
}

func (t *TrueCondition) Inverse() {
	t.inverse = true
}

// represents a conditions (such as x == y)
type Condition struct {
	left     Value
	operator ComparisonOperator
	right    Value
}

func (c *Condition) IsTrue(data map[string]interface{}) bool {
	left := c.left.ResolveWithNil(data)
	var right interface{}
	if c.right != nil {
		right = c.right.ResolveWithNil(data)
	}
	return ConditionLookup[c.operator](left, right)
}

func UnaryComparison(left, right interface{}) bool {
	if left == nil {
		return false
	}
	switch typed := left.(type) {
	case bool:
		return typed
	case string:
		return len(typed) > 0
	case []byte:
		return len(typed) > 0
	}
	return true
}

func NotUnaryComparison(left, right interface{}) bool {
	return !UnaryComparison(left, right)
}

func EqualsComparison(left, right interface{}) bool {
	if s, ok := right.(string); ok && s == "liquid:empty" {
		if n, ok := ToLength(left); ok {
			return n == 0
		}
		return false
	}

	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][Equals](left, right)
}

func NotEqualsComparison(left, right interface{}) bool {
	return !EqualsComparison(left, right)
}

func LessThanComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][LessThan](left, right)
}

func LessThanOrEqualComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return TypeOperations[t][Equals](left, right) || TypeOperations[t][LessThan](left, right)
}

func GreaterThanComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return !TypeOperations[t][Equals](left, right) && !TypeOperations[t][LessThan](left, right)
}

func GreaterThanOrEqualComparison(left, right interface{}) bool {
	var t Type
	if left, right, t = convertToSameType(left, right); t == Unknown {
		return false
	}
	return !TypeOperations[t][LessThan](left, right)
}

// I think most of this sucks
func ContainsComparison(left, right interface{}) bool {
	if s, ok := left.(string); ok {
		return strings.Contains(s, ToString(right))
	}
	if b, ok := left.([]byte); ok {
		return bytes.Contains(b, ToBytes(right))
	}

	if strs, ok := left.([]string); ok {
		needle := ToString(right)
		for i, l := 0, len(strs); i < l; i++ {
			if strs[i] == needle {
				return true
			}
		}
		return false
	}

	if n, ok := left.([]int); ok {
		needle, ok := ToInt(right)
		if ok == false {
			return false
		}
		for i, l := 0, len(n); i < l; i++ {
			if n[i] == needle {
				return true
			}
		}
		return false
	}

	value := reflect.ValueOf(left)
	kind := value.Kind()
	if kind == reflect.Array || kind == reflect.Slice {
		l := value.Len()
		if l == 0 {
			return false
		}
		for i := 0; i < l; i++ {
			if EqualsComparison(value.Index(i).Interface(), right) {
				return true
			}
		}
		return false
	}
	if kind == reflect.Map {
		if value.Len() == 0 {
			return false
		}
		if b, ok := right.([]byte); ok {
			right = string(b)
		}
		rightValue := reflect.ValueOf(right)
		if rightValue.Type() == value.Type().Key() {
			return value.MapIndex(rightValue).IsValid()
		}
		return false
	}
	return false
}

func NotContainsComparison(left, right interface{}) bool {
	return !ContainsComparison(left, right)
}

func convertToSameType(left, right interface{}) (interface{}, interface{}, Type) {
	//rely on the above code to handle this properly
	if left == nil || right == nil {
		return left, right, Nil
	}

	if s, ok := left.(string); ok {
		return convertStringsToSameType(s, right)
	} else if s, ok := right.(string); ok {
		return convertStringsToSameType(s, left)
	}
	if b, ok := left.([]byte); ok {
		return convertStringsToSameType(string(b), right)
	} else if b, ok := right.([]byte); ok {
		return convertStringsToSameType(string(b), left)
	}

	leftValue, rightValue := reflect.ValueOf(left), reflect.ValueOf(right)
	leftKind, rightKind := leftValue.Kind(), rightValue.Kind()
	if leftKind == rightKind {
		if t, ok := KindToType[leftKind]; ok {
			return left, right, t
		}
	}
	if left, right, t := convertNumbersToSameType(leftValue, leftKind, rightValue, rightKind); t != Unknown {
		return left, right, t
	}
	return left, right, Unknown
}

func convertStringsToSameType(a string, b interface{}) (interface{}, interface{}, Type) {
	if a == "today" {
		if t, ok := b.(time.Time); ok {
			return Now(), t, Today
		}
	} else if a == "now" {
		if t, ok := b.(time.Time); ok {
			return Now(), t, Time
		}
	}
	return a, ToString(b), String
}

func convertNumbersToSameType(leftValue reflect.Value, leftKind reflect.Kind, rightValue reflect.Value, rightKind reflect.Kind) (interface{}, interface{}, Type) {
	if isInt(leftKind) {
		if isInt(rightKind) {
			return leftValue.Int(), rightValue.Int(), Int64
		} else if isFloat(rightKind) {
			return float64(leftValue.Int()), rightValue.Float(), Float64
		}
	} else if isFloat(leftKind) {
		if isInt(rightKind) {
			return leftValue.Float(), float64(rightValue.Int()), Float64
		} else if isFloat(rightKind) {
			return leftValue.Float(), rightValue.Float(), Float64
		}
	} else if isComplex(leftKind) && isComplex(rightKind) {
		return leftValue.Complex(), rightValue.Complex(), Complex128
	}
	return nil, nil, Unknown
}

func isInt(kind reflect.Kind) bool {
	return kind == reflect.Int || kind == reflect.Int8 || kind == reflect.Int16 || kind == reflect.Int32 || kind == reflect.Int64
}

func isFloat(kind reflect.Kind) bool {
	return kind == reflect.Float64 || kind == reflect.Float32
}

func isComplex(kind reflect.Kind) bool {
	return kind == reflect.Complex128 || kind == reflect.Complex64
}
<|endoftext|>


<commit_before>// Package configtest provides structs and logic for declarative configuration
// tests.
package configtest

import (
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/taskcluster/taskcluster-worker/config"
)

// Case allows declaration of a transformation to run on input and validate
// against declared tesult.
type Case struct {
	Transform string
	Input     map[string]interface{}
	Result    map[string]interface{}
}

// Test will execute the test case panicing if Input doesn't become Result
func (c Case) Test(t *testing.T) {
	transform := config.Providers()[c.Transform]
	require.NotNil(t, transform, "unknown transform ", c.Transform)

	err := transform.Transform(c.Input)
	require.NoError(t, err, "Transform(Input) failed")

	require.Equal(t, c.Input, c.Result, "Unexpected result")
}
<commit_msg>get 'Expected' and 'Received' the right way round<commit_after>// Package configtest provides structs and logic for declarative configuration
// tests.
package configtest

import (
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/taskcluster/taskcluster-worker/config"
)

// Case allows declaration of a transformation to run on input and validate
// against declared tesult.
type Case struct {
	Transform string
	Input     map[string]interface{}
	Result    map[string]interface{}
}

// Test will execute the test case panicing if Input doesn't become Result
func (c Case) Test(t *testing.T) {
	transform := config.Providers()[c.Transform]
	require.NotNil(t, transform, "unknown transform ", c.Transform)

	err := transform.Transform(c.Input)
	require.NoError(t, err, "Transform(Input) failed")

	require.Equal(t, c.Result, c.Input, "Unexpected result")
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 trivago GmbH
//
// 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 core

import (
	"github.com/trivago/tgo/tlog"
	"time"
)

// SimpleRouter router plugin
// Configuration example:
//
//  MyRouter:
//    Type: "router.Broadcast"
//    Stream: "foo"
//    TimeoutMs: 200
//    Modulators:
//	- filter.RegExp:
// 	  Expression: "[a-zA-Z]+"
//
type SimpleRouter struct {
	id         string
	modulators ModulatorArray
	Producers  []Producer
	Timeout    *time.Duration
	streamID   MessageStreamID
	Log        tlog.LogScope
}

// Configure sets up all values required by SimpleRouter.
func (router *SimpleRouter) Configure(conf PluginConfigReader) error {
	router.id = conf.GetID()
	router.Log = conf.GetLogScope()
	router.Timeout = nil
	router.streamID = conf.GetStreamID("Stream", GetStreamID(conf.GetID()))
	router.modulators = conf.GetModulatorArray("Modulators", router.Log, ModulatorArray{})

	if router.streamID == WildcardStreamID {
		router.Log.Note.Print("A wildcard stream configuration only affects the wildcard stream, not all routers")
	}

	if conf.HasValue("TimeoutMs") {
		timeout := time.Duration(conf.GetInt("TimeoutMs", 0)) * time.Millisecond
		router.Timeout = &timeout
	}

	return conf.Errors.OrNil()
}

// GetID returns the ID of this stream
func (router *SimpleRouter) GetID() string {
	return router.id
}

// StreamID returns the id of the stream this plugin is bound to.
func (router *SimpleRouter) StreamID() MessageStreamID {
	return router.streamID
}

// AddProducer adds all producers to the list of known producers.
// Duplicates will be filtered.
func (router *SimpleRouter) AddProducer(producers ...Producer) {
	for _, prod := range producers {
		for _, inListProd := range router.Producers {
			if inListProd == prod {
				return // ### return, already in list ###
			}
		}
		router.Producers = append(router.Producers, prod)
	}
}

// GetProducers returns the producers bound to this stream
func (router *SimpleRouter) GetProducers() []Producer {
	return router.Producers
}

// Modulate calls all modulators in their order of definition
func (router *SimpleRouter) Modulate(msg *Message) ModulateResult {
	return router.modulators.Modulate(msg)
}
<commit_msg>Removed formatter support from routers<commit_after>// Copyright 2015-2016 trivago GmbH
//
// 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 core

import (
	"github.com/trivago/tgo/tlog"
	"time"
)

// SimpleRouter router plugin
// Configuration example:
//
//  MyRouter:
//    Type: "router.Broadcast"
//    Stream: "foo"
//    TimeoutMs: 200
//    Filters:
//	- filter.RegExp:
// 	  Expression: "[a-zA-Z]+"
//
type SimpleRouter struct {
	id         string
	modulators ModulatorArray
	Producers  []Producer
	Timeout    *time.Duration
	streamID   MessageStreamID
	Log        tlog.LogScope
}

// Configure sets up all values required by SimpleRouter.
func (router *SimpleRouter) Configure(conf PluginConfigReader) error {
	router.id = conf.GetID()
	router.Log = conf.GetLogScope()
	router.Timeout = nil
	router.streamID = conf.GetStreamID("Stream", GetStreamID(conf.GetID()))

	// init router.modulators with filters only
	filters := conf.GetFilterArray("Filters", router.Log, FilterArray{})
	for _, filter := range filters {
		filterModulator := NewFilterModulator(filter)
		router.modulators = append(router.modulators, filterModulator)
	}

	if router.streamID == WildcardStreamID {
		router.Log.Note.Print("A wildcard stream configuration only affects the wildcard stream, not all routers")
	}

	if conf.HasValue("TimeoutMs") {
		timeout := time.Duration(conf.GetInt("TimeoutMs", 0)) * time.Millisecond
		router.Timeout = &timeout
	}

	return conf.Errors.OrNil()
}

// GetID returns the ID of this stream
func (router *SimpleRouter) GetID() string {
	return router.id
}

// StreamID returns the id of the stream this plugin is bound to.
func (router *SimpleRouter) StreamID() MessageStreamID {
	return router.streamID
}

// AddProducer adds all producers to the list of known producers.
// Duplicates will be filtered.
func (router *SimpleRouter) AddProducer(producers ...Producer) {
	for _, prod := range producers {
		for _, inListProd := range router.Producers {
			if inListProd == prod {
				return // ### return, already in list ###
			}
		}
		router.Producers = append(router.Producers, prod)
	}
}

// GetProducers returns the producers bound to this stream
func (router *SimpleRouter) GetProducers() []Producer {
	return router.Producers
}

// Modulate calls all modulators in their order of definition
func (router *SimpleRouter) Modulate(msg *Message) ModulateResult {
	return router.modulators.Modulate(msg)
}
<|endoftext|>


<commit_before>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	// "strings"
	"sync"
	"time"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"

	"flag"
)

var mutex = new(sync.Mutex)
var conn dbox.IConnection

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

var (
	masters    = toolkit.M{}
	t0         time.Time
	fiscalyear int
)

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func getCursor(obj orm.IModel) dbox.ICursor {
	c, e := gdrj.Find(obj,
		nil, nil)
	//toolkit.M{}.Set("take", 10))
	if e != nil {
		return nil
	}
	return c
}

func prepmaster() {
	toolkit.Println("--> PL Model")
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))

	toolkit.Println("--> Sub Channel")
	subchannels := toolkit.M{}
	csr, _ := conn.NewQuery().From("subchannels").Cursor(nil)
	defer csr.Close()
	for {
		m := toolkit.M{}
		e := csr.Fetch(&m, 1, false)
		if e != nil {
			break
		}
		subchannels.Set(m.GetString("_id"), m.GetString("title"))
	}
	masters.Set("subchannels", subchannels)

	toolkit.Println("--> Customer")
	customers := toolkit.M{}
	ccb := getCursor(new(gdrj.Customer))
	defer ccb.Close()
	for {
		cust := new(gdrj.Customer)
		e := ccb.Fetch(cust, 1, false)
		if e != nil {
			break
		}

		customers.Set(cust.ID, cust)
	}
	masters.Set("customers", customers)

	branchs := toolkit.M{}
	cmb := getCursor(new(gdrj.MasterBranch))
	defer cmb.Close()
	for {
		stx := toolkit.M{}
		e := cmb.Fetch(&stx, 1, false)
		if e != nil {
			break
		}

		branchs.Set(stx.Get("_id", "").(string), stx)
	}
	masters.Set("branchs", branchs)

	//Another master

}

func main() {

	t0 = time.Now()
	flag.IntVar(&fiscalyear, "year", 2015, "fiscal year to process. default is 2015")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	setinitialconnection()
	defer gdrj.CloseDb()

	var f *dbox.Filter
	f = dbox.And(dbox.Gte("date", speriode), dbox.Lt("date", eperiode))
	f = dbox.Or(dbox.Eq("_id", "RD_2014_4_40007354_24260"),
		dbox.Eq("_id", "EXPORT_2014_4_40007767_13"),
		dbox.Eq("_id", "VDIST/2015-2014/FK/IPR/14003129_CD04_2"))

	toolkit.Printfn("Prepare : %v", t0)
	prepmaster()

	toolkit.Printfn("Run : %v", t0)

	c, _ := gdrj.Find(new(gdrj.SalesTrx), f, nil)
	defer c.Close()

	count := c.Count()
	jobs := make(chan *gdrj.SalesTrx, count)
	result := make(chan string, count)
	for wi := 0; wi < 10; wi++ {
		go workerproc(wi, jobs, result)
	}

	step := count / 100
	i := 0
	toolkit.Printfn("START ... %d records ", count)
	for {
		stx := new(gdrj.SalesTrx)
		e := c.Fetch(stx, 1, false)
		if e != nil {
			break
		}

		i++
		jobs <- stx
		if i%step == 0 {
			toolkit.Printfn("Sending %d of %d (%d) in %s",
				i, count, i/step,
				time.Since(t0).String())
		}
	}

	close(jobs)

	for ri := 0; ri < i; ri++ {
		<-result

		if ri%step == 0 {
			toolkit.Printfn("Saving %d of %d (%d pct) in %s",
				ri, count, ri/step, time.Since(t0).String())
		}
	}
}

func workerproc(wi int, jobs <-chan *gdrj.SalesTrx, result chan<- string) {
	workerconn, _ := modules.GetDboxIConnection("db_godrej")
	defer workerconn.Close()

	trx := new(gdrj.SalesTrx)
	for trx = range jobs {
		pl := new(gdrj.SalesPL)

		pl.ID = trx.ID
		pl.SKUID = trx.SKUID
		pl.SKUID_VDIST = trx.SKUID_VDIST
		pl.OutletID = trx.OutletID

		pl.Date = gdrj.SetDate(trx.Date)

		pl.SalesQty = trx.SalesQty
		pl.GrossAmount = trx.GrossAmount
		pl.DiscountAmount = trx.DiscountAmount
		pl.TaxAmount = trx.TaxAmount

		pl.Customer = trx.Customer
		pl.Product = trx.Product

		pl.CleanAndClasify(masters)

		pl.CalcSales(masters)
		pl.CalcSum(masters)

		tablename := toolkit.Sprintf("%v-1", pl.TableName())
		workerconn.NewQuery().From(tablename).
			Save().Exec(toolkit.M{}.Set("data", pl))

		result <- pl.ID
	}
}
<commit_msg>update<commit_after>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	// "strings"
	"sync"
	"time"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"

	"flag"
)

var mutex = new(sync.Mutex)
var conn dbox.IConnection

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

var (
	masters    = toolkit.M{}
	t0         time.Time
	fiscalyear int
)

func buildmap(holder interface{},
	fnModel func() orm.IModel,
	filter *dbox.Filter,
	fnIter func(holder interface{}, obj interface{})) interface{} {
	crx, _ := gdrj.Find(fnModel(), filter, nil)
	defer crx.Close()
	for {
		s := fnModel()
		e := crx.Fetch(s, 1, false)
		if e != nil {
			break
		}
		fnIter(holder, s)
	}
	return holder
}

func getCursor(obj orm.IModel) dbox.ICursor {
	c, e := gdrj.Find(obj,
		nil, nil)
	//toolkit.M{}.Set("take", 10))
	if e != nil {
		return nil
	}
	return c
}

func prepmaster() {
	toolkit.Println("--> PL Model")
	masters.Set("plmodel", buildmap(map[string]*gdrj.PLModel{},
		func() orm.IModel {
			return new(gdrj.PLModel)
		},
		nil,
		func(holder, obj interface{}) {
			h := holder.(map[string]*gdrj.PLModel)
			o := obj.(*gdrj.PLModel)
			h[o.ID] = o
		}).(map[string]*gdrj.PLModel))

	toolkit.Println("--> Sub Channel")
	subchannels := toolkit.M{}
	csr, _ := conn.NewQuery().From("subchannels").Cursor(nil)
	defer csr.Close()
	for {
		m := toolkit.M{}
		e := csr.Fetch(&m, 1, false)
		if e != nil {
			break
		}
		subchannels.Set(m.GetString("_id"), m.GetString("title"))
	}
	masters.Set("subchannels", subchannels)

	toolkit.Println("--> Customer")
	customers := toolkit.M{}
	ccb := getCursor(new(gdrj.Customer))
	defer ccb.Close()
	for {
		cust := new(gdrj.Customer)
		e := ccb.Fetch(cust, 1, false)
		if e != nil {
			break
		}

		customers.Set(cust.ID, cust)
	}
	masters.Set("customers", customers)

	branchs := toolkit.M{}
	cmb := getCursor(new(gdrj.MasterBranch))
	defer cmb.Close()
	for {
		stx := toolkit.M{}
		e := cmb.Fetch(&stx, 1, false)
		if e != nil {
			break
		}

		branchs.Set(stx.Get("_id", "").(string), stx)
	}
	masters.Set("branchs", branchs)

	//Another master

}

func main() {

	t0 = time.Now()
	flag.IntVar(&fiscalyear, "year", 2015, "fiscal year to process. default is 2015")
	flag.Parse()

	eperiode := time.Date(fiscalyear, 4, 1, 0, 0, 0, 0, time.UTC)
	speriode := eperiode.AddDate(-1, 0, 0)

	setinitialconnection()
	defer gdrj.CloseDb()

	var f *dbox.Filter
	f = dbox.And(dbox.Gte("date", speriode), dbox.Lt("date", eperiode))
	// f = dbox.Or(dbox.Eq("_id", "RD_2014_4_40007354_24260"),dbox.Eq("_id", "EXPORT_2014_4_40007767_13"),dbox.Eq("_id", "VDIST/2015-2014/FK/IPR/14003129_CD04_2"))

	toolkit.Printfn("Prepare : %v", t0)
	prepmaster()

	toolkit.Printfn("Run : %v", t0)

	c, _ := gdrj.Find(new(gdrj.SalesTrx), f, nil)
	defer c.Close()

	count := c.Count()
	jobs := make(chan *gdrj.SalesTrx, count)
	result := make(chan string, count)
	for wi := 0; wi < 10; wi++ {
		go workerproc(wi, jobs, result)
	}

	step := count / 100
	i := 0
	toolkit.Printfn("START ... %d records ", count)
	for {
		stx := new(gdrj.SalesTrx)
		e := c.Fetch(stx, 1, false)
		if e != nil {
			break
		}

		i++
		jobs <- stx
		if i%step == 0 {
			toolkit.Printfn("Sending %d of %d (%d) in %s",
				i, count, i/step,
				time.Since(t0).String())
		}
	}

	close(jobs)

	for ri := 0; ri < i; ri++ {
		<-result

		if ri%step == 0 {
			toolkit.Printfn("Saving %d of %d (%d pct) in %s",
				ri, count, ri/step, time.Since(t0).String())
		}
	}
}

func workerproc(wi int, jobs <-chan *gdrj.SalesTrx, result chan<- string) {
	workerconn, _ := modules.GetDboxIConnection("db_godrej")
	defer workerconn.Close()

	trx := new(gdrj.SalesTrx)
	for trx = range jobs {
		pl := new(gdrj.SalesPL)

		pl.ID = trx.ID
		pl.SKUID = trx.SKUID
		pl.SKUID_VDIST = trx.SKUID_VDIST
		pl.OutletID = trx.OutletID

		pl.Date = gdrj.SetDate(trx.Date)

		pl.SalesQty = trx.SalesQty
		pl.GrossAmount = trx.GrossAmount
		pl.DiscountAmount = trx.DiscountAmount
		pl.TaxAmount = trx.TaxAmount

		pl.Customer = trx.Customer
		pl.Product = trx.Product

		pl.CleanAndClasify(masters)

		pl.CalcSales(masters)
		pl.CalcSum(masters)

		tablename := toolkit.Sprintf("%v-1", pl.TableName())
		workerconn.NewQuery().From(tablename).
			Save().Exec(toolkit.M{}.Set("data", pl))

		result <- pl.ID
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package util

import (
	"strings"
)

const (
	uriPrefix      = "file://"
	unixSep        = "/"
	windowColonRep = "%3A"
	colon          = ":"
	windowsSep     = "\\"
)

// ConvertURItoFilePath - converts file uri (eg: file://example.spec) to OS specific file paths.
func ConvertURItoFilePath(uri string) string {
	if IsWindows() {
		return convertURIToWindowsPath(uri)
	}
	return convertURIToUnixPath(uri)
}

func convertURIToWindowsPath(uri string) string {
	uri = strings.TrimPrefix(uri, uriPrefix+unixSep)
	uri = strings.Replace(uri, windowColonRep, colon, -1)
	return strings.Replace(uri, unixSep, windowsSep, -1)
}

func convertURIToUnixPath(uri string) string {
	return strings.TrimPrefix(uri, uriPrefix)
}

// ConvertPathToURI - converts OS specific file paths to file uri (eg: file://example.spec).
func ConvertPathToURI(path string) string {
	if IsWindows() {
		return convertWindowsPathToURI(path)
	}
	return convertUnixPathToURI(path)
}

func convertWindowsPathToURI(path string) string {
	path = strings.Replace(path, colon, windowColonRep, -1)
	return uriPrefix + unixSep + strings.Replace(path, windowsSep, unixSep, -1)
}

func convertUnixPathToURI(path string) string {
	return uriPrefix + path
}
<commit_msg>Handling project with space in path getgauge/gauge-vscode#50<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

// Gauge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Gauge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package util

import (
	"strings"
	"net/url"
)

const (
	uriPrefix      = "file://"
	unixSep        = "/"
	windowColonRep = "%3A"
	colon          = ":"
	windowsSep     = "\\"
)

// ConvertURItoFilePath - converts file uri (eg: file://example.spec) to OS specific file paths.
func ConvertURItoFilePath(uri string) string {
	if IsWindows() {
		return convertURIToWindowsPath(uri)
	}
	return convertURIToUnixPath(uri)
}

func convertURIToWindowsPath(uri string) string {
	uri = strings.TrimPrefix(uri, uriPrefix+unixSep)
	uri = strings.Replace(uri, windowColonRep, colon, -1)
	path,_ := url.PathUnescape(strings.Replace(uri, unixSep, windowsSep, -1))
	return path
}

func convertURIToUnixPath(uri string) string {
	path,_ := url.PathUnescape(uri)
	return strings.TrimPrefix(path, uriPrefix)
}

// ConvertPathToURI - converts OS specific file paths to file uri (eg: file://example.spec).
func ConvertPathToURI(path string) string {
	if IsWindows() {
		return convertWindowsPathToURI(path)
	}
	return convertUnixPathToURI(path)
}

func convertWindowsPathToURI(path string) string {
	path = strings.Replace(path, windowsSep, unixSep, -1)
	encodedPath := url.URL{Path: path}
	path = strings.Replace(strings.TrimPrefix(encodedPath.String(), "./"), colon, windowColonRep, -1)
	return uriPrefix + unixSep + path
}

func convertUnixPathToURI(path string) string {
	encodedPath := url.URL{Path:path}
	return uriPrefix + encodedPath.String()
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2016 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 simplebft

func (s *SBFT) testBacklog(m *Msg, src uint64) bool {
	if len(s.backLog[src]) > 0 {
		return true
	}

	return s.testBacklog2(m, src)
}

func (s *SBFT) testBacklog2(m *Msg, src uint64) bool {
	record := func(seq uint64) bool {
		if seq > s.cur.subject.Seq.Seq {
			return true
		}
		return false
	}

	if pp := m.GetPreprepare(); pp != nil && !s.cur.executed {
		return true
	} else if p := m.GetPrepare(); p != nil {
		return record(p.Seq.Seq)
	} else if c := m.GetCommit(); c != nil {
		return record(c.Seq.Seq)
	} else if c := m.GetCheckpoint(); c != nil {
		return record(c.Seq)
	}
	return false
}

func (s *SBFT) recordBacklogMsg(m *Msg, src uint64) {
	s.backLog[src] = append(s.backLog[src], m)
}

func (s *SBFT) processBacklog() {
	processed := true

	for processed {
		processed = false
		for src, _ := range s.backLog {
			for len(s.backLog[src]) > 0 {
				m, rest := s.backLog[src][0], s.backLog[src][1:]
				if s.testBacklog2(m, src) {
					break
				}
				s.backLog[src] = rest

				log.Debugf("processing stored message from %d: %s", src, m)

				s.handleQueueableMessage(m, src)
				processed = true
			}
		}
	}
}
<commit_msg>add comment about DoS<commit_after>/*
Copyright IBM Corp. 2016 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 simplebft

func (s *SBFT) testBacklog(m *Msg, src uint64) bool {
	if len(s.backLog[src]) > 0 {
		return true
	}

	return s.testBacklog2(m, src)
}

func (s *SBFT) testBacklog2(m *Msg, src uint64) bool {
	record := func(seq uint64) bool {
		if seq > s.cur.subject.Seq.Seq {
			return true
		}
		return false
	}

	if pp := m.GetPreprepare(); pp != nil && !s.cur.executed {
		return true
	} else if p := m.GetPrepare(); p != nil {
		return record(p.Seq.Seq)
	} else if c := m.GetCommit(); c != nil {
		return record(c.Seq.Seq)
	} else if c := m.GetCheckpoint(); c != nil {
		return record(c.Seq)
	}
	return false
}

func (s *SBFT) recordBacklogMsg(m *Msg, src uint64) {
	// TODO prevent DoS by limiting the number of messages per replica
	s.backLog[src] = append(s.backLog[src], m)
}

func (s *SBFT) processBacklog() {
	processed := true

	for processed {
		processed = false
		for src, _ := range s.backLog {
			for len(s.backLog[src]) > 0 {
				m, rest := s.backLog[src][0], s.backLog[src][1:]
				if s.testBacklog2(m, src) {
					break
				}
				s.backLog[src] = rest

				log.Debugf("processing stored message from %d: %s", src, m)

				s.handleQueueableMessage(m, src)
				processed = true
			}
		}
	}
}
<|endoftext|>


<commit_before>package colonycore

import (
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
)

func (ds *WebGrabber) TableName() string {
	return "webgrabbers"
}

func (ds *WebGrabber) RecordID() interface{} {
	return ds.ID
}

type WebGrabber struct {
	orm.ModelBase
	ID           string          `json:"_id",bson:"_id"`
	SourceType   string          `json:"sourcetype",bson:"sourcetype"`
	GrabConf     toolkit.M       `json:"grabconf",bson:"grabconf"`
	IntervalConf *IntervalConf   `json:"intervalconf",bson:"intervalconf"`
	LogConf      *LogConf        `json:"logconf",bson:"logconf"`
	HistConf     *HistConf       `json:"histconf",bson:"histconf"`
	DataSettings []*DataSettings `json:"datasettings",bson:"datasettings"`
	Running      bool            `json:"running",bson:"running"`
}

type IntervalConf struct {
	StartTime       string    `json:"starttime",bson:"starttime"`
	ExpiredTime     string    `json:"expiredtime",bson:"expiredtime"`
	IntervalType    string    `json:"intervaltype",bson:"intervaltype"`
	GrabInterval    int       `json:"grabinterval",bson:"grabinterval"`
	TimeoutInterval int       `json:"timeoutinterval",bson:"timeoutinterval"`
	CronConf        toolkit.M `json:"cronconf",bson:"cronconf"`
}

type LogConf struct {
	LogPath     string `json:"logpath",bson:"logpath"`
	FileName    string `json:"filename",bson:"filename"`
	FilePattern string `json:"filepattern",bson:"filepattern"`
}

type HistConf struct {
	Histpath    string `json:"histpath",bson:"histpath"`
	RecPath     string `json:"recpath",bson:"recpath"`
	FileName    string `json:"filename",bson:"filename"`
	FilePattern string `json:"filepattern",bson:"filepattern"`
}

type DataSettings struct {
	Nameid         string            `json:"nameid",bson:"nameid"`
	RowSelector    string            `json:"rowselector",bson:"rowselector"`
	ColumnSettings []*ColumnSettings `json:"columnsettings",bson:"columnsettings"`
	FilterCond     toolkit.M         `json:"filtercond",bson:"filtercond"`
	DestOutputType string            `json:"destoutputtype",bson:"destoutputtype"`
	DestType       string            `json:"desttype",bson:"desttype"`
	ConnectionInfo *ConnectionInfo   `json:"connectioninfo",bson:"connectioninfo"`
}

type ColumnSettings struct {
	Index     int    `json:"index",bson:"index"`
	Alias     string `json:"alias",bson:"alias"`
	Selector  string `json:"selector",bson:"selector"`
	ValueType string `json:"valuetype",bson:"valuetype"`
	AttrName  string `json:"attrname",bson:"attrname"`
}

type ConnectionInfo struct {
	ConnectionID string    `json:"connectionid",bson:"connectionid"`
	Host         string    `json:"host",bson:"host"`
	UserName     string    `json:"username",bson:"username"`
	Password     string    `json:"password",bson:"password"`
	Database     string    `json:"database",bson:"database"`
	Collection   string    `json:"collection",bson:"collection"`
	Settings     toolkit.M `json:"settings",bson:"settings"`
}
<commit_msg>add LimitRow  in DataSettings<commit_after>package colonycore

import (
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
)

func (ds *WebGrabber) TableName() string {
	return "webgrabbers"
}

func (ds *WebGrabber) RecordID() interface{} {
	return ds.ID
}

type WebGrabber struct {
	orm.ModelBase
	ID           string          `json:"_id",bson:"_id"`
	SourceType   string          `json:"sourcetype",bson:"sourcetype"`
	GrabConf     toolkit.M       `json:"grabconf",bson:"grabconf"`
	IntervalConf *IntervalConf   `json:"intervalconf",bson:"intervalconf"`
	LogConf      *LogConf        `json:"logconf",bson:"logconf"`
	HistConf     *HistConf       `json:"histconf",bson:"histconf"`
	DataSettings []*DataSettings `json:"datasettings",bson:"datasettings"`
	Running      bool            `json:"running",bson:"running"`
}

type IntervalConf struct {
	StartTime       string    `json:"starttime",bson:"starttime"`
	ExpiredTime     string    `json:"expiredtime",bson:"expiredtime"`
	IntervalType    string    `json:"intervaltype",bson:"intervaltype"`
	GrabInterval    int       `json:"grabinterval",bson:"grabinterval"`
	TimeoutInterval int       `json:"timeoutinterval",bson:"timeoutinterval"`
	CronConf        toolkit.M `json:"cronconf",bson:"cronconf"`
}

type LogConf struct {
	LogPath     string `json:"logpath",bson:"logpath"`
	FileName    string `json:"filename",bson:"filename"`
	FilePattern string `json:"filepattern",bson:"filepattern"`
}

type HistConf struct {
	Histpath    string `json:"histpath",bson:"histpath"`
	RecPath     string `json:"recpath",bson:"recpath"`
	FileName    string `json:"filename",bson:"filename"`
	FilePattern string `json:"filepattern",bson:"filepattern"`
}

type DataSettings struct {
	Nameid         string            `json:"nameid",bson:"nameid"`
	RowSelector    string            `json:"rowselector",bson:"rowselector"`
	ColumnSettings []*ColumnSettings `json:"columnsettings",bson:"columnsettings"`

	LimitRow       toolkit.M       `json:"limitrow",bson:"limitrow"`
	FilterCond     toolkit.M       `json:"filtercond",bson:"filtercond"`
	DestOutputType string          `json:"destoutputtype",bson:"destoutputtype"`
	DestType       string          `json:"desttype",bson:"desttype"`
	ConnectionInfo *ConnectionInfo `json:"connectioninfo",bson:"connectioninfo"`
}

type ColumnSettings struct {
	Index     int    `json:"index",bson:"index"`
	Alias     string `json:"alias",bson:"alias"`
	Selector  string `json:"selector",bson:"selector"`
	ValueType string `json:"valuetype",bson:"valuetype"`
	AttrName  string `json:"attrname",bson:"attrname"`
}

type ConnectionInfo struct {
	ConnectionID string    `json:"connectionid",bson:"connectionid"`
	Host         string    `json:"host",bson:"host"`
	UserName     string    `json:"username",bson:"username"`
	Password     string    `json:"password",bson:"password"`
	Database     string    `json:"database",bson:"database"`
	Collection   string    `json:"collection",bson:"collection"`
	Settings     toolkit.M `json:"settings",bson:"settings"`
}
<|endoftext|>


<commit_before>package geometry

import (
	"math"
	"testing"
)

func TestNewVector3D(t *testing.T) {
	if !NewVector3D(1, 2, 3).Equal(&Vector3D{1, 2, 3}) {
		t.Error("NewVector3D")
	}
}

func Benchmark_Vector3D_New(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewVector3D(0, 0, 0)
	}
}

func TestVector3DAdd(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if !r.Add(v1, v2).Equal(&Vector3D{4, 6, 11}) {
		t.Error("Vector3D.Add")
	}
}

func Benchmark_Vector3D_Add(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		r.Add(v1, v2)
	}
}

func TestVector3DCopy(t *testing.T) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}
	if !v1.Copy(v2).Equal(v2) {
		t.Error("Vector3D.Copy")
	}
}

func Benchmark_Vector3D_Copy(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}
	for i := 0; i < b.N; i++ {
		v1.Copy(v2)
	}
}

func TestVector3DCrossProduct(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}, &Vector3D{4, 5, 6}
	if !r.CrossProduct(v1, v2).Equal(&Vector3D{-3, 6, -3}) {
		t.Error("Vector3D.CrossProduct")
	}
}

func Benchmark_Vector3D_CrossProduct(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}, &Vector3D{4, 5, 6}
	for i := 0; i < b.N; i++ {
		r.CrossProduct(v1, v2)
	}
}

type vector3DDirectionEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DDirectionEqualValues = []vector3DDirectionEqualData{
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{-2, -2, -2}, false},
	{Vector3D{1, 0, 0}, Vector3D{2, 0, 0}, true},
	{Vector3D{1, 0, 0}, Vector3D{-2, 0, 0}, false},
	{Vector3D{0, 1, 0}, Vector3D{0, 2, 0}, true},
	{Vector3D{0, 1, 0}, Vector3D{0, -2, 0}, false},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, 2}, true},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, -2}, false},
}

func testVector3DDirectionEqual(d vector3DDirectionEqualData, t *testing.T) {
	if d.v1.DirectionEqual(&d.v2) != d.equal {
		t.Error("Vector3D.DirectionEqual", d.v1, d.v2, "want", d.equal)
	}
	if d.v2.DirectionEqual(&d.v1) != d.equal {
		t.Error("Vector3D.DirectionEqual", d.v2, d.v1, "want", d.equal)
	}
}

func TestVector3DDirectionEqual(t *testing.T) {
	for _, v := range vector3DDirectionEqualValues {
		testVector3DDirectionEqual(v, t)
	}
}

func Benchmark_Vector3D_DirectionEqual(b *testing.B) {
	v1, v2 := &Vector3D{1, 1, 1}, &Vector3D{2, 2, 2}
	// v1, v2 := &Vector3D{0, 0, 1}, &Vector3D{0, 0, 2}
	for i := 0; i < b.N; i++ {
		v1.DirectionEqual(v2)
	}
}

type vector3DDirectionFuzzyEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DDirectionFuzzyEqualValues = []vector3DDirectionFuzzyEqualData{
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2 + 1e-11}, false},
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2 + 1e-12}, true},
	{Vector3D{1, 1, 1}, Vector3D{2, 2 + 1e-11, 2}, false},
	{Vector3D{1, 1, 1}, Vector3D{2, 2 + 1e-12, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{2 + 1e-11, 2, 2}, false},
	{Vector3D{1, 1, 1}, Vector3D{2 + 1e-12, 2, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-12, 1, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-13, 1, 1}, true},
	{Vector3D{1, 0, 0}, Vector3D{2, 0, 0}, true},
	{Vector3D{1, 0, 0}, Vector3D{-2, 0, 0}, false},
	{Vector3D{0, 1, 0}, Vector3D{0, 2, 0}, true},
	{Vector3D{0, 1, 0}, Vector3D{0, -2, 0}, false},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, 2}, true},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, -2}, false},
}

func testVector3DDirectionFuzzyEqual(d vector3DDirectionFuzzyEqualData, t *testing.T) {
	if d.v1.DirectionFuzzyEqual(&d.v2) != d.equal {
		t.Error("Vector3D.DirectionFuzzyEqual", d.v1, d.v2, "want", d.equal)
	}
	if d.v2.DirectionFuzzyEqual(&d.v1) != d.equal {
		t.Error("Vector3D.DirectionFuzzyEqual", d.v2, d.v1, "want", d.equal)
	}
}

func TestVector3DDirectionFuzzyEqual(t *testing.T) {
	for _, v := range vector3DDirectionFuzzyEqualValues {
		testVector3DDirectionFuzzyEqual(v, t)
	}
}

func Benchmark_Vector3D_DirectionFuzzyEqual(b *testing.B) {
	v1, v2 := &Vector3D{1, 1, 1}, &Vector3D{2, 2, 2}
	// v1, v2 := &Vector3D{0, 0, 1}, &Vector3D{0, 0, 2}
	for i := 0; i < b.N; i++ {
		v1.DirectionFuzzyEqual(v2)
	}
}

func TestVector3DDotProduct(t *testing.T) {
	v1, v2 := &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if v1.DotProduct(v2) != 41 {
		t.Error("Vector3D.DotProduct")
	}
}

func Benchmark_Vector3D_DotProduct(b *testing.B) {
	v1, v2 := &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		v1.DotProduct(v2)
	}
}

func TestVector3DEqual(t *testing.T) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	if v1.Equal(v2) {
		t.Error("Vector3D.Equal")
	}
	v2.X = 0
	if !v1.Equal(v2) {
		t.Error("Vector3D.Equal")
	}
}

func Benchmark_Vector3D_Equal(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	for i := 0; i < b.N; i++ {
		v1.Equal(v2)
	}
}

type vector3DFuzzyEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DFuzzyEqualValues = []vector3DFuzzyEqualData{
	{Vector3D{1, 1, 1}, Vector3D{1, 1, 1 + 1e-12}, false},
	{Vector3D{1, 1, 1}, Vector3D{1, 1, 1 + 1e-13}, true},
	{Vector3D{1, 1, 1}, Vector3D{1, 1 + 1e-12, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1, 1 + 1e-13, 1}, true},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-12, 1, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-13, 1, 1}, true},
}

func testVector3DFuzzyEqual(d vector3DFuzzyEqualData, t *testing.T) {
	if d.v1.FuzzyEqual(&d.v2) != d.equal {
		t.Error("Vector3D.FuzzyEqual", d.v1, d.v2, d.equal)
	}
	if d.v2.FuzzyEqual(&d.v1) != d.equal {
		t.Error("Vector3D.FuzzyEqual", d.v2, d.v1, d.equal)
	}
}

func TestVector3DFuzzyEqual(t *testing.T) {
	for _, v := range vector3DFuzzyEqualValues {
		testVector3DFuzzyEqual(v, t)
	}
}

func Benchmark_Vector3D_FuzzyEqual(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	for i := 0; i < b.N; i++ {
		v1.FuzzyEqual(v2)
	}
}

func TestVector3DMagnitude(t *testing.T) {
	v := &Vector3D{3, 4, 5}
	if v.Magnitude() != math.Sqrt(50) {
		t.Error("Vector3D.Magnitude")
	}
}

func Benchmark_Vector3D_Magnitude(b *testing.B) {
	v := &Vector3D{3, 4, 5}
	for i := 0; i < b.N; i++ {
		v.Magnitude()
	}
}

func TestVector3DMagnitudeSquared(t *testing.T) {
	v := &Vector3D{3, 4, 5}
	if v.MagnitudeSquared() != 50 {
		t.Error("Vector3D.MagnitudeSquared")
	}
}

func Benchmark_Vector3D_MagnitudeSquared(b *testing.B) {
	v := &Vector3D{3, 4, 5}
	for i := 0; i < b.N; i++ {
		v.MagnitudeSquared()
	}
}

func TestVector3DNormalize(t *testing.T) {
	s := 1 / math.Sqrt(29)
	v1, v2 := &Vector3D{2, 3, 4}, &Vector3D{s * 2, s * 3, s * 4}
	if !v1.Normalize(v1).FuzzyEqual(v2) {
		t.Error("Vector3D.Normalize")
	}
}

func Benchmark_Vector3D_Normalize(b *testing.B) {
	v1, v2 := &Vector3D{2, 3, 4}, &Vector3D{}
	for i := 0; i < b.N; i++ {
		v1.Normalize(v2)
	}
}

func TestVector3DSubtract(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if !r.Subtract(v1, v2).Equal(&Vector3D{-2, -2, -1}) {
		t.Error("Vector3D.Subtract")
	}
}

func Benchmark_Vector3D_Subtract(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		r.Subtract(v1, v2)
	}
}
<commit_msg>Added 3D vector divide test and benchmark.<commit_after>package geometry

import (
	"math"
	"testing"
)

func TestNewVector3D(t *testing.T) {
	if !NewVector3D(1, 2, 3).Equal(&Vector3D{1, 2, 3}) {
		t.Error("NewVector3D")
	}
}

func Benchmark_Vector3D_New(b *testing.B) {
	for i := 0; i < b.N; i++ {
		NewVector3D(0, 0, 0)
	}
}

func TestVector3DAdd(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if !r.Add(v1, v2).Equal(&Vector3D{4, 6, 11}) {
		t.Error("Vector3D.Add")
	}
}

func Benchmark_Vector3D_Add(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		r.Add(v1, v2)
	}
}

func TestVector3DCopy(t *testing.T) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}
	if !v1.Copy(v2).Equal(v2) {
		t.Error("Vector3D.Copy")
	}
}

func Benchmark_Vector3D_Copy(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}
	for i := 0; i < b.N; i++ {
		v1.Copy(v2)
	}
}

func TestVector3DCrossProduct(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}, &Vector3D{4, 5, 6}
	if !r.CrossProduct(v1, v2).Equal(&Vector3D{-3, 6, -3}) {
		t.Error("Vector3D.CrossProduct")
	}
}

func Benchmark_Vector3D_CrossProduct(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 3}, &Vector3D{4, 5, 6}
	for i := 0; i < b.N; i++ {
		r.CrossProduct(v1, v2)
	}
}

type vector3DDirectionEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DDirectionEqualValues = []vector3DDirectionEqualData{
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{-2, -2, -2}, false},
	{Vector3D{1, 0, 0}, Vector3D{2, 0, 0}, true},
	{Vector3D{1, 0, 0}, Vector3D{-2, 0, 0}, false},
	{Vector3D{0, 1, 0}, Vector3D{0, 2, 0}, true},
	{Vector3D{0, 1, 0}, Vector3D{0, -2, 0}, false},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, 2}, true},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, -2}, false},
}

func testVector3DDirectionEqual(d vector3DDirectionEqualData, t *testing.T) {
	if d.v1.DirectionEqual(&d.v2) != d.equal {
		t.Error("Vector3D.DirectionEqual", d.v1, d.v2, "want", d.equal)
	}
	if d.v2.DirectionEqual(&d.v1) != d.equal {
		t.Error("Vector3D.DirectionEqual", d.v2, d.v1, "want", d.equal)
	}
}

func TestVector3DDirectionEqual(t *testing.T) {
	for _, v := range vector3DDirectionEqualValues {
		testVector3DDirectionEqual(v, t)
	}
}

func Benchmark_Vector3D_DirectionEqual(b *testing.B) {
	v1, v2 := &Vector3D{1, 1, 1}, &Vector3D{2, 2, 2}
	// v1, v2 := &Vector3D{0, 0, 1}, &Vector3D{0, 0, 2}
	for i := 0; i < b.N; i++ {
		v1.DirectionEqual(v2)
	}
}

type vector3DDirectionFuzzyEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DDirectionFuzzyEqualValues = []vector3DDirectionFuzzyEqualData{
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2 + 1e-11}, false},
	{Vector3D{1, 1, 1}, Vector3D{2, 2, 2 + 1e-12}, true},
	{Vector3D{1, 1, 1}, Vector3D{2, 2 + 1e-11, 2}, false},
	{Vector3D{1, 1, 1}, Vector3D{2, 2 + 1e-12, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{2 + 1e-11, 2, 2}, false},
	{Vector3D{1, 1, 1}, Vector3D{2 + 1e-12, 2, 2}, true},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-12, 1, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-13, 1, 1}, true},
	{Vector3D{1, 0, 0}, Vector3D{2, 0, 0}, true},
	{Vector3D{1, 0, 0}, Vector3D{-2, 0, 0}, false},
	{Vector3D{0, 1, 0}, Vector3D{0, 2, 0}, true},
	{Vector3D{0, 1, 0}, Vector3D{0, -2, 0}, false},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, 2}, true},
	{Vector3D{0, 0, 1}, Vector3D{0, 0, -2}, false},
}

func testVector3DDirectionFuzzyEqual(d vector3DDirectionFuzzyEqualData, t *testing.T) {
	if d.v1.DirectionFuzzyEqual(&d.v2) != d.equal {
		t.Error("Vector3D.DirectionFuzzyEqual", d.v1, d.v2, "want", d.equal)
	}
	if d.v2.DirectionFuzzyEqual(&d.v1) != d.equal {
		t.Error("Vector3D.DirectionFuzzyEqual", d.v2, d.v1, "want", d.equal)
	}
}

func TestVector3DDirectionFuzzyEqual(t *testing.T) {
	for _, v := range vector3DDirectionFuzzyEqualValues {
		testVector3DDirectionFuzzyEqual(v, t)
	}
}

func Benchmark_Vector3D_DirectionFuzzyEqual(b *testing.B) {
	v1, v2 := &Vector3D{1, 1, 1}, &Vector3D{2, 2, 2}
	// v1, v2 := &Vector3D{0, 0, 1}, &Vector3D{0, 0, 2}
	for i := 0; i < b.N; i++ {
		v1.DirectionFuzzyEqual(v2)
	}
}

func TestVector3DDivide(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{2, 4, 6}, &Vector3D{2, 2, 2}
	if !r.Divide(v1, v2).Equal(&Vector3D{1, 2, 3}) {
		t.Error("Vector3D.Divide")
	}
}

func Benchmark_Vector3D_Divide(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{2, 4, 6}, &Vector3D{2, 2, 2}
	for i := 0; i < b.N; i++ {
		r.Divide(v1, v2)
	}
}

func TestVector3DDotProduct(t *testing.T) {
	v1, v2 := &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if v1.DotProduct(v2) != 41 {
		t.Error("Vector3D.DotProduct")
	}
}

func Benchmark_Vector3D_DotProduct(b *testing.B) {
	v1, v2 := &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		v1.DotProduct(v2)
	}
}

func TestVector3DEqual(t *testing.T) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	if v1.Equal(v2) {
		t.Error("Vector3D.Equal")
	}
	v2.X = 0
	if !v1.Equal(v2) {
		t.Error("Vector3D.Equal")
	}
}

func Benchmark_Vector3D_Equal(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	for i := 0; i < b.N; i++ {
		v1.Equal(v2)
	}
}

type vector3DFuzzyEqualData struct {
	v1, v2 Vector3D
	equal  bool
}

var vector3DFuzzyEqualValues = []vector3DFuzzyEqualData{
	{Vector3D{1, 1, 1}, Vector3D{1, 1, 1 + 1e-12}, false},
	{Vector3D{1, 1, 1}, Vector3D{1, 1, 1 + 1e-13}, true},
	{Vector3D{1, 1, 1}, Vector3D{1, 1 + 1e-12, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1, 1 + 1e-13, 1}, true},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-12, 1, 1}, false},
	{Vector3D{1, 1, 1}, Vector3D{1 + 1e-13, 1, 1}, true},
}

func testVector3DFuzzyEqual(d vector3DFuzzyEqualData, t *testing.T) {
	if d.v1.FuzzyEqual(&d.v2) != d.equal {
		t.Error("Vector3D.FuzzyEqual", d.v1, d.v2, d.equal)
	}
	if d.v2.FuzzyEqual(&d.v1) != d.equal {
		t.Error("Vector3D.FuzzyEqual", d.v2, d.v1, d.equal)
	}
}

func TestVector3DFuzzyEqual(t *testing.T) {
	for _, v := range vector3DFuzzyEqualValues {
		testVector3DFuzzyEqual(v, t)
	}
}

func Benchmark_Vector3D_FuzzyEqual(b *testing.B) {
	v1, v2 := &Vector3D{}, &Vector3D{1, 0, 0}
	for i := 0; i < b.N; i++ {
		v1.FuzzyEqual(v2)
	}
}

func TestVector3DMagnitude(t *testing.T) {
	v := &Vector3D{3, 4, 5}
	if v.Magnitude() != math.Sqrt(50) {
		t.Error("Vector3D.Magnitude")
	}
}

func Benchmark_Vector3D_Magnitude(b *testing.B) {
	v := &Vector3D{3, 4, 5}
	for i := 0; i < b.N; i++ {
		v.Magnitude()
	}
}

func TestVector3DMagnitudeSquared(t *testing.T) {
	v := &Vector3D{3, 4, 5}
	if v.MagnitudeSquared() != 50 {
		t.Error("Vector3D.MagnitudeSquared")
	}
}

func Benchmark_Vector3D_MagnitudeSquared(b *testing.B) {
	v := &Vector3D{3, 4, 5}
	for i := 0; i < b.N; i++ {
		v.MagnitudeSquared()
	}
}

func TestVector3DNormalize(t *testing.T) {
	s := 1 / math.Sqrt(29)
	v1, v2 := &Vector3D{2, 3, 4}, &Vector3D{s * 2, s * 3, s * 4}
	if !v1.Normalize(v1).FuzzyEqual(v2) {
		t.Error("Vector3D.Normalize")
	}
}

func Benchmark_Vector3D_Normalize(b *testing.B) {
	v1, v2 := &Vector3D{2, 3, 4}, &Vector3D{}
	for i := 0; i < b.N; i++ {
		v1.Normalize(v2)
	}
}

func TestVector3DSubtract(t *testing.T) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	if !r.Subtract(v1, v2).Equal(&Vector3D{-2, -2, -1}) {
		t.Error("Vector3D.Subtract")
	}
}

func Benchmark_Vector3D_Subtract(b *testing.B) {
	r, v1, v2 := &Vector3D{}, &Vector3D{1, 2, 5}, &Vector3D{3, 4, 6}
	for i := 0; i < b.N; i++ {
		r.Subtract(v1, v2)
	}
}
<|endoftext|>


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

package xmile_test

import (
	"bufio"
	"bytes"
	"fmt"
	xmile "github.com/bpowers/go-xmile/compat"
	"github.com/bpowers/go-xmile/smile"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"
	"text/template"
)

const dotTmpl = `
digraph model {
{{range $.Clouds}}
{{.}} [shape=none,label=""]{{end}}

{{range $.Stocks}}
{{.Name}} [shape=box]{{end}}

{{range $.Flows}}
{{.Name}} [shape=circle]{{end}}

{{range $.Auxs}}
{{.Name}} [shape=circle]{{end}}

{{range $.Stocks}}{{with $s := .}}{{range $.OutsC}}
{{$s.Name}} -> {{.}}{{end}}{{end}}{{end}}

{{range $.Auxs}}{{with $s := .}}{{range $.OutsC}}
{{$s.Name}} -> {{.}}{{end}}{{end}}{{end}}
}
`

type DotData struct {
	Clouds []string
	Stocks []VInfo
	Flows  []VInfo
	Auxs   []VInfo
}

// VInfo stores information about a var for use by dot.
//
// stock: only connectors out.
// flow: all 3, connector outs & flow ins and outs.
// aux: only outsc.
type VInfo struct {
	Name  string
	OutsC []string
	OutsF []string
	Ins   []string // only flows have ins
}

func normalizeName(n string) string {
	n = strings.Replace(n, `\n`, "_", -1)
	n = strings.ToLower(n)
	return n
}

func normalizeNames(f *xmile.File) {
	for _, m := range f.Models {
		for _, v := range m.Variables {
			v.Name = normalizeName(v.Name)
		}
	}
}

func writeDot(f *xmile.File) error {
	normalizeNames(f)

	for _, m := range f.Models {
		for _, v := range m.Variables {
			log.Printf("parsing (%s, '%s')", v.Name, v.Eqn)
			expr, err := smile.Parse(v.Name, v.Eqn)
			if err != nil {
				return fmt.Errorf("smile.Parse(%s, '%s'): %s", v.Name, v.Eqn, err)
			}
			_ = expr
		}

		var data DotData

		var buf bytes.Buffer
		tmpl := template.New("model.dot")
		if _, err := tmpl.Parse(dotTmpl); err != nil {
			return fmt.Errorf("tmpl.Parse(dotTmpl): %s", err)
		}
		if err := tmpl.Execute(&buf, &data); err != nil {
			return fmt.Errorf("tmpl.Execute: %s", err)
		}

		w := bufio.NewWriter(os.Stderr)
		defer w.Flush()
		w.Write(buf.Bytes())
		w.Write([]byte("\n"))
	}

	return nil
}

/*
func TestRead(t *testing.T) {
	contents, err := ioutil.ReadFile("../models/pred_prey.stmx")
	if err != nil {
		t.Fatalf("ioutil.ReadFile: %s", err)
	}

	f, err := xmile.ReadFile(contents)
	if err != nil {
		t.Fatalf("xmile.ReadFile: %s", err)
	}

	output, err := xml.MarshalIndent(f, "", "    ")
	if err != nil {
		t.Fatalf("xml.MarshalIndent: %s", err)
	}

	os.Stderr.Write([]byte(xmile.XMLDeclaration + "\n"))
	os.Stderr.Write(output)
	os.Stderr.Write([]byte("\n"))
}
*/

func TestDot(t *testing.T) {
	contents, err := ioutil.ReadFile("../models/pred_prey.stmx")
	if err != nil {
		t.Fatalf("ioutil.ReadFile: %s", err)
	}

	f, err := xmile.ReadFile(contents)
	if err != nil {
		t.Fatalf("xmile.ReadFile: %s", err)
	}

	f.Models[0].Interface = xmile.View{}
	if err := writeDot(f); err != nil {
		t.Fatalf("writeDot: %s", err)
	}
}
<commit_msg>xmile: start of getting list of referenced vars<commit_after>// Copyright 2013 Bobby Powers. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package xmile_test

import (
	"bufio"
	"bytes"
	"fmt"
	xmile "github.com/bpowers/go-xmile/compat"
	"github.com/bpowers/go-xmile/smile"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"
	"text/template"
)

const dotTmpl = `
digraph model {
{{range $.Clouds}}
{{.}} [shape=none,label=""]{{end}}

{{range $.Stocks}}
{{.Name}} [shape=box]{{end}}

{{range $.Flows}}
{{.Name}} [shape=circle]{{end}}

{{range $.Auxs}}
{{.Name}} [shape=circle]{{end}}

{{range $.Stocks}}{{with $s := .}}{{range $.OutsC}}
{{$s.Name}} -> {{.}}{{end}}{{end}}{{end}}

{{range $.Auxs}}{{with $s := .}}{{range $.OutsC}}
{{$s.Name}} -> {{.}}{{end}}{{end}}{{end}}
}
`

type DotData struct {
	Clouds []string
	Stocks []VInfo
	Flows  []VInfo
	Auxs   []VInfo
}

// VInfo stores information about a var for use by dot.
//
// stock: only connectors out.
// flow: all 3, connector outs & flow ins and outs.
// aux: only outsc.
type VInfo struct {
	Name  string
	OutsC []string
	OutsF []string
	Ins   []string // only flows have ins
}

func normalizeName(n string) string {
	n = strings.Replace(n, `\n`, "_", -1)
	n = strings.ToLower(n)
	return n
}

func normalizeNames(f *xmile.File) {
	for _, m := range f.Models {
		for _, v := range m.Variables {
			v.Name = normalizeName(v.Name)
		}
	}
}

func varMap(m *xmile.Model) map[string]*xmile.Variable {
	vm := make(map[string]*xmile.Variable)
	for _, v := range m.Variables {
		vm[normalizeName(v.Name)] = v
	}
	return vm
}

func refs(v *xmile.Variable) ([]string, error) {
	expr, err := smile.Parse(v.Name, v.Eqn)
	if err != nil {
		return nil, fmt.Errorf("smile.Parse(%s, '%s'): %s", v.Name, v.Eqn, err)
	}
	_ = expr
	return nil, nil
}

func writeDot(f *xmile.File) error {
	normalizeNames(f)

	for _, m := range f.Models {
		vm := varMap(m)
		for _, v := range m.Variables {
			outs, err := refs(v)
			log.Printf("var %s refs %v", v.Name, outs)
			if err != nil {
				return fmt.Errorf("refs(%s,'%s'): %s", v.Name, v.Eqn, err)
			}
			_ = outs
		}
		_ = vm

		var data DotData

		var buf bytes.Buffer
		tmpl := template.New("model.dot")
		if _, err := tmpl.Parse(dotTmpl); err != nil {
			return fmt.Errorf("tmpl.Parse(dotTmpl): %s", err)
		}
		if err := tmpl.Execute(&buf, &data); err != nil {
			return fmt.Errorf("tmpl.Execute: %s", err)
		}

		w := bufio.NewWriter(os.Stderr)
		defer w.Flush()
		w.Write(buf.Bytes())
		w.Write([]byte("\n"))
	}

	return nil
}

/*
func TestRead(t *testing.T) {
	contents, err := ioutil.ReadFile("../models/pred_prey.stmx")
	if err != nil {
		t.Fatalf("ioutil.ReadFile: %s", err)
	}

	f, err := xmile.ReadFile(contents)
	if err != nil {
		t.Fatalf("xmile.ReadFile: %s", err)
	}

	output, err := xml.MarshalIndent(f, "", "    ")
	if err != nil {
		t.Fatalf("xml.MarshalIndent: %s", err)
	}

	os.Stderr.Write([]byte(xmile.XMLDeclaration + "\n"))
	os.Stderr.Write(output)
	os.Stderr.Write([]byte("\n"))
}
*/

func TestDot(t *testing.T) {
	contents, err := ioutil.ReadFile("../models/pred_prey.stmx")
	if err != nil {
		t.Fatalf("ioutil.ReadFile: %s", err)
	}

	f, err := xmile.ReadFile(contents)
	if err != nil {
		t.Fatalf("xmile.ReadFile: %s", err)
	}

	f.Models[0].Interface = xmile.View{}
	if err := writeDot(f); err != nil {
		t.Fatalf("writeDot: %s", err)
	}
}
<|endoftext|>


<commit_before>
package main

import (
  "github.com/sanjosh/golang/thriftproxy/buf/buf"
  "git.apache.org/thrift.git/lib/go/thrift"
  "math/rand"
  "time"
  "fmt"
  "net"
  "log"
  "flag"
  "os"
)

func Usage() {
    fmt.Fprintln(os.Stderr, "usage of ", os.Args[0], "[-h host:port] [-n num_iterations] [-s buffer_size]")
}

func main() {

  flag.Usage = Usage

  var host string
  var port int
  var bufferSize int
  var numIter int

  flag.StringVar(&host, "h", "localhost", "host and port")
  flag.IntVar(&port, "p", 7777, "port")
  flag.IntVar(&numIter, "n", 1000, "num_iterations")
  flag.IntVar(&bufferSize, "s", 4096, "buffer size")
  flag.Parse()
  portStr := fmt.Sprint(port)

  filePrefix := "testme"

  socket, err := thrift.NewTSocket(net.JoinHostPort(host, portStr))
  if err != nil {
    log.Fatal("cannot connect %s %s", host, portStr)
  }
  defer socket.Close()
  protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

  client := buf.NewBufClientFactory(socket, protocolFactory)

  if err := socket.Open(); err != nil {
    log.Fatal("error opening", err)
  }

  value := make([]byte, bufferSize)
  rand.Read(value)

  startTime := time.Now()
  for i := 0; i < numIter; i = i + 1 {
    filename := fmt.Sprintf("%s_%d", filePrefix, i)
    err := client.WriteData(filename, string(value[:]))
    if err != nil {
        log.Fatal("failed in iteration=%d", i)
    }
  }
  elapsed := time.Since(startTime)
  fmt.Println(bufferSize, ",", numIter, ",", elapsed)

  //data, err := client.ReadData(filename)
  //if data != string(value[:]) {
    //fmt.Println("error in value")
  //}
}
<commit_msg>Fixed port number option<commit_after>
package main

import (
  "github.com/sanjosh/golang/thriftproxy/buf/buf"
  "git.apache.org/thrift.git/lib/go/thrift"
  "math/rand"
  "time"
  "fmt"
  "net"
  "log"
  "flag"
  "os"
)

func Usage() {
    fmt.Fprintln(os.Stderr, "usage of ", os.Args[0], "[-h host or ip] [-p port] [-n num_iterations] [-s buffer_size]")
}

func main() {

  flag.Usage = Usage

  var host string
  var port int
  var bufferSize int
  var numIter int

  flag.StringVar(&host, "h", "localhost", "host")
  flag.IntVar(&port, "p", 8888, "port")
  flag.IntVar(&numIter, "n", 1000, "num_iterations")
  flag.IntVar(&bufferSize, "s", 4096, "buffer size")
  flag.Parse()
  portStr := fmt.Sprint(port)

  filePrefix := "testme"

  socket, err := thrift.NewTSocket(net.JoinHostPort(host, portStr))
  if err != nil {
    log.Fatal("cannot connect %s %s", host, portStr)
  }
  defer socket.Close()
  protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

  client := buf.NewBufClientFactory(socket, protocolFactory)

  if err := socket.Open(); err != nil {
    log.Fatal("error opening", err)
  }

  value := make([]byte, bufferSize)
  rand.Read(value)

  startTime := time.Now()
  for i := 0; i < numIter; i = i + 1 {
    filename := fmt.Sprintf("%s_%d", filePrefix, i)
    err := client.WriteData(filename, string(value[:]))
    if err != nil {
        log.Fatal("failed in iteration=%d", i)
    }
  }
  elapsed := time.Since(startTime)
  fmt.Println(bufferSize, ",", numIter, ",", elapsed)

  //data, err := client.ReadData(filename)
  //if data != string(value[:]) {
    //fmt.Println("error in value")
  //}
}
<|endoftext|>


<commit_before>package cpu

import (
	"fmt"
	"strings"
)

const (
	notAffectedSysFsValue = "Not Affected"
	vulnerableSysFsValue  = "Vulnerable"
	mitigationSysFsValue  = "Mitigation"
)

const (
	NotAffected VulnerabilityState = "not affected"
	Vulnerable  VulnerabilityState = "vulnerable"
	Mitigation  VulnerabilityState = "mitigation"
)

type VulnerabilityState string

func (s VulnerabilityState) String() string {
	return string(s)
}

type Vulnerability struct {
	CodeName   string
	State      VulnerabilityState
	Mitigation string
}

func ParseVulnerability(name, value string) (Vulnerability, error) {
	v := Vulnerability{CodeName: name}

	if value == notAffectedSysFsValue {
		v.State = NotAffected
		return v, nil
	}

	if strings.HasPrefix(value, vulnerableSysFsValue) {
		v.State = Vulnerable
		v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, vulnerableSysFsValue), ": ")
		return v, nil
	}

	if strings.HasPrefix(value, mitigationSysFsValue) {
		v.State = Mitigation
		v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, mitigationSysFsValue), ": ")
		return v, nil
	}

	return v, fmt.Errorf("unknown vulnerability state for %s: %s", name, value)
}
<commit_msg>Add license header<commit_after>// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cpu

import (
	"fmt"
	"strings"
)

const (
	notAffectedSysFsValue = "Not Affected"
	vulnerableSysFsValue  = "Vulnerable"
	mitigationSysFsValue  = "Mitigation"
)

const (
	NotAffected VulnerabilityState = "not affected"
	Vulnerable  VulnerabilityState = "vulnerable"
	Mitigation  VulnerabilityState = "mitigation"
)

type VulnerabilityState string

func (s VulnerabilityState) String() string {
	return string(s)
}

type Vulnerability struct {
	CodeName   string
	State      VulnerabilityState
	Mitigation string
}

func ParseVulnerability(name, value string) (Vulnerability, error) {
	v := Vulnerability{CodeName: name}

	if value == notAffectedSysFsValue {
		v.State = NotAffected
		return v, nil
	}

	if strings.HasPrefix(value, vulnerableSysFsValue) {
		v.State = Vulnerable
		v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, vulnerableSysFsValue), ": ")
		return v, nil
	}

	if strings.HasPrefix(value, mitigationSysFsValue) {
		v.State = Mitigation
		v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, mitigationSysFsValue), ": ")
		return v, nil
	}

	return v, fmt.Errorf("unknown vulnerability state for %s: %s", name, value)
}
<|endoftext|>


<commit_before>package handler

import (
	"net/http"

	"github.com/mattbostock/leavediary/model"
)

func Allowance(w http.ResponseWriter, r *http.Request) {
	user := currentUser(r)

	if user.ID == 0 { // no current user; not logged in
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}

	job := user.CurrentJob()

	leavePeriods, err := job.LeavePeriods()
	if err != nil {
		internalError(w, err)
		return
	}

	output.HTML(w, http.StatusOK, "allowance",
		&struct {
			JobID        uint64
			LeavePeriods []model.LeaveAllowance
			User         model.User
		}{
			job.ID,
			leavePeriods,
			user,
		})
}
<commit_msg>Allowance handler: Redirect to /settings if no job<commit_after>package handler

import (
	"net/http"

	"github.com/mattbostock/leavediary/model"
)

func Allowance(w http.ResponseWriter, r *http.Request) {
	user := currentUser(r)

	if user.ID == 0 { // no current user; not logged in
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}

	job := user.CurrentJob()
	if job.ID == 0 { // no job
		log.Infoln("No jobs defined")
		http.Redirect(w, r, "/settings", http.StatusTemporaryRedirect)
		return
	}

	leavePeriods, err := job.LeavePeriods()
	if err != nil {
		internalError(w, err)
		return
	}

	output.HTML(w, http.StatusOK, "allowance",
		&struct {
			JobID        uint64
			LeavePeriods []model.LeaveAllowance
			User         model.User
		}{
			job.ID,
			leavePeriods,
			user,
		})
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"strings"
	"time"

	"gopkg.in/mgo.v2/bson"

	"github.com/emreler/finch/auth"
	"github.com/emreler/finch/channel"
	"github.com/emreler/finch/logger"
	"github.com/emreler/finch/models"
	"github.com/emreler/finch/storage"
)

const (
	// TypeHTTP .
	TypeHTTP = "http"
)

// Handlers .
type Handlers struct {
	stg    *storage.Storage
	alt    *storage.Alerter
	logger *logger.Logger
	auth   *auth.Auth
}

// NewHandlers initializes handlers
func NewHandlers(stg *storage.Storage, alt *storage.Alerter, logger *logger.Logger, auth *auth.Auth) *Handlers {
	return &Handlers{stg: stg, alt: alt, logger: logger, auth: auth}
}

// CreateAlertRequest .
type CreateAlertRequest struct {
	Token       string `json:"token"`
	Name        string `json:"name"`
	Channel     string `json:"channel"`
	URL         string `json:"url"`
	Method      string `json:"method"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
	AlertDate   string `json:"alertDate"`
	AlertAfter  int    `json:"alertAfter"`
	RepeatEvery int    `json:"repeatEvery"`
}

// Validate validates request
func (r *CreateAlertRequest) Validate() error {
	if r.Channel == TypeHTTP {
		if match, _ := regexp.Match("^(http://|https://)", []byte(r.URL)); !match {
			return fmt.Errorf("url must be present in the http(s)://domain.com format")
		}

		if match, _ := regexp.Match("^(http://|https://)(localhost|127.0.0.1|0.0.0.0|172.17)", []byte(r.URL)); match {
			return fmt.Errorf("url can't be a local pointing address")
		}
	}
	return nil
}

// CreateAlertResponse .
type CreateAlertResponse struct {
	AlertDate string `json:"alertDate"`
}

// CreateUserRequest .
type CreateUserRequest struct {
	Name  *string `json:"name"`
	Email *string `json:"email"`
}

func (r *CreateUserRequest) Validate() error {
	if r.Name == nil || r.Email == nil {
		return fmt.Errorf("Missing fields")
	}

	*r.Name = strings.TrimSpace(*r.Name)
	*r.Email = strings.TrimSpace(*r.Email)

	if *r.Name == "" || *r.Email == "" {
		return fmt.Errorf("'name' and 'email' can't be empty")
	}

	re := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+$`)
	if !re.MatchString(*r.Email) {
		return fmt.Errorf("Invalid 'email' value")
	}

	return nil
}

// CreateUserResponse .
type CreateUserResponse struct {
	Token   string `json:"token"`
	Expires int64  `json:"expires"`
}

// GetAlertsResponse .
type GetAlertsResponse struct {
	Alerts []*models.Alert `json:"alerts"`
	Count  int             `json:"count"`
}

type UpdateAlertRequest struct {
	Enabled *bool `json:"enabled"`
}

func (h *Handlers) AlertDetail(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	re = regexp.MustCompile("/alerts/([0-9A-Fa-f]{24})$")
	match = re.FindStringSubmatch(r.URL.Path)

	if len(match) != 2 {
		return nil, fmt.Errorf("Invalid URL")
	}

	alertID := match[1]

	alert, err := h.stg.GetAlert(alertID)

	if err != nil {
		return nil, err
	}

	if alert.User.Hex() != userID {
		return nil, fmt.Errorf("Unauthorized request")
	}

	if r.Method == "GET" {
		return alert, nil
	} else if r.Method == "PATCH" {
		req := &UpdateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if req.Enabled == nil {
			return nil, fmt.Errorf("Invalid format")
		}

		alert.Enabled = *req.Enabled

		err := h.stg.UpdateAlert(alert)

		if err != nil {
			return nil, err
		}

		return nil, nil
	}

	return nil, fmt.Errorf("Invalid method")
}

// Alerts creates new alert
func (h *Handlers) Alerts(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	if r.Method == "POST" {
		req := &CreateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			h.logger.Error(err)
			return nil, err
		}

		var alertDate time.Time

		if req.AlertAfter != 0 {
			alertDate = time.Now().Add(time.Duration(req.AlertAfter) * time.Second)
		} else if req.AlertDate != "" {
			alertDate, err = time.Parse(time.RFC3339, req.AlertDate)

			if err != nil {
				return nil, fmt.Errorf("Invalid date format")
			}
		}

		alert := models.NewAlert()
		alert.Name = req.Name
		alert.AlertDate = alertDate
		alert.Channel = req.Channel
		alert.URL = req.URL
		alert.Method = req.Method
		alert.ContentType = req.ContentType
		alert.Data = req.Data
		alert.User = bson.ObjectIdHex(userID)

		if req.RepeatEvery > 0 {
			alert.Schedule = &models.Schedule{RepeatEvery: req.RepeatEvery}
		}

		alertID, err := h.stg.CreateAlert(alert)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		seconds := int(alertDate.Sub(time.Now()).Seconds())

		h.logger.Info(fmt.Sprintf("%d seconds later", seconds))

		h.alt.AddAlert(alertID, alertDate)

		res := &CreateAlertResponse{alertDate.Format(time.RFC3339)}
		return res, nil
	} else if r.Method == "GET" {
		alerts, err := h.stg.GetUserAlerts(userID)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &GetAlertsResponse{Alerts: alerts, Count: len(alerts)}

		return res, nil
	} else {
		return nil, fmt.Errorf("Invalid method: %s", r.Method)
	}
}

// ProcessAlert processes the alert
func (h *Handlers) ProcessAlert(alertID string) {
	alert, err := h.stg.GetAlert(alertID)

	if err != nil {
		h.logger.Error(err)
		return
	}

	if alert.Enabled == true {
		h.logger.Info(fmt.Sprintf("Processing %s", alertID))
		if alert.Channel == TypeHTTP {
			httpChannel := &channel.HttpChannel{}
			err := httpChannel.Notify(alert)

			if err != nil {
				h.logger.Info(fmt.Sprintf("Error while notifying with HTTP channel. %s", err.Error()))
			}
		}
	}

	if alert.Schedule != nil && alert.Schedule.RepeatEvery > 0 {
		nextAlertDate := time.Now().Add(time.Duration(alert.Schedule.RepeatEvery) * time.Second)
		h.logger.Info(fmt.Sprintf("Scheduling next alert %d seconds later at %s", alert.Schedule.RepeatEvery, nextAlertDate))
		h.alt.AddAlert(alertID, nextAlertDate)
	}
}

// CreateUser .
func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	if r.Method == "POST" {
		req := &CreateUserRequest{}

		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&req)

		if err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			return nil, err
		}

		user := &models.User{Name: *req.Name, Email: *req.Email}

		userID, err := h.stg.CreateUser(user)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		exp := time.Now().Add(24 * 365 * time.Hour)
		tokenString, err := h.auth.GenerateToken(userID, exp)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &CreateUserResponse{Token: tokenString, Expires: exp.Unix()}
		return res, nil
	}

	return nil, fmt.Errorf("Invalid method: %s", r.Method)
}
<commit_msg>Update create alert validation<commit_after>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"strings"
	"time"

	"gopkg.in/mgo.v2/bson"

	"github.com/emreler/finch/auth"
	"github.com/emreler/finch/channel"
	"github.com/emreler/finch/logger"
	"github.com/emreler/finch/models"
	"github.com/emreler/finch/storage"
)

const (
	// TypeHTTP .
	TypeHTTP = "http"
)

// Handlers .
type Handlers struct {
	stg    *storage.Storage
	alt    *storage.Alerter
	logger *logger.Logger
	auth   *auth.Auth
}

// NewHandlers initializes handlers
func NewHandlers(stg *storage.Storage, alt *storage.Alerter, logger *logger.Logger, auth *auth.Auth) *Handlers {
	return &Handlers{stg: stg, alt: alt, logger: logger, auth: auth}
}

// CreateAlertRequest .
type CreateAlertRequest struct {
	Token       string `json:"token"`
	Name        string `json:"name"`
	Channel     string `json:"channel"`
	URL         string `json:"url"`
	Method      string `json:"method"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
	AlertDate   string `json:"alertDate"`
	AlertAfter  int    `json:"alertAfter"`
	RepeatEvery int    `json:"repeatEvery"`
}

// Validate validates request
func (r *CreateAlertRequest) Validate() error {
	if r.Channel == TypeHTTP {
		if match, _ := regexp.Match("^(http://|https://)", []byte(r.URL)); !match {
			return fmt.Errorf("url must be present in the http(s)://domain.com format")
		}

		if match, _ := regexp.Match("^(http://|https://)(localhost|127.0.0.1|0.0.0.0|172.17)", []byte(r.URL)); match {
			return fmt.Errorf("url can't be a local pointing address")
		}
	}
	return nil
}

// CreateAlertResponse .
type CreateAlertResponse struct {
	AlertDate string `json:"alertDate"`
}

// CreateUserRequest .
type CreateUserRequest struct {
	Name  *string `json:"name"`
	Email *string `json:"email"`
}

func (r *CreateUserRequest) Validate() error {
	if r.Name == nil || r.Email == nil {
		return fmt.Errorf("Missing fields")
	}

	*r.Name = strings.TrimSpace(*r.Name)
	*r.Email = strings.TrimSpace(*r.Email)

	if *r.Name == "" || *r.Email == "" {
		return fmt.Errorf("'name' and 'email' can't be empty")
	}

	re := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+$`)
	if !re.MatchString(*r.Email) {
		return fmt.Errorf("Invalid 'email' value")
	}

	if (r.AlertAfter == 0 || r.AlertAfter < 0) && r.AlertDate == "" {
		return fmt.Errorf("Either 'alertAfter' or 'alertDate' fields must be present")
	}

	return nil
}

// CreateUserResponse .
type CreateUserResponse struct {
	Token   string `json:"token"`
	Expires int64  `json:"expires"`
}

// GetAlertsResponse .
type GetAlertsResponse struct {
	Alerts []*models.Alert `json:"alerts"`
	Count  int             `json:"count"`
}

type UpdateAlertRequest struct {
	Enabled *bool `json:"enabled"`
}

func (h *Handlers) AlertDetail(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	re = regexp.MustCompile("/alerts/([0-9A-Fa-f]{24})$")
	match = re.FindStringSubmatch(r.URL.Path)

	if len(match) != 2 {
		return nil, fmt.Errorf("Invalid URL")
	}

	alertID := match[1]

	alert, err := h.stg.GetAlert(alertID)

	if err != nil {
		return nil, err
	}

	if alert.User.Hex() != userID {
		return nil, fmt.Errorf("Unauthorized request")
	}

	if r.Method == "GET" {
		return alert, nil
	} else if r.Method == "PATCH" {
		req := &UpdateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if req.Enabled == nil {
			return nil, fmt.Errorf("Invalid format")
		}

		alert.Enabled = *req.Enabled

		err := h.stg.UpdateAlert(alert)

		if err != nil {
			return nil, err
		}

		return nil, nil
	}

	return nil, fmt.Errorf("Invalid method")
}

// Alerts creates new alert
func (h *Handlers) Alerts(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	if r.Method == "POST" {
		req := &CreateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			h.logger.Error(err)
			return nil, err
		}

		var alertDate time.Time

		if req.AlertAfter > 0 {
			alertDate = time.Now().Add(time.Duration(req.AlertAfter) * time.Second)
		} else if req.AlertDate != "" {
			alertDate, err = time.Parse(time.RFC3339, req.AlertDate)

			if err != nil {
				return nil, fmt.Errorf("Invalid date format")
			}
		}

		alert := models.NewAlert()
		alert.Name = req.Name
		alert.AlertDate = alertDate
		alert.Channel = req.Channel
		alert.URL = req.URL
		alert.Method = req.Method
		alert.ContentType = req.ContentType
		alert.Data = req.Data
		alert.User = bson.ObjectIdHex(userID)

		if req.RepeatEvery > 0 {
			alert.Schedule = &models.Schedule{RepeatEvery: req.RepeatEvery}
		}

		alertID, err := h.stg.CreateAlert(alert)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		seconds := int(alertDate.Sub(time.Now()).Seconds())

		h.logger.Info(fmt.Sprintf("%d seconds later", seconds))

		h.alt.AddAlert(alertID, alertDate)

		res := &CreateAlertResponse{alertDate.Format(time.RFC3339)}
		return res, nil
	} else if r.Method == "GET" {
		alerts, err := h.stg.GetUserAlerts(userID)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &GetAlertsResponse{Alerts: alerts, Count: len(alerts)}

		return res, nil
	} else {
		return nil, fmt.Errorf("Invalid method: %s", r.Method)
	}
}

// ProcessAlert processes the alert
func (h *Handlers) ProcessAlert(alertID string) {
	alert, err := h.stg.GetAlert(alertID)

	if err != nil {
		h.logger.Error(err)
		return
	}

	if alert.Enabled == true {
		h.logger.Info(fmt.Sprintf("Processing %s", alertID))
		if alert.Channel == TypeHTTP {
			httpChannel := &channel.HttpChannel{}
			err := httpChannel.Notify(alert)

			if err != nil {
				h.logger.Info(fmt.Sprintf("Error while notifying with HTTP channel. %s", err.Error()))
			}
		}
	}

	if alert.Schedule != nil && alert.Schedule.RepeatEvery > 0 {
		nextAlertDate := time.Now().Add(time.Duration(alert.Schedule.RepeatEvery) * time.Second)
		h.logger.Info(fmt.Sprintf("Scheduling next alert %d seconds later at %s", alert.Schedule.RepeatEvery, nextAlertDate))
		h.alt.AddAlert(alertID, nextAlertDate)
	}
}

// CreateUser .
func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	if r.Method == "POST" {
		req := &CreateUserRequest{}

		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&req)

		if err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			return nil, err
		}

		user := &models.User{Name: *req.Name, Email: *req.Email}

		userID, err := h.stg.CreateUser(user)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		exp := time.Now().Add(24 * 365 * time.Hour)
		tokenString, err := h.auth.GenerateToken(userID, exp)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &CreateUserResponse{Token: tokenString, Expires: exp.Unix()}
		return res, nil
	}

	return nil, fmt.Errorf("Invalid method: %s", r.Method)
}
<|endoftext|>