<commit_before>package govaluate

import (
	"errors"
	"fmt"
	"math"
	"regexp"
)

const (
	TYPEERROR_LOGICAL    string = "Value '%v' cannot be used with the logical operator '%v', it is not a bool"
	TYPEERROR_MODIFIER   string = "Value '%v' cannot be used with the modifier '%v', it is not a number"
	TYPEERROR_COMPARATOR string = "Value '%v' cannot be used with the comparator '%v', it is not a number"
	TYPEERROR_TERNARY    string = "Value '%v' cannot be used with the ternary operator '%v', it is not a bool"
	TYPEERROR_PREFIX     string = "Value '%v' cannot be used with the prefix '%v'"
)

type evaluationOperator func(left interface{}, right interface{}, parameters Parameters) (interface{}, error)
type stageTypeCheck func(value interface{}) bool
type stageCombinedTypeCheck func(left interface{}, right interface{}) bool

type evaluationStage struct {
	symbol OperatorSymbol

	leftStage, rightStage *evaluationStage

	// the operation that will be used to evaluate this stage (such as adding [left] to [right] and return the result)
	operator evaluationOperator

	// ensures that both left and right values are appropriate for this stage. Returns an error if they aren't operable.
	leftTypeCheck  stageTypeCheck
	rightTypeCheck stageTypeCheck

	// if specified, will override whatever is used in "leftTypeCheck" and "rightTypeCheck".
	// primarily used for specific operators that don't care which side a given type is on, but still requires one side to be of a given type
	// (like string concat)
	typeCheck stageCombinedTypeCheck

	// regardless of which type check is used, this string format will be used as the error message for type errors
	typeErrorFormat string
}

func (this *evaluationStage) swapWith(other *evaluationStage) {

	temp := *other
	other.setToNonStage(*this)
	this.setToNonStage(temp)
}

func (this *evaluationStage) setToNonStage(other evaluationStage) {

	this.symbol = other.symbol
	this.operator = other.operator
	this.leftTypeCheck = other.leftTypeCheck
	this.rightTypeCheck = other.rightTypeCheck
	this.typeCheck = other.typeCheck
	this.typeErrorFormat = other.typeErrorFormat
}

func addStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	// string concat if either are strings
	if isString(left) || isString(right) {
		return fmt.Sprintf("%v%v", left, right), nil
	}

	return left.(float64) + right.(float64), nil
}
func subtractStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) - right.(float64), nil
}
func multiplyStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) * right.(float64), nil
}
func divideStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) / right.(float64), nil
}
func exponentStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return math.Pow(left.(float64), right.(float64)), nil
}
func modulusStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return math.Mod(left.(float64), right.(float64)), nil
}
func gteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if(isString(left) && isString(right)) {
		return left.(string) >= right.(string), nil
	}
	return left.(float64) >= right.(float64), nil
}
func gtStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if(isString(left) && isString(right)) {
		return left.(string) > right.(string), nil
	}
	return left.(float64) > right.(float64), nil
}
func lteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if(isString(left) && isString(right)) {
		return left.(string) <= right.(string), nil
	}
	return left.(float64) <= right.(float64), nil
}
func ltStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if(isString(left) && isString(right)) {
		return left.(string) < right.(string), nil
	}
	return left.(float64) < right.(float64), nil
}
func equalStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left == right, nil
}
func notEqualStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left != right, nil
}
func andStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(bool) && right.(bool), nil
}
func orStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(bool) || right.(bool), nil
}
func negateStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return -right.(float64), nil
}
func invertStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return !right.(bool), nil
}
func bitwiseNotStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(^int64(right.(float64))), nil
}
func ternaryIfStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if left.(bool) {
		return right, nil
	}
	return nil, nil
}
func ternaryElseStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if left != nil {
		return left, nil
	}
	return right, nil
}

func regexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	var pattern *regexp.Regexp
	var err error

	switch right.(type) {
	case string:
		pattern, err = regexp.Compile(right.(string))
		if err != nil {
			return nil, errors.New(fmt.Sprintf("Unable to compile regexp pattern '%v': %v", right, err))
		}
	case *regexp.Regexp:
		pattern = right.(*regexp.Regexp)
	}

	return pattern.Match([]byte(left.(string))), nil
}

func notRegexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	ret, err := regexStage(left, right, parameters)
	if err != nil {
		return nil, err
	}

	return !(ret.(bool)), nil
}

func bitwiseOrStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) | int64(right.(float64))), nil
}
func bitwiseAndStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) & int64(right.(float64))), nil
}
func bitwiseXORStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) ^ int64(right.(float64))), nil
}
func leftShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(uint64(left.(float64)) << uint64(right.(float64))), nil
}
func rightShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(uint64(left.(float64)) >> uint64(right.(float64))), nil
}

func makeParameterStage(parameterName string) evaluationOperator {

	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
		value, err := parameters.Get(parameterName)
		if err != nil {
			return nil, err
		}

		return value, nil
	}
}

func makeLiteralStage(literal interface{}) evaluationOperator {
	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
		return literal, nil
	}
}

func makeFunctionStage(function ExpressionFunction) evaluationOperator {

	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

		if right == nil {
			return function()
		}

		switch right.(type) {
		case []interface{}:
			return function(right.([]interface{})...)
		default:
			return function(right)
		}

	}
}

func separatorStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	var ret []interface{}

	switch left.(type) {
	case []interface{}:
		ret = append(left.([]interface{}), right)
	default:
		ret = []interface{}{left, right}
	}

	return ret, nil
}

func inStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	for _, value := range right.([]interface{}) {
		if left == value {
			return true, nil
		}
	}
	return false, nil
}

//

func isString(value interface{}) bool {

	switch value.(type) {
	case string:
		return true
	}
	return false
}

func isRegexOrString(value interface{}) bool {

	switch value.(type) {
	case string:
		return true
	case *regexp.Regexp:
		return true
	}
	return false
}

func isBool(value interface{}) bool {
	switch value.(type) {
	case bool:
		return true
	}
	return false
}

func isFloat64(value interface{}) bool {
	switch value.(type) {
	case float64:
		return true
	}
	return false
}

/*
	Addition usually means between numbers, but can also mean string concat.
	String concat needs one (or both) of the sides to be a string.
*/
func additionTypeCheck(left interface{}, right interface{}) bool {

	if isFloat64(left) && isFloat64(right) {
		return true
	}
	if !isString(left) && !isString(right) {
		return false
	}
	return true
}

/*
	Comparison can either be between numbers, or lexicographic between two strings,
	but never between the two.
*/
func comparatorTypeCheck(left interface{}, right interface{}) bool {

	if isFloat64(left) && isFloat64(right) {
		return true
	}
	if isString(left) && isString(right) {
		return true
	}
	return false
}

func isArray(value interface{}) bool {
	switch value.(type) {
	case []interface{}:
		return true
	}
	return false
}
<commit_msg>Intern bools to avoid allocation on bool to interface{}<commit_after>package govaluate

import (
	"errors"
	"fmt"
	"math"
	"regexp"
)

const (
	TYPEERROR_LOGICAL    string = "Value '%v' cannot be used with the logical operator '%v', it is not a bool"
	TYPEERROR_MODIFIER   string = "Value '%v' cannot be used with the modifier '%v', it is not a number"
	TYPEERROR_COMPARATOR string = "Value '%v' cannot be used with the comparator '%v', it is not a number"
	TYPEERROR_TERNARY    string = "Value '%v' cannot be used with the ternary operator '%v', it is not a bool"
	TYPEERROR_PREFIX     string = "Value '%v' cannot be used with the prefix '%v'"
)

type evaluationOperator func(left interface{}, right interface{}, parameters Parameters) (interface{}, error)
type stageTypeCheck func(value interface{}) bool
type stageCombinedTypeCheck func(left interface{}, right interface{}) bool

type evaluationStage struct {
	symbol OperatorSymbol

	leftStage, rightStage *evaluationStage

	// the operation that will be used to evaluate this stage (such as adding [left] to [right] and return the result)
	operator evaluationOperator

	// ensures that both left and right values are appropriate for this stage. Returns an error if they aren't operable.
	leftTypeCheck  stageTypeCheck
	rightTypeCheck stageTypeCheck

	// if specified, will override whatever is used in "leftTypeCheck" and "rightTypeCheck".
	// primarily used for specific operators that don't care which side a given type is on, but still requires one side to be of a given type
	// (like string concat)
	typeCheck stageCombinedTypeCheck

	// regardless of which type check is used, this string format will be used as the error message for type errors
	typeErrorFormat string
}

var (
	_true  = interface{}(true)
	_false = interface{}(false)
)

func (this *evaluationStage) swapWith(other *evaluationStage) {

	temp := *other
	other.setToNonStage(*this)
	this.setToNonStage(temp)
}

func (this *evaluationStage) setToNonStage(other evaluationStage) {

	this.symbol = other.symbol
	this.operator = other.operator
	this.leftTypeCheck = other.leftTypeCheck
	this.rightTypeCheck = other.rightTypeCheck
	this.typeCheck = other.typeCheck
	this.typeErrorFormat = other.typeErrorFormat
}

func addStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	// string concat if either are strings
	if isString(left) || isString(right) {
		return fmt.Sprintf("%v%v", left, right), nil
	}

	return left.(float64) + right.(float64), nil
}
func subtractStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) - right.(float64), nil
}
func multiplyStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) * right.(float64), nil
}
func divideStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return left.(float64) / right.(float64), nil
}
func exponentStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return math.Pow(left.(float64), right.(float64)), nil
}
func modulusStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return math.Mod(left.(float64), right.(float64)), nil
}
func gteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if isString(left) && isString(right) {
		return boolIface(left.(string) >= right.(string)), nil
	}
	return boolIface(left.(float64) >= right.(float64)), nil
}
func gtStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if isString(left) && isString(right) {
		return boolIface(left.(string) > right.(string)), nil
	}
	return boolIface(left.(float64) > right.(float64)), nil
}
func lteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if isString(left) && isString(right) {
		return boolIface(left.(string) <= right.(string)), nil
	}
	return boolIface(left.(float64) <= right.(float64)), nil
}
func ltStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if isString(left) && isString(right) {
		return boolIface(left.(string) < right.(string)), nil
	}
	return boolIface(left.(float64) < right.(float64)), nil
}
func equalStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return boolIface(left == right), nil
}
func notEqualStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return boolIface(left != right), nil
}
func andStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return boolIface(left.(bool) && right.(bool)), nil
}
func orStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return boolIface(left.(bool) || right.(bool)), nil
}
func negateStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return -right.(float64), nil
}
func invertStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return boolIface(!right.(bool)), nil
}
func bitwiseNotStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(^int64(right.(float64))), nil
}
func ternaryIfStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if left.(bool) {
		return right, nil
	}
	return nil, nil
}
func ternaryElseStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	if left != nil {
		return left, nil
	}
	return right, nil
}

func regexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	var pattern *regexp.Regexp
	var err error

	switch right.(type) {
	case string:
		pattern, err = regexp.Compile(right.(string))
		if err != nil {
			return nil, errors.New(fmt.Sprintf("Unable to compile regexp pattern '%v': %v", right, err))
		}
	case *regexp.Regexp:
		pattern = right.(*regexp.Regexp)
	}

	return pattern.Match([]byte(left.(string))), nil
}

func notRegexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	ret, err := regexStage(left, right, parameters)
	if err != nil {
		return nil, err
	}

	return !(ret.(bool)), nil
}

func bitwiseOrStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) | int64(right.(float64))), nil
}
func bitwiseAndStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) & int64(right.(float64))), nil
}
func bitwiseXORStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(int64(left.(float64)) ^ int64(right.(float64))), nil
}
func leftShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(uint64(left.(float64)) << uint64(right.(float64))), nil
}
func rightShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
	return float64(uint64(left.(float64)) >> uint64(right.(float64))), nil
}

func makeParameterStage(parameterName string) evaluationOperator {

	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
		value, err := parameters.Get(parameterName)
		if err != nil {
			return nil, err
		}

		return value, nil
	}
}

func makeLiteralStage(literal interface{}) evaluationOperator {
	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
		return literal, nil
	}
}

func makeFunctionStage(function ExpressionFunction) evaluationOperator {

	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

		if right == nil {
			return function()
		}

		switch right.(type) {
		case []interface{}:
			return function(right.([]interface{})...)
		default:
			return function(right)
		}

	}
}

func separatorStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	var ret []interface{}

	switch left.(type) {
	case []interface{}:
		ret = append(left.([]interface{}), right)
	default:
		ret = []interface{}{left, right}
	}

	return ret, nil
}

func inStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {

	for _, value := range right.([]interface{}) {
		if left == value {
			return true, nil
		}
	}
	return false, nil
}

//

func isString(value interface{}) bool {

	switch value.(type) {
	case string:
		return true
	}
	return false
}

func isRegexOrString(value interface{}) bool {

	switch value.(type) {
	case string:
		return true
	case *regexp.Regexp:
		return true
	}
	return false
}

func isBool(value interface{}) bool {
	switch value.(type) {
	case bool:
		return true
	}
	return false
}

func isFloat64(value interface{}) bool {
	switch value.(type) {
	case float64:
		return true
	}
	return false
}

/*
	Addition usually means between numbers, but can also mean string concat.
	String concat needs one (or both) of the sides to be a string.
*/
func additionTypeCheck(left interface{}, right interface{}) bool {

	if isFloat64(left) && isFloat64(right) {
		return true
	}
	if !isString(left) && !isString(right) {
		return false
	}
	return true
}

/*
	Comparison can either be between numbers, or lexicographic between two strings,
	but never between the two.
*/
func comparatorTypeCheck(left interface{}, right interface{}) bool {

	if isFloat64(left) && isFloat64(right) {
		return true
	}
	if isString(left) && isString(right) {
		return true
	}
	return false
}

func isArray(value interface{}) bool {
	switch value.(type) {
	case []interface{}:
		return true
	}
	return false
}

/*
	Converting a boolean to an interface{} requires an allocation.
	We can use interned bools to avoid this cost.
*/
func boolIface(b bool) interface{} {
	if b {
		return _true
	}
	return _false
}
<|endoftext|>


<commit_before>package renderweb

import (
	"net/http"
	"strings"

	"github.com/rs/xmux"

	"golang.org/x/net/context"
)

type requestContext struct {
	*http.Request
	context.Context
}

// NewRequestContext - Creates a context with request. Created context exposes many values.
// Context request values are available under `request` namespace (raw request).
//
//   * `request` - HTTP Request (*http.Request)
//   * `request.host` - Alias for `request.url.host` (string)
//   * `request.method` - Request Method (string)
//   * `request.remote` - Request Remote address (string)
//   * `request.header` - Request Header (http.Header)
//   * `request.header.{key}` - Request Header value (string)
//   * `request.form` - Request Form (url.Values)
//   * `request.form.{key}` - Request Form value (string)
//   * `request.url` - Request URL (*url.URL)
//   * `request.url.host` - Request URL Host (*url.URL)
//   * `request.url.query` - Request URL Query (url.Values)
//   * `request.url.query.{key}` - Request URL Query value (string)
//   * `request.url.params` - Request URL Parameters (xmux.ParamHolder)
//   * `request.url.params.{key}` - Request URL Parameter value (string)
//
func NewRequestContext(ctx context.Context, req *http.Request) context.Context {
	return &requestContext{
		Context: ctx,
		Request: req,
	}
}

func (ctx *requestContext) Value(key interface{}) interface{} {
	name, ok := key.(string)
	if !ok {
		return ctx.Context.Value(key)
	}

	if !strings.Contains(name, ".") {
		if name == "request" {
			return ctx.Request
		}
		return ctx.Context.Value(key)
	}

	split := strings.Split(name, ".")
	if split[0] != "request" {
		return ctx.Context.Value(key)
	}

	switch split[1] {
	case "host":
		return ctx.Request.Host
	case "method":
		return ctx.Request.Method
	case "remote":
		return ctx.Request.RemoteAddr
	case "url":
		return ctx.getFromURL(key, split[2:]...)
	case "header":
		return ctx.getFromHeader(split[2:]...)
	case "form":
		return ctx.getFromForm(split[2:]...)
	}

	return ctx.Context.Value(key)
}

func (ctx *requestContext) getFromURL(key interface{}, rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.URL
	}
	switch rest[0] {
	case "host":
		return ctx.Request.Host
	case "path":
		return ctx.Request.URL.Path
	case "query":
		if len(rest) == 0 {
			return ctx.Request.URL.Query()
		}
		return ctx.Request.URL.Query().Get(strings.Join(rest[1:], "."))
	case "params":
		if len(rest) == 0 {
			return xmux.Params(ctx.Context)
		}
		return xmux.Params(ctx.Context).Get(strings.Join(rest[1:], "."))
	default:
		return ctx.Context.Value(key)
	}
}

func (ctx *requestContext) getFromForm(rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.Form
	}
	return ctx.Request.Form.Get(strings.Join(rest, "."))
}

func (ctx *requestContext) getFromHeader(rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.Header
	}
	return ctx.Request.Header.Get(strings.Join(rest, "."))
}
<commit_msg>request context: make sure form is always parsed<commit_after>package renderweb

import (
	"net/http"
	"strings"

	"github.com/rs/xmux"

	"golang.org/x/net/context"
)

type requestContext struct {
	*http.Request
	context.Context
}

// NewRequestContext - Creates a context with request. Created context exposes many values.
// Context request values are available under `request` namespace (raw request).
//
//   * `request` - HTTP Request (*http.Request)
//   * `request.host` - Alias for `request.url.host` (string)
//   * `request.method` - Request Method (string)
//   * `request.remote` - Request Remote address (string)
//   * `request.header` - Request Header (http.Header)
//   * `request.header.{key}` - Request Header value (string)
//   * `request.form` - Request Form (url.Values)
//   * `request.form.{key}` - Request Form value (string)
//   * `request.url` - Request URL (*url.URL)
//   * `request.url.host` - Request URL Host (*url.URL)
//   * `request.url.query` - Request URL Query (url.Values)
//   * `request.url.query.{key}` - Request URL Query value (string)
//   * `request.url.params` - Request URL Parameters (xmux.ParamHolder)
//   * `request.url.params.{key}` - Request URL Parameter value (string)
//
func NewRequestContext(ctx context.Context, req *http.Request) context.Context {
	return &requestContext{
		Context: ctx,
		Request: req,
	}
}

func (ctx *requestContext) Value(key interface{}) interface{} {
	name, ok := key.(string)
	if !ok {
		return ctx.Context.Value(key)
	}

	if !strings.Contains(name, ".") {
		if name == "request" {
			return ctx.Request
		}
		return ctx.Context.Value(key)
	}

	split := strings.Split(name, ".")
	if split[0] != "request" {
		return ctx.Context.Value(key)
	}

	switch split[1] {
	case "host":
		return ctx.Request.Host
	case "method":
		return ctx.Request.Method
	case "remote":
		return ctx.Request.RemoteAddr
	case "url":
		return ctx.getFromURL(key, split[2:]...)
	case "header":
		return ctx.getFromHeader(split[2:]...)
	case "form":
		return ctx.getFromForm(split[2:]...)
	}

	return ctx.Context.Value(key)
}

func (ctx *requestContext) getFromURL(key interface{}, rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.URL
	}
	switch rest[0] {
	case "host":
		return ctx.Request.Host
	case "path":
		return ctx.Request.URL.Path
	case "query":
		if len(rest) == 0 {
			return ctx.Request.URL.Query()
		}
		return ctx.Request.URL.Query().Get(strings.Join(rest[1:], "."))
	case "params":
		if len(rest) == 0 {
			return xmux.Params(ctx.Context)
		}
		return xmux.Params(ctx.Context).Get(strings.Join(rest[1:], "."))
	default:
		return ctx.Context.Value(key)
	}
}

func (ctx *requestContext) getFromForm(rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.Form
	}
	if err := ctx.Request.ParseForm(); err != nil {
		return nil
	}
	return ctx.Request.Form.Get(strings.Join(rest, "."))
}

func (ctx *requestContext) getFromHeader(rest ...string) interface{} {
	if len(rest) == 0 {
		return ctx.Request.Header
	}
	return ctx.Request.Header.Get(strings.Join(rest, "."))
}
<|endoftext|>


<commit_before>// Example shows how to work with Upwork API
//
// Licensed under the Upwork's API Terms of Use;
// you may not use this file except in compliance with the Terms.
//
// 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.
//
// Author::    Maksym Novozhylov (mnovozhilov@upwork.com)
// Copyright:: Copyright 2018(c) Upwork.com
// License::   See LICENSE.txt and TOS - https://developers.upwork.com/api-tos.html
package main

import (
    "fmt"
    "bufio"
    "os"
    "context" // uncomment if you need to setup a custom http client
    _ "net/http" // uncomment if you need to setup a custom http client

    _ "golang.org/x/oauth2" // uncomment if you need to work with oauth2.Token or other object, e.g. to store or re-cache token pair

    "github.com/upwork/golang-upwork-oauth2/api"
    "github.com/upwork/golang-upwork-oauth2/api/routers/auth"
    _ "github.com/upwork/golang-upwork-oauth2/api/routers/messages" // uncomment to test messages example
    _ "github.com/upwork/golang-upwork-oauth2/api/routers/graphql" // uncomment to test graphql example
)

const cfgFile = "config.json" // update the path to your config file, or provide properties directly in your code

func main() {
    // init context
    ctx := context.Background()

/* it is possible to set up properties from code
    settings := map[string]string{
        "client_id": "clientid",
        "client_secret": "clientsecret",
    }
    config := api.NewConfig(settings)

    //or read them from a specific configuration file
    config := api.ReadConfig(cfgFile)
    config.Print()
*/

/* it is possible to setup a custom http client if needed
    httpClient := &http.Client{Timeout: 2}
    config := api.ReadConfig(cfgFile)
    ctx = config.SetCustomHttpClient(ctx, httpClient)
    client := api.Setup(config)
*/
    ctx = context.TODO() // define NoContext if you do not use a custom client, otherwise use earlier defined context
    client := api.Setup(api.ReadConfig(cfgFile))
    // You can configure the package send the requests as application/json, by default PostForm is used.
    // This will be automatically set to true for GraphQL request
    // client.SetPostAsJson(true)

    // GraphQL requests require X-Upwork-API-TenantId header, which can be setup using the following method
    // client.SetOrgUidHeader(ctx, "1234567890") // Organization UID

/*
    // WARNING: oauth2 library will refresh the access token for you
    // Setup notify function for refresh-token-workflow
    // type Token, see https://godoc.org/golang.org/x/oauth2#Token
    f := func(t *oauth2.Token) error {
        // re-cache refreshed token
        _, err := fmt.Printf("The token has been refreshed, here is a new one: %#v\n", t)
        return err
    }
    client.SetRefreshTokenNotifyFunc(f)
*/
    // we need an access/refresh token pair in case we haven't received it yet
    if !client.HasAccessToken(ctx) {
	// required to authorize the application. Once you have an access/refresh token pair associated with
	// the user, no need to redirect to the authorization screen.
        aurl := client.GetAuthorizationUrl("random-state")

        // read code
        reader := bufio.NewReader(os.Stdin)
        fmt.Println("Visit the authorization url and provide oauth_verifier for further authorization")
        fmt.Println(aurl)
        authzCode, _ := reader.ReadString('\n')

	// WARNING: be sure to validate FormValue("state") before getting access token

        // get access token
        token := client.GetToken(ctx, authzCode)
	fmt.Println(token) // type Token, see https://godoc.org/golang.org/x/oauth2#Token
    }

    // http.Response and specified type will be returned, you can use any
    // use client.SetApiResponseType to specify the response type: use api.ByteResponse
    // or api.ErrorResponse, see usage example below
    // by default api.ByteResponse is used, i.e. []byte is returned as second value
    _, jsonDataFromHttp1 := auth.New(&client).GetUserInfo()

    // here you can Unmarshal received json string, or do any other action(s) if you used ByteResponse
    fmt.Println(string(jsonDataFromHttp1.([]byte))) // []byte

    // if you used ErrorResponse, like
    // client.SetApiResponseType(api.ErrorResponse)
    // httpResponse, err := auth.New(&client).GetUserInfo()
    // if err == nil {
    //     ... do smth with http.Response
    // }

    // run a post request using parameters as an example
    // params := make(map[string]string)
    // params["story"] = `{"message": "test message", "userId": "~017xxxxx"}`
    // _, jsonDataFromHttp2 := messages.New(&client).SendMessageToRoom("company_id", "room_id", params)
    // fmt.Println(string(jsonDataFromHttp2.([]byte)))

    // getting reports example
    // params := make(map[string]string)
    // params["tq"] = "select memo where worked_on >= '05-08-2015'"
    // params["tqx"] = "out:json"
    // _, jsonDataFromHttp3 := timereports.New(&client).GetByFreelancerFull(params)
    // fmt.Println(string(jsonDataFromHttp3.([]byte)))

    // sending GraphQL request
    // jsonData := map[string]string{
    //     "query": `
    //       {
    //         user {
    //           id
    //           nid
    //         }
    //         organization {
    //           id
    //         }
    //      }
    //    `,
    //  }
    // _, jsonDataFromHttp4 := graphql.New(&client).Execute(jsonData)
    // fmt.Println(string(jsonDataFromHttp4.([]byte)))
}
<commit_msg>Add remark to the comment for Organization UID<commit_after>// Example shows how to work with Upwork API
//
// Licensed under the Upwork's API Terms of Use;
// you may not use this file except in compliance with the Terms.
//
// 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.
//
// Author::    Maksym Novozhylov (mnovozhilov@upwork.com)
// Copyright:: Copyright 2018(c) Upwork.com
// License::   See LICENSE.txt and TOS - https://developers.upwork.com/api-tos.html
package main

import (
    "fmt"
    "bufio"
    "os"
    "context" // uncomment if you need to setup a custom http client
    _ "net/http" // uncomment if you need to setup a custom http client

    _ "golang.org/x/oauth2" // uncomment if you need to work with oauth2.Token or other object, e.g. to store or re-cache token pair

    "github.com/upwork/golang-upwork-oauth2/api"
    "github.com/upwork/golang-upwork-oauth2/api/routers/auth"
    _ "github.com/upwork/golang-upwork-oauth2/api/routers/messages" // uncomment to test messages example
    _ "github.com/upwork/golang-upwork-oauth2/api/routers/graphql" // uncomment to test graphql example
)

const cfgFile = "config.json" // update the path to your config file, or provide properties directly in your code

func main() {
    // init context
    ctx := context.Background()

/* it is possible to set up properties from code
    settings := map[string]string{
        "client_id": "clientid",
        "client_secret": "clientsecret",
    }
    config := api.NewConfig(settings)

    //or read them from a specific configuration file
    config := api.ReadConfig(cfgFile)
    config.Print()
*/

/* it is possible to setup a custom http client if needed
    httpClient := &http.Client{Timeout: 2}
    config := api.ReadConfig(cfgFile)
    ctx = config.SetCustomHttpClient(ctx, httpClient)
    client := api.Setup(config)
*/
    ctx = context.TODO() // define NoContext if you do not use a custom client, otherwise use earlier defined context
    client := api.Setup(api.ReadConfig(cfgFile))
    // You can configure the package send the requests as application/json, by default PostForm is used.
    // This will be automatically set to true for GraphQL request
    // client.SetPostAsJson(true)

    // GraphQL requests require X-Upwork-API-TenantId header, which can be setup using the following method
    // client.SetOrgUidHeader(ctx, "1234567890") // Organization UID (optional)

/*
    // WARNING: oauth2 library will refresh the access token for you
    // Setup notify function for refresh-token-workflow
    // type Token, see https://godoc.org/golang.org/x/oauth2#Token
    f := func(t *oauth2.Token) error {
        // re-cache refreshed token
        _, err := fmt.Printf("The token has been refreshed, here is a new one: %#v\n", t)
        return err
    }
    client.SetRefreshTokenNotifyFunc(f)
*/
    // we need an access/refresh token pair in case we haven't received it yet
    if !client.HasAccessToken(ctx) {
	// required to authorize the application. Once you have an access/refresh token pair associated with
	// the user, no need to redirect to the authorization screen.
        aurl := client.GetAuthorizationUrl("random-state")

        // read code
        reader := bufio.NewReader(os.Stdin)
        fmt.Println("Visit the authorization url and provide oauth_verifier for further authorization")
        fmt.Println(aurl)
        authzCode, _ := reader.ReadString('\n')

	// WARNING: be sure to validate FormValue("state") before getting access token

        // get access token
        token := client.GetToken(ctx, authzCode)
	fmt.Println(token) // type Token, see https://godoc.org/golang.org/x/oauth2#Token
    }

    // http.Response and specified type will be returned, you can use any
    // use client.SetApiResponseType to specify the response type: use api.ByteResponse
    // or api.ErrorResponse, see usage example below
    // by default api.ByteResponse is used, i.e. []byte is returned as second value
    _, jsonDataFromHttp1 := auth.New(&client).GetUserInfo()

    // here you can Unmarshal received json string, or do any other action(s) if you used ByteResponse
    fmt.Println(string(jsonDataFromHttp1.([]byte))) // []byte

    // if you used ErrorResponse, like
    // client.SetApiResponseType(api.ErrorResponse)
    // httpResponse, err := auth.New(&client).GetUserInfo()
    // if err == nil {
    //     ... do smth with http.Response
    // }

    // run a post request using parameters as an example
    // params := make(map[string]string)
    // params["story"] = `{"message": "test message", "userId": "~017xxxxx"}`
    // _, jsonDataFromHttp2 := messages.New(&client).SendMessageToRoom("company_id", "room_id", params)
    // fmt.Println(string(jsonDataFromHttp2.([]byte)))

    // getting reports example
    // params := make(map[string]string)
    // params["tq"] = "select memo where worked_on >= '05-08-2015'"
    // params["tqx"] = "out:json"
    // _, jsonDataFromHttp3 := timereports.New(&client).GetByFreelancerFull(params)
    // fmt.Println(string(jsonDataFromHttp3.([]byte)))

    // sending GraphQL request
    // jsonData := map[string]string{
    //     "query": `
    //       {
    //         user {
    //           id
    //           nid
    //         }
    //         organization {
    //           id
    //         }
    //      }
    //    `,
    //  }
    // _, jsonDataFromHttp4 := graphql.New(&client).Execute(jsonData)
    // fmt.Println(string(jsonDataFromHttp4.([]byte)))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"time"

	"math/rand"

	"encoding/json"

	"github.com/achilleasa/usrv"
	"github.com/achilleasa/usrv-tracer"
	"github.com/achilleasa/usrv-tracer/middleware"
	"github.com/achilleasa/usrv-tracer/storage"
	"github.com/achilleasa/usrv/usrvtest"
	"golang.org/x/net/context"
)

type Add4Request struct {
	A, B, C, D int
}
type Add2Request struct {
	A, B int
}
type AddResponse struct {
	Sum int
}

type Adder struct {
	add2Client *usrv.Client
	add4Client *usrv.Client
	Server     *usrv.Server
}

// add 2 numbers
func (adder *Adder) add2(ctx context.Context, rawReq interface{}) (interface{}, error) {
	req := rawReq.(Add2Request)

	// Simulate processing delay
	<-time.After(time.Millisecond * time.Duration(rand.Intn(5)))

	return &AddResponse{Sum: req.A + req.B}, nil
}

// Add 4 numbers. Makes 2 parallel calls to add2 and sums the results
func (adder *Adder) add4(ctx context.Context, rawReq interface{}) (interface{}, error) {
	req := rawReq.(Add4Request)

	// Add (a,b) and (c,d) in parallel
	req1, _ := json.Marshal(Add2Request{A: req.A, B: req.B})
	req1Chan := adder.add2Client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req1},
	)

	req2, _ := json.Marshal(Add2Request{A: req.C, B: req.D})
	req2Chan := adder.add2Client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req2},
	)

	// Wait for responses
	var res1, res2 AddResponse
	for {
		select {
		case srvRes := <-req1Chan:
			json.Unmarshal(srvRes.Message.Payload, &res1)
			req1Chan = nil
		case srvRes := <-req2Chan:
			json.Unmarshal(srvRes.Message.Payload, &res2)
			req2Chan = nil
		}

		if req1Chan == nil && req2Chan == nil {
			break
		}
	}

	// Run a final add2 to get the sum
	req3, _ := json.Marshal(Add2Request{A: res1.Sum, B: res2.Sum})
	req3Chan := adder.add2Client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req3},
	)

	srvRes := <-req3Chan
	var res3 AddResponse
	json.Unmarshal(srvRes.Message.Payload, &res3)
	return &res3, nil
}

func (adder *Adder) Add4(a, b, c, d int) (int, string) {
	req, _ := json.Marshal(Add4Request{a, b, c, d})
	reqChan := adder.add4Client.Request(
		context.WithValue(context.Background(), usrv.CtxCurEndpoint, "com.test.api"),
		&usrv.Message{Payload: req},
	)

	srvRes := <-reqChan
	var res AddResponse
	json.Unmarshal(srvRes.Message.Payload, &res)

	// Return the value and the injected trace id
	return res.Sum, srvRes.Message.Headers.Get(middleware.CtxTraceId).(string)
}

func NewAdder(transp usrv.Transport, collector *tracer.Collector) *Adder {
	server, err := usrv.NewServer(transp)
	if err != nil {
		panic(err)
	}

	add2Dec := func(data []byte) (interface{}, error) {
		var payload Add2Request
		err := json.Unmarshal(data, &payload)
		return payload, err
	}

	add4Dec := func(data []byte) (interface{}, error) {
		var payload Add4Request
		err := json.Unmarshal(data, &payload)
		return payload, err
	}

	adder := &Adder{
		add2Client: usrv.NewClient(transp, "com.test.add/2"),
		add4Client: usrv.NewClient(transp, "com.test.add/4"),
		Server:     server,
	}

	// Register endpoints and add the tracer middleware
	server.Handle(
		"com.test.add/2",
		usrv.PipelineHandler{add2Dec, adder.add2, json.Marshal},
		middleware.Tracer(collector),
	)
	server.Handle(
		"com.test.add/4",
		usrv.PipelineHandler{add4Dec, adder.add4, json.Marshal},
		middleware.Tracer(collector),
	)

	return adder
}

func main() {
	// Setup collector
	collector, err := tracer.NewCollector(storage.Memory, 100, 0)
	if err != nil {
		panic(err)
	}

	// Use in-memory transport for this demo
	transp := usrvtest.NewTransport()
	defer transp.Close()

	// Start RPC server
	adder := NewAdder(transp, collector)
	go func() {
		err := adder.Server.ListenAndServe()
		if err != nil {
			panic(err)
		}
	}()
	defer adder.Server.Close()
	<-time.After(100 * time.Millisecond)

	// Make a call to the service
	sum, traceId := adder.Add4(1, 3, 5, 7)
	fmt.Printf("[%s] Sum: 1 + 3 + 5 + 7 = %d\n", traceId, sum)

	// Get trace log from storage
	traceLog, err := storage.Memory.GetTrace(traceId)
	if err != nil {
		panic(err)
	}
	fmt.Printf("\nTrace log:\n")
	for _, rec := range traceLog {
		fmt.Printf("   %v\n", rec)
	}

	// Get service dependencies
	deps, err := storage.Memory.GetDependencies()
	if err != nil {
		panic(err)
	}
	fmt.Printf("\nService dependencies:\n")
	for _, srv := range deps {
		fmt.Printf("   [%s] depends on: %s\n", srv.Service, srv.Dependencies)
	}
}
<commit_msg>Updated example to work with usrv client changes<commit_after>package main

import (
	"fmt"

	"time"

	"math/rand"

	"encoding/json"

	"github.com/achilleasa/usrv"
	"github.com/achilleasa/usrv-tracer"
	"github.com/achilleasa/usrv-tracer/middleware"
	"github.com/achilleasa/usrv-tracer/storage"
	"github.com/achilleasa/usrv/usrvtest"
	"golang.org/x/net/context"
)

type Add4Request struct {
	A, B, C, D int
}
type Add2Request struct {
	A, B int
}
type AddResponse struct {
	Sum int
}

var (
	add2Endpoint = "com.test.add/2"
	add4Endpoint = "com.test.add/4"
)

type Adder struct {
	client *usrv.Client
	Server *usrv.Server
}

// add 2 numbers
func (adder *Adder) add2(ctx context.Context, rawReq interface{}) (interface{}, error) {
	req := rawReq.(Add2Request)

	// Simulate processing delay
	<-time.After(time.Millisecond * time.Duration(rand.Intn(5)))

	return &AddResponse{Sum: req.A + req.B}, nil
}

// Add 4 numbers. Makes 2 parallel calls to add2 and sums the results
func (adder *Adder) add4(ctx context.Context, rawReq interface{}) (interface{}, error) {
	req := rawReq.(Add4Request)

	// Add (a,b) and (c,d) in parallel
	req1, _ := json.Marshal(Add2Request{A: req.A, B: req.B})
	req1Chan := adder.client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req1},
		add2Endpoint,
	)

	req2, _ := json.Marshal(Add2Request{A: req.C, B: req.D})
	req2Chan := adder.client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req2},
		add2Endpoint,
	)

	// Wait for responses
	var res1, res2 AddResponse
	for {
		select {
		case srvRes := <-req1Chan:
			json.Unmarshal(srvRes.Message.Payload, &res1)
			req1Chan = nil
		case srvRes := <-req2Chan:
			json.Unmarshal(srvRes.Message.Payload, &res2)
			req2Chan = nil
		}

		if req1Chan == nil && req2Chan == nil {
			break
		}
	}

	// Run a final add2 to get the sum
	req3, _ := json.Marshal(Add2Request{A: res1.Sum, B: res2.Sum})
	req3Chan := adder.client.Request(
		ctx, // Make sure you include the original context so requests can be linked together
		&usrv.Message{Payload: req3},
		add2Endpoint,
	)

	srvRes := <-req3Chan
	var res3 AddResponse
	json.Unmarshal(srvRes.Message.Payload, &res3)
	return &res3, nil
}

func (adder *Adder) Add4(a, b, c, d int) (int, string) {
	req, _ := json.Marshal(Add4Request{a, b, c, d})
	reqChan := adder.client.Request(
		context.WithValue(context.Background(), usrv.CtxCurEndpoint, "com.test.api"),
		&usrv.Message{Payload: req},
		add4Endpoint,
	)

	srvRes := <-reqChan
	var res AddResponse
	json.Unmarshal(srvRes.Message.Payload, &res)

	// Return the value and the injected trace id
	return res.Sum, srvRes.Message.Headers.Get(middleware.CtxTraceId).(string)
}

func NewAdder(transp usrv.Transport, collector *tracer.Collector) *Adder {
	server, err := usrv.NewServer(transp)
	if err != nil {
		panic(err)
	}

	add2Dec := func(data []byte) (interface{}, error) {
		var payload Add2Request
		err := json.Unmarshal(data, &payload)
		return payload, err
	}

	add4Dec := func(data []byte) (interface{}, error) {
		var payload Add4Request
		err := json.Unmarshal(data, &payload)
		return payload, err
	}

	adder := &Adder{
		client: usrv.NewClient(transp),
		Server: server,
	}

	// Register endpoints and add the tracer middleware
	server.Handle(
		add2Endpoint,
		usrv.PipelineHandler{add2Dec, adder.add2, json.Marshal},
		middleware.Tracer(collector),
	)
	server.Handle(
		add4Endpoint,
		usrv.PipelineHandler{add4Dec, adder.add4, json.Marshal},
		middleware.Tracer(collector),
	)

	return adder
}

func main() {
	// Setup collector
	collector, err := tracer.NewCollector(storage.Memory, 100, 0)
	if err != nil {
		panic(err)
	}

	// Use in-memory transport for this demo
	transp := usrvtest.NewTransport()
	defer transp.Close()

	// Start RPC server
	adder := NewAdder(transp, collector)
	go func() {
		err := adder.Server.ListenAndServe()
		if err != nil {
			panic(err)
		}
	}()
	defer adder.Server.Close()
	<-time.After(100 * time.Millisecond)

	// Make a call to the service
	sum, traceId := adder.Add4(1, 3, 5, 7)
	fmt.Printf("[%s] Sum: 1 + 3 + 5 + 7 = %d\n", traceId, sum)

	// Get trace log from storage
	traceLog, err := storage.Memory.GetTrace(traceId)
	if err != nil {
		panic(err)
	}
	fmt.Printf("\nTrace log:\n")
	for _, rec := range traceLog {
		fmt.Printf("   %v\n", rec)
	}

	// Get service dependencies
	deps, err := storage.Memory.GetDependencies()
	if err != nil {
		panic(err)
	}
	fmt.Printf("\nService dependencies:\n")
	for _, srv := range deps {
		fmt.Printf("   [%s] depends on: %s\n", srv.Service, srv.Dependencies)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"runtime"
	"time"

	"koding/kites/config"
	"koding/kites/config/configstore"
	"koding/klient/app"
	konfig "koding/klient/config"
	"koding/klient/klientsvc"
	"koding/klient/registration"
)

// TODO: workaround for #10057
var f = flag.NewFlagSet(os.Args[0], flag.ExitOnError)

var (
	flagIP          = f.String("ip", "", "Change public ip")
	flagPort        = f.Int("port", 56789, "Change running port")
	flagVersion     = f.Bool("version", false, "Show version and exit")
	flagRegisterURL = f.String("register-url", "", "Change register URL to kontrol")
	flagDebug       = f.Bool("debug", false, "Debug mode")
	flagScreenrc    = f.String("screenrc", "/opt/koding/embedded/etc/screenrc", "Default screenrc path")
	flagScreenTerm  = f.String("screen-term", "", "Overwrite $TERM for screen")

	// Registration flags
	flagUsername   = f.String("username", "", "Username to be registered to Kontrol")
	flagToken      = f.String("token", "", "Token to be passed to Kontrol to register")
	flagRegister   = f.Bool("register", false, "Register to Kontrol with your Koding Password")
	flagKontrolURL = f.String("kontrol-url", "", "Change kontrol URL to be used for registration")

	// Update parameters
	flagUpdateInterval = f.Duration("update-interval", time.Minute*5,
		"Change interval for checking for new updates")
	flagUpdateURL = f.String("update-url",
		"",
		"Change update endpoint for latest version")

	// Vagrant flags
	flagVagrantHome = f.String("vagrant-home", "", "Change Vagrant home path")

	// Tunnel flags
	flagTunnelName    = f.String("tunnel-name", "", "Enable tunneling by setting non-empty tunnel name")
	flagTunnelKiteURL = f.String("tunnel-kite-url", "", "Change default tunnel server kite URL")
	flagNoTunnel      = f.Bool("no-tunnel", defaultNoTunnel(), "Force tunnel connection off")
	flagNoProxy       = f.Bool("no-proxy", false, "Force TLS proxy for tunneled connection off")
	flagAutoupdate    = f.Bool("autoupdate", false, "Force turn automatic updates on")

	// Upload log flags
	flagLogBucketRegion   = f.String("log-bucket-region", "", "Change bucket region to upload logs")
	flagLogBucketName     = f.String("log-bucket-name", "", "Change bucket name to upload logs")
	flagLogUploadInterval = f.Duration("log-upload-interval", 90*time.Minute, "Change interval of upload logs")

	// Metadata flags.
	flagMetadata     = f.String("metadata", "", "Base64-encoded Koding metadata")
	flagMetadataFile = f.String("metadata-file", "", "Koding metadata file")
)

func defaultNoTunnel() bool {
	return os.Getenv("KITE_NO_TUNNEL") == "1"
}

func main() {
	// Call realMain instead of doing the work here so we can use
	// `defer` statements within the function and have them work properly.
	// (defers aren't called with os.Exit)
	os.Exit(realMain())
}

func realMain() int {
	f.Var(config.CurrentUser, "metadata-user", "Overwrite default user to store the metadata for.")
	f.Parse(os.Args[1:])

	// For forward-compatibility with go1.5+, where GOMAXPROCS is
	// always set to a number of available cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	if *flagVersion {
		fmt.Println(konfig.Version)
		return 0
	}

	debug := *flagDebug || konfig.Konfig.Debug

	if *flagRegister {
		kontrolURL := *flagKontrolURL
		if kontrolURL == "" {
			kontrolURL = konfig.Konfig.Endpoints.Kontrol().Public.String()
		}

		koding, err := url.Parse(kontrolURL)
		if err != nil {
			log.Fatalf("failed to parse -kontrol-url: %s", err)
		}

		// TODO(rjeczalik): rework client to display KODING_URL instead of KONTROLURL
		koding.Path = ""

		if err := registration.Register(koding, *flagUsername, *flagToken, debug); err != nil {
			fmt.Fprintln(os.Stderr, "registration failed:", err)
			return 1
		}

		return 0
	}

	vagrantHome := filepath.Join(config.CurrentUser.HomeDir, ".vagrant.d")

	if *flagVagrantHome != "" {
		vagrantHome = *flagVagrantHome
	} else if s := os.Getenv("VAGRANT_CWD"); s != "" {
		vagrantHome = s
	}

	conf := &app.KlientConfig{
		Name:              konfig.Name,
		Environment:       konfig.Environment,
		Region:            konfig.Region,
		Version:           konfig.Version,
		IP:                *flagIP,
		Port:              *flagPort,
		RegisterURL:       *flagRegisterURL,
		KontrolURL:        *flagKontrolURL,
		Debug:             debug,
		UpdateInterval:    *flagUpdateInterval,
		UpdateURL:         *flagUpdateURL,
		ScreenrcPath:      *flagScreenrc,
		ScreenTerm:        *flagScreenTerm,
		VagrantHome:       vagrantHome,
		TunnelName:        *flagTunnelName,
		TunnelKiteURL:     *flagTunnelKiteURL,
		NoTunnel:          *flagNoTunnel,
		NoProxy:           *flagNoProxy,
		Autoupdate:        *flagAutoupdate,
		LogBucketRegion:   *flagLogBucketRegion,
		LogBucketName:     *flagLogBucketName,
		LogUploadInterval: *flagLogUploadInterval,
		Metadata:          *flagMetadata,
		MetadataFile:      *flagMetadataFile,
	}

	if err := handleMetadata(conf); err != nil {
		log.Fatalf("error writing Koding metadata: %s", err)
	}

	if len(f.Args()) != 0 {
		if err := handleInternalCommand(f.Arg(0), f.Args()[1:]...); err != nil {
			log.Fatal(err)
		}

		return 0
	}

	a, err := app.NewKlient(conf)
	if err != nil {
		log.Fatal(err)
	}

	defer a.Close()
	a.Run()

	return 0
}

func handleInternalCommand(cmd string, args ...string) (err error) {
	// The following commands are intended for internal use
	// only. They are used by kloud to install klient
	// where no kd is available.
	//
	// TODO(rjeczalik): we should bundle klient with kd
	// and have only 1 klient/kd distribution.
	switch cmd {
	case "config":
		err = printConfig()
	case "install":
		err = klientsvc.Install()
	case "start":
		err = klientsvc.Start()
	case "stop":
		err = klientsvc.Stop()
	case "uninstall":
		err = klientsvc.Uninstall()
	case "run":
		err = klientsvc.Install()
		if err != nil {
			break
		}

		err = klientsvc.Start()
	default:
		return fmt.Errorf("unrecognized command: %s", cmd)
	}

	if err != nil {
		return fmt.Errorf("internal command failed: %s", err)
	}

	return nil
}

func handleMetadata(conf *app.KlientConfig) error {
	if conf.Metadata != "" && conf.MetadataFile != "" {
		return errors.New("the -metadata and -metadata-file flags are exclusive")
	}

	if conf.Metadata != "" {
		p, err := base64.StdEncoding.DecodeString(conf.Metadata)
		if err != nil {
			return errors.New("failed to decode Koding metadata: " + err.Error())
		}

		conf.Metadata = string(p)
	}

	if conf.MetadataFile != "" {
		p, err := ioutil.ReadFile(conf.MetadataFile)
		if err != nil {
			return errors.New("failed to read Koding metadata file: " + err.Error())
		}

		conf.Metadata = string(p)
	}

	if conf.Metadata != "" {
		var m configstore.Metadata

		if err := json.Unmarshal([]byte(conf.Metadata), &m); err != nil {
			return errors.New("failed to decode Koding metadata: " + err.Error())
		}

		if err := configstore.WriteMetadata(m); err != nil {
			return errors.New("failed to write Koding metadata: " + err.Error())
		}

		konfig.Konfig = konfig.ReadKonfig() // re-read konfig after dumping metadata
	}

	return nil
}

func printConfig() error {
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "\t")

	return enc.Encode(map[string]interface{}{
		"builtinKonfig": konfig.Builtin,
		"konfig":        konfig.Konfig,
	})
}
<commit_msg>klient/main: start cron while starting KD<commit_after>package main

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"runtime"
	"time"

	"github.com/koding/logging"

	"koding/kites/config"
	"koding/kites/config/configstore"
	"koding/kites/metrics"
	"koding/klient/app"
	konfig "koding/klient/config"
	"koding/klient/klientsvc"
	"koding/klient/registration"
	endpointkloud "koding/klientctl/endpoint/kloud"
)

// TODO: workaround for #10057
var f = flag.NewFlagSet(os.Args[0], flag.ExitOnError)

var (
	flagIP          = f.String("ip", "", "Change public ip")
	flagPort        = f.Int("port", 56789, "Change running port")
	flagVersion     = f.Bool("version", false, "Show version and exit")
	flagRegisterURL = f.String("register-url", "", "Change register URL to kontrol")
	flagDebug       = f.Bool("debug", false, "Debug mode")
	flagScreenrc    = f.String("screenrc", "/opt/koding/embedded/etc/screenrc", "Default screenrc path")
	flagScreenTerm  = f.String("screen-term", "", "Overwrite $TERM for screen")

	// Registration flags
	flagUsername   = f.String("username", "", "Username to be registered to Kontrol")
	flagToken      = f.String("token", "", "Token to be passed to Kontrol to register")
	flagRegister   = f.Bool("register", false, "Register to Kontrol with your Koding Password")
	flagKontrolURL = f.String("kontrol-url", "", "Change kontrol URL to be used for registration")

	// Update parameters
	flagUpdateInterval = f.Duration("update-interval", time.Minute*5,
		"Change interval for checking for new updates")
	flagUpdateURL = f.String("update-url",
		"",
		"Change update endpoint for latest version")

	// Vagrant flags
	flagVagrantHome = f.String("vagrant-home", "", "Change Vagrant home path")

	// Tunnel flags
	flagTunnelName    = f.String("tunnel-name", "", "Enable tunneling by setting non-empty tunnel name")
	flagTunnelKiteURL = f.String("tunnel-kite-url", "", "Change default tunnel server kite URL")
	flagNoTunnel      = f.Bool("no-tunnel", defaultNoTunnel(), "Force tunnel connection off")
	flagNoProxy       = f.Bool("no-proxy", false, "Force TLS proxy for tunneled connection off")
	flagAutoupdate    = f.Bool("autoupdate", false, "Force turn automatic updates on")

	// Upload log flags
	flagLogBucketRegion   = f.String("log-bucket-region", "", "Change bucket region to upload logs")
	flagLogBucketName     = f.String("log-bucket-name", "", "Change bucket name to upload logs")
	flagLogUploadInterval = f.Duration("log-upload-interval", 90*time.Minute, "Change interval of upload logs")

	// Metadata flags.
	flagMetadata     = f.String("metadata", "", "Base64-encoded Koding metadata")
	flagMetadataFile = f.String("metadata-file", "", "Koding metadata file")
)

func defaultNoTunnel() bool {
	return os.Getenv("KITE_NO_TUNNEL") == "1"
}

func main() {
	// Call realMain instead of doing the work here so we can use
	// `defer` statements within the function and have them work properly.
	// (defers aren't called with os.Exit)
	os.Exit(realMain())
}

func realMain() int {
	f.Var(config.CurrentUser, "metadata-user", "Overwrite default user to store the metadata for.")
	f.Parse(os.Args[1:])

	// For forward-compatibility with go1.5+, where GOMAXPROCS is
	// always set to a number of available cores.
	runtime.GOMAXPROCS(runtime.NumCPU())

	if *flagVersion {
		fmt.Println(konfig.Version)
		return 0
	}

	debug := *flagDebug || konfig.Konfig.Debug

	if *flagRegister {
		kontrolURL := *flagKontrolURL
		if kontrolURL == "" {
			kontrolURL = konfig.Konfig.Endpoints.Kontrol().Public.String()
		}

		koding, err := url.Parse(kontrolURL)
		if err != nil {
			log.Fatalf("failed to parse -kontrol-url: %s", err)
		}

		// TODO(rjeczalik): rework client to display KODING_URL instead of KONTROLURL
		koding.Path = ""

		if err := registration.Register(koding, *flagUsername, *flagToken, debug); err != nil {
			fmt.Fprintln(os.Stderr, "registration failed:", err)
			return 1
		}

		return 0
	}

	vagrantHome := filepath.Join(config.CurrentUser.HomeDir, ".vagrant.d")

	if *flagVagrantHome != "" {
		vagrantHome = *flagVagrantHome
	} else if s := os.Getenv("VAGRANT_CWD"); s != "" {
		vagrantHome = s
	}

	conf := &app.KlientConfig{
		Name:              konfig.Name,
		Environment:       konfig.Environment,
		Region:            konfig.Region,
		Version:           konfig.Version,
		IP:                *flagIP,
		Port:              *flagPort,
		RegisterURL:       *flagRegisterURL,
		KontrolURL:        *flagKontrolURL,
		Debug:             debug,
		UpdateInterval:    *flagUpdateInterval,
		UpdateURL:         *flagUpdateURL,
		ScreenrcPath:      *flagScreenrc,
		ScreenTerm:        *flagScreenTerm,
		VagrantHome:       vagrantHome,
		TunnelName:        *flagTunnelName,
		TunnelKiteURL:     *flagTunnelKiteURL,
		NoTunnel:          *flagNoTunnel,
		NoProxy:           *flagNoProxy,
		Autoupdate:        *flagAutoupdate,
		LogBucketRegion:   *flagLogBucketRegion,
		LogBucketName:     *flagLogBucketName,
		LogUploadInterval: *flagLogUploadInterval,
		Metadata:          *flagMetadata,
		MetadataFile:      *flagMetadataFile,
	}

	if err := handleMetadata(conf); err != nil {
		log.Fatalf("error writing Koding metadata: %s", err)
	}

	if len(f.Args()) != 0 {
		if err := handleInternalCommand(f.Arg(0), f.Args()[1:]...); err != nil {
			log.Fatal(err)
		}

		return 0
	}

	a, err := app.NewKlient(conf)
	if err != nil {
		log.Fatal(err)
	}

	defer a.Close()
	go metrics.StartCron(endpointkloud.DefaultClient, logging.NewCustom("klient-cron", conf.Debug))
	a.Run()

	return 0
}

func handleInternalCommand(cmd string, args ...string) (err error) {
	// The following commands are intended for internal use
	// only. They are used by kloud to install klient
	// where no kd is available.
	//
	// TODO(rjeczalik): we should bundle klient with kd
	// and have only 1 klient/kd distribution.
	switch cmd {
	case "config":
		err = printConfig()
	case "install":
		err = klientsvc.Install()
	case "start":
		err = klientsvc.Start()
	case "stop":
		err = klientsvc.Stop()
	case "uninstall":
		err = klientsvc.Uninstall()
	case "run":
		err = klientsvc.Install()
		if err != nil {
			break
		}

		err = klientsvc.Start()
	default:
		return fmt.Errorf("unrecognized command: %s", cmd)
	}

	if err != nil {
		return fmt.Errorf("internal command failed: %s", err)
	}

	return nil
}

func handleMetadata(conf *app.KlientConfig) error {
	if conf.Metadata != "" && conf.MetadataFile != "" {
		return errors.New("the -metadata and -metadata-file flags are exclusive")
	}

	if conf.Metadata != "" {
		p, err := base64.StdEncoding.DecodeString(conf.Metadata)
		if err != nil {
			return errors.New("failed to decode Koding metadata: " + err.Error())
		}

		conf.Metadata = string(p)
	}

	if conf.MetadataFile != "" {
		p, err := ioutil.ReadFile(conf.MetadataFile)
		if err != nil {
			return errors.New("failed to read Koding metadata file: " + err.Error())
		}

		conf.Metadata = string(p)
	}

	if conf.Metadata != "" {
		var m configstore.Metadata

		if err := json.Unmarshal([]byte(conf.Metadata), &m); err != nil {
			return errors.New("failed to decode Koding metadata: " + err.Error())
		}

		if err := configstore.WriteMetadata(m); err != nil {
			return errors.New("failed to write Koding metadata: " + err.Error())
		}

		konfig.Konfig = konfig.ReadKonfig() // re-read konfig after dumping metadata
	}

	return nil
}

func printConfig() error {
	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "\t")

	return enc.Encode(map[string]interface{}{
		"builtinKonfig": konfig.Builtin,
		"konfig":        konfig.Konfig,
	})
}
<|endoftext|>


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

// +build linux darwin

package interp_test

import (
	"bytes"
	"fmt"
	"go/build"
	"go/types"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/interp"
	"golang.org/x/tools/go/ssa/ssautil"
)

// Each line contains a space-separated list of $GOROOT/test/
// filenames comprising the main package of a program.
// They are ordered quickest-first, roughly.
//
// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
// golden file checking, etc.
var gorootTestTests = []string{
	"235.go",
	"alias1.go",
	"chancap.go",
	"func5.go",
	"func6.go",
	"func7.go",
	"func8.go",
	"helloworld.go",
	"varinit.go",
	"escape3.go",
	"initcomma.go",
	"cmp.go",
	"compos.go",
	"turing.go",
	"indirect.go",
	"complit.go",
	"for.go",
	"struct0.go",
	"intcvt.go",
	"printbig.go",
	"deferprint.go",
	"escape.go",
	"range.go",
	"const4.go",
	"float_lit.go",
	"bigalg.go",
	"decl.go",
	"if.go",
	"named.go",
	"bigmap.go",
	"func.go",
	"reorder2.go",
	"closure.go",
	"gc.go",
	"simassign.go",
	"iota.go",
	"nilptr2.go",
	"goprint.go", // doesn't actually assert anything (cmpout)
	"utf.go",
	"method.go",
	"char_lit.go",
	"env.go",
	"int_lit.go",
	"string_lit.go",
	"defer.go",
	"typeswitch.go",
	"stringrange.go",
	"reorder.go",
	"method3.go",
	"literal.go",
	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
	"zerodivide.go",
	"convert.go",
	"convT2X.go",
	"switch.go",
	"initialize.go",
	"ddd.go",
	"blank.go", // partly disabled
	"map.go",
	"closedchan.go",
	"divide.go",
	"rename.go",
	"const3.go",
	"nil.go",
	"recover.go", // reflection parts disabled
	"recover1.go",
	"recover2.go",
	"recover3.go",
	"typeswitch1.go",
	"floatcmp.go",
	"crlf.go", // doesn't actually assert anything (runoutput)
	// Slow tests follow.
	"bom.go",                         // ~1.7s
	"gc1.go",                         // ~1.7s
	"cmplxdivide.go cmplxdivide1.go", // ~2.4s

	// Working, but not worth enabling:
	// "append.go",    // works, but slow (15s).
	// "gc2.go",       // works, but slow, and cheats on the memory check.
	// "sigchld.go",   // works, but only on POSIX.
	// "peano.go",     // works only up to n=9, and slow even then.
	// "stack.go",     // works, but too slow (~30s) by default.
	// "solitaire.go", // works, but too slow (~30s).
	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
	// "rotate.go rotate0.go", // emits source for a test
	// "rotate.go rotate1.go", // emits source for a test
	// "rotate.go rotate2.go", // emits source for a test
	// "rotate.go rotate3.go", // emits source for a test
	// "64bit.go",             // emits source for a test
	// "run.go",               // test driver, not a test.

	// Broken.  TODO(adonovan): fix.
	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
	// args.go         // works, but requires specific os.Args from the driver.
	// index.go        // a template, not a real test.
	// mallocfin.go    // SetFinalizer not implemented.

	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
	// bench chan bugs fixedbugs interface ken.
}

// These are files in go.tools/go/ssa/interp/testdata/.
var testdataTests = []string{
	"boundmeth.go",
	"complit.go",
	"coverage.go",
	"defer.go",
	"fieldprom.go",
	"ifaceconv.go",
	"ifaceprom.go",
	"initorder.go",
	"methprom.go",
	"mrvchain.go",
	"range.go",
	"recover.go",
	"reflect.go",
	"static.go",
	"callstack.go",
}

type successPredicate func(exitcode int, output string) error

func run(t *testing.T, dir, input string, success successPredicate) bool {
	if runtime.GOOS == "darwin" {
		t.Skip("skipping on darwin until golang.org/issue/23166 is fixed")
	}
	fmt.Printf("Input: %s\n", input)

	start := time.Now()

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		if strings.HasSuffix(i, ".go") {
			i = dir + i
		}
		inputs = append(inputs, i)
	}

	var conf loader.Config
	if _, err := conf.FromArgs(inputs, true); err != nil {
		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
		return false
	}

	conf.Import("runtime")

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println("FAIL")
			fmt.Println(hint)
		} else {
			fmt.Println("PASS")
		}

		interp.CapturedOutput = nil
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", strings.Join(inputs, " "))

	iprog, err := conf.Load()
	if err != nil {
		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
		return false
	}

	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
	prog.Build()

	// Find first main or test package among the initial packages.
	var mainPkg *ssa.Package
	for _, info := range iprog.InitialPackages() {
		if info.Pkg.Path() == "runtime" {
			continue // not an initial package
		}
		p := prog.Package(info.Pkg)
		if p.Pkg.Name() == "main" && p.Func("main") != nil {
			mainPkg = p
			break
		}

		mainPkg = prog.CreateTestMainPackage(p)
		if mainPkg != nil {
			break
		}
	}
	if mainPkg == nil {
		t.Fatalf("no main or test packages among initial packages: %s", inputs)
	}

	var out bytes.Buffer
	interp.CapturedOutput = &out

	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -test -run --interp=T %s\n", strings.Join(inputs, " "))
	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{WordSize: 8, MaxAlign: 8}, inputs[0], []string{})

	// The definition of success varies with each file.
	if err := success(exitCode, out.String()); err != nil {
		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
		return false
	}

	hint = "" // call off the hounds

	if false {
		fmt.Println(input, time.Since(start)) // test profiling
	}

	return true
}

const slash = string(os.PathSeparator)

func printFailures(failures []string) {
	if failures != nil {
		fmt.Println("The following tests failed:")
		for _, f := range failures {
			fmt.Printf("\t%s\n", f)
		}
	}
}

func success(exitcode int, output string) error {
	if exitcode != 0 {
		return fmt.Errorf("exit code was %d", exitcode)
	}
	if strings.Contains(output, "BUG") {
		return fmt.Errorf("exited zero but output contained 'BUG'")
	}
	return nil
}

// TestTestdataFiles runs the interpreter on testdata/*.go.
func TestTestdataFiles(t *testing.T) {
	var failures []string
	start := time.Now()
	for _, input := range testdataTests {
		if testing.Short() && time.Since(start) > 30*time.Second {
			printFailures(failures)
			t.Skipf("timeout - aborting test")
		}
		if !run(t, "testdata"+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
func TestGorootTest(t *testing.T) {
	if testing.Short() {
		t.Skip() // too slow (~30s)
	}

	var failures []string

	for _, input := range gorootTestTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// CreateTestMainPackage should return nil if there were no tests.
func TestNullTestmainPackage(t *testing.T) {
	var conf loader.Config
	conf.CreateFromFilenames("", "testdata/b_test.go")
	iprog, err := conf.Load()
	if err != nil {
		t.Fatalf("CreatePackages failed: %s", err)
	}
	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
	mainPkg := prog.Package(iprog.Created[0].Pkg)
	if mainPkg.Func("main") != nil {
		t.Fatalf("unexpected main function")
	}
	if prog.CreateTestMainPackage(mainPkg) != nil {
		t.Fatalf("CreateTestMainPackage returned non-nil")
	}
}
<commit_msg>go/ssa/interp: disable regularly broken tests in short mode<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux darwin

package interp_test

import (
	"bytes"
	"fmt"
	"go/build"
	"go/types"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/interp"
	"golang.org/x/tools/go/ssa/ssautil"
)

// Each line contains a space-separated list of $GOROOT/test/
// filenames comprising the main package of a program.
// They are ordered quickest-first, roughly.
//
// TODO(adonovan): integrate into the $GOROOT/test driver scripts,
// golden file checking, etc.
var gorootTestTests = []string{
	"235.go",
	"alias1.go",
	"chancap.go",
	"func5.go",
	"func6.go",
	"func7.go",
	"func8.go",
	"helloworld.go",
	"varinit.go",
	"escape3.go",
	"initcomma.go",
	"cmp.go",
	"compos.go",
	"turing.go",
	"indirect.go",
	"complit.go",
	"for.go",
	"struct0.go",
	"intcvt.go",
	"printbig.go",
	"deferprint.go",
	"escape.go",
	"range.go",
	"const4.go",
	"float_lit.go",
	"bigalg.go",
	"decl.go",
	"if.go",
	"named.go",
	"bigmap.go",
	"func.go",
	"reorder2.go",
	"closure.go",
	"gc.go",
	"simassign.go",
	"iota.go",
	"nilptr2.go",
	"goprint.go", // doesn't actually assert anything (cmpout)
	"utf.go",
	"method.go",
	"char_lit.go",
	"env.go",
	"int_lit.go",
	"string_lit.go",
	"defer.go",
	"typeswitch.go",
	"stringrange.go",
	"reorder.go",
	"method3.go",
	"literal.go",
	"nul1.go", // doesn't actually assert anything (errorcheckoutput)
	"zerodivide.go",
	"convert.go",
	"convT2X.go",
	"switch.go",
	"initialize.go",
	"ddd.go",
	"blank.go", // partly disabled
	"map.go",
	"closedchan.go",
	"divide.go",
	"rename.go",
	"const3.go",
	"nil.go",
	"recover.go", // reflection parts disabled
	"recover1.go",
	"recover2.go",
	"recover3.go",
	"typeswitch1.go",
	"floatcmp.go",
	"crlf.go", // doesn't actually assert anything (runoutput)
	// Slow tests follow.
	"bom.go", // ~1.7s
	"gc1.go", // ~1.7s
	"cmplxdivide.go cmplxdivide1.go", // ~2.4s

	// Working, but not worth enabling:
	// "append.go",    // works, but slow (15s).
	// "gc2.go",       // works, but slow, and cheats on the memory check.
	// "sigchld.go",   // works, but only on POSIX.
	// "peano.go",     // works only up to n=9, and slow even then.
	// "stack.go",     // works, but too slow (~30s) by default.
	// "solitaire.go", // works, but too slow (~30s).
	// "const.go",     // works but for but one bug: constant folder doesn't consider representations.
	// "init1.go",     // too slow (80s) and not that interesting. Cheats on ReadMemStats check too.
	// "rotate.go rotate0.go", // emits source for a test
	// "rotate.go rotate1.go", // emits source for a test
	// "rotate.go rotate2.go", // emits source for a test
	// "rotate.go rotate3.go", // emits source for a test
	// "64bit.go",             // emits source for a test
	// "run.go",               // test driver, not a test.

	// Broken.  TODO(adonovan): fix.
	// copy.go         // very slow; but with N=4 quickly crashes, slice index out of range.
	// nilptr.go       // interp: V > uintptr not implemented. Slow test, lots of mem
	// args.go         // works, but requires specific os.Args from the driver.
	// index.go        // a template, not a real test.
	// mallocfin.go    // SetFinalizer not implemented.

	// TODO(adonovan): add tests from $GOROOT/test/* subtrees:
	// bench chan bugs fixedbugs interface ken.
}

// These are files in go.tools/go/ssa/interp/testdata/.
var testdataTests = []string{
	"boundmeth.go",
	"complit.go",
	"coverage.go",
	"defer.go",
	"fieldprom.go",
	"ifaceconv.go",
	"ifaceprom.go",
	"initorder.go",
	"methprom.go",
	"mrvchain.go",
	"range.go",
	"recover.go",
	"reflect.go",
	"static.go",
	"callstack.go",
}

type successPredicate func(exitcode int, output string) error

func run(t *testing.T, dir, input string, success successPredicate) bool {
	if testing.Short() {
		t.Skip("test breaks regularly; skipping in short mode so a failure doesn't affect trybots or build.golang.org; golang.org/issue/27292")
	}
	if runtime.GOOS == "darwin" {
		t.Skip("skipping on darwin until golang.org/issue/23166 is fixed")
	}
	fmt.Printf("Input: %s\n", input)

	start := time.Now()

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		if strings.HasSuffix(i, ".go") {
			i = dir + i
		}
		inputs = append(inputs, i)
	}

	var conf loader.Config
	if _, err := conf.FromArgs(inputs, true); err != nil {
		t.Errorf("FromArgs(%s) failed: %s", inputs, err)
		return false
	}

	conf.Import("runtime")

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println("FAIL")
			fmt.Println(hint)
		} else {
			fmt.Println("PASS")
		}

		interp.CapturedOutput = nil
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", strings.Join(inputs, " "))

	iprog, err := conf.Load()
	if err != nil {
		t.Errorf("conf.Load(%s) failed: %s", inputs, err)
		return false
	}

	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
	prog.Build()

	// Find first main or test package among the initial packages.
	var mainPkg *ssa.Package
	for _, info := range iprog.InitialPackages() {
		if info.Pkg.Path() == "runtime" {
			continue // not an initial package
		}
		p := prog.Package(info.Pkg)
		if p.Pkg.Name() == "main" && p.Func("main") != nil {
			mainPkg = p
			break
		}

		mainPkg = prog.CreateTestMainPackage(p)
		if mainPkg != nil {
			break
		}
	}
	if mainPkg == nil {
		t.Fatalf("no main or test packages among initial packages: %s", inputs)
	}

	var out bytes.Buffer
	interp.CapturedOutput = &out

	hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -test -run --interp=T %s\n", strings.Join(inputs, " "))
	exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{WordSize: 8, MaxAlign: 8}, inputs[0], []string{})

	// The definition of success varies with each file.
	if err := success(exitCode, out.String()); err != nil {
		t.Errorf("interp.Interpret(%s) failed: %s", inputs, err)
		return false
	}

	hint = "" // call off the hounds

	if false {
		fmt.Println(input, time.Since(start)) // test profiling
	}

	return true
}

const slash = string(os.PathSeparator)

func printFailures(failures []string) {
	if failures != nil {
		fmt.Println("The following tests failed:")
		for _, f := range failures {
			fmt.Printf("\t%s\n", f)
		}
	}
}

func success(exitcode int, output string) error {
	if exitcode != 0 {
		return fmt.Errorf("exit code was %d", exitcode)
	}
	if strings.Contains(output, "BUG") {
		return fmt.Errorf("exited zero but output contained 'BUG'")
	}
	return nil
}

// TestTestdataFiles runs the interpreter on testdata/*.go.
func TestTestdataFiles(t *testing.T) {
	var failures []string
	start := time.Now()
	for _, input := range testdataTests {
		if testing.Short() && time.Since(start) > 30*time.Second {
			printFailures(failures)
			t.Skipf("timeout - aborting test")
		}
		if !run(t, "testdata"+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
func TestGorootTest(t *testing.T) {
	if testing.Short() {
		t.Skip() // too slow (~30s)
	}

	var failures []string

	for _, input := range gorootTestTests {
		if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) {
			failures = append(failures, input)
		}
	}
	printFailures(failures)
}

// CreateTestMainPackage should return nil if there were no tests.
func TestNullTestmainPackage(t *testing.T) {
	var conf loader.Config
	conf.CreateFromFilenames("", "testdata/b_test.go")
	iprog, err := conf.Load()
	if err != nil {
		t.Fatalf("CreatePackages failed: %s", err)
	}
	prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
	mainPkg := prog.Package(iprog.Created[0].Pkg)
	if mainPkg.Func("main") != nil {
		t.Fatalf("unexpected main function")
	}
	if prog.CreateTestMainPackage(mainPkg) != nil {
		t.Fatalf("CreateTestMainPackage returned non-nil")
	}
}
<|endoftext|>


<commit_before>package tchannel

// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import (
	"bytes"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/uber/tchannel/golang/typed"
)

func TestNoFragmentation(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	arg1 := []byte("Hello")
	w := newBodyWriter(out)
	require.Nil(t, w.WriteArgument(BytesOutput(arg1), true))

	// Should be a single frame
	// fragment flags(1), checksum type (1), checksum(5), chunk size(2), chunk(5)
	expectedFrames := combineBuffers([][]byte{
		[]byte{0x00, byte(ChecksumTypeCrc32)},
		ChecksumTypeCrc32.New().Add([]byte("Hello")),
		[]byte{0x00, 0x05},
		[]byte("Hello")})
	assertFramesEqual(t, expectedFrames, out.sentFragments, "no fragmentation")

	r1 := newBodyReader(in, true)
	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}

	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())
}

func TestFragmentationRoundTrip(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	// Write three arguments, each of which should span fragments
	arg1 := make([]byte, MaxFramePayloadSize*2+756)
	for i := range arg1 {
		arg1[i] = byte(i % 0x0F)
	}
	w := newBodyWriter(out)
	if _, err := w.Write(arg1); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg2 := make([]byte, MaxFramePayloadSize+229)
	for i := range arg2 {
		arg2[i] = byte(i%0x0F) + 0x10
	}
	if _, err := w.Write(arg2); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg3 := make([]byte, MaxFramePayloadSize+72)
	for i := range arg3 {
		arg3[i] = byte(i%0x0F) + 0x20
	}
	if _, err := w.Write(arg3); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(true))

	// Read the three arguments
	r1 := newBodyReader(in, false)

	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())

	r2 := newBodyReader(in, false)
	rarg2 := make([]byte, len(arg2))
	if _, err := r2.Read(rarg2); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg2, rarg2)
	require.Nil(t, r2.endArgument())

	r3 := newBodyReader(in, true)
	rarg3 := make([]byte, len(arg3))
	if _, err := r3.Read(rarg3); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg3, rarg3)
	require.Nil(t, r3.endArgument())
}

func TestArgEndOnFragmentBoundary(t *testing.T) {
	// Each argument should line up exactly at the end of each fragment
	in, out := buildChannels(ChecksumTypeCrc32)

	// Calculate the number of bytes available in the fragment content, which is the size
	// of the full frame minus the header content for the fragment.  Header content consists of
	// 1 byte flag, 1 byte checksum type, 4 byte checksum value, for a total of 6 bytes
	fragmentContentSize := int(MaxFramePayloadSize) - 6
	arg1 := make([]byte, fragmentContentSize-2) // reserve 2 bytes for the arg chunk size
	for i := range arg1 {
		arg1[i] = byte(i % 0x0F)
	}
	w := newBodyWriter(out)
	if _, err := w.Write(arg1); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg2 := make([]byte, len(arg1)-2) // additional 2 byte trailing size for arg1
	for i := range arg2 {
		arg2[i] = byte(i % 0x1F)
	}
	if _, err := w.Write(arg2); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg3 := make([]byte, len(arg2)) // additional 2 byte trailing size for arg2
	for i := range arg3 {
		arg3[i] = byte(i % 0x2F)
	}
	if _, err := w.Write(arg3); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(true))

	// We should have sent 4 fragments (one for arg1, one for zero arg1 size + arg2,
	// one for zero arg2 size + arg3, one for zero arg3 size)
	sentFragments := out.sentFragments
	require.Equal(t, 4, len(sentFragments))
	lastFragment := sentFragments[len(sentFragments)-1]

	// 1 byte flags, 1 byte checksum type, 4 bytes checksum, 2 bytes size (0)
	require.Equal(t, 8, int(lastFragment.Header.PayloadSize()))
	r1 := newBodyReader(in, false)

	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())

	r2 := newBodyReader(in, false)
	rarg2 := make([]byte, len(arg2))
	if _, err := r2.Read(rarg2); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg2, rarg2)
	require.Nil(t, r2.endArgument())

	r3 := newBodyReader(in, true)
	rarg3 := make([]byte, len(arg3))
	if _, err := r3.Read(rarg3); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg3, rarg3)
	require.Nil(t, r3.endArgument())
}

func TestEmptyFragments(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	w := newBodyWriter(out)
	require.Nil(t, w.WriteArgument(BytesOutput(nil), false))
	require.Nil(t, w.WriteArgument(BytesOutput(nil), true))

	r1 := newBodyReader(in, false)
	var arg1 BytesInput
	require.Nil(t, r1.ReadArgument(&arg1, false))
	assert.Equal(t, 0, len(arg1))

	r2 := newBodyReader(in, true)
	var arg2 BytesInput
	require.Nil(t, r2.ReadArgument(&arg2, true))
	assert.Equal(t, 0, len(arg2))
}

func buildChannels(checksumType ChecksumType) (*inFragments, *outFragments) {
	ch := make(chan *Frame, 512)

	in := &inFragments{ch: ch}
	out := &outFragments{ch: ch, checksum: checksumType.New()}
	return in, out
}

type inFragments struct {
	checksum Checksum
	ch       <-chan *Frame
	current  *inFragment
}

type sampleMessage struct{}

func (m *sampleMessage) ID() uint32                       { return 0xDEADBEEF }
func (m *sampleMessage) messageType() messageType         { return messageTypeCallReq }
func (m *sampleMessage) read(r *typed.ReadBuffer) error   { return nil }
func (m *sampleMessage) write(w *typed.WriteBuffer) error { return nil }

func (in *inFragments) waitForFragment() (*inFragment, error) {
	if in.current == nil || !in.current.hasMoreChunks() {
		var err error
		f := <-in.ch
		if in.current, err = newInboundFragment(f, &sampleMessage{}, in.checksum); err != nil {
			return nil, err
		}

		in.checksum = in.current.checksum
	}

	return in.current, nil
}

type outFragments struct {
	fragmentSize  int
	checksum      Checksum
	ch            chan<- *Frame
	sentFragments []*Frame
}

func (out *outFragments) beginFragment() (*outFragment, error) {
	return newOutboundFragment(NewFrame(MaxFramePayloadSize), &sampleMessage{}, out.checksum)
}

func (out *outFragments) flushFragment(toSend *outFragment, last bool) error {
	f := toSend.finish(last)
	out.ch <- f
	out.sentFragments = append(out.sentFragments, f)
	return nil
}

func assertFramesEqual(t *testing.T, expected [][]byte, frames []*Frame, msg string) {
	require.Equal(t, len(expected), len(frames), fmt.Sprintf("incorrect number of frames for %s", msg))

	for i := range expected {
		assert.Equal(t, len(expected[i]), int(frames[i].Header.PayloadSize()),
			fmt.Sprintf("incorrect size for frame %d of %s", i, msg))
		assert.Equal(t, expected[i], frames[i].Payload[:frames[i].Header.PayloadSize()])
	}
}

func combineBuffers(elements ...[][]byte) [][]byte {
	var buffers [][]byte
	for i := range elements {
		buffers = append(buffers, bytes.Join(elements[i], []byte{}))
	}

	return buffers
}
<commit_msg>cleanup comments<commit_after>package tchannel

// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import (
	"bytes"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/uber/tchannel/golang/typed"
)

func TestNoFragmentation(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	arg1 := []byte("Hello")
	w := newBodyWriter(out)
	require.Nil(t, w.WriteArgument(BytesOutput(arg1), true))

	// Should be a single frame
	// fragment flags(1), checksum type (1), checksum(5), chunk size(2), chunk(5)
	expectedFrames := combineBuffers([][]byte{
		[]byte{0x00, byte(ChecksumTypeCrc32)},
		ChecksumTypeCrc32.New().Add([]byte("Hello")),
		[]byte{0x00, 0x05},
		[]byte("Hello")})
	assertFramesEqual(t, expectedFrames, out.sentFragments, "no fragmentation")

	r1 := newBodyReader(in, true)
	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}

	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())
}

func TestFragmentationRoundTrip(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	// Write three arguments, each of which should span fragments
	arg1 := make([]byte, MaxFramePayloadSize*2+756)
	for i := range arg1 {
		arg1[i] = byte(i % 0x0F)
	}
	w := newBodyWriter(out)
	if _, err := w.Write(arg1); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg2 := make([]byte, MaxFramePayloadSize+229)
	for i := range arg2 {
		arg2[i] = byte(i%0x0F) + 0x10
	}
	if _, err := w.Write(arg2); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg3 := make([]byte, MaxFramePayloadSize+72)
	for i := range arg3 {
		arg3[i] = byte(i%0x0F) + 0x20
	}
	if _, err := w.Write(arg3); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(true))

	// Read the three arguments
	r1 := newBodyReader(in, false)

	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())

	r2 := newBodyReader(in, false)
	rarg2 := make([]byte, len(arg2))
	if _, err := r2.Read(rarg2); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg2, rarg2)
	require.Nil(t, r2.endArgument())

	r3 := newBodyReader(in, true)
	rarg3 := make([]byte, len(arg3))
	if _, err := r3.Read(rarg3); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg3, rarg3)
	require.Nil(t, r3.endArgument())
}

func TestArgEndOnFragmentBoundary(t *testing.T) {
	// Each argument should line up exactly at the end of each fragment
	in, out := buildChannels(ChecksumTypeCrc32)

	// Calculate the number of bytes available in the fragment content,
	// which is the size of the full frame minus the header content for the
	// fragment.  Header content consists of 1 byte flag, 1 byte checksum
	// type, 4 byte checksum value, for a total of 6 bytes
	fragmentContentSize := int(MaxFramePayloadSize) - 6
	arg1 := make([]byte, fragmentContentSize-2) // reserve 2 bytes for the arg chunk size
	for i := range arg1 {
		arg1[i] = byte(i % 0x0F)
	}
	w := newBodyWriter(out)
	if _, err := w.Write(arg1); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg2 := make([]byte, len(arg1)-2) // additional 2 byte trailing size for arg1
	for i := range arg2 {
		arg2[i] = byte(i % 0x1F)
	}
	if _, err := w.Write(arg2); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(false))

	arg3 := make([]byte, len(arg2)) // additional 2 byte trailing size for arg2
	for i := range arg3 {
		arg3[i] = byte(i % 0x2F)
	}
	if _, err := w.Write(arg3); err != nil {
		require.Nil(t, err)
	}
	require.Nil(t, w.endArgument(true))

	// We should have sent 4 fragments (one for arg1, one for zero arg1
	// size + arg2, one for zero arg2 size + arg3, one for zero arg3 size)
	sentFragments := out.sentFragments
	require.Equal(t, 4, len(sentFragments))
	lastFragment := sentFragments[len(sentFragments)-1]

	// 1 byte flags, 1 byte checksum type, 4 bytes checksum, 2 bytes size (0)
	require.Equal(t, 8, int(lastFragment.Header.PayloadSize()))
	r1 := newBodyReader(in, false)

	rarg1 := make([]byte, len(arg1))
	if _, err := r1.Read(rarg1); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg1, rarg1)
	require.Nil(t, r1.endArgument())

	r2 := newBodyReader(in, false)
	rarg2 := make([]byte, len(arg2))
	if _, err := r2.Read(rarg2); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg2, rarg2)
	require.Nil(t, r2.endArgument())

	r3 := newBodyReader(in, true)
	rarg3 := make([]byte, len(arg3))
	if _, err := r3.Read(rarg3); err != nil {
		require.Nil(t, err)
	}
	assert.Equal(t, arg3, rarg3)
	require.Nil(t, r3.endArgument())
}

func TestEmptyFragments(t *testing.T) {
	in, out := buildChannels(ChecksumTypeCrc32)

	w := newBodyWriter(out)
	require.Nil(t, w.WriteArgument(BytesOutput(nil), false))
	require.Nil(t, w.WriteArgument(BytesOutput(nil), true))

	r1 := newBodyReader(in, false)
	var arg1 BytesInput
	require.Nil(t, r1.ReadArgument(&arg1, false))
	assert.Equal(t, 0, len(arg1))

	r2 := newBodyReader(in, true)
	var arg2 BytesInput
	require.Nil(t, r2.ReadArgument(&arg2, true))
	assert.Equal(t, 0, len(arg2))
}

func buildChannels(checksumType ChecksumType) (*inFragments, *outFragments) {
	ch := make(chan *Frame, 512)

	in := &inFragments{ch: ch}
	out := &outFragments{ch: ch, checksum: checksumType.New()}
	return in, out
}

type inFragments struct {
	checksum Checksum
	ch       <-chan *Frame
	current  *inFragment
}

type sampleMessage struct{}

func (m *sampleMessage) ID() uint32                       { return 0xDEADBEEF }
func (m *sampleMessage) messageType() messageType         { return messageTypeCallReq }
func (m *sampleMessage) read(r *typed.ReadBuffer) error   { return nil }
func (m *sampleMessage) write(w *typed.WriteBuffer) error { return nil }

func (in *inFragments) waitForFragment() (*inFragment, error) {
	if in.current == nil || !in.current.hasMoreChunks() {
		var err error
		f := <-in.ch
		if in.current, err = newInboundFragment(f, &sampleMessage{}, in.checksum); err != nil {
			return nil, err
		}

		in.checksum = in.current.checksum
	}

	return in.current, nil
}

type outFragments struct {
	fragmentSize  int
	checksum      Checksum
	ch            chan<- *Frame
	sentFragments []*Frame
}

func (out *outFragments) beginFragment() (*outFragment, error) {
	return newOutboundFragment(NewFrame(MaxFramePayloadSize), &sampleMessage{}, out.checksum)
}

func (out *outFragments) flushFragment(toSend *outFragment, last bool) error {
	f := toSend.finish(last)
	out.ch <- f
	out.sentFragments = append(out.sentFragments, f)
	return nil
}

func assertFramesEqual(t *testing.T, expected [][]byte, frames []*Frame, msg string) {
	require.Equal(t, len(expected), len(frames), fmt.Sprintf("incorrect number of frames for %s", msg))

	for i := range expected {
		assert.Equal(t, len(expected[i]), int(frames[i].Header.PayloadSize()),
			fmt.Sprintf("incorrect size for frame %d of %s", i, msg))
		assert.Equal(t, expected[i], frames[i].Payload[:frames[i].Header.PayloadSize()])
	}
}

func combineBuffers(elements ...[][]byte) [][]byte {
	var buffers [][]byte
	for i := range elements {
		buffers = append(buffers, bytes.Join(elements[i], []byte{}))
	}

	return buffers
}
<|endoftext|>


<commit_before>package google

import "fmt"

func GetBucketIamPolicyCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamPolicyBindings)
}

func GetBucketIamBindingCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamRoleBindings)
}

func GetBucketIamMemberCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamMemberBindings)
}

func MergeBucketIamPolicy(existing, incoming Asset) Asset {
	existing.IAMPolicy = incoming.IAMPolicy
	return existing
}

func MergeBucketIamBinding(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAuthoritativeBindings)
}

func MergeBucketIamBindingDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAuthoritativeBindings)
}

func MergeBucketIamMember(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAdditiveBindings)
}

func MergeBucketIamMemberDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAdditiveBindings)
}

func newBucketIamAsset(
	d TerraformResourceData,
	config *Config,
	expandBindings func(d TerraformResourceData) ([]IAMBinding, error),
) ([]Asset, error) {
	bindings, err := expandBindings(d)
	if err != nil {
		return []Asset{}, fmt.Errorf("expanding bindings: %v", err)
	}

	name, err := assetName(d, config, "//storage.googleapis.com/{{name}}")
	if err != nil {
		return []Asset{}, err
	}

	return []Asset{{
		Name: name,
		Type: "storage.googleapis.com/Bucket",
		IAMPolicy: &IAMPolicy{
			Bindings: bindings,
		},
	}}, nil
}

func FetchBucketIamPolicy(d TerraformResourceData, config *Config) (Asset, error) {
	return fetchIamPolicy(
		StorageBucketIamUpdaterProducer,
		d,
		config,
		"//storage.googleapis.com/{{name}}",
		"storage.googleapis.com/Bucket",
	)
}
<commit_msg>Fixed storage bucket iam CAI name (#4622) (#667)<commit_after>package google

import "fmt"

func GetBucketIamPolicyCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamPolicyBindings)
}

func GetBucketIamBindingCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamRoleBindings)
}

func GetBucketIamMemberCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
	return newBucketIamAsset(d, config, expandIamMemberBindings)
}

func MergeBucketIamPolicy(existing, incoming Asset) Asset {
	existing.IAMPolicy = incoming.IAMPolicy
	return existing
}

func MergeBucketIamBinding(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAuthoritativeBindings)
}

func MergeBucketIamBindingDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAuthoritativeBindings)
}

func MergeBucketIamMember(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAdditiveBindings)
}

func MergeBucketIamMemberDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAdditiveBindings)
}

func newBucketIamAsset(
	d TerraformResourceData,
	config *Config,
	expandBindings func(d TerraformResourceData) ([]IAMBinding, error),
) ([]Asset, error) {
	bindings, err := expandBindings(d)
	if err != nil {
		return []Asset{}, fmt.Errorf("expanding bindings: %v", err)
	}

	name, err := assetName(d, config, "//storage.googleapis.com/{{bucket}}")
	if err != nil {
		return []Asset{}, err
	}

	return []Asset{{
		Name: name,
		Type: "storage.googleapis.com/Bucket",
		IAMPolicy: &IAMPolicy{
			Bindings: bindings,
		},
	}}, nil
}

func FetchBucketIamPolicy(d TerraformResourceData, config *Config) (Asset, error) {
	return fetchIamPolicy(
		StorageBucketIamUpdaterProducer,
		d,
		config,
		"//storage.googleapis.com/{{bucket}}",
		"storage.googleapis.com/Bucket",
	)
}
<|endoftext|>