<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package sender_test

import (
	"errors"
	"fmt"
	"io"
	"net"
	"path"
	"runtime"
	"time"

	"github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	corecharm "gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/worker/metrics/sender"
	"github.com/juju/juju/worker/metrics/spool"
)

var _ = gc.Suite(&senderSuite{})

type senderSuite struct {
	spoolDir      string
	socketDir     string
	metricfactory spool.MetricFactory
}

func (s *senderSuite) SetUpTest(c *gc.C) {
	s.spoolDir = c.MkDir()
	s.socketDir = c.MkDir()

	s.metricfactory = &stubMetricFactory{
		&testing.Stub{},
		s.spoolDir,
	}

	declaredMetrics := map[string]corecharm.Metric{
		"pings": corecharm.Metric{Description: "test pings", Type: corecharm.MetricTypeAbsolute},
	}
	recorder, err := s.metricfactory.Recorder(declaredMetrics, "local:trusty/testcharm", "testcharm/0")
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.AddMetric("pings", "50", time.Now())
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.Close()
	c.Assert(err, jc.ErrorIsNil)

	reader, err := s.metricfactory.Reader()
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 1)

	testing.PatchValue(sender.SocketName, func(_, _ string) string {
		return sockPath(c)
	})
}

func (s *senderSuite) TestHandler(c *gc.C) {
	apiSender := newTestAPIMetricSender()
	tmpDir := c.MkDir()
	metricFactory := &stubMetricFactory{
		&testing.Stub{},
		tmpDir,
	}

	declaredMetrics := map[string]corecharm.Metric{
		"pings": corecharm.Metric{Description: "test pings", Type: corecharm.MetricTypeAbsolute},
	}
	recorder, err := metricFactory.Recorder(declaredMetrics, "local:trusty/testcharm", "testcharm/0")
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.AddMetric("pings", "50", time.Now())
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.Close()
	c.Assert(err, jc.ErrorIsNil)

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "")
	c.Assert(err, jc.ErrorIsNil)

	conn := &mockConnection{data: []byte(fmt.Sprintf("%v\n", tmpDir))}
	err = metricSender.Handle(conn)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)
	c.Assert(apiSender.batches[0].Tag, gc.Equals, "testcharm/0")
	c.Assert(apiSender.batches[0].Batch.CharmURL, gc.Equals, "local:trusty/testcharm")
	c.Assert(apiSender.batches[0].Batch.Metrics, gc.HasLen, 1)
	c.Assert(apiSender.batches[0].Batch.Metrics[0].Key, gc.Equals, "pings")
	c.Assert(apiSender.batches[0].Batch.Metrics[0].Value, gc.Equals, "50")
}

func (s *senderSuite) TestMetricSendingSuccess(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 0)
}

func (s *senderSuite) TestSendingGetDuplicate(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	apiErr := &params.Error{Message: "already exists", Code: params.CodeAlreadyExists}
	select {
	case apiSender.errors <- apiErr:
	default:
		c.Fatalf("blocked error channel")
	}

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 0)
}

func (s *senderSuite) TestSendingFails(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	select {
	case apiSender.sendError <- errors.New("something went wrong"):
	default:
		c.Fatalf("blocked error channel")
	}

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, gc.ErrorMatches, "something went wrong")

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 1)
}

func (s *senderSuite) TestNoSpoolDirectory(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	metricfactory := &stubMetricFactory{
		&testing.Stub{},
		"/some/random/spool/dir",
	}

	metricSender, err := sender.NewSender(apiSender, metricfactory, s.socketDir, "")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, gc.ErrorMatches, `failed to open spool directory "/some/random/spool/dir": .*`)

	c.Assert(apiSender.batches, gc.HasLen, 0)
}

func (s *senderSuite) TestNoMetricsToSend(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	newTmpSpoolDir := c.MkDir()
	metricfactory := &stubMetricFactory{
		&testing.Stub{},
		newTmpSpoolDir,
	}

	metricSender, err := sender.NewSender(apiSender, metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 0)
}

func newTestAPIMetricSender() *testAPIMetricSender {
	return &testAPIMetricSender{errors: make(chan error, 1), sendError: make(chan error, 1)}
}

type testAPIMetricSender struct {
	batches   []params.MetricBatchParam
	errors    chan error
	sendError chan error
}

func (t *testAPIMetricSender) AddMetricBatches(batches []params.MetricBatchParam) (map[string]error, error) {
	t.batches = batches

	var err error
	select {
	case e := <-t.errors:
		err = e
	default:
		err = (*params.Error)(nil)
	}

	var sendErr error
	select {
	case e := <-t.sendError:
		sendErr = e
	default:
		sendErr = nil
	}

	errors := make(map[string]error)
	for _, b := range batches {
		errors[b.Batch.UUID] = err
	}
	return errors, sendErr
}

type stubMetricFactory struct {
	*testing.Stub
	spoolDir string
}

func (s *stubMetricFactory) Recorder(declaredMetrics map[string]corecharm.Metric, charmURL, unitTag string) (spool.MetricRecorder, error) {
	s.MethodCall(s, "Recorder", declaredMetrics, charmURL, unitTag)
	config := spool.MetricRecorderConfig{
		SpoolDir: s.spoolDir,
		Metrics:  declaredMetrics,
		CharmURL: charmURL,
		UnitTag:  unitTag,
	}

	return spool.NewJSONMetricRecorder(config)
}

func (s *stubMetricFactory) Reader() (spool.MetricReader, error) {
	s.MethodCall(s, "Reader")
	return spool.NewJSONMetricReader(s.spoolDir)

}

type mockConnection struct {
	net.Conn
	testing.Stub
	data []byte
}

// SetDeadline implements the net.Conn interface.
func (c *mockConnection) SetDeadline(t time.Time) error {
	c.AddCall("SetDeadline", t)
	return nil
}

// Write implements the net.Conn interface.
func (c *mockConnection) Write(data []byte) (int, error) {
	c.AddCall("Write", data)
	c.data = data
	return len(data), nil
}

// Close implements the net.Conn interface.
func (c *mockConnection) Close() error {
	c.AddCall("Close")
	return nil
}

func (c mockConnection) eof() bool {
	return len(c.data) == 0
}

func (c *mockConnection) readByte() byte {
	b := c.data[0]
	c.data = c.data[1:]
	return b
}

func (c *mockConnection) Read(p []byte) (n int, err error) {
	if c.eof() {
		err = io.EOF
		return
	}
	if cp := cap(p); cp > 0 {
		for n < cp {
			p[n] = c.readByte()
			n++
			if c.eof() {
				break
			}
		}
	}
	return
}

func sockPath(c *gc.C) string {
	sockPath := path.Join(c.MkDir(), "test.listener")
	if runtime.GOOS == "windows" {
		return `\\.\pipe` + sockPath[2:]
	}
	return sockPath
}
<commit_msg>worker/metrics/sender: fix mutex copy bug in test<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package sender_test

import (
	"errors"
	"fmt"
	"io"
	"net"
	"path"
	"runtime"
	"time"

	"github.com/juju/testing"
	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"
	corecharm "gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/worker/metrics/sender"
	"github.com/juju/juju/worker/metrics/spool"
)

var _ = gc.Suite(&senderSuite{})

type senderSuite struct {
	spoolDir      string
	socketDir     string
	metricfactory spool.MetricFactory
}

func (s *senderSuite) SetUpTest(c *gc.C) {
	s.spoolDir = c.MkDir()
	s.socketDir = c.MkDir()

	s.metricfactory = &stubMetricFactory{
		&testing.Stub{},
		s.spoolDir,
	}

	declaredMetrics := map[string]corecharm.Metric{
		"pings": corecharm.Metric{Description: "test pings", Type: corecharm.MetricTypeAbsolute},
	}
	recorder, err := s.metricfactory.Recorder(declaredMetrics, "local:trusty/testcharm", "testcharm/0")
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.AddMetric("pings", "50", time.Now())
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.Close()
	c.Assert(err, jc.ErrorIsNil)

	reader, err := s.metricfactory.Reader()
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 1)

	testing.PatchValue(sender.SocketName, func(_, _ string) string {
		return sockPath(c)
	})
}

func (s *senderSuite) TestHandler(c *gc.C) {
	apiSender := newTestAPIMetricSender()
	tmpDir := c.MkDir()
	metricFactory := &stubMetricFactory{
		&testing.Stub{},
		tmpDir,
	}

	declaredMetrics := map[string]corecharm.Metric{
		"pings": corecharm.Metric{Description: "test pings", Type: corecharm.MetricTypeAbsolute},
	}
	recorder, err := metricFactory.Recorder(declaredMetrics, "local:trusty/testcharm", "testcharm/0")
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.AddMetric("pings", "50", time.Now())
	c.Assert(err, jc.ErrorIsNil)

	err = recorder.Close()
	c.Assert(err, jc.ErrorIsNil)

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "")
	c.Assert(err, jc.ErrorIsNil)

	conn := &mockConnection{data: []byte(fmt.Sprintf("%v\n", tmpDir))}
	err = metricSender.Handle(conn)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)
	c.Assert(apiSender.batches[0].Tag, gc.Equals, "testcharm/0")
	c.Assert(apiSender.batches[0].Batch.CharmURL, gc.Equals, "local:trusty/testcharm")
	c.Assert(apiSender.batches[0].Batch.Metrics, gc.HasLen, 1)
	c.Assert(apiSender.batches[0].Batch.Metrics[0].Key, gc.Equals, "pings")
	c.Assert(apiSender.batches[0].Batch.Metrics[0].Value, gc.Equals, "50")
}

func (s *senderSuite) TestMetricSendingSuccess(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 0)
}

func (s *senderSuite) TestSendingGetDuplicate(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	apiErr := &params.Error{Message: "already exists", Code: params.CodeAlreadyExists}
	select {
	case apiSender.errors <- apiErr:
	default:
		c.Fatalf("blocked error channel")
	}

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 0)
}

func (s *senderSuite) TestSendingFails(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	select {
	case apiSender.sendError <- errors.New("something went wrong"):
	default:
		c.Fatalf("blocked error channel")
	}

	metricSender, err := sender.NewSender(apiSender, s.metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, gc.ErrorMatches, "something went wrong")

	c.Assert(apiSender.batches, gc.HasLen, 1)

	reader, err := spool.NewJSONMetricReader(s.spoolDir)
	c.Assert(err, jc.ErrorIsNil)
	batches, err := reader.Read()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(batches, gc.HasLen, 1)
}

func (s *senderSuite) TestNoSpoolDirectory(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	metricfactory := &stubMetricFactory{
		&testing.Stub{},
		"/some/random/spool/dir",
	}

	metricSender, err := sender.NewSender(apiSender, metricfactory, s.socketDir, "")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, gc.ErrorMatches, `failed to open spool directory "/some/random/spool/dir": .*`)

	c.Assert(apiSender.batches, gc.HasLen, 0)
}

func (s *senderSuite) TestNoMetricsToSend(c *gc.C) {
	apiSender := newTestAPIMetricSender()

	newTmpSpoolDir := c.MkDir()
	metricfactory := &stubMetricFactory{
		&testing.Stub{},
		newTmpSpoolDir,
	}

	metricSender, err := sender.NewSender(apiSender, metricfactory, s.socketDir, "test-unit-0")
	c.Assert(err, jc.ErrorIsNil)
	stopCh := make(chan struct{})
	err = metricSender.Do(stopCh)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(apiSender.batches, gc.HasLen, 0)
}

func newTestAPIMetricSender() *testAPIMetricSender {
	return &testAPIMetricSender{errors: make(chan error, 1), sendError: make(chan error, 1)}
}

type testAPIMetricSender struct {
	batches   []params.MetricBatchParam
	errors    chan error
	sendError chan error
}

func (t *testAPIMetricSender) AddMetricBatches(batches []params.MetricBatchParam) (map[string]error, error) {
	t.batches = batches

	var err error
	select {
	case e := <-t.errors:
		err = e
	default:
		err = (*params.Error)(nil)
	}

	var sendErr error
	select {
	case e := <-t.sendError:
		sendErr = e
	default:
		sendErr = nil
	}

	errors := make(map[string]error)
	for _, b := range batches {
		errors[b.Batch.UUID] = err
	}
	return errors, sendErr
}

type stubMetricFactory struct {
	*testing.Stub
	spoolDir string
}

func (s *stubMetricFactory) Recorder(declaredMetrics map[string]corecharm.Metric, charmURL, unitTag string) (spool.MetricRecorder, error) {
	s.MethodCall(s, "Recorder", declaredMetrics, charmURL, unitTag)
	config := spool.MetricRecorderConfig{
		SpoolDir: s.spoolDir,
		Metrics:  declaredMetrics,
		CharmURL: charmURL,
		UnitTag:  unitTag,
	}

	return spool.NewJSONMetricRecorder(config)
}

func (s *stubMetricFactory) Reader() (spool.MetricReader, error) {
	s.MethodCall(s, "Reader")
	return spool.NewJSONMetricReader(s.spoolDir)

}

type mockConnection struct {
	net.Conn
	testing.Stub
	data []byte
}

// SetDeadline implements the net.Conn interface.
func (c *mockConnection) SetDeadline(t time.Time) error {
	c.AddCall("SetDeadline", t)
	return nil
}

// Write implements the net.Conn interface.
func (c *mockConnection) Write(data []byte) (int, error) {
	c.AddCall("Write", data)
	c.data = data
	return len(data), nil
}

// Close implements the net.Conn interface.
func (c *mockConnection) Close() error {
	c.AddCall("Close")
	return nil
}

func (c *mockConnection) eof() bool {
	return len(c.data) == 0
}

func (c *mockConnection) readByte() byte {
	b := c.data[0]
	c.data = c.data[1:]
	return b
}

func (c *mockConnection) Read(p []byte) (n int, err error) {
	if c.eof() {
		err = io.EOF
		return
	}
	if cp := cap(p); cp > 0 {
		for n < cp {
			p[n] = c.readByte()
			n++
			if c.eof() {
				break
			}
		}
	}
	return
}

func sockPath(c *gc.C) string {
	sockPath := path.Join(c.MkDir(), "test.listener")
	if runtime.GOOS == "windows" {
		return `\\.\pipe` + sockPath[2:]
	}
	return sockPath
}
<|endoftext|>


<commit_before>package blinkstick

import (
	"fmt"
	"image/color"

	"github.com/boombuler/hid"
)

// Version of Blinkstick
// One Line for this, used by release.sh script
// Keep "const Version on one line"
const Version = "0.0.1"

// VendorID blinkstick
const VendorID = 0x20a0

// ProductID blinkstick
const ProductID = 0x41e5

// USBDevice ...
type USBDevice struct {
	DeviceInfo *hid.DeviceInfo
	Device     *hid.Device
}

// Blinkstick represents a blinkstick device
type Blinkstick interface {
	List() []Blinkstick
	SetColor(color.Color) error
	GetDeviceInfo() *hid.DeviceInfo
	ListFilter(hid *hid.DeviceInfo) (bool, Blinkstick)
}

// SetColor set color
func (usbDevice *USBDevice) setColor(index byte, c color.Color) error {
	if usbDevice.Device == nil {
		if err := usbDevice.Open(); err != nil {
			return err
		}
	}
	r, g, b, _ := c.RGBA()
	d := *usbDevice.Device
	return d.WriteFeature([]byte{0x05, 0x00, index, byte(r >> 8), byte(g >> 8), byte(b >> 8)})
}

// Open open a device
func (usbDevice *USBDevice) Open() error {
	device, err := usbDevice.DeviceInfo.Open()
	if err != nil {
		return fmt.Errorf("Error while opening device: %s", err)
	}
	usbDevice.Device = &device
	return nil
}

// ListFilter is used to filter device on List
type ListFilter func(*hid.DeviceInfo) (bool, Blinkstick)

// List gets all blinkstick device
func List(opts ...ListFilter) []Blinkstick {
	out := []Blinkstick{}

	if len(opts) == 0 {
		opts = append(opts, Nano{}.ListFilter)
	}

	for di := range hid.Devices() {
		if di.VendorId == VendorID && di.ProductId == ProductID {
			for _, o := range opts {
				if toKeep, blinkstick := o(di); toKeep {
					out = append(out, blinkstick)
				}
			}

		}
	}
	return out
}
<commit_msg>[auto] bump version to v0.0.2<commit_after>package blinkstick

import (
	"fmt"
	"image/color"

	"github.com/boombuler/hid"
)

// Version of Blinkstick
// One Line for this, used by release.sh script
// Keep "const Version on one line"
const Version = "0.0.2"

// VendorID blinkstick
const VendorID = 0x20a0

// ProductID blinkstick
const ProductID = 0x41e5

// USBDevice ...
type USBDevice struct {
	DeviceInfo *hid.DeviceInfo
	Device     *hid.Device
}

// Blinkstick represents a blinkstick device
type Blinkstick interface {
	List() []Blinkstick
	SetColor(color.Color) error
	GetDeviceInfo() *hid.DeviceInfo
	ListFilter(hid *hid.DeviceInfo) (bool, Blinkstick)
}

// SetColor set color
func (usbDevice *USBDevice) setColor(index byte, c color.Color) error {
	if usbDevice.Device == nil {
		if err := usbDevice.Open(); err != nil {
			return err
		}
	}
	r, g, b, _ := c.RGBA()
	d := *usbDevice.Device
	return d.WriteFeature([]byte{0x05, 0x00, index, byte(r >> 8), byte(g >> 8), byte(b >> 8)})
}

// Open open a device
func (usbDevice *USBDevice) Open() error {
	device, err := usbDevice.DeviceInfo.Open()
	if err != nil {
		return fmt.Errorf("Error while opening device: %s", err)
	}
	usbDevice.Device = &device
	return nil
}

// ListFilter is used to filter device on List
type ListFilter func(*hid.DeviceInfo) (bool, Blinkstick)

// List gets all blinkstick device
func List(opts ...ListFilter) []Blinkstick {
	out := []Blinkstick{}

	if len(opts) == 0 {
		opts = append(opts, Nano{}.ListFilter)
	}

	for di := range hid.Devices() {
		if di.VendorId == VendorID && di.ProductId == ProductID {
			for _, o := range opts {
				if toKeep, blinkstick := o(di); toKeep {
					out = append(out, blinkstick)
				}
			}

		}
	}
	return out
}
<|endoftext|>


<commit_before>package colony

import (
	"image"
	"image/color"
	"image/draw"

	"engo.io/ecs"
	"engo.io/engo/common"
)

func uniformimg(c color.NRGBA, width, height float32) *image.NRGBA {
	iw, ih := int(width), int(height)

	bounds := image.Rect(0, 0, iw, ih)

	source := image.NewUniform(c)
	out := image.NewNRGBA(bounds)
	draw.Draw(out, bounds, source, image.ZP, draw.Src)

	return out
}

func imgtexture(img *image.NRGBA) *common.Texture {
	obj := common.NewImageObject(img)

	texture := common.NewTextureSingle(obj)
	return &texture
}

func basictext(text string, size float32) (*common.Texture, error) {
	fnt := stdfont()
	fnt.Size = float64(size)

	err := fnt.CreatePreloaded()

	if err != nil {
		return nil, err
	}

	texture := fnt.Render(text + " ")

	return &texture, nil
}

type ScreenDims struct {
	ScreenWidth float32
	ScreenHeight float32
}

func (sd ScreenDims) TextSize() float32 {
	return sd.ScreenWidth / 40
}

type CenterTiles struct {
	ViewSquareSize float32
	VSMinX float32
	VSMinY float32
	VSMaxX float32
	VSMaxY float32
}

func NewCenterTiles(sd ScreenDims) CenterTiles {
	tv := CenterTiles{}

	bound := sd.ScreenWidth
	bigger := sd.ScreenHeight
	if bound > bigger {
		bigger, bound = bound, bigger
	}

	margin := bound / 4
	tv.ViewSquareSize = bound - margin
	tv.VSMinX = (sd.ScreenWidth - tv.ViewSquareSize) / 2
	tv.VSMinY = (sd.ScreenHeight - tv.ViewSquareSize) / 2

	return tv
}

type HudSection struct {
	ecs.BasicEntity
	common.RenderComponent
	common.SpaceComponent
}

func hudmsg(msg string, size float32, position func(*common.Texture) (float32, float32)) *HudSection {
	texture, err := basictext(msg, size)

	if err != nil {
		panic(err)
	}

	x, y := position(texture)

	hud := &HudSection{}

	hud.BasicEntity = ecs.NewBasic()

	hud.SpaceComponent = spacecompsz(x, y, texture.Width(), texture.Height())

	hud.RenderComponent = rndcomp(texture)

	hud.RenderComponent.SetShader(common.HUDShader)
	hud.RenderComponent.SetZIndex(2)

	return hud
}

func hudbg(xmin, ymin, xmax, ymax float32) *HudSection {
	black := color.NRGBA{R:255, G: 255, B: 255, A: 255}

	img := uniformimg(black, xmax - xmin, ymax - ymin)

	texture := imgtexture(img)

	hud := &HudSection{}

	hud.BasicEntity = ecs.NewBasic()

	hud.SpaceComponent = spacecomprect(xmin, xmax, ymin, ymax)

	hud.RenderComponent = rndcomp(texture)

	hud.RenderComponent.SetShader(common.HUDShader)
	hud.RenderComponent.SetZIndex(1)

	return hud
}
<commit_msg>Tactical hud toolbar<commit_after>package colony

import (
	"image"
	"image/color"
	"image/draw"

	"engo.io/ecs"
	"engo.io/engo/common"
)

func uniformimg(c color.NRGBA, width, height float32) *image.NRGBA {
	iw, ih := int(width), int(height)

	bounds := image.Rect(0, 0, iw, ih)

	source := image.NewUniform(c)
	out := image.NewNRGBA(bounds)
	draw.Draw(out, bounds, source, image.ZP, draw.Src)

	return out
}

func imgtexture(img *image.NRGBA) *common.Texture {
	obj := common.NewImageObject(img)

	texture := common.NewTextureSingle(obj)
	return &texture
}

func basictext(text string, size float32) (*common.Texture, error) {
	fnt := stdfont()
	fnt.Size = float64(size)

	err := fnt.CreatePreloaded()

	if err != nil {
		return nil, err
	}

	texture := fnt.Render(text + " ")

	return &texture, nil
}

type ScreenDims struct {
	ScreenWidth float32
	ScreenHeight float32
}

func (sd ScreenDims) TextSize() float32 {
	return sd.ScreenWidth / 40
}

type CenterTiles struct {
	ViewSquareSize float32
	VSMinX float32
	VSMinY float32
	VSMaxX float32
	VSMaxY float32
}

func NewCenterTiles(sd ScreenDims) CenterTiles {
	tv := CenterTiles{}

	bound := sd.ScreenWidth
	bigger := sd.ScreenHeight
	if bound > bigger {
		bigger, bound = bound, bigger
	}

	margin := bound / 4
	tv.ViewSquareSize = bound - margin
	tv.VSMinX = (sd.ScreenWidth - tv.ViewSquareSize) / 2
	tv.VSMinY = (sd.ScreenHeight - tv.ViewSquareSize) / 2

	return tv
}

type HudSection struct {
	ecs.BasicEntity
	common.RenderComponent
	common.SpaceComponent
}

func hudmsg(msg string, size float32, position func(*common.Texture) (float32, float32)) *HudSection {
	texture, err := basictext(msg, size)

	if err != nil {
		panic(err)
	}

	x, y := position(texture)

	hud := &HudSection{}

	hud.BasicEntity = ecs.NewBasic()

	hud.SpaceComponent = spacecompsz(x, y, texture.Width(), texture.Height())

	hud.RenderComponent = rndcomp(texture)

	hud.RenderComponent.SetShader(common.HUDShader)
	hud.RenderComponent.SetZIndex(2)

	return hud
}

func hudbg(xmin, ymin, xmax, ymax float32) *HudSection {
	black := color.NRGBA{A: 255}

	img := uniformimg(black, xmax - xmin, ymax - ymin)

	texture := imgtexture(img)

	hud := &HudSection{}

	hud.BasicEntity = ecs.NewBasic()

	hud.SpaceComponent = spacecomprect(xmin, ymin, xmax, ymax)

	hud.RenderComponent = rndcomp(texture)

	hud.RenderComponent.SetShader(common.HUDShader)
	hud.RenderComponent.SetZIndex(1)

	return hud
}
<|endoftext|>


<commit_before>package rules

import (
	"fmt"
	"log"

	"github.com/terraform-linters/tflint/plugin"
	"github.com/terraform-linters/tflint/rules/awsrules"
	"github.com/terraform-linters/tflint/rules/terraformrules"
	"github.com/terraform-linters/tflint/tflint"
)

// Rule is an implementation that receives a Runner and inspects for resources and modules.
type Rule interface {
	Name() string
	Enabled() bool
	Check(runner *tflint.Runner) error
}

// DefaultRules is rules by default
var DefaultRules = append(manualDefaultRules, modelRules...)
var deepCheckRules = append(manualDeepCheckRules, apiRules...)

var manualDefaultRules = []Rule{
	awsrules.NewAwsDBInstanceDefaultParameterGroupRule(),
	awsrules.NewAwsDBInstanceInvalidTypeRule(),
	awsrules.NewAwsDBInstancePreviousTypeRule(),
	awsrules.NewAwsElastiCacheClusterDefaultParameterGroupRule(),
	awsrules.NewAwsElastiCacheClusterInvalidTypeRule(),
	awsrules.NewAwsElastiCacheClusterPreviousTypeRule(),
	awsrules.NewAwsInstancePreviousTypeRule(),
	awsrules.NewAwsRouteNotSpecifiedTargetRule(),
	awsrules.NewAwsRouteSpecifiedMultipleTargetsRule(),
	awsrules.NewAwsS3BucketInvalidACLRule(),
	awsrules.NewAwsS3BucketInvalidRegionRule(),
	awsrules.NewAwsSpotFleetRequestInvalidExcessCapacityTerminationPolicyRule(),
	terraformrules.NewTerraformDashInResourceNameRule(),
	terraformrules.NewTerraformDocumentedOutputsRule(),
	terraformrules.NewTerraformDocumentedVariablesRule(),
	terraformrules.NewTerraformModulePinnedSourceRule(),
}

var manualDeepCheckRules = []Rule{
	awsrules.NewAwsInstanceInvalidAMIRule(),
	awsrules.NewAwsLaunchConfigurationInvalidImageIDRule(),
}

// CheckRuleNames returns map of rules indexed by name
func CheckRuleNames(ruleNames []string, c *tflint.Config) error {
	log.Print("[INFO] Checking rules")

	rulesMap := map[string]Rule{}
	for _, rule := range append(DefaultRules, deepCheckRules...) {
		rulesMap[rule.Name()] = rule
	}

	pluginRules, err := plugin.NewRules(c)
	if err != nil {
		return err
	}
	for _, rule := range pluginRules {
		if _, exists := rulesMap[rule.Name()]; exists {
			return fmt.Errorf("Rule %s is duplicated. Rule names must be unique", rule.Name())
		}
		rulesMap[rule.Name()] = rule
	}

	totalEnabled := 0
	for _, rule := range rulesMap {
		if rule.Enabled() {
			totalEnabled++
		}
	}
	log.Printf("[INFO]   %d (%d) rules total", len(rulesMap), totalEnabled)
	for _, rule := range ruleNames {
		if _, ok := rulesMap[rule]; !ok {
			return fmt.Errorf("Rule not found: %s", rule)
		}
	}
	return nil
}

// NewRules returns rules according to configuration
func NewRules(c *tflint.Config) ([]Rule, error) {
	log.Print("[INFO] Prepare rules")

	ret := []Rule{}
	allRules := []Rule{}

	if c.DeepCheck {
		log.Printf("[DEBUG] Deep check mode is enabled. Add deep check rules")
		allRules = append(DefaultRules, deepCheckRules...)
	} else {
		allRules = DefaultRules
	}

	pluginRules, err := plugin.NewRules(c)
	if err != nil {
		return ret, err
	}
	for _, pluginRule := range pluginRules {
		allRules = append(allRules, pluginRule)
	}

	for _, rule := range allRules {
		enabled := rule.Enabled()
		if r := c.Rules[rule.Name()]; r != nil {
			if r.Enabled {
				log.Printf("[DEBUG] `%s` is enabled", rule.Name())
			} else {
				log.Printf("[DEBUG] `%s` is disabled", rule.Name())
			}
			enabled = r.Enabled
		}

		if enabled {
			ret = append(ret, rule)
		}
	}
	log.Printf("[INFO]   %d rules enabled", len(ret))
	return ret, nil
}
<commit_msg>Register tf_module_semver_source with the provider<commit_after>package rules

import (
	"fmt"
	"log"

	"github.com/terraform-linters/tflint/plugin"
	"github.com/terraform-linters/tflint/rules/awsrules"
	"github.com/terraform-linters/tflint/rules/terraformrules"
	"github.com/terraform-linters/tflint/tflint"
)

// Rule is an implementation that receives a Runner and inspects for resources and modules.
type Rule interface {
	Name() string
	Enabled() bool
	Check(runner *tflint.Runner) error
}

// DefaultRules is rules by default
var DefaultRules = append(manualDefaultRules, modelRules...)
var deepCheckRules = append(manualDeepCheckRules, apiRules...)

var manualDefaultRules = []Rule{
	awsrules.NewAwsDBInstanceDefaultParameterGroupRule(),
	awsrules.NewAwsDBInstanceInvalidTypeRule(),
	awsrules.NewAwsDBInstancePreviousTypeRule(),
	awsrules.NewAwsElastiCacheClusterDefaultParameterGroupRule(),
	awsrules.NewAwsElastiCacheClusterInvalidTypeRule(),
	awsrules.NewAwsElastiCacheClusterPreviousTypeRule(),
	awsrules.NewAwsInstancePreviousTypeRule(),
	awsrules.NewAwsRouteNotSpecifiedTargetRule(),
	awsrules.NewAwsRouteSpecifiedMultipleTargetsRule(),
	awsrules.NewAwsS3BucketInvalidACLRule(),
	awsrules.NewAwsS3BucketInvalidRegionRule(),
	awsrules.NewAwsSpotFleetRequestInvalidExcessCapacityTerminationPolicyRule(),
	terraformrules.NewTerraformDashInResourceNameRule(),
	terraformrules.NewTerraformDocumentedOutputsRule(),
	terraformrules.NewTerraformDocumentedVariablesRule(),
	terraformrules.NewTerraformModulePinnedSourceRule(),
	terraformrules.NewTerraformModuleSemverSourceRule(),
}

var manualDeepCheckRules = []Rule{
	awsrules.NewAwsInstanceInvalidAMIRule(),
	awsrules.NewAwsLaunchConfigurationInvalidImageIDRule(),
}

// CheckRuleNames returns map of rules indexed by name
func CheckRuleNames(ruleNames []string, c *tflint.Config) error {
	log.Print("[INFO] Checking rules")

	rulesMap := map[string]Rule{}
	for _, rule := range append(DefaultRules, deepCheckRules...) {
		rulesMap[rule.Name()] = rule
	}

	pluginRules, err := plugin.NewRules(c)
	if err != nil {
		return err
	}
	for _, rule := range pluginRules {
		if _, exists := rulesMap[rule.Name()]; exists {
			return fmt.Errorf("Rule %s is duplicated. Rule names must be unique", rule.Name())
		}
		rulesMap[rule.Name()] = rule
	}

	totalEnabled := 0
	for _, rule := range rulesMap {
		if rule.Enabled() {
			totalEnabled++
		}
	}
	log.Printf("[INFO]   %d (%d) rules total", len(rulesMap), totalEnabled)
	for _, rule := range ruleNames {
		if _, ok := rulesMap[rule]; !ok {
			return fmt.Errorf("Rule not found: %s", rule)
		}
	}
	return nil
}

// NewRules returns rules according to configuration
func NewRules(c *tflint.Config) ([]Rule, error) {
	log.Print("[INFO] Prepare rules")

	ret := []Rule{}
	allRules := []Rule{}

	if c.DeepCheck {
		log.Printf("[DEBUG] Deep check mode is enabled. Add deep check rules")
		allRules = append(DefaultRules, deepCheckRules...)
	} else {
		allRules = DefaultRules
	}

	pluginRules, err := plugin.NewRules(c)
	if err != nil {
		return ret, err
	}
	for _, pluginRule := range pluginRules {
		allRules = append(allRules, pluginRule)
	}

	for _, rule := range allRules {
		enabled := rule.Enabled()
		if r := c.Rules[rule.Name()]; r != nil {
			if r.Enabled {
				log.Printf("[DEBUG] `%s` is enabled", rule.Name())
			} else {
				log.Printf("[DEBUG] `%s` is disabled", rule.Name())
			}
			enabled = r.Enabled
		}

		if enabled {
			ret = append(ret, rule)
		}
	}
	log.Printf("[INFO]   %d rules enabled", len(ret))
	return ret, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"
)

import (
	. "github.com/modcloth/amqp-tools"
)

const (
	SUCCESS           = 0
	ARG_PARSING_ERROR = 1
	FATAL_ERROR       = 86
	PARTIAL_FAILURE   = 9
)

type DeliveryPropertiesHolder struct {
	ContentType            *string
	ContentEncoding        *string
	DeliveryMode           *uint
	Priority               *uint
	CorrelationIdGenerator NexterWrapper
	ReplyTo                *string
	Expiration             *string
	MessageIdGenerator     NexterWrapper
	Timestamp              *int64
	Type                   *string
	UserId                 *string
	AppId                  *string
}

func (me *DeliveryPropertiesHolder) DeliveryPropertiesGenerator() *DeliveryPropertiesGenerator {
	return &DeliveryPropertiesGenerator{
		ContentType:            *me.ContentType,
		ContentEncoding:        *me.ContentEncoding,
		DeliveryMode:           uint8(*me.DeliveryMode),
		Priority:               uint8(*me.Priority),
		CorrelationIdGenerator: &me.CorrelationIdGenerator,
		ReplyTo:                *me.ReplyTo,
		Expiration:             *me.Expiration,
		MessageIdGenerator:     &me.MessageIdGenerator,
		Timestamp:              *me.Timestamp,
		Type:                   *me.Type,
		UserId:                 *me.UserId,
		AppId:                  *me.AppId,
	}
}

var (
	deliveryProperties *DeliveryPropertiesHolder = new(DeliveryPropertiesHolder)
	amqpUri                                      = flag.String("uri", "", "AMQP connection URI")
	amqpUsername                                 = flag.String("user", "guest", "AMQP username")
	amqpPassword                                 = flag.String("password", "guest", "AMQP password")
	amqpHost                                     = flag.String("host", "localhost", "AMQP host")
	amqpVHost                                    = flag.String("vhost", "", "AMQP vhost")
	amqpPort                                     = flag.Int("port", 5672, "AMQP port")

	routingKey = flag.String("routing-key", "", "Publish message to routing key")
	mandatory  = flag.Bool("mandatory", false,
		"Publish message with mandatory property set.")
	immediate = flag.Bool("immediate", false,
		"Publish message with immediate property set.")

	usageString = `Usage: %s [options] <exchange> <file> [file file ...]

Publishes files as messages to a given exchange.  If there is only a single
filename entry and it is "-", then file names will be read from standard
input assuming entries delimited by at least a line feed ("\n").  Any extra
whitespace in each entry will be stripped before attempting to open the file.

`
)

func init() {
	deliveryProperties.ContentType = flag.String("content-type", "",
		"Content-type, else derived from file extension.")
	deliveryProperties.ContentEncoding = flag.String("content-encoding", "UTF-8",
		"Mime content-encoding.")
	deliveryProperties.DeliveryMode = flag.Uint("delivery-mode", 1,
		"Delivery mode (1 for non-persistent, 2 for persistent.")
	deliveryProperties.Priority = flag.Uint("priority", 0, "queue implementation use - 0 to 9")
	deliveryProperties.ReplyTo = flag.String("replyto", "", "application use - address to to reply to (ex: rpc)")
	deliveryProperties.Expiration = flag.String("expiration", "", "implementation use - message expiration spec")
	deliveryProperties.Timestamp = flag.Int64("timestamp", time.Now().Unix(), "unix timestamp of message")
	deliveryProperties.Type = flag.String("type", "", "application use - message type name")
	deliveryProperties.UserId = flag.String("userid", "", "application use - creating user - should be authenticated user")
	deliveryProperties.AppId = flag.String("appid", "", "application use - creating application id")

	flag.Var(&deliveryProperties.CorrelationIdGenerator,
		"correlationid",
		"'series' for incrementing ids, 'uuid' for UUIDs, static value otherwise")
	flag.Var(&deliveryProperties.MessageIdGenerator,
		"messageid",
		"'series' for incrementing ids, 'uuid' for UUIDs, static value otherwise")
}

type NexterWrapper struct{ nexter Nexter }

func (nw *NexterWrapper) Next() (string, error) {
	if nw.nexter == nil {
		nw.nexter = new(UUIDProvider)
	}
	return nw.nexter.Next()
}
func (nw *NexterWrapper) String() string { return "uuid" }
func (nw *NexterWrapper) Set(arg string) error {
	switch arg {
	case "uuid":
		nw.nexter = new(UUIDProvider)
	case "series":
		nw.nexter = new(SeriesProvider)
	default:
		nw.nexter = &StaticProvider{
			Value: arg,
		}
	}
	return nil
}

func main() {
	hadError := false

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usageString, filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() < 2 {
		fmt.Fprintf(os.Stderr,
			"ERROR: The exchange name and a list of file names are required\n")
		flag.Usage()
		os.Exit(ARG_PARSING_ERROR)
	}

	exchange := flag.Arg(0)
	files := flag.Args()[1:flag.NArg()]

	connectionUri := *amqpUri
	if len(connectionUri) < 1 {
		connectionUri = fmt.Sprintf("amqp://%s:%s@%s:%d/%s", *amqpUsername,
			*amqpPassword, *amqpHost, *amqpPort, *amqpVHost)
	}

	fileChan := make(chan string)
	resultChan := make(chan *PublishResult)

	go func() {
		defer close(fileChan)

		if len(files) == 1 && files[0] == "-" {
			log.Println("Reading files from stdin")
			stdin := bufio.NewReader(os.Stdin)
			for {
				line, err := stdin.ReadString('\n')
				if err != nil {
					if err != io.EOF {
						log.Println("ERROR:", err)
					}
					break
				}
				fileChan <- strings.TrimSpace(line)
			}
		} else {
			log.Println("Using files provided on command line")
			for _, file := range files {
				fileChan <- file
			}
		}
	}()

	go PublishFiles(fileChan, connectionUri, exchange, *routingKey,
		*mandatory, *immediate, deliveryProperties.DeliveryPropertiesGenerator(), resultChan)

	for result := range resultChan {
		if result.Error != nil {
			if result.IsFatal {
				log.Println("FATAL:", result.Message, result.Error)
				os.Exit(FATAL_ERROR)
			} else {
				log.Println("ERROR:", result.Message, result.Error)
				hadError = true
			}
		} else {
		  log.Println(result.Message)
		}
	}

	if hadError {
		os.Exit(PARTIAL_FAILURE)
	} else {
		os.Exit(SUCCESS)
	}
}
<commit_msg>Whitespace<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"
)

import (
	. "github.com/modcloth/amqp-tools"
)

const (
	SUCCESS           = 0
	ARG_PARSING_ERROR = 1
	FATAL_ERROR       = 86
	PARTIAL_FAILURE   = 9
)

type DeliveryPropertiesHolder struct {
	ContentType            *string
	ContentEncoding        *string
	DeliveryMode           *uint
	Priority               *uint
	CorrelationIdGenerator NexterWrapper
	ReplyTo                *string
	Expiration             *string
	MessageIdGenerator     NexterWrapper
	Timestamp              *int64
	Type                   *string
	UserId                 *string
	AppId                  *string
}

func (me *DeliveryPropertiesHolder) DeliveryPropertiesGenerator() *DeliveryPropertiesGenerator {
	return &DeliveryPropertiesGenerator{
		ContentType:            *me.ContentType,
		ContentEncoding:        *me.ContentEncoding,
		DeliveryMode:           uint8(*me.DeliveryMode),
		Priority:               uint8(*me.Priority),
		CorrelationIdGenerator: &me.CorrelationIdGenerator,
		ReplyTo:                *me.ReplyTo,
		Expiration:             *me.Expiration,
		MessageIdGenerator:     &me.MessageIdGenerator,
		Timestamp:              *me.Timestamp,
		Type:                   *me.Type,
		UserId:                 *me.UserId,
		AppId:                  *me.AppId,
	}
}

var (
	deliveryProperties *DeliveryPropertiesHolder = new(DeliveryPropertiesHolder)
	amqpUri                                      = flag.String("uri", "", "AMQP connection URI")
	amqpUsername                                 = flag.String("user", "guest", "AMQP username")
	amqpPassword                                 = flag.String("password", "guest", "AMQP password")
	amqpHost                                     = flag.String("host", "localhost", "AMQP host")
	amqpVHost                                    = flag.String("vhost", "", "AMQP vhost")
	amqpPort                                     = flag.Int("port", 5672, "AMQP port")

	routingKey = flag.String("routing-key", "", "Publish message to routing key")
	mandatory  = flag.Bool("mandatory", false,
		"Publish message with mandatory property set.")
	immediate = flag.Bool("immediate", false,
		"Publish message with immediate property set.")

	usageString = `Usage: %s [options] <exchange> <file> [file file ...]

Publishes files as messages to a given exchange.  If there is only a single
filename entry and it is "-", then file names will be read from standard
input assuming entries delimited by at least a line feed ("\n").  Any extra
whitespace in each entry will be stripped before attempting to open the file.

`
)

func init() {
	deliveryProperties.ContentType = flag.String("content-type", "",
		"Content-type, else derived from file extension.")
	deliveryProperties.ContentEncoding = flag.String("content-encoding", "UTF-8",
		"Mime content-encoding.")
	deliveryProperties.DeliveryMode = flag.Uint("delivery-mode", 1,
		"Delivery mode (1 for non-persistent, 2 for persistent.")
	deliveryProperties.Priority = flag.Uint("priority", 0, "queue implementation use - 0 to 9")
	deliveryProperties.ReplyTo = flag.String("replyto", "", "application use - address to to reply to (ex: rpc)")
	deliveryProperties.Expiration = flag.String("expiration", "", "implementation use - message expiration spec")
	deliveryProperties.Timestamp = flag.Int64("timestamp", time.Now().Unix(), "unix timestamp of message")
	deliveryProperties.Type = flag.String("type", "", "application use - message type name")
	deliveryProperties.UserId = flag.String("userid", "", "application use - creating user - should be authenticated user")
	deliveryProperties.AppId = flag.String("appid", "", "application use - creating application id")

	flag.Var(&deliveryProperties.CorrelationIdGenerator,
		"correlationid",
		"'series' for incrementing ids, 'uuid' for UUIDs, static value otherwise")
	flag.Var(&deliveryProperties.MessageIdGenerator,
		"messageid",
		"'series' for incrementing ids, 'uuid' for UUIDs, static value otherwise")
}

type NexterWrapper struct{ nexter Nexter }

func (nw *NexterWrapper) Next() (string, error) {
	if nw.nexter == nil {
		nw.nexter = new(UUIDProvider)
	}
	return nw.nexter.Next()
}
func (nw *NexterWrapper) String() string { return "uuid" }
func (nw *NexterWrapper) Set(arg string) error {
	switch arg {
	case "uuid":
		nw.nexter = new(UUIDProvider)
	case "series":
		nw.nexter = new(SeriesProvider)
	default:
		nw.nexter = &StaticProvider{
			Value: arg,
		}
	}
	return nil
}

func main() {
	hadError := false

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usageString, filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() < 2 {
		fmt.Fprintf(os.Stderr,
			"ERROR: The exchange name and a list of file names are required\n")
		flag.Usage()
		os.Exit(ARG_PARSING_ERROR)
	}

	exchange := flag.Arg(0)
	files := flag.Args()[1:flag.NArg()]

	connectionUri := *amqpUri
	if len(connectionUri) < 1 {
		connectionUri = fmt.Sprintf("amqp://%s:%s@%s:%d/%s", *amqpUsername,
			*amqpPassword, *amqpHost, *amqpPort, *amqpVHost)
	}

	fileChan := make(chan string)
	resultChan := make(chan *PublishResult)

	go func() {
		defer close(fileChan)

		if len(files) == 1 && files[0] == "-" {
			log.Println("Reading files from stdin")
			stdin := bufio.NewReader(os.Stdin)
			for {
				line, err := stdin.ReadString('\n')
				if err != nil {
					if err != io.EOF {
						log.Println("ERROR:", err)
					}
					break
				}
				fileChan <- strings.TrimSpace(line)
			}
		} else {
			log.Println("Using files provided on command line")
			for _, file := range files {
				fileChan <- file
			}
		}
	}()

	go PublishFiles(fileChan, connectionUri, exchange, *routingKey,
		*mandatory, *immediate, deliveryProperties.DeliveryPropertiesGenerator(), resultChan)

	for result := range resultChan {
		if result.Error != nil {
			if result.IsFatal {
				log.Println("FATAL:", result.Message, result.Error)
				os.Exit(FATAL_ERROR)
			} else {
				log.Println("ERROR:", result.Message, result.Error)
				hadError = true
			}
		} else {
			log.Println(result.Message)
		}
	}

	if hadError {
		os.Exit(PARTIAL_FAILURE)
	} else {
		os.Exit(SUCCESS)
	}
}
<|endoftext|>


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

// +build darwin freebsd linux netbsd openbsd

// Unix cryptographically secure pseudorandom number
// generator.

package rand

import (
	"bufio"
	"crypto/aes"
	"crypto/cipher"
	"io"
	"os"
	"sync"
	"time"
)

// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.

func init() { Reader = &devReader{name: "/dev/urandom"} }

// A devReader satisfies reads by reading the file named name.
type devReader struct {
	name string
	f    io.Reader
	mu   sync.Mutex
}

func (r *devReader) Read(b []byte) (n int, err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.f == nil {
		f, err := os.Open(r.name)
		if f == nil {
			return 0, err
		}
		r.f = bufio.NewReader(f)
	}
	return r.f.Read(b)
}

// Alternate pseudo-random implementation for use on
// systems without a reliable /dev/urandom.  So far we
// haven't needed it.

// newReader returns a new pseudorandom generator that
// seeds itself by reading from entropy.  If entropy == nil,
// the generator seeds itself by reading from the system's
// random number generator, typically /dev/random.
// The Read method on the returned reader always returns
// the full amount asked for, or else it returns an error.
//
// The generator uses the X9.31 algorithm with AES-128,
// reseeding after every 1 MB of generated data.
func newReader(entropy io.Reader) io.Reader {
	if entropy == nil {
		entropy = &devReader{name: "/dev/random"}
	}
	return &reader{entropy: entropy}
}

type reader struct {
	mu                   sync.Mutex
	budget               int // number of bytes that can be generated
	cipher               cipher.Block
	entropy              io.Reader
	time, seed, dst, key [aes.BlockSize]byte
}

func (r *reader) Read(b []byte) (n int, err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	n = len(b)

	for len(b) > 0 {
		if r.budget == 0 {
			_, err := io.ReadFull(r.entropy, r.seed[0:])
			if err != nil {
				return n - len(b), err
			}
			_, err = io.ReadFull(r.entropy, r.key[0:])
			if err != nil {
				return n - len(b), err
			}
			r.cipher, err = aes.NewCipher(r.key[0:])
			if err != nil {
				return n - len(b), err
			}
			r.budget = 1 << 20 // reseed after generating 1MB
		}
		r.budget -= aes.BlockSize

		// ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
		//
		// single block:
		// t = encrypt(time)
		// dst = encrypt(t^seed)
		// seed = encrypt(t^dst)
		ns := time.Now().UnixNano()
		r.time[0] = byte(ns >> 56)
		r.time[1] = byte(ns >> 48)
		r.time[2] = byte(ns >> 40)
		r.time[3] = byte(ns >> 32)
		r.time[4] = byte(ns >> 24)
		r.time[5] = byte(ns >> 16)
		r.time[6] = byte(ns >> 8)
		r.time[7] = byte(ns)
		r.cipher.Encrypt(r.time[0:], r.time[0:])
		for i := 0; i < aes.BlockSize; i++ {
			r.dst[i] = r.time[i] ^ r.seed[i]
		}
		r.cipher.Encrypt(r.dst[0:], r.dst[0:])
		for i := 0; i < aes.BlockSize; i++ {
			r.seed[i] = r.time[i] ^ r.dst[i]
		}
		r.cipher.Encrypt(r.seed[0:], r.seed[0:])

		m := copy(b, r.dst[0:])
		b = b[m:]
	}

	return n, nil
}
<commit_msg>crypto/rand: enable rand.Reader on plan9<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin freebsd linux netbsd openbsd plan9

// Unix cryptographically secure pseudorandom number
// generator.

package rand

import (
	"bufio"
	"crypto/aes"
	"crypto/cipher"
	"io"
	"os"
	"runtime"
	"sync"
	"time"
)

// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.

func init() {
	if runtime.GOOS == "plan9" {
		Reader = newReader(nil)
	} else {
		Reader = &devReader{name: "/dev/urandom"}
	}
}

// A devReader satisfies reads by reading the file named name.
type devReader struct {
	name string
	f    io.Reader
	mu   sync.Mutex
}

func (r *devReader) Read(b []byte) (n int, err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	if r.f == nil {
		f, err := os.Open(r.name)
		if f == nil {
			return 0, err
		}
		if runtime.GOOS == "plan9" {
			r.f = f
		} else {
			r.f = bufio.NewReader(f)
		}
	}
	return r.f.Read(b)
}

// Alternate pseudo-random implementation for use on
// systems without a reliable /dev/urandom.

// newReader returns a new pseudorandom generator that
// seeds itself by reading from entropy.  If entropy == nil,
// the generator seeds itself by reading from the system's
// random number generator, typically /dev/random.
// The Read method on the returned reader always returns
// the full amount asked for, or else it returns an error.
//
// The generator uses the X9.31 algorithm with AES-128,
// reseeding after every 1 MB of generated data.
func newReader(entropy io.Reader) io.Reader {
	if entropy == nil {
		entropy = &devReader{name: "/dev/random"}
	}
	return &reader{entropy: entropy}
}

type reader struct {
	mu                   sync.Mutex
	budget               int // number of bytes that can be generated
	cipher               cipher.Block
	entropy              io.Reader
	time, seed, dst, key [aes.BlockSize]byte
}

func (r *reader) Read(b []byte) (n int, err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	n = len(b)

	for len(b) > 0 {
		if r.budget == 0 {
			_, err := io.ReadFull(r.entropy, r.seed[0:])
			if err != nil {
				return n - len(b), err
			}
			_, err = io.ReadFull(r.entropy, r.key[0:])
			if err != nil {
				return n - len(b), err
			}
			r.cipher, err = aes.NewCipher(r.key[0:])
			if err != nil {
				return n - len(b), err
			}
			r.budget = 1 << 20 // reseed after generating 1MB
		}
		r.budget -= aes.BlockSize

		// ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
		//
		// single block:
		// t = encrypt(time)
		// dst = encrypt(t^seed)
		// seed = encrypt(t^dst)
		ns := time.Now().UnixNano()
		r.time[0] = byte(ns >> 56)
		r.time[1] = byte(ns >> 48)
		r.time[2] = byte(ns >> 40)
		r.time[3] = byte(ns >> 32)
		r.time[4] = byte(ns >> 24)
		r.time[5] = byte(ns >> 16)
		r.time[6] = byte(ns >> 8)
		r.time[7] = byte(ns)
		r.cipher.Encrypt(r.time[0:], r.time[0:])
		for i := 0; i < aes.BlockSize; i++ {
			r.dst[i] = r.time[i] ^ r.seed[i]
		}
		r.cipher.Encrypt(r.dst[0:], r.dst[0:])
		for i := 0; i < aes.BlockSize; i++ {
			r.seed[i] = r.time[i] ^ r.dst[i]
		}
		r.cipher.Encrypt(r.seed[0:], r.seed[0:])

		m := copy(b, r.dst[0:])
		b = b[m:]
	}

	return n, nil
}
<|endoftext|>


<commit_before>// Copyright 2009 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 parser

import (
	"go/ast";
	"go/parser";
	"os";
	"testing";
)

var illegalInputs = []interface{} {
	nil,
	3.14,
	[]byte(nil),
	"foo!",
}

func TestParseIllegalInputs(t *testing.T) {
	for _, src := range illegalInputs {
		prog, err := Parse(src, 0);
		if err == nil {
			t.Errorf("Parse(%v) should have failed", src);
		}
	}
}

var validPrograms = []interface{} {
	`package main`,
	`package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
}

func TestParseValidPrograms(t *testing.T) {
	for _, src := range validPrograms {
		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q) failed: %v", src, err);
		}
	}
}

var validFiles = []string {
	"parser.go",
	"parser_test.go",
}

func TestParse3(t *testing.T) {
	for _, filename := range validFiles {
		src, err := os.Open(filename, os.O_RDONLY, 0);
		defer src.Close();
		if err != nil {
			t.Fatalf("os.Open(%s): %v\n", filename, err);
		}

		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q): %v", src, err);
		}
	}
}
<commit_msg>fix error messages<commit_after>// Copyright 2009 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 parser

import (
	"go/ast";
	"go/parser";
	"os";
	"testing";
)

var illegalInputs = []interface{} {
	nil,
	3.14,
	[]byte(nil),
	"foo!",
}

func TestParseIllegalInputs(t *testing.T) {
	for _, src := range illegalInputs {
		prog, err := Parse(src, 0);
		if err == nil {
			t.Errorf("Parse(%v) should have failed", src);
		}
	}
}

var validPrograms = []interface{} {
	`package main`,
	`package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
}

func TestParseValidPrograms(t *testing.T) {
	for _, src := range validPrograms {
		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q) failed: %v", src, err);
		}
	}
}

var validFiles = []string {
	"parser.go",
	"parser_test.go",
}

func TestParse3(t *testing.T) {
	for _, filename := range validFiles {
		src, err := os.Open(filename, os.O_RDONLY, 0);
		defer src.Close();
		if err != nil {
			t.Fatal(err);
		}

		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%s): %v", filename, err);
		}
	}
}
<|endoftext|>


<commit_before>// Package serial provides high level interface to STM32 USART devices.
package serial

import (
	"stm32/usart"
)

// Dev wraps usart.Dev to provide high level interface to send and receive
// data using standard Read*/Write* methods family.
//
// It expects that provided usart.Dev is properly configured, has RxNotEmpty
// interrupt enabled and any other interrupts disabled. On its own Serial uses
// Status, Load, Store, EnableIRQs, DisableIRQs methods (last two are used to
// enable/disable TxEmpty and TxDone interrupts).
type Dev struct {
	dev    *usart.Dev
	rx     chan uint16
	tx     chan uint16
	txdone chan struct{}
	unix   bool
	flush  bool
}

// New creates new Dev for USART device with Rx/Tx buffer of specified
// lengths in 9-bit words.
func New(dev *usart.Dev, rxlen, txlen int) *Dev {
	s := new(Dev)
	s.dev = dev
	s.rx = make(chan uint16, rxlen)
	s.tx = make(chan uint16, txlen)
	s.txdone = make(chan struct{}, 1)
	return s
}

type Error uintptr

const (
	ErrBufferFull Error = 1 << (9 + iota)
	ErrParity
	ErrFraming
	ErrNoise
	ErrOverrun
)

func (e Error) Error() string {
	switch e {
	case 0:
		return "no error"
	case ErrBufferFull:
		return "buffer full"
	case ErrParity:
		return "parity error"
	case ErrFraming:
		return "framing error"
	case ErrNoise:
		return "noisy signal"
	case ErrOverrun:
		return "hardware buffer overrun"
	default:
		return "more than one from: ErrBufferFull, ErrParity, ErrFraming, ErrOverrun"
	}
}

const flushReq = 1 << 15

// IRQ should be called by USART interrupt handler.
func (s *Dev) IRQ() {
	st := s.dev.Status()
	if st&usart.RxNotEmpty != 0 {
		d := s.dev.Load() & 0x1ff
		// Add error bits
		d |= uint32(st&0xf) << 10
		if len(s.rx) >= cap(s.rx)-1 {
			d |= uint32(ErrBufferFull)
		}
		select {
		case s.rx <- uint16(d):
		default:
			// Rx channel is full.
		}
	}
	if s.flush {
		if st&usart.TxDone == 0 {
			return
		}
		s.dev.DisableIRQs(usart.TxDoneIRQ)
		s.flush = false
		s.txdone <- struct{}{}
	}
	if st&usart.TxEmpty != 0 {
		select {
		case d := <-s.tx:
			if d == flushReq {
				if st&usart.TxDone != 0 {
					// Fast path.
					s.txdone <- struct{}{}
					break
				}
				s.flush = true
				s.dev.EnableIRQs(usart.TxDoneIRQ)
				break
			}
			s.dev.Store(uint32(d))
		default:
			// Tx channel is empty.
			s.dev.DisableIRQs(usart.TxEmptyIRQ)
		}
	} else {
		s.dev.EnableIRQs(usart.TxEmptyIRQ)
	}
}

// Flush waits for complete transmission of last word (including its stop bits)
// written to s.
func (s *Dev) Flush() error {
	s.tx <- flushReq
	<-s.txdone
	return nil
}

// SetUnix enabls/disables unix text mode. If enabled, every readed '\r' is
// translated to '\n' and  every writed '\n' is translated to "\r\n". This
// simple translation works well for many terminal emulators but not for all.
func (s *Dev) SetUnix(enable bool) {
	s.unix = enable
}

// WriteBits can write 9-bit words to s. Text mode doesn't affect written data.
func (s *Dev) WriteBits(d uint16) error {
	s.tx <- d & 0x1ff
	s.dev.EnableIRQs(usart.TxEmptyIRQ)
	return nil
}

func (s *Dev) WriteByte(b byte) error {
	if s.unix && b == '\n' {
		s.WriteBits('\r')
	}
	s.WriteBits(uint16(b))
	return nil
}

func split(d16 uint16) (d9 uint16, err error) {
	if e := Error(d16) &^ 0x1ff; e != 0 {
		err = e
	}
	d9 = d16 & 0x1ff
	return
}

// ReadBits can read 9-bit words from s. Text mode doesn't affect read data.
func (s *Dev) ReadBits() (uint16, error) {
	return split(<-s.rx)
}

func (s *Dev) byte(d uint16) byte {
	b := byte(d)
	if s.unix && b == '\r' {
		b = '\n'
	}
	return b
}

func (s *Dev) ReadByte() (byte, error) {
	d, err := s.ReadBits()
	return s.byte(d), err
}

func (s *Dev) Write(buf []byte) (int, error) {
	for i, b := range buf {
		if err := s.WriteByte(b); err != nil {
			return i + 1, err
		}
	}
	return len(buf), nil
}

func (s *Dev) WriteString(str string) (int, error) {
	for i := 0; i < len(str); i++ {
		if e := s.WriteByte(str[i]); e != nil {
			return i + 1, e
		}
	}
	return len(str), nil
}

func (s *Dev) Read(buf []byte) (n int, err error) {
	if len(buf) == 0 {
		return
	}
	// Need to read at least one byte.
	buf[n], err = s.ReadByte()
	n++
	if err != nil {
		return
	}
	// Read next bytes until rx channel is empty.
	for n < len(buf) {
		select {
		case d := <-s.rx:
			d, err = split(d)
			buf[n] = s.byte(d)
			n++
			if err != nil {
				return
			}
		default:
			return
		}
	}
	return
}

// USART returns wrapped USART device.
func (s *Dev) USART() *usart.Dev {
	return s.dev
}
<commit_msg>serial: New SetFlushLF method.<commit_after>// Package serial provides high level interface to STM32 USART devices.
package serial

import (
	"stm32/usart"
)

// Dev wraps usart.Dev to provide high level interface to send and receive
// data using standard Read*/Write* methods family.
//
// It expects that provided usart.Dev is properly configured, has RxNotEmpty
// interrupt enabled and any other interrupts disabled. On its own Serial uses
// Status, Load, Store, EnableIRQs, DisableIRQs methods (last two are used to
// enable/disable TxEmpty and TxDone interrupts).
type Dev struct {
	dev    *usart.Dev
	rx     chan uint16
	tx     chan uint16
	txdone chan struct{}
	unix   bool
	flush  bool
	fllf   bool
}

// New creates new Dev for USART device with Rx/Tx buffer of specified
// lengths in 9-bit words.
func New(dev *usart.Dev, rxlen, txlen int) *Dev {
	s := new(Dev)
	s.dev = dev
	s.rx = make(chan uint16, rxlen)
	s.tx = make(chan uint16, txlen)
	s.txdone = make(chan struct{}, 1)
	return s
}

type Error uintptr

const (
	ErrBufferFull Error = 1 << (9 + iota)
	ErrParity
	ErrFraming
	ErrNoise
	ErrOverrun
)

func (e Error) Error() string {
	switch e {
	case 0:
		return "no error"
	case ErrBufferFull:
		return "buffer full"
	case ErrParity:
		return "parity error"
	case ErrFraming:
		return "framing error"
	case ErrNoise:
		return "noisy signal"
	case ErrOverrun:
		return "hardware buffer overrun"
	default:
		return "more than one from: ErrBufferFull, ErrParity, ErrFraming, ErrOverrun"
	}
}

const flushReq = 1 << 15

// IRQ should be called by USART interrupt handler.
func (s *Dev) IRQ() {
	st := s.dev.Status()
	if st&usart.RxNotEmpty != 0 {
		d := s.dev.Load() & 0x1ff
		// Add error bits
		d |= uint32(st&0xf) << 10
		if len(s.rx) >= cap(s.rx)-1 {
			d |= uint32(ErrBufferFull)
		}
		select {
		case s.rx <- uint16(d):
		default:
			// Rx channel is full.
		}
	}
	if s.flush {
		if st&usart.TxDone == 0 {
			return
		}
		s.dev.DisableIRQs(usart.TxDoneIRQ)
		s.flush = false
		s.txdone <- struct{}{}
	}
	if st&usart.TxEmpty != 0 {
		select {
		case d := <-s.tx:
			if d == flushReq {
				if st&usart.TxDone != 0 {
					// Fast path.
					s.txdone <- struct{}{}
					break
				}
				s.flush = true
				s.dev.EnableIRQs(usart.TxDoneIRQ)
				break
			}
			s.dev.Store(uint32(d))
		default:
			// Tx channel is empty.
			s.dev.DisableIRQs(usart.TxEmptyIRQ)
		}
	} else {
		s.dev.EnableIRQs(usart.TxEmptyIRQ)
	}
}

// Flush waits for complete transmission of last word (including its stop bits)
// written to s.
func (s *Dev) Flush() error {
	s.tx <- flushReq
	<-s.txdone
	return nil
}

// SetUnix enabls/disables unix text mode. If enabled, every readed '\r' is
// translated to '\n' and  every writed '\n' is translated to "\r\n". This
// simple translation works well for many terminal emulators but not for all.
func (s *Dev) SetUnix(enable bool) {
	s.unix = enable
}

// SetFlushLF enables/disables automatic flush after every '\n'.
func (s *Dev) SetFlushLF(enable bool) {
	s.fllf = enabld
}

// WriteBits can write 9-bit words to s. Text mode doesn't affect written data.
func (s *Dev) WriteBits(d uint16) error {
	s.tx <- d & 0x1ff
	s.dev.EnableIRQs(usart.TxEmptyIRQ)
	return nil
}

func (s *Dev) WriteByte(b byte) error {
	if s.unix && b == '\n' {
		s.WriteBits('\r')
	}
	s.WriteBits(uint16(b))
	if s.fllf && b == '\n' {
		s.Flush()
	}
	return nil
}

func split(d16 uint16) (d9 uint16, err error) {
	if e := Error(d16) &^ 0x1ff; e != 0 {
		err = e
	}
	d9 = d16 & 0x1ff
	return
}

// ReadBits can read 9-bit words from s. Text mode doesn't affect read data.
func (s *Dev) ReadBits() (uint16, error) {
	return split(<-s.rx)
}

func (s *Dev) byte(d uint16) byte {
	b := byte(d)
	if s.unix && b == '\r' {
		b = '\n'
	}
	return b
}

func (s *Dev) ReadByte() (byte, error) {
	d, err := s.ReadBits()
	return s.byte(d), err
}

func (s *Dev) Write(buf []byte) (int, error) {
	for i, b := range buf {
		if err := s.WriteByte(b); err != nil {
			return i + 1, err
		}
	}
	return len(buf), nil
}

func (s *Dev) WriteString(str string) (int, error) {
	for i := 0; i < len(str); i++ {
		if e := s.WriteByte(str[i]); e != nil {
			return i + 1, e
		}
	}
	return len(str), nil
}

func (s *Dev) Read(buf []byte) (n int, err error) {
	if len(buf) == 0 {
		return
	}
	// Need to read at least one byte.
	buf[n], err = s.ReadByte()
	n++
	if err != nil {
		return
	}
	// Read next bytes until rx channel is empty.
	for n < len(buf) {
		select {
		case d := <-s.rx:
			d, err = split(d)
			buf[n] = s.byte(d)
			n++
			if err != nil {
				return
			}
		default:
			return
		}
	}
	return
}

// USART returns wrapped USART device.
func (s *Dev) USART() *usart.Dev {
	return s.dev
}
<|endoftext|>


<commit_before>package vegeta

import (
	"fmt"
	"net"
	"net/http"
	"net/http/httptest"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

func TestAttackRate(t *testing.T) {
	t.Parallel()

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
	)
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})
	rate := uint64(100)
	atk := NewAttacker()
	var hits uint64
	for _ = range atk.Attack(tr, rate, 1*time.Second) {
		hits++
	}
	if hits != rate {
		t.Fatalf("Wrong number of hits: want %d, got %d\n", rate, hits)
	}
}

func TestDefaultAttackerCertConfig(t *testing.T) {
	t.Parallel()

	server := httptest.NewTLSServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
	)
	atk := NewAttacker()
	request, _ := http.NewRequest("GET", server.URL, nil)
	_, err := atk.client.Do(request)
	if err != nil && strings.Contains(err.Error(), "x509: certificate signed by unknown authority") {
		t.Errorf("Invalid certificates should be ignored: Got `%s`", err)
	}
}

func TestRedirects(t *testing.T) {
	t.Parallel()

	var servers [2]*httptest.Server
	var hits uint64

	for i := range servers {
		servers[i] = httptest.NewServer(
			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				atomic.AddUint64(&hits, 1)
				http.Redirect(w, r, servers[(i+1)%2].URL, 302)
			}),
		)
	}

	atk := NewAttacker(Redirects(2))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: servers[0].URL})
	var rate uint64 = 10
	results := atk.Attack(tr, rate, 1*time.Second)

	want := fmt.Sprintf("stopped after %d redirects", 2)
	for result := range results {
		if !strings.Contains(result.Error, want) {
			t.Fatalf("Expected error to be: %s, Got: %s", want, result.Error)
		}
	}

	if want, got := rate*(2+1), hits; want != got {
		t.Fatalf("Expected hits to be: %d, Got: %d", want, got)
	}
}

func TestTimeout(t *testing.T) {
	t.Parallel()

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			<-time.After(20 * time.Millisecond)
		}),
	)

	atk := NewAttacker(Timeout(10 * time.Millisecond))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})
	results := atk.Attack(tr, 1, 1*time.Second)

	want := "net/http: timeout awaiting response headers"
	for result := range results {
		if !strings.Contains(result.Error, want) {
			t.Fatalf("Expected error to be: %s, Got: %s", want, result.Error)
		}
	}
}

func TestLocalAddr(t *testing.T) {
	t.Parallel()

	addr, err := net.ResolveIPAddr("ip", "127.0.0.1")
	if err != nil {
		t.Fatal(err)
	}

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			host, _, err := net.SplitHostPort(r.RemoteAddr)
			if err != nil {
				t.Fatal(err)
			}

			if host != addr.String() {
				t.Fatalf("Wrong source address. Want %s, Got %s", addr, host)
			}
		}),
	)

	atk := NewAttacker(LocalAddr(*addr))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})

	for result := range atk.Attack(tr, 1, 1*time.Second) {
		if result.Error != "" {
			t.Fatal(result.Error)
		}
	}
}

func TestKeepAlive(t *testing.T) {
	t.Parallel()

	atk := NewAttacker(KeepAlive(false))

	if atk.dialer.KeepAlive != 0 {
		t.Fatalf("Dialer KeepAlive is not disabled. Want 0. Got %d", atk.dialer.KeepAlive)
	}

	disableKeepAlive := atk.client.Transport.(*http.Transport).DisableKeepAlives
	if disableKeepAlive == false {
		t.Fatalf("Transport DisableKeepAlives is not enabled. Want true. Got %s", disableKeepAlive)
	}
}
<commit_msg>Fix fmt of bool for go vet<commit_after>package vegeta

import (
	"fmt"
	"net"
	"net/http"
	"net/http/httptest"
	"strings"
	"sync/atomic"
	"testing"
	"time"
)

func TestAttackRate(t *testing.T) {
	t.Parallel()

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
	)
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})
	rate := uint64(100)
	atk := NewAttacker()
	var hits uint64
	for _ = range atk.Attack(tr, rate, 1*time.Second) {
		hits++
	}
	if hits != rate {
		t.Fatalf("Wrong number of hits: want %d, got %d\n", rate, hits)
	}
}

func TestDefaultAttackerCertConfig(t *testing.T) {
	t.Parallel()

	server := httptest.NewTLSServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
	)
	atk := NewAttacker()
	request, _ := http.NewRequest("GET", server.URL, nil)
	_, err := atk.client.Do(request)
	if err != nil && strings.Contains(err.Error(), "x509: certificate signed by unknown authority") {
		t.Errorf("Invalid certificates should be ignored: Got `%s`", err)
	}
}

func TestRedirects(t *testing.T) {
	t.Parallel()

	var servers [2]*httptest.Server
	var hits uint64

	for i := range servers {
		servers[i] = httptest.NewServer(
			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				atomic.AddUint64(&hits, 1)
				http.Redirect(w, r, servers[(i+1)%2].URL, 302)
			}),
		)
	}

	atk := NewAttacker(Redirects(2))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: servers[0].URL})
	var rate uint64 = 10
	results := atk.Attack(tr, rate, 1*time.Second)

	want := fmt.Sprintf("stopped after %d redirects", 2)
	for result := range results {
		if !strings.Contains(result.Error, want) {
			t.Fatalf("Expected error to be: %s, Got: %s", want, result.Error)
		}
	}

	if want, got := rate*(2+1), hits; want != got {
		t.Fatalf("Expected hits to be: %d, Got: %d", want, got)
	}
}

func TestTimeout(t *testing.T) {
	t.Parallel()

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			<-time.After(20 * time.Millisecond)
		}),
	)

	atk := NewAttacker(Timeout(10 * time.Millisecond))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})
	results := atk.Attack(tr, 1, 1*time.Second)

	want := "net/http: timeout awaiting response headers"
	for result := range results {
		if !strings.Contains(result.Error, want) {
			t.Fatalf("Expected error to be: %s, Got: %s", want, result.Error)
		}
	}
}

func TestLocalAddr(t *testing.T) {
	t.Parallel()

	addr, err := net.ResolveIPAddr("ip", "127.0.0.1")
	if err != nil {
		t.Fatal(err)
	}

	server := httptest.NewServer(
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			host, _, err := net.SplitHostPort(r.RemoteAddr)
			if err != nil {
				t.Fatal(err)
			}

			if host != addr.String() {
				t.Fatalf("Wrong source address. Want %s, Got %s", addr, host)
			}
		}),
	)

	atk := NewAttacker(LocalAddr(*addr))
	tr := NewStaticTargeter(&Target{Method: "GET", URL: server.URL})

	for result := range atk.Attack(tr, 1, 1*time.Second) {
		if result.Error != "" {
			t.Fatal(result.Error)
		}
	}
}

func TestKeepAlive(t *testing.T) {
	t.Parallel()

	atk := NewAttacker(KeepAlive(false))

	if atk.dialer.KeepAlive != 0 {
		t.Fatalf("Dialer KeepAlive is not disabled. Want 0. Got %d", atk.dialer.KeepAlive)
	}

	disableKeepAlive := atk.client.Transport.(*http.Transport).DisableKeepAlives
	if disableKeepAlive == false {
		t.Fatalf("Transport DisableKeepAlives is not enabled. Want true. Got %t", disableKeepAlive)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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.

// The cmdline provider fetches a remote configuration from the URL specified
// in the kernel boot option "coreos.config.url".

package cmdline

import (
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
)

const (
	name           = "cmdline"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	cmdlinePath    = "/proc/cmdline"
	cmdlineUrlFlag = "coreos.config.url"
	oemMountPath   = "/mnt/oem"               // Mountpoint where oem partition is mounted when present.
	oemDirPath     = "/sysroot/usr/share/oem" // OEM dir within root fs to consider for pxe scenarios.
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		path:    cmdlinePath,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	path      string
	client    *http.Client
	configUrl string
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	if p.rawConfig == nil {
		return config.Config{}, nil
	} else {
		return config.Parse(p.rawConfig)
	}
}

func (p *provider) IsOnline() bool {
	if p.configUrl == "" {
		args, err := ioutil.ReadFile(p.path)
		if err != nil {
			p.logger.Err("couldn't read cmdline")
			return false
		}

		p.configUrl = parseCmdline(args)
		p.logger.Debug("parsed url from cmdline: %q", p.configUrl)
		if p.configUrl == "" {
			// If the cmdline flag wasn't provided, just no-op.
			p.logger.Info("no config URL provided")
			return true
		}
	}

	return p.getRawConfig()

}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

func parseCmdline(cmdline []byte) (url string) {
	for _, arg := range strings.Split(string(cmdline), " ") {
		parts := strings.SplitN(strings.TrimSpace(arg), "=", 2)
		key := parts[0]

		if key != cmdlineUrlFlag {
			continue
		}

		if len(parts) == 2 {
			url = parts[1]
		}
	}

	return
}

// getRawConfig gets the raw configuration data from p.configUrl.
// Supported URL schemes are:
// http://	remote resource accessed via http
// oem://	local file in /sysroot/usr/share/oem or /mnt/oem
func (p *provider) getRawConfig() bool {
	url, err := url.Parse(p.configUrl)
	if err != nil {
		p.logger.Err("failed to parse url: %v", err)
		return false
	}

	switch url.Scheme {
	case "http":
		if resp, err := p.client.Get(p.configUrl); err == nil {
			defer resp.Body.Close()

			switch resp.StatusCode {
			case http.StatusOK, http.StatusNoContent:
			default:
				p.logger.Debug("failed fetching: HTTP status: %s",
					resp.Status)
				return false
			}

			p.logger.Debug("successfully fetched")
			p.rawConfig, err = ioutil.ReadAll(resp.Body)
			if err != nil {
				p.logger.Err("failed to read body: %v", err)
				return false
			}
		} else {
			p.logger.Warning("failed fetching: %v", err)
			return false
		}
	case "oem":
		path := filepath.Clean(url.Path)
		if !filepath.IsAbs(path) {
			p.logger.Err("oem path is not absolute: %q", url.Path)
			return false
		}

		absPath := filepath.Join(oemMountPath, path)
		p.rawConfig, err = ioutil.ReadFile(absPath)
		if os.IsNotExist(err) {
			p.logger.Info("oem config not found in %q, trying %q",
				oemMountPath, oemDirPath)
			absPath = filepath.Join(oemDirPath, path)
			p.rawConfig, err = ioutil.ReadFile(absPath)
		}

		if err != nil {
			p.logger.Err("failed to read oem config: %v", err)
			return false
		}
	default:
		p.logger.Err("unsupported url scheme: %q", url.Scheme)
		return false
	}

	return true
}
<commit_msg>providers/cmdline: mount oem partition for oem:// if needed<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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.

// The cmdline provider fetches a remote configuration from the URL specified
// in the kernel boot option "coreos.config.url".

package cmdline

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
	"github.com/coreos/ignition/src/systemd"
)

const (
	name           = "cmdline"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	cmdlinePath    = "/proc/cmdline"
	cmdlineUrlFlag = "coreos.config.url"
	oemDevicePath  = "/dev/disk/by-label/OEM" // Device link where oem partition is found.
	oemDirPath     = "/sysroot/usr/share/oem" // OEM dir within root fs to consider for pxe scenarios.
	oemMountPath   = "/mnt/oem"               // Mountpoint where oem partition is mounted when present.
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		path:    cmdlinePath,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	path      string
	client    *http.Client
	configUrl string
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	if p.rawConfig == nil {
		return config.Config{}, nil
	} else {
		return config.Parse(p.rawConfig)
	}
}

func (p *provider) IsOnline() bool {
	if p.configUrl == "" {
		args, err := ioutil.ReadFile(p.path)
		if err != nil {
			p.logger.Err("couldn't read cmdline")
			return false
		}

		p.configUrl = parseCmdline(args)
		p.logger.Debug("parsed url from cmdline: %q", p.configUrl)
		if p.configUrl == "" {
			// If the cmdline flag wasn't provided, just no-op.
			p.logger.Info("no config URL provided")
			return true
		}
	}

	return p.getRawConfig()

}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

func parseCmdline(cmdline []byte) (url string) {
	for _, arg := range strings.Split(string(cmdline), " ") {
		parts := strings.SplitN(strings.TrimSpace(arg), "=", 2)
		key := parts[0]

		if key != cmdlineUrlFlag {
			continue
		}

		if len(parts) == 2 {
			url = parts[1]
		}
	}

	return
}

// getRawConfig gets the raw configuration data from p.configUrl.
// Supported URL schemes are:
// http://	remote resource accessed via http
// oem://	local file in /sysroot/usr/share/oem or /mnt/oem
func (p *provider) getRawConfig() bool {
	url, err := url.Parse(p.configUrl)
	if err != nil {
		p.logger.Err("failed to parse url: %v", err)
		return false
	}

	switch url.Scheme {
	case "http":
		if resp, err := p.client.Get(p.configUrl); err == nil {
			defer resp.Body.Close()

			switch resp.StatusCode {
			case http.StatusOK, http.StatusNoContent:
			default:
				p.logger.Debug("failed fetching: HTTP status: %s",
					resp.Status)
				return false
			}

			p.logger.Debug("successfully fetched")
			p.rawConfig, err = ioutil.ReadAll(resp.Body)
			if err != nil {
				p.logger.Err("failed to read body: %v", err)
				return false
			}
		} else {
			p.logger.Warning("failed fetching: %v", err)
			return false
		}
	case "oem":
		path := filepath.Clean(url.Path)
		if !filepath.IsAbs(path) {
			p.logger.Err("oem path is not absolute: %q", url.Path)
			return false
		}

		// check if present under oemDirPath, if so use it.
		absPath := filepath.Join(oemDirPath, path)
		p.rawConfig, err = ioutil.ReadFile(absPath)
		if os.IsNotExist(err) {
			p.logger.Info("oem config not found in %q, trying %q",
				oemDirPath, oemMountPath)

			// try oemMountPath, requires mounting it.
			err = p.mountOEM()
			if err == nil {
				absPath := filepath.Join(oemMountPath, path)
				p.rawConfig, err = ioutil.ReadFile(absPath)
				p.umountOEM()
			}
		}

		if err != nil {
			p.logger.Err("failed to read oem config: %v", err)
			return false
		}
	default:
		p.logger.Err("unsupported url scheme: %q", url.Scheme)
		return false
	}

	return true
}

// mountOEM waits for the presence of and mounts the oem partition @ oemMountPath.
func (p *provider) mountOEM() error {
	dev := []string{oemDevicePath}
	if err := systemd.WaitOnDevices(dev, "oem-cmdline"); err != nil {
		p.logger.Err("failed to wait for oem device: %v", err)
		return err
	}

	if err := p.logger.LogOp(
		func() error {
			return syscall.Mount(dev[0], oemMountPath, "ext4", 0, "")
		},
		"mounting %q at %q", oemDevicePath, oemMountPath,
	); err != nil {
		return fmt.Errorf("failed to mount device %q at %q: %v",
			oemDevicePath, oemMountPath, err)
	}

	return nil
}

// umountOEM unmounts the oem partition @ oemMountPath.
func (p *provider) umountOEM() {
	p.logger.LogOp(
		func() error { return syscall.Unmount(oemMountPath, 0) },
		"unmounting %q", oemMountPath,
	)
}
<|endoftext|>


<commit_before>package integration_test

import (
	"bufio"
	"context"
	"fmt"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"

	"k8s.io/client-go/tools/clientcmd/api"

	"github.com/datawire/dlib/dtime"
	"github.com/telepresenceio/telepresence/v2/integration_test/itest"
	"github.com/telepresenceio/telepresence/v2/pkg/filelocation"
	"github.com/telepresenceio/telepresence/v2/pkg/vif/routing"
)

func getClusterIPs(cluster *api.Cluster) ([]net.IP, error) {
	var ips []net.IP
	svcUrl, err := url.Parse(cluster.Server)
	if err != nil {
		return nil, err
	}
	hostname := svcUrl.Hostname()
	if rawIP := net.ParseIP(hostname); rawIP != nil {
		ips = []net.IP{rawIP}
	} else {
		ips, err = net.LookupIP(hostname)
		if err != nil {
			return nil, err
		}
	}
	return ips, nil
}

func (s *notConnectedSuite) Test_APIServerIsProxied() {
	require := s.Require()
	var ips []net.IP
	ctx := itest.WithKubeConfigExtension(s.Context(), func(cluster *api.Cluster) map[string]interface{} {
		var apiServers []string
		var err error
		ips, err = getClusterIPs(cluster)
		require.NoError(err)
		for _, ip := range ips {
			apiServers = append(apiServers, fmt.Sprintf(`%s/24`, ip))
		}
		return map[string]interface{}{"also-proxy": apiServers}
	})

	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)
	stdout := itest.TelepresenceOk(ctx, "status")
	require.Contains(stdout, fmt.Sprintf("Also Proxy : (%d subnets)", len(ips)))
	for _, ip := range ips {
		rng := make(net.IP, len(ip))
		copy(rng[:], ip)
		rng[len(rng)-1] = 0
		require.Contains(stdout, fmt.Sprintf("- %s/24", rng), fmt.Sprintf("Expecting to find '- %s/24'", rng))
	}
	require.Contains(stdout, "networking to the cluster is enabled")
}

func (s *notConnectedSuite) Test_NeverProxy() {
	require := s.Require()
	ctx := s.Context()
	svcName := "echo-never-proxy"
	itest.ApplyEchoService(ctx, svcName, s.AppNamespace(), 8080)
	ip, err := itest.Output(ctx, "kubectl",
		"--namespace", s.AppNamespace(),
		"get", "svc", svcName,
		"-o",
		"jsonpath={.spec.clusterIP}")
	require.NoError(err)
	var ips []net.IP
	ctx = itest.WithKubeConfigExtension(ctx, func(cluster *api.Cluster) map[string]interface{} {
		var err error
		ips, err = getClusterIPs(cluster)
		require.NoError(err)
		return map[string]interface{}{"never-proxy": []string{ip + "/32"}}
	})
	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)
	stdout := itest.TelepresenceOk(ctx, "status")
	// The cluster's IP address will also be never proxied, so we gotta account for that.
	require.Contains(stdout, fmt.Sprintf("Never Proxy: (%d subnets)", len(ips)+1))
	s.Eventually(func() bool {
		return itest.Run(ctx, "curl", "--silent", "--max-time", "0.5", ip) != nil
	}, 15*time.Second, 2*time.Second, fmt.Sprintf("never-proxied IP %s is reachable", ip))
}

func (s *notConnectedSuite) Test_ConflictingProxies() {
	require := s.Require()
	ctx := s.Context()

	testIP := &net.IPNet{
		IP:   net.ParseIP("10.128.0.32"),
		Mask: net.CIDRMask(32, 32),
	}
	// We don't really care if we can't route this with TP disconnected provided the result is the same once we connect
	originalRoute, _ := routing.GetRoute(ctx, testIP)
	for name, t := range map[string]struct {
		alsoProxy  []string
		neverProxy []string
		expectEq   bool
	}{
		"Never Proxy wins": {
			alsoProxy:  []string{"10.128.0.0/16"},
			neverProxy: []string{"10.128.0.0/24"},
			expectEq:   true,
		},
		"Also Proxy wins": {
			alsoProxy:  []string{"10.128.0.0/24"},
			neverProxy: []string{"10.128.0.0/16"},
			expectEq:   false,
		},
	} {
		s.Run(name, func() {
			ctx := itest.WithKubeConfigExtension(ctx, func(cluster *api.Cluster) map[string]interface{} {
				return map[string]interface{}{
					"never-proxy": t.neverProxy,
					"also-proxy":  t.alsoProxy,
				}
			})
			itest.TelepresenceOk(ctx, "connect")
			defer itest.TelepresenceQuitOk(ctx)
			s.Eventually(func() bool {
				return itest.Run(ctx, "curl", "--silent", "-k", "--max-time", "0.5", "https://kubernetes.default:443") == nil
			}, 15*time.Second, 2*time.Second, "cluster is not connected")
			newRoute, err := routing.GetRoute(ctx, testIP)
			if t.expectEq {
				require.True((newRoute.Interface == nil && originalRoute.Interface == nil) || (newRoute.Interface.Name == originalRoute.Interface.Name))
			} else {
				require.NoError(err)
				require.NotNil(newRoute.Interface)
				if originalRoute.Interface != nil {
					require.NotEqual(newRoute.Interface.Name, originalRoute.Interface.Name, "Expected %s not to equal %s", newRoute.Interface.Name, originalRoute.Interface.Name)
				}
			}
		})
	}
}

func (s *notConnectedSuite) Test_DNSIncludes() {
	ctx := itest.WithKubeConfigExtension(s.Context(), func(cluster *api.Cluster) map[string]interface{} {
		return map[string]interface{}{"dns": map[string][]string{"include-suffixes": {".org"}}}
	})
	require := s.Require()
	logDir, err := filelocation.AppUserLogDir(ctx)
	require.NoError(err)
	logFile := filepath.Join(logDir, "daemon.log")

	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)

	retryCount := 0
	s.Eventually(func() bool {
		// Test with ".org" suffix that was added as an include-suffix
		host := fmt.Sprintf("zwslkjsdf-%d.org", retryCount)
		short, cancel := context.WithTimeout(ctx, 20*time.Millisecond)
		defer cancel()
		_ = itest.Run(short, "curl", "--silent", "--connect-timeout", "0.5", host)

		// Give query time to reach telepresence and produce a log entry
		dtime.SleepWithContext(ctx, 100*time.Millisecond)

		rootLog, err := os.Open(logFile)
		require.NoError(err)
		defer rootLog.Close()

		scanFor := fmt.Sprintf(`LookupHost "%s"`, host)
		scn := bufio.NewScanner(rootLog)
		for scn.Scan() {
			if strings.Contains(scn.Text(), scanFor) {
				return true
			}
		}
		retryCount++
		return false
	}, 10*time.Second, time.Second, "daemon.log does not contain expected LookupHost entry")
}
<commit_msg>Clarify why a test is failing<commit_after>package integration_test

import (
	"bufio"
	"context"
	"fmt"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"time"

	"k8s.io/client-go/tools/clientcmd/api"

	"github.com/datawire/dlib/dtime"
	"github.com/telepresenceio/telepresence/v2/integration_test/itest"
	"github.com/telepresenceio/telepresence/v2/pkg/filelocation"
	"github.com/telepresenceio/telepresence/v2/pkg/vif/routing"
)

func getClusterIPs(cluster *api.Cluster) ([]net.IP, error) {
	var ips []net.IP
	svcUrl, err := url.Parse(cluster.Server)
	if err != nil {
		return nil, err
	}
	hostname := svcUrl.Hostname()
	if rawIP := net.ParseIP(hostname); rawIP != nil {
		ips = []net.IP{rawIP}
	} else {
		ips, err = net.LookupIP(hostname)
		if err != nil {
			return nil, err
		}
	}
	return ips, nil
}

func (s *notConnectedSuite) Test_APIServerIsProxied() {
	require := s.Require()
	var ips []net.IP
	ctx := itest.WithKubeConfigExtension(s.Context(), func(cluster *api.Cluster) map[string]interface{} {
		var apiServers []string
		var err error
		ips, err = getClusterIPs(cluster)
		require.NoError(err)
		for _, ip := range ips {
			apiServers = append(apiServers, fmt.Sprintf(`%s/24`, ip))
		}
		return map[string]interface{}{"also-proxy": apiServers}
	})

	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)
	stdout := itest.TelepresenceOk(ctx, "status")
	require.Contains(stdout, fmt.Sprintf("Also Proxy : (%d subnets)", len(ips)))
	for _, ip := range ips {
		rng := make(net.IP, len(ip))
		copy(rng[:], ip)
		rng[len(rng)-1] = 0
		require.Contains(stdout, fmt.Sprintf("- %s/24", rng), fmt.Sprintf("Expecting to find '- %s/24'", rng))
	}
	require.Contains(stdout, "networking to the cluster is enabled")
}

func (s *notConnectedSuite) Test_NeverProxy() {
	require := s.Require()
	ctx := s.Context()
	svcName := "echo-never-proxy"
	itest.ApplyEchoService(ctx, svcName, s.AppNamespace(), 8080)
	ip, err := itest.Output(ctx, "kubectl",
		"--namespace", s.AppNamespace(),
		"get", "svc", svcName,
		"-o",
		"jsonpath={.spec.clusterIP}")
	require.NoError(err)
	var ips []net.IP
	ctx = itest.WithKubeConfigExtension(ctx, func(cluster *api.Cluster) map[string]interface{} {
		var err error
		ips, err = getClusterIPs(cluster)
		require.NoError(err)
		return map[string]interface{}{"never-proxy": []string{ip + "/32"}}
	})
	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)
	stdout := itest.TelepresenceOk(ctx, "status")
	// The cluster's IP address will also be never proxied, so we gotta account for that.
	require.Contains(stdout, fmt.Sprintf("Never Proxy: (%d subnets)", len(ips)+1))
	s.Eventually(func() bool {
		return itest.Run(ctx, "curl", "--silent", "--max-time", "0.5", ip) != nil
	}, 15*time.Second, 2*time.Second, fmt.Sprintf("never-proxied IP %s is reachable", ip))
}

func (s *notConnectedSuite) Test_ConflictingProxies() {
	require := s.Require()
	ctx := s.Context()

	testIP := &net.IPNet{
		IP:   net.ParseIP("10.128.0.32"),
		Mask: net.CIDRMask(32, 32),
	}
	// We don't really care if we can't route this with TP disconnected provided the result is the same once we connect
	originalRoute, _ := routing.GetRoute(ctx, testIP)
	for name, t := range map[string]struct {
		alsoProxy  []string
		neverProxy []string
		expectEq   bool
	}{
		"Never Proxy wins": {
			alsoProxy:  []string{"10.128.0.0/16"},
			neverProxy: []string{"10.128.0.0/24"},
			expectEq:   true,
		},
		"Also Proxy wins": {
			alsoProxy:  []string{"10.128.0.0/24"},
			neverProxy: []string{"10.128.0.0/16"},
			expectEq:   false,
		},
	} {
		s.Run(name, func() {
			ctx := itest.WithKubeConfigExtension(ctx, func(cluster *api.Cluster) map[string]interface{} {
				return map[string]interface{}{
					"never-proxy": t.neverProxy,
					"also-proxy":  t.alsoProxy,
				}
			})
			itest.TelepresenceOk(ctx, "connect")
			defer itest.TelepresenceQuitOk(ctx)
			s.Eventually(func() bool {
				return itest.Run(ctx, "curl", "--silent", "-k", "--max-time", "0.5", "https://kubernetes.default:443") == nil
			}, 15*time.Second, 2*time.Second, "cluster is not connected")
			newRoute, err := routing.GetRoute(ctx, testIP)
			if t.expectEq {
				if originalRoute.Interface != nil {
					require.NotNil(newRoute.Interface)
					require.Equal(originalRoute.Interface.Name, newRoute.Interface.Name)
				} else {
					require.Nil(newRoute.Interface)
				}
			} else {
				require.NoError(err)
				require.NotNil(newRoute.Interface)
				if originalRoute.Interface != nil {
					require.NotEqual(newRoute.Interface.Name, originalRoute.Interface.Name, "Expected %s not to equal %s", newRoute.Interface.Name, originalRoute.Interface.Name)
				}
			}
		})
	}
}

func (s *notConnectedSuite) Test_DNSIncludes() {
	ctx := itest.WithKubeConfigExtension(s.Context(), func(cluster *api.Cluster) map[string]interface{} {
		return map[string]interface{}{"dns": map[string][]string{"include-suffixes": {".org"}}}
	})
	require := s.Require()
	logDir, err := filelocation.AppUserLogDir(ctx)
	require.NoError(err)
	logFile := filepath.Join(logDir, "daemon.log")

	itest.TelepresenceOk(ctx, "connect")
	defer itest.TelepresenceQuitOk(ctx)

	retryCount := 0
	s.Eventually(func() bool {
		// Test with ".org" suffix that was added as an include-suffix
		host := fmt.Sprintf("zwslkjsdf-%d.org", retryCount)
		short, cancel := context.WithTimeout(ctx, 20*time.Millisecond)
		defer cancel()
		_ = itest.Run(short, "curl", "--silent", "--connect-timeout", "0.5", host)

		// Give query time to reach telepresence and produce a log entry
		dtime.SleepWithContext(ctx, 100*time.Millisecond)

		rootLog, err := os.Open(logFile)
		require.NoError(err)
		defer rootLog.Close()

		scanFor := fmt.Sprintf(`LookupHost "%s"`, host)
		scn := bufio.NewScanner(rootLog)
		for scn.Scan() {
			if strings.Contains(scn.Text(), scanFor) {
				return true
			}
		}
		retryCount++
		return false
	}, 10*time.Second, time.Second, "daemon.log does not contain expected LookupHost entry")
}
<|endoftext|>