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

// This file contains a modified copy of the encoding/xml encoder.
// All dynamic behavior has been removed, and reflecttion has been replaced with go/types.
// This allows us to statically find unmarshable types
// with the same rules for tags, shadowing and addressability as encoding/xml.
// This is used for SA1026 and SA5008.

// NOTE(dh): we do not check CanInterface in various places, which means we'll accept more marshaler implementations than encoding/xml does. This will lead to a small amount of false negatives.

package fakexml

import (
	"fmt"
	"go/token"
	"go/types"

	"honnef.co/go/tools/go/types/typeutil"
	"honnef.co/go/tools/staticcheck/fakereflect"
)

func Marshal(v types.Type) error {
	return NewEncoder().Encode(v)
}

type Encoder struct {
	seen map[fakereflect.TypeAndCanAddr]struct{}
}

func NewEncoder() *Encoder {
	e := &Encoder{
		seen: map[fakereflect.TypeAndCanAddr]struct{}{},
	}
	return e
}

func (enc *Encoder) Encode(v types.Type) error {
	rv := fakereflect.TypeAndCanAddr{Type: v}
	return enc.marshalValue(rv, nil, nil, "x")
}

func implementsMarshaler(v fakereflect.TypeAndCanAddr) bool {
	t := v.Type
	obj, _, _ := types.LookupFieldOrMethod(t, false, nil, "MarshalXML")
	if obj == nil {
		return false
	}
	fn, ok := obj.(*types.Func)
	if !ok {
		return false
	}
	params := fn.Type().(*types.Signature).Params()
	if params.Len() != 2 {
		return false
	}
	if !typeutil.IsType(params.At(0).Type(), "*encoding/xml.Encoder") {
		return false
	}
	if !typeutil.IsType(params.At(1).Type(), "encoding/xml.StartElement") {
		return false
	}
	rets := fn.Type().(*types.Signature).Results()
	if rets.Len() != 1 {
		return false
	}
	if !typeutil.IsType(rets.At(0).Type(), "error") {
		return false
	}
	return true
}

func implementsMarshalerAttr(v fakereflect.TypeAndCanAddr) bool {
	t := v.Type
	obj, _, _ := types.LookupFieldOrMethod(t, false, nil, "MarshalXMLAttr")
	if obj == nil {
		return false
	}
	fn, ok := obj.(*types.Func)
	if !ok {
		return false
	}
	params := fn.Type().(*types.Signature).Params()
	if params.Len() != 1 {
		return false
	}
	if !typeutil.IsType(params.At(0).Type(), "encoding/xml.Name") {
		return false
	}
	rets := fn.Type().(*types.Signature).Results()
	if rets.Len() != 2 {
		return false
	}
	if !typeutil.IsType(rets.At(0).Type(), "encoding/xml.Attr") {
		return false
	}
	if !typeutil.IsType(rets.At(1).Type(), "error") {
		return false
	}
	return true
}

var textMarshalerType = types.NewInterfaceType([]*types.Func{
	types.NewFunc(token.NoPos, nil, "MarshalText", types.NewSignature(nil,
		types.NewTuple(),
		types.NewTuple(
			types.NewVar(token.NoPos, nil, "", types.NewSlice(types.Typ[types.Byte])),
			types.NewVar(0, nil, "", types.Universe.Lookup("error").Type())),
		false,
	)),
}, nil).Complete()

var N = 0

type CyclicTypeError struct {
	Type types.Type
	Path string
}

func (err *CyclicTypeError) Error() string {
	return "cyclic type"
}

// marshalValue writes one or more XML elements representing val.
// If val was obtained from a struct field, finfo must have its details.
func (e *Encoder) marshalValue(val fakereflect.TypeAndCanAddr, finfo *fieldInfo, startTemplate *StartElement, stack string) error {
	if _, ok := e.seen[val]; ok {
		return nil
	}
	e.seen[val] = struct{}{}

	// Drill into interfaces and pointers.
	seen := map[fakereflect.TypeAndCanAddr]struct{}{}
	for val.IsInterface() || val.IsPtr() {
		if val.IsInterface() {
			return nil
		}
		val = val.Elem()
		if _, ok := seen[val]; ok {
			// Loop in type graph, e.g. 'type P *P'
			return &CyclicTypeError{val.Type, stack}
		}
		seen[val] = struct{}{}
	}

	// Check for marshaler.
	if implementsMarshaler(val) {
		return nil
	}
	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if implementsMarshaler(pv) {
			return nil
		}
	}

	// Check for text marshaler.
	if val.Implements(textMarshalerType) {
		return nil
	}
	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if pv.Implements(textMarshalerType) {
			return nil
		}
	}

	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
	if (val.IsSlice() || val.IsArray()) && !isByteArray(val) && !isByteSlice(val) {
		if err := e.marshalValue(val.Elem(), finfo, startTemplate, stack+"[0]"); err != nil {
			return err
		}
		return nil
	}

	tinfo, err := getTypeInfo(val)
	if err != nil {
		return err
	}

	// Create start element.
	// Precedence for the XML element name is:
	// 0. startTemplate
	// 1. XMLName field in underlying struct;
	// 2. field name/tag in the struct field; and
	// 3. type name
	var start StartElement

	if startTemplate != nil {
		start.Name = startTemplate.Name
		start.Attr = append(start.Attr, startTemplate.Attr...)
	} else if tinfo.xmlname != nil {
		xmlname := tinfo.xmlname
		if xmlname.name != "" {
			start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
		}
	}

	// Attributes
	for i := range tinfo.fields {
		finfo := &tinfo.fields[i]
		if finfo.flags&fAttr == 0 {
			continue
		}
		fv := finfo.value(val)

		name := Name{Space: finfo.xmlns, Local: finfo.name}
		if err := e.marshalAttr(&start, name, fv, stack+pathByIndex(val, finfo.idx)); err != nil {
			return err
		}
	}

	if val.IsStruct() {
		return e.marshalStruct(tinfo, val, stack)
	} else {
		return e.marshalSimple(val, stack)
	}
}

func isSlice(v fakereflect.TypeAndCanAddr) bool {
	_, ok := v.Type.Underlying().(*types.Slice)
	return ok
}

func isByteSlice(v fakereflect.TypeAndCanAddr) bool {
	slice, ok := v.Type.Underlying().(*types.Slice)
	if !ok {
		return false
	}
	basic, ok := slice.Elem().Underlying().(*types.Basic)
	if !ok {
		return false
	}
	return basic.Kind() == types.Uint8
}

func isByteArray(v fakereflect.TypeAndCanAddr) bool {
	slice, ok := v.Type.Underlying().(*types.Array)
	if !ok {
		return false
	}
	basic, ok := slice.Elem().Underlying().(*types.Basic)
	if !ok {
		return false
	}
	return basic.Kind() == types.Uint8
}

// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
func (e *Encoder) marshalAttr(start *StartElement, name Name, val fakereflect.TypeAndCanAddr, stack string) error {
	if implementsMarshalerAttr(val) {
		return nil
	}

	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if implementsMarshalerAttr(pv) {
			return nil
		}
	}

	if val.Implements(textMarshalerType) {
		return nil
	}

	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if pv.Implements(textMarshalerType) {
			return nil
		}
	}

	// Dereference or skip nil pointer
	if val.IsPtr() {
		val = val.Elem()
	}

	// Walk slices.
	if isSlice(val) && !isByteSlice(val) {
		if err := e.marshalAttr(start, name, val.Elem(), stack+"[0]"); err != nil {
			return err
		}
		return nil
	}

	if typeutil.IsType(val.Type, "encoding/xml.Attr") {
		return nil
	}

	return e.marshalSimple(val, stack)
}

func (e *Encoder) marshalSimple(val fakereflect.TypeAndCanAddr, stack string) error {
	switch val.Type.Underlying().(type) {
	case *types.Basic, *types.Interface:
		return nil
	case *types.Slice, *types.Array:
		basic, ok := val.Elem().Type.Underlying().(*types.Basic)
		if !ok || basic.Kind() != types.Uint8 {
			return &UnsupportedTypeError{val.Type, stack}
		}
		return nil
	default:
		return &UnsupportedTypeError{val.Type, stack}
	}
}

func indirect(vf fakereflect.TypeAndCanAddr) fakereflect.TypeAndCanAddr {
	for vf.IsPtr() {
		vf = vf.Elem()
	}
	return vf
}

func pathByIndex(t fakereflect.TypeAndCanAddr, index []int) string {
	path := ""
	for _, i := range index {
		if t.IsPtr() {
			t = t.Elem()
		}
		path += "." + t.Field(i).Name
		t = t.Field(i).Type
	}
	return path
}

func (e *Encoder) marshalStruct(tinfo *typeInfo, val fakereflect.TypeAndCanAddr, stack string) error {
	for i := range tinfo.fields {
		finfo := &tinfo.fields[i]
		if finfo.flags&fAttr != 0 {
			continue
		}
		vf := finfo.value(val)

		switch finfo.flags & fMode {
		case fCDATA, fCharData:
			if vf.Implements(textMarshalerType) {
				continue
			}
			if vf.CanAddr() {
				pv := fakereflect.PtrTo(vf)
				if pv.Implements(textMarshalerType) {
					continue
				}
			}

			vf = indirect(vf)
			continue

		case fComment:
			vf = indirect(vf)
			if !(isByteSlice(vf) || isByteArray(vf)) {
				return fmt.Errorf("xml: bad type for comment field of %s", val)
			}
			continue

		case fInnerXML:
			vf = indirect(vf)
			if typeutil.IsType(vf.Type, "[]byte") || typeutil.IsType(vf.Type, "string") {
				continue
			}

		case fElement, fElement | fAny:
		}
		if err := e.marshalValue(vf, finfo, nil, stack+pathByIndex(val, finfo.idx)); err != nil {
			return err
		}
	}
	return nil
}

// UnsupportedTypeError is returned when Marshal encounters a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
	Type types.Type
	Path string
}

func (e *UnsupportedTypeError) Error() string {
	return fmt.Sprintf("xml: unsupported type %s, via %s ", e.Type, e.Path)
}
<commit_msg>staticcheck/fakexml: delete dead assignment<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains a modified copy of the encoding/xml encoder.
// All dynamic behavior has been removed, and reflecttion has been replaced with go/types.
// This allows us to statically find unmarshable types
// with the same rules for tags, shadowing and addressability as encoding/xml.
// This is used for SA1026 and SA5008.

// NOTE(dh): we do not check CanInterface in various places, which means we'll accept more marshaler implementations than encoding/xml does. This will lead to a small amount of false negatives.

package fakexml

import (
	"fmt"
	"go/token"
	"go/types"

	"honnef.co/go/tools/go/types/typeutil"
	"honnef.co/go/tools/staticcheck/fakereflect"
)

func Marshal(v types.Type) error {
	return NewEncoder().Encode(v)
}

type Encoder struct {
	seen map[fakereflect.TypeAndCanAddr]struct{}
}

func NewEncoder() *Encoder {
	e := &Encoder{
		seen: map[fakereflect.TypeAndCanAddr]struct{}{},
	}
	return e
}

func (enc *Encoder) Encode(v types.Type) error {
	rv := fakereflect.TypeAndCanAddr{Type: v}
	return enc.marshalValue(rv, nil, nil, "x")
}

func implementsMarshaler(v fakereflect.TypeAndCanAddr) bool {
	t := v.Type
	obj, _, _ := types.LookupFieldOrMethod(t, false, nil, "MarshalXML")
	if obj == nil {
		return false
	}
	fn, ok := obj.(*types.Func)
	if !ok {
		return false
	}
	params := fn.Type().(*types.Signature).Params()
	if params.Len() != 2 {
		return false
	}
	if !typeutil.IsType(params.At(0).Type(), "*encoding/xml.Encoder") {
		return false
	}
	if !typeutil.IsType(params.At(1).Type(), "encoding/xml.StartElement") {
		return false
	}
	rets := fn.Type().(*types.Signature).Results()
	if rets.Len() != 1 {
		return false
	}
	if !typeutil.IsType(rets.At(0).Type(), "error") {
		return false
	}
	return true
}

func implementsMarshalerAttr(v fakereflect.TypeAndCanAddr) bool {
	t := v.Type
	obj, _, _ := types.LookupFieldOrMethod(t, false, nil, "MarshalXMLAttr")
	if obj == nil {
		return false
	}
	fn, ok := obj.(*types.Func)
	if !ok {
		return false
	}
	params := fn.Type().(*types.Signature).Params()
	if params.Len() != 1 {
		return false
	}
	if !typeutil.IsType(params.At(0).Type(), "encoding/xml.Name") {
		return false
	}
	rets := fn.Type().(*types.Signature).Results()
	if rets.Len() != 2 {
		return false
	}
	if !typeutil.IsType(rets.At(0).Type(), "encoding/xml.Attr") {
		return false
	}
	if !typeutil.IsType(rets.At(1).Type(), "error") {
		return false
	}
	return true
}

var textMarshalerType = types.NewInterfaceType([]*types.Func{
	types.NewFunc(token.NoPos, nil, "MarshalText", types.NewSignature(nil,
		types.NewTuple(),
		types.NewTuple(
			types.NewVar(token.NoPos, nil, "", types.NewSlice(types.Typ[types.Byte])),
			types.NewVar(0, nil, "", types.Universe.Lookup("error").Type())),
		false,
	)),
}, nil).Complete()

var N = 0

type CyclicTypeError struct {
	Type types.Type
	Path string
}

func (err *CyclicTypeError) Error() string {
	return "cyclic type"
}

// marshalValue writes one or more XML elements representing val.
// If val was obtained from a struct field, finfo must have its details.
func (e *Encoder) marshalValue(val fakereflect.TypeAndCanAddr, finfo *fieldInfo, startTemplate *StartElement, stack string) error {
	if _, ok := e.seen[val]; ok {
		return nil
	}
	e.seen[val] = struct{}{}

	// Drill into interfaces and pointers.
	seen := map[fakereflect.TypeAndCanAddr]struct{}{}
	for val.IsInterface() || val.IsPtr() {
		if val.IsInterface() {
			return nil
		}
		val = val.Elem()
		if _, ok := seen[val]; ok {
			// Loop in type graph, e.g. 'type P *P'
			return &CyclicTypeError{val.Type, stack}
		}
		seen[val] = struct{}{}
	}

	// Check for marshaler.
	if implementsMarshaler(val) {
		return nil
	}
	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if implementsMarshaler(pv) {
			return nil
		}
	}

	// Check for text marshaler.
	if val.Implements(textMarshalerType) {
		return nil
	}
	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if pv.Implements(textMarshalerType) {
			return nil
		}
	}

	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
	if (val.IsSlice() || val.IsArray()) && !isByteArray(val) && !isByteSlice(val) {
		if err := e.marshalValue(val.Elem(), finfo, startTemplate, stack+"[0]"); err != nil {
			return err
		}
		return nil
	}

	tinfo, err := getTypeInfo(val)
	if err != nil {
		return err
	}

	// Create start element.
	// Precedence for the XML element name is:
	// 0. startTemplate
	// 1. XMLName field in underlying struct;
	// 2. field name/tag in the struct field; and
	// 3. type name
	var start StartElement

	if startTemplate != nil {
		start.Name = startTemplate.Name
		start.Attr = append(start.Attr, startTemplate.Attr...)
	} else if tinfo.xmlname != nil {
		xmlname := tinfo.xmlname
		if xmlname.name != "" {
			start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
		}
	}

	// Attributes
	for i := range tinfo.fields {
		finfo := &tinfo.fields[i]
		if finfo.flags&fAttr == 0 {
			continue
		}
		fv := finfo.value(val)

		name := Name{Space: finfo.xmlns, Local: finfo.name}
		if err := e.marshalAttr(&start, name, fv, stack+pathByIndex(val, finfo.idx)); err != nil {
			return err
		}
	}

	if val.IsStruct() {
		return e.marshalStruct(tinfo, val, stack)
	} else {
		return e.marshalSimple(val, stack)
	}
}

func isSlice(v fakereflect.TypeAndCanAddr) bool {
	_, ok := v.Type.Underlying().(*types.Slice)
	return ok
}

func isByteSlice(v fakereflect.TypeAndCanAddr) bool {
	slice, ok := v.Type.Underlying().(*types.Slice)
	if !ok {
		return false
	}
	basic, ok := slice.Elem().Underlying().(*types.Basic)
	if !ok {
		return false
	}
	return basic.Kind() == types.Uint8
}

func isByteArray(v fakereflect.TypeAndCanAddr) bool {
	slice, ok := v.Type.Underlying().(*types.Array)
	if !ok {
		return false
	}
	basic, ok := slice.Elem().Underlying().(*types.Basic)
	if !ok {
		return false
	}
	return basic.Kind() == types.Uint8
}

// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
func (e *Encoder) marshalAttr(start *StartElement, name Name, val fakereflect.TypeAndCanAddr, stack string) error {
	if implementsMarshalerAttr(val) {
		return nil
	}

	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if implementsMarshalerAttr(pv) {
			return nil
		}
	}

	if val.Implements(textMarshalerType) {
		return nil
	}

	if val.CanAddr() {
		pv := fakereflect.PtrTo(val)
		if pv.Implements(textMarshalerType) {
			return nil
		}
	}

	// Dereference or skip nil pointer
	if val.IsPtr() {
		val = val.Elem()
	}

	// Walk slices.
	if isSlice(val) && !isByteSlice(val) {
		if err := e.marshalAttr(start, name, val.Elem(), stack+"[0]"); err != nil {
			return err
		}
		return nil
	}

	if typeutil.IsType(val.Type, "encoding/xml.Attr") {
		return nil
	}

	return e.marshalSimple(val, stack)
}

func (e *Encoder) marshalSimple(val fakereflect.TypeAndCanAddr, stack string) error {
	switch val.Type.Underlying().(type) {
	case *types.Basic, *types.Interface:
		return nil
	case *types.Slice, *types.Array:
		basic, ok := val.Elem().Type.Underlying().(*types.Basic)
		if !ok || basic.Kind() != types.Uint8 {
			return &UnsupportedTypeError{val.Type, stack}
		}
		return nil
	default:
		return &UnsupportedTypeError{val.Type, stack}
	}
}

func indirect(vf fakereflect.TypeAndCanAddr) fakereflect.TypeAndCanAddr {
	for vf.IsPtr() {
		vf = vf.Elem()
	}
	return vf
}

func pathByIndex(t fakereflect.TypeAndCanAddr, index []int) string {
	path := ""
	for _, i := range index {
		if t.IsPtr() {
			t = t.Elem()
		}
		path += "." + t.Field(i).Name
		t = t.Field(i).Type
	}
	return path
}

func (e *Encoder) marshalStruct(tinfo *typeInfo, val fakereflect.TypeAndCanAddr, stack string) error {
	for i := range tinfo.fields {
		finfo := &tinfo.fields[i]
		if finfo.flags&fAttr != 0 {
			continue
		}
		vf := finfo.value(val)

		switch finfo.flags & fMode {
		case fCDATA, fCharData:
			if vf.Implements(textMarshalerType) {
				continue
			}
			if vf.CanAddr() {
				pv := fakereflect.PtrTo(vf)
				if pv.Implements(textMarshalerType) {
					continue
				}
			}
			continue

		case fComment:
			vf = indirect(vf)
			if !(isByteSlice(vf) || isByteArray(vf)) {
				return fmt.Errorf("xml: bad type for comment field of %s", val)
			}
			continue

		case fInnerXML:
			vf = indirect(vf)
			if typeutil.IsType(vf.Type, "[]byte") || typeutil.IsType(vf.Type, "string") {
				continue
			}

		case fElement, fElement | fAny:
		}
		if err := e.marshalValue(vf, finfo, nil, stack+pathByIndex(val, finfo.idx)); err != nil {
			return err
		}
	}
	return nil
}

// UnsupportedTypeError is returned when Marshal encounters a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
	Type types.Type
	Path string
}

func (e *UnsupportedTypeError) Error() string {
	return fmt.Sprintf("xml: unsupported type %s, via %s ", e.Type, e.Path)
}
<|endoftext|>


<commit_before>package v1

/* CHECKLIST
 * [ ] Uses interfaces as appropriate
 * [ ] Private package variables use underscore prefix
 * [ ] All parameters validated
 * [ ] All errors handled
 * [ ] Reviewed for concurrency safety
 * [ ] Code complete
 * [ ] Full test coverage
 */

import (
	"net/http"

	"github.com/tidepool-org/platform/data/context"
	"github.com/tidepool-org/platform/data/deduplicator/root"
	"github.com/tidepool-org/platform/data/normalizer"
	"github.com/tidepool-org/platform/data/parser"
	"github.com/tidepool-org/platform/data/types"
	"github.com/tidepool-org/platform/data/types/base/upload"
	"github.com/tidepool-org/platform/data/validator"
	"github.com/tidepool-org/platform/dataservices/server"
	"github.com/tidepool-org/platform/userservices/client"
)

func UsersDatasetsCreate(serverContext server.Context) {
	targetUserID := serverContext.Request().PathParam("userid")
	if targetUserID == "" {
		serverContext.RespondWithError(ErrorUserIDMissing())
		return
	}

	err := serverContext.Client().ValidateTargetUserPermissions(serverContext, serverContext.RequestUserID(), targetUserID, client.UploadPermissions)
	if err != nil {
		if client.IsUnauthorizedError(err) {
			serverContext.RespondWithError(ErrorUnauthorized())
		} else {
			serverContext.RespondWithInternalServerFailure("Unable to validate target user permissions", err)
		}
		return
	}

	targetUserGroupID, err := serverContext.Client().GetUserGroupID(serverContext, targetUserID)
	if err != nil {
		if client.IsUnauthorizedError(err) {
			serverContext.RespondWithError(ErrorUnauthorized())
		} else {
			serverContext.RespondWithInternalServerFailure("Unable to get group id for target user", err)
		}
		return
	}

	var rawDatum map[string]interface{}
	if err = serverContext.Request().DecodeJsonPayload(&rawDatum); err != nil {
		serverContext.RespondWithError(ErrorJSONMalformed())
		return
	}

	datumContext, err := context.NewStandard(serverContext.Logger())
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum context", err)
		return
	}

	datumParser, err := parser.NewStandardObject(datumContext, &rawDatum, parser.AppendErrorNotParsed)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum parser", err)
		return
	}

	datumValidator, err := validator.NewStandard(datumContext)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum validator", err)
		return
	}

	datumNormalizer, err := normalizer.NewStandard(datumContext)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum normalizer", err)
		return
	}

	datasetDatum, err := types.Parse(datumParser)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to parse datum parser", err)
		return
	}

	datumParser.ProcessNotParsed()

	datasetDatum.Validate(datumValidator)

	if errors := datumContext.Errors(); len(errors) > 0 {
		serverContext.RespondWithStatusAndErrors(http.StatusBadRequest, errors)
		return
	}

	datasetDatum.SetUserID(targetUserID)
	datasetDatum.SetGroupID(targetUserGroupID)
	datasetDatum.Normalize(datumNormalizer)

	datasetUpload, ok := datasetDatum.(*upload.Upload)
	if !ok {
		serverContext.RespondWithInternalServerFailure("Unexpected datum type", datasetDatum)
		return
	}

	if err = serverContext.Store().Insert(datasetUpload); err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to insert dataset", err)
		return
	}

	deduplicator, err := root.NewFactory().NewDeduplicator(serverContext.Logger(), serverContext.Store(), datasetUpload)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("No duplicator found matching dataset", err)
		return
	}

	if err = deduplicator.InitializeDataset(); err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to initialize dataset", err)
		return
	}

	// TODO: Filter datasetUpload to only "public" fields
	serverContext.Response().WriteHeader(http.StatusCreated)
	serverContext.Response().WriteJson(datasetUpload)
}
<commit_msg>Set upload user id programmatically, do not parse<commit_after>package v1

/* CHECKLIST
 * [ ] Uses interfaces as appropriate
 * [ ] Private package variables use underscore prefix
 * [ ] All parameters validated
 * [ ] All errors handled
 * [ ] Reviewed for concurrency safety
 * [ ] Code complete
 * [ ] Full test coverage
 */

import (
	"net/http"

	"github.com/tidepool-org/platform/data/context"
	"github.com/tidepool-org/platform/data/deduplicator/root"
	"github.com/tidepool-org/platform/data/normalizer"
	"github.com/tidepool-org/platform/data/parser"
	"github.com/tidepool-org/platform/data/types"
	"github.com/tidepool-org/platform/data/types/base/upload"
	"github.com/tidepool-org/platform/data/validator"
	"github.com/tidepool-org/platform/dataservices/server"
	"github.com/tidepool-org/platform/userservices/client"
)

func UsersDatasetsCreate(serverContext server.Context) {
	targetUserID := serverContext.Request().PathParam("userid")
	if targetUserID == "" {
		serverContext.RespondWithError(ErrorUserIDMissing())
		return
	}

	err := serverContext.Client().ValidateTargetUserPermissions(serverContext, serverContext.RequestUserID(), targetUserID, client.UploadPermissions)
	if err != nil {
		if client.IsUnauthorizedError(err) {
			serverContext.RespondWithError(ErrorUnauthorized())
		} else {
			serverContext.RespondWithInternalServerFailure("Unable to validate target user permissions", err)
		}
		return
	}

	targetUserGroupID, err := serverContext.Client().GetUserGroupID(serverContext, targetUserID)
	if err != nil {
		if client.IsUnauthorizedError(err) {
			serverContext.RespondWithError(ErrorUnauthorized())
		} else {
			serverContext.RespondWithInternalServerFailure("Unable to get group id for target user", err)
		}
		return
	}

	var rawDatum map[string]interface{}
	if err = serverContext.Request().DecodeJsonPayload(&rawDatum); err != nil {
		serverContext.RespondWithError(ErrorJSONMalformed())
		return
	}

	datumContext, err := context.NewStandard(serverContext.Logger())
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum context", err)
		return
	}

	datumParser, err := parser.NewStandardObject(datumContext, &rawDatum, parser.AppendErrorNotParsed)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum parser", err)
		return
	}

	datumValidator, err := validator.NewStandard(datumContext)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum validator", err)
		return
	}

	datumNormalizer, err := normalizer.NewStandard(datumContext)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to create datum normalizer", err)
		return
	}

	datasetDatum, err := types.Parse(datumParser)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to parse datum parser", err)
		return
	}

	datumParser.ProcessNotParsed()

	datasetDatum.Validate(datumValidator)

	if errors := datumContext.Errors(); len(errors) > 0 {
		serverContext.RespondWithStatusAndErrors(http.StatusBadRequest, errors)
		return
	}

	datasetDatum.SetUserID(targetUserID)
	datasetDatum.SetGroupID(targetUserGroupID)
	datasetDatum.Normalize(datumNormalizer)

	datasetUpload, ok := datasetDatum.(*upload.Upload)
	if !ok {
		serverContext.RespondWithInternalServerFailure("Unexpected datum type", datasetDatum)
		return
	}

	datasetUpload.SetUploadUserID(serverContext.RequestUserID())

	if err = serverContext.Store().Insert(datasetUpload); err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to insert dataset", err)
		return
	}

	deduplicator, err := root.NewFactory().NewDeduplicator(serverContext.Logger(), serverContext.Store(), datasetUpload)
	if err != nil {
		serverContext.RespondWithInternalServerFailure("No duplicator found matching dataset", err)
		return
	}

	if err = deduplicator.InitializeDataset(); err != nil {
		serverContext.RespondWithInternalServerFailure("Unable to initialize dataset", err)
		return
	}

	// TODO: Filter datasetUpload to only "public" fields
	serverContext.Response().WriteHeader(http.StatusCreated)
	serverContext.Response().WriteJson(datasetUpload)
}
<|endoftext|>


<commit_before>// pipe command for converting characters into DTMF tone PCM data.
// example usage:  pipe tones onto aplay;
// ./DTMFplayer[SYSV64].elf <<< "0123456789ABCD#*" | aplay -fs16
// (DTMFplayer has the same default rate as aplay, but has 16bit precision not aplay's 8bit default.)
// or specifiy sample rate;
// ./DTMFplayer\[SYSV64\].elf -rate=16000 <<< "0123456789ABCD#*" | aplay -fs16 -r 16000
package main

import (
	"bufio"
	"flag"
	"io"
	"os"
	"bytes"
)

import . "github.com/splace/signals"

var length = X(.07)
var gap = X(.08)

func main() {
	help := flag.Bool("help", false, "display help/usage.")
	var sampleRate uint
	flag.UintVar(&sampleRate, "rate", 8000, "`samples` per second.")
	flag.Parse()
	if *help {
		flag.PrintDefaults()
		os.Exit(0)
	}
	// cache the raw PCM data for each tone
	// (example, not really required.)
	var Tones = map[rune]PCM{
		'0': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'1': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'2': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'3': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'4': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'5': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'6': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'7': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'8': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'9': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'A': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'B': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'C': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'D': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'*': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'#': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
	}

	var gapPCM = NewPCMSignal(Constant{0}, gap, uint32(sampleRate), 2).(PCM16bit).PCM
	rr := bufio.NewReader(os.Stdin)
	for {
		Rune, _, err := rr.ReadRune()
		if err == io.EOF {
			os.Stdin.Close()
			break
		} else if err != nil {
			panic(err)
		}
		io.Copy(os.Stdout, bytes.NewReader(Tones[Rune].Data))
		io.Copy(os.Stdout, bytes.NewReader(gapPCM.Data))
	}

	os.Stdout.Close()
}

<commit_msg>comment<commit_after>// pipe command for converting characters into DTMF tone PCM data.
// example usage:  pipe tones onto aplay;
// ./DTMFplayer[SYSV64].elf <<< "0123456789ABCD#*" | aplay -fs16
// (DTMFplayer has the same default rate as aplay, but has 16bit precision not aplay's 8bit default.)
// or specifiy sample rate;
// ./DTMFplayer\[SYSV64\].elf -rate=16000 <<< "0123456789ABCD#*" | aplay -fs16 -r 16000
package main

import (
	"bufio"
	"flag"
	"io"
	"os"
	"bytes"
)

import . "github.com/splace/signals"

var length = X(.07)
var gap = X(.08)

func main() {
	help := flag.Bool("help", false, "display help/usage.")
	var sampleRate uint
	flag.UintVar(&sampleRate, "rate", 8000, "`samples` per second.")
	flag.Parse()
	if *help {
		flag.PrintDefaults()
		os.Exit(0)
	}
	// cache the raw PCM data for each tone. (helps efficiency if a lot of repeat tones.)
	var Tones = map[rune]PCM{
		'0': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'1': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'2': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'3': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'4': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'5': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'6': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'7': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'8': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1336)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'9': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'A': NewPCMSignal(Stacked{Sine{X(1.0 / 697)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'B': NewPCMSignal(Stacked{Sine{X(1.0 / 770)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'C': NewPCMSignal(Stacked{Sine{X(1.0 / 852)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'D': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1633)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'*': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1209)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
		'#': NewPCMSignal(Stacked{Sine{X(1.0 / 941)}, Sine{X(1.0 / 1477)}}, length, uint32(sampleRate), 2).(PCM16bit).PCM,
	}

	var gapPCM = NewPCMSignal(Constant{0}, gap, uint32(sampleRate), 2).(PCM16bit).PCM
	rr := bufio.NewReader(os.Stdin)
	for {
		Rune, _, err := rr.ReadRune()
		if err == io.EOF {
			os.Stdin.Close()
			break
		} else if err != nil {
			panic(err)
		}
		io.Copy(os.Stdout, bytes.NewReader(Tones[Rune].Data))
		io.Copy(os.Stdout, bytes.NewReader(gapPCM.Data))
	}

	os.Stdout.Close()
}

<|endoftext|>


<commit_before>package api

import (
	"log"
	"sync"

	"github.com/denkhaus/bitshares/client"
	"github.com/denkhaus/bitshares/latency"
	"github.com/juju/errors"
)

type ClientProvider interface {
	OnError(fn client.ErrorFunc)
	OnNotify(subscriberID int, fn client.NotifyFunc) error
	CallAPI(apiID int, method string, args ...interface{}) (interface{}, error)
	SetDebug(debug bool)
	Close() error
}

type SimpleClientProvider struct {
	client.WebsocketClient
}

func NewSimpleClientProvider(endpointURL string) *SimpleClientProvider {
	sim := SimpleClientProvider{
		WebsocketClient: client.NewWebsocketClient(endpointURL),
	}

	return &sim
}

func (p *SimpleClientProvider) CallAPI(apiID int, method string, args ...interface{}) (interface{}, error) {
	if !p.WebsocketClient.IsConnected() {
		if err := p.Connect(); err != nil {
			return nil, errors.Annotate(err, "Connect")
		}
	}

	return p.WebsocketClient.CallAPI(apiID, method, args...)
}

type BestNodeClientProvider struct {
	mu  sync.Mutex
	api BitsharesAPI
	client.WebsocketClient
	tester latency.LatencyTester
}

func NewBestNodeClientProvider(endpointURL string, api BitsharesAPI) (*BestNodeClientProvider, error) {
	tester, err := latency.NewLatencyTester(endpointURL)
	if err != nil {
		return nil, errors.Annotate(err, "NewLatencyTester")
	}

	pr := &BestNodeClientProvider{
		api:             api,
		tester:          tester,
		WebsocketClient: tester.TopNodeClient(),
	}

	tester.OnTopNodeChanged(pr.onTopNodeChanged)
	tester.Start()

	return pr, nil
}

func (p *BestNodeClientProvider) onTopNodeChanged(newEndpoint string) error {
	p.mu.Lock()
	defer p.mu.Unlock()
	log.Printf("change top node client -> %s\n", newEndpoint)

	if p.WebsocketClient.IsConnected() {
		p.WebsocketClient.Close()
	}

	p.WebsocketClient = p.tester.TopNodeClient()

	if err := p.Connect(); err != nil {
		return errors.Annotate(err, "Connect [client]")
	}

	if err := p.api.Connect(); err != nil {
		return errors.Annotate(err, "Connect [api]")
	}

	return nil
}

func (p *BestNodeClientProvider) CallAPI(apiID int, method string, args ...interface{}) (interface{}, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	return p.WebsocketClient.CallAPI(apiID, method, args...)
}

func (p *BestNodeClientProvider) Close() error {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.WebsocketClient.IsConnected() {
		p.WebsocketClient.Close()
		if err := p.WebsocketClient.Close(); err != nil {
			return errors.Annotate(err, "Close [client]")
		}
	}

	if err := p.tester.Close(); err != nil {
		return errors.Annotate(err, "Close [tester]")
	}

	return nil
}
<commit_msg>fix connect issue<commit_after>package api

import (
	"log"
	"sync"

	"github.com/denkhaus/bitshares/client"
	"github.com/denkhaus/bitshares/latency"
	"github.com/juju/errors"
)

type ClientProvider interface {
	OnError(fn client.ErrorFunc)
	OnNotify(subscriberID int, fn client.NotifyFunc) error
	CallAPI(apiID int, method string, args ...interface{}) (interface{}, error)
	SetDebug(debug bool)
	Close() error
}

type SimpleClientProvider struct {
	client.WebsocketClient
}

func NewSimpleClientProvider(endpointURL string) *SimpleClientProvider {
	sim := SimpleClientProvider{
		WebsocketClient: client.NewWebsocketClient(endpointURL),
	}

	return &sim
}

func (p *SimpleClientProvider) CallAPI(apiID int, method string, args ...interface{}) (interface{}, error) {
	if !p.WebsocketClient.IsConnected() {
		if err := p.Connect(); err != nil {
			return nil, errors.Annotate(err, "Connect")
		}
	}

	return p.WebsocketClient.CallAPI(apiID, method, args...)
}

type BestNodeClientProvider struct {
	mu  sync.Mutex
	api BitsharesAPI
	client.WebsocketClient
	tester latency.LatencyTester
}

func NewBestNodeClientProvider(endpointURL string, api BitsharesAPI) (*BestNodeClientProvider, error) {
	tester, err := latency.NewLatencyTester(endpointURL)
	if err != nil {
		return nil, errors.Annotate(err, "NewLatencyTester")
	}

	pr := &BestNodeClientProvider{
		api:             api,
		tester:          tester,
		WebsocketClient: tester.TopNodeClient(),
	}

	tester.OnTopNodeChanged(pr.onTopNodeChanged)
	tester.Start()

	return pr, nil
}

func (p *BestNodeClientProvider) onTopNodeChanged(newEndpoint string) error {
	p.mu.Lock()
	defer p.mu.Unlock()

	log.Printf("change top node client -> %s\n", newEndpoint)

	if p.IsConnected() {
		if err := p.WebsocketClient.Close(); err != nil {
			return errors.Annotate(err, "Close [client]")
		}
	}

	p.WebsocketClient = p.tester.TopNodeClient()

	if err := p.Connect(); err != nil {
		return errors.Annotate(err, "Connect [client]")
	}

	if err := p.api.Connect(); err != nil {
		return errors.Annotate(err, "Connect [api]")
	}

	return nil
}

func (p *BestNodeClientProvider) CallAPI(apiID int, method string, args ...interface{}) (interface{}, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if !p.IsConnected() {
		if err := p.Connect(); err != nil {
			return nil, errors.Annotate(err, "Connect [client]")
		}
	}

	return p.WebsocketClient.CallAPI(apiID, method, args...)
}

func (p *BestNodeClientProvider) Close() error {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.WebsocketClient.IsConnected() {
		p.WebsocketClient.Close()
		if err := p.WebsocketClient.Close(); err != nil {
			return errors.Annotate(err, "Close [client]")
		}
	}

	if err := p.tester.Close(); err != nil {
		return errors.Annotate(err, "Close [tester]")
	}

	return nil
}
<|endoftext|>


<commit_before>package byteio

// WriteUintX writes the unsigned integer using a variable number of bytes
func (e *BigEndianWriter) WriteUintX(d uint64) (int, error) {
	pos := 8
	if d > 9295997013522923647 {
		e.buffer[8] = byte(d)
		d >>= 8
	} else {
		e.buffer[8] = byte(d & 0x7f)
		d >>= 7
	}
	for ; d > 0; d >>= 7 {
		pos--
		d--
		e.buffer[pos] = byte(d&0x7f) | 0x80
	}
	return e.Write(e.buffer[pos:])
}

// WriteIntX writes the integer using a variable number of bytes
func (e *BigEndianWriter) WriteIntX(d int64) (int, error) {
	return e.WriteUintX(zigzag(d))
}
<commit_msg>replaced magic number with a built const<commit_after>package byteio

const maxBENineByte = 0x80<<56 | 0x80<<49 | 0x80<<42 | 0x80<<35 | 0x80<<28 | 0x80<<21 | 0x80<<14 | 0x80<<7 | 0x7f

// WriteUintX writes the unsigned integer using a variable number of bytes
func (e *BigEndianWriter) WriteUintX(d uint64) (int, error) {
	pos := 8
	if d > maxBENineByte {
		e.buffer[8] = byte(d)
		d >>= 8
	} else {
		e.buffer[8] = byte(d & 0x7f)
		d >>= 7
	}
	for ; d > 0; d >>= 7 {
		pos--
		d--
		e.buffer[pos] = byte(d&0x7f) | 0x80
	}
	return e.Write(e.buffer[pos:])
}

// WriteIntX writes the integer using a variable number of bytes
func (e *BigEndianWriter) WriteIntX(d int64) (int, error) {
	return e.WriteUintX(zigzag(d))
}
<|endoftext|>


<commit_before>package release

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/goreleaser/goreleaser/client"
	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/stretchr/testify/assert"
)

func TestPipeDescription(t *testing.T) {
	assert.NotEmpty(t, Pipe{}.Description())
}

func TestRunPipe(t *testing.T) {
	assert := assert.New(t)
	folder, err := ioutil.TempDir("", "gorelasertest")
	assert.NoError(err)
	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
	assert.NoError(err)
	debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
	assert.NoError(err)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Dist: folder,
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	ctx.AddArtifact(tarfile.Name())
	ctx.AddArtifact(debfile.Name())
	client := &DummyClient{}
	assert.NoError(doRun(ctx, client))
	assert.True(client.CreatedRelease)
	assert.True(client.UploadedFile)
}

func TestRunPipeWithFileThatDontExist(t *testing.T) {
	assert := assert.New(t)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	ctx.AddArtifact("this-file-wont-exist-hopefuly")
	client := &DummyClient{}
	assert.Error(doRun(ctx, client))
	assert.True(client.CreatedRelease)
	assert.False(client.UploadedFile)
}

type DummyClient struct {
	CreatedRelease bool
	UploadedFile   bool
}

func (client *DummyClient) GetInfo(ctx *context.Context) (info client.Info, err error) {
	return
}

func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
	client.CreatedRelease = true
	return
}

func (client *DummyClient) CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error) {
	return
}

func (client *DummyClient) Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error) {
	client.UploadedFile = true
	return
}
<commit_msg>more release tests<commit_after>package release

import (
	"bytes"
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/goreleaser/goreleaser/client"
	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/stretchr/testify/assert"
)

func TestPipeDescription(t *testing.T) {
	assert.NotEmpty(t, Pipe{}.Description())
}

func TestRunPipe(t *testing.T) {
	var assert = assert.New(t)
	folder, err := ioutil.TempDir("", "gorelasertest")
	assert.NoError(err)
	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
	assert.NoError(err)
	debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
	assert.NoError(err)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Dist: folder,
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	ctx.AddArtifact(tarfile.Name())
	ctx.AddArtifact(debfile.Name())
	client := &DummyClient{}
	assert.NoError(doRun(ctx, client))
	assert.True(client.CreatedRelease)
	assert.True(client.UploadedFile)
}

func TestRunPipeReleaseCreationFailed(t *testing.T) {
	var assert = assert.New(t)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	client := &DummyClient{
		FailToCreateRelease: true,
	}
	assert.Error(doRun(ctx, client))
	assert.False(client.CreatedRelease)
	assert.False(client.UploadedFile)
}

func TestRunPipeWithFileThatDontExist(t *testing.T) {
	var assert = assert.New(t)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	ctx.AddArtifact("this-file-wont-exist-hopefuly")
	client := &DummyClient{}
	assert.Error(doRun(ctx, client))
	assert.True(client.CreatedRelease)
	assert.False(client.UploadedFile)
}

func TestRunPipeUploadFailure(t *testing.T) {
	var assert = assert.New(t)
	folder, err := ioutil.TempDir("", "gorelasertest")
	assert.NoError(err)
	tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
	assert.NoError(err)
	var ctx = &context.Context{
		Git: context.GitInfo{
			CurrentTag: "v1.0.0",
		},
		Config: config.Project{
			Dist: folder,
			Release: config.Release{
				GitHub: config.Repo{
					Owner: "test",
					Name:  "test",
				},
			},
		},
	}
	ctx.AddArtifact(tarfile.Name())
	client := &DummyClient{
		FailToUpload: true,
	}
	assert.Error(doRun(ctx, client))
	assert.True(client.CreatedRelease)
	assert.False(client.UploadedFile)
}

type DummyClient struct {
	FailToCreateRelease bool
	FailToUpload        bool
	CreatedRelease      bool
	UploadedFile        bool
}

func (client *DummyClient) GetInfo(ctx *context.Context) (info client.Info, err error) {
	return
}

func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
	if client.FailToCreateRelease {
		return 0, errors.New("release failed")
	}
	client.CreatedRelease = true
	return
}

func (client *DummyClient) CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error) {
	return
}

func (client *DummyClient) Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error) {
	if client.FailToUpload {
		return errors.New("upload failed")
	}
	client.UploadedFile = true
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/ying32/govcl/vcl"
	"github.com/ying32/govcl/vcl/types"
)

func (m *TForm1) OnFormCreate(sender vcl.IObject) {
	fmt.Println(Form1.Caption(), m.PixelsPerInch())
	Form1.Button1.SetOnClick(func(sender vcl.IObject) {
		//vcl.ShowMessage("Hello!")
		jpg := vcl.NewJPEGImage()
		defer jpg.Free()
		jpg.LoadFromFile("a.jpg")
	})

	Form1.CheckBox1.SetOnClick(func(sender vcl.IObject) {
		Form1.Button1.SetEnabled(Form1.CheckBox1.Checked())

	})

	Form1.SetOnCloseQuery(func(sender vcl.IObject, canClose *bool) {
		fmt.Println("关闭。")
	})

	Form1.ActFileNew.SetOnExecute(func(vcl.IObject) {
		vcl.ShowMessage("ActFileNew Execute.")
	})
	Form1.Button2.SetOnClick(func(vcl.IObject) {
		result := Form2.ShowModal()
		if result == types.MrOk {
			vcl.ShowMessage("Form2返回了OK")
		} else if result == types.MrClose || result == types.MrNone {
			vcl.ShowMessage("Form2返回了Close")
		} else if result == types.MrCancel {
			vcl.ShowMessage("Form2返回了Cancel")
		}
	})
	Form1.ActExit.SetOnExecute(func(vcl.IObject) {
		vcl.Application.Terminate()
	})
}
<commit_msg>Update basicResForm/Form1Impl.go<commit_after>package main

import (
	"fmt"

	"github.com/ying32/govcl/vcl/rtl"
	"github.com/ying32/govcl/vcl/types/keys"

	"github.com/ying32/govcl/vcl"
	"github.com/ying32/govcl/vcl/types"
)

func (f *TForm1) OnFormCreate(sender vcl.IObject) {
	fmt.Println(Form1.Caption(), f.PixelsPerInch())
	Form1.Button1.SetOnClick(func(sender vcl.IObject) {
		//vcl.ShowMessage("Hello!")
		jpg := vcl.NewJPEGImage()
		defer jpg.Free()
		jpg.LoadFromFile("a.jpg")
	})

	Form1.CheckBox1.SetOnClick(func(sender vcl.IObject) {
		Form1.Button1.SetEnabled(Form1.CheckBox1.Checked())

	})

	Form1.SetOnCloseQuery(func(sender vcl.IObject, canClose *bool) {
		fmt.Println("关闭。")
	})

	Form1.ActFileNew.SetOnExecute(func(vcl.IObject) {
		vcl.ShowMessage("ActFileNew Execute.")
	})
	Form1.Button2.SetOnClick(func(vcl.IObject) {
		result := Form2.ShowModal()
		if result == types.MrOk {
			vcl.ShowMessage("Form2返回了OK")
		} else if result == types.MrClose || result == types.MrNone {
			vcl.ShowMessage("Form2返回了Close")
		} else if result == types.MrCancel {
			vcl.ShowMessage("Form2返回了Cancel")
		}
	})
	Form1.ActExit.SetOnExecute(func(vcl.IObject) {
		vcl.Application.Terminate()
	})

	// 遍历组件
	// 只要owner设置为Form的都可以通过这个方法来遍历。
	var i int32
	for i = 0; i < f.ComponentCount(); i++ {
		comp := f.Components(i)
		//fmt.Println(i, "=", comp.Name())
		if comp.InheritsFrom(vcl.TMemoClass()) {
			fmt.Println(i, "=", comp.Name(), ", 继承自TMemo")
			mem := vcl.MemoFromObj(comp)
			mem.SetOnKeyUp(f.memoOnKeyup)
		}
	}
}

func (f *TForm1) memoOnKeyup(sender vcl.IObject, key *types.Char, shift types.TShiftState) {
	if rtl.InSets(shift, types.SsCtrl) && *key == /*keys.VkA*/ keys.VkB {
		vcl.MemoFromObj(sender).SelectAll()
	}
}
<|endoftext|>


<commit_before>package sarama

import "testing"

var (
	saslAuthenticateRequest = []byte{
		0, 3, 'f', 'o', 'o',
	}
)

func TestSaslAuthenticateRequest(t *testing.T) {
	var request *SaslHandshakeRequest

	request = new(SaslHandshakeRequest)
	request.Mechanism = "foo"
	testRequest(t, "basic", request, saslAuthenticateRequest)
}
<commit_msg>Fix SaslAuthenticateRequest<commit_after>package sarama

import "testing"

var (
	saslAuthenticateRequest = []byte{
		0, 0, 0, 3, 'f', 'o', 'o',
	}
)

func TestSaslAuthenticateRequest(t *testing.T) {
	var request *SaslAuthenticateRequest

	request = new(SaslAuthenticateRequest)
	request.SaslAuthBytes = []byte(`foo`)
	testRequest(t, "basic", request, saslAuthenticateRequest)
}
<|endoftext|>


<commit_before>package emulator

import (
	"fmt"
	"reflect"
	"time"

	ccapi "github.com/ingvagabund/cluster-capacity/pkg/api"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/restclient"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/store"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/strategy"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/client/cache"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/watch"
	soptions "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options"
	"k8s.io/kubernetes/plugin/pkg/scheduler"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
	"k8s.io/kubernetes/plugin/pkg/scheduler/factory"

	"io/ioutil"
	"os"

	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/runtime"
	// register algorithm providers
	_ "k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
)

type ClusterCapacity struct {
	// caches modified by emulation strategy
	resourceStore store.ResourceStore

	// emulation strategy
	strategy strategy.Strategy

	// fake kube client
	kubeclient clientset.Interface

	// schedulers
	schedulers       map[string]*scheduler.Scheduler
	schedulerConfigs map[string]*scheduler.Config
	defaultScheduler string

	// pod to schedule
	simulatedPod *api.Pod
	maxSimulated int
	simulated    int
	status       Status

	// stop the analysis
	stop chan struct{}
}

// capture all scheduled pods with reason why the analysis could not continue
type Status struct {
	Pods       []*api.Pod
	StopReason string
}

func (c *ClusterCapacity) Status() Status {
	return c.status
}

func (c *ClusterCapacity) SyncWithClient(client cache.Getter) error {

	for _, resource := range c.resourceStore.Resources() {
		listWatcher := cache.NewListWatchFromClient(client, resource, api.NamespaceAll, fields.ParseSelectorOrDie(""))

		options := api.ListOptions{ResourceVersion: "0"}
		list, err := listWatcher.List(options)
		if err != nil {
			return fmt.Errorf("Failed to list objects: %v", err)
		}

		listMetaInterface, err := meta.ListAccessor(list)
		if err != nil {
			return fmt.Errorf("Unable to understand list result %#v: %v", list, err)
		}
		resourceVersion := listMetaInterface.GetResourceVersion()

		items, err := meta.ExtractList(list)
		if err != nil {
			return fmt.Errorf("Unable to understand list result %#v (%v)", list, err)
		}
		found := make([]interface{}, 0, len(items))
		for _, item := range items {
			found = append(found, item)
		}
		err = c.resourceStore.Replace(resource, found, resourceVersion)
		if err != nil {
			return fmt.Errorf("Unable to store %s list result: %v", resource, err)
		}
	}
	return nil
}

func (c *ClusterCapacity) SyncWithStore(resourceStore store.ResourceStore) {
	for _, resource := range resourceStore.Resources() {
		err := c.resourceStore.Replace(resource, resourceStore.List(resource), "0")
		if err != nil {
			fmt.Printf("Resource replace error: %v\n", err)
		}
	}
}

func (c *ClusterCapacity) Bind(binding *api.Binding, schedulerName string) error {
	// pod name: binding.Name
	// node name: binding.Target.Name
	// fmt.Printf("\nPod: %v, node: %v, scheduler: %v\n", binding.Name, binding.Target.Name, schedulerName)

	// run the pod through strategy
	key := &api.Pod{
		ObjectMeta: api.ObjectMeta{Name: binding.Name, Namespace: binding.Namespace},
	}
	pod, exists, err := c.resourceStore.Get(ccapi.Pods, runtime.Object(key))
	if err != nil {
		return fmt.Errorf("Unable to bind: %v", err)
	}
	if !exists {
		return fmt.Errorf("Unable to bind, pod %v not found", pod)
	}
	updatedPod := *pod.(*api.Pod)
	updatedPod.Spec.NodeName = binding.Target.Name
	// fmt.Printf("Pod binding: %v\n", updatedPod)

	// TODO(jchaloup): rename Add to Update as this actually updates the scheduled pod
	if err := c.strategy.Add(&updatedPod); err != nil {
		return fmt.Errorf("Unable to recompute new cluster state: %v", err)
	}

	c.status.Pods = append(c.status.Pods, &updatedPod)
	go func() {
		<-c.schedulerConfigs[schedulerName].Recorder.(*record.FakeRecorder).Events
		//fmt.Printf("Scheduling event: %v\n", event)
	}()
	// all good, create another pod
	if err := c.nextPod(); err != nil {
		return fmt.Errorf("Unable to create next pod to schedule: %v", err)
	}
	return nil
}

func (c *ClusterCapacity) Update(pod *api.Pod, podCondition *api.PodCondition, schedulerName string) error {
	// once the api.PodCondition
	podUnschedulableCond := &api.PodCondition{
		Type:   api.PodScheduled,
		Status: api.ConditionFalse,
		Reason: "Unschedulable",
	}

	stop := reflect.DeepEqual(podCondition, podUnschedulableCond)

	//fmt.Printf("pod condition: %v\n", podCondition)
	go func() {
		event := <-c.schedulerConfigs[schedulerName].Recorder.(*record.FakeRecorder).Events
		// end the simulation
		// TODO(jchaloup): this needs to be reworked in a case of multiple schedulers
		// The stop condition is different for a case of multi-pods
		if stop {
			c.status.StopReason = event
			for _, name := range c.schedulerConfigs {
				close(name.StopEverything)
			}
			c.stop <- struct{}{}
		}
	}()

	return nil
}

func (c *ClusterCapacity) nextPod() error {
	pod := *c.simulatedPod
	// use simulated pod name with an index to construct the name
	pod.ObjectMeta.Name = fmt.Sprintf("%v-%v", c.simulatedPod.Name, c.simulated)
	c.simulated++
	return c.resourceStore.Add(ccapi.Pods, runtime.Object(&pod))
}

func (c *ClusterCapacity) Run() error {
	// TODO(jchaloup): remove all pods that are not scheduled yet

	for _, scheduler := range c.schedulers {
		scheduler.Run()
	}
	// wait some time before at least nodes are populated
	// TODO(jchaloup); find a better way how to do this or at least increase it to <100ms
	time.Sleep(100 * time.Millisecond)
	// create the first simulated pod
	err := c.nextPod()
	if err != nil {
		return fmt.Errorf("Unable to create next pod to schedule: %v", err)
	}

	<-c.stop
	close(c.stop)

	return nil
}

type localBinderPodConditionUpdater struct {
	SchedulerName string
	C             *ClusterCapacity
}

func (b *localBinderPodConditionUpdater) Bind(binding *api.Binding) error {
	return b.C.Bind(binding, b.SchedulerName)
}

func (b *localBinderPodConditionUpdater) Update(pod *api.Pod, podCondition *api.PodCondition) error {
	return b.C.Update(pod, podCondition, b.SchedulerName)
}

func (c *ClusterCapacity) createSchedulerConfig(s *soptions.SchedulerServer) (*scheduler.Config, error) {
	configFactory := factory.NewConfigFactory(c.kubeclient, s.SchedulerName, s.HardPodAffinitySymmetricWeight, s.FailureDomains)
	config, err := createConfig(s, configFactory)

	if err != nil {
		return nil, fmt.Errorf("Failed to create scheduler configuration: %v", err)
	}

	// Collect scheduler succesfully/failed scheduled pod
	config.Recorder = record.NewFakeRecorder(10)
	// Replace the binder with simulator pod counter
	lbpcu := &localBinderPodConditionUpdater{
		SchedulerName: s.SchedulerName,
		C:             c,
	}
	config.Binder = lbpcu
	config.PodConditionUpdater = lbpcu
	return config, nil
}

func (c *ClusterCapacity) AddScheduler(s *soptions.SchedulerServer) error {
	config, err := c.createSchedulerConfig(s)
	if err != nil {
		return err
	}

	c.schedulers[s.SchedulerName] = scheduler.New(config)
	c.schedulerConfigs[s.SchedulerName] = config
	return nil
}

func createConfig(s *soptions.SchedulerServer, configFactory *factory.ConfigFactory) (*scheduler.Config, error) {
	if _, err := os.Stat(s.PolicyConfigFile); err == nil {
		var (
			policy     schedulerapi.Policy
			configData []byte
		)
		configData, err := ioutil.ReadFile(s.PolicyConfigFile)
		if err != nil {
			return nil, fmt.Errorf("unable to read policy config: %v", err)
		}
		if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
			return nil, fmt.Errorf("invalid configuration: %v", err)
		}
		return configFactory.CreateFromConfig(policy)
	}

	// if the config file isn't provided, use the specified (or default) provider
	return configFactory.CreateFromProvider(s.AlgorithmProvider)
}

// Create new cluster capacity analysis
// The analysis is completely independent of apiserver so no need
// for kubeconfig nor for apiserver url
func New(s *soptions.SchedulerServer, simulatedPod *api.Pod) (*ClusterCapacity, error) {
	resourceStore := store.NewResourceStore()
	restClient := restclient.NewRESTClient(resourceStore)

	cc := &ClusterCapacity{
		resourceStore: resourceStore,
		strategy:      strategy.NewPredictiveStrategy(resourceStore),
		kubeclient:    clientset.New(restClient),
		simulatedPod:  simulatedPod,
		simulated:     0,
	}

	resourceStore.RegisterEventHandler(ccapi.Pods, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPodWatchEvent(watch.Added, obj.(*api.Pod))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPodWatchEvent(watch.Modified, newObj.(*api.Pod))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPodWatchEvent(watch.Deleted, obj.(*api.Pod))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.Services, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Added, obj.(*api.Service))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Modified, newObj.(*api.Service))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Deleted, obj.(*api.Service))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.ReplicationControllers, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Added, obj.(*api.ReplicationController))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Modified, newObj.(*api.ReplicationController))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Deleted, obj.(*api.ReplicationController))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.PersistentVolumes, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Added, obj.(*api.PersistentVolume))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Modified, newObj.(*api.PersistentVolume))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Deleted, obj.(*api.PersistentVolume))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.Nodes, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Added, obj.(*api.Node))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Modified, newObj.(*api.Node))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Deleted, obj.(*api.Node))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.PersistentVolumeClaims, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Added, obj.(*api.PersistentVolumeClaim))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Modified, newObj.(*api.PersistentVolumeClaim))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Deleted, obj.(*api.PersistentVolumeClaim))
		},
	})

	cc.schedulers = make(map[string]*scheduler.Scheduler)
	cc.schedulerConfigs = make(map[string]*scheduler.Config)

	// read the default scheduler name from configuration
	config, err := cc.createSchedulerConfig(s)
	if err != nil {
		return nil, fmt.Errorf("Unable to create cluster capacity analyzer: %v", err)
	}

	cc.schedulers[s.SchedulerName] = scheduler.New(config)
	cc.schedulerConfigs[s.SchedulerName] = config
	cc.defaultScheduler = s.SchedulerName

	cc.stop = make(chan struct{})

	// Create empty event recorder, broadcaster, metrics and everything up to binder.
	// Binder is redirected to cluster capacity's counter.

	return cc, nil
}
<commit_msg>close all schedulers when there is no pod to schedule<commit_after>package emulator

import (
	"fmt"
	"reflect"
	"time"

	ccapi "github.com/ingvagabund/cluster-capacity/pkg/api"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/restclient"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/store"
	"github.com/ingvagabund/cluster-capacity/pkg/client/emulator/strategy"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/client/cache"
	clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/watch"
	soptions "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options"
	"k8s.io/kubernetes/plugin/pkg/scheduler"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
	"k8s.io/kubernetes/plugin/pkg/scheduler/factory"

	"io/ioutil"
	"os"

	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/runtime"
	// register algorithm providers
	_ "k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
)

type ClusterCapacity struct {
	// caches modified by emulation strategy
	resourceStore store.ResourceStore

	// emulation strategy
	strategy strategy.Strategy

	// fake kube client
	kubeclient clientset.Interface

	// schedulers
	schedulers       map[string]*scheduler.Scheduler
	schedulerConfigs map[string]*scheduler.Config
	defaultScheduler string

	// pod to schedule
	simulatedPod *api.Pod
	maxSimulated int
	simulated    int
	status       Status

	// stop the analysis
	stop chan struct{}
}

// capture all scheduled pods with reason why the analysis could not continue
type Status struct {
	Pods       []*api.Pod
	StopReason string
}

func (c *ClusterCapacity) Status() Status {
	return c.status
}

func (c *ClusterCapacity) SyncWithClient(client cache.Getter) error {

	for _, resource := range c.resourceStore.Resources() {
		listWatcher := cache.NewListWatchFromClient(client, resource, api.NamespaceAll, fields.ParseSelectorOrDie(""))

		options := api.ListOptions{ResourceVersion: "0"}
		list, err := listWatcher.List(options)
		if err != nil {
			return fmt.Errorf("Failed to list objects: %v", err)
		}

		listMetaInterface, err := meta.ListAccessor(list)
		if err != nil {
			return fmt.Errorf("Unable to understand list result %#v: %v", list, err)
		}
		resourceVersion := listMetaInterface.GetResourceVersion()

		items, err := meta.ExtractList(list)
		if err != nil {
			return fmt.Errorf("Unable to understand list result %#v (%v)", list, err)
		}
		found := make([]interface{}, 0, len(items))
		for _, item := range items {
			found = append(found, item)
		}
		err = c.resourceStore.Replace(resource, found, resourceVersion)
		if err != nil {
			return fmt.Errorf("Unable to store %s list result: %v", resource, err)
		}
	}
	return nil
}

func (c *ClusterCapacity) SyncWithStore(resourceStore store.ResourceStore) {
	for _, resource := range resourceStore.Resources() {
		err := c.resourceStore.Replace(resource, resourceStore.List(resource), "0")
		if err != nil {
			fmt.Printf("Resource replace error: %v\n", err)
		}
	}
}

func (c *ClusterCapacity) Bind(binding *api.Binding, schedulerName string) error {
	// pod name: binding.Name
	// node name: binding.Target.Name
	// fmt.Printf("\nPod: %v, node: %v, scheduler: %v\n", binding.Name, binding.Target.Name, schedulerName)

	// run the pod through strategy
	key := &api.Pod{
		ObjectMeta: api.ObjectMeta{Name: binding.Name, Namespace: binding.Namespace},
	}
	pod, exists, err := c.resourceStore.Get(ccapi.Pods, runtime.Object(key))
	if err != nil {
		return fmt.Errorf("Unable to bind: %v", err)
	}
	if !exists {
		return fmt.Errorf("Unable to bind, pod %v not found", pod)
	}
	updatedPod := *pod.(*api.Pod)
	updatedPod.Spec.NodeName = binding.Target.Name
	// fmt.Printf("Pod binding: %v\n", updatedPod)

	// TODO(jchaloup): rename Add to Update as this actually updates the scheduled pod
	if err := c.strategy.Add(&updatedPod); err != nil {
		return fmt.Errorf("Unable to recompute new cluster state: %v", err)
	}

	c.status.Pods = append(c.status.Pods, &updatedPod)
	go func() {
		<-c.schedulerConfigs[schedulerName].Recorder.(*record.FakeRecorder).Events
		//fmt.Printf("Scheduling event: %v\n", event)
	}()
	// all good, create another pod
	if err := c.nextPod(); err != nil {
		return fmt.Errorf("Unable to create next pod to schedule: %v", err)
	}
	return nil
}

func (c *ClusterCapacity) Close() {
	for _, name := range c.schedulerConfigs {
		close(name.StopEverything)
	}
}

func (c *ClusterCapacity) Update(pod *api.Pod, podCondition *api.PodCondition, schedulerName string) error {
	// once the api.PodCondition
	podUnschedulableCond := &api.PodCondition{
		Type:   api.PodScheduled,
		Status: api.ConditionFalse,
		Reason: "Unschedulable",
	}

	stop := reflect.DeepEqual(podCondition, podUnschedulableCond)

	//fmt.Printf("pod condition: %v\n", podCondition)
	go func() {
		event := <-c.schedulerConfigs[schedulerName].Recorder.(*record.FakeRecorder).Events
		// end the simulation
		// TODO(jchaloup): this needs to be reworked in a case of multiple schedulers
		// The stop condition is different for a case of multi-pods
		if stop {
			c.status.StopReason = event
			c.Close()
			c.stop <- struct{}{}
		}
	}()

	return nil
}

func (c *ClusterCapacity) nextPod() error {
	pod := *c.simulatedPod
	// use simulated pod name with an index to construct the name
	pod.ObjectMeta.Name = fmt.Sprintf("%v-%v", c.simulatedPod.Name, c.simulated)
	c.simulated++
	return c.resourceStore.Add(ccapi.Pods, runtime.Object(&pod))
}

func (c *ClusterCapacity) Run() error {
	// TODO(jchaloup): remove all pods that are not scheduled yet

	for _, scheduler := range c.schedulers {
		scheduler.Run()
	}
	// wait some time before at least nodes are populated
	// TODO(jchaloup); find a better way how to do this or at least increase it to <100ms
	time.Sleep(100 * time.Millisecond)
	// create the first simulated pod
	err := c.nextPod()
	if err != nil {
		c.Close()
		close(c.stop)
		return fmt.Errorf("Unable to create next pod to schedule: %v", err)
	}

	<-c.stop
	close(c.stop)

	return nil
}

type localBinderPodConditionUpdater struct {
	SchedulerName string
	C             *ClusterCapacity
}

func (b *localBinderPodConditionUpdater) Bind(binding *api.Binding) error {
	return b.C.Bind(binding, b.SchedulerName)
}

func (b *localBinderPodConditionUpdater) Update(pod *api.Pod, podCondition *api.PodCondition) error {
	return b.C.Update(pod, podCondition, b.SchedulerName)
}

func (c *ClusterCapacity) createSchedulerConfig(s *soptions.SchedulerServer) (*scheduler.Config, error) {
	configFactory := factory.NewConfigFactory(c.kubeclient, s.SchedulerName, s.HardPodAffinitySymmetricWeight, s.FailureDomains)
	config, err := createConfig(s, configFactory)

	if err != nil {
		return nil, fmt.Errorf("Failed to create scheduler configuration: %v", err)
	}

	// Collect scheduler succesfully/failed scheduled pod
	config.Recorder = record.NewFakeRecorder(10)
	// Replace the binder with simulator pod counter
	lbpcu := &localBinderPodConditionUpdater{
		SchedulerName: s.SchedulerName,
		C:             c,
	}
	config.Binder = lbpcu
	config.PodConditionUpdater = lbpcu
	return config, nil
}

func (c *ClusterCapacity) AddScheduler(s *soptions.SchedulerServer) error {
	config, err := c.createSchedulerConfig(s)
	if err != nil {
		return err
	}

	c.schedulers[s.SchedulerName] = scheduler.New(config)
	c.schedulerConfigs[s.SchedulerName] = config
	return nil
}

func createConfig(s *soptions.SchedulerServer, configFactory *factory.ConfigFactory) (*scheduler.Config, error) {
	if _, err := os.Stat(s.PolicyConfigFile); err == nil {
		var (
			policy     schedulerapi.Policy
			configData []byte
		)
		configData, err := ioutil.ReadFile(s.PolicyConfigFile)
		if err != nil {
			return nil, fmt.Errorf("unable to read policy config: %v", err)
		}
		if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
			return nil, fmt.Errorf("invalid configuration: %v", err)
		}
		return configFactory.CreateFromConfig(policy)
	}

	// if the config file isn't provided, use the specified (or default) provider
	return configFactory.CreateFromProvider(s.AlgorithmProvider)
}

// Create new cluster capacity analysis
// The analysis is completely independent of apiserver so no need
// for kubeconfig nor for apiserver url
func New(s *soptions.SchedulerServer, simulatedPod *api.Pod) (*ClusterCapacity, error) {
	resourceStore := store.NewResourceStore()
	restClient := restclient.NewRESTClient(resourceStore)

	cc := &ClusterCapacity{
		resourceStore: resourceStore,
		strategy:      strategy.NewPredictiveStrategy(resourceStore),
		kubeclient:    clientset.New(restClient),
		simulatedPod:  simulatedPod,
		simulated:     0,
	}

	resourceStore.RegisterEventHandler(ccapi.Pods, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPodWatchEvent(watch.Added, obj.(*api.Pod))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPodWatchEvent(watch.Modified, newObj.(*api.Pod))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPodWatchEvent(watch.Deleted, obj.(*api.Pod))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.Services, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Added, obj.(*api.Service))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Modified, newObj.(*api.Service))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitServiceWatchEvent(watch.Deleted, obj.(*api.Service))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.ReplicationControllers, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Added, obj.(*api.ReplicationController))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Modified, newObj.(*api.ReplicationController))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitReplicationControllerWatchEvent(watch.Deleted, obj.(*api.ReplicationController))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.PersistentVolumes, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Added, obj.(*api.PersistentVolume))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Modified, newObj.(*api.PersistentVolume))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeWatchEvent(watch.Deleted, obj.(*api.PersistentVolume))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.Nodes, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Added, obj.(*api.Node))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Modified, newObj.(*api.Node))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitNodeWatchEvent(watch.Deleted, obj.(*api.Node))
		},
	})

	resourceStore.RegisterEventHandler(ccapi.PersistentVolumeClaims, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Added, obj.(*api.PersistentVolumeClaim))
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Modified, newObj.(*api.PersistentVolumeClaim))
		},
		DeleteFunc: func(obj interface{}) {
			restClient.EmitPersistentVolumeClaimWatchEvent(watch.Deleted, obj.(*api.PersistentVolumeClaim))
		},
	})

	cc.schedulers = make(map[string]*scheduler.Scheduler)
	cc.schedulerConfigs = make(map[string]*scheduler.Config)

	// read the default scheduler name from configuration
	config, err := cc.createSchedulerConfig(s)
	if err != nil {
		return nil, fmt.Errorf("Unable to create cluster capacity analyzer: %v", err)
	}

	cc.schedulers[s.SchedulerName] = scheduler.New(config)
	cc.schedulerConfigs[s.SchedulerName] = config
	cc.defaultScheduler = s.SchedulerName

	cc.stop = make(chan struct{})

	// Create empty event recorder, broadcaster, metrics and everything up to binder.
	// Binder is redirected to cluster capacity's counter.

	return cc, nil
}
<|endoftext|>


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

package conn

import (
	"fmt"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/time"
	sys_time "time"
)

// A connection to the SimpleDB service.
type Conn interface {
	// Send the supplied request to the service, taking care of adding
	// appropriate authentication info.
	SendRequest(req Request) (resp []byte, err error)
}

// Create a connection using the supplied dependencies.
func NewConn(
	key aws.AccessKey,
	httpConn HttpConn,
	signer Signer,
	clock time.Clock) (Conn, error) {
	return &conn{key, httpConn, signer, clock}, nil
}

type conn struct {
	key aws.AccessKey
	httpConn HttpConn
	signer Signer
	clock time.Clock
}

func (c *conn) SendRequest(req Request) (resp []byte, err error) {
	// Make a copy of the request that we can modify below.
	originalReq := req
	req = Request{}
	for key, val := range originalReq {
		req[key] = val
	}

	// Set authentication info.
	req["AWSAccessKeyId"] = c.key.Id
	req["Timestamp"] = c.clock.Now().Format(sys_time.RFC3339)
	req["SignatureVersion"] = "2"
	req["SignatureMethod"] = "HmacSHA1"

	// Sign the request.
	if err = c.signer.SignRequest(req); err != nil {
		err = fmt.Errorf("SignRequest: %v", err)
		return
	}

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

package conn

import (
	"fmt"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/time"
)

const (
	iso8601Format = "2006-01-02T15:04:05Z"
)

// A connection to the SimpleDB service.
type Conn interface {
	// Send the supplied request to the service, taking care of adding
	// appropriate authentication info.
	SendRequest(req Request) (resp []byte, err error)
}

// Create a connection using the supplied dependencies.
func NewConn(
	key aws.AccessKey,
	httpConn HttpConn,
	signer Signer,
	clock time.Clock) (Conn, error) {
	return &conn{key, httpConn, signer, clock}, nil
}

type conn struct {
	key aws.AccessKey
	httpConn HttpConn
	signer Signer
	clock time.Clock
}

func (c *conn) SendRequest(req Request) (resp []byte, err error) {
	// Make a copy of the request that we can modify below.
	originalReq := req
	req = Request{}
	for key, val := range originalReq {
		req[key] = val
	}

	// Set authentication info.
	req["AWSAccessKeyId"] = c.key.Id
	req["Timestamp"] = c.clock.Now().Format(iso8601Format)
	req["SignatureVersion"] = "2"
	req["SignatureMethod"] = "HmacSHA1"

	// Sign the request.
	if err = c.signer.SignRequest(req); err != nil {
		err = fmt.Errorf("SignRequest: %v", err)
		return
	}

	return nil, fmt.Errorf("TODO")
}
<|endoftext|>


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

package redirect

import (
	"net/http"
	"net/url"
	"strings"

	"github.com/google/exposure-notifications-verification-server/pkg/cache"
	"github.com/google/exposure-notifications-verification-server/pkg/controller"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
)

func (c *Controller) HandleIndex() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		// Strip of the port if that was passed along in the host header.
		baseHost := strings.ToLower(r.Host)
		if i := strings.Index(baseHost, ":"); i > 0 {
			baseHost = baseHost[0:i]
		}

		var hostRegion string = ""
		for hostname, region := range c.hostnameToRegion {
			if hostname == baseHost {
				hostRegion = region
				break
			}
		}
		realm, err := c.db.FindRealmByRegion(hostRegion)
		if err != nil {
			if database.IsNotFound(err) {
				controller.NotFound(w, r, c.h)
				return
			}

			controller.InternalError(w, r, c.h, err)
			return
		}

		// Get App Store Data.
		var appStoreData AppStoreData
		cacheKey := &cache.Key{
			Namespace: "apps:appstoredata:by_region",
			Key:       hostRegion,
		}
		if err := c.cacher.Fetch(ctx, cacheKey, &appStoreData, c.config.AppCacheTTL, func() (interface{}, error) {
			c.logger.Debug("fetching new app store data")
			return c.getAppStoreData(realm.ID)
		}); err != nil {
			controller.InternalError(w, r, c.h, err)
			return
		}

		if sendto, success := decideRedirect(hostRegion, r.UserAgent(), *r.URL, appStoreData); success {
			http.Redirect(w, r, sendto, http.StatusSeeOther)
			return
		}

		c.logger.Warnw("unknown host", "host", r.Host)
		m := controller.TemplateMapFromContext(ctx)
		m["requestURI"] = (&url.URL{
			Scheme: "https",
			Host:   r.Host,
			Path:   strings.TrimPrefix(r.URL.RequestURI(), "/"),
		}).String()
		c.h.RenderHTMLStatus(w, http.StatusNotFound, "404", m)
	})
}

// isAndroid determines if a User-Agent is a Android device.
func isAndroid(userAgent string) bool {
	return strings.Contains(strings.ToLower(userAgent), "android")
}

// isIOS determines if a User-Agent is an iOS EN device.
func isIOS(userAgent string) bool {
	return strings.Contains(strings.ToLower(userAgent), "iphone")
}

// decideRedirect selects where to redirect based on several signals.
func decideRedirect(region, userAgent string, url url.URL,
	appStoreData AppStoreData) (string, bool) {
	// Canonicalize path as lowercase.
	path := strings.ToLower(url.Path)

	// Check for browser type.
	onAndroid := isAndroid(userAgent)
	onIOS := isIOS(userAgent)

	// On Android redirect to Play Store if App Link doesn't trigger
	// and an a link is set up.
	if onAndroid && appStoreData.AndroidURL != "" && appStoreData.AndroidAppID != "" {
		return buildIntentURL(path, url.Query(), region, appStoreData.AndroidAppID, appStoreData.AndroidURL), true
	}

	// On iOS redirect to App Store if App Link doesn't trigger
	// and an a link is set up.
	if onIOS && appStoreData.IOSURL != "" {
		return appStoreData.IOSURL, true
	}

	if onIOS || onAndroid {
		return buildEnsURL(path, url.Query(), region), true
	}

	return "", false
}

// buildEnsURL returns the ens:// URL for the given path, query, and region.
func buildEnsURL(path string, query url.Values, region string) string {
	u := &url.URL{
		Scheme: "ens",
		Path:   strings.TrimPrefix(path, "/"),
	}
	u.RawQuery = query.Encode()
	q := u.Query()
	q.Set("r", region)
	u.RawQuery = q.Encode()

	return u.String()
}

// buildIntentURL returns the ens:// URL with fallback
// for the given path, query, and region.
func buildIntentURL(path string, query url.Values, region, appID, fallback string) string {
	u := &url.URL{
		Scheme: "intent",
		Path:   strings.TrimPrefix(path, "/"),
	}
	u.RawQuery = query.Encode()
	q := u.Query()
	q.Set("r", region)
	u.RawQuery = q.Encode()

	suffix := "#Intent"
	suffix += ";scheme=ens"
	suffix += ";package=" + appID
	suffix += ";action=android.intent.action.VIEW"
	suffix += ";category=android.intent.category.BROWSABLE"
	suffix += ";S.browser_fallback_url=" + url.QueryEscape(fallback)
	suffix += ";end"

	return u.String() + suffix
}
<commit_msg>change log message when redirect doesn't redirect (#876)<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package redirect

import (
	"net/http"
	"net/url"
	"strings"

	"github.com/google/exposure-notifications-verification-server/pkg/cache"
	"github.com/google/exposure-notifications-verification-server/pkg/controller"
	"github.com/google/exposure-notifications-verification-server/pkg/database"
)

func (c *Controller) HandleIndex() http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		// Strip of the port if that was passed along in the host header.
		baseHost := strings.ToLower(r.Host)
		if i := strings.Index(baseHost, ":"); i > 0 {
			baseHost = baseHost[0:i]
		}

		var hostRegion string = ""
		for hostname, region := range c.hostnameToRegion {
			if hostname == baseHost {
				hostRegion = region
				break
			}
		}
		realm, err := c.db.FindRealmByRegion(hostRegion)
		if err != nil {
			if database.IsNotFound(err) {
				controller.NotFound(w, r, c.h)
				return
			}

			controller.InternalError(w, r, c.h, err)
			return
		}

		// Get App Store Data.
		var appStoreData AppStoreData
		cacheKey := &cache.Key{
			Namespace: "apps:appstoredata:by_region",
			Key:       hostRegion,
		}
		if err := c.cacher.Fetch(ctx, cacheKey, &appStoreData, c.config.AppCacheTTL, func() (interface{}, error) {
			c.logger.Debug("fetching new app store data")
			return c.getAppStoreData(realm.ID)
		}); err != nil {
			controller.InternalError(w, r, c.h, err)
			return
		}

		if sendto, success := decideRedirect(hostRegion, r.UserAgent(), *r.URL, appStoreData); success {
			http.Redirect(w, r, sendto, http.StatusSeeOther)
			return
		}

		c.logger.Warnw("not a mobile user agent", "host", r.Host, "userAgent", r.UserAgent())
		m := controller.TemplateMapFromContext(ctx)
		m["requestURI"] = (&url.URL{
			Scheme: "https",
			Host:   r.Host,
			Path:   strings.TrimPrefix(r.URL.RequestURI(), "/"),
		}).String()
		c.h.RenderHTMLStatus(w, http.StatusNotFound, "404", m)
	})
}

// isAndroid determines if a User-Agent is a Android device.
func isAndroid(userAgent string) bool {
	return strings.Contains(strings.ToLower(userAgent), "android")
}

// isIOS determines if a User-Agent is an iOS EN device.
func isIOS(userAgent string) bool {
	return strings.Contains(strings.ToLower(userAgent), "iphone")
}

// decideRedirect selects where to redirect based on several signals.
func decideRedirect(region, userAgent string, url url.URL, appStoreData AppStoreData) (string, bool) {
	// Canonicalize path as lowercase.
	path := strings.ToLower(url.Path)

	// Check for browser type.
	onAndroid := isAndroid(userAgent)
	onIOS := isIOS(userAgent)

	// On Android redirect to Play Store if App Link doesn't trigger
	// and an a link is set up.
	if onAndroid && appStoreData.AndroidURL != "" && appStoreData.AndroidAppID != "" {
		return buildIntentURL(path, url.Query(), region, appStoreData.AndroidAppID, appStoreData.AndroidURL), true
	}

	// On iOS redirect to App Store if App Link doesn't trigger
	// and an a link is set up.
	if onIOS && appStoreData.IOSURL != "" {
		return appStoreData.IOSURL, true
	}

	if onIOS || onAndroid {
		return buildEnsURL(path, url.Query(), region), true
	}

	return "", false
}

// buildEnsURL returns the ens:// URL for the given path, query, and region.
func buildEnsURL(path string, query url.Values, region string) string {
	u := &url.URL{
		Scheme: "ens",
		Path:   strings.TrimPrefix(path, "/"),
	}
	u.RawQuery = query.Encode()
	q := u.Query()
	q.Set("r", region)
	u.RawQuery = q.Encode()

	return u.String()
}

// buildIntentURL returns the ens:// URL with fallback
// for the given path, query, and region.
func buildIntentURL(path string, query url.Values, region, appID, fallback string) string {
	u := &url.URL{
		Scheme: "intent",
		Path:   strings.TrimPrefix(path, "/"),
	}
	u.RawQuery = query.Encode()
	q := u.Query()
	q.Set("r", region)
	u.RawQuery = q.Encode()

	suffix := "#Intent"
	suffix += ";scheme=ens"
	suffix += ";package=" + appID
	suffix += ";action=android.intent.action.VIEW"
	suffix += ";category=android.intent.category.BROWSABLE"
	suffix += ";S.browser_fallback_url=" + url.QueryEscape(fallback)
	suffix += ";end"

	return u.String() + suffix
}
<|endoftext|>


<commit_before>package eval_test

import (
	"testing"

	. "src.elv.sh/pkg/eval"

	. "src.elv.sh/pkg/eval/evaltest"
	"src.elv.sh/pkg/eval/vals"
)

func TestRunParallel(t *testing.T) {
	Test(t,
		That(`run-parallel { put lorem } { echo ipsum }`).
			Puts("lorem").Prints("ipsum\n"),
	)
}

func TestEach(t *testing.T) {
	Test(t,
		That(`put 1 233 | each $put~`).Puts("1", "233"),
		That(`echo "1\n233" | each $put~`).Puts("1", "233"),
		That(`echo "1\r\n233" | each $put~`).Puts("1", "233"),
		That(`each $put~ [1 233]`).Puts("1", "233"),
		That(`range 10 | each [x]{ if (== $x 4) { break }; put $x }`).
			Puts(0, 1, 2, 3),
		That(`range 10 | each [x]{ if (== $x 4) { fail haha }; put $x }`).
			Puts(0, 1, 2, 3).Throws(AnyError),
		// TODO(xiaq): Test that "each" does not close the stdin.
	)
}

func TestPeach(t *testing.T) {
	// Testing the `peach` builtin is a challenge since, by definition, the order of execution is
	// undefined.
	Test(t,
		// Verify the output has the expected values when sorted.
		That(`range 5 | peach [x]{ * 2 $x } | order`).Puts(0, 2, 4, 6, 8),
		// Verify that successive runs produce the output in different order. This test can
		// theoretically suffer false positives but the vast majority of the time this will produce
		// the expected output in the first iteration. The probability it will produce the same
		// order of output in 100 iterations is effectively zero.
		That(`
			fn f { range 100 | peach $put~ | put [(all)] }
			var x = (f)
			for _ [(range 100)] {
				var y = (f)
				if (not-eq $x $y) {
					put $true
					break
				}
			}
		`).Puts(true),
		// Verify that exceptions are propagated.
		That(`peach [x]{ fail $x } [a]`).
			Throws(FailError{"a"}, "fail $x ", "peach [x]{ fail $x } [a]"),
		// Verify that `break` works by terminating the `peach` before the entire sequence is
		// consumed.
		That(`
			var tot = 0
			range 1 101 |
				peach [x]{ if (== 50 $x) { break } else { put $x } } |
				< (+ (all)) (+ (range 1 101))
		`).Puts(true),
	)
}

func TestFail(t *testing.T) {
	Test(t,
		That("fail haha").Throws(FailError{"haha"}, "fail haha"),
		That("fn f { fail haha }", "fail ?(f)").Throws(
			FailError{"haha"}, "fail haha ", "f"),
		That("fail []").Throws(
			FailError{vals.EmptyList}, "fail []"),
		That("put ?(fail 1)[reason][type]").Puts("fail"),
		That("put ?(fail 1)[reason][content]").Puts("1"),
	)
}

func TestReturn(t *testing.T) {
	Test(t,
		That("return").Throws(Return),
		// Use of return inside fn is tested in TestFn
	)
}
<commit_msg>Reduce the flakiness of TestPeach with some random jitter.<commit_after>package eval_test

import (
	"testing"

	. "src.elv.sh/pkg/eval"

	. "src.elv.sh/pkg/eval/evaltest"
	"src.elv.sh/pkg/eval/vals"
)

func TestRunParallel(t *testing.T) {
	Test(t,
		That(`run-parallel { put lorem } { echo ipsum }`).
			Puts("lorem").Prints("ipsum\n"),
	)
}

func TestEach(t *testing.T) {
	Test(t,
		That(`put 1 233 | each $put~`).Puts("1", "233"),
		That(`echo "1\n233" | each $put~`).Puts("1", "233"),
		That(`echo "1\r\n233" | each $put~`).Puts("1", "233"),
		That(`each $put~ [1 233]`).Puts("1", "233"),
		That(`range 10 | each [x]{ if (== $x 4) { break }; put $x }`).
			Puts(0, 1, 2, 3),
		That(`range 10 | each [x]{ if (== $x 4) { fail haha }; put $x }`).
			Puts(0, 1, 2, 3).Throws(AnyError),
		// TODO(xiaq): Test that "each" does not close the stdin.
	)
}

func TestPeach(t *testing.T) {
	// Testing the `peach` builtin is a challenge since, by definition, the order of execution is
	// undefined.
	Test(t,
		// Verify the output has the expected values when sorted.
		That(`range 5 | peach [x]{ * 2 $x } | order`).Puts(0, 2, 4, 6, 8),
		// Test that the order of output does not necessarily match the order of
		// input.
		//
		// Most of the time this effect can be observed without the need of any
		// jitter, but if the system only has one CPU core to execute goroutines
		// (which can happen even when GOMAXPROCS > 1), the scheduling of
		// goroutines can become deterministic. The random jitter fixes that by
		// forcing goroutines to yield the thread and allow other goroutines to
		// execute.
		That(`
			var @in = (range 100)
			while $true {
				var @out = (all $in | peach [x]{ sleep (* (rand) 0.01); put $x })
				if (not-eq $in $out) {
					put $true
					break
				}
			}
		`).Puts(true),
		// Verify that exceptions are propagated.
		That(`peach [x]{ fail $x } [a]`).
			Throws(FailError{"a"}, "fail $x ", "peach [x]{ fail $x } [a]"),
		// Verify that `break` works by terminating the `peach` before the entire sequence is
		// consumed.
		That(`
			var tot = 0
			range 1 101 |
				peach [x]{ if (== 50 $x) { break } else { put $x } } |
				< (+ (all)) (+ (range 1 101))
		`).Puts(true),
	)
}

func TestFail(t *testing.T) {
	Test(t,
		That("fail haha").Throws(FailError{"haha"}, "fail haha"),
		That("fn f { fail haha }", "fail ?(f)").Throws(
			FailError{"haha"}, "fail haha ", "f"),
		That("fail []").Throws(
			FailError{vals.EmptyList}, "fail []"),
		That("put ?(fail 1)[reason][type]").Puts("fail"),
		That("put ?(fail 1)[reason][content]").Puts("1"),
	)
}

func TestReturn(t *testing.T) {
	Test(t,
		That("return").Throws(Return),
		// Use of return inside fn is tested in TestFn
	)
}
<|endoftext|>


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

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resource

import (
	"github.com/golang/glog"

	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/watch"
)

// Selector is a Visitor for resources that match a label selector.
type Selector struct {
	Client    RESTClient
	Mapping   *meta.RESTMapping
	Namespace string
	Selector  labels.Selector
}

// NewSelector creates a resource selector which hides details of getting items by their label selector.
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector labels.Selector) *Selector {
	return &Selector{
		Client:    client,
		Mapping:   mapping,
		Namespace: namespace,
		Selector:  selector,
	}
}

// Visit implements Visitor
func (r *Selector) Visit(fn VisitorFunc) error {
	list, err := NewHelper(r.Client, r.Mapping).List(r.Namespace, r.ResourceMapping().APIVersion, r.Selector)
	if err != nil {
		if errors.IsBadRequest(err) || errors.IsNotFound(err) {
			if r.Selector.Empty() {
				glog.V(2).Infof("Unable to list %q: %v", r.Mapping.Resource, err)
			} else {
				glog.V(2).Infof("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, err)
			}
			return nil
		}
		return err
	}
	accessor := r.Mapping.MetadataAccessor
	resourceVersion, _ := accessor.ResourceVersion(list)
	info := &Info{
		Client:    r.Client,
		Mapping:   r.Mapping,
		Namespace: r.Namespace,

		Object:          list,
		ResourceVersion: resourceVersion,
	}
	return fn(info)
}

func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) {
	return NewHelper(r.Client, r.Mapping).Watch(r.Namespace, resourceVersion, r.ResourceMapping().APIVersion, r.Selector, fields.Everything())
}

// ResourceMapping returns the mapping for this resource and implements ResourceMapping
func (r *Selector) ResourceMapping() *meta.RESTMapping {
	return r.Mapping
}
<commit_msg>don't swallow bad request errors<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resource

import (
	"fmt"

	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/watch"
)

// Selector is a Visitor for resources that match a label selector.
type Selector struct {
	Client    RESTClient
	Mapping   *meta.RESTMapping
	Namespace string
	Selector  labels.Selector
}

// NewSelector creates a resource selector which hides details of getting items by their label selector.
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector labels.Selector) *Selector {
	return &Selector{
		Client:    client,
		Mapping:   mapping,
		Namespace: namespace,
		Selector:  selector,
	}
}

// Visit implements Visitor
func (r *Selector) Visit(fn VisitorFunc) error {
	list, err := NewHelper(r.Client, r.Mapping).List(r.Namespace, r.ResourceMapping().APIVersion, r.Selector)
	if err != nil {
		if errors.IsBadRequest(err) || errors.IsNotFound(err) {
			if r.Selector.Empty() {
				return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err)
			} else {
				return fmt.Errorf("Unable to find %q that match the selector %q: %v", r.Mapping.Resource, r.Selector, err)
			}
		}
		return err
	}
	accessor := r.Mapping.MetadataAccessor
	resourceVersion, _ := accessor.ResourceVersion(list)
	info := &Info{
		Client:    r.Client,
		Mapping:   r.Mapping,
		Namespace: r.Namespace,

		Object:          list,
		ResourceVersion: resourceVersion,
	}
	return fn(info)
}

func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) {
	return NewHelper(r.Client, r.Mapping).Watch(r.Namespace, resourceVersion, r.ResourceMapping().APIVersion, r.Selector, fields.Everything())
}

// ResourceMapping returns the mapping for this resource and implements ResourceMapping
func (r *Selector) ResourceMapping() *meta.RESTMapping {
	return r.Mapping
}
<|endoftext|>