<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsVpcPeeringConnection() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVPCPeeringCreate,
		Read:   resourceAwsVPCPeeringRead,
		Update: resourceAwsVPCPeeringUpdate,
		Delete: resourceAwsVPCPeeringDelete,

		Schema: map[string]*schema.Schema{
			"peer_owner_id": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("AWS_ACCOUNT_ID", nil),
			},
			"peer_vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"auto_accept": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"accept_status": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	// Create the vpc peering connection
	createOpts := &ec2.CreateVPCPeeringConnectionInput{
		PeerOwnerID: aws.String(d.Get("peer_owner_id").(string)),
		PeerVPCID:   aws.String(d.Get("peer_vpc_id").(string)),
		VPCID:       aws.String(d.Get("vpc_id").(string)),
	}
	log.Printf("[DEBUG] VPCPeeringCreate create config: %#v", createOpts)
	resp, err := conn.CreateVPCPeeringConnection(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating vpc peering connection: %s", err)
	}

	// Get the ID and store it
	rt := resp.VPCPeeringConnection
	d.SetId(*rt.VPCPeeringConnectionID)
	log.Printf("[INFO] VPC Peering Connection ID: %s", d.Id())

	// Wait for the vpc peering connection to become available
	log.Printf(
		"[DEBUG] Waiting for vpc peering connection (%s) to become available",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "pending-acceptance",
		Refresh: resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id()),
		Timeout: 1 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for vpc peering (%s) to become available: %s",
			d.Id(), err)
	}

	return resourceAwsVPCPeeringUpdate(d, meta)
}

func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())()
	if err != nil {
		return err
	}
	if pcRaw == nil {
		d.SetId("")
		return nil
	}

	pc := pcRaw.(*ec2.VPCPeeringConnection)

	d.Set("accept_status", *pc.Status.Code)
	d.Set("peer_owner_id", pc.AccepterVPCInfo.OwnerID)
	d.Set("peer_vpc_id", pc.AccepterVPCInfo.VPCID)
	d.Set("vpc_id", pc.RequesterVPCInfo.VPCID)
	d.Set("tags", tagsToMap(pc.Tags))

	return nil
}

func resourceVPCPeeringConnectionAccept(conn *ec2.EC2, id string) (string, error) {

	log.Printf("[INFO] Accept VPC Peering Connection with id: %s", id)

	req := &ec2.AcceptVPCPeeringConnectionInput{
		VPCPeeringConnectionID: aws.String(id),
	}

	resp, err := conn.AcceptVPCPeeringConnection(req)
	pc := resp.VPCPeeringConnection
	return *pc.Status.Code, err
}

func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	if err := setTags(conn, d); err != nil {
		return err
	} else {
		d.SetPartial("tags")
	}

	if _, ok := d.GetOk("auto_accept"); ok {

		pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())()

		if err != nil {
			return err
		}
		if pcRaw == nil {
			d.SetId("")
			return nil
		}
		pc := pcRaw.(*ec2.VPCPeeringConnection)

		if *pc.Status.Code == "pending-acceptance" {

			status, err := resourceVPCPeeringConnectionAccept(conn, d.Id())

			log.Printf(
				"[DEBUG] VPC Peering connection accept status %s",
				status)
			if err != nil {
				return err
			}
		}
	}

	return resourceAwsVPCPeeringRead(d, meta)
}

func resourceAwsVPCPeeringDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	_, err := conn.DeleteVPCPeeringConnection(
		&ec2.DeleteVPCPeeringConnectionInput{
			VPCPeeringConnectionID: aws.String(d.Id()),
		})
	return err
}

// resourceAwsVPCPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a VPCPeeringConnection.
func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {

		resp, err := conn.DescribeVPCPeeringConnections(&ec2.DescribeVPCPeeringConnectionsInput{
			VPCPeeringConnectionIDs: []*string{aws.String(id)},
		})
		if err != nil {
			if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcPeeringConnectionID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on VPCPeeringConnectionStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		pc := resp.VPCPeeringConnections[0]

		return pc, *pc.Status.Code, nil
	}
}
<commit_msg>providers/aws: vpc peering failed == deleted [GH-2322]<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsVpcPeeringConnection() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsVPCPeeringCreate,
		Read:   resourceAwsVPCPeeringRead,
		Update: resourceAwsVPCPeeringUpdate,
		Delete: resourceAwsVPCPeeringDelete,

		Schema: map[string]*schema.Schema{
			"peer_owner_id": &schema.Schema{
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				DefaultFunc: schema.EnvDefaultFunc("AWS_ACCOUNT_ID", nil),
			},
			"peer_vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"vpc_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"auto_accept": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"accept_status": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsVPCPeeringCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	// Create the vpc peering connection
	createOpts := &ec2.CreateVPCPeeringConnectionInput{
		PeerOwnerID: aws.String(d.Get("peer_owner_id").(string)),
		PeerVPCID:   aws.String(d.Get("peer_vpc_id").(string)),
		VPCID:       aws.String(d.Get("vpc_id").(string)),
	}
	log.Printf("[DEBUG] VPCPeeringCreate create config: %#v", createOpts)
	resp, err := conn.CreateVPCPeeringConnection(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating vpc peering connection: %s", err)
	}

	// Get the ID and store it
	rt := resp.VPCPeeringConnection
	d.SetId(*rt.VPCPeeringConnectionID)
	log.Printf("[INFO] VPC Peering Connection ID: %s", d.Id())

	// Wait for the vpc peering connection to become available
	log.Printf(
		"[DEBUG] Waiting for vpc peering connection (%s) to become available",
		d.Id())
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "pending-acceptance",
		Refresh: resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id()),
		Timeout: 1 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for vpc peering (%s) to become available: %s",
			d.Id(), err)
	}

	return resourceAwsVPCPeeringUpdate(d, meta)
}

func resourceAwsVPCPeeringRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())()
	if err != nil {
		return err
	}
	if pcRaw == nil {
		d.SetId("")
		return nil
	}

	pc := pcRaw.(*ec2.VPCPeeringConnection)

	// The failed status is a status that we can assume just means the
	// connection is gone. Destruction isn't allowed, and it eventually
	// just "falls off" the console. See GH-2322
	if *pc.Status.Code == "failed" {
		d.SetId("")
		return nil
	}

	d.Set("accept_status", *pc.Status.Code)
	d.Set("peer_owner_id", pc.AccepterVPCInfo.OwnerID)
	d.Set("peer_vpc_id", pc.AccepterVPCInfo.VPCID)
	d.Set("vpc_id", pc.RequesterVPCInfo.VPCID)
	d.Set("tags", tagsToMap(pc.Tags))

	return nil
}

func resourceVPCPeeringConnectionAccept(conn *ec2.EC2, id string) (string, error) {

	log.Printf("[INFO] Accept VPC Peering Connection with id: %s", id)

	req := &ec2.AcceptVPCPeeringConnectionInput{
		VPCPeeringConnectionID: aws.String(id),
	}

	resp, err := conn.AcceptVPCPeeringConnection(req)
	pc := resp.VPCPeeringConnection
	return *pc.Status.Code, err
}

func resourceAwsVPCPeeringUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	if err := setTags(conn, d); err != nil {
		return err
	} else {
		d.SetPartial("tags")
	}

	if _, ok := d.GetOk("auto_accept"); ok {

		pcRaw, _, err := resourceAwsVPCPeeringConnectionStateRefreshFunc(conn, d.Id())()

		if err != nil {
			return err
		}
		if pcRaw == nil {
			d.SetId("")
			return nil
		}
		pc := pcRaw.(*ec2.VPCPeeringConnection)

		if *pc.Status.Code == "pending-acceptance" {

			status, err := resourceVPCPeeringConnectionAccept(conn, d.Id())

			log.Printf(
				"[DEBUG] VPC Peering connection accept status %s",
				status)
			if err != nil {
				return err
			}
		}
	}

	return resourceAwsVPCPeeringRead(d, meta)
}

func resourceAwsVPCPeeringDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	_, err := conn.DeleteVPCPeeringConnection(
		&ec2.DeleteVPCPeeringConnectionInput{
			VPCPeeringConnectionID: aws.String(d.Id()),
		})
	return err
}

// resourceAwsVPCPeeringConnectionStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a VPCPeeringConnection.
func resourceAwsVPCPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {

		resp, err := conn.DescribeVPCPeeringConnections(&ec2.DescribeVPCPeeringConnectionsInput{
			VPCPeeringConnectionIDs: []*string{aws.String(id)},
		})
		if err != nil {
			if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidVpcPeeringConnectionID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on VPCPeeringConnectionStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		pc := resp.VPCPeeringConnections[0]

		return pc, *pc.Status.Code, nil
	}
}
<|endoftext|>


<commit_before>package tools

func MinInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func MaxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<commit_msg>tools: :nail_care:<commit_after>package tools

// MinInt returns the smaller of two `int`s, "a", or "b".
func MinInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

// MaxInt returns the greater of two `int`s, "a", or "b".
func MaxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<|endoftext|>


<commit_before>package env

import (
	"encoding"
	"errors"
	"fmt"
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/caarlos0/env/v5/parsers"
)

// nolint: gochecknoglobals
var (
	// ErrNotAStructPtr is returned if you pass something that is not a pointer to a
	// Struct to Parse
	ErrNotAStructPtr = errors.New("env: expected a pointer to a Struct")

	defaultBuiltInParsers = map[reflect.Kind]ParserFunc{
		reflect.Bool: func(v string) (interface{}, error) {
			return strconv.ParseBool(v)
		},
		reflect.String: func(v string) (interface{}, error) {
			return v, nil
		},
		reflect.Int: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int(i), err
		},
		reflect.Int16: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 16)
			return int16(i), err
		},
		reflect.Int32: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int32(i), err
		},
		reflect.Int64: func(v string) (interface{}, error) {
			return strconv.ParseInt(v, 10, 64)
		},
		reflect.Int8: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 8)
			return int8(i), err
		},
		reflect.Uint: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint(i), err
		},
		reflect.Uint16: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 16)
			return uint16(i), err
		},
		reflect.Uint32: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint32(i), err
		},
		reflect.Uint64: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 64)
			return i, err
		},
		reflect.Uint8: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 8)
			return uint8(i), err
		},
		reflect.Float64: func(v string) (interface{}, error) {
			return strconv.ParseFloat(v, 64)
		},
		reflect.Float32: func(v string) (interface{}, error) {
			f, err := strconv.ParseFloat(v, 32)
			return float32(f), err
		},
	}
)

func defaultCustomParsers() CustomParsers {
	return CustomParsers{
		parsers.URLType:      parsers.URLFunc,
		parsers.DurationType: parsers.DurationFunc,
	}
}

// CustomParsers is a friendly name for the type that `ParseWithFuncs()` accepts
type CustomParsers map[reflect.Type]ParserFunc

// ParserFunc defines the signature of a function that can be used within `CustomParsers`
type ParserFunc func(v string) (interface{}, error)

// Parse parses a struct containing `env` tags and loads its values from
// environment variables.
func Parse(v interface{}) error {
	return ParseWithFuncs(v, CustomParsers{})
}

// ParseWithFuncs is the same as `Parse` except it also allows the user to pass
// in custom parsers.
func ParseWithFuncs(v interface{}, funcMap CustomParsers) error {
	ptrRef := reflect.ValueOf(v)
	if ptrRef.Kind() != reflect.Ptr {
		return ErrNotAStructPtr
	}
	ref := ptrRef.Elem()
	if ref.Kind() != reflect.Struct {
		return ErrNotAStructPtr
	}
	var parsers = defaultCustomParsers()
	for k, v := range funcMap {
		parsers[k] = v
	}
	return doParse(ref, parsers)
}

func doParse(ref reflect.Value, funcMap CustomParsers) error {
	refType := ref.Type()

	for i := 0; i < refType.NumField(); i++ {
		refField := ref.Field(i)
		if !refField.CanSet() {
			continue
		}
		if reflect.Ptr == refField.Kind() && !refField.IsNil() {
			err := Parse(refField.Interface())
			if nil != err {
				return err
			}
			continue
		}
		refTypeField := refType.Field(i)
		value, err := get(refTypeField)
		if err != nil {
			return err
		}
		if value == "" {
			if reflect.Struct == refField.Kind() {
				if err := doParse(refField, funcMap); err != nil {
					return err
				}
			}
			continue
		}
		if err := set(refField, refTypeField, value, funcMap); err != nil {
			return err
		}
	}
	return nil
}

func get(field reflect.StructField) (string, error) {
	var (
		val string
		err error
	)

	key, opts := parseKeyForOption(field.Tag.Get("env"))

	defaultValue := field.Tag.Get("envDefault")
	val = getOr(key, defaultValue)

	expandVar := field.Tag.Get("envExpand")
	if strings.ToLower(expandVar) == "true" {
		val = os.ExpandEnv(val)
	}

	if len(opts) > 0 {
		for _, opt := range opts {
			// The only option supported is "required".
			switch opt {
			case "":
				break
			case "required":
				val, err = getRequired(key)
			default:
				err = fmt.Errorf("env: tag option %q not supported", opt)
			}
		}
	}

	return val, err
}

// split the env tag's key into the expected key and desired option, if any.
func parseKeyForOption(key string) (string, []string) {
	opts := strings.Split(key, ",")
	return opts[0], opts[1:]
}

func getRequired(key string) (string, error) {
	if value, ok := os.LookupEnv(key); ok {
		return value, nil
	}
	return "", fmt.Errorf(`env: required environment variable %q is not set`, key)
}

func getOr(key, defaultValue string) string {
	value, ok := os.LookupEnv(key)
	if ok {
		return value
	}
	return defaultValue
}

func set(field reflect.Value, sf reflect.StructField, value string, funcMap CustomParsers) error {
	if field.Kind() == reflect.Slice {
		return handleSlice(field, value, sf, funcMap)
	}

	set, err := handleTextUnmarshaler(field, value, sf)
	if set {
		return nil
	}
	if err != nil {
		return err
	}

	parserFunc, ok := funcMap[sf.Type]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}
		field.Set(reflect.ValueOf(val))
		return nil
	}

	parserFunc, ok = defaultBuiltInParsers[sf.Type.Kind()]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}
		field.Set(reflect.ValueOf(val).Convert(sf.Type))
		return nil
	}

	return newNoParserError(sf)
}

func handleSlice(field reflect.Value, value string, sf reflect.StructField, funcMap CustomParsers) error {
	var separator = sf.Tag.Get("envSeparator")
	if separator == "" {
		separator = ","
	}
	var parts = strings.Split(value, separator)

	var elemType = sf.Type.Elem()
	if elemType.Kind() == reflect.Ptr {
		elemType = elemType.Elem()
	}

	if _, ok := reflect.New(elemType).Interface().(encoding.TextUnmarshaler); ok {
		return parseTextUnmarshalers(field, parts, sf)
	}

	parserFunc, ok := funcMap[elemType]
	if !ok {
		parserFunc, ok = defaultBuiltInParsers[elemType.Kind()]
		if !ok {
			return newNoParserError(sf)
		}
	}

	var result = reflect.MakeSlice(sf.Type, 0, len(parts))
	for _, part := range parts {
		r, err := parserFunc(part)
		if err != nil {
			return newParseError(sf, err)
		}
		var v = reflect.ValueOf(r).Convert(elemType)
		if sf.Type.Elem().Kind() == reflect.Ptr {
			// TODO: add this!
			return fmt.Errorf("env: pointer slices of built-in and aliased types are not supported: %s %s", sf.Name, sf.Type)
		}
		result = reflect.Append(result, v)
	}
	field.Set(result)
	return nil
}

func handleTextUnmarshaler(field reflect.Value, value string, sf reflect.StructField) (bool, error) {
	if reflect.Ptr == field.Kind() {
		if field.IsNil() {
			field.Set(reflect.New(field.Type().Elem()))
		}
	} else if field.CanAddr() {
		field = field.Addr()
	}

	tm, ok := field.Interface().(encoding.TextUnmarshaler)
	if !ok {
		return false, nil
	}
	var err = tm.UnmarshalText([]byte(value))
	return err == nil, newParseError(sf, err)
}

func parseTextUnmarshalers(field reflect.Value, data []string, sf reflect.StructField) error {
	s := len(data)
	elemType := field.Type().Elem()
	slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s)
	for i, v := range data {
		sv := slice.Index(i)
		kind := sv.Kind()
		if kind == reflect.Ptr {
			sv = reflect.New(elemType.Elem())
		} else {
			sv = sv.Addr()
		}
		tm := sv.Interface().(encoding.TextUnmarshaler)
		if err := tm.UnmarshalText([]byte(v)); err != nil {
			return newParseError(sf, err)
		}
		if kind == reflect.Ptr {
			slice.Index(i).Set(sv)
		}
	}

	field.Set(slice)

	return nil
}

func newParseError(sf reflect.StructField, err error) error {
	if err == nil {
		return nil
	}
	return parseError{
		sf:  sf,
		err: err,
	}
}

type parseError struct {
	sf  reflect.StructField
	err error
}

func (e parseError) Error() string {
	return fmt.Sprintf(`env: parse error on field "%s" of type "%s": %v`, e.sf.Name, e.sf.Type, e.err)
}

func newNoParserError(sf reflect.StructField) error {
	return fmt.Errorf(`env: no parser found for field "%s" of type "%s"`, sf.Name, sf.Type)
}
<commit_msg>refactor: improve code a bit<commit_after>package env

import (
	"encoding"
	"errors"
	"fmt"
	"os"
	"reflect"
	"strconv"
	"strings"

	"github.com/caarlos0/env/v5/parsers"
)

// nolint: gochecknoglobals
var (
	// ErrNotAStructPtr is returned if you pass something that is not a pointer to a
	// Struct to Parse
	ErrNotAStructPtr = errors.New("env: expected a pointer to a Struct")

	defaultBuiltInParsers = map[reflect.Kind]ParserFunc{
		reflect.Bool: func(v string) (interface{}, error) {
			return strconv.ParseBool(v)
		},
		reflect.String: func(v string) (interface{}, error) {
			return v, nil
		},
		reflect.Int: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int(i), err
		},
		reflect.Int16: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 16)
			return int16(i), err
		},
		reflect.Int32: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 32)
			return int32(i), err
		},
		reflect.Int64: func(v string) (interface{}, error) {
			return strconv.ParseInt(v, 10, 64)
		},
		reflect.Int8: func(v string) (interface{}, error) {
			i, err := strconv.ParseInt(v, 10, 8)
			return int8(i), err
		},
		reflect.Uint: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint(i), err
		},
		reflect.Uint16: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 16)
			return uint16(i), err
		},
		reflect.Uint32: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 32)
			return uint32(i), err
		},
		reflect.Uint64: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 64)
			return i, err
		},
		reflect.Uint8: func(v string) (interface{}, error) {
			i, err := strconv.ParseUint(v, 10, 8)
			return uint8(i), err
		},
		reflect.Float64: func(v string) (interface{}, error) {
			return strconv.ParseFloat(v, 64)
		},
		reflect.Float32: func(v string) (interface{}, error) {
			f, err := strconv.ParseFloat(v, 32)
			return float32(f), err
		},
	}
)

func defaultCustomParsers() CustomParsers {
	return CustomParsers{
		parsers.URLType:      parsers.URLFunc,
		parsers.DurationType: parsers.DurationFunc,
	}
}

// CustomParsers is a friendly name for the type that `ParseWithFuncs()` accepts
type CustomParsers map[reflect.Type]ParserFunc

// ParserFunc defines the signature of a function that can be used within `CustomParsers`
type ParserFunc func(v string) (interface{}, error)

// Parse parses a struct containing `env` tags and loads its values from
// environment variables.
func Parse(v interface{}) error {
	return ParseWithFuncs(v, CustomParsers{})
}

// ParseWithFuncs is the same as `Parse` except it also allows the user to pass
// in custom parsers.
func ParseWithFuncs(v interface{}, funcMap CustomParsers) error {
	ptrRef := reflect.ValueOf(v)
	if ptrRef.Kind() != reflect.Ptr {
		return ErrNotAStructPtr
	}
	ref := ptrRef.Elem()
	if ref.Kind() != reflect.Struct {
		return ErrNotAStructPtr
	}
	var parsers = defaultCustomParsers()
	for k, v := range funcMap {
		parsers[k] = v
	}
	return doParse(ref, parsers)
}

func doParse(ref reflect.Value, funcMap CustomParsers) error {
	refType := ref.Type()

	for i := 0; i < refType.NumField(); i++ {
		refField := ref.Field(i)
		if !refField.CanSet() {
			continue
		}
		if reflect.Ptr == refField.Kind() && !refField.IsNil() {
			err := Parse(refField.Interface())
			if nil != err {
				return err
			}
			continue
		}
		refTypeField := refType.Field(i)
		value, err := get(refTypeField)
		if err != nil {
			return err
		}
		if value == "" {
			if reflect.Struct == refField.Kind() {
				if err := doParse(refField, funcMap); err != nil {
					return err
				}
			}
			continue
		}
		if err := set(refField, refTypeField, value, funcMap); err != nil {
			return err
		}
	}
	return nil
}

func get(field reflect.StructField) (string, error) {
	var (
		val string
		err error
	)

	key, opts := parseKeyForOption(field.Tag.Get("env"))

	defaultValue := field.Tag.Get("envDefault")
	val = getOr(key, defaultValue)

	expandVar := field.Tag.Get("envExpand")
	if strings.ToLower(expandVar) == "true" {
		val = os.ExpandEnv(val)
	}

	if len(opts) > 0 {
		for _, opt := range opts {
			// The only option supported is "required".
			switch opt {
			case "":
				break
			case "required":
				val, err = getRequired(key)
			default:
				err = fmt.Errorf("env: tag option %q not supported", opt)
			}
		}
	}

	return val, err
}

// split the env tag's key into the expected key and desired option, if any.
func parseKeyForOption(key string) (string, []string) {
	opts := strings.Split(key, ",")
	return opts[0], opts[1:]
}

func getRequired(key string) (string, error) {
	if value, ok := os.LookupEnv(key); ok {
		return value, nil
	}
	return "", fmt.Errorf(`env: required environment variable %q is not set`, key)
}

func getOr(key, defaultValue string) string {
	value, ok := os.LookupEnv(key)
	if ok {
		return value
	}
	return defaultValue
}

func set(field reflect.Value, sf reflect.StructField, value string, funcMap CustomParsers) error {
	if field.Kind() == reflect.Slice {
		return handleSlice(field, value, sf, funcMap)
	}

	var tm = asTextUnmarshaler(field)
	if tm != nil {
		var err = tm.UnmarshalText([]byte(value))
		return newParseError(sf, err)
	}

	parserFunc, ok := funcMap[sf.Type]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}
		field.Set(reflect.ValueOf(val))
		return nil
	}

	parserFunc, ok = defaultBuiltInParsers[sf.Type.Kind()]
	if ok {
		val, err := parserFunc(value)
		if err != nil {
			return newParseError(sf, err)
		}
		field.Set(reflect.ValueOf(val).Convert(sf.Type))
		return nil
	}

	return newNoParserError(sf)
}

func handleSlice(field reflect.Value, value string, sf reflect.StructField, funcMap CustomParsers) error {
	var separator = sf.Tag.Get("envSeparator")
	if separator == "" {
		separator = ","
	}
	var parts = strings.Split(value, separator)

	var elemType = sf.Type.Elem()
	if elemType.Kind() == reflect.Ptr {
		elemType = elemType.Elem()
	}

	if _, ok := reflect.New(elemType).Interface().(encoding.TextUnmarshaler); ok {
		return parseTextUnmarshalers(field, parts, sf)
	}

	parserFunc, ok := funcMap[elemType]
	if !ok {
		parserFunc, ok = defaultBuiltInParsers[elemType.Kind()]
		if !ok {
			return newNoParserError(sf)
		}
	}

	var result = reflect.MakeSlice(sf.Type, 0, len(parts))
	for _, part := range parts {
		r, err := parserFunc(part)
		if err != nil {
			return newParseError(sf, err)
		}
		var v = reflect.ValueOf(r).Convert(elemType)
		if sf.Type.Elem().Kind() == reflect.Ptr {
			// TODO: add this!
			return fmt.Errorf("env: pointer slices of built-in and aliased types are not supported: %s %s", sf.Name, sf.Type)
		}
		result = reflect.Append(result, v)
	}
	field.Set(result)
	return nil
}

func asTextUnmarshaler(field reflect.Value) encoding.TextUnmarshaler {
	if reflect.Ptr == field.Kind() {
		if field.IsNil() {
			field.Set(reflect.New(field.Type().Elem()))
		}
	} else if field.CanAddr() {
		field = field.Addr()
	}

	tm, ok := field.Interface().(encoding.TextUnmarshaler)
	if !ok {
		return nil
	}
	return tm
}

func parseTextUnmarshalers(field reflect.Value, data []string, sf reflect.StructField) error {
	s := len(data)
	elemType := field.Type().Elem()
	slice := reflect.MakeSlice(reflect.SliceOf(elemType), s, s)
	for i, v := range data {
		sv := slice.Index(i)
		kind := sv.Kind()
		if kind == reflect.Ptr {
			sv = reflect.New(elemType.Elem())
		} else {
			sv = sv.Addr()
		}
		tm := sv.Interface().(encoding.TextUnmarshaler)
		if err := tm.UnmarshalText([]byte(v)); err != nil {
			return newParseError(sf, err)
		}
		if kind == reflect.Ptr {
			slice.Index(i).Set(sv)
		}
	}

	field.Set(slice)

	return nil
}

func newParseError(sf reflect.StructField, err error) error {
	if err == nil {
		return nil
	}
	return parseError{
		sf:  sf,
		err: err,
	}
}

type parseError struct {
	sf  reflect.StructField
	err error
}

func (e parseError) Error() string {
	return fmt.Sprintf(`env: parse error on field "%s" of type "%s": %v`, e.sf.Name, e.sf.Type, e.err)
}

func newNoParserError(sf reflect.StructField) error {
	return fmt.Errorf(`env: no parser found for field "%s" of type "%s"`, sf.Name, sf.Type)
}
<|endoftext|>


<commit_before>
package gotomic

import (
	"testing"
)

func TestPutGetDelete(t *testing.T) {
	treap := NewTreap()
	_, ok := treap.Get(c(3))
	if ok {
		t.Error("should not contain 3")
	}
	treap.Put(c(3), 44)
	v, ok := treap.Get(c(3))
	if !ok {
		t.Error("should contain 3")
	}
	if v != 44 {
		t.Error("should be 44")
	}
	v, ok = treap.Delete(c(3))
	if !ok {
		t.Error("should contain 3")
	}
	if v != 44 {
		t.Error("should be 44")
	}
	v, ok = treap.Get(c(3))
	if ok {
		t.Error("should not contain 3")
	}
	v, ok = treap.Delete(c(3))
	if v == 44 {
		t.Error("should not be 44")
	}
	if ok {
		t.Error("should not contain 3")
	}
}
<commit_msg>more testing<commit_after>
package gotomic

import (
	"testing"
)

func TestTreapPutGetDelete(t *testing.T) {
	treap := NewTreap()
	_, ok := treap.Get(c(3))
	if ok {
		t.Error("should not contain 3")
	}
	treap.Put(c(3), 44)
	v, ok := treap.Get(c(3))
	if !ok {
		t.Error("should contain 3")
	}
	if v != 44 {
		t.Error("should be 44")
	}
	v, ok = treap.Delete(c(3))
	if !ok {
		t.Error("should contain 3")
	}
	if v != 44 {
		t.Error("should be 44")
	}
	v, ok = treap.Get(c(3))
	if ok {
		t.Error("should not contain 3")
	}
	v, ok = treap.Delete(c(3))
	if v == 44 {
		t.Error("should not be 44")
	}
	if ok {
		t.Error("should not contain 3")
	}
}

func TestTreapMin(t *testing.T) {
	treap := NewTreap()
	k, v, ok := treap.Min()
	if ok {
		t.Error("should not have min value")
	}
	treap.Put(c(3), "3")
	k, v, ok = treap.Min()
	if !ok {
		t.Error("should have min value")
	}
	if k != c(3) {
		t.Error("min should be 3")
	}
	if v != "3" {
		t.Error("min should be 3")
	}
	treap.Put(c(2), "2")
	k, v, ok = treap.Min()
	if !ok {
		t.Error("should have min value")
	}
	if k != c(2) {
		t.Error("min should be 2")
	}
	if v != "2" {
		t.Errorf("min should be 2, not %#v", v)
	}
	treap.Put(c(4), "4")
	k, v, ok = treap.Min()
	if !ok {
		t.Error("should have min value")
	}
	if k != c(2) {
		t.Error("min should be 2")
	}
	if v != "2" {
		t.Error("min should be 2")
	}
}<|endoftext|>


<commit_before>// Package appinsights provides an interface to submit telemetry to Application Insights.
// See more at https://azure.microsoft.com/en-us/services/application-insights/
package appinsights

const (
	sdkName = "go"
	Version = "0.3.0"
)
<commit_msg>Tag prerelease version<commit_after>// Package appinsights provides an interface to submit telemetry to Application Insights.
// See more at https://azure.microsoft.com/en-us/services/application-insights/
package appinsights

const (
	sdkName = "go"
	Version = "0.3.1-pre"
)
<|endoftext|>


<commit_before>/*
Copyright 2021 The Vitess Authors.

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

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

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

package planbuilder

import (
	"sort"
	"strings"

	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vtgate/engine"
	"vitess.io/vitess/go/vt/vtgate/semantics"
	"vitess.io/vitess/go/vt/vtgate/vindexes"

	"vitess.io/vitess/go/vt/vterrors"
)

func transformToLogicalPlan(tree queryTree, semTable *semantics.SemTable, processing *postProcessor) (logicalPlan, error) {
	switch n := tree.(type) {
	case *routeTree:
		return transformRoutePlan(n, semTable)

	case *joinTree:
		return transformJoinPlan(n, semTable, processing)

	case *derivedTree:
		plan, err := transformToLogicalPlan(n.inner, semTable, processing)
		if err != nil {
			return nil, err
		}
		processing.inDerived = true
		plan, err = processing.planHorizon(plan, n.query)
		if err != nil {
			return nil, err
		}
		processing.inDerived = false

		rb, isRoute := plan.(*route)
		if !isRoute {
			return plan, nil
		}
		innerSelect := rb.Select
		derivedTable := &sqlparser.DerivedTable{Select: innerSelect}
		tblExpr := &sqlparser.AliasedTableExpr{
			Expr: derivedTable,
			As:   sqlparser.NewTableIdent(n.alias),
		}
		rb.Select = &sqlparser.Select{
			From: []sqlparser.TableExpr{tblExpr},
		}
		return plan, nil
	}

	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unknown type encountered: %T", tree)
}

func transformJoinPlan(n *joinTree, semTable *semantics.SemTable, processing *postProcessor) (logicalPlan, error) {
	lhs, err := transformToLogicalPlan(n.lhs, semTable, processing)
	if err != nil {
		return nil, err
	}
	rhs, err := transformToLogicalPlan(n.rhs, semTable, processing)
	if err != nil {
		return nil, err
	}
	opCode := engine.InnerJoin
	if n.outer {
		opCode = engine.LeftJoin
	}
	return &joinGen4{
		Left:   lhs,
		Right:  rhs,
		Cols:   n.columns,
		Vars:   n.vars,
		Opcode: opCode,
	}, nil
}

func transformRoutePlan(n *routeTree, semTable *semantics.SemTable) (*route, error) {
	var tablesForSelect sqlparser.TableExprs
	tableNameMap := map[string]interface{}{}

	sort.Sort(n.tables)
	for _, t := range n.tables {
		tableExpr, err := relToTableExpr(t)
		if err != nil {
			return nil, err
		}
		tablesForSelect = append(tablesForSelect, tableExpr)
		for _, name := range t.tableNames() {
			tableNameMap[name] = nil
		}
	}

	for _, predicate := range n.vindexPredicates {
		switch predicate := predicate.(type) {
		case *sqlparser.ComparisonExpr:
			if predicate.Operator == sqlparser.InOp {
				switch predicate.Left.(type) {
				case *sqlparser.ColName:
					predicate.Right = sqlparser.ListArg(engine.ListVarName)
				}
			}
		}
	}

	for _, leftJoin := range n.leftJoins {
		var lft sqlparser.TableExpr
		if len(tablesForSelect) == 1 {
			lft = tablesForSelect[0]
		} else {
			lft = &sqlparser.ParenTableExpr{Exprs: tablesForSelect}
		}

		rightExpr, err := relToTableExpr(leftJoin.right)
		if err != nil {
			return nil, err
		}
		joinExpr := &sqlparser.JoinTableExpr{
			Join: sqlparser.LeftJoinType,
			Condition: sqlparser.JoinCondition{
				On: leftJoin.pred,
			},
			RightExpr: rightExpr,
			LeftExpr:  lft,
		}
		tablesForSelect = sqlparser.TableExprs{joinExpr}
		for _, tblNames := range leftJoin.right.tableNames() {
			tableNameMap[tblNames] = nil
		}
	}

	predicates := n.Predicates()
	var where *sqlparser.Where
	if predicates != nil {
		where = &sqlparser.Where{Expr: predicates, Type: sqlparser.WhereClause}
	}

	var singleColumn vindexes.SingleColumn
	if n.vindex != nil {
		singleColumn = n.vindex.(vindexes.SingleColumn)
	}

	var expressions sqlparser.SelectExprs
	for _, col := range n.columns {
		expressions = append(expressions, &sqlparser.AliasedExpr{
			Expr: col,
			As:   sqlparser.ColIdent{},
		})
	}

	var tableNames []string
	for name := range tableNameMap {
		tableNames = append(tableNames, name)
	}
	sort.Strings(tableNames)

	return &route{
		eroute: &engine.Route{
			Opcode:              n.routeOpCode,
			TableName:           strings.Join(tableNames, ", "),
			Keyspace:            n.keyspace,
			Vindex:              singleColumn,
			Values:              n.vindexValues,
			SysTableTableName:   n.SysTableTableName,
			SysTableTableSchema: n.SysTableTableSchema,
		},
		Select: &sqlparser.Select{
			SelectExprs: expressions,
			From:        tablesForSelect,
			Where:       where,
			Comments:    semTable.Comments,
		},
		tables: n.solved,
	}, nil
}

func relToTableExpr(t relation) (sqlparser.TableExpr, error) {
	switch t := t.(type) {
	case *routeTable:
		var expr sqlparser.SimpleTableExpr
		if t.qtable.IsInfSchema {
			expr = t.qtable.Table
		} else {
			expr = sqlparser.TableName{
				Name: t.vtable.Name,
			}
		}
		return &sqlparser.AliasedTableExpr{
			Expr:       expr,
			Partitions: nil,
			As:         t.qtable.Alias.As,
			Hints:      t.qtable.Alias.Hints,
		}, nil
	case parenTables:
		tables := sqlparser.TableExprs{}
		for _, t := range t {
			tableExpr, err := relToTableExpr(t)
			if err != nil {
				return nil, err
			}
			tables = append(tables, tableExpr)
		}
		return &sqlparser.ParenTableExpr{Exprs: tables}, nil
	case *joinTables:
		lExpr, err := relToTableExpr(t.lhs)
		if err != nil {
			return nil, err
		}
		rExpr, err := relToTableExpr(t.rhs)
		if err != nil {
			return nil, err
		}
		return &sqlparser.JoinTableExpr{
			LeftExpr:  lExpr,
			Join:      sqlparser.NormalJoinType,
			RightExpr: rExpr,
			Condition: sqlparser.JoinCondition{
				On: t.pred,
			},
		}, nil
	case *derivedTable:
		innerTables, err := relToTableExpr(t.tables)
		if err != nil {
			return nil, err
		}
		tbls := innerTables.(*sqlparser.ParenTableExpr)

		sel := &sqlparser.Select{
			SelectExprs: t.query.SelectExprs,
			From:        tbls.Exprs,
			Where:       &sqlparser.Where{Expr: sqlparser.AndExpressions(t.predicates...)},
		}
		expr := &sqlparser.DerivedTable{
			Select: sel,
		}
		return &sqlparser.AliasedTableExpr{
			Expr:       expr,
			Partitions: nil,
			As:         sqlparser.NewTableIdent(t.alias),
		}, nil
	default:
		return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unknown relation type: %T", t)
	}
}
<commit_msg>Addition of comment in transformToLogicalPlan to explain the derived tree transformation<commit_after>/*
Copyright 2021 The Vitess Authors.

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

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

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

package planbuilder

import (
	"sort"
	"strings"

	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vtgate/engine"
	"vitess.io/vitess/go/vt/vtgate/semantics"
	"vitess.io/vitess/go/vt/vtgate/vindexes"

	"vitess.io/vitess/go/vt/vterrors"
)

func transformToLogicalPlan(tree queryTree, semTable *semantics.SemTable, processing *postProcessor) (logicalPlan, error) {
	switch n := tree.(type) {
	case *routeTree:
		return transformRoutePlan(n, semTable)

	case *joinTree:
		return transformJoinPlan(n, semTable, processing)

	case *derivedTree:
		// transforming the inner part of the derived table into a logical plan
		// so that we can do horizon planning on the inner. If the logical plan
		// we've produced is a Route, we set its Select.From field to be an aliased
		// expression containing our derived table's inner select and the derived
		// table's alias.

		plan, err := transformToLogicalPlan(n.inner, semTable, processing)
		if err != nil {
			return nil, err
		}
		processing.inDerived = true
		plan, err = processing.planHorizon(plan, n.query)
		if err != nil {
			return nil, err
		}
		processing.inDerived = false

		rb, isRoute := plan.(*route)
		if !isRoute {
			return plan, nil
		}
		innerSelect := rb.Select
		derivedTable := &sqlparser.DerivedTable{Select: innerSelect}
		tblExpr := &sqlparser.AliasedTableExpr{
			Expr: derivedTable,
			As:   sqlparser.NewTableIdent(n.alias),
		}
		rb.Select = &sqlparser.Select{
			From: []sqlparser.TableExpr{tblExpr},
		}
		return plan, nil
	}

	return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unknown type encountered: %T", tree)
}

func transformJoinPlan(n *joinTree, semTable *semantics.SemTable, processing *postProcessor) (logicalPlan, error) {
	lhs, err := transformToLogicalPlan(n.lhs, semTable, processing)
	if err != nil {
		return nil, err
	}
	rhs, err := transformToLogicalPlan(n.rhs, semTable, processing)
	if err != nil {
		return nil, err
	}
	opCode := engine.InnerJoin
	if n.outer {
		opCode = engine.LeftJoin
	}
	return &joinGen4{
		Left:   lhs,
		Right:  rhs,
		Cols:   n.columns,
		Vars:   n.vars,
		Opcode: opCode,
	}, nil
}

func transformRoutePlan(n *routeTree, semTable *semantics.SemTable) (*route, error) {
	var tablesForSelect sqlparser.TableExprs
	tableNameMap := map[string]interface{}{}

	sort.Sort(n.tables)
	for _, t := range n.tables {
		tableExpr, err := relToTableExpr(t)
		if err != nil {
			return nil, err
		}
		tablesForSelect = append(tablesForSelect, tableExpr)
		for _, name := range t.tableNames() {
			tableNameMap[name] = nil
		}
	}

	for _, predicate := range n.vindexPredicates {
		switch predicate := predicate.(type) {
		case *sqlparser.ComparisonExpr:
			if predicate.Operator == sqlparser.InOp {
				switch predicate.Left.(type) {
				case *sqlparser.ColName:
					predicate.Right = sqlparser.ListArg(engine.ListVarName)
				}
			}
		}
	}

	for _, leftJoin := range n.leftJoins {
		var lft sqlparser.TableExpr
		if len(tablesForSelect) == 1 {
			lft = tablesForSelect[0]
		} else {
			lft = &sqlparser.ParenTableExpr{Exprs: tablesForSelect}
		}

		rightExpr, err := relToTableExpr(leftJoin.right)
		if err != nil {
			return nil, err
		}
		joinExpr := &sqlparser.JoinTableExpr{
			Join: sqlparser.LeftJoinType,
			Condition: sqlparser.JoinCondition{
				On: leftJoin.pred,
			},
			RightExpr: rightExpr,
			LeftExpr:  lft,
		}
		tablesForSelect = sqlparser.TableExprs{joinExpr}
		for _, tblNames := range leftJoin.right.tableNames() {
			tableNameMap[tblNames] = nil
		}
	}

	predicates := n.Predicates()
	var where *sqlparser.Where
	if predicates != nil {
		where = &sqlparser.Where{Expr: predicates, Type: sqlparser.WhereClause}
	}

	var singleColumn vindexes.SingleColumn
	if n.vindex != nil {
		singleColumn = n.vindex.(vindexes.SingleColumn)
	}

	var expressions sqlparser.SelectExprs
	for _, col := range n.columns {
		expressions = append(expressions, &sqlparser.AliasedExpr{
			Expr: col,
			As:   sqlparser.ColIdent{},
		})
	}

	var tableNames []string
	for name := range tableNameMap {
		tableNames = append(tableNames, name)
	}
	sort.Strings(tableNames)

	return &route{
		eroute: &engine.Route{
			Opcode:              n.routeOpCode,
			TableName:           strings.Join(tableNames, ", "),
			Keyspace:            n.keyspace,
			Vindex:              singleColumn,
			Values:              n.vindexValues,
			SysTableTableName:   n.SysTableTableName,
			SysTableTableSchema: n.SysTableTableSchema,
		},
		Select: &sqlparser.Select{
			SelectExprs: expressions,
			From:        tablesForSelect,
			Where:       where,
			Comments:    semTable.Comments,
		},
		tables: n.solved,
	}, nil
}

func relToTableExpr(t relation) (sqlparser.TableExpr, error) {
	switch t := t.(type) {
	case *routeTable:
		var expr sqlparser.SimpleTableExpr
		if t.qtable.IsInfSchema {
			expr = t.qtable.Table
		} else {
			expr = sqlparser.TableName{
				Name: t.vtable.Name,
			}
		}
		return &sqlparser.AliasedTableExpr{
			Expr:       expr,
			Partitions: nil,
			As:         t.qtable.Alias.As,
			Hints:      t.qtable.Alias.Hints,
		}, nil
	case parenTables:
		tables := sqlparser.TableExprs{}
		for _, t := range t {
			tableExpr, err := relToTableExpr(t)
			if err != nil {
				return nil, err
			}
			tables = append(tables, tableExpr)
		}
		return &sqlparser.ParenTableExpr{Exprs: tables}, nil
	case *joinTables:
		lExpr, err := relToTableExpr(t.lhs)
		if err != nil {
			return nil, err
		}
		rExpr, err := relToTableExpr(t.rhs)
		if err != nil {
			return nil, err
		}
		return &sqlparser.JoinTableExpr{
			LeftExpr:  lExpr,
			Join:      sqlparser.NormalJoinType,
			RightExpr: rExpr,
			Condition: sqlparser.JoinCondition{
				On: t.pred,
			},
		}, nil
	case *derivedTable:
		innerTables, err := relToTableExpr(t.tables)
		if err != nil {
			return nil, err
		}
		tbls := innerTables.(*sqlparser.ParenTableExpr)

		sel := &sqlparser.Select{
			SelectExprs: t.query.SelectExprs,
			From:        tbls.Exprs,
			Where:       &sqlparser.Where{Expr: sqlparser.AndExpressions(t.predicates...)},
		}
		expr := &sqlparser.DerivedTable{
			Select: sel,
		}
		return &sqlparser.AliasedTableExpr{
			Expr:       expr,
			Partitions: nil,
			As:         sqlparser.NewTableIdent(t.alias),
		}, nil
	default:
		return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] unknown relation type: %T", t)
	}
}
<|endoftext|>


<commit_before>package util

import (
	//	"fmt"
	"net/mail"
	"strconv"
)

func (u *SomaUtil) ValidateStringAsNodeAssetId(s string) {
	_, err := strconv.ParseUint(s, 10, 64)
	u.AbortOnError(err)
}

func (u *SomaUtil) ValidateStringAsBool(s string) {
	_, err := strconv.ParseBool(s)
	u.AbortOnError(err)
}

func (u *SomaUtil) ValidateStringAsEmployeeNumber(s string) {
	employeeNumber, err := strconv.Atoi(s)
	u.AbortOnError(err, "Syntax error, employeenr argument not a number")
	if employeeNumber < 0 {
		u.Abort("Negative employee number is not allowed")
	}
}

func (u *SomaUtil) ValidateStringAsMailAddress(s string) {
	_, err := mail.ParseAddress(s)
	u.AbortOnError(err, "Syntax error, mailaddr does not parse as RFC 5322 address")
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Add util function ValidateStringInSlice<commit_after>package util

import (
	"fmt"
	"net/mail"
	"strconv"
)

func (u *SomaUtil) ValidateStringAsNodeAssetId(s string) {
	_, err := strconv.ParseUint(s, 10, 64)
	u.AbortOnError(err)
}

func (u *SomaUtil) ValidateStringAsBool(s string) {
	_, err := strconv.ParseBool(s)
	u.AbortOnError(err)
}

func (u *SomaUtil) ValidateStringAsEmployeeNumber(s string) {
	employeeNumber, err := strconv.Atoi(s)
	u.AbortOnError(err, "Syntax error, employeenr argument not a number")
	if employeeNumber < 0 {
		u.Abort("Negative employee number is not allowed")
	}
}

func (u *SomaUtil) ValidateStringAsMailAddress(s string) {
	_, err := mail.ParseAddress(s)
	u.AbortOnError(err, "Syntax error, mailaddr does not parse as RFC 5322 address")
}

func (u *SomaUtil) ValidateStringInSlice(s string, sl []string) {
	if !u.SliceContainsString(s, sl) {
		if len(sl) == 0 {
			u.Abort("Error, cannot compare '%s' to empty keyword list")
		}

		// default []string.String() method prints [elem0 elem1 ...]
		// without quoting whitespace: []string{"a", "a b",} -> "[a a b]"
		errStr := fmt.Sprintf("Error, '%s' not one of: '%s'", s, sl[0])
		for _, v := range sl[1:] {
			errStr = fmt.Sprintf("%s, '%s'", errStr, v)
		}
		u.Abort(errStr)
	}
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>package vndrtest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

const testRepo = "github.com/docker/swarmkit"

func setGopath(cmd *exec.Cmd, gopath string) {
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, "GOPATH=") {
			continue
		}
		cmd.Env = append(cmd.Env, env)
	}
	cmd.Env = append(cmd.Env, "GOPATH="+gopath)
}

func TestVndr(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}

	gitCmd := exec.Command("git", "clone", "https://"+testRepo+".git", repoDir)
	out, err := gitCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("failed to clone %s to %s: %v, out: %s", testRepo, repoDir, err, out)
	}
	if err := os.RemoveAll(filepath.Join(repoDir, "vendor")); err != nil {
		t.Fatal(err)
	}

	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}

	installCmd := exec.Command("go", "install", testRepo)
	setGopath(installCmd, tmp)
	out, err = installCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("install %s failed: %v, out: %s", testRepo, err, out)
	}

	// revendor only etcd
	vndrRevendorCmd := exec.Command(vndrBin, "github.com/coreos/etcd")
	vndrRevendorCmd.Dir = repoDir
	setGopath(vndrRevendorCmd, tmp)

	out, err = vndrRevendorCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}
}

func TestVndrInit(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoPath := "github.com/LK4D4"
	repoDir := filepath.Join(tmp, "src", repoPath)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}

	cpCmd := exec.Command("cp", "-r", "./testdata/dumbproject", repoDir)
	out, err := cpCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("cp failed: %v, out: %s", err, out)
	}
	vndrCmd := exec.Command(vndrBin, "init")
	vndrCmd.Dir = filepath.Join(repoDir, "dumbproject")
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}

	pkgPath := filepath.Join(repoPath, "dumbproject")
	installCmd := exec.Command("go", "install", pkgPath)
	setGopath(installCmd, tmp)
	out, err = installCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("install %s failed: %v, out: %s", pkgPath, err, out)
	}
	vndr2Cmd := exec.Command(vndrBin, "init")
	vndr2Cmd.Dir = filepath.Join(repoDir, "dumbproject")
	setGopath(vndr2Cmd, tmp)

	out, err = vndr2Cmd.CombinedOutput()
	if err == nil || !bytes.Contains(out, []byte("There must not be")) {
		t.Fatalf("vndr is expected to fail about existing vendor, got %v: %s", err, out)
	}
}

func TestValidateSubpackages(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	content := []byte(`github.com/docker/docker branch
github.com/docker/docker/pkg/idtools branch
github.com/coreos/etcd/raft branch
github.com/docker/docker/pkg/archive branch
github.com/coreos/etcd branch
github.com/docker/swarmkit branch
github.com/docker/go branch
github.com/docker/go-connections branch
github.com/docker/go-units branch
github.com/docker/libcompose branch
github.com/docker/swarmkit branch
`)
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err := vndrCmd.CombinedOutput()
	if err == nil {
		t.Fatal("error is expected")
	}
	t.Logf("Output of vndr:\n%s", out)
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/docker/docker, github.com/docker/docker/pkg/idtools, github.com/docker/docker/pkg/archive' has same root import github.com/docker/docker")) {
		t.Error("duplicated docker package not found")
	}
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/coreos/etcd/raft, github.com/coreos/etcd' has same root import github.com/coreos/etcd")) {
		t.Error("duplicated etcd package not found")
	}
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/docker/swarmkit, github.com/docker/swarmkit' has same root import github.com/docker/swarmkit")) {
		t.Error("duplicated swarmkit package not found")
	}
	if bytes.Contains(out, []byte("go-units")) {
		t.Errorf("go-units should not be reported: %s", out)
	}
	if bytes.Contains(out, []byte("go-connections")) {
		t.Errorf("go-connections should not be reported: %s", out)
	}
	if bytes.Contains(out, []byte("libcompose")) {
		t.Errorf("libcompose should not be reported: %s", out)
	}

	tmpFileName := "vendor.conf.tmp"
	tmpConfig := filepath.Join(repoDir, tmpFileName)
	if _, err := os.Stat(tmpConfig); err != nil {
		t.Fatalf("error stat %s: %v", tmpFileName, err)
	}
	b, err := ioutil.ReadFile(tmpConfig)
	if err != nil {
		t.Fatal(err)
	}
	expected := []byte(`github.com/docker/docker branch
github.com/coreos/etcd branch
github.com/docker/swarmkit branch
github.com/docker/go branch
github.com/docker/go-connections branch
github.com/docker/go-units branch
github.com/docker/libcompose branch
`)
	if !bytes.Equal(b, expected) {
		t.Fatalf("suggested vendor.conf is wrong:\n%s\n Should be %s", b, expected)
	}
}

func TestCleanWhitelist(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	content := []byte(`github.com/containers/image master
github.com/projectatomic/skopeo master`)
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin,
		"-whitelist", `github\.com/containers/image/MAINTAINERS`,
		"-whitelist", `github\.com/projectatomic/skopeo/integration/.*`)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err := vndrCmd.CombinedOutput()
	if err != nil {
		t.Logf("output: %v", string(out))
		t.Fatalf("error was not expected: %v", err)
	}

	if !bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/containers/image/MAINTAINERS`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`output missing regular expression "github\.com/containers/image/MAINTAINERS"`)
	}
	if !bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/projectatomic/skopeo/integration/.*`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`output missing regular expression "github\.com/projectatomic/skopeo/integration/.*"`)
	}

	// Make sure that the files were not "cleaned".
	for _, path := range []string{
		"github.com/containers/image/MAINTAINERS",
		"github.com/projectatomic/skopeo/integration",
	} {
		path = filepath.Join(repoDir, "vendor", path)
		if _, err := os.Lstat(path); err != nil {
			t.Errorf("%s was cleaned but shouldn't have been", path)
		}
	}

	// Run again to make sure the above will be cleaned.
	vndrCmd = exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Logf("output: %v", string(out))
		t.Fatalf("[no -whitelist] error was not expected: %v", err)
	}

	if bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/containers/image/MAINTAINERS`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`[no -whitelist] output missing regular expression "github\.com/containers/image/MAINTAINERS"`)
	}
	if bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/projectatomic/skopeo/integration/.*`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`[no -whitelist] output missing regular expression "github\.com/projectatomic/skopeo/integration/.*"`)
	}

	// Make sure that the files were "cleaned".
	for _, path := range []string{
		"github.com/containers/image/MAINTAINERS",
		"github.com/projectatomic/skopeo/integration",
	} {
		path = filepath.Join(repoDir, "vendor", path)
		if _, err := os.Lstat(path); err == nil {
			t.Errorf("[no -whitelist] %s was NOT cleaned but should have been", path)
		}
	}
}

func TestUnused(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	unusedPkg := "github.com/docker/go-units"
	content := []byte(unusedPkg + " master\n")
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	msg := fmt.Sprintf("WARNING: package %s is unused, consider removing it from vendor.conf", unusedPkg)
	out, err := vndrCmd.CombinedOutput()
	if !bytes.Contains(out, []byte(msg)) {
		t.Logf("output: %v", string(out))
		t.Errorf("there is no warning about unused package %s", unusedPkg)
	}
}
<commit_msg>skip some tests on `go test -short`<commit_after>package vndrtest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

const testRepo = "github.com/docker/swarmkit"

func setGopath(cmd *exec.Cmd, gopath string) {
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, "GOPATH=") {
			continue
		}
		cmd.Env = append(cmd.Env, env)
	}
	cmd.Env = append(cmd.Env, "GOPATH="+gopath)
}

func skipOnShort(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}
}

func TestVndr(t *testing.T) {
	skipOnShort(t)
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}

	gitCmd := exec.Command("git", "clone", "https://"+testRepo+".git", repoDir)
	out, err := gitCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("failed to clone %s to %s: %v, out: %s", testRepo, repoDir, err, out)
	}
	if err := os.RemoveAll(filepath.Join(repoDir, "vendor")); err != nil {
		t.Fatal(err)
	}

	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}

	installCmd := exec.Command("go", "install", testRepo)
	setGopath(installCmd, tmp)
	out, err = installCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("install %s failed: %v, out: %s", testRepo, err, out)
	}

	// revendor only etcd
	vndrRevendorCmd := exec.Command(vndrBin, "github.com/coreos/etcd")
	vndrRevendorCmd.Dir = repoDir
	setGopath(vndrRevendorCmd, tmp)

	out, err = vndrRevendorCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}
}

func TestVndrInit(t *testing.T) {
	skipOnShort(t)
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoPath := "github.com/LK4D4"
	repoDir := filepath.Join(tmp, "src", repoPath)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}

	cpCmd := exec.Command("cp", "-r", "./testdata/dumbproject", repoDir)
	out, err := cpCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("cp failed: %v, out: %s", err, out)
	}
	vndrCmd := exec.Command(vndrBin, "init")
	vndrCmd.Dir = filepath.Join(repoDir, "dumbproject")
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("vndr failed: %v, out: %s", err, out)
	}
	if !bytes.Contains(out, []byte("Success")) {
		t.Fatalf("Output did not report success: %s", out)
	}

	pkgPath := filepath.Join(repoPath, "dumbproject")
	installCmd := exec.Command("go", "install", pkgPath)
	setGopath(installCmd, tmp)
	out, err = installCmd.CombinedOutput()
	if err != nil {
		t.Fatalf("install %s failed: %v, out: %s", pkgPath, err, out)
	}
	vndr2Cmd := exec.Command(vndrBin, "init")
	vndr2Cmd.Dir = filepath.Join(repoDir, "dumbproject")
	setGopath(vndr2Cmd, tmp)

	out, err = vndr2Cmd.CombinedOutput()
	if err == nil || !bytes.Contains(out, []byte("There must not be")) {
		t.Fatalf("vndr is expected to fail about existing vendor, got %v: %s", err, out)
	}
}

func TestValidateSubpackages(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	content := []byte(`github.com/docker/docker branch
github.com/docker/docker/pkg/idtools branch
github.com/coreos/etcd/raft branch
github.com/docker/docker/pkg/archive branch
github.com/coreos/etcd branch
github.com/docker/swarmkit branch
github.com/docker/go branch
github.com/docker/go-connections branch
github.com/docker/go-units branch
github.com/docker/libcompose branch
github.com/docker/swarmkit branch
`)
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err := vndrCmd.CombinedOutput()
	if err == nil {
		t.Fatal("error is expected")
	}
	t.Logf("Output of vndr:\n%s", out)
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/docker/docker, github.com/docker/docker/pkg/idtools, github.com/docker/docker/pkg/archive' has same root import github.com/docker/docker")) {
		t.Error("duplicated docker package not found")
	}
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/coreos/etcd/raft, github.com/coreos/etcd' has same root import github.com/coreos/etcd")) {
		t.Error("duplicated etcd package not found")
	}
	if !bytes.Contains(out, []byte("WARNING: packages 'github.com/docker/swarmkit, github.com/docker/swarmkit' has same root import github.com/docker/swarmkit")) {
		t.Error("duplicated swarmkit package not found")
	}
	if bytes.Contains(out, []byte("go-units")) {
		t.Errorf("go-units should not be reported: %s", out)
	}
	if bytes.Contains(out, []byte("go-connections")) {
		t.Errorf("go-connections should not be reported: %s", out)
	}
	if bytes.Contains(out, []byte("libcompose")) {
		t.Errorf("libcompose should not be reported: %s", out)
	}

	tmpFileName := "vendor.conf.tmp"
	tmpConfig := filepath.Join(repoDir, tmpFileName)
	if _, err := os.Stat(tmpConfig); err != nil {
		t.Fatalf("error stat %s: %v", tmpFileName, err)
	}
	b, err := ioutil.ReadFile(tmpConfig)
	if err != nil {
		t.Fatal(err)
	}
	expected := []byte(`github.com/docker/docker branch
github.com/coreos/etcd branch
github.com/docker/swarmkit branch
github.com/docker/go branch
github.com/docker/go-connections branch
github.com/docker/go-units branch
github.com/docker/libcompose branch
`)
	if !bytes.Equal(b, expected) {
		t.Fatalf("suggested vendor.conf is wrong:\n%s\n Should be %s", b, expected)
	}
}

func TestCleanWhitelist(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	content := []byte(`github.com/containers/image master
github.com/projectatomic/skopeo master`)
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin,
		"-whitelist", `github\.com/containers/image/MAINTAINERS`,
		"-whitelist", `github\.com/projectatomic/skopeo/integration/.*`)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err := vndrCmd.CombinedOutput()
	if err != nil {
		t.Logf("output: %v", string(out))
		t.Fatalf("error was not expected: %v", err)
	}

	if !bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/containers/image/MAINTAINERS`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`output missing regular expression "github\.com/containers/image/MAINTAINERS"`)
	}
	if !bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/projectatomic/skopeo/integration/.*`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`output missing regular expression "github\.com/projectatomic/skopeo/integration/.*"`)
	}

	// Make sure that the files were not "cleaned".
	for _, path := range []string{
		"github.com/containers/image/MAINTAINERS",
		"github.com/projectatomic/skopeo/integration",
	} {
		path = filepath.Join(repoDir, "vendor", path)
		if _, err := os.Lstat(path); err != nil {
			t.Errorf("%s was cleaned but shouldn't have been", path)
		}
	}

	// Run again to make sure the above will be cleaned.
	vndrCmd = exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	out, err = vndrCmd.CombinedOutput()
	if err != nil {
		t.Logf("output: %v", string(out))
		t.Fatalf("[no -whitelist] error was not expected: %v", err)
	}

	if bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/containers/image/MAINTAINERS`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`[no -whitelist] output missing regular expression "github\.com/containers/image/MAINTAINERS"`)
	}
	if bytes.Contains(out, []byte(fmt.Sprintf(`Ignoring paths matching %q`, `github\.com/projectatomic/skopeo/integration/.*`))) {
		t.Logf("output: %v", string(out))
		t.Errorf(`[no -whitelist] output missing regular expression "github\.com/projectatomic/skopeo/integration/.*"`)
	}

	// Make sure that the files were "cleaned".
	for _, path := range []string{
		"github.com/containers/image/MAINTAINERS",
		"github.com/projectatomic/skopeo/integration",
	} {
		path = filepath.Join(repoDir, "vendor", path)
		if _, err := os.Lstat(path); err == nil {
			t.Errorf("[no -whitelist] %s was NOT cleaned but should have been", path)
		}
	}
}

func TestUnused(t *testing.T) {
	vndrBin, err := exec.LookPath("vndr")
	if err != nil {
		t.Fatal(err)
	}
	tmp, err := ioutil.TempDir("", "test-vndr-")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)
	repoDir := filepath.Join(tmp, "src", testRepo)
	if err := os.MkdirAll(repoDir, 0700); err != nil {
		t.Fatal(err)
	}
	unusedPkg := "github.com/docker/go-units"
	content := []byte(unusedPkg + " master\n")
	vendorConf := filepath.Join(repoDir, "vendor.conf")
	if err := ioutil.WriteFile(vendorConf, content, 0666); err != nil {
		t.Fatal(err)
	}
	vndrCmd := exec.Command(vndrBin)
	vndrCmd.Dir = repoDir
	setGopath(vndrCmd, tmp)

	msg := fmt.Sprintf("WARNING: package %s is unused, consider removing it from vendor.conf", unusedPkg)
	out, err := vndrCmd.CombinedOutput()
	if !bytes.Contains(out, []byte(msg)) {
		t.Logf("output: %v", string(out))
		t.Errorf("there is no warning about unused package %s", unusedPkg)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	ui "github.com/gizak/termui"
	"strings"
)

type TicketListPage struct {
	BaseListPage
}

func (p *TicketListPage) GetSelectedTicketId() string {
	return strings.Split(p.cachedResults[p.selectedLine], " ")[0]
}

func (p *TicketListPage) SelectItem() {
	previousPage = currentPage
	currentPage = &ticketShowPage
	changePage()
}

func (p *TicketListPage) GoBack() {
	previousPage = currentPage
	currentPage = &ticketQueryPage
	changePage()
}

func (p *TicketListPage) Create(opts ...interface{}) {
	ui.Clear()
	var label string
	var queryJQL string
	var queryName string
	if len(opts) > 0 {
		log.Noticef("TicketListPage.Create opts: %s", opts)
		if d, ok := opts[0].(map[string]string); ok {
			label = d["label"]
		}
	}
	ls := ui.NewList()
	p.uiList = ls
	p.selectedLine = 0
	p.firstDisplayLine = 0
	if label != "" {
		queryName = ticketQueryPage.SelectedQuery().Name + "+" + label
		queryJQL = ticketQueryPage.SelectedQuery().JQL + " AND labels = " + label
	} else {
		queryName = ticketQueryPage.SelectedQuery().Name
		queryJQL = ticketQueryPage.SelectedQuery().JQL
	}
	p.cachedResults = JiraQueryAsStrings(queryJQL)
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = fmt.Sprintf("%s: %s", queryName, queryJQL)
	ls.Height = ui.TermHeight()
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.Update()
}
<commit_msg>remove a debug log line<commit_after>package main

import (
	"fmt"
	ui "github.com/gizak/termui"
	"strings"
)

type TicketListPage struct {
	BaseListPage
}

func (p *TicketListPage) GetSelectedTicketId() string {
	return strings.Split(p.cachedResults[p.selectedLine], " ")[0]
}

func (p *TicketListPage) SelectItem() {
	previousPage = currentPage
	currentPage = &ticketShowPage
	changePage()
}

func (p *TicketListPage) GoBack() {
	previousPage = currentPage
	currentPage = &ticketQueryPage
	changePage()
}

func (p *TicketListPage) Create(opts ...interface{}) {
	ui.Clear()
	var label string
	var queryJQL string
	var queryName string
	if len(opts) > 0 {
		if d, ok := opts[0].(map[string]string); ok {
			label = d["label"]
		}
	}
	ls := ui.NewList()
	p.uiList = ls
	p.selectedLine = 0
	p.firstDisplayLine = 0
	if label != "" {
		queryName = ticketQueryPage.SelectedQuery().Name + "+" + label
		queryJQL = ticketQueryPage.SelectedQuery().JQL + " AND labels = " + label
	} else {
		queryName = ticketQueryPage.SelectedQuery().Name
		queryJQL = ticketQueryPage.SelectedQuery().JQL
	}
	p.cachedResults = JiraQueryAsStrings(queryJQL)
	p.displayLines = make([]string, len(p.cachedResults))
	ls.ItemFgColor = ui.ColorYellow
	ls.BorderLabel = fmt.Sprintf("%s: %s", queryName, queryJQL)
	ls.Height = ui.TermHeight()
	ls.Width = ui.TermWidth()
	ls.Y = 0
	p.Update()
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/ngaut/log"
	"github.com/pingcap/ticlient"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/metric"
	"github.com/pingcap/tidb/store/hbase"
	"github.com/pingcap/tidb/store/localstore/boltdb"
	"github.com/pingcap/tidb/tidb-server/server"
	"github.com/pingcap/tidb/util/printer"
)

var (
	store      = flag.String("store", "goleveldb", "registered store name, [memory, goleveldb, hbase, boltdb, tikv]")
	storePath  = flag.String("path", "/tmp/tidb", "tidb storage path")
	logLevel   = flag.String("L", "debug", "log level: info, debug, warn, error, fatal")
	port       = flag.String("P", "4000", "mp server port")
	statusPort = flag.String("status", "10080", "tidb server status port")
	lease      = flag.Int("lease", 1, "schema lease seconds, very dangerous to change only if you know what you do")
)

func main() {
	tidb.RegisterStore("hbase", hbasekv.Driver{})
	tidb.RegisterLocalStore("boltdb", boltdb.Driver{})
	tidb.RegisterStore("tikv", ticlient.Driver{})

	metric.RunMetric(3 * time.Second)
	printer.PrintTiDBInfo()
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Parse()

	if *lease < 0 {
		log.Fatalf("invalid lease seconds %d", *lease)
	}

	tidb.SetSchemaLease(time.Duration(*lease) * time.Second)

	cfg := &server.Config{
		Addr:       fmt.Sprintf(":%s", *port),
		LogLevel:   *logLevel,
		StatusAddr: fmt.Sprintf(":%s", *statusPort),
	}

	log.SetLevelByString(cfg.LogLevel)
	store, err := tidb.NewStore(fmt.Sprintf("%s://%s", *store, *storePath))
	if err != nil {
		log.Fatal(err)
	}

	var driver server.IDriver
	driver = server.NewTiDBDriver(store)
	var svr *server.Server
	svr, err = server.NewServer(cfg, driver)
	if err != nil {
		log.Fatal(err)
	}

	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	go func() {
		sig := <-sc
		log.Infof("Got signal [%d] to exit.", sig)
		svr.Close()
		os.Exit(0)
	}()

	log.Error(svr.Run())
}
<commit_msg>tide-server: create a session on startup. (#1086)<commit_after>// Copyright 2015 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/ticlient"
	"github.com/pingcap/tidb"
	"github.com/pingcap/tidb/metric"
	"github.com/pingcap/tidb/store/hbase"
	"github.com/pingcap/tidb/store/localstore/boltdb"
	"github.com/pingcap/tidb/tidb-server/server"
	"github.com/pingcap/tidb/util/printer"
)

var (
	store      = flag.String("store", "goleveldb", "registered store name, [memory, goleveldb, hbase, boltdb, tikv]")
	storePath  = flag.String("path", "/tmp/tidb", "tidb storage path")
	logLevel   = flag.String("L", "debug", "log level: info, debug, warn, error, fatal")
	port       = flag.String("P", "4000", "mp server port")
	statusPort = flag.String("status", "10080", "tidb server status port")
	lease      = flag.Int("lease", 1, "schema lease seconds, very dangerous to change only if you know what you do")
)

func main() {
	tidb.RegisterStore("hbase", hbasekv.Driver{})
	tidb.RegisterLocalStore("boltdb", boltdb.Driver{})
	tidb.RegisterStore("tikv", ticlient.Driver{})

	metric.RunMetric(3 * time.Second)
	printer.PrintTiDBInfo()
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Parse()

	if *lease < 0 {
		log.Fatalf("invalid lease seconds %d", *lease)
	}

	tidb.SetSchemaLease(time.Duration(*lease) * time.Second)

	cfg := &server.Config{
		Addr:       fmt.Sprintf(":%s", *port),
		LogLevel:   *logLevel,
		StatusAddr: fmt.Sprintf(":%s", *statusPort),
	}

	log.SetLevelByString(cfg.LogLevel)
	store, err := tidb.NewStore(fmt.Sprintf("%s://%s", *store, *storePath))
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}
	// Create a session to load information schema.
	se, err := tidb.CreateSession(store)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}
	se.Close()

	var driver server.IDriver
	driver = server.NewTiDBDriver(store)
	var svr *server.Server
	svr, err = server.NewServer(cfg, driver)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	go func() {
		sig := <-sc
		log.Infof("Got signal [%d] to exit.", sig)
		svr.Close()
		os.Exit(0)
	}()

	log.Error(svr.Run())
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"net"
	"os"
	"path/filepath"

	"github.com/concourse/concourse/atc/atccmd"
	"github.com/concourse/flag"
	"github.com/concourse/concourse/tsa/tsacmd"
	flags "github.com/jessevdk/go-flags"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/sigmon"

	"github.com/concourse/concourse/bin/bindata"
)

type WebCommand struct {
	*atccmd.RunCommand

	*tsacmd.TSACommand `group:"TSA Configuration" namespace:"tsa"`
}

const cliArtifactsBindata = "cli-artifacts"

func (WebCommand) lessenRequirements(command *flags.Command) {
	// defaults to address from external URL
	command.FindOptionByLongName("tsa-peer-ip").Required = false

	// defaults to atc external URL
	command.FindOptionByLongName("tsa-atc-url").Required = false

	// defaults to atc session signing key
	command.FindOptionByLongName("tsa-session-signing-key").Required = false
}

func (cmd *WebCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *WebCommand) Runner(args []string) (ifrit.Runner, error) {
	err := bindata.RestoreAssets(os.TempDir(), cliArtifactsBindata)
	if err == nil {
		cmd.RunCommand.CLIArtifactsDir = flag.Dir(filepath.Join(os.TempDir(), cliArtifactsBindata))
	}

	cmd.populateTSAFlagsFromATCFlags()

	atcRunner, shouldSkipTSA, err := cmd.RunCommand.Runner(args)
	if err != nil {
		return nil, err
	}

	if shouldSkipTSA {
		return atcRunner, nil
	}

	tsaRunner, err := cmd.TSACommand.Runner(args)
	if err != nil {
		return nil, err
	}

	return grouper.NewParallel(os.Interrupt, grouper.Members{
		{Name: "atc", Runner: atcRunner},
		{Name: "tsa", Runner: tsaRunner},
	}), nil
}

func (cmd *WebCommand) populateTSAFlagsFromATCFlags() error {
	cmd.TSACommand.SessionSigningKey = cmd.RunCommand.Auth.AuthFlags.SigningKey

	if cmd.RunCommand.Auth.AuthFlags.SigningKey.PrivateKey == nil &&
		cmd.TSACommand.SessionSigningKey.PrivateKey == nil {
		signingKey, err := rsa.GenerateKey(rand.Reader, 2048)
		if err != nil {
			return fmt.Errorf("failed to generate session signing key: %s", err)
		}

		cmd.RunCommand.Auth.AuthFlags.SigningKey = &flag.PrivateKey{PrivateKey: signingKey}
		cmd.TSACommand.SessionSigningKey = &flag.PrivateKey{PrivateKey: signingKey}
	}

	if len(cmd.TSACommand.ATCURLs) == 0 {
		cmd.TSACommand.ATCURLs = []flag.URL{cmd.RunCommand.PeerURLOrDefault()}
	}

	host, _, err := net.SplitHostPort(cmd.RunCommand.PeerURLOrDefault().URL.Host)
	if err != nil {
		return err
	}

	cmd.TSACommand.PeerIP = host

	return nil
}
<commit_msg>remove cli artifacts embedding<commit_after>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"net"
	"os"

	"github.com/concourse/concourse/atc/atccmd"
	"github.com/concourse/concourse/tsa/tsacmd"
	"github.com/concourse/flag"
	flags "github.com/jessevdk/go-flags"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/sigmon"
)

type WebCommand struct {
	*atccmd.RunCommand

	*tsacmd.TSACommand `group:"TSA Configuration" namespace:"tsa"`
}

func (WebCommand) lessenRequirements(command *flags.Command) {
	// defaults to address from external URL
	command.FindOptionByLongName("tsa-peer-ip").Required = false

	// defaults to atc external URL
	command.FindOptionByLongName("tsa-atc-url").Required = false

	// defaults to atc session signing key
	command.FindOptionByLongName("tsa-session-signing-key").Required = false
}

func (cmd *WebCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *WebCommand) Runner(args []string) (ifrit.Runner, error) {
	cmd.populateTSAFlagsFromATCFlags()

	atcRunner, shouldSkipTSA, err := cmd.RunCommand.Runner(args)
	if err != nil {
		return nil, err
	}

	if shouldSkipTSA {
		return atcRunner, nil
	}

	tsaRunner, err := cmd.TSACommand.Runner(args)
	if err != nil {
		return nil, err
	}

	return grouper.NewParallel(os.Interrupt, grouper.Members{
		{Name: "atc", Runner: atcRunner},
		{Name: "tsa", Runner: tsaRunner},
	}), nil
}

func (cmd *WebCommand) populateTSAFlagsFromATCFlags() error {
	cmd.TSACommand.SessionSigningKey = cmd.RunCommand.Auth.AuthFlags.SigningKey

	if cmd.RunCommand.Auth.AuthFlags.SigningKey.PrivateKey == nil &&
		cmd.TSACommand.SessionSigningKey.PrivateKey == nil {
		signingKey, err := rsa.GenerateKey(rand.Reader, 2048)
		if err != nil {
			return fmt.Errorf("failed to generate session signing key: %s", err)
		}

		cmd.RunCommand.Auth.AuthFlags.SigningKey = &flag.PrivateKey{PrivateKey: signingKey}
		cmd.TSACommand.SessionSigningKey = &flag.PrivateKey{PrivateKey: signingKey}
	}

	if len(cmd.TSACommand.ATCURLs) == 0 {
		cmd.TSACommand.ATCURLs = []flag.URL{cmd.RunCommand.PeerURLOrDefault()}
	}

	host, _, err := net.SplitHostPort(cmd.RunCommand.PeerURLOrDefault().URL.Host)
	if err != nil {
		return err
	}

	cmd.TSACommand.PeerIP = host

	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Rob Thornton
// All rights reserved.
// This source code is governed by a Simplied BSD-License. Please see the
// LICENSE included in this distribution for a copy of the full license
// or, if one is not included, you may also find a copy at
// http://opensource.org/licenses/BSD-2-Clause

package token_test

import (
	"testing"

	"github.com/rthornton128/calc/token"
)

var test_expr = "(+ 2 3)\n(- 5 4)"

func TestFilePosition(t *testing.T) {
	var tests = []struct {
		col, row int
		pos      token.Pos
	}{
		{1, 1, token.Pos(1)},
		{1, 2, token.Pos(8)},
		{7, 2, token.Pos(14)},
	}
	f := token.NewFile("", 1, 15)
	f.AddLine(token.Pos(1))
	p := f.Position(token.Pos(1))
	if p.String() != "1:1" {
		t.Fatal("Nameless file: Expected: 1:1, Got:", p.String())
	}

	f = token.NewFile("test.calc", 1, 15)
	f.AddLine(token.Pos(1))
	p = f.Position(token.Pos(1))
	if p.String() != "test.calc:1:1" {
		t.Fatal("Nameless file: Expected: test.calc:1:1, Got:", p.String())
	}

	f = token.NewFile("test", 1, len(test_expr))
	f.AddLine(token.Pos(7))
	f.AddLine(token.Pos(14))
	for _, v := range tests {
		p := f.Position(v.pos)
		if p.Col != v.col || p.Row != v.row {
			t.Fatal("For:", v.pos, "Expected:", v.col, "and", v.row, "Got:",
				p.Col, "and", p.Row)
		}
	}
}

func TestFileSetPosition(t *testing.T) {
	fs := token.NewFileSet()
	fs.Add("testA.calc", test_expr)
	fs.Add("testB.calc", test_expr)
}

func TestLookup(t *testing.T) {
	var tests = []struct {
		str string
		tok token.Token
	}{
		{"+", token.ADD},
		{"%", token.REM},
		{"EOF", token.EOF},
		{"Integer", token.INTEGER},
		{"Comment", token.COMMENT},
		{"", token.IDENT},
	}

	for i, v := range tests {
		if res := token.Lookup(v.str); res != v.tok {
			t.Fatal(i, "- Expected:", v.tok, "Got:", res)
		}
	}
}

func TestIsLiteral(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, false},
		{token.REM, false},
		{token.EOF, false},
		{token.IDENT, true},
		{token.INTEGER, true},
		{token.IDENT, true},
		{token.COMMENT, false},
		{token.VAR, false},
		{token.ASSIGN, false},
	}

	for _, v := range tests {
		if res := v.tok.IsLiteral(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestIsOperator(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, true},
		{token.REM, true},
		{token.EOF, false},
		{token.INTEGER, false},
		{token.COMMENT, false},
		{token.VAR, false},
		{token.ASSIGN, true},
	}

	for _, v := range tests {
		if res := v.tok.IsOperator(); res != v.exp {
			t.Fatal(int(v.tok), "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestIsKeyword(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, false},
		{token.REM, false},
		{token.EOF, false},
		{token.INTEGER, false},
		{token.COMMENT, false},
		{token.VAR, true},
		{token.ASSIGN, false},
	}

	for _, v := range tests {
		if res := v.tok.IsKeyword(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestString(t *testing.T) {
	var tests = []struct {
		str string
		tok token.Token
	}{
		{"+", token.ADD},
		{"%", token.REM},
		{"EOF", token.EOF},
		{"Integer", token.INTEGER},
		{"Comment", token.COMMENT},
	}

	for i, v := range tests {
		if res := v.tok.String(); res != v.str {
			t.Fatal(i, "- Expected:", v.str, "Got:", res)
		}
	}
}

func TestValid(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, true},
		{token.REM, true},
		{token.EOF, true},
		{token.INTEGER, true},
		{token.COMMENT, true},
		{token.Token(-1), false},
		{token.Token(999999), false},
	}

	for _, v := range tests {
		if res := v.tok.Valid(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}
<commit_msg>fix tests for removal of COMMENT token and change to AddLine<commit_after>// Copyright (c) 2014, Rob Thornton
// All rights reserved.
// This source code is governed by a Simplied BSD-License. Please see the
// LICENSE included in this distribution for a copy of the full license
// or, if one is not included, you may also find a copy at
// http://opensource.org/licenses/BSD-2-Clause

package token_test

import (
	"testing"

	"github.com/rthornton128/calc/token"
)

var test_expr = "(+ 2 3)\n(- 5 4)"

func TestFilePosition(t *testing.T) {
	var tests = []struct {
		col, row int
		pos      token.Pos
	}{
		{1, 1, token.Pos(1)},
		{1, 2, token.Pos(8)},
		{7, 2, token.Pos(14)},
	}
	f := token.NewFile("", 1, 15)
	f.AddLine(0)
	p := f.Position(token.Pos(1))
	if p.String() != "1:1" {
		t.Fatal("Nameless file: Expected: 1:1, Got:", p.String())
	}

	f = token.NewFile("test.calc", 1, 15)
	f.AddLine(0)
	p = f.Position(token.Pos(1))
	if p.String() != "test.calc:1:1" {
		t.Fatal("Nameless file: Expected: test.calc:1:1, Got:", p.String())
	}

	f = token.NewFile("test", 1, len(test_expr))
	f.AddLine(0)
	f.AddLine(6)
	for _, v := range tests {
		p := f.Position(v.pos)
		if p.Col != v.col || p.Row != v.row {
			t.Fatal("For:", v.pos, "Expected:", v.col, "and", v.row, "Got:",
				p.Col, "and", p.Row)
		}
	}
}

func TestFileSetPosition(t *testing.T) {
	fs := token.NewFileSet()
	fs.Add("testA.calc", test_expr)
	fs.Add("testB.calc", test_expr)
}

func TestLookup(t *testing.T) {
	var tests = []struct {
		str string
		tok token.Token
	}{
		{"+", token.ADD},
		{"%", token.REM},
		{"EOF", token.EOF},
		{"Integer", token.INTEGER},
		{"", token.IDENT},
	}

	for i, v := range tests {
		if res := token.Lookup(v.str); res != v.tok {
			t.Fatal(i, "- Expected:", v.tok, "Got:", res)
		}
	}
}

func TestIsLiteral(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, false},
		{token.REM, false},
		{token.EOF, false},
		{token.IDENT, true},
		{token.INTEGER, true},
		{token.IDENT, true},
		{token.VAR, false},
		{token.ASSIGN, false},
	}

	for _, v := range tests {
		if res := v.tok.IsLiteral(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestIsOperator(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, true},
		{token.REM, true},
		{token.EOF, false},
		{token.INTEGER, false},
		{token.VAR, false},
		{token.ASSIGN, true},
	}

	for _, v := range tests {
		if res := v.tok.IsOperator(); res != v.exp {
			t.Fatal(int(v.tok), "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestIsKeyword(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, false},
		{token.REM, false},
		{token.EOF, false},
		{token.INTEGER, false},
		{token.VAR, true},
		{token.ASSIGN, false},
	}

	for _, v := range tests {
		if res := v.tok.IsKeyword(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}

func TestString(t *testing.T) {
	var tests = []struct {
		str string
		tok token.Token
	}{
		{"+", token.ADD},
		{"%", token.REM},
		{"EOF", token.EOF},
		{"Integer", token.INTEGER},
	}

	for i, v := range tests {
		if res := v.tok.String(); res != v.str {
			t.Fatal(i, "- Expected:", v.str, "Got:", res)
		}
	}
}

func TestValid(t *testing.T) {
	var tests = []struct {
		tok token.Token
		exp bool
	}{
		{token.ADD, true},
		{token.REM, true},
		{token.EOF, true},
		{token.INTEGER, true},
		{token.Token(-1), false},
		{token.Token(999999), false},
	}

	for _, v := range tests {
		if res := v.tok.Valid(); res != v.exp {
			t.Fatal(v.tok, "- Expected:", v.exp, "Got:", res)
		}
	}
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

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

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

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

	devicefilter containes eBPF device filter program

	The implementation is based on https://github.com/containers/crun/blob/0.10.2/src/libcrun/ebpf.c

	Although ebpf.c is originally licensed under LGPL-3.0-or-later, the author (Giuseppe Scrivano)
	agreed to relicense the file in Apache License 2.0: https://github.com/opencontainers/runc/issues/2144#issuecomment-543116397

	This particular Go implementation based on runc version
	https://github.com/opencontainers/runc/blob/master/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
*/

package v2

import (
	"fmt"
	"github.com/opencontainers/runtime-spec/specs-go"
	"math"

	"github.com/cilium/ebpf/asm"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

const (
	// license string format is same as kernel MODULE_LICENSE macro
	license = "Apache"
)

// DeviceFilter returns eBPF device filter program and its license string
func DeviceFilter(devices []specs.LinuxDeviceCgroup) (asm.Instructions, string, error) {
	p := &program{}
	p.init()
	for i := len(devices) - 1; i >= 0; i-- {
		if err := p.appendDevice(devices[i]); err != nil {
			return nil, "", err
		}
	}
	insts, err := p.finalize()
	return insts, license, err
}

type program struct {
	insts       asm.Instructions
	hasWildCard bool
	blockID     int
}

func (p *program) init() {
	// struct bpf_cgroup_dev_ctx: https://elixir.bootlin.com/linux/v5.3.6/source/include/uapi/linux/bpf.h#L3423
	/*
		u32 access_type
		u32 major
		u32 minor
	*/
	// R2 <- type (lower 16 bit of u32 access_type at R1[0])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R2, asm.R1, 0, asm.Half))

	// R3 <- access (upper 16 bit of u32 access_type at R1[0])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R3, asm.R1, 0, asm.Word),
		// RSh: bitwise shift right
		asm.RSh.Imm32(asm.R3, 16))

	// R4 <- major (u32 major at R1[4])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R4, asm.R1, 4, asm.Word))

	// R5 <- minor (u32 minor at R1[8])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R5, asm.R1, 8, asm.Word))
}

// appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element.
func (p *program) appendDevice(dev specs.LinuxDeviceCgroup) error {
	if p.blockID < 0 {
		return errors.New("the program is finalized")
	}
	if p.hasWildCard {
		// All entries after wildcard entry are ignored
		return nil
	}

	bpfType := int32(-1)
	hasType := true
	switch dev.Type {
	case string('c'):
		bpfType = int32(unix.BPF_DEVCG_DEV_CHAR)
	case string('b'):
		bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK)
	case string('a'):
		hasType = false
	default:
		// if not specified in OCI json, typ is set to DeviceTypeAll
		return errors.Errorf("invalid DeviceType %q", dev.Type)
	}
	if *dev.Major > math.MaxUint32 {
		return errors.Errorf("invalid major %d", *dev.Major)
	}
	if *dev.Minor > math.MaxUint32 {
		return errors.Errorf("invalid minor %d", *dev.Major)
	}
	hasMajor := *dev.Major >= 0 // if not specified in OCI json, major is set to -1
	hasMinor := *dev.Minor >= 0
	bpfAccess := int32(0)
	for _, r := range dev.Access {
		switch r {
		case 'r':
			bpfAccess |= unix.BPF_DEVCG_ACC_READ
		case 'w':
			bpfAccess |= unix.BPF_DEVCG_ACC_WRITE
		case 'm':
			bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD
		default:
			return errors.Errorf("unknown device access %v", r)
		}
	}
	// If the access is rwm, skip the check.
	hasAccess := bpfAccess != (unix.BPF_DEVCG_ACC_READ | unix.BPF_DEVCG_ACC_WRITE | unix.BPF_DEVCG_ACC_MKNOD)

	blockSym := fmt.Sprintf("block-%d", p.blockID)
	nextBlockSym := fmt.Sprintf("block-%d", p.blockID+1)
	prevBlockLastIdx := len(p.insts) - 1
	if hasType {
		p.insts = append(p.insts,
			// if (R2 != bpfType) goto next
			asm.JNE.Imm(asm.R2, bpfType, nextBlockSym),
		)
	}
	if hasAccess {
		p.insts = append(p.insts,
			// if (R3 & bpfAccess == 0 /* use R1 as a temp var */) goto next
			asm.Mov.Reg32(asm.R1, asm.R3),
			asm.And.Imm32(asm.R1, bpfAccess),
			asm.JEq.Imm(asm.R1, 0, nextBlockSym),
		)
	}
	if hasMajor {
		p.insts = append(p.insts,
			// if (R4 != major) goto next
			asm.JNE.Imm(asm.R4, int32(*dev.Major), nextBlockSym),
		)
	}
	if hasMinor {
		p.insts = append(p.insts,
			// if (R5 != minor) goto next
			asm.JNE.Imm(asm.R5, int32(*dev.Minor), nextBlockSym),
		)
	}
	if !hasType && !hasAccess && !hasMajor && !hasMinor {
		p.hasWildCard = true
	}
	p.insts = append(p.insts, acceptBlock(dev.Allow)...)
	// set blockSym to the first instruction we added in this iteration
	p.insts[prevBlockLastIdx+1] = p.insts[prevBlockLastIdx+1].Sym(blockSym)
	p.blockID++
	return nil
}

func (p *program) finalize() (asm.Instructions, error) {
	if p.hasWildCard {
		// acceptBlock with asm.Return() is already inserted
		return p.insts, nil
	}
	blockSym := fmt.Sprintf("block-%d", p.blockID)
	p.insts = append(p.insts,
		// R0 <- 0
		asm.Mov.Imm32(asm.R0, 0).Sym(blockSym),
		asm.Return(),
	)
	p.blockID = -1
	return p.insts, nil
}

func acceptBlock(accept bool) asm.Instructions {
	v := int32(0)
	if accept {
		v = 1
	}
	return []asm.Instruction{
		// R0 <- v
		asm.Mov.Imm32(asm.R0, v),
		asm.Return(),
	}
}
<commit_msg>Header fix<commit_after>/*
   Copyright The containerd Authors.

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

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

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

package v2

import (
	"fmt"
	"github.com/opencontainers/runtime-spec/specs-go"
	"math"

	"github.com/cilium/ebpf/asm"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

/*
Devicefilter containes eBPF device filter program

The implementation is based on https://github.com/containers/crun/blob/0.10.2/src/libcrun/ebpf.c

Although ebpf.c is originally licensed under LGPL-3.0-or-later, the author (Giuseppe Scrivano)
agreed to relicense the file in Apache License 2.0: https://github.com/opencontainers/runc/issues/2144#issuecomment-543116397

This particular Go implementation based on runc version
https://github.com/opencontainers/runc/blob/master/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go
*/
const (
	// license string format is same as kernel MODULE_LICENSE macro
	license = "Apache"
)

// DeviceFilter returns eBPF device filter program and its license string
func DeviceFilter(devices []specs.LinuxDeviceCgroup) (asm.Instructions, string, error) {
	p := &program{}
	p.init()
	for i := len(devices) - 1; i >= 0; i-- {
		if err := p.appendDevice(devices[i]); err != nil {
			return nil, "", err
		}
	}
	insts, err := p.finalize()
	return insts, license, err
}

type program struct {
	insts       asm.Instructions
	hasWildCard bool
	blockID     int
}

func (p *program) init() {
	// struct bpf_cgroup_dev_ctx: https://elixir.bootlin.com/linux/v5.3.6/source/include/uapi/linux/bpf.h#L3423
	/*
		u32 access_type
		u32 major
		u32 minor
	*/
	// R2 <- type (lower 16 bit of u32 access_type at R1[0])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R2, asm.R1, 0, asm.Half))

	// R3 <- access (upper 16 bit of u32 access_type at R1[0])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R3, asm.R1, 0, asm.Word),
		// RSh: bitwise shift right
		asm.RSh.Imm32(asm.R3, 16))

	// R4 <- major (u32 major at R1[4])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R4, asm.R1, 4, asm.Word))

	// R5 <- minor (u32 minor at R1[8])
	p.insts = append(p.insts,
		asm.LoadMem(asm.R5, asm.R1, 8, asm.Word))
}

// appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element.
func (p *program) appendDevice(dev specs.LinuxDeviceCgroup) error {
	if p.blockID < 0 {
		return errors.New("the program is finalized")
	}
	if p.hasWildCard {
		// All entries after wildcard entry are ignored
		return nil
	}

	bpfType := int32(-1)
	hasType := true
	switch dev.Type {
	case string('c'):
		bpfType = int32(unix.BPF_DEVCG_DEV_CHAR)
	case string('b'):
		bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK)
	case string('a'):
		hasType = false
	default:
		// if not specified in OCI json, typ is set to DeviceTypeAll
		return errors.Errorf("invalid DeviceType %q", dev.Type)
	}
	if *dev.Major > math.MaxUint32 {
		return errors.Errorf("invalid major %d", *dev.Major)
	}
	if *dev.Minor > math.MaxUint32 {
		return errors.Errorf("invalid minor %d", *dev.Major)
	}
	hasMajor := *dev.Major >= 0 // if not specified in OCI json, major is set to -1
	hasMinor := *dev.Minor >= 0
	bpfAccess := int32(0)
	for _, r := range dev.Access {
		switch r {
		case 'r':
			bpfAccess |= unix.BPF_DEVCG_ACC_READ
		case 'w':
			bpfAccess |= unix.BPF_DEVCG_ACC_WRITE
		case 'm':
			bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD
		default:
			return errors.Errorf("unknown device access %v", r)
		}
	}
	// If the access is rwm, skip the check.
	hasAccess := bpfAccess != (unix.BPF_DEVCG_ACC_READ | unix.BPF_DEVCG_ACC_WRITE | unix.BPF_DEVCG_ACC_MKNOD)

	blockSym := fmt.Sprintf("block-%d", p.blockID)
	nextBlockSym := fmt.Sprintf("block-%d", p.blockID+1)
	prevBlockLastIdx := len(p.insts) - 1
	if hasType {
		p.insts = append(p.insts,
			// if (R2 != bpfType) goto next
			asm.JNE.Imm(asm.R2, bpfType, nextBlockSym),
		)
	}
	if hasAccess {
		p.insts = append(p.insts,
			// if (R3 & bpfAccess == 0 /* use R1 as a temp var */) goto next
			asm.Mov.Reg32(asm.R1, asm.R3),
			asm.And.Imm32(asm.R1, bpfAccess),
			asm.JEq.Imm(asm.R1, 0, nextBlockSym),
		)
	}
	if hasMajor {
		p.insts = append(p.insts,
			// if (R4 != major) goto next
			asm.JNE.Imm(asm.R4, int32(*dev.Major), nextBlockSym),
		)
	}
	if hasMinor {
		p.insts = append(p.insts,
			// if (R5 != minor) goto next
			asm.JNE.Imm(asm.R5, int32(*dev.Minor), nextBlockSym),
		)
	}
	if !hasType && !hasAccess && !hasMajor && !hasMinor {
		p.hasWildCard = true
	}
	p.insts = append(p.insts, acceptBlock(dev.Allow)...)
	// set blockSym to the first instruction we added in this iteration
	p.insts[prevBlockLastIdx+1] = p.insts[prevBlockLastIdx+1].Sym(blockSym)
	p.blockID++
	return nil
}

func (p *program) finalize() (asm.Instructions, error) {
	if p.hasWildCard {
		// acceptBlock with asm.Return() is already inserted
		return p.insts, nil
	}
	blockSym := fmt.Sprintf("block-%d", p.blockID)
	p.insts = append(p.insts,
		// R0 <- 0
		asm.Mov.Imm32(asm.R0, 0).Sym(blockSym),
		asm.Return(),
	)
	p.blockID = -1
	return p.insts, nil
}

func acceptBlock(accept bool) asm.Instructions {
	v := int32(0)
	if accept {
		v = 1
	}
	return []asm.Instruction{
		// R0 <- v
		asm.Mov.Imm32(asm.R0, v),
		asm.Return(),
	}
}
<|endoftext|>