<commit_before>// +build !js

package webrtc

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/pion/rtp"
	"github.com/pion/rtp/codecs"
	"github.com/pion/sdp/v2"
)

// PayloadTypes for the default codecs
const (
	DefaultPayloadTypePCMU = 0
	DefaultPayloadTypePCMA = 8
	DefaultPayloadTypeG722 = 9
	DefaultPayloadTypeOpus = 111
	DefaultPayloadTypeVP8  = 96
	DefaultPayloadTypeVP9  = 98
	DefaultPayloadTypeH264 = 102

	mediaNameAudio = "audio"
	mediaNameVideo = "video"
)

// MediaEngine defines the codecs supported by a PeerConnection
type MediaEngine struct {
	codecs []*RTPCodec
}

// RegisterCodec registers a codec to a media engine
func (m *MediaEngine) RegisterCodec(codec *RTPCodec) uint8 {
	// pion/webrtc#43
	m.codecs = append(m.codecs, codec)
	return codec.PayloadType
}

// RegisterDefaultCodecs is a helper that registers the default codecs supported by Pion WebRTC
func (m *MediaEngine) RegisterDefaultCodecs() {
	m.RegisterCodec(NewRTPPCMUCodec(DefaultPayloadTypePCMU, 8000))
	m.RegisterCodec(NewRTPPCMACodec(DefaultPayloadTypePCMA, 8000))
	m.RegisterCodec(NewRTPOpusCodec(DefaultPayloadTypeOpus, 48000))
	m.RegisterCodec(NewRTPG722Codec(DefaultPayloadTypeG722, 8000))
	m.RegisterCodec(NewRTPVP8Codec(DefaultPayloadTypeVP8, 90000))
	m.RegisterCodec(NewRTPH264Codec(DefaultPayloadTypeH264, 90000))
	m.RegisterCodec(NewRTPVP9Codec(DefaultPayloadTypeVP9, 90000))
}

// PopulateFromSDP finds all codecs in a session description and adds them to a MediaEngine, using dynamic
// payload types and parameters from the sdp.
func (m *MediaEngine) PopulateFromSDP(sd SessionDescription) error {
	sdp := sdp.SessionDescription{}
	if err := sdp.Unmarshal([]byte(sd.SDP)); err != nil {
		return err
	}

	for _, md := range sdp.MediaDescriptions {
		if md.MediaName.Media != mediaNameAudio && md.MediaName.Media != mediaNameVideo {
			continue
		}

		for _, format := range md.MediaName.Formats {
			pt, err := strconv.Atoi(format)
			if err != nil {
				return fmt.Errorf("format parse error")
			}

			payloadType := uint8(pt)
			payloadCodec, err := sdp.GetCodecForPayloadType(payloadType)
			if err != nil {
				return fmt.Errorf("could not find codec for payload type %d", payloadType)
			}

			var codec *RTPCodec
			clockRate := payloadCodec.ClockRate
			parameters := payloadCodec.Fmtp
			codecName := strings.ToUpper(payloadCodec.Name)
			switch codecName {
			case PCMU:
				codec = NewRTPPCMUCodec(payloadType, clockRate)
			case PCMA:
				codec = NewRTPPCMACodec(payloadType, clockRate)
			case G722:
				codec = NewRTPG722Codec(payloadType, clockRate)
			case Opus:
				codec = NewRTPOpusCodec(payloadType, clockRate)
			case VP8:
				codec = NewRTPVP8Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			case VP9:
				codec = NewRTPVP9Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			case H264:
				codec = NewRTPH264Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			default:
				// ignoring other codecs
				continue
			}
			m.RegisterCodec(codec)
		}
	}
	return nil
}

func (m *MediaEngine) getCodec(payloadType uint8) (*RTPCodec, error) {
	for _, codec := range m.codecs {
		if codec.PayloadType == payloadType {
			return codec, nil
		}
	}
	return nil, ErrCodecNotFound
}

func (m *MediaEngine) getCodecSDP(sdpCodec sdp.Codec) (*RTPCodec, error) {
	for _, codec := range m.codecs {
		if codec.Name == sdpCodec.Name &&
			codec.ClockRate == sdpCodec.ClockRate &&
			(sdpCodec.EncodingParameters == "" ||
				strconv.Itoa(int(codec.Channels)) == sdpCodec.EncodingParameters) &&
			codec.SDPFmtpLine == sdpCodec.Fmtp { // pion/webrtc#43
			return codec, nil
		}
	}
	return nil, ErrCodecNotFound
}

// GetCodecsByKind returns all codecs of a chosen kind in the codecs list
func (m *MediaEngine) GetCodecsByKind(kind RTPCodecType) []*RTPCodec {
	var codecs []*RTPCodec
	for _, codec := range m.codecs {
		if codec.Type == kind {
			codecs = append(codecs, codec)
		}
	}
	return codecs
}

// Names for the default codecs supported by Pion WebRTC
const (
	PCMU = "PCMU"
	PCMA = "PCMA"
	G722 = "G722"
	Opus = "OPUS"
	VP8  = "VP8"
	VP9  = "VP9"
	H264 = "H264"
)

// NewRTPPCMUCodec is a helper to create a PCMU codec
func NewRTPPCMUCodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		PCMU,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G711Payloader{})
	return c
}

// NewRTPPCMACodec is a helper to create a PCMA codec
func NewRTPPCMACodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		PCMA,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G711Payloader{})
	return c
}

// NewRTPG722Codec is a helper to create a G722 codec
func NewRTPG722Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		G722,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G722Payloader{})
	return c
}

// NewRTPOpusCodec is a helper to create an Opus codec
func NewRTPOpusCodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		Opus,
		clockrate,
		2, //According to RFC7587, Opus RTP streams must have exactly 2 channels.
		"minptime=10;useinbandfec=1",
		payloadType,
		&codecs.OpusPayloader{})
	return c
}

// NewRTPVP8Codec is a helper to create an VP8 codec
func NewRTPVP8Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		VP8,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.VP8Payloader{})
	return c
}

// NewRTPVP8CodecExt is a helper to create an VP8 codec
func NewRTPVP8CodecExt(payloadType uint8, clockrate uint32, rtcpfb []RTCPFeedback) *RTPCodec {
	c := NewRTPCodecExt(RTPCodecTypeVideo,
		VP8,
		clockrate,
		0,
		"",
		payloadType,
		rtcpfb,
		&codecs.VP8Payloader{})
	return c
}

// NewRTPVP9Codec is a helper to create an VP9 codec
func NewRTPVP9Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		VP9,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.VP9Payloader{})
	return c
}

// NewRTPH264Codec is a helper to create an H264 codec
func NewRTPH264Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		H264,
		clockrate,
		0,
		"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
		payloadType,
		&codecs.H264Payloader{})
	return c
}

// NewRTPH264CodecExt is a helper to create an H264 codec
func NewRTPH264CodecExt(payloadType uint8, clockrate uint32, rtcpfb []RTCPFeedback) *RTPCodec {
	c := NewRTPCodecExt(RTPCodecTypeVideo,
		H264,
		clockrate,
		0,
		"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
		payloadType,
		rtcpfb,
		&codecs.H264Payloader{})
	return c
}

// RTPCodecType determines the type of a codec
type RTPCodecType int

const (

	// RTPCodecTypeAudio indicates this is an audio codec
	RTPCodecTypeAudio RTPCodecType = iota + 1

	// RTPCodecTypeVideo indicates this is a video codec
	RTPCodecTypeVideo
)

func (t RTPCodecType) String() string {
	switch t {
	case RTPCodecTypeAudio:
		return "audio"
	case RTPCodecTypeVideo:
		return "video"
	default:
		return ErrUnknownType.Error()
	}
}

// NewRTPCodecType creates a RTPCodecType from a string
func NewRTPCodecType(r string) RTPCodecType {
	switch {
	case strings.EqualFold(r, "audio"):
		return RTPCodecTypeAudio
	case strings.EqualFold(r, "video"):
		return RTPCodecTypeVideo
	default:
		return RTPCodecType(0)
	}
}

// RTPCodec represents a codec supported by the PeerConnection
type RTPCodec struct {
	RTPCodecCapability
	Type        RTPCodecType
	Name        string
	PayloadType uint8
	Payloader   rtp.Payloader
}

// NewRTPCodec is used to define a new codec
func NewRTPCodec(
	codecType RTPCodecType,
	name string,
	clockrate uint32,
	channels uint16,
	fmtp string,
	payloadType uint8,
	payloader rtp.Payloader,
) *RTPCodec {
	return &RTPCodec{
		RTPCodecCapability: RTPCodecCapability{
			MimeType:    codecType.String() + "/" + name,
			ClockRate:   clockrate,
			Channels:    channels,
			SDPFmtpLine: fmtp,
		},
		PayloadType: payloadType,
		Payloader:   payloader,
		Type:        codecType,
		Name:        name,
	}
}

// NewRTPCodecExt is used to define a new codec
func NewRTPCodecExt(
	codecType RTPCodecType,
	name string,
	clockrate uint32,
	channels uint16,
	fmtp string,
	payloadType uint8,
	rtcpfb []RTCPFeedback,
	payloader rtp.Payloader,
) *RTPCodec {
	return &RTPCodec{
		RTPCodecCapability: RTPCodecCapability{
			MimeType:     codecType.String() + "/" + name,
			ClockRate:    clockrate,
			Channels:     channels,
			SDPFmtpLine:  fmtp,
			RTCPFeedback: rtcpfb,
		},
		PayloadType: payloadType,
		Payloader:   payloader,
		Type:        codecType,
		Name:        name,
	}
}

// RTPCodecCapability provides information about codec capabilities.
type RTPCodecCapability struct {
	MimeType     string
	ClockRate    uint32
	Channels     uint16
	SDPFmtpLine  string
	RTCPFeedback []RTCPFeedback
}

// RTPHeaderExtensionCapability is used to define a RFC5285 RTP header extension supported by the codec.
type RTPHeaderExtensionCapability struct {
	URI string
}

// RTPCapabilities represents the capabilities of a transceiver
type RTPCapabilities struct {
	Codecs           []RTPCodecCapability
	HeaderExtensions []RTPHeaderExtensionCapability
}
<commit_msg>Prefer Opus over G711<commit_after>// +build !js

package webrtc

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/pion/rtp"
	"github.com/pion/rtp/codecs"
	"github.com/pion/sdp/v2"
)

// PayloadTypes for the default codecs
const (
	DefaultPayloadTypePCMU = 0
	DefaultPayloadTypePCMA = 8
	DefaultPayloadTypeG722 = 9
	DefaultPayloadTypeOpus = 111
	DefaultPayloadTypeVP8  = 96
	DefaultPayloadTypeVP9  = 98
	DefaultPayloadTypeH264 = 102

	mediaNameAudio = "audio"
	mediaNameVideo = "video"
)

// MediaEngine defines the codecs supported by a PeerConnection
type MediaEngine struct {
	codecs []*RTPCodec
}

// RegisterCodec registers a codec to a media engine
func (m *MediaEngine) RegisterCodec(codec *RTPCodec) uint8 {
	// pion/webrtc#43
	m.codecs = append(m.codecs, codec)
	return codec.PayloadType
}

// RegisterDefaultCodecs is a helper that registers the default codecs supported by Pion WebRTC
func (m *MediaEngine) RegisterDefaultCodecs() {
	// Audio Codecs in order of preference
	m.RegisterCodec(NewRTPOpusCodec(DefaultPayloadTypeOpus, 48000))
	m.RegisterCodec(NewRTPPCMUCodec(DefaultPayloadTypePCMU, 8000))
	m.RegisterCodec(NewRTPPCMACodec(DefaultPayloadTypePCMA, 8000))
	m.RegisterCodec(NewRTPG722Codec(DefaultPayloadTypeG722, 8000))

	// Video Codecs in order of preference
	m.RegisterCodec(NewRTPVP8Codec(DefaultPayloadTypeVP8, 90000))
	m.RegisterCodec(NewRTPVP9Codec(DefaultPayloadTypeVP9, 90000))
	m.RegisterCodec(NewRTPH264Codec(DefaultPayloadTypeH264, 90000))
}

// PopulateFromSDP finds all codecs in a session description and adds them to a MediaEngine, using dynamic
// payload types and parameters from the sdp.
func (m *MediaEngine) PopulateFromSDP(sd SessionDescription) error {
	sdp := sdp.SessionDescription{}
	if err := sdp.Unmarshal([]byte(sd.SDP)); err != nil {
		return err
	}

	for _, md := range sdp.MediaDescriptions {
		if md.MediaName.Media != mediaNameAudio && md.MediaName.Media != mediaNameVideo {
			continue
		}

		for _, format := range md.MediaName.Formats {
			pt, err := strconv.Atoi(format)
			if err != nil {
				return fmt.Errorf("format parse error")
			}

			payloadType := uint8(pt)
			payloadCodec, err := sdp.GetCodecForPayloadType(payloadType)
			if err != nil {
				return fmt.Errorf("could not find codec for payload type %d", payloadType)
			}

			var codec *RTPCodec
			clockRate := payloadCodec.ClockRate
			parameters := payloadCodec.Fmtp
			codecName := strings.ToUpper(payloadCodec.Name)
			switch codecName {
			case PCMU:
				codec = NewRTPPCMUCodec(payloadType, clockRate)
			case PCMA:
				codec = NewRTPPCMACodec(payloadType, clockRate)
			case G722:
				codec = NewRTPG722Codec(payloadType, clockRate)
			case Opus:
				codec = NewRTPOpusCodec(payloadType, clockRate)
			case VP8:
				codec = NewRTPVP8Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			case VP9:
				codec = NewRTPVP9Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			case H264:
				codec = NewRTPH264Codec(payloadType, clockRate)
				codec.SDPFmtpLine = parameters
			default:
				// ignoring other codecs
				continue
			}
			m.RegisterCodec(codec)
		}
	}
	return nil
}

func (m *MediaEngine) getCodec(payloadType uint8) (*RTPCodec, error) {
	for _, codec := range m.codecs {
		if codec.PayloadType == payloadType {
			return codec, nil
		}
	}
	return nil, ErrCodecNotFound
}

func (m *MediaEngine) getCodecSDP(sdpCodec sdp.Codec) (*RTPCodec, error) {
	for _, codec := range m.codecs {
		if codec.Name == sdpCodec.Name &&
			codec.ClockRate == sdpCodec.ClockRate &&
			(sdpCodec.EncodingParameters == "" ||
				strconv.Itoa(int(codec.Channels)) == sdpCodec.EncodingParameters) &&
			codec.SDPFmtpLine == sdpCodec.Fmtp { // pion/webrtc#43
			return codec, nil
		}
	}
	return nil, ErrCodecNotFound
}

// GetCodecsByKind returns all codecs of a chosen kind in the codecs list
func (m *MediaEngine) GetCodecsByKind(kind RTPCodecType) []*RTPCodec {
	var codecs []*RTPCodec
	for _, codec := range m.codecs {
		if codec.Type == kind {
			codecs = append(codecs, codec)
		}
	}
	return codecs
}

// Names for the default codecs supported by Pion WebRTC
const (
	PCMU = "PCMU"
	PCMA = "PCMA"
	G722 = "G722"
	Opus = "OPUS"
	VP8  = "VP8"
	VP9  = "VP9"
	H264 = "H264"
)

// NewRTPPCMUCodec is a helper to create a PCMU codec
func NewRTPPCMUCodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		PCMU,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G711Payloader{})
	return c
}

// NewRTPPCMACodec is a helper to create a PCMA codec
func NewRTPPCMACodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		PCMA,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G711Payloader{})
	return c
}

// NewRTPG722Codec is a helper to create a G722 codec
func NewRTPG722Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		G722,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.G722Payloader{})
	return c
}

// NewRTPOpusCodec is a helper to create an Opus codec
func NewRTPOpusCodec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeAudio,
		Opus,
		clockrate,
		2, //According to RFC7587, Opus RTP streams must have exactly 2 channels.
		"minptime=10;useinbandfec=1",
		payloadType,
		&codecs.OpusPayloader{})
	return c
}

// NewRTPVP8Codec is a helper to create an VP8 codec
func NewRTPVP8Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		VP8,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.VP8Payloader{})
	return c
}

// NewRTPVP8CodecExt is a helper to create an VP8 codec
func NewRTPVP8CodecExt(payloadType uint8, clockrate uint32, rtcpfb []RTCPFeedback) *RTPCodec {
	c := NewRTPCodecExt(RTPCodecTypeVideo,
		VP8,
		clockrate,
		0,
		"",
		payloadType,
		rtcpfb,
		&codecs.VP8Payloader{})
	return c
}

// NewRTPVP9Codec is a helper to create an VP9 codec
func NewRTPVP9Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		VP9,
		clockrate,
		0,
		"",
		payloadType,
		&codecs.VP9Payloader{})
	return c
}

// NewRTPH264Codec is a helper to create an H264 codec
func NewRTPH264Codec(payloadType uint8, clockrate uint32) *RTPCodec {
	c := NewRTPCodec(RTPCodecTypeVideo,
		H264,
		clockrate,
		0,
		"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
		payloadType,
		&codecs.H264Payloader{})
	return c
}

// NewRTPH264CodecExt is a helper to create an H264 codec
func NewRTPH264CodecExt(payloadType uint8, clockrate uint32, rtcpfb []RTCPFeedback) *RTPCodec {
	c := NewRTPCodecExt(RTPCodecTypeVideo,
		H264,
		clockrate,
		0,
		"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
		payloadType,
		rtcpfb,
		&codecs.H264Payloader{})
	return c
}

// RTPCodecType determines the type of a codec
type RTPCodecType int

const (

	// RTPCodecTypeAudio indicates this is an audio codec
	RTPCodecTypeAudio RTPCodecType = iota + 1

	// RTPCodecTypeVideo indicates this is a video codec
	RTPCodecTypeVideo
)

func (t RTPCodecType) String() string {
	switch t {
	case RTPCodecTypeAudio:
		return "audio"
	case RTPCodecTypeVideo:
		return "video"
	default:
		return ErrUnknownType.Error()
	}
}

// NewRTPCodecType creates a RTPCodecType from a string
func NewRTPCodecType(r string) RTPCodecType {
	switch {
	case strings.EqualFold(r, "audio"):
		return RTPCodecTypeAudio
	case strings.EqualFold(r, "video"):
		return RTPCodecTypeVideo
	default:
		return RTPCodecType(0)
	}
}

// RTPCodec represents a codec supported by the PeerConnection
type RTPCodec struct {
	RTPCodecCapability
	Type        RTPCodecType
	Name        string
	PayloadType uint8
	Payloader   rtp.Payloader
}

// NewRTPCodec is used to define a new codec
func NewRTPCodec(
	codecType RTPCodecType,
	name string,
	clockrate uint32,
	channels uint16,
	fmtp string,
	payloadType uint8,
	payloader rtp.Payloader,
) *RTPCodec {
	return &RTPCodec{
		RTPCodecCapability: RTPCodecCapability{
			MimeType:    codecType.String() + "/" + name,
			ClockRate:   clockrate,
			Channels:    channels,
			SDPFmtpLine: fmtp,
		},
		PayloadType: payloadType,
		Payloader:   payloader,
		Type:        codecType,
		Name:        name,
	}
}

// NewRTPCodecExt is used to define a new codec
func NewRTPCodecExt(
	codecType RTPCodecType,
	name string,
	clockrate uint32,
	channels uint16,
	fmtp string,
	payloadType uint8,
	rtcpfb []RTCPFeedback,
	payloader rtp.Payloader,
) *RTPCodec {
	return &RTPCodec{
		RTPCodecCapability: RTPCodecCapability{
			MimeType:     codecType.String() + "/" + name,
			ClockRate:    clockrate,
			Channels:     channels,
			SDPFmtpLine:  fmtp,
			RTCPFeedback: rtcpfb,
		},
		PayloadType: payloadType,
		Payloader:   payloader,
		Type:        codecType,
		Name:        name,
	}
}

// RTPCodecCapability provides information about codec capabilities.
type RTPCodecCapability struct {
	MimeType     string
	ClockRate    uint32
	Channels     uint16
	SDPFmtpLine  string
	RTCPFeedback []RTCPFeedback
}

// RTPHeaderExtensionCapability is used to define a RFC5285 RTP header extension supported by the codec.
type RTPHeaderExtensionCapability struct {
	URI string
}

// RTPCapabilities represents the capabilities of a transceiver
type RTPCapabilities struct {
	Codecs           []RTPCodecCapability
	HeaderExtensions []RTPHeaderExtensionCapability
}
<|endoftext|>


<commit_before>/*
Copyright 2020 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 (
	"errors"
	"fmt"

	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vterrors"
	"vitess.io/vitess/go/vt/vtgate/engine"
)

// planFilter solves this particular expression, either by pushing it down to a child or changing this logicalPlan
func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, whereType string, origin logicalPlan) (logicalPlan, error) {
	switch node := input.(type) {
	case *join:
		isLeft := true
		var in logicalPlan
		if node.isOnLeft(origin.Order()) {
			in = node.Left
		} else {
			if node.ejoin.Opcode == engine.LeftJoin {
				return nil, errors.New("unsupported: cross-shard left join and where clause")
			}
			isLeft = false
			in = node.Right
		}

		filtered, err := planFilter(pb, in, filter, whereType, origin)
		if err != nil {
			return nil, err
		}
		if isLeft {
			node.Left = filtered
		} else {
			node.Right = filtered
		}
		return node, nil

	case *route:
		sel := node.Select.(*sqlparser.Select)
		switch whereType {
		case sqlparser.WhereStr:
			sel.AddWhere(filter)
		case sqlparser.HavingStr:
			sel.AddHaving(filter)
		}
		node.UpdatePlan(pb, filter)
		return node, nil
	case *pulloutSubquery:
		plan, err := planFilter(pb, node.underlying, filter, whereType, origin)
		node.underlying = plan
		return node, err
	case *vindexFunc:
		return filterVindexFunc(node, filter)
	case *subquery:
		return nil, errors.New("unsupported: filtering on results of cross-shard subquery")
	case *orderedAggregate:
		return nil, errors.New("unsupported: filtering on results of aggregates")
	}

	return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "[BUG] unreachable %T.filtering", input)
}

func filterVindexFunc(node *vindexFunc, filter sqlparser.Expr) (logicalPlan, error) {
	if node.eVindexFunc.Opcode != engine.VindexNone {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (multiple filters)")
	}

	// Check LHS.
	comparison, ok := filter.(*sqlparser.ComparisonExpr)
	if !ok {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (not a comparison)")
	}
	if comparison.Operator != sqlparser.EqualOp {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (not equality)")
	}
	colname, ok := comparison.Left.(*sqlparser.ColName)
	if !ok {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (lhs is not a column)")
	}
	if !colname.Name.EqualString("id") {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (lhs is not id)")
	}

	// Check RHS.
	// We have to check before calling NewPlanValue because NewPlanValue allows lists also.
	if !sqlparser.IsValue(comparison.Right) {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (rhs is not a value)")
	}
	var err error
	node.eVindexFunc.Value, err = sqlparser.NewPlanValue(comparison.Right)
	if err != nil {
		return nil, fmt.Errorf("unsupported: where clause for vindex function must be of the form id = <val>: %v", err)
	}
	node.eVindexFunc.Opcode = engine.VindexMap
	return node, nil
}
<commit_msg>check error before returning<commit_after>/*
Copyright 2020 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 (
	"errors"
	"fmt"

	"vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vterrors"
	"vitess.io/vitess/go/vt/vtgate/engine"
)

// planFilter solves this particular expression, either by pushing it down to a child or changing this logicalPlan
func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, whereType string, origin logicalPlan) (logicalPlan, error) {
	switch node := input.(type) {
	case *join:
		isLeft := true
		var in logicalPlan
		if node.isOnLeft(origin.Order()) {
			in = node.Left
		} else {
			if node.ejoin.Opcode == engine.LeftJoin {
				return nil, errors.New("unsupported: cross-shard left join and where clause")
			}
			isLeft = false
			in = node.Right
		}

		filtered, err := planFilter(pb, in, filter, whereType, origin)
		if err != nil {
			return nil, err
		}
		if isLeft {
			node.Left = filtered
		} else {
			node.Right = filtered
		}
		return node, nil

	case *route:
		sel := node.Select.(*sqlparser.Select)
		switch whereType {
		case sqlparser.WhereStr:
			sel.AddWhere(filter)
		case sqlparser.HavingStr:
			sel.AddHaving(filter)
		}
		node.UpdatePlan(pb, filter)
		return node, nil
	case *pulloutSubquery:
		plan, err := planFilter(pb, node.underlying, filter, whereType, origin)
		if err != nil {
			return nil, err
		}
		node.underlying = plan
		return node, nil
	case *vindexFunc:
		return filterVindexFunc(node, filter)
	case *subquery:
		return nil, errors.New("unsupported: filtering on results of cross-shard subquery")
	case *orderedAggregate:
		return nil, errors.New("unsupported: filtering on results of aggregates")
	}

	return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "[BUG] unreachable %T.filtering", input)
}

func filterVindexFunc(node *vindexFunc, filter sqlparser.Expr) (logicalPlan, error) {
	if node.eVindexFunc.Opcode != engine.VindexNone {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (multiple filters)")
	}

	// Check LHS.
	comparison, ok := filter.(*sqlparser.ComparisonExpr)
	if !ok {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (not a comparison)")
	}
	if comparison.Operator != sqlparser.EqualOp {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (not equality)")
	}
	colname, ok := comparison.Left.(*sqlparser.ColName)
	if !ok {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (lhs is not a column)")
	}
	if !colname.Name.EqualString("id") {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (lhs is not id)")
	}

	// Check RHS.
	// We have to check before calling NewPlanValue because NewPlanValue allows lists also.
	if !sqlparser.IsValue(comparison.Right) {
		return nil, errors.New("unsupported: where clause for vindex function must be of the form id = <val> (rhs is not a value)")
	}
	var err error
	node.eVindexFunc.Value, err = sqlparser.NewPlanValue(comparison.Right)
	if err != nil {
		return nil, fmt.Errorf("unsupported: where clause for vindex function must be of the form id = <val>: %v", err)
	}
	node.eVindexFunc.Opcode = engine.VindexMap
	return node, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"fmt"
	"regexp"

	"github.com/google/mtail/metrics"
)

// compiler is data for the code generator.
type codegen struct {
	name string // Name of the program.

	errors ErrorList // Compile errors.
	obj    object    // The object to return

	decos []*decoNode // Decorator stack to unwind
}

// CodeGen is the function that compiles the program to bytecode and data.
func CodeGen(name string, ast node) (*object, error) {
	c := &codegen{name: name}
	Walk(c, ast)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	return &c.obj, nil
}

func (c *codegen) errorf(format string, args ...interface{}) {
	e := fmt.Sprintf(format, args...)
	c.errors.Add(position{filename: c.name}, e)
}

func (c *codegen) emit(i instr) {
	c.obj.prog = append(c.obj.prog, i)
}

func (c *codegen) VisitBefore(node node) Visitor {
	switch n := node.(type) {

	case *declNode:
		// Build the list of addressable metrics for this program, and set the symbol's address.
		n.sym.addr = len(c.obj.m)
		c.obj.m = append(c.obj.m, n.sym.binding.(*metrics.Metric))
		return nil

	case *condNode:
		if n.cond != nil {
			Walk(c, n.cond)
		}
		// Save PC of previous jump instruction emitted by the n.cond
		// compilation.  (See regexNode and relNode cases, which will emit a
		// jump as the last instr.)  This jump will skip over the truthNode.
		pc := len(c.obj.prog) - 1
		// Set matched flag false for children.
		c.emit(instr{setmatched, false})
		Walk(c, n.truthNode)
		// Re-set matched flag to true for rest of current block.
		c.emit(instr{setmatched, true})
		// Rewrite n.cond's jump target to jump to instruction after block.
		c.obj.prog[pc].opnd = len(c.obj.prog)
		// Now also emit the else clause, and a jump.
		if n.elseNode != nil {
			c.emit(instr{op: jmp})
			// Rewrite jump again to avoid this else-skipper just emitted.
			c.obj.prog[pc].opnd = len(c.obj.prog)
			// Now get the PC of the else-skipper just emitted.
			pc = len(c.obj.prog) - 1
			Walk(c, n.elseNode)
			// Rewrite else-skipper to the next PC.
			c.obj.prog[pc].opnd = len(c.obj.prog)
		}
		return nil

	case *regexNode:
		re, err := regexp.Compile(n.pattern)
		if err != nil {
			c.errorf("%s", err)
			return nil
		}
		c.obj.re = append(c.obj.re, re)
		// Store the location of this regular expression in the regexNode
		n.addr = len(c.obj.re) - 1
		c.emit(instr{match, n.addr})
		c.emit(instr{op: jnm})

	case *stringConstNode:
		c.obj.str = append(c.obj.str, n.text)
		c.emit(instr{str, len(c.obj.str) - 1})

	case *intConstNode:
		c.emit(instr{push, n.i})

	case *floatConstNode:
		c.emit(instr{push, n.f})

	case *idNode:
		c.emit(instr{mload, n.sym.addr})
		m := n.sym.binding.(*metrics.Metric)
		c.emit(instr{dload, len(m.Keys)})

	case *caprefNode:
		rn := n.sym.binding.(*regexNode)
		// rn.addr contains the index of the regular expression object,
		// which correlates to storage on the re slice
		c.emit(instr{push, rn.addr})
		// n.sym.addr is the capture group offset
		c.emit(instr{capref, n.sym.addr})

	case *defNode:
		// Do nothing, defs are inlined.
		return nil

	case *decoNode:
		// Put the current block on the stack
		c.decos = append(c.decos, n)
		// then iterate over the decorator's nodes
		walknodelist(c, n.def.children)
		c.decos = c.decos[:len(c.decos)-1]
		return nil

	case *nextNode:
		// Visit the 'next' block on the decorated block stack
		deco := c.decos[len(c.decos)-1]
		walknodelist(c, deco.children)
		return nil

	case *otherwiseNode:
		c.emit(instr{op: otherwise})
		c.emit(instr{op: jnm})
	}

	return c
}

func (c *codegen) VisitAfter(node node) {
	switch n := node.(type) {
	case *builtinNode:
		if n.args != nil {
			c.emit(instr{builtin[n.name], len(n.args.(*exprlistNode).children)})
		} else {
			c.emit(instr{op: builtin[n.name]})
		}
	case *unaryExprNode:
		switch n.op {
		case INC:
			c.emit(instr{op: inc})
		case NOT:
			c.emit(instr{op: not})
		}
	case *binaryExprNode:
		switch n.op {
		case LT:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jnm})
		case GT:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jnm})
		case LE:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jm})
		case GE:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jm})
		case EQ:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jnm})
		case NE:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jm})
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		case '*':
			c.emit(instr{op: mul})
		case '/':
			c.emit(instr{op: div})
		case '%':
			c.emit(instr{op: mod})
		case AND:
			c.emit(instr{op: and})
		case OR:
			c.emit(instr{op: or})
		case XOR:
			c.emit(instr{op: xor})
		case ASSIGN:
			c.emit(instr{op: set})
		case ADD_ASSIGN:
			c.emit(instr{inc, 1})
		case SHL:
			c.emit(instr{op: shl})
		case SHR:
			c.emit(instr{op: shr})
		case POW:
			c.emit(instr{op: pow})
		}
	}
}
<commit_msg>Prefixes code generation errors with 'Internal Compiler Error'<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"fmt"
	"regexp"

	"github.com/google/mtail/metrics"
)

// compiler is data for the code generator.
type codegen struct {
	name string // Name of the program.

	errors ErrorList // Compile errors.
	obj    object    // The object to return

	decos []*decoNode // Decorator stack to unwind
}

// CodeGen is the function that compiles the program to bytecode and data.
func CodeGen(name string, ast node) (*object, error) {
	c := &codegen{name: name}
	Walk(c, ast)
	if len(c.errors) > 0 {
		return nil, c.errors
	}
	return &c.obj, nil
}

func (c *codegen) errorf(format string, args ...interface{}) {
	e := "Internal compiler error: " + fmt.Sprintf(format, args...)
	c.errors.Add(position{filename: c.name}, e)
}

func (c *codegen) emit(i instr) {
	c.obj.prog = append(c.obj.prog, i)
}

func (c *codegen) VisitBefore(node node) Visitor {
	switch n := node.(type) {

	case *declNode:
		// Build the list of addressable metrics for this program, and set the symbol's address.
		n.sym.addr = len(c.obj.m)
		c.obj.m = append(c.obj.m, n.sym.binding.(*metrics.Metric))
		return nil

	case *condNode:
		if n.cond != nil {
			Walk(c, n.cond)
		}
		// Save PC of previous jump instruction emitted by the n.cond
		// compilation.  (See regexNode and relNode cases, which will emit a
		// jump as the last instr.)  This jump will skip over the truthNode.
		pc := len(c.obj.prog) - 1
		// Set matched flag false for children.
		c.emit(instr{setmatched, false})
		Walk(c, n.truthNode)
		// Re-set matched flag to true for rest of current block.
		c.emit(instr{setmatched, true})
		// Rewrite n.cond's jump target to jump to instruction after block.
		c.obj.prog[pc].opnd = len(c.obj.prog)
		// Now also emit the else clause, and a jump.
		if n.elseNode != nil {
			c.emit(instr{op: jmp})
			// Rewrite jump again to avoid this else-skipper just emitted.
			c.obj.prog[pc].opnd = len(c.obj.prog)
			// Now get the PC of the else-skipper just emitted.
			pc = len(c.obj.prog) - 1
			Walk(c, n.elseNode)
			// Rewrite else-skipper to the next PC.
			c.obj.prog[pc].opnd = len(c.obj.prog)
		}
		return nil

	case *regexNode:
		re, err := regexp.Compile(n.pattern)
		if err != nil {
			c.errorf("%s", err)
			return nil
		}
		c.obj.re = append(c.obj.re, re)
		// Store the location of this regular expression in the regexNode
		n.addr = len(c.obj.re) - 1
		c.emit(instr{match, n.addr})
		c.emit(instr{op: jnm})

	case *stringConstNode:
		c.obj.str = append(c.obj.str, n.text)
		c.emit(instr{str, len(c.obj.str) - 1})

	case *intConstNode:
		c.emit(instr{push, n.i})

	case *floatConstNode:
		c.emit(instr{push, n.f})

	case *idNode:
		c.emit(instr{mload, n.sym.addr})
		m := n.sym.binding.(*metrics.Metric)
		c.emit(instr{dload, len(m.Keys)})

	case *caprefNode:
		rn := n.sym.binding.(*regexNode)
		// rn.addr contains the index of the regular expression object,
		// which correlates to storage on the re slice
		c.emit(instr{push, rn.addr})
		// n.sym.addr is the capture group offset
		c.emit(instr{capref, n.sym.addr})

	case *defNode:
		// Do nothing, defs are inlined.
		return nil

	case *decoNode:
		// Put the current block on the stack
		c.decos = append(c.decos, n)
		// then iterate over the decorator's nodes
		walknodelist(c, n.def.children)
		c.decos = c.decos[:len(c.decos)-1]
		return nil

	case *nextNode:
		// Visit the 'next' block on the decorated block stack
		deco := c.decos[len(c.decos)-1]
		walknodelist(c, deco.children)
		return nil

	case *otherwiseNode:
		c.emit(instr{op: otherwise})
		c.emit(instr{op: jnm})
	}

	return c
}

func (c *codegen) VisitAfter(node node) {
	switch n := node.(type) {
	case *builtinNode:
		if n.args != nil {
			c.emit(instr{builtin[n.name], len(n.args.(*exprlistNode).children)})
		} else {
			c.emit(instr{op: builtin[n.name]})
		}
	case *unaryExprNode:
		switch n.op {
		case INC:
			c.emit(instr{op: inc})
		case NOT:
			c.emit(instr{op: not})
		}
	case *binaryExprNode:
		switch n.op {
		case LT:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jnm})
		case GT:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jnm})
		case LE:
			c.emit(instr{cmp, 1})
			c.emit(instr{op: jm})
		case GE:
			c.emit(instr{cmp, -1})
			c.emit(instr{op: jm})
		case EQ:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jnm})
		case NE:
			c.emit(instr{cmp, 0})
			c.emit(instr{op: jm})
		case '+':
			c.emit(instr{op: add})
		case '-':
			c.emit(instr{op: sub})
		case '*':
			c.emit(instr{op: mul})
		case '/':
			c.emit(instr{op: div})
		case '%':
			c.emit(instr{op: mod})
		case AND:
			c.emit(instr{op: and})
		case OR:
			c.emit(instr{op: or})
		case XOR:
			c.emit(instr{op: xor})
		case ASSIGN:
			c.emit(instr{op: set})
		case ADD_ASSIGN:
			c.emit(instr{inc, 1})
		case SHL:
			c.emit(instr{op: shl})
		case SHR:
			c.emit(instr{op: shr})
		case POW:
			c.emit(instr{op: pow})
		}
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package components

import (
	"errors"
	"reflect"

	graph "gopkg.in/r3labs/graph.v2"
)

// NatGateway : mapping of a nat component
type NatGateway struct {
	ProviderType           string            `json:"_provider"`
	ComponentType          string            `json:"_component"`
	ComponentID            string            `json:"_component_id"`
	State                  string            `json:"_state"`
	Action                 string            `json:"_action"`
	NatGatewayAWSID        string            `json:"nat_gateway_aws_id"`
	Name                   string            `json:"name"`
	PublicNetwork          string            `json:"public_network"`
	RoutedNetworks         []string          `json:"routed_networks"`
	RoutedNetworkAWSIDs    []string          `json:"routed_networks_aws_ids"`
	PublicNetworkAWSID     string            `json:"public_network_aws_id"`
	NatGatewayAllocationID string            `json:"nat_gateway_allocation_id"`
	NatGatewayAllocationIP string            `json:"nat_gateway_allocation_ip"`
	InternetGatewayID      string            `json:"internet_gateway_id"`
	DatacenterType         string            `json:"datacenter_type"`
	DatacenterName         string            `json:"datacenter_name"`
	DatacenterRegion       string            `json:"datacenter_region"`
	AccessKeyID            string            `json:"aws_access_key_id"`
	SecretAccessKey        string            `json:"aws_secret_access_key"`
	VpcID                  string            `json:"vpc_id"`
	Tags                   map[string]string `json:"tags"`
	Service                string            `json:"service"`
}

// GetID : returns the component's ID
func (n *NatGateway) GetID() string {
	return n.ComponentID
}

// GetName returns a components name
func (n *NatGateway) GetName() string {
	return n.Name
}

// GetProvider : returns the provider type
func (n *NatGateway) GetProvider() string {
	return n.ProviderType
}

// GetProviderID returns a components provider id
func (n *NatGateway) GetProviderID() string {
	return n.NatGatewayAWSID
}

// GetType : returns the type of the component
func (n *NatGateway) GetType() string {
	return n.ComponentType
}

// GetState : returns the state of the component
func (n *NatGateway) GetState() string {
	return n.State
}

// SetState : sets the state of the component
func (n *NatGateway) SetState(s string) {
	n.State = s
}

// GetAction : returns the action of the component
func (n *NatGateway) GetAction() string {
	return n.Action
}

// SetAction : Sets the action of the component
func (n *NatGateway) SetAction(s string) {
	n.Action = s
}

// GetGroup : returns the components group
func (n *NatGateway) GetGroup() string {
	return ""
}

// GetTags returns a components tags
func (n *NatGateway) GetTags() map[string]string {
	return n.Tags
}

// GetTag returns a components tag
func (n *NatGateway) GetTag(tag string) string {
	return n.Tags[tag]
}

// Diff : diff's the component against another component of the same type
func (n *NatGateway) Diff(c graph.Component) bool {
	cn, ok := c.(*NatGateway)
	if ok {
		return !reflect.DeepEqual(n.RoutedNetworks, cn.RoutedNetworks)
	}

	return false
}

// Update : updates the provider returned values of a component
func (n *NatGateway) Update(c graph.Component) {
	cn, ok := c.(*NatGateway)
	if ok {
		n.NatGatewayAWSID = cn.NatGatewayAWSID
		n.NatGatewayAllocationID = cn.NatGatewayAllocationID
		n.NatGatewayAllocationIP = cn.NatGatewayAllocationIP
	}

	n.SetDefaultVariables()
}

// Rebuild : rebuilds the component's internal state, such as templated values
func (n *NatGateway) Rebuild(g *graph.Graph) {
	if n.PublicNetwork == "" && n.PublicNetworkAWSID != "" {
		pn := g.GetComponents().ByProviderID(n.PublicNetworkAWSID)
		if pn != nil {
			n.PublicNetwork = pn.GetName()
		}
	}

	if n.PublicNetworkAWSID != "" && n.PublicNetwork != "" {
		n.PublicNetworkAWSID = templSubnetID(n.PublicNetwork)
	}

	if len(n.RoutedNetworks) > len(n.RoutedNetworkAWSIDs) {
		for _, nw := range n.RoutedNetworks {
			n.RoutedNetworkAWSIDs = append(n.RoutedNetworkAWSIDs, templSubnetID(nw))
		}
	}

	if len(n.RoutedNetworkAWSIDs) > len(n.RoutedNetworks) {
		for _, nwid := range n.RoutedNetworkAWSIDs {
			nw := g.GetComponents().ByProviderID(nwid)
			if nw != nil {
				n.RoutedNetworks = append(n.RoutedNetworks, nw.GetName())
			}
		}
	}

	n.VpcID = templSubnetVPCID(n.PublicNetwork)

	n.SetDefaultVariables()
}

// Dependencies : returns a list of component id's upon which the component depends
func (n *NatGateway) Dependencies() []string {
	var deps []string

	for _, nw := range n.RoutedNetworkAWSIDs {
		deps = append(deps, TYPENETWORK+TYPEDELIMITER+nw)
	}

	deps = append(deps, TYPENETWORK+TYPEDELIMITER+n.PublicNetwork)

	return deps
}

// Validate : validates the components values
func (n *NatGateway) Validate() error {
	if n.Name == "" {
		return errors.New("Nat Gateway name should not be null")
	}

	if n.PublicNetwork == "" {
		return errors.New("Nat Gateway should specify a public network")
	}

	return nil
}

// IsStateful : returns true if the component needs to be actioned to be removed.
func (n *NatGateway) IsStateful() bool {
	return true
}

// SetDefaultVariables : sets up the default template variables for a component
func (n *NatGateway) SetDefaultVariables() {
	n.ComponentType = TYPENATGATEWAY
	n.ComponentID = TYPENATGATEWAY + TYPEDELIMITER + n.Name
	n.ProviderType = PROVIDERTYPE
	n.DatacenterName = DATACENTERNAME
	n.DatacenterType = DATACENTERTYPE
	n.DatacenterRegion = DATACENTERREGION
	n.AccessKeyID = ACCESSKEYID
	n.SecretAccessKey = SECRETACCESSKEY
}
<commit_msg>fixed nat dependencies<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package components

import (
	"errors"
	"reflect"

	graph "gopkg.in/r3labs/graph.v2"
)

// NatGateway : mapping of a nat component
type NatGateway struct {
	ProviderType           string            `json:"_provider"`
	ComponentType          string            `json:"_component"`
	ComponentID            string            `json:"_component_id"`
	State                  string            `json:"_state"`
	Action                 string            `json:"_action"`
	NatGatewayAWSID        string            `json:"nat_gateway_aws_id"`
	Name                   string            `json:"name"`
	PublicNetwork          string            `json:"public_network"`
	RoutedNetworks         []string          `json:"routed_networks"`
	RoutedNetworkAWSIDs    []string          `json:"routed_networks_aws_ids"`
	PublicNetworkAWSID     string            `json:"public_network_aws_id"`
	NatGatewayAllocationID string            `json:"nat_gateway_allocation_id"`
	NatGatewayAllocationIP string            `json:"nat_gateway_allocation_ip"`
	InternetGatewayID      string            `json:"internet_gateway_id"`
	DatacenterType         string            `json:"datacenter_type"`
	DatacenterName         string            `json:"datacenter_name"`
	DatacenterRegion       string            `json:"datacenter_region"`
	AccessKeyID            string            `json:"aws_access_key_id"`
	SecretAccessKey        string            `json:"aws_secret_access_key"`
	VpcID                  string            `json:"vpc_id"`
	Tags                   map[string]string `json:"tags"`
	Service                string            `json:"service"`
}

// GetID : returns the component's ID
func (n *NatGateway) GetID() string {
	return n.ComponentID
}

// GetName returns a components name
func (n *NatGateway) GetName() string {
	return n.Name
}

// GetProvider : returns the provider type
func (n *NatGateway) GetProvider() string {
	return n.ProviderType
}

// GetProviderID returns a components provider id
func (n *NatGateway) GetProviderID() string {
	return n.NatGatewayAWSID
}

// GetType : returns the type of the component
func (n *NatGateway) GetType() string {
	return n.ComponentType
}

// GetState : returns the state of the component
func (n *NatGateway) GetState() string {
	return n.State
}

// SetState : sets the state of the component
func (n *NatGateway) SetState(s string) {
	n.State = s
}

// GetAction : returns the action of the component
func (n *NatGateway) GetAction() string {
	return n.Action
}

// SetAction : Sets the action of the component
func (n *NatGateway) SetAction(s string) {
	n.Action = s
}

// GetGroup : returns the components group
func (n *NatGateway) GetGroup() string {
	return ""
}

// GetTags returns a components tags
func (n *NatGateway) GetTags() map[string]string {
	return n.Tags
}

// GetTag returns a components tag
func (n *NatGateway) GetTag(tag string) string {
	return n.Tags[tag]
}

// Diff : diff's the component against another component of the same type
func (n *NatGateway) Diff(c graph.Component) bool {
	cn, ok := c.(*NatGateway)
	if ok {
		return !reflect.DeepEqual(n.RoutedNetworks, cn.RoutedNetworks)
	}

	return false
}

// Update : updates the provider returned values of a component
func (n *NatGateway) Update(c graph.Component) {
	cn, ok := c.(*NatGateway)
	if ok {
		n.NatGatewayAWSID = cn.NatGatewayAWSID
		n.NatGatewayAllocationID = cn.NatGatewayAllocationID
		n.NatGatewayAllocationIP = cn.NatGatewayAllocationIP
	}

	n.SetDefaultVariables()
}

// Rebuild : rebuilds the component's internal state, such as templated values
func (n *NatGateway) Rebuild(g *graph.Graph) {
	if n.PublicNetwork == "" && n.PublicNetworkAWSID != "" {
		pn := g.GetComponents().ByProviderID(n.PublicNetworkAWSID)
		if pn != nil {
			n.PublicNetwork = pn.GetName()
		}
	}

	if n.PublicNetworkAWSID != "" && n.PublicNetwork != "" {
		n.PublicNetworkAWSID = templSubnetID(n.PublicNetwork)
	}

	if len(n.RoutedNetworks) > len(n.RoutedNetworkAWSIDs) {
		for _, nw := range n.RoutedNetworks {
			n.RoutedNetworkAWSIDs = append(n.RoutedNetworkAWSIDs, templSubnetID(nw))
		}
	}

	if len(n.RoutedNetworkAWSIDs) > len(n.RoutedNetworks) {
		for _, nwid := range n.RoutedNetworkAWSIDs {
			nw := g.GetComponents().ByProviderID(nwid)
			if nw != nil {
				n.RoutedNetworks = append(n.RoutedNetworks, nw.GetName())
			}
		}
	}

	n.VpcID = templSubnetVPCID(n.PublicNetwork)

	n.SetDefaultVariables()
}

// Dependencies : returns a list of component id's upon which the component depends
func (n *NatGateway) Dependencies() []string {
	var deps []string

	for _, nw := range n.RoutedNetworks {
		deps = append(deps, TYPENETWORK+TYPEDELIMITER+nw)
	}

	deps = append(deps, TYPENETWORK+TYPEDELIMITER+n.PublicNetwork)

	return deps
}

// Validate : validates the components values
func (n *NatGateway) Validate() error {
	if n.Name == "" {
		return errors.New("Nat Gateway name should not be null")
	}

	if n.PublicNetwork == "" {
		return errors.New("Nat Gateway should specify a public network")
	}

	return nil
}

// IsStateful : returns true if the component needs to be actioned to be removed.
func (n *NatGateway) IsStateful() bool {
	return true
}

// SetDefaultVariables : sets up the default template variables for a component
func (n *NatGateway) SetDefaultVariables() {
	n.ComponentType = TYPENATGATEWAY
	n.ComponentID = TYPENATGATEWAY + TYPEDELIMITER + n.Name
	n.ProviderType = PROVIDERTYPE
	n.DatacenterName = DATACENTERNAME
	n.DatacenterType = DATACENTERTYPE
	n.DatacenterRegion = DATACENTERREGION
	n.AccessKeyID = ACCESSKEYID
	n.SecretAccessKey = SECRETACCESSKEY
}
<|endoftext|>


<commit_before>package oauth2

import (
	"net/http"
	"time"

	"github.com/ory-am/fosite"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

type RefreshTokenGrantHandler struct {
	AccessTokenStrategy AccessTokenStrategy

	RefreshTokenStrategy RefreshTokenStrategy

	// RefreshTokenGrantStorage is used to persist session data across requests.
	RefreshTokenGrantStorage RefreshTokenGrantStorage

	// AccessTokenLifespan defines the lifetime of an access token.
	AccessTokenLifespan time.Duration
}

// HandleTokenEndpointRequest implements https://tools.ietf.org/html/rfc6749#section-6
func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Context, req *http.Request, request fosite.AccessRequester) error {
	// grant_type REQUIRED.
	// Value MUST be set to "client_credentials".
	if !request.GetGrantTypes().Exact("refresh_token") {
		return errors.Wrap(fosite.ErrUnknownRequest, "")
	}

	if !request.GetClient().GetGrantTypes().Has("refresh_token") {
		return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type refresh_token")
	}

	refresh := req.PostForm.Get("refresh_token")
	signature := c.RefreshTokenStrategy.RefreshTokenSignature(refresh)
	accessRequest, err := c.RefreshTokenGrantStorage.GetRefreshTokenSession(ctx, signature, nil)
	if errors.Cause(err) == fosite.ErrNotFound {
		return errors.Wrap(fosite.ErrInvalidRequest, err.Error())
	} else if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	// The authorization server MUST ... validate the refresh token.
	if err := c.RefreshTokenStrategy.ValidateRefreshToken(ctx, request, refresh); err != nil {
		return errors.Wrap(fosite.ErrInvalidRequest, err.Error())
	}

	request.SetRequestedScopes(accessRequest.GetRequestedScopes())
	for _, scope := range accessRequest.GetGrantedScopes() {
		request.GrantScope(scope)
	}

	// The authorization server MUST ... and ensure that the refresh token was issued to the authenticated client
	if accessRequest.GetClient().GetID() != request.GetClient().GetID() {
		return errors.Wrap(fosite.ErrInvalidRequest, "Client ID mismatch")
	}
	return nil
}

// PopulateTokenEndpointResponse implements https://tools.ietf.org/html/rfc6749#section-6
func (c *RefreshTokenGrantHandler) PopulateTokenEndpointResponse(ctx context.Context, req *http.Request, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
	if !requester.GetGrantTypes().Exact("refresh_token") {
		return errors.Wrap(fosite.ErrUnknownRequest, "")
	}

	accessToken, accessSignature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, requester)
	if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	refreshToken, refreshSignature, err := c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester)
	if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	signature := c.RefreshTokenStrategy.RefreshTokenSignature(req.PostForm.Get("refresh_token"))
	if err := c.RefreshTokenGrantStorage.PersistRefreshTokenGrantSession(ctx, signature, accessSignature, refreshSignature, requester); err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	responder.SetAccessToken(accessToken)
	responder.SetTokenType("bearer")
	responder.SetExpiresIn(c.AccessTokenLifespan / time.Second)
	responder.SetScopes(requester.GetGrantedScopes())
	responder.SetExtra("refresh_token", refreshToken)
	return nil
}
<commit_msg>oauth2: corrected grant type in comment (#82)<commit_after>package oauth2

import (
	"net/http"
	"time"

	"github.com/ory-am/fosite"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

type RefreshTokenGrantHandler struct {
	AccessTokenStrategy AccessTokenStrategy

	RefreshTokenStrategy RefreshTokenStrategy

	// RefreshTokenGrantStorage is used to persist session data across requests.
	RefreshTokenGrantStorage RefreshTokenGrantStorage

	// AccessTokenLifespan defines the lifetime of an access token.
	AccessTokenLifespan time.Duration
}

// HandleTokenEndpointRequest implements https://tools.ietf.org/html/rfc6749#section-6
func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Context, req *http.Request, request fosite.AccessRequester) error {
	// grant_type REQUIRED.
	// Value MUST be set to "refresh_token".
	if !request.GetGrantTypes().Exact("refresh_token") {
		return errors.Wrap(fosite.ErrUnknownRequest, "")
	}

	if !request.GetClient().GetGrantTypes().Has("refresh_token") {
		return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type refresh_token")
	}

	refresh := req.PostForm.Get("refresh_token")
	signature := c.RefreshTokenStrategy.RefreshTokenSignature(refresh)
	accessRequest, err := c.RefreshTokenGrantStorage.GetRefreshTokenSession(ctx, signature, nil)
	if errors.Cause(err) == fosite.ErrNotFound {
		return errors.Wrap(fosite.ErrInvalidRequest, err.Error())
	} else if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	// The authorization server MUST ... validate the refresh token.
	if err := c.RefreshTokenStrategy.ValidateRefreshToken(ctx, request, refresh); err != nil {
		return errors.Wrap(fosite.ErrInvalidRequest, err.Error())
	}

	request.SetRequestedScopes(accessRequest.GetRequestedScopes())
	for _, scope := range accessRequest.GetGrantedScopes() {
		request.GrantScope(scope)
	}

	// The authorization server MUST ... and ensure that the refresh token was issued to the authenticated client
	if accessRequest.GetClient().GetID() != request.GetClient().GetID() {
		return errors.Wrap(fosite.ErrInvalidRequest, "Client ID mismatch")
	}
	return nil
}

// PopulateTokenEndpointResponse implements https://tools.ietf.org/html/rfc6749#section-6
func (c *RefreshTokenGrantHandler) PopulateTokenEndpointResponse(ctx context.Context, req *http.Request, requester fosite.AccessRequester, responder fosite.AccessResponder) error {
	if !requester.GetGrantTypes().Exact("refresh_token") {
		return errors.Wrap(fosite.ErrUnknownRequest, "")
	}

	accessToken, accessSignature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, requester)
	if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	refreshToken, refreshSignature, err := c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester)
	if err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	signature := c.RefreshTokenStrategy.RefreshTokenSignature(req.PostForm.Get("refresh_token"))
	if err := c.RefreshTokenGrantStorage.PersistRefreshTokenGrantSession(ctx, signature, accessSignature, refreshSignature, requester); err != nil {
		return errors.Wrap(fosite.ErrServerError, err.Error())
	}

	responder.SetAccessToken(accessToken)
	responder.SetTokenType("bearer")
	responder.SetExpiresIn(c.AccessTokenLifespan / time.Second)
	responder.SetScopes(requester.GetGrantedScopes())
	responder.SetExtra("refresh_token", refreshToken)
	return nil
}
<|endoftext|>


<commit_before>package caddy

import (
	"context"
	"github.com/dgrijalva/jwt-go"
	"github.com/mholt/caddy/caddyhttp/httpserver"
	"github.com/tarent/loginsrv/login"
	"github.com/tarent/loginsrv/model"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

//Tests a page while being logged in as a user (doesn't test that the {user} replacer changes)
func Test_ServeHTTP_200(t *testing.T) {
	//Set the ServeHTTP *http.Request
	r, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatalf("Unable to create request: %v", err)
	}

	// Associate a replacer with the request:
	r = r.WithContext(context.WithValue(context.Background(), httpserver.ReplacerCtxKey, httpserver.NewReplacer(r, nil, "-")))

	//Set the ServeHTTP http.ResponseWriter
	w := httptest.NewRecorder()

	//Set the CaddyHandler config
	configh := login.DefaultConfig()
	configh.Backends = login.Options{"simple": {"bob": "secret"}}
	loginh, err := login.NewHandler(configh)
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set the CaddyHandler that will use ServeHTTP
	h := &CaddyHandler{
		next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return http.StatusOK, nil // not t.Fatalf, or we will not see what other methods yield
		}),
		config:       login.DefaultConfig(),
		loginHandler: loginh,
	}

	//Set user token
	userInfo := model.UserInfo{Sub: "bob", Expiry: time.Now().Add(time.Second).Unix()}
	token := jwt.NewWithClaims(jwt.SigningMethodHS512, userInfo)
	validToken, err := token.SignedString([]byte(h.config.JwtSecret))
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set cookie for user token on the ServeHTTP http.ResponseWriter
	cookie := http.Cookie{Name: "jwt_token", Value: validToken, HttpOnly: true}
	http.SetCookie(w, &cookie)

	//Add the cookie to the request
	r.AddCookie(&cookie)

	//Test that cookie is a valid token
	_, valid := loginh.GetToken(r)
	if !valid {
		t.Errorf("loginHandler cookie is not valid")
	}

	status, err := h.ServeHTTP(w, r)

	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	if status != 200 {
		t.Errorf("Expected returned status code to be %d, got %d", 0, status)
	}

	// Check that the replacer now is able to substitute the user variable in log lines
	replacer, replacerOk := r.Context().Value(httpserver.ReplacerCtxKey).(httpserver.Replacer)
	if !replacerOk {
		t.Errorf("no replacer associated with request")

	} else {
		replacement := replacer.Replace("{user}")
		if replacement != "bob" {
			t.Errorf(`wrong replacement: expected "bob", but got %q`, replacement)
		}
	}
}

//Tests the login page without being logged as a user (doesn't test that the {user} replacer stays as-is)
func Test_ServeHTTP_login(t *testing.T) {
	//Set the ServeHTTP *http.Request
	r, err := http.NewRequest("GET", "/login", nil)
	if err != nil {
		t.Fatalf("Unable to create request: %v", err)
	}

	//Set the ServeHTTP http.ResponseWriter
	w := httptest.NewRecorder()

	//Set the CaddyHandler config
	configh := login.DefaultConfig()
	configh.Backends = login.Options{"simple": {"bob": "secret"}}
	loginh, err := login.NewHandler(configh)
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set the CaddyHandler that will use ServeHTTP
	h := &CaddyHandler{
		next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return http.StatusOK, nil // not t.Fatalf, or we will not see what other methods yield
		}),
		config:       login.DefaultConfig(),
		loginHandler: loginh,
	}

	status, err := h.ServeHTTP(w, r)

	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	if status != 0 {
		t.Errorf("Expected returned status code to be %d, got %d", 0, status)
	}
}
<commit_msg>removed test for {user} log, since it is not in caddy release, yet<commit_after>package caddy

import (
	"context"
	"github.com/dgrijalva/jwt-go"
	"github.com/mholt/caddy/caddyhttp/httpserver"
	"github.com/tarent/loginsrv/login"
	"github.com/tarent/loginsrv/model"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

//Tests a page while being logged in as a user (doesn't test that the {user} replacer changes)
func Test_ServeHTTP_200(t *testing.T) {
	//Set the ServeHTTP *http.Request
	r, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatalf("Unable to create request: %v", err)
	}

	// Associate a replacer with the request:
	r = r.WithContext(context.WithValue(context.Background(), httpserver.ReplacerCtxKey, httpserver.NewReplacer(r, nil, "-")))

	//Set the ServeHTTP http.ResponseWriter
	w := httptest.NewRecorder()

	//Set the CaddyHandler config
	configh := login.DefaultConfig()
	configh.Backends = login.Options{"simple": {"bob": "secret"}}
	loginh, err := login.NewHandler(configh)
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set the CaddyHandler that will use ServeHTTP
	h := &CaddyHandler{
		next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return http.StatusOK, nil // not t.Fatalf, or we will not see what other methods yield
		}),
		config:       login.DefaultConfig(),
		loginHandler: loginh,
	}

	//Set user token
	userInfo := model.UserInfo{Sub: "bob", Expiry: time.Now().Add(time.Second).Unix()}
	token := jwt.NewWithClaims(jwt.SigningMethodHS512, userInfo)
	validToken, err := token.SignedString([]byte(h.config.JwtSecret))
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set cookie for user token on the ServeHTTP http.ResponseWriter
	cookie := http.Cookie{Name: "jwt_token", Value: validToken, HttpOnly: true}
	http.SetCookie(w, &cookie)

	//Add the cookie to the request
	r.AddCookie(&cookie)

	//Test that cookie is a valid token
	_, valid := loginh.GetToken(r)
	if !valid {
		t.Errorf("loginHandler cookie is not valid")
	}

	status, err := h.ServeHTTP(w, r)

	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	if status != 200 {
		t.Errorf("Expected returned status code to be %d, got %d", 0, status)
	}

	/**
	TODO: This will only work with the caddy master branch or the next caddy release

		// Check that the replacer now is able to substitute the user variable in log lines
		replacer, replacerOk := r.Context().Value(httpserver.ReplacerCtxKey).(httpserver.Replacer)
		if !replacerOk {
			t.Errorf("no replacer associated with request")

		} else {
			replacement := replacer.Replace("{user}")
			if replacement != "bob" {
				t.Errorf(`wrong replacement: expected "bob", but got %q`, replacement)
			}
		}
	*/
}

//Tests the login page without being logged as a user (doesn't test that the {user} replacer stays as-is)
func Test_ServeHTTP_login(t *testing.T) {
	//Set the ServeHTTP *http.Request
	r, err := http.NewRequest("GET", "/login", nil)
	if err != nil {
		t.Fatalf("Unable to create request: %v", err)
	}

	//Set the ServeHTTP http.ResponseWriter
	w := httptest.NewRecorder()

	//Set the CaddyHandler config
	configh := login.DefaultConfig()
	configh.Backends = login.Options{"simple": {"bob": "secret"}}
	loginh, err := login.NewHandler(configh)
	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	//Set the CaddyHandler that will use ServeHTTP
	h := &CaddyHandler{
		next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return http.StatusOK, nil // not t.Fatalf, or we will not see what other methods yield
		}),
		config:       login.DefaultConfig(),
		loginHandler: loginh,
	}

	status, err := h.ServeHTTP(w, r)

	if err != nil {
		t.Errorf("Expected nil error, got: %v", err)
	}

	if status != 0 {
		t.Errorf("Expected returned status code to be %d, got %d", 0, status)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2017 Ludovic Fauvet
// Licensed under the MIT license

package daemon

import (
    "fmt"
    "github.com/etix/mirrorbits/database"
    "github.com/etix/mirrorbits/mirrors"
    . "github.com/etix/mirrorbits/testing"
    "reflect"
    "sort"
    "testing"
    "time"
)

func TestStart(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    defer c.Stop()

    if c.running != true {
        t.Fatalf("Expected true, got false")
    }
}

func TestStop(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    c.Stop()

    if c.running != false {
        t.Fatalf("Expected false, got true")
    }
}

func TestClusterLoop(t *testing.T) {
    mock, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)

    cmd_publish := mock.Command("PUBLISH", string(database.CLUSTER), fmt.Sprintf("%s %s", clusterAnnounce, c.nodeID)).Expect("1")

    c.Start()
    defer c.Stop()

    n := time.Now()

    for {
        if time.Now().Sub(n) > 1500*time.Millisecond {
            t.Fatalf("Announce not made")
        }
        if mock.Stats(cmd_publish) > 0 {
            // Success
            break
        }
    }
}

func TestRefreshNodeList(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)

    n := Node{
        ID:           "test-4242",
        LastAnnounce: time.Now().UTC().Unix(),
    }
    c.nodes = append(c.nodes, n)
    sort.Sort(ByNodeID(c.nodes))

    n = Node{
        ID:           "meh-4242",
        LastAnnounce: time.Now().UTC().Add(time.Second * -6).Unix(),
    }
    c.nodes = append(c.nodes, n)
    sort.Sort(ByNodeID(c.nodes))

    c.Start()
    defer c.Stop()

    c.refreshNodeList("test-4242", "test-4242")

    if len(c.nodes) != 1 {
        t.Fatalf("Node meh-4242 should have left")
    }

    c.refreshNodeList("meh-4242", "test-4242")

    if len(c.nodes) != 2 {
        t.Fatalf("Node meh-4242 should have joined")
    }
}

func TestAddMirror(t *testing.T) {
    _, conn := PrepareRedisTest()

    c := NewCluster(conn)

    r := []string{"bbb"}
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    r = []string{"aaa", "bbb"}
    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    r = []string{"aaa", "bbb", "ccc"}
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }
}

func TestRemoveMirror(t *testing.T) {
    _, conn := PrepareRedisTest()

    c := NewCluster(conn)

    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })

    c.RemoveMirror(&mirrors.Mirror{ID: "xxx"})
    r := []string{"aaa", "bbb", "ccc"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    c.RemoveMirror(&mirrors.Mirror{ID: "aaa"})
    r = []string{"bbb", "ccc"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    c.RemoveMirror(&mirrors.Mirror{ID: "ccc"})
    r = []string{"bbb"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }
}

func TestIsHandled(t *testing.T) {
    _, conn := PrepareRedisTest()

    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    defer c.Stop()

    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ddd",
    })

    c.nodeTotal = 1

    if !c.IsHandled("aaa") || !c.IsHandled("bbb") || !c.IsHandled("ccc") || !c.IsHandled("ddd") {
        t.Fatalf("All mirrors should be handled")
    }

    c.nodeTotal = 2

    handled := 0

    if c.IsHandled("aaa") {
        handled += 1
    }
    if c.IsHandled("bbb") {
        handled += 1
    }
    if c.IsHandled("ccc") {
        handled += 1
    }
    if c.IsHandled("ddd") {
        handled += 1
    }

    if handled != 2 {
        t.Fatalf("Expected 2, got %d", handled)
    }
}

func TestRemoveMirrorIDFromSlice(t *testing.T) {
    s1 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r1 := []string{"aaa", "bbb", "ddd", "eee"}
    r := removeMirrorIDFromSlice(s1, "ccc")
    if !reflect.DeepEqual(r1, r) {
        t.Fatalf("Expected %+v, got %+v", r1, r)
    }

    s2 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r2 := []string{"bbb", "ccc", "ddd", "eee"}
    r = removeMirrorIDFromSlice(s2, "aaa")
    if !reflect.DeepEqual(r2, r) {
        t.Fatalf("Expected %+v, got %+v", r2, r)
    }

    s3 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r3 := []string{"aaa", "bbb", "ccc", "ddd"}
    r = removeMirrorIDFromSlice(s3, "eee")
    if !reflect.DeepEqual(r3, r) {
        t.Fatalf("Expected %+v, got %+v", r3, r)
    }

    s4 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r4 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r = removeMirrorIDFromSlice(s4, "xxx")
    if !reflect.DeepEqual(r4, r) {
        t.Fatalf("Expected %+v, got %+v", r4, r)
    }
}

func TestAddMirrorIDToSlice(t *testing.T) {
    s1 := []string{"aaa", "ccc"}
    r1 := []string{"aaa", "bbb", "ccc"}
    r := addMirrorIDToSlice(s1, "bbb")
    if !reflect.DeepEqual(r1, r) {
        t.Fatalf("Expected %+v, got %+v", r1, r)
    }

    s2 := []string{"aaa", "bbb", "ccc"}
    r2 := []string{"111", "aaa", "bbb", "ccc"}
    r = addMirrorIDToSlice(s2, "111")
    if !reflect.DeepEqual(r2, r) {
        t.Fatalf("Expected %+v, got %+v", r2, r)
    }

    s3 := []string{"aaa", "bbb", "ccc"}
    r3 := []string{"aaa", "bbb", "ccc", "ddd"}
    r = addMirrorIDToSlice(s3, "ddd")
    if !reflect.DeepEqual(r3, r) {
        t.Fatalf("Expected %+v, got %+v", r3, r)
    }
}
<commit_msg>tests: cool down between retries<commit_after>// Copyright (c) 2014-2017 Ludovic Fauvet
// Licensed under the MIT license

package daemon

import (
    "fmt"
    "github.com/etix/mirrorbits/database"
    "github.com/etix/mirrorbits/mirrors"
    . "github.com/etix/mirrorbits/testing"
    "reflect"
    "sort"
    "testing"
    "time"
)

func TestStart(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    defer c.Stop()

    if c.running != true {
        t.Fatalf("Expected true, got false")
    }
}

func TestStop(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    c.Stop()

    if c.running != false {
        t.Fatalf("Expected false, got true")
    }
}

func TestClusterLoop(t *testing.T) {
    mock, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)

    cmd_publish := mock.Command("PUBLISH", string(database.CLUSTER), fmt.Sprintf("%s %s", clusterAnnounce, c.nodeID)).Expect("1")

    c.Start()
    defer c.Stop()

    n := time.Now()

    for {
        if time.Since(n) > 1500*time.Millisecond {
            t.Fatalf("Announce not made")
        }
        if mock.Stats(cmd_publish) > 0 {
            // Success
            break
        }
        time.Sleep(50 * time.Millisecond)
    }
}

func TestRefreshNodeList(t *testing.T) {
    _, conn := PrepareRedisTest()
    conn.ConnectPubsub()

    c := NewCluster(conn)

    n := Node{
        ID:           "test-4242",
        LastAnnounce: time.Now().UTC().Unix(),
    }
    c.nodes = append(c.nodes, n)
    sort.Sort(ByNodeID(c.nodes))

    n = Node{
        ID:           "meh-4242",
        LastAnnounce: time.Now().UTC().Add(time.Second * -6).Unix(),
    }
    c.nodes = append(c.nodes, n)
    sort.Sort(ByNodeID(c.nodes))

    c.Start()
    defer c.Stop()

    c.refreshNodeList("test-4242", "test-4242")

    if len(c.nodes) != 1 {
        t.Fatalf("Node meh-4242 should have left")
    }

    c.refreshNodeList("meh-4242", "test-4242")

    if len(c.nodes) != 2 {
        t.Fatalf("Node meh-4242 should have joined")
    }
}

func TestAddMirror(t *testing.T) {
    _, conn := PrepareRedisTest()

    c := NewCluster(conn)

    r := []string{"bbb"}
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    r = []string{"aaa", "bbb"}
    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    r = []string{"aaa", "bbb", "ccc"}
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }
}

func TestRemoveMirror(t *testing.T) {
    _, conn := PrepareRedisTest()

    c := NewCluster(conn)

    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })

    c.RemoveMirror(&mirrors.Mirror{ID: "xxx"})
    r := []string{"aaa", "bbb", "ccc"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    c.RemoveMirror(&mirrors.Mirror{ID: "aaa"})
    r = []string{"bbb", "ccc"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }

    c.RemoveMirror(&mirrors.Mirror{ID: "ccc"})
    r = []string{"bbb"}
    if !reflect.DeepEqual(r, c.mirrorsIndex) {
        t.Fatalf("Expected %+v, got %+v", r, c.mirrorsIndex)
    }
}

func TestIsHandled(t *testing.T) {
    _, conn := PrepareRedisTest()

    conn.ConnectPubsub()

    c := NewCluster(conn)
    c.Start()
    defer c.Stop()

    c.AddMirror(&mirrors.Mirror{
        ID: "aaa",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "bbb",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ccc",
    })
    c.AddMirror(&mirrors.Mirror{
        ID: "ddd",
    })

    c.nodeTotal = 1

    if !c.IsHandled("aaa") || !c.IsHandled("bbb") || !c.IsHandled("ccc") || !c.IsHandled("ddd") {
        t.Fatalf("All mirrors should be handled")
    }

    c.nodeTotal = 2

    handled := 0

    if c.IsHandled("aaa") {
        handled += 1
    }
    if c.IsHandled("bbb") {
        handled += 1
    }
    if c.IsHandled("ccc") {
        handled += 1
    }
    if c.IsHandled("ddd") {
        handled += 1
    }

    if handled != 2 {
        t.Fatalf("Expected 2, got %d", handled)
    }
}

func TestRemoveMirrorIDFromSlice(t *testing.T) {
    s1 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r1 := []string{"aaa", "bbb", "ddd", "eee"}
    r := removeMirrorIDFromSlice(s1, "ccc")
    if !reflect.DeepEqual(r1, r) {
        t.Fatalf("Expected %+v, got %+v", r1, r)
    }

    s2 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r2 := []string{"bbb", "ccc", "ddd", "eee"}
    r = removeMirrorIDFromSlice(s2, "aaa")
    if !reflect.DeepEqual(r2, r) {
        t.Fatalf("Expected %+v, got %+v", r2, r)
    }

    s3 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r3 := []string{"aaa", "bbb", "ccc", "ddd"}
    r = removeMirrorIDFromSlice(s3, "eee")
    if !reflect.DeepEqual(r3, r) {
        t.Fatalf("Expected %+v, got %+v", r3, r)
    }

    s4 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r4 := []string{"aaa", "bbb", "ccc", "ddd", "eee"}
    r = removeMirrorIDFromSlice(s4, "xxx")
    if !reflect.DeepEqual(r4, r) {
        t.Fatalf("Expected %+v, got %+v", r4, r)
    }
}

func TestAddMirrorIDToSlice(t *testing.T) {
    s1 := []string{"aaa", "ccc"}
    r1 := []string{"aaa", "bbb", "ccc"}
    r := addMirrorIDToSlice(s1, "bbb")
    if !reflect.DeepEqual(r1, r) {
        t.Fatalf("Expected %+v, got %+v", r1, r)
    }

    s2 := []string{"aaa", "bbb", "ccc"}
    r2 := []string{"111", "aaa", "bbb", "ccc"}
    r = addMirrorIDToSlice(s2, "111")
    if !reflect.DeepEqual(r2, r) {
        t.Fatalf("Expected %+v, got %+v", r2, r)
    }

    s3 := []string{"aaa", "bbb", "ccc"}
    r3 := []string{"aaa", "bbb", "ccc", "ddd"}
    r = addMirrorIDToSlice(s3, "ddd")
    if !reflect.DeepEqual(r3, r) {
        t.Fatalf("Expected %+v, got %+v", r3, r)
    }
}
<|endoftext|>


<commit_before>package sections

import (
	"fmt"
	"github.com/rpaloschi/dxf-go/core"
)

type StringMappedTable interface {
	Keys() []string
	Get(key string) (core.DxfElement, bool)
}

type LayerTable map[string]*Layer

func (table LayerTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

func (table LayerTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

type StyleTable map[string]*Style

func (table StyleTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

func (table StyleTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

type LineTypeTable map[string]*LineType

func (table LineTypeTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

func (table LineTypeTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

func StringMappedTablesAreEquals(tableA StringMappedTable, tableB StringMappedTable) bool {
	keysA := tableA.Keys()
	keysB := tableB.Keys()

	if len(keysA) != len(keysB) {
		return false
	}

	for _, key := range keysA {
		elementA, _ := tableA.Get(key)
		if elementB, ok := tableB.Get(key); ok {
			if !elementA.Equals(elementB) {
				return false
			}
		} else {
			return false
		}
	}

	return true
}

// TablesSection representation
type TablesSection struct {
	Layers    LayerTable
	Styles    StyleTable
	LineTypes LineTypeTable
}

// Equals Compare two TablesSection for equality
func (t TablesSection) Equals(other core.DxfElement) bool {
	if otherTable, ok := other.(*TablesSection); ok {
		return StringMappedTablesAreEquals(t.Layers, otherTable.Layers) &&
			StringMappedTablesAreEquals(t.Styles, otherTable.Styles) &&
			StringMappedTablesAreEquals(t.LineTypes, otherTable.LineTypes)
	}

	return false
}

// NewTablesSection parses the TablesSection from a slice of tags.
func NewTablesSection(tags core.TagSlice) (*TablesSection, error) {
	tables := new(TablesSection)

	tableParsers := map[string]func(slice core.TagSlice) error{
		"LAYER": func(slice core.TagSlice) error {
			layerTables, err := NewLayerTable(slice)
			tables.Layers = layerTables
			return err

		},
		"STYLE": func(slice core.TagSlice) error {
			styleTables, err := NewStyleTable(slice)
			tables.Styles = styleTables
			return err
		},
		"LTYPE": func(slice core.TagSlice) error {
			lineTypeTables, err := NewLineTypeTable(slice)
			tables.LineTypes = lineTypeTables
			return err
		},
	}

	// skip (0, 'SECTION') and (2, 'TABLES')
	tags = tags[2:]
	stopTag := core.NewTag(0, core.NewStringValue("ENDSEC"))
	endOfChunk := core.NewTag(0, core.NewStringValue("ENDTAB"))
	for _, tableTags := range SplitTagChunks(tags, stopTag, endOfChunk) {
		entryTagsList, err := TableEntryTags(tableTags)
		if err != nil {
			return nil, err
		}

		for _, entryTags := range entryTagsList {
			tableType := entryTags[0].Value.ToString()
			if tableFactory, ok := tableParsers[tableType]; ok {
				if err := tableFactory(tableTags); err != nil {
					return nil, err
				}
			} else {
				fmt.Printf("Ignoring unknown table type: %+v\n", tableType)
			}
		}
	}

	return tables, nil
}
<commit_msg>Improve tables module documentation.<commit_after>package sections

import (
	"fmt"
	"github.com/rpaloschi/dxf-go/core"
)

// StringMappedTable is an abstraction of any map string->DxfElement.
// The intention is to be able to apply consistent algorithms through different
// typed maps.
type StringMappedTable interface {
	Keys() []string
	Get(key string) (core.DxfElement, bool)
}

// LayerTable layer table implementation. (Implements StringMappedTable).
type LayerTable map[string]*Layer

// Keys the LayerTable keys.
func (table LayerTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

// Get returns a DxfElement at key.
func (table LayerTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

// StyleTable style table implementation. (Implements StringMappedTable).
type StyleTable map[string]*Style

// Keys the StyleTable keys.
func (table StyleTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

// Get returns a DxfElement at key.
func (table StyleTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

// LineTypeTable ltype table implementation. (Implements StringMappedTable).
type LineTypeTable map[string]*LineType

// Keys the LineTypeTable keys.
func (table LineTypeTable) Keys() []string {
	keys := make([]string, len(table))
	i := 0
	for k := range table {
		keys[i] = k
		i++
	}
	return keys
}

// Get returns a DxfElement at key.
func (table LineTypeTable) Get(key string) (core.DxfElement, bool) {
	element, ok := table[key]
	return element, ok
}

// StringMappedTablesAreEquals generic algorithm to compare tableA and tableB for equality.
func StringMappedTablesAreEquals(tableA StringMappedTable, tableB StringMappedTable) bool {
	keysA := tableA.Keys()
	keysB := tableB.Keys()

	if len(keysA) != len(keysB) {
		return false
	}

	for _, key := range keysA {
		elementA, _ := tableA.Get(key)
		if elementB, ok := tableB.Get(key); ok {
			if !elementA.Equals(elementB) {
				return false
			}
		} else {
			return false
		}
	}

	return true
}

// TablesSection representation
type TablesSection struct {
	Layers    LayerTable
	Styles    StyleTable
	LineTypes LineTypeTable
}

// Equals Compare two TablesSection for equality
func (t TablesSection) Equals(other core.DxfElement) bool {
	if otherTable, ok := other.(*TablesSection); ok {
		return StringMappedTablesAreEquals(t.Layers, otherTable.Layers) &&
			StringMappedTablesAreEquals(t.Styles, otherTable.Styles) &&
			StringMappedTablesAreEquals(t.LineTypes, otherTable.LineTypes)
	}

	return false
}

// NewTablesSection parses the TablesSection from a slice of tags.
func NewTablesSection(tags core.TagSlice) (*TablesSection, error) {
	tables := new(TablesSection)

	tableParsers := map[string]func(slice core.TagSlice) error{
		"LAYER": func(slice core.TagSlice) error {
			layerTables, err := NewLayerTable(slice)
			tables.Layers = layerTables
			return err

		},
		"STYLE": func(slice core.TagSlice) error {
			styleTables, err := NewStyleTable(slice)
			tables.Styles = styleTables
			return err
		},
		"LTYPE": func(slice core.TagSlice) error {
			lineTypeTables, err := NewLineTypeTable(slice)
			tables.LineTypes = lineTypeTables
			return err
		},
	}

	// skip (0, 'SECTION') and (2, 'TABLES')
	tags = tags[2:]
	stopTag := core.NewTag(0, core.NewStringValue("ENDSEC"))
	endOfChunk := core.NewTag(0, core.NewStringValue("ENDTAB"))
	for _, tableTags := range SplitTagChunks(tags, stopTag, endOfChunk) {
		entryTagsList, err := TableEntryTags(tableTags)
		if err != nil {
			return nil, err
		}

		for _, entryTags := range entryTagsList {
			tableType := entryTags[0].Value.ToString()
			if tableFactory, ok := tableParsers[tableType]; ok {
				if err := tableFactory(tableTags); err != nil {
					return nil, err
				}
			} else {
				fmt.Printf("Ignoring unknown table type: %+v\n", tableType)
			}
		}
	}

	return tables, nil
}
<|endoftext|>


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

// Package sensors exposes sensor data.
package sensors

import (
	"fmt"
	"log"
	"time"

	"github.com/go-daq/smbus"
	"github.com/go-daq/smbus/sensor/bme280"
	"github.com/go-daq/smbus/sensor/tsl2591"
)

type Sensors struct {
	Timestamp time.Time `json:"timestamp"`
	Tsl       Tsl       `json:"tsl"`
	Bme       Bme       `json:"bme280"`
}

func New(bus *smbus.Conn, addr uint8) (Sensors, error) {
	data := Sensors{
		Timestamp: time.Now().UTC(),
	}
	err := data.read(bus, addr)
	if err != nil {
		return Sensors{}, err
	}
	return data, nil
}

func (s *Sensors) read(bus *smbus.Conn, addr uint8) error {
	var err error
	err = s.Tsl.read(bus, addr, 0x80)
	if err != nil {
		return fmt.Errorf("tsl error: %v", err)
	}
	err = s.Bme.read(bus, addr, 0x80)
	if err != nil {
		return fmt.Errorf("bme error: %v", err)
	}
	return err
}

type Tsl struct {
	Lux  float64 `json:"lux"`
	Full uint16  `json:"full"`
	IR   uint16  `json:"ir"`
}

func (tsl *Tsl) read(bus *smbus.Conn, addr uint8, ch uint8) error {
	err := bus.WriteReg(addr, 0x04, ch)
	if err != nil {
		log.Printf("tsl-write-reg error: %v", err)
		return err
	}

	dev, err := tsl2591.Open(bus, tsl2591.Addr, tsl2591.IntegTime100ms, tsl2591.GainLow)
	if err != nil {
		log.Printf("tsl-open-bus error: %v", err)
		return err
	}

	full, ir, err := dev.FullLuminosity()
	if err != nil {
		log.Printf("tsl-sample error: %v", err)
		return err
	}

	tsl.Lux = dev.Lux(full, ir)
	tsl.Full = full
	tsl.IR = ir

	return err
}

type Bme struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
	Pres float64 `json:"pres"`
}

func (bme *Bme) read(bus *smbus.Conn, addr uint8, ch uint8) error {
	err := bus.WriteReg(addr, 0x04, ch)
	if err != nil {
		log.Printf("write-reg error: %v", err)
		return err
	}

	dev, err := bme280.Open(bus, bme280.I2CAddr, bme280.OpSample8)
	if err != nil {
		log.Printf("open-bus error (i2c-addr=0x%x): %v", bme280.I2CAddr, err)
		return err
	}

	h, p, t, err := dev.Sample()
	if err != nil {
		log.Printf("sample error: %v", err)
		return err
	}

	const HPa = 1.0 / 100.0
	bme.Hum = h
	bme.Pres = p * HPa
	bme.Temp = t

	return err
}
<commit_msg>tcp-srv/sensors: add AT30TSE75x sensor<commit_after>// Copyright 2017 The tcp-srv Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sensors exposes sensor data.
package sensors

import (
	"fmt"
	"log"
	"time"

	"github.com/go-daq/smbus"
	"github.com/go-daq/smbus/sensor/at30tse75x"
	"github.com/go-daq/smbus/sensor/bme280"
	"github.com/go-daq/smbus/sensor/tsl2591"
)

type Sensors struct {
	Timestamp time.Time `json:"timestamp"`
	Tsl       Tsl       `json:"tsl"`
	Bme       Bme       `json:"bme280"`
	At30tse   At30tse   `json:"at30tse"`
}

func New(bus *smbus.Conn, addr uint8) (Sensors, error) {
	data := Sensors{
		Timestamp: time.Now().UTC(),
	}
	err := data.read(bus, addr)
	if err != nil {
		return Sensors{}, err
	}
	return data, nil
}

func (s *Sensors) read(bus *smbus.Conn, addr uint8) error {
	var err error
	err = s.Tsl.read(bus, addr, 0x80)
	if err != nil {
		return fmt.Errorf("tsl error: %v", err)
	}
	err = s.Bme.read(bus, addr, 0x80)
	if err != nil {
		return fmt.Errorf("bme error: %v", err)
	}
	err = s.At30tse.read(bus, addr, 0x08)
	if err != nil {
		return fmt.Errorf("at30tse error: %v", err)
	}
	return err
}

type Tsl struct {
	Lux  float64 `json:"lux"`
	Full uint16  `json:"full"`
	IR   uint16  `json:"ir"`
}

func (tsl *Tsl) read(bus *smbus.Conn, addr uint8, ch uint8) error {
	err := bus.WriteReg(addr, 0x04, ch)
	if err != nil {
		log.Printf("tsl-write-reg error: %v", err)
		return err
	}

	dev, err := tsl2591.Open(bus, tsl2591.Addr, tsl2591.IntegTime100ms, tsl2591.GainLow)
	if err != nil {
		log.Printf("tsl-open-bus error: %v", err)
		return err
	}

	full, ir, err := dev.FullLuminosity()
	if err != nil {
		log.Printf("tsl-sample error: %v", err)
		return err
	}

	tsl.Lux = dev.Lux(full, ir)
	tsl.Full = full
	tsl.IR = ir

	return err
}

type Bme struct {
	Temp float64 `json:"temp"`
	Hum  float64 `json:"hum"`
	Pres float64 `json:"pres"`
}

func (bme *Bme) read(bus *smbus.Conn, addr uint8, ch uint8) error {
	err := bus.WriteReg(addr, 0x04, ch)
	if err != nil {
		log.Printf("write-reg error: %v", err)
		return err
	}

	dev, err := bme280.Open(bus, bme280.I2CAddr, bme280.OpSample8)
	if err != nil {
		log.Printf("open-bus error (i2c-addr=0x%x): %v", bme280.I2CAddr, err)
		return err
	}

	h, p, t, err := dev.Sample()
	if err != nil {
		log.Printf("sample error: %v", err)
		return err
	}

	const HPa = 1.0 / 100.0
	bme.Hum = h
	bme.Pres = p * HPa
	bme.Temp = t

	return err
}

type At30tse struct {
	Temp float64 `json:"temp"`
}

func (at30 *At30tse) read(bus *smbus.Conn, addr uint8, ch uint8) error {
	err := bus.WriteReg(addr, 0x04, ch)
	if err != nil {
		log.Printf("at30tse-write-reg error: %v", err)
		return err
	}

	const eeprom = 4
	dev, err := at30tse75x.Open(bus, 0, eeprom)
	if err != nil {
		log.Printf("at30tse-open-bus error: %v", err)
		return err
	}

	t, err := dev.T()
	if err != nil {
		log.Printf("at30tse-sample error: %v", err)
		return err
	}
	at30.Temp = t
	return nil
}
<|endoftext|>


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

package sensors

/*
#cgo LDFLAGS: -llog -landroid

#include <stdlib.h>
#include <android/sensor.h>

#include "sensors_android.h"
*/
import "C"
import "unsafe"

var (
	aStop chan struct{}
)

func init() {
	C.initSensors()
}

func startAccelerometer(fn func(deltaX, deltaY, deltaZ float64)) {
	aStop = make(chan struct{})
	go func() {
		// TODO(jbd): Need to runtime.LockOSThread?
		C.startAccelerometer()
		for {
			select {
			case <-aStop:
				return
			default:
				ev := C.pollAccelerometer()
				fn(float64(ev.x), float64(ev.y), float64(ev.z))
				C.free(unsafe.Pointer(ev))
			}
		}
	}()
}

func stopAccelerometer() {
	aStop <- struct{}{}
	C.destroyAccelerometer()
}
<commit_msg>allow the poller goroutine to be preempted and lock the os thread.<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sensors

/*
#cgo LDFLAGS: -llog -landroid

#include <stdlib.h>
#include <android/sensor.h>

#include "sensors_android.h"
*/
import "C"
import (
	"runtime"
	"unsafe"
)
import "time"

var (
	aStop chan struct{}
)

func init() {
	C.initSensors()
}

func startAccelerometer(fn func(deltaX, deltaY, deltaZ float64)) {
	aStop = make(chan struct{})
	go func() {
		// TODO(jbd): Need to runtime.LockOSThread?
		runtime.LockOSThread()
		C.startAccelerometer()
		for {
			select {
			case <-aStop:
				return
			default:
				ev := C.pollAccelerometer()
				fn(float64(ev.x), float64(ev.y), float64(ev.z))
				C.free(unsafe.Pointer(ev))
			}
			time.Sleep(time.Microsecond)
		}
	}()
}

func stopAccelerometer() {
	aStop <- struct{}{}
	C.destroyAccelerometer()
}
<|endoftext|>


<commit_before>package ltsv

import (
	"bytes"
	"testing"
	"io"
)

type readerTest struct {
	value  string
	records []map[string]string
}

var readerTests = []readerTest {
	{
		`host:127.0.0.1	ident:-	user:frank	time:[10/Oct/2000:13:55:36 -0700]	req:GET /apache_pb.gif

HTTP/1.0	status:200	size:2326	referer:http://www.example.com/start.html	ua:Mozilla/4.08 [en] (Win98; I ;Nav)
`,
		[]map[string]string{
			{"host": "127.0.0.1", "ident": "-", "user": "frank", "time": "[10/Oct/2000:13:55:36 -0700]", "req": "GET /apache_pb.gif"},
			{"status": "200", "size": "2326", "referer": "http://www.example.com/start.html", "ua": "Mozilla/4.08 [en] (Win98; I ;Nav)"},
		},
	},
	{
		` trimspace :こんにちは
		 trim space :こんばんは
日本語:ラベル
nolabelnofield
ha,s.p-un_ct: おはよう `,
		[]map[string]string{
			{"trimspace": "こんにちは"},
			{"trim space": "こんばんは"},
			{"日本語": "ラベル"},
			{"ha,s.p-un_ct": " おはよう "},
		},
	},
}

func TestReader(t *testing.T) {
	for n, test := range readerTests {
		reader := NewReader(bytes.NewBufferString(test.value))
		for i, result := range test.records {
			record, err := reader.Read()
			if err != nil {
				t.Errorf("error %v at test %d, line %d", err, n, i)
			}
			for label, field := range result {
				if record[label] != field {
					t.Errorf("wrong field %s: test %d, line %d, label %s, field %s", record[label], n, i, label, field)
				}
			}
			if len(result) != len(record) {
				t.Errorf("wrong size %d, %v :test %d, line %d", len(record), record, n, i)
			}
		}
		_, err := reader.Read()
		if err != io.EOF {
			t.Errorf("expected EOF: %v", err)
		}
	}
}

func TestWriter(t *testing.T) {
}
<commit_msg>add tests for Writer<commit_after>package ltsv

import (
	"bytes"
	"io"
	"testing"
)

type readerTest struct {
	value   string
	records []map[string]string
}

var readerTests = []readerTest{
	{
		`host:127.0.0.1	ident:-	user:frank	time:[10/Oct/2000:13:55:36 -0700]	req:GET /apache_pb.gif

HTTP/1.0	status:200	size:2326	referer:http://www.example.com/start.html	ua:Mozilla/4.08 [en] (Win98; I ;Nav)
`,
		[]map[string]string{
			{"host": "127.0.0.1", "ident": "-", "user": "frank", "time": "[10/Oct/2000:13:55:36 -0700]", "req": "GET /apache_pb.gif"},
			{"status": "200", "size": "2326", "referer": "http://www.example.com/start.html", "ua": "Mozilla/4.08 [en] (Win98; I ;Nav)"},
		},
	},
	{
		` trimspace :こんにちは
		 trim space :こんばんは
日本語:ラベル
nolabelnofield
ha,s.p-un_ct: おはよう `,
		[]map[string]string{
			{"trimspace": "こんにちは"},
			{"trim space": "こんばんは"},
			{"日本語": "ラベル"},
			{"ha,s.p-un_ct": " おはよう "},
		},
	},
}

func TestReaderRead(t *testing.T) {
	for n, test := range readerTests {
		reader := NewReader(bytes.NewBufferString(test.value))
		for i, result := range test.records {
			record, err := reader.Read()
			if err != nil {
				t.Errorf("error %v at test %d, line %d", err, n, i)
			}
			for label, field := range result {
				if record[label] != field {
					t.Errorf("wrong field %s at test %d, line %d, label %s, field %s", record[label], n, i, label, field)
				}
			}
			if len(result) != len(record) {
				t.Errorf("wrong size of record %d at test %d, line %d", len(record), n, i)
			}
		}
		_, err := reader.Read()
		if err == nil || err != io.EOF {
			t.Errorf("expected EOF got %v at test %d", err, n)
		}
	}
}

func TestWriterWrite(t *testing.T) {
	var buf bytes.Buffer
	for n, test := range readerTests {
		buf.Reset()
		writer := NewWriter(&buf)
		for i, record := range test.records {
			err := writer.Write(record)
			if err != nil {
				t.Errorf("error %v at test %d, line %d", err, n, i)
			}
		}
		writer.Flush()

		reader := NewReader(&buf)
		records, err := reader.ReadAll()
		if err != nil {
			t.Errorf("error %v at test %d", err, n)
			continue
		}
		if len(records) != len(test.records) {
			t.Errorf("wrong size of records %d at test %d", len(records), n)
		} else {
			for i := 0; i < len(test.records); i++ {
				record := records[i]
				result := test.records[i]
				for label, field := range result {
					if field != record[label] {
						t.Errorf("wrong field %s at test %d, line %d, label %s, field %s", record[label], n, i, label, field)
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package physics

import (
	"math"
)

type Vector struct {
	X, Y float64
}

func NewVector(x, y float64) *Vector {
	return &Vector{x, y}
}

func (v *Vector) Copy() *Vector {
	return NewVector(v.X, v.Y)
}

func (v *Vector) Magnitude() float64 {
	return math.Sqrt((v.X * v.X) + (v.Y * v.Y))
}

func (v *Vector) Normalize() *Vector {
	mgn := v.Magnitude()
	if mgn == 0 {
		return v
	}
	v.X /= mgn
	v.Y /= mgn
	return v
}

func (v *Vector) Zero() *Vector {
	v.X = 0
	v.Y = 0
	return v
}

func (v *Vector) Add(vs ...*Vector) *Vector {
	for _, v2 := range vs {
		v.X += v2.X
		v.Y += v2.Y
	}
	return v
}

func (v *Vector) Scale(fs ...float64) *Vector {
	f2 := 1.0
	for _, f := range fs {
		f2 *= f
	}
	v.X *= f2
	v.Y *= f2
	return v
}

func (v *Vector) Dot(v2 *Vector) float64 {
	x := v.X * v2.X
	y := v.Y * v2.Y
	return x + y
}
<commit_msg>Updated movement of enemies. Added positional audio for orb. Updated animation for trashcan and orb when moving<commit_after>package physics

import (
	"math"
)

type Vector struct {
	X, Y float64
}

func NewVector(x, y float64) *Vector {
	return &Vector{x, y}
}

func (v *Vector) Copy() *Vector {
	return NewVector(v.X, v.Y)
}

func (v *Vector) Magnitude() float64 {
	return math.Sqrt((v.X * v.X) + (v.Y * v.Y))
}

func (v *Vector) Normalize() *Vector {
	v = v.round()
	mgn := v.Magnitude()
	if mgn == 0 {
		return v
	}
	v.X /= mgn
	v.Y /= mgn
	return v
}

func (v *Vector) Zero() *Vector {
	v.X = 0
	v.Y = 0
	return v
}

func (v *Vector) Add(vs ...*Vector) *Vector {
	for _, v2 := range vs {
		v.X += v2.X
		v.Y += v2.Y
	}
	return v.round()
}

func (v *Vector) Scale(fs ...float64) *Vector {
	f2 := 1.0
	for _, f := range fs {
		f2 *= f
	}
	v.X *= f2
	v.Y *= f2
	return v.round()
}

func (v *Vector) Dot(v2 *Vector) float64 {
	x := v.X * v2.X
	y := v.Y * v2.Y
	return x + y
}

func (v *Vector) round() *Vector {
	CUTOFF := 0.001
	if math.Abs(v.X) < CUTOFF {
		v.X = 0
	}
	if math.Abs(v.Y) < CUTOFF {
		v.Y = 0
	}
	return v
}
<|endoftext|>