<commit_before>package univedo

import (
	"bytes"
	"github.com/nu7hatch/gouuid"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
	"time"
)

func readMessage(s string) (interface{}, error) {
	m := &message{buffer: bytes.NewBufferString(s)}
	return m.read()
}

func sendMessage(o interface{}) ([]byte, error) {
	m := &message{buffer: &bytes.Buffer{}}
	err := m.send(o)
	if err != nil {
		return []byte{}, err
	}
	return m.buffer.Bytes(), nil
}

func TestCbor(t *testing.T) {
	Convey("cbor reads", t, func() {
		Convey("null", func() {
			r, err := readMessage("\xf6")
			So(r, ShouldBeNil)
			So(err, ShouldBeNil)
		})

		Convey("true", func() {
			r, err := readMessage("\xf5")
			So(r, ShouldBeTrue)
			So(err, ShouldBeNil)
		})

		Convey("false", func() {
			r, err := readMessage("\xf4")
			So(r, ShouldBeFalse)
			So(err, ShouldBeNil)
		})

		Convey("float32", func() {
			r, err := readMessage("\xfa\x47\xc3\x50\x00")
			So(r, ShouldEqual, 100000.0)
			So(err, ShouldBeNil)
		})

		Convey("float64", func() {
			r, err := readMessage("\xfb\x3f\xf1\x99\x99\x99\x99\x99\x9a")
			So(r, ShouldEqual, 1.1)
			So(err, ShouldBeNil)
		})

		Convey("small uint", func() {
			r, err := readMessage("\x0a")
			So(r, ShouldEqual, 10)
			So(err, ShouldBeNil)
		})

		Convey("uint8", func() {
			r, err := readMessage("\x18\x2a")
			So(r, ShouldEqual, 42)
			So(err, ShouldBeNil)
		})

		Convey("uint16", func() {
			r, err := readMessage("\x19\x03\xe8")
			So(r, ShouldEqual, 1000)
			So(err, ShouldBeNil)
		})

		Convey("uint32", func() {
			r, err := readMessage("\x1a\x00\x0f\x42\x40")
			So(r, ShouldEqual, 1000000)
			So(err, ShouldBeNil)
		})

		Convey("uint64", func() {
			r, err := readMessage("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00")
			So(r, ShouldEqual, 1000000000000)
			So(err, ShouldBeNil)
		})

		Convey("small int", func() {
			r, err := readMessage("\x20")
			So(r, ShouldEqual, -1)
			So(err, ShouldBeNil)
		})

		Convey("int8", func() {
			r, err := readMessage("\x38\x63")
			So(r, ShouldEqual, -100)
			So(err, ShouldBeNil)
		})

		Convey("int16", func() {
			r, err := readMessage("\x39\x03\xe7")
			So(r, ShouldEqual, -1000)
			So(err, ShouldBeNil)
		})

		Convey("int32", func() {
			r, err := readMessage("\x3a\x00\x0f\x42\x3f")
			So(r, ShouldEqual, -1000000)
			So(err, ShouldBeNil)
		})

		Convey("int64", func() {
			r, err := readMessage("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff")
			So(r, ShouldEqual, -1000000000000)
			So(err, ShouldBeNil)
		})

		Convey("strings", func() {
			r, err := readMessage("\x66foobar")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, "foobar")
		})

		Convey("utf8 strings", func() {
			r, err := readMessage("\x67f\xc3\xb6obar")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, "föobar")
		})

		Convey("blobs", func() {
			r, err := readMessage("\x46foobar")
			So(err, ShouldBeNil)
			So(r, ShouldResemble, []byte("foobar"))
		})

		Convey("lists", func() {
			r, err := readMessage("\x82\x63foo\x63bar")
			So(err, ShouldBeNil)
			So(r, ShouldResemble, []interface{}{"foo", "bar"})
		})

		Convey("maps", func() {
			r, err := readMessage("\xa2\x63bar\x02\x63foo\x01")
			So(err, ShouldBeNil)
			m := r.(map[string]interface{})
			So(len(m), ShouldEqual, 2)
			So(m["foo"], ShouldEqual, 1)
			So(m["bar"], ShouldEqual, 2)
		})

		Convey("records", func() {
			r, err := readMessage("\xc8\x18\x2a")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, 42)
		})

		Convey("datetimes", func() {
			r, err := readMessage("\xc0\x74\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30\x5a")
			So(err, ShouldBeNil)
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00Z")
			So(r, ShouldResemble, ref)
		})

		Convey("micro datetimes", func() {
			r, err := readMessage("\xc0\x78\x1b\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30.000001\x5a")
			So(err, ShouldBeNil)
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00.000001Z")
			So(r, ShouldResemble, ref)
		})

		Convey("uuids", func() {
			r, err := readMessage("\xc7\x50\x68\x4E\xF8\x95\x72\xA2\x42\x98\xBC\x5B\x58\x0F\x1C\x1D\x27\x07")
			So(err, ShouldBeNil)
			ref, _ := uuid.ParseHex("684ef895-72a2-4298-bc5b-580f1c1d2707")
			So(r, ShouldResemble, ref)
		})
	})

	Convey("cbor sends", t, func() {
		Convey("null", func() {
			b, err := sendMessage(nil)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf6"))
		})

		Convey("true", func() {
			b, err := sendMessage(true)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf5"))
		})

		Convey("false", func() {
			b, err := sendMessage(false)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf4"))
		})

		Convey("float32", func() {
			b, err := sendMessage(float32(100000.0))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xfa\x47\xc3\x50\x00"))
		})

		Convey("float64", func() {
			b, err := sendMessage(1.1)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xfb\x3f\xf1\x99\x99\x99\x99\x99\x9a"))
		})

		Convey("small uint", func() {
			b, err := sendMessage(uint8(10))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("uint8", func() {
			b, err := sendMessage(uint8(42))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x18\x2a"))
		})

		Convey("uint16", func() {
			b, err := sendMessage(uint16(1000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x19\x03\xe8"))
		})

		Convey("uint32", func() {
			b, err := sendMessage(uint32(1000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x1a\x00\x0f\x42\x40"))
		})

		Convey("uint64", func() {
			b, err := sendMessage(uint64(1000000000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"))
		})

		Convey("small int", func() {
			b, err := sendMessage(int8(-1))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x20"))
		})

		Convey("small positive int", func() {
			b, err := sendMessage(int8(10))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("int8", func() {
			b, err := sendMessage(int8(-100))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x38\x63"))
		})

		Convey("int16", func() {
			b, err := sendMessage(int16(-1000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x39\x03\xe7"))
		})

		Convey("int32", func() {
			b, err := sendMessage(int32(-1000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x3a\x00\x0f\x42\x3f"))
		})

		Convey("int64", func() {
			b, err := sendMessage(int64(-1000000000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"))
		})

		Convey("int", func() {
			b, err := sendMessage(10)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("strings", func() {
			b, err := sendMessage("foobar")
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x66foobar"))
		})

		Convey("utf8 strings", func() {
			b, err := sendMessage("föobar")
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x67f\xc3\xb6obar"))
		})

		Convey("blobs", func() {
			b, err := sendMessage([]byte("foobar"))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x46foobar"))
		})

		Convey("lists", func() {
			b, err := sendMessage([]interface{}{"foo", "bar"})
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x82\x63foo\x63bar"))
		})

		Convey("maps", func() {
			b, err := sendMessage(map[string]interface{}{"bar": 2, "foo": 1})
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xa2\x63bar\x02\x63foo\x01"))
		})

		Convey("datetimes", func() {
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00Z")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc0\x74\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30\x5a"))
		})

		Convey("micro datetimes", func() {
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00.000001Z")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc0\x78\x1b\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30.000001\x5a"))
		})

		Convey("uuids", func() {
			ref, _ := uuid.ParseHex("684ef895-72a2-4298-bc5b-580f1c1d2707")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc7\x50\x68\x4E\xF8\x95\x72\xA2\x42\x98\xBC\x5B\x58\x0F\x1C\x1D\x27\x07"))
		})
	})
}
<commit_msg>fix map sending test<commit_after>package univedo

import (
	"bytes"
	"github.com/nu7hatch/gouuid"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
	"time"
)

func readMessage(s string) (interface{}, error) {
	m := &message{buffer: bytes.NewBufferString(s)}
	return m.read()
}

func sendMessage(o interface{}) ([]byte, error) {
	m := &message{buffer: &bytes.Buffer{}}
	err := m.send(o)
	if err != nil {
		return []byte{}, err
	}
	return m.buffer.Bytes(), nil
}

func TestCbor(t *testing.T) {
	Convey("cbor reads", t, func() {
		Convey("null", func() {
			r, err := readMessage("\xf6")
			So(r, ShouldBeNil)
			So(err, ShouldBeNil)
		})

		Convey("true", func() {
			r, err := readMessage("\xf5")
			So(r, ShouldBeTrue)
			So(err, ShouldBeNil)
		})

		Convey("false", func() {
			r, err := readMessage("\xf4")
			So(r, ShouldBeFalse)
			So(err, ShouldBeNil)
		})

		Convey("float32", func() {
			r, err := readMessage("\xfa\x47\xc3\x50\x00")
			So(r, ShouldEqual, 100000.0)
			So(err, ShouldBeNil)
		})

		Convey("float64", func() {
			r, err := readMessage("\xfb\x3f\xf1\x99\x99\x99\x99\x99\x9a")
			So(r, ShouldEqual, 1.1)
			So(err, ShouldBeNil)
		})

		Convey("small uint", func() {
			r, err := readMessage("\x0a")
			So(r, ShouldEqual, 10)
			So(err, ShouldBeNil)
		})

		Convey("uint8", func() {
			r, err := readMessage("\x18\x2a")
			So(r, ShouldEqual, 42)
			So(err, ShouldBeNil)
		})

		Convey("uint16", func() {
			r, err := readMessage("\x19\x03\xe8")
			So(r, ShouldEqual, 1000)
			So(err, ShouldBeNil)
		})

		Convey("uint32", func() {
			r, err := readMessage("\x1a\x00\x0f\x42\x40")
			So(r, ShouldEqual, 1000000)
			So(err, ShouldBeNil)
		})

		Convey("uint64", func() {
			r, err := readMessage("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00")
			So(r, ShouldEqual, 1000000000000)
			So(err, ShouldBeNil)
		})

		Convey("small int", func() {
			r, err := readMessage("\x20")
			So(r, ShouldEqual, -1)
			So(err, ShouldBeNil)
		})

		Convey("int8", func() {
			r, err := readMessage("\x38\x63")
			So(r, ShouldEqual, -100)
			So(err, ShouldBeNil)
		})

		Convey("int16", func() {
			r, err := readMessage("\x39\x03\xe7")
			So(r, ShouldEqual, -1000)
			So(err, ShouldBeNil)
		})

		Convey("int32", func() {
			r, err := readMessage("\x3a\x00\x0f\x42\x3f")
			So(r, ShouldEqual, -1000000)
			So(err, ShouldBeNil)
		})

		Convey("int64", func() {
			r, err := readMessage("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff")
			So(r, ShouldEqual, -1000000000000)
			So(err, ShouldBeNil)
		})

		Convey("strings", func() {
			r, err := readMessage("\x66foobar")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, "foobar")
		})

		Convey("utf8 strings", func() {
			r, err := readMessage("\x67f\xc3\xb6obar")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, "föobar")
		})

		Convey("blobs", func() {
			r, err := readMessage("\x46foobar")
			So(err, ShouldBeNil)
			So(r, ShouldResemble, []byte("foobar"))
		})

		Convey("lists", func() {
			r, err := readMessage("\x82\x63foo\x63bar")
			So(err, ShouldBeNil)
			So(r, ShouldResemble, []interface{}{"foo", "bar"})
		})

		Convey("maps", func() {
			r, err := readMessage("\xa2\x63bar\x02\x63foo\x01")
			So(err, ShouldBeNil)
			m := r.(map[string]interface{})
			So(len(m), ShouldEqual, 2)
			So(m["foo"], ShouldEqual, 1)
			So(m["bar"], ShouldEqual, 2)
		})

		Convey("records", func() {
			r, err := readMessage("\xc8\x18\x2a")
			So(err, ShouldBeNil)
			So(r, ShouldEqual, 42)
		})

		Convey("datetimes", func() {
			r, err := readMessage("\xc0\x74\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30\x5a")
			So(err, ShouldBeNil)
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00Z")
			So(r, ShouldResemble, ref)
		})

		Convey("micro datetimes", func() {
			r, err := readMessage("\xc0\x78\x1b\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30.000001\x5a")
			So(err, ShouldBeNil)
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00.000001Z")
			So(r, ShouldResemble, ref)
		})

		Convey("uuids", func() {
			r, err := readMessage("\xc7\x50\x68\x4E\xF8\x95\x72\xA2\x42\x98\xBC\x5B\x58\x0F\x1C\x1D\x27\x07")
			So(err, ShouldBeNil)
			ref, _ := uuid.ParseHex("684ef895-72a2-4298-bc5b-580f1c1d2707")
			So(r, ShouldResemble, ref)
		})
	})

	Convey("cbor sends", t, func() {
		Convey("null", func() {
			b, err := sendMessage(nil)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf6"))
		})

		Convey("true", func() {
			b, err := sendMessage(true)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf5"))
		})

		Convey("false", func() {
			b, err := sendMessage(false)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xf4"))
		})

		Convey("float32", func() {
			b, err := sendMessage(float32(100000.0))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xfa\x47\xc3\x50\x00"))
		})

		Convey("float64", func() {
			b, err := sendMessage(1.1)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xfb\x3f\xf1\x99\x99\x99\x99\x99\x9a"))
		})

		Convey("small uint", func() {
			b, err := sendMessage(uint8(10))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("uint8", func() {
			b, err := sendMessage(uint8(42))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x18\x2a"))
		})

		Convey("uint16", func() {
			b, err := sendMessage(uint16(1000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x19\x03\xe8"))
		})

		Convey("uint32", func() {
			b, err := sendMessage(uint32(1000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x1a\x00\x0f\x42\x40"))
		})

		Convey("uint64", func() {
			b, err := sendMessage(uint64(1000000000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"))
		})

		Convey("small int", func() {
			b, err := sendMessage(int8(-1))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x20"))
		})

		Convey("small positive int", func() {
			b, err := sendMessage(int8(10))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("int8", func() {
			b, err := sendMessage(int8(-100))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x38\x63"))
		})

		Convey("int16", func() {
			b, err := sendMessage(int16(-1000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x39\x03\xe7"))
		})

		Convey("int32", func() {
			b, err := sendMessage(int32(-1000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x3a\x00\x0f\x42\x3f"))
		})

		Convey("int64", func() {
			b, err := sendMessage(int64(-1000000000000))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x3b\x00\x00\x00\xe8\xd4\xa5\x0f\xff"))
		})

		Convey("int", func() {
			b, err := sendMessage(10)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x0a"))
		})

		Convey("strings", func() {
			b, err := sendMessage("foobar")
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x66foobar"))
		})

		Convey("utf8 strings", func() {
			b, err := sendMessage("föobar")
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x67f\xc3\xb6obar"))
		})

		Convey("blobs", func() {
			b, err := sendMessage([]byte("foobar"))
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x46foobar"))
		})

		Convey("lists", func() {
			b, err := sendMessage([]interface{}{"foo", "bar"})
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\x82\x63foo\x63bar"))
		})

		Convey("maps", func() {
			b, err := sendMessage(map[string]interface{}{"bar": 2, "foo": 1})
			So(err, ShouldBeNil)
			So(bytes.Equal(b, []byte("\xa2\x63bar\x02\x63foo\x01")) || bytes.Equal(b, []byte("\xa2\x63foo\x01\x63bar\x02")), ShouldBeTrue)
		})

		Convey("datetimes", func() {
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00Z")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc0\x74\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30\x5a"))
		})

		Convey("micro datetimes", func() {
			ref, _ := time.Parse(time.RFC3339Nano, "2013-03-21T20:04:00.000001Z")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc0\x78\x1b\x32\x30\x31\x33\x2d\x30\x33\x2d\x32\x31\x54\x32\x30\x3a\x30\x34\x3a\x30\x30.000001\x5a"))
		})

		Convey("uuids", func() {
			ref, _ := uuid.ParseHex("684ef895-72a2-4298-bc5b-580f1c1d2707")
			b, err := sendMessage(ref)
			So(err, ShouldBeNil)
			So(b, ShouldResemble, []byte("\xc7\x50\x68\x4E\xF8\x95\x72\xA2\x42\x98\xBC\x5B\x58\x0F\x1C\x1D\x27\x07"))
		})
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/urfave/cli"
	"os"
)

type Rotatee struct {
	setting RotateeSetting
}

func newRotatee(setting RotateeSetting) *Rotatee {
	return &Rotatee{setting: setting}
}

type RotateeSetting struct {
	verbose bool
}

func (r *Rotatee) start() {
	fmt.Println("started")
	writeCh := make(chan []byte)
	// writer loop
	go func() {
		writer := os.Stdin
		for {
			chunk := <-writeCh
			_, err := writer.Write(chunk)
			if err != nil {
				panic("Reader goroutine IO failed")
			}
		}
	}()

	// reader loop
	reader := os.Stdin
	readBuf := make([]byte, 1024)
	for {
		len, err := reader.Read(readBuf)
		if err != nil {
			panic("Writer goroutine IO failed")
		}
		// do copy because 'content' is shared among goroutine(s)
		content := make([]byte, len)
		copy(content, readBuf[:len])
		writeCh <- content
	}
	return
}

func main() {
	app := cli.NewApp()
	app.Name = "rotatee"
	app.Usage = "advanced tee, advanced input rotation"
	app.Action = func(c *cli.Context) error {
		fmt.Printf("Args: %q\n", c.Args())
		rotatee := newRotatee(RotateeSetting{
			verbose: false,
		})
		rotatee.start()
		return nil
	}
	app.Run(os.Args)
}
<commit_msg>Currently use logrus<commit_after>package main

import (
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"os"
)

var log = logrus.New()

type Rotatee struct {
	setting RotateeSetting
}

func newRotatee(setting RotateeSetting) *Rotatee {
	return &Rotatee{setting: setting}
}

type RotateeSetting struct {
	verbose bool
}

func (r *Rotatee) start() {
	log.WithFields(logrus.Fields{"Rotatee": r}).Debug("Start rotatee")
	writeCh := make(chan []byte)
	// writer loop
	go func() {
		writer := os.Stdin
		for {
			chunk := <-writeCh
			_, err := writer.Write(chunk)
			if err != nil {
				panic("Reader goroutine IO failed")
			}
		}
	}()

	// reader loop
	reader := os.Stdin
	readBuf := make([]byte, 1024)
	for {
		len, err := reader.Read(readBuf)
		if err != nil {
			log.Panic("Writer goroutine IO failed")
		}
		// do copy because 'content' is shared among goroutine(s)
		content := make([]byte, len)
		copy(content, readBuf[:len])
		writeCh <- content
	}
}

func main() {
	// setup logger
	log.Level = logrus.DebugLevel //TODO
	log.Out = os.Stdout
	log.Debug("At main")

	app := cli.NewApp()
	app.Name = "rotatee"
	app.Usage = "advanced tee, advanced input rotation"
	app.Action = func(c *cli.Context) error {
		log.WithFields(logrus.Fields{"Args": c.Args()}).Debug("Parsed input arguments")
		rotatee := newRotatee(RotateeSetting{
			verbose: false,
		})
		rotatee.start()
		return nil
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>// +build !appengine

package maxminddb

import "os"

// Open takes a string path to a MaxMind DB file and returns a Reader
// structure or an error. The database file is opened using a memory map,
// except on Google App Engine where mmap is not supported; there the database
// is loaded into memory. Use the Close method on the Reader object to return
// the resources to the system.
func Open(file string) (*Reader, error) {
	mapFile, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	defer func() {
		if rerr := mapFile.Close(); rerr != nil {
			err = rerr
		}
	}()

	stats, err := mapFile.Stat()
	if err != nil {
		return nil, err
	}

	fileSize := int(stats.Size())
	mmap, err := mmap(int(mapFile.Fd()), fileSize)
	if err != nil {
		return nil, err
	}

	reader, err := FromBytes(mmap)
	if err != nil {
		if err2 := munmap(mmap); err2 != nil {
			// failing to unmap the file is probably the more severe error
			return nil, err2
		}
		return nil, err
	}

	reader.hasMappedFile = true
	return reader, err
}

// Close unmaps the database file from virtual memory and returns the
// resources to the system. If called on a Reader opened using FromBytes
// or Open on Google App Engine, this method does nothing.
func (r *Reader) Close() (err error) {
	if r.hasMappedFile {
		err = munmap(r.buffer)
		r.hasMappedFile = false
	}
	return err
}
<commit_msg>SetFinalizer to unmap files<commit_after>// +build !appengine

package maxminddb

import (
	"os"
	"runtime"
)

// Open takes a string path to a MaxMind DB file and returns a Reader
// structure or an error. The database file is opened using a memory map,
// except on Google App Engine where mmap is not supported; there the database
// is loaded into memory. Use the Close method on the Reader object to return
// the resources to the system.
func Open(file string) (*Reader, error) {
	mapFile, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	defer func() {
		if rerr := mapFile.Close(); rerr != nil {
			err = rerr
		}
	}()

	stats, err := mapFile.Stat()
	if err != nil {
		return nil, err
	}

	fileSize := int(stats.Size())
	mmap, err := mmap(int(mapFile.Fd()), fileSize)
	if err != nil {
		return nil, err
	}

	reader, err := FromBytes(mmap)
	if err != nil {
		if err2 := munmap(mmap); err2 != nil {
			// failing to unmap the file is probably the more severe error
			return nil, err2
		}
		return nil, err
	}

	reader.hasMappedFile = true
	runtime.SetFinalizer(reader, (*Reader).Close)
	return reader, err
}

// Close unmaps the database file from virtual memory and returns the
// resources to the system. If called on a Reader opened using FromBytes
// or Open on Google App Engine, this method does nothing.
func (r *Reader) Close() error {
	if !r.hasMappedFile {
		return nil
	}
	runtime.SetFinalizer(r, nil)
	r.hasMappedFile = false
	return munmap(r.buffer)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/x509"
	"encoding/pem"
	"flag"
	"fmt"
	"html"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

type certInfo struct {
	FileName string
	NotAfter time.Time
	CertName string
}

var pageHead = `

`

// wg is used to pevent a webrequest from attempting to return information
// before the async directory scanner is finished.
var wg sync.WaitGroup

// dir is the directory passed in by the user
var dir string

// certInfos will contain all of the information about certs we find.
var certInfos []certInfo

// walkFunc is the walking function called by each file and directory
// found in the flag specified directory.
func walkFunc(path string, info os.FileInfo, err error) (e error) {
	if info.IsDir() {
		return
	}
	f, e := os.Open(path)
	// If we can't open it, forget about it.
	if e != nil {
		return
	}

	// isOpen will tell you whether or not we have found a BEGIN or
	// if we found an END. TRUE if we have found a BEGIN but no END.
	// FALSE if we have found nothing or END and no BEGIN.
	isOpen := false

	// tryCert
	tryCert := ""
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()

		// Try to find certificates deep in files. Once we find a begin
		// certificate and an end certificate, try to parse it.
		if strings.Contains(text, "BEGIN CERTIFICATE-----") {
			tryCert = fmt.Sprintf("%s\n", strings.TrimSpace(text))
			isOpen = true
		} else if strings.Contains(text, "END CERTIFICATE-----") {
			// This is a peculiar state. We found an END without a begin.
			// Just ignore it and try again later.
			if !isOpen {
				tryCert = ""
			}
			tryCert = fmt.Sprintf("%s%s", tryCert, strings.TrimSpace(text))
			// Try to parse the certificate.
			p, _ := pem.Decode([]byte(tryCert))
			cert, err := x509.ParseCertificate(p.Bytes)
			if err == nil {
				c := *new(certInfo)
				c.NotAfter = cert.NotAfter
				c.FileName = path
				dnsNames := ""
				for _, dnsName := range cert.DNSNames {
					if len(dnsNames) == 0 {
						dnsNames = dnsName
					} else {
						dnsNames = fmt.Sprintf("%s, %s", dnsNames, dnsName)
					}
				}
				c.CertName = dnsNames
				certInfos = append(certInfos, c)
			}
			isOpen = false
		} else {
			if isOpen {
				tryCert = fmt.Sprintf("%s%s\n", tryCert, strings.TrimSpace(text))
			}
		}
	}
	return
}
func serveResults(w http.ResponseWriter, r *http.Request) {
	wg.Wait()
	w.Write([]byte(pageHead))
	for _, cert := range certInfos {
		certClass := ""
		monthAway := time.Now().AddDate(0, 1, 0)
		if cert.NotAfter.Before(monthAway) {
			certClass = "warning"
		}
		htmlRow := fmt.Sprintf("

%s

%s

%s

", certClass, cert.NotAfter, html.EscapeString(cert.FileName), html.EscapeString(cert.CertName))
		w.Write([]byte(htmlRow))
	}
	w.Write([]byte("
"))
}
func main() {
	flag.StringVar(&dir, "d", "", "search `directory` for certificates")
	flag.Parse()

	if len(dir) == 0 {
		log.Fatalf("Must supply a directory to search for ceritficates.")
	}
	go func() {
		for {
			wg.Add(1)
			certInfos = *new([]certInfo)

			// walk through each file or directory and accumulate all the certificates
			filepath.Walk(dir, walkFunc)
			wg.Done()
			time.Sleep(time.Minute)
		}
	}()
	http.HandleFunc("/", serveResults)
	http.ListenAndServe(":8000", nil)
}
<commit_msg>Add doc<commit_after>package main

import (
	"bufio"
	"crypto/x509"
	"encoding/pem"
	"flag"
	"fmt"
	"html"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

type certInfo struct {
	FileName string
	NotAfter time.Time
	CertName string
}

var pageHead = `

`

// wg is used to pevent a webrequest from attempting to return information
// before the async directory scanner is finished.
var wg sync.WaitGroup

// dir is the directory passed in by the user
var dir string

// certInfos will contain all of the information about certs we find.
var certInfos []certInfo

// walkFunc is the walking function called by each file and directory
// found in the flag specified directory.
func walkFunc(path string, info os.FileInfo, err error) (e error) {
	if info.IsDir() {
		return
	}
	f, e := os.Open(path)
	// If we can't open it, forget about it.
	if e != nil {
		return
	}

	// isOpen will tell you whether or not we have found a BEGIN or
	// if we found an END. TRUE if we have found a BEGIN but no END.
	// FALSE if we have found nothing or END and no BEGIN.
	isOpen := false

	// tryCert is what we think might be a certificate. We will try
	// to parse it as an x509 cert.
	tryCert := ""
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		text := scanner.Text()

		// Try to find certificates deep in files. Once we find a begin
		// certificate and an end certificate, try to parse it.
		if strings.Contains(text, "BEGIN CERTIFICATE-----") {
			tryCert = fmt.Sprintf("%s\n", strings.TrimSpace(text))
			isOpen = true
		} else if strings.Contains(text, "END CERTIFICATE-----") {
			// This is a peculiar state. We found an END without a begin.
			// Just ignore it and try again later.
			if !isOpen {
				tryCert = ""
			}
			tryCert = fmt.Sprintf("%s%s", tryCert, strings.TrimSpace(text))
			// Try to parse the certificate.
			p, _ := pem.Decode([]byte(tryCert))
			cert, err := x509.ParseCertificate(p.Bytes)
			if err == nil {
				c := *new(certInfo)
				c.NotAfter = cert.NotAfter
				c.FileName = path
				dnsNames := ""
				for _, dnsName := range cert.DNSNames {
					if len(dnsNames) == 0 {
						dnsNames = dnsName
					} else {
						dnsNames = fmt.Sprintf("%s, %s", dnsNames, dnsName)
					}
				}
				c.CertName = dnsNames
				certInfos = append(certInfos, c)
			}
			isOpen = false
		} else {
			if isOpen {
				tryCert = fmt.Sprintf("%s%s\n", tryCert, strings.TrimSpace(text))
			}
		}
	}
	return
}
func serveResults(w http.ResponseWriter, r *http.Request) {
	wg.Wait()
	w.Write([]byte(pageHead))
	for _, cert := range certInfos {
		certClass := ""
		monthAway := time.Now().AddDate(0, 1, 0)
		if cert.NotAfter.Before(monthAway) {
			certClass = "warning"
		}
		htmlRow := fmt.Sprintf("

%s

%s

%s

", certClass, cert.NotAfter, html.EscapeString(cert.FileName), html.EscapeString(cert.CertName))
		w.Write([]byte(htmlRow))
	}
	w.Write([]byte("
"))
}
func main() {
	flag.StringVar(&dir, "d", "", "search `directory` for certificates")
	flag.Parse()

	if len(dir) == 0 {
		log.Fatalf("Must supply a directory to search for ceritficates.")
	}
	go func() {
		for {
			wg.Add(1)
			certInfos = *new([]certInfo)

			// walk through each file or directory and accumulate all the certificates
			filepath.Walk(dir, walkFunc)
			wg.Done()
			time.Sleep(time.Minute)
		}
	}()
	http.HandleFunc("/", serveResults)
	http.ListenAndServe(":8000", nil)
}
<|endoftext|>


<commit_before>package image

/*
#cgo pkg-config: MagickWand-6.Q16

#include <wand/MagickWand.h>

char *MagickGetPropertyName(char **properties, size_t index) {
  return properties[index];
}

*/
import "C"

import (
	"fmt"
	// "imsto"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"unsafe"
)

func cargv(b [][]byte) **C.char {
	outer := make([]*C.char, len(b)+1)
	for i, inner := range b {
		outer[i] = C.CString(string(inner))
	}
	return (**C.char)(unsafe.Pointer(&outer[0])) // void bar(**char) {...}
}

// Image object
type wandImpl struct {
	wand *C.MagickWand

	filename string
	width    string
	height   string

	wopt WriteOption
}

func init() {
	C.MagickWandGenesis()
}

// Returns a new image object.
func newWandImage() *wandImpl {
	self := &wandImpl{}

	self.wand = C.NewMagickWand()

	return self
}

// Opens an image file, returns nil on success, error otherwise.
func (self *wandImpl) Open(r io.Reader) error {
	// stat, err := os.Stat(filename)

	// if err != nil {
	// 	return err
	// }

	// if stat.IsDir() == true {
	// 	return fmt.Errorf(`Could not open file "%s": it's a directory!`, filename)
	// }
	var status C.MagickBooleanType

	if f, ok := r.(*os.File); ok {
		f.Seek(0, 0)
		// cfilename := C.CString(filename)
		// status := C.MagickReadImage(self.wand, cfilename)
		// C.free(unsafe.Pointer(cfilename))
		cmode := C.CString("rb")
		defer C.free(unsafe.Pointer(cmode))
		file := C.fdopen(C.int(f.Fd()), cmode)
		defer C.fclose(file)
		status = C.MagickReadImageFile(self.wand, file)
		self.filename = f.Name()
	} else {
		// var blob []byte
		blob, err := ioutil.ReadAll(f)

		if err != nil {
			log.Println(err)
			return err
		}

		status = C.MagickReadImageBlob(self.wand, unsafe.Pointer(&blob[0]), C.size_t(len(blob)))
	}
	if status == C.MagickFalse {
		return fmt.Errorf(`Could not open image: %s`, self.Error())
	}

	// self.filename = filename

	// _im := C.GetImageFromMagickWand(self.wand)

	// fmt.Println(_im.columns)

	return nil
}

// Reads an image or image sequence from a blob.
func (self *wandImpl) OpenBlob(blob []byte) error {
	status := C.MagickReadImageBlob(self.wand, unsafe.Pointer(&blob[0]), C.size_t(len(blob)))

	if status == C.MagickFalse {
		return fmt.Errorf(`Could not open image from blob: %s`, self.Error())
	}

	return nil
}

func (self *wandImpl) GetAttr() *ImageAttr {
	return NewImageAttr(self.Width(), self.Height(), self.Quality())
}

// Returns the format of a particular image in a sequence.
func (self *wandImpl) Format() string {
	return C.GoString(C.MagickGetImageFormat(self.wand))
}

// Sets the format of a particular image
func (self *wandImpl) SetFormat(format string) error {
	cformat := C.CString(format)
	defer C.free(unsafe.Pointer(cformat))

	if C.MagickSetImageFormat(self.wand, cformat) == C.MagickFalse {
		return fmt.Errorf("Could not set format: %s", self.Error())
	}

	return nil
}

func (self *wandImpl) SetOption(wopt WriteOption) {
	self.wopt = wopt
	self.SetQuality(wopt.Quality)
}

// Get image data as a byte array.
func (self *wandImpl) GetImageBlob() ([]byte, error) {
	size := C.size_t(0)
	p := unsafe.Pointer(C.MagickGetImageBlob(self.wand, &size))
	if size == 0 {
		return nil, fmt.Errorf("Could not get image blob \n")
	}

	blob := C.GoBytes(p, C.int(size))

	C.MagickRelinquishMemory(p)

	return blob, nil
}

// Converts the current image into a thumbnail of the specified
// width and height preserving ratio. It uses Crop() to clip the
// image to the specified area.
//
// If width or height are bigger than the current image, a centered
// thumbnail will be produced.
//
// Is width and height are smaller than the current image, the image
// will be resized and cropped, if needed.
func (self *wandImpl) Thumbnail(topt ThumbOption) error {

	// TODO:

	return nil
}

// Returns image' width.
func (self *wandImpl) Width() uint {
	return uint(C.MagickGetImageWidth(self.wand))
}

// Returns image' height.
func (self *wandImpl) Height() uint {
	return uint(C.MagickGetImageHeight(self.wand))
}

// Writes image to a file, returns nil on success.
func (self *wandImpl) Write(out io.Writer) error {
	if f, ok := out.(*os.File); ok {

		cmode := C.CString("w+")
		defer C.free(unsafe.Pointer(cmode))
		file := C.fdopen(C.int(f.Fd()), cmode)
		defer C.fclose(file)
		success := C.MagickWriteImageFile(self.wand, file)

		if success == C.MagickFalse {
			return fmt.Errorf("Could not write: %s", self.Error())
		}

	} else {
		var size *uint
		blob := self.Blob(size)

		log.Printf("blob %d bytes\n", size)
		out.Write(blob)
	}
	return nil
}

// Implements direct to memory image formats. It returns the image as a blob
func (self *wandImpl) Blob(length *uint) []byte {
	ptr := unsafe.Pointer(C.MagickGetImageBlob(self.wand, (*C.size_t)(unsafe.Pointer(length))))
	data := C.GoBytes(ptr, C.int(*length))
	C.MagickRelinquishMemory(ptr)
	return data
}

// Changes the size of the image, returns true on success.
func (self *wandImpl) Resize(width uint, height uint) error {
	success := C.MagickResizeImage(self.wand, C.size_t(width), C.size_t(height), C.GaussianFilter, C.double(1.0))

	if success == C.MagickFalse {
		return fmt.Errorf("Could not resize: %s", self.Error())
	}

	return nil
}

// Returns the compression quality of the image. Ranges from 1 (lowest) to 100 (highest).
func (self *wandImpl) Quality() uint8 {
	return uint8(C.MagickGetImageCompressionQuality(self.wand))
}

// Changes the compression quality of the canvas. Ranges from 1 (lowest) to 100 (highest).
func (self *wandImpl) SetQuality(quality uint8) error {
	success := C.MagickSetImageCompressionQuality(self.wand, C.size_t(quality))

	if success == C.MagickFalse {
		return fmt.Errorf("Could not set compression quality: %s", self.Error())
	}

	return nil
}

// Destroys image.
func (self *wandImpl) Destroy() error {

	if self.wand == nil {
		return fmt.Errorf("Nothing to destroy")
	} else {
		C.DestroyMagickWand(self.wand)
		self.wand = nil
	}

	return nil
}

func (self *wandImpl) Close() error {
	self.Destroy()
	return nil
}

// Returns all metadata keys from the currently loaded image.
func (self *wandImpl) Metadata() map[string]string {
	var n C.size_t
	var i C.size_t

	var value *C.char
	var key *C.char

	data := make(map[string]string)

	cplist := C.CString("*")

	properties := C.MagickGetImageProperties(self.wand, cplist, &n)

	C.free(unsafe.Pointer(cplist))

	for i = 0; i < n; i++ {
		key = C.MagickGetPropertyName(properties, C.size_t(i))
		value = C.MagickGetImageProperty(self.wand, key)

		data[strings.Trim(C.GoString(key), " ")] = strings.Trim(C.GoString(value), " ")

		C.MagickRelinquishMemory(unsafe.Pointer(value))
		C.MagickRelinquishMemory(unsafe.Pointer(key))
	}

	return data
}

// Returns the latest error reported by the MagickWand API.
func (self *wandImpl) Error() error {
	var t C.ExceptionType
	ptr := C.MagickGetException(self.wand, &t)
	message := C.GoString(ptr)
	C.MagickClearException(self.wand)
	C.MagickRelinquishMemory(unsafe.Pointer(ptr))
	return fmt.Errorf(message)
}

func Finalize() {
	C.MagickWandTerminus()
}
<commit_msg>区分Linux和OSX时的编译环境<commit_after>package image

/*
#cgo linux pkg-config: MagickWand
#cgo darwin pkg-config: MagickWand-6.Q16

#include <wand/MagickWand.h>

char *MagickGetPropertyName(char **properties, size_t index) {
  return properties[index];
}

*/
import "C"

import (
	"fmt"
	// "imsto"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"unsafe"
)

func cargv(b [][]byte) **C.char {
	outer := make([]*C.char, len(b)+1)
	for i, inner := range b {
		outer[i] = C.CString(string(inner))
	}
	return (**C.char)(unsafe.Pointer(&outer[0])) // void bar(**char) {...}
}

// Image object
type wandImpl struct {
	wand *C.MagickWand

	filename string
	width    string
	height   string

	wopt WriteOption
}

func init() {
	C.MagickWandGenesis()
}

// Returns a new image object.
func newWandImage() *wandImpl {
	self := &wandImpl{}

	self.wand = C.NewMagickWand()

	return self
}

// Opens an image file, returns nil on success, error otherwise.
func (self *wandImpl) Open(r io.Reader) error {
	// stat, err := os.Stat(filename)

	// if err != nil {
	// 	return err
	// }

	// if stat.IsDir() == true {
	// 	return fmt.Errorf(`Could not open file "%s": it's a directory!`, filename)
	// }
	var status C.MagickBooleanType

	if f, ok := r.(*os.File); ok {
		f.Seek(0, 0)
		// cfilename := C.CString(filename)
		// status := C.MagickReadImage(self.wand, cfilename)
		// C.free(unsafe.Pointer(cfilename))
		cmode := C.CString("rb")
		defer C.free(unsafe.Pointer(cmode))
		file := C.fdopen(C.int(f.Fd()), cmode)
		defer C.fclose(file)
		status = C.MagickReadImageFile(self.wand, file)
		self.filename = f.Name()
	} else {
		// var blob []byte
		blob, err := ioutil.ReadAll(f)

		if err != nil {
			log.Println(err)
			return err
		}

		status = C.MagickReadImageBlob(self.wand, unsafe.Pointer(&blob[0]), C.size_t(len(blob)))
	}
	if status == C.MagickFalse {
		return fmt.Errorf(`Could not open image: %s`, self.Error())
	}

	// self.filename = filename

	// _im := C.GetImageFromMagickWand(self.wand)

	// fmt.Println(_im.columns)

	return nil
}

// Reads an image or image sequence from a blob.
func (self *wandImpl) OpenBlob(blob []byte) error {
	status := C.MagickReadImageBlob(self.wand, unsafe.Pointer(&blob[0]), C.size_t(len(blob)))

	if status == C.MagickFalse {
		return fmt.Errorf(`Could not open image from blob: %s`, self.Error())
	}

	return nil
}

func (self *wandImpl) GetAttr() *ImageAttr {
	return NewImageAttr(self.Width(), self.Height(), self.Quality())
}

// Returns the format of a particular image in a sequence.
func (self *wandImpl) Format() string {
	return C.GoString(C.MagickGetImageFormat(self.wand))
}

// Sets the format of a particular image
func (self *wandImpl) SetFormat(format string) error {
	cformat := C.CString(format)
	defer C.free(unsafe.Pointer(cformat))

	if C.MagickSetImageFormat(self.wand, cformat) == C.MagickFalse {
		return fmt.Errorf("Could not set format: %s", self.Error())
	}

	return nil
}

func (self *wandImpl) SetOption(wopt WriteOption) {
	self.wopt = wopt
	self.SetQuality(wopt.Quality)
}

// Get image data as a byte array.
func (self *wandImpl) GetImageBlob() ([]byte, error) {
	size := C.size_t(0)
	p := unsafe.Pointer(C.MagickGetImageBlob(self.wand, &size))
	if size == 0 {
		return nil, fmt.Errorf("Could not get image blob \n")
	}

	blob := C.GoBytes(p, C.int(size))

	C.MagickRelinquishMemory(p)

	return blob, nil
}

// Converts the current image into a thumbnail of the specified
// width and height preserving ratio. It uses Crop() to clip the
// image to the specified area.
//
// If width or height are bigger than the current image, a centered
// thumbnail will be produced.
//
// Is width and height are smaller than the current image, the image
// will be resized and cropped, if needed.
func (self *wandImpl) Thumbnail(topt ThumbOption) error {

	// TODO:

	return nil
}

// Returns image' width.
func (self *wandImpl) Width() uint {
	return uint(C.MagickGetImageWidth(self.wand))
}

// Returns image' height.
func (self *wandImpl) Height() uint {
	return uint(C.MagickGetImageHeight(self.wand))
}

// Writes image to a file, returns nil on success.
func (self *wandImpl) Write(out io.Writer) error {
	if f, ok := out.(*os.File); ok {

		cmode := C.CString("w+")
		defer C.free(unsafe.Pointer(cmode))
		file := C.fdopen(C.int(f.Fd()), cmode)
		defer C.fclose(file)
		success := C.MagickWriteImageFile(self.wand, file)

		if success == C.MagickFalse {
			return fmt.Errorf("Could not write: %s", self.Error())
		}

	} else {
		var size *uint
		blob := self.Blob(size)

		log.Printf("blob %d bytes\n", size)
		out.Write(blob)
	}
	return nil
}

// Implements direct to memory image formats. It returns the image as a blob
func (self *wandImpl) Blob(length *uint) []byte {
	ptr := unsafe.Pointer(C.MagickGetImageBlob(self.wand, (*C.size_t)(unsafe.Pointer(length))))
	data := C.GoBytes(ptr, C.int(*length))
	C.MagickRelinquishMemory(ptr)
	return data
}

// Changes the size of the image, returns true on success.
func (self *wandImpl) Resize(width uint, height uint) error {
	success := C.MagickResizeImage(self.wand, C.size_t(width), C.size_t(height), C.GaussianFilter, C.double(1.0))

	if success == C.MagickFalse {
		return fmt.Errorf("Could not resize: %s", self.Error())
	}

	return nil
}

// Returns the compression quality of the image. Ranges from 1 (lowest) to 100 (highest).
func (self *wandImpl) Quality() uint8 {
	return uint8(C.MagickGetImageCompressionQuality(self.wand))
}

// Changes the compression quality of the canvas. Ranges from 1 (lowest) to 100 (highest).
func (self *wandImpl) SetQuality(quality uint8) error {
	success := C.MagickSetImageCompressionQuality(self.wand, C.size_t(quality))

	if success == C.MagickFalse {
		return fmt.Errorf("Could not set compression quality: %s", self.Error())
	}

	return nil
}

// Destroys image.
func (self *wandImpl) Destroy() error {

	if self.wand == nil {
		return fmt.Errorf("Nothing to destroy")
	} else {
		C.DestroyMagickWand(self.wand)
		self.wand = nil
	}

	return nil
}

func (self *wandImpl) Close() error {
	self.Destroy()
	return nil
}

// Returns all metadata keys from the currently loaded image.
func (self *wandImpl) Metadata() map[string]string {
	var n C.size_t
	var i C.size_t

	var value *C.char
	var key *C.char

	data := make(map[string]string)

	cplist := C.CString("*")

	properties := C.MagickGetImageProperties(self.wand, cplist, &n)

	C.free(unsafe.Pointer(cplist))

	for i = 0; i < n; i++ {
		key = C.MagickGetPropertyName(properties, C.size_t(i))
		value = C.MagickGetImageProperty(self.wand, key)

		data[strings.Trim(C.GoString(key), " ")] = strings.Trim(C.GoString(value), " ")

		C.MagickRelinquishMemory(unsafe.Pointer(value))
		C.MagickRelinquishMemory(unsafe.Pointer(key))
	}

	return data
}

// Returns the latest error reported by the MagickWand API.
func (self *wandImpl) Error() error {
	var t C.ExceptionType
	ptr := C.MagickGetException(self.wand, &t)
	message := C.GoString(ptr)
	C.MagickClearException(self.wand)
	C.MagickRelinquishMemory(unsafe.Pointer(ptr))
	return fmt.Errorf(message)
}

func Finalize() {
	C.MagickWandTerminus()
}
<|endoftext|>


<commit_before>package inbox_test

import (
	"encoding/json"
	"errors"
	"sync/atomic"
	"syscall"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"

	"github.com/apcera/nats"
	"github.com/cloudfoundry-incubator/runtime-schema/cc_messages"
	"github.com/cloudfoundry-incubator/stager/cc_client/fakes"
	. "github.com/cloudfoundry-incubator/stager/inbox"
	"github.com/cloudfoundry-incubator/stager/stager/fake_stager"
	"github.com/cloudfoundry/gunk/diegonats"
)

var _ = Describe("Inbox", func() {
	var fakenats *diegonats.FakeNATSClient
	var fakeCcClient *fakes.FakeCcClient
	var fauxstager *fake_stager.FakeStager
	var logOutput *gbytes.Buffer
	var logger lager.Logger
	var validator RequestValidator
	var stagingRequest cc_messages.StagingRequestFromCC

	var inbox ifrit.Process

	BeforeEach(func() {
		logOutput = gbytes.NewBuffer()
		logger = lager.NewLogger("fakelogger")
		logger.RegisterSink(lager.NewWriterSink(logOutput, lager.INFO))

		stagingRequest = cc_messages.StagingRequestFromCC{
			AppId:  "myapp",
			TaskId: "mytask",
		}

		fakenats = diegonats.NewFakeClient()
		fakeCcClient = &fakes.FakeCcClient{}
		fauxstager = &fake_stager.FakeStager{}
		validator = func(request cc_messages.StagingRequestFromCC) error {
			return nil
		}
	})

	publishStagingMessage := func() {
		msg, _ := json.Marshal(stagingRequest)
		fakenats.Publish(DiegoStageStartSubject, msg)
	}

	Context("when subscribing fails", func() {
		var attempts uint32
		var process chan ifrit.Process

		BeforeEach(func() {
			fakenats.WhenSubscribing(DiegoStageStartSubject, func(callback nats.MsgHandler) error {
				atomic.AddUint32(&attempts, 1)
				return errors.New("oh no!")
			})
		})

		JustBeforeEach(func() {
			process = make(chan ifrit.Process)
			go func() {
				process <- ifrit.Invoke(New(fakenats, fakeCcClient, fauxstager, nil, validator, logger))
			}()
		})

		AfterEach(func(done Done) {
			p := <-process
			p.Signal(syscall.SIGTERM)
			<-p.Wait()
			close(done)
		})

		It("continues retrying until it succeeds", func() {
			Eventually(func() uint32 {
				return atomic.LoadUint32(&attempts)
			}).Should(BeNumerically(">=", 1))

			Eventually(func() uint32 {
				return atomic.LoadUint32(&attempts)
			}).Should(BeNumerically(">=", 2))

			Consistently(func() []*nats.Subscription {
				return fakenats.Subscriptions(DiegoStageStartSubject)
			}).Should(BeEmpty())

			fakenats.WhenSubscribing(DiegoStageStartSubject, func(callback nats.MsgHandler) error {
				return nil
			})

			Eventually(func() []*nats.Subscription {
				return fakenats.Subscriptions(DiegoStageStartSubject)
			}).ShouldNot(BeEmpty())
		})
	})

	Context("when subscribing succeeds", func() {
		JustBeforeEach(func() {
			inbox = ifrit.Envoke(New(fakenats, fakeCcClient, fauxstager, nil, validator, logger))
		})

		AfterEach(func(done Done) {
			inbox.Signal(syscall.SIGTERM)
			<-inbox.Wait()
			close(done)
		})

		Context("and it receives a staging request", func() {
			It("kicks off staging", func() {
				publishStagingMessage()

				Ω(fauxstager.TimesStageInvoked).To(Equal(1))
				Ω(fauxstager.StagingRequests[0]).To(Equal(stagingRequest))
			})

			Context("when staging finishes successfully", func() {
				It("does not send a staging complete message", func() {
					publishStagingMessage()
					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(0))
				})
			})

			Context("when staging finishes unsuccessfully", func() {
				BeforeEach(func() {
					fauxstager.AlwaysFail = true
				})

				It("logs the failure", func() {
					Ω(logOutput.Contents()).Should(BeEmpty())

					publishStagingMessage()

					Ω(logOutput).Should(gbytes.Say("failed"))
				})

				It("sends a staging failure response", func() {
					publishStagingMessage()

					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(1))
					response, _ := fakeCcClient.StagingCompleteArgsForCall(0)

					stagingResponse := cc_messages.StagingResponseForCC{}
					json.Unmarshal(response, &stagingResponse)
					Ω(stagingResponse.Error).Should(Equal("Staging failed: The thingy broke :("))
				})
			})

			Context("when the request is invalid", func() {
				BeforeEach(func() {
					validator = func(cc_messages.StagingRequestFromCC) error {
						return errors.New("NO.")
					}
				})

				It("logs the failure", func() {
					publishStagingMessage()
					Ω(logOutput.Contents()).ShouldNot(BeEmpty())
				})

				It("sends a staging failure response", func() {
					publishStagingMessage()

					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(1))
					response, _ := fakeCcClient.StagingCompleteArgsForCall(0)

					stagingResponse := cc_messages.StagingResponseForCC{}
					json.Unmarshal(response, &stagingResponse)

					Ω(stagingResponse).Should(Equal(cc_messages.StagingResponseForCC{
						AppId:  "myapp",
						TaskId: "mytask",
						Error:  "Invalid staging request: NO.",
					}))
				})
			})

			Context("when unmarshaling fails", func() {
				It("logs the failure", func() {
					Ω(logOutput.Contents()).Should(BeEmpty())

					fakenats.Publish(DiegoStageStartSubject, []byte("fdsaljkfdsljkfedsews:/sdfa:''''"))

					Ω(logOutput).Should(gbytes.Say("malformed"))
				})

				It("does not send a message in response", func() {
					fakenats.Publish(DiegoStageStartSubject, []byte("fdsaljkfdsljkfedsews:/sdfa:''''"))
					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(0))
				})
			})
		})
	})
})
<commit_msg>We don't log as much as we thought.<commit_after>package inbox_test

import (
	"encoding/json"
	"errors"
	"sync/atomic"
	"syscall"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"

	"github.com/apcera/nats"
	"github.com/cloudfoundry-incubator/runtime-schema/cc_messages"
	"github.com/cloudfoundry-incubator/stager/cc_client/fakes"
	. "github.com/cloudfoundry-incubator/stager/inbox"
	"github.com/cloudfoundry-incubator/stager/stager/fake_stager"
	"github.com/cloudfoundry/gunk/diegonats"
)

var _ = Describe("Inbox", func() {
	var fakenats *diegonats.FakeNATSClient
	var fakeCcClient *fakes.FakeCcClient
	var fauxstager *fake_stager.FakeStager
	var logOutput *gbytes.Buffer
	var logger lager.Logger
	var validator RequestValidator
	var stagingRequest cc_messages.StagingRequestFromCC

	var inbox ifrit.Process

	BeforeEach(func() {
		logOutput = gbytes.NewBuffer()
		logger = lager.NewLogger("fakelogger")
		logger.RegisterSink(lager.NewWriterSink(logOutput, lager.INFO))

		stagingRequest = cc_messages.StagingRequestFromCC{
			AppId:  "myapp",
			TaskId: "mytask",
		}

		fakenats = diegonats.NewFakeClient()
		fakeCcClient = &fakes.FakeCcClient{}
		fauxstager = &fake_stager.FakeStager{}
		validator = func(request cc_messages.StagingRequestFromCC) error {
			return nil
		}
	})

	publishStagingMessage := func() {
		msg, _ := json.Marshal(stagingRequest)
		fakenats.Publish(DiegoStageStartSubject, msg)
	}

	Context("when subscribing fails", func() {
		var attempts uint32
		var process chan ifrit.Process

		BeforeEach(func() {
			fakenats.WhenSubscribing(DiegoStageStartSubject, func(callback nats.MsgHandler) error {
				atomic.AddUint32(&attempts, 1)
				return errors.New("oh no!")
			})
		})

		JustBeforeEach(func() {
			process = make(chan ifrit.Process)
			go func() {
				process <- ifrit.Invoke(New(fakenats, fakeCcClient, fauxstager, nil, validator, logger))
			}()
		})

		AfterEach(func(done Done) {
			p := <-process
			p.Signal(syscall.SIGTERM)
			<-p.Wait()
			close(done)
		})

		It("continues retrying until it succeeds", func() {
			Eventually(func() uint32 {
				return atomic.LoadUint32(&attempts)
			}).Should(BeNumerically(">=", 1))

			Eventually(func() uint32 {
				return atomic.LoadUint32(&attempts)
			}).Should(BeNumerically(">=", 2))

			Consistently(func() []*nats.Subscription {
				return fakenats.Subscriptions(DiegoStageStartSubject)
			}).Should(BeEmpty())

			fakenats.WhenSubscribing(DiegoStageStartSubject, func(callback nats.MsgHandler) error {
				return nil
			})

			Eventually(func() []*nats.Subscription {
				return fakenats.Subscriptions(DiegoStageStartSubject)
			}).ShouldNot(BeEmpty())
		})
	})

	Context("when subscribing succeeds", func() {
		JustBeforeEach(func() {
			inbox = ifrit.Envoke(New(fakenats, fakeCcClient, fauxstager, nil, validator, logger))
		})

		AfterEach(func(done Done) {
			inbox.Signal(syscall.SIGTERM)
			<-inbox.Wait()
			close(done)
		})

		Context("and it receives a staging request", func() {
			It("kicks off staging", func() {
				publishStagingMessage()

				Ω(fauxstager.TimesStageInvoked).To(Equal(1))
				Ω(fauxstager.StagingRequests[0]).To(Equal(stagingRequest))
			})

			Context("when staging finishes successfully", func() {
				It("does not send a staging complete message", func() {
					publishStagingMessage()
					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(0))
				})
			})

			Context("when staging finishes unsuccessfully", func() {
				BeforeEach(func() {
					fauxstager.AlwaysFail = true
				})

				It("logs the failure", func() {
					Ω(logOutput.Contents()).Should(BeEmpty())

					publishStagingMessage()

					Ω(logOutput).Should(gbytes.Say("failed"))
				})

				It("sends a staging failure response", func() {
					publishStagingMessage()

					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(1))
					response, _ := fakeCcClient.StagingCompleteArgsForCall(0)

					stagingResponse := cc_messages.StagingResponseForCC{}
					json.Unmarshal(response, &stagingResponse)
					Ω(stagingResponse.Error).Should(Equal("Staging failed"))
				})
			})

			Context("when the request is invalid", func() {
				BeforeEach(func() {
					validator = func(cc_messages.StagingRequestFromCC) error {
						return errors.New("NO.")
					}
				})

				It("logs the failure", func() {
					publishStagingMessage()
					Ω(logOutput.Contents()).ShouldNot(BeEmpty())
				})

				It("sends a staging failure response", func() {
					publishStagingMessage()

					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(1))
					response, _ := fakeCcClient.StagingCompleteArgsForCall(0)

					stagingResponse := cc_messages.StagingResponseForCC{}
					json.Unmarshal(response, &stagingResponse)

					Ω(stagingResponse).Should(Equal(cc_messages.StagingResponseForCC{
						AppId:  "myapp",
						TaskId: "mytask",
						Error:  "Invalid staging request: NO.",
					}))
				})
			})

			Context("when unmarshaling fails", func() {
				It("logs the failure", func() {
					Ω(logOutput.Contents()).Should(BeEmpty())

					fakenats.Publish(DiegoStageStartSubject, []byte("fdsaljkfdsljkfedsews:/sdfa:''''"))

					Ω(logOutput).Should(gbytes.Say("malformed"))
				})

				It("does not send a message in response", func() {
					fakenats.Publish(DiegoStageStartSubject, []byte("fdsaljkfdsljkfedsews:/sdfa:''''"))
					Ω(fakeCcClient.StagingCompleteCallCount()).To(Equal(0))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "image"
  "log"
  "github.com/disintegration/imaging"
)

// "encoding/hex"
// "image/color"

func main() {
  // Open test image
  src, err := imaging.Open("lena_512.png")
  if err != nil {
    log.Fatalf("Open failed: %v", err)
  }

  dhash(src, 8)

  // Crop the image to 350x350 px using the Center anchor
  //src = imaging.CropAnchor(src, 350, 350, imaging.Center)

  // Resize the cropped image to a width of 256px, but preserving aspect ratio
  //src = imaging.Resize(src, 256, 0, imaging.Lanczos)

  // Create a blurred version of the image
  //img1 := imaging.Blur(src, 2)

  // Create a grayscaled version of the image, and heighten the contrast & sharpness
  //img2 := imaging.Grayscale(src)
  //img2 = imaging.AdjustContrast(img2, 20)
  //img2 = imaging.Sharpen(img2, 2)

  // Create an inverted version of the image
  //img3 := imaging.Invert(src)

  // Create an embossed version of the image using a convolution filter
  //img4 := imaging.Convolve3x3(
  //  src,
  //  [9]float64{
  //    -1, -1,  0,
  //    -1,  1,  1,
  //     0,  1,  1,
  //  },
  //  nil,
  //)

  // Create a new image and paste the four produced images into it
  //dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
  //dst = imaging.Paste(dst, img1, image.Pt(0, 0))
  //dst = imaging.Paste(dst, img2, image.Pt(0, 256))
  //dst = imaging.Paste(dst, img3, image.Pt(256, 0))
  //dst = imaging.Paste(dst, img4, image.Pt(256, 256))

  // Save the resulting image using JPEG format
  //err = imaging.Save(dst, "example_out.jpg")
  //if err != nil {
  //  log.Fatalf("Save failed: %v", err)
  //}
}

func dhash(img image.Image, bitLen int) {
  // Width and height of the scaled-down image
  width, height := bitLen + 1, bitLen

  // Grayscale the image. Do this first for performance.
  res := imaging.Grayscale(img)

  // Downscale the image by 'bitLen' amount for a horizonal diff.
  res = imaging.Resize(res, width, height, imaging.Lanczos)

  var sig []byte  // The byte array signature that will be returned
  var prev uint32 // Variable to store the previous pixel value

  // Calculate the horizonal gradient difference
  for y := 0; y < height; y++ {
    for x := 0; x < width; x++ {
      // Since the image is grayscaled, r = g = b
      r,_,_,_ := res.At(x,y).RGBA() // Get the pixel at (x,y)
      // r = r / 257 // Not needed, </> comparison still works the same

      // If this is not the first value of the current row, then
      // compare the gradient difference from the previous one
      if x > 0 {
        if prev < r {
          sig = append(sig, 1) // if it's smaller, append '1'
        } else {
          sig = append(sig, 0) // else append '0'
        }
      }
      prev = r // Set this current pixel value as the previous one
    }
  }

  fmt.Println(sig)

  // Initialize the difference matrix that will be returned
  // DiffMatrix := make([][]int, bitLen)
  // for i := range DiffMatrix {
  //   DiffMatrix[i] = make([]int, bitLen)
  // }
  // DiffMatrix[x-1][y] = 1 // DiffMatrix is 8x8, not 9x8
  // fmt.Print("1")
  // row = append(row, 1)

  /*
  // var diff [hashlen][hashlen]int
  // diff := make([][]int, hashlen)
  var pixels [][]uint32
  bounds := res.Bounds()

  s := ""

  for y := 0; y < bounds.Max.Y; y++ {
    var row []uint32
    for x := 0; x < bounds.Max.X; x++ {
      r,_,_,_ := res.At(x,y).RGBA()
      row = append(row, r/257)
    }
    fmt.Println(row)
    pixels = append(pixels, row)
  }

  // extract the first row NOPE

  // fmt.Println(diff)

  // For each row
  for i := 0; i < 8; i++ {

    // For each column, except the last
    for j := 0; j < 9 - 1; j++ {
      if pixels[i][j] < pixels[i][j+1] {
        // fmt.Print("1")
        s += "1"
      } else {
        // fmt.Print("0")
        s += "0"
      }
      // fmt.Println(pixels[i][j], pixels[i][j+1])
      // fmt.Println(i,j)
    }
  }

  dst := []byte(s)
  encStr := hex.EncodeToString(dst)

  // for y := 0; y < 8; y++ {
  //   for x := 0; x < 9; x++ {
      // if pixels[x-1][y] < pixels[x][y] {
      //   // diff[x][y] = 1
      //   fmt.Print("1")
      // } else {
      //   // diff[x][y] = 0
        // fmt.Print("0")
      // }
  //   }
  // }
  fmt.Printf("%s\n", encStr)
  // fmt.Println(diff)
  */
}

// Generate a pixel array that can be iterated over
/*func grayscalePixelArray(img image.Image) [][]uint32 {
  var pixels [][]uint32

  // Determine the bounds
  bounds := img.Bounds()

  // For each row
  for x := 0; x < bounds.Max.X; x++ {
    var row []uint32

    // For each column
    for y := 0; y < bounds.Max.Y; y++ {
      // Since it's grayscale, r = g = b
      r,_,_,_ := img.At(x,y).RGBA()

      // Append this column to a 'row' array
      row = append(row, r / 257)
    }

    // append that 'row' array to the pixel array
    pixels = append(pixels, row)
  }
  return pixels
}*/

// do a 'rotate' Go function and a 'scale' one
<commit_msg>Working horizontal dhash implementation<commit_after>package main

import (
  "fmt"
  "image"
  "log"
  "github.com/disintegration/imaging"
)

// "encoding/hex"
// "image/color"

func main() {
  // Open test image
  src, err := imaging.Open("lena_512.png")
  if err != nil {
    log.Fatalf("Open failed: %v", err)
  }

  dhash(src, 8)

  // Crop the image to 350x350 px using the Center anchor
  //src = imaging.CropAnchor(src, 350, 350, imaging.Center)

  // Resize the cropped image to a width of 256px, but preserving aspect ratio
  //src = imaging.Resize(src, 256, 0, imaging.Lanczos)

  // Create a blurred version of the image
  //img1 := imaging.Blur(src, 2)

  // Create a grayscaled version of the image, and heighten the contrast & sharpness
  //img2 := imaging.Grayscale(src)
  //img2 = imaging.AdjustContrast(img2, 20)
  //img2 = imaging.Sharpen(img2, 2)

  // Create an inverted version of the image
  //img3 := imaging.Invert(src)

  // Create an embossed version of the image using a convolution filter
  //img4 := imaging.Convolve3x3(
  //  src,
  //  [9]float64{
  //    -1, -1,  0,
  //    -1,  1,  1,
  //     0,  1,  1,
  //  },
  //  nil,
  //)

  // Create a new image and paste the four produced images into it
  //dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0})
  //dst = imaging.Paste(dst, img1, image.Pt(0, 0))
  //dst = imaging.Paste(dst, img2, image.Pt(0, 256))
  //dst = imaging.Paste(dst, img3, image.Pt(256, 0))
  //dst = imaging.Paste(dst, img4, image.Pt(256, 256))

  // Save the resulting image using JPEG format
  //err = imaging.Save(dst, "example_out.jpg")
  //if err != nil {
  //  log.Fatalf("Save failed: %v", err)
  //}
}

func binaryArrayToHex()  {

}

func dhash(img image.Image, bitLen int) {
  // Width and height of the scaled-down image
  width, height := bitLen + 1, bitLen

  // Grayscale the image. Do this first for performance.
  res := imaging.Grayscale(img)

  // Downscale the image by 'bitLen' amount for a horizonal diff.
  res = imaging.Resize(res, width, height, imaging.Lanczos)

  var sig []byte  // The byte array signature that will be returned
  var prev uint32 // Variable to store the previous pixel value

  // Calculate the horizonal gradient difference
  for y := 0; y < height; y++ {
    for x := 0; x < width; x++ {
      // Since the image is grayscaled, r = g = b
      r,_,_,_ := res.At(x,y).RGBA() // Get the pixel at (x,y)
      // r = r / 257 // Not needed, </> comparison still works the same

      // If this is not the first value of the current row, then
      // compare the gradient difference from the previous one
      if x > 0 {
        if prev < r {
          sig = append(sig, 1) // if it's smaller, append '1'
        } else {
          sig = append(sig, 0) // else append '0'
        }
      }
      prev = r // Set this current pixel value as the previous one
    }
  }

  fmt.Printf(sig)

  // Initialize the difference matrix that will be returned
  // DiffMatrix := make([][]int, bitLen)
  // for i := range DiffMatrix {
  //   DiffMatrix[i] = make([]int, bitLen)
  // }
  // DiffMatrix[x-1][y] = 1 // DiffMatrix is 8x8, not 9x8
  // fmt.Print("1")
  // row = append(row, 1)

  /*
  // var diff [hashlen][hashlen]int
  // diff := make([][]int, hashlen)
  var pixels [][]uint32
  bounds := res.Bounds()

  s := ""

  for y := 0; y < bounds.Max.Y; y++ {
    var row []uint32
    for x := 0; x < bounds.Max.X; x++ {
      r,_,_,_ := res.At(x,y).RGBA()
      row = append(row, r/257)
    }
    fmt.Println(row)
    pixels = append(pixels, row)
  }

  // extract the first row NOPE

  // fmt.Println(diff)

  // For each row
  for i := 0; i < 8; i++ {

    // For each column, except the last
    for j := 0; j < 9 - 1; j++ {
      if pixels[i][j] < pixels[i][j+1] {
        // fmt.Print("1")
        s += "1"
      } else {
        // fmt.Print("0")
        s += "0"
      }
      // fmt.Println(pixels[i][j], pixels[i][j+1])
      // fmt.Println(i,j)
    }
  }

  dst := []byte(s)
  encStr := hex.EncodeToString(dst)

  // for y := 0; y < 8; y++ {
  //   for x := 0; x < 9; x++ {
      // if pixels[x-1][y] < pixels[x][y] {
      //   // diff[x][y] = 1
      //   fmt.Print("1")
      // } else {
      //   // diff[x][y] = 0
        // fmt.Print("0")
      // }
  //   }
  // }
  fmt.Printf("%s\n", encStr)
  // fmt.Println(diff)
  */
}

// Generate a pixel array that can be iterated over
/*func grayscalePixelArray(img image.Image) [][]uint32 {
  var pixels [][]uint32

  // Determine the bounds
  bounds := img.Bounds()

  // For each row
  for x := 0; x < bounds.Max.X; x++ {
    var row []uint32

    // For each column
    for y := 0; y < bounds.Max.Y; y++ {
      // Since it's grayscale, r = g = b
      r,_,_,_ := img.At(x,y).RGBA()

      // Append this column to a 'row' array
      row = append(row, r / 257)
    }

    // append that 'row' array to the pixel array
    pixels = append(pixels, row)
  }
  return pixels
}*/

// do a 'rotate' Go function and a 'scale' one
<|endoftext|>


<commit_before>package enw

import (
	. "gopkg.in/check.v1"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type EnwSuite struct{}

var _ = Suite(&EnwSuite{})
<commit_msg>added test.<commit_after>package enw

import (
	"runtime"

	. "gopkg.in/check.v1"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type EnwSuite struct{}

var _ = Suite(&EnwSuite{})

func (e *EnwSuite) TestStartAndStopWatching(c *C) {
	n := runtime.NumGoroutine()
	Watch("VAR", func(string, string) {})
	c.Assert(runtime.NumGoroutine(), Equals, n+1)

	Forget("VAR")
	runtime.Gosched()
	c.Assert(runtime.NumGoroutine(), Equals, n)
}
<|endoftext|>


<commit_before>package index

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"testing"
)

const (
	url = "https://www.etsy.com/"
	rev = "r420"
)

func thisDir() string {
	_, file, _, _ := runtime.Caller(0)
	return filepath.Dir(file)
}

func buildIndex(url, rev string) (*IndexRef, error) {
	dir, err := ioutil.TempDir(os.TempDir(), "hound")
	if err != nil {
		return nil, err
	}

	var opt IndexOptions

	return Build(&opt, dir, thisDir(), url, rev)
}

func TestSearch(t *testing.T) {
	// Build an index
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}
	defer ref.Remove()

	// Make sure the metadata in the ref is good.
	if ref.Rev != rev {
		t.Fatalf("expected rev of %s, got %s", rev, ref.Rev)
	}

	if ref.Url != url {
		t.Fatalf("expected url of %s got %s", url, ref.Url)
	}

	// Make sure the ref can be opened.
	idx, err := ref.Open()
	if err != nil {
		t.Fatal(err)
	}
	defer idx.Close()

	// Make sure we can carry out a search
	if _, err := idx.Search("5a1c0dac2d9b3ea4085b30dd14375c18eab993d5", &SearchOptions{}); err != nil {
		t.Fatal(err)
	}
}

func TestRemove(t *testing.T) {
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}

	if err := ref.Remove(); err != nil {
		t.Fatal(err)
	}

	if _, err := os.Stat(ref.Dir()); err == nil {
		t.Fatalf("Remove did not delete directory: %s", ref.Dir())
	}
}

func TestRead(t *testing.T) {
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}
	defer ref.Remove()

	r, err := Read(ref.Dir())
	if err != nil {
		t.Fatal(err)
	}

	if r.Url != url {
		t.Fatalf("expected url of %s, got %s", url, r.Url)
	}

	if r.Rev != rev {
		t.Fatal("expected rev of %s, got %s", rev, r.Rev)
	}

	idx, err := r.Open()
	if err != nil {
		t.Fatal(err)
	}
	defer idx.Close()
}
<commit_msg>index: fix warning with use of %s in Fatal<commit_after>package index

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"testing"
)

const (
	url = "https://www.etsy.com/"
	rev = "r420"
)

func thisDir() string {
	_, file, _, _ := runtime.Caller(0)
	return filepath.Dir(file)
}

func buildIndex(url, rev string) (*IndexRef, error) {
	dir, err := ioutil.TempDir(os.TempDir(), "hound")
	if err != nil {
		return nil, err
	}

	var opt IndexOptions

	return Build(&opt, dir, thisDir(), url, rev)
}

func TestSearch(t *testing.T) {
	// Build an index
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}
	defer ref.Remove()

	// Make sure the metadata in the ref is good.
	if ref.Rev != rev {
		t.Fatalf("expected rev of %s, got %s", rev, ref.Rev)
	}

	if ref.Url != url {
		t.Fatalf("expected url of %s got %s", url, ref.Url)
	}

	// Make sure the ref can be opened.
	idx, err := ref.Open()
	if err != nil {
		t.Fatal(err)
	}
	defer idx.Close()

	// Make sure we can carry out a search
	if _, err := idx.Search("5a1c0dac2d9b3ea4085b30dd14375c18eab993d5", &SearchOptions{}); err != nil {
		t.Fatal(err)
	}
}

func TestRemove(t *testing.T) {
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}

	if err := ref.Remove(); err != nil {
		t.Fatal(err)
	}

	if _, err := os.Stat(ref.Dir()); err == nil {
		t.Fatalf("Remove did not delete directory: %s", ref.Dir())
	}
}

func TestRead(t *testing.T) {
	ref, err := buildIndex(url, rev)
	if err != nil {
		t.Fatal(err)
	}
	defer ref.Remove()

	r, err := Read(ref.Dir())
	if err != nil {
		t.Fatal(err)
	}

	if r.Url != url {
		t.Fatalf("expected url of %s, got %s", url, r.Url)
	}

	if r.Rev != rev {
		t.Fatalf("expected rev of %s, got %s", rev, r.Rev)
	}

	idx, err := r.Open()
	if err != nil {
		t.Fatal(err)
	}
	defer idx.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"net/http"
	"strconv"
	"sync/atomic"
	"testing"
	"time"

	"github.com/buger/gor/listener"
	"github.com/buger/gor/replay"

	"math/rand"
)

func isEqual(t *testing.T, a interface{}, b interface{}) {
	if a != b {
		t.Error("Original and Replayed request not match\n", a, "!=", b)
	}
}

var envs int

type Env struct {
	Verbose bool

	ListenHandler http.HandlerFunc
	ReplayHandler http.HandlerFunc

	ReplayLimit   int
	ListenerLimit int
	ForwardPort   int
}

func (e *Env) start() (p int) {
	p = 50000 + envs*10

	go e.startHTTP(p, http.HandlerFunc(e.ListenHandler))
	go e.startHTTP(p+2, http.HandlerFunc(e.ReplayHandler))

	go e.startHTTP(p+3, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}))

	go e.startListener(p, p+1)
	go e.startReplay(p+1, p+2)

	// Time to start http and gor instances
	time.Sleep(time.Millisecond * 100)

	envs++

	return
}

func (e *Env) startListener(port int, replayPort int) {
	listener.Settings.Verbose = e.Verbose
	listener.Settings.Address = "127.0.0.1"
	listener.Settings.ReplayAddress = "127.0.0.1:" + strconv.Itoa(replayPort)
	listener.Settings.Port = port

	if e.ListenerLimit != 0 {
		listener.Settings.ReplayLimit = e.ListenerLimit
	}

	listener.Run()
}

func (e *Env) startReplay(port int, forwardPort int) {
	replay.Settings.Verbose = e.Verbose
	replay.Settings.Host = "127.0.0.1"
	replay.Settings.Address = "127.0.0.1:" + strconv.Itoa(port)
	replay.Settings.ForwardAddress = "127.0.0.1:" + strconv.Itoa(forwardPort)
	replay.Settings.Port = port

	if e.ReplayLimit != 0 {
		replay.Settings.ForwardAddress += "|" + strconv.Itoa(e.ReplayLimit)
	}

	replay.Settings.ForwardAddress += ",127.0.0.1:" + strconv.Itoa(forwardPort+1)

	replay.Run()
}

func (e *Env) startHTTP(port int, handler http.Handler) {
	err := http.ListenAndServe(":"+strconv.Itoa(port), handler)

	if err != nil {
		fmt.Println("Error while starting http server:", err)
	}
}

func getRequest(port int) *http.Request {
	var req *http.Request

	rand.Seed(time.Now().UTC().UnixNano())

	if rand.Int31n(2) == 0 {
		req, _ = http.NewRequest("GET", "http://localhost:"+strconv.Itoa(port)+"/test", nil)
	} else {
		buf := bytes.NewReader([]byte("a=b&c=d"))
		req, _ = http.NewRequest("POST", "http://localhost:"+strconv.Itoa(port)+"/test", buf)
	}

	req.Header.Add("Referer", "http://localhost/test")
	req.Header.Add("Accept", "*/*")
	req.Header.Add("Accept-Language", "en-GB,*")
	req.Header.Add("X-Forwarded-For", "1.1.1.1, 2.2.2.2, 3.3.3.3")
	req.Header.Add("X-Forwarded-Proto", "http")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.1 Safari/534.34")

	ck1 := new(http.Cookie)
	ck1.Name = "test"
	ck1.Value = "value"

	req.AddCookie(ck1)

	return req
}

func TestReplay(t *testing.T) {
	var request *http.Request
	received := make(chan int)

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}

	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		isEqual(t, r.URL.Path, request.URL.Path)

		if len(r.Cookies()) > 0 {
			isEqual(t, r.Cookies()[0].Value, request.Cookies()[0].Value)
		} else {
			t.Error("Cookies should not be blank")
		}

		http.Error(w, "OK", http.StatusAccepted)

		if t.Failed() {
			fmt.Println("\nReplayed:", r)
		}

		received <- 1
	}

	env := &Env{
		Verbose:       true,
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
	}
	p := env.start()

	request = getRequest(p)

	_, err := http.DefaultClient.Do(request)

	if err != nil {
		t.Error("Can't make request", err)
	}

	select {
	case <-received:
	case <-time.After(time.Second):
		t.Error("Timeout error")
	}
}

func rateLimitEnv(replayLimit int, listenerLimit int, connCount int, t *testing.T) int32 {
	var processed int32

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}

	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		atomic.AddInt32(&processed, 1)
		http.Error(w, "OK", http.StatusAccepted)
	}

	env := &Env{
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
		ReplayLimit:   replayLimit,
		ListenerLimit: listenerLimit,
		Verbose:       true,
	}

	p := env.start()

	for i := 0; i < connCount; i++ {
		req := getRequest(p)

		go func() {
			resp, err := http.DefaultClient.Do(req)
			if err == nil {
				resp.Body.Close()
			} else {
				t.Errorf("", err)
			}
		}()
	}

	time.Sleep(time.Millisecond * 500)

	return processed
}

func TestWithoutReplayRateLimit(t *testing.T) {
	processed := rateLimitEnv(0, 0, 10, t)

	if processed != 10 {
		t.Error("It should forward all requests without rate-limiting, got:", processed)
	}
}

func TestReplayRateLimit(t *testing.T) {
	processed := rateLimitEnv(5, 0, 10, t)

	if processed != 5 {
		t.Error("It should forward only 5 requests with rate-limiting, got:", processed)
	}
}

func TestListenerRateLimit(t *testing.T) {
	processed := rateLimitEnv(0, 3, 100, t)

	if processed != 3 {
		t.Error("It should forward only 3 requests with rate-limiting, got:", processed)
	}
}

func (e *Env) startFileListener() (p int) {
	p = 50000 + envs*10

	e.ForwardPort = p + 2
	go e.startHTTP(p, http.HandlerFunc(e.ListenHandler))
	go e.startHTTP(p+2, http.HandlerFunc(e.ReplayHandler))
	go e.startFileUsingListener(p, p+1)

	// Time to start http and gor instances
	time.Sleep(time.Millisecond * 100)

	envs++

	return
}

func (e *Env) startFileUsingListener(port int, replayPort int) {
	listener.Settings.Verbose = e.Verbose
	listener.Settings.Address = "127.0.0.1"
	listener.Settings.FileToReplayPath = "integration_request.gor"
	listener.Settings.Port = port

	if e.ListenerLimit != 0 {
		listener.Settings.ReplayAddress += "|" + strconv.Itoa(e.ListenerLimit)
	}

	listener.Run()
}

func (e *Env) startFileUsingReplay() {
	replay.Settings.Verbose = e.Verbose
	replay.Settings.FileToReplayPath = "integration_request.gor"
	replay.Settings.ForwardAddress = "127.0.0.1:" + strconv.Itoa(e.ForwardPort)

	if e.ReplayLimit != 0 {
		replay.Settings.ForwardAddress += "|" + strconv.Itoa(e.ReplayLimit)
	}

	replay.Run()
}

func TestSavingRequestToFileAndReplayThem(t *testing.T) {
	processed := make(chan int)

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusNotFound)
	}

	requestsCount := 0
	var replayedRequests []*http.Request
	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		requestsCount++

		isEqual(t, r.URL.Path, "/test")
		isEqual(t, r.Cookies()[0].Value, "value")

		http.Error(w, "404 page not found", http.StatusNotFound)

		replayedRequests = append(replayedRequests, r)
		if t.Failed() {
			fmt.Println("\nReplayed:", r)
		}

		if requestsCount > 1 {
			processed <- 1
		}
	}

	env := &Env{
		Verbose:       true,
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
	}

	p := env.startFileListener()

	for i := 0; i < 30; i++ {
		request := getRequest(p)

		go func() {
			_, err := http.DefaultClient.Do(request)

			if err != nil {
				t.Error("Can't make request", err)
			}
		}()
	}

	// TODO: wait until gor will process response, should be kind of flag/semaphore
	time.Sleep(time.Millisecond * 700)
	go env.startFileUsingReplay()

	select {
	case <-processed:
	case <-time.After(2 * time.Second):
		for _, value := range replayedRequests {
			fmt.Println(value)
		}
		t.Error("Timeout error")
	}
}
<commit_msg>Integration test for header injection<commit_after>package main

import (
	"bytes"
	"fmt"
	"net/http"
	"strconv"
	"sync/atomic"
	"testing"
	"time"

	"github.com/buger/gor/listener"
	"github.com/buger/gor/replay"

	"math/rand"
)

func isEqual(t *testing.T, a interface{}, b interface{}) {
	if a != b {
		t.Error("Original and Replayed request not match\n", a, "!=", b)
	}
}

var envs int

type Env struct {
	Verbose bool

	ListenHandler http.HandlerFunc
	ReplayHandler http.HandlerFunc

	ReplayLimit   int
	ListenerLimit int
	ForwardPort   int

	AdditionalHeaders replay.Headers
}

func (e *Env) start() (p int) {
	p = 50000 + envs*10

	go e.startHTTP(p, http.HandlerFunc(e.ListenHandler))
	go e.startHTTP(p+2, http.HandlerFunc(e.ReplayHandler))

	go e.startHTTP(p+3, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}))

	go e.startListener(p, p+1)
	go e.startReplay(p+1, p+2)

	// Time to start http and gor instances
	time.Sleep(time.Millisecond * 100)

	envs++

	return
}

func (e *Env) startListener(port int, replayPort int) {
	listener.Settings.Verbose = e.Verbose
	listener.Settings.Address = "127.0.0.1"
	listener.Settings.ReplayAddress = "127.0.0.1:" + strconv.Itoa(replayPort)
	listener.Settings.Port = port

	if e.ListenerLimit != 0 {
		listener.Settings.ReplayLimit = e.ListenerLimit
	}

	listener.Run()
}

func (e *Env) startReplay(port int, forwardPort int) {
	replay.Settings.Verbose = e.Verbose
	replay.Settings.Host = "127.0.0.1"
	replay.Settings.Address = "127.0.0.1:" + strconv.Itoa(port)
	replay.Settings.ForwardAddress = "127.0.0.1:" + strconv.Itoa(forwardPort)
	replay.Settings.Port = port

	if e.ReplayLimit != 0 {
		replay.Settings.ForwardAddress += "|" + strconv.Itoa(e.ReplayLimit)
	}

	if len(e.AdditionalHeaders) > 0 {
		replay.Settings.AdditionalHeaders = e.AdditionalHeaders
	}

	replay.Settings.ForwardAddress += ",127.0.0.1:" + strconv.Itoa(forwardPort+1)

	replay.Run()
}

func (e *Env) startHTTP(port int, handler http.Handler) {
	err := http.ListenAndServe(":"+strconv.Itoa(port), handler)

	if err != nil {
		fmt.Println("Error while starting http server:", err)
	}
}

func getRequest(port int) *http.Request {
	var req *http.Request

	rand.Seed(time.Now().UTC().UnixNano())

	if rand.Int31n(2) == 0 {
		req, _ = http.NewRequest("GET", "http://localhost:"+strconv.Itoa(port)+"/test", nil)
	} else {
		buf := bytes.NewReader([]byte("a=b&c=d"))
		req, _ = http.NewRequest("POST", "http://localhost:"+strconv.Itoa(port)+"/test", buf)
	}

	req.Header.Add("Referer", "http://localhost/test")
	req.Header.Add("Accept", "*/*")
	req.Header.Add("Accept-Language", "en-GB,*")
	req.Header.Add("X-Forwarded-For", "1.1.1.1, 2.2.2.2, 3.3.3.3")
	req.Header.Add("X-Forwarded-Proto", "http")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.1 Safari/534.34")

	ck1 := new(http.Cookie)
	ck1.Name = "test"
	ck1.Value = "value"

	req.AddCookie(ck1)

	return req
}

func TestReplay(t *testing.T) {
	var request *http.Request
	received := make(chan int)

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}

	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		isEqual(t, r.URL.Path, request.URL.Path)

		isEqual(t, r.Header.Get("New-Header"), "Inserted")
		isEqual(t, r.Header.Get("X-Forwarded-Proto"), "Overwritten")

		if len(r.Cookies()) > 0 {
			isEqual(t, r.Cookies()[0].Value, request.Cookies()[0].Value)
		} else {
			t.Error("Cookies should not be blank")
		}

		http.Error(w, "OK", http.StatusAccepted)

		if t.Failed() {
			fmt.Println("\nReplayed:", r)
		}

		received <- 1
	}

	env := &Env{
		Verbose:       true,
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
		AdditionalHeaders: replay.Headers{
			{"New-Header", "Inserted"},
			{"X-Forwarded-Proto", "Overwritten"},
		},
	}
	p := env.start()

	request = getRequest(p)

	_, err := http.DefaultClient.Do(request)

	if err != nil {
		t.Error("Can't make request", err)
	}

	select {
	case <-received:
	case <-time.After(time.Second):
		t.Error("Timeout error")
	}
}

func rateLimitEnv(replayLimit int, listenerLimit int, connCount int, t *testing.T) int32 {
	var processed int32

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusAccepted)
	}

	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		atomic.AddInt32(&processed, 1)
		http.Error(w, "OK", http.StatusAccepted)
	}

	env := &Env{
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
		ReplayLimit:   replayLimit,
		ListenerLimit: listenerLimit,
		Verbose:       true,
	}

	p := env.start()

	for i := 0; i < connCount; i++ {
		req := getRequest(p)

		go func() {
			resp, err := http.DefaultClient.Do(req)
			if err == nil {
				resp.Body.Close()
			} else {
				t.Errorf("", err)
			}
		}()
	}

	time.Sleep(time.Millisecond * 500)

	return processed
}

func TestWithoutReplayRateLimit(t *testing.T) {
	processed := rateLimitEnv(0, 0, 10, t)

	if processed != 10 {
		t.Error("It should forward all requests without rate-limiting, got:", processed)
	}
}

func TestReplayRateLimit(t *testing.T) {
	processed := rateLimitEnv(5, 0, 10, t)

	if processed != 5 {
		t.Error("It should forward only 5 requests with rate-limiting, got:", processed)
	}
}

func TestListenerRateLimit(t *testing.T) {
	processed := rateLimitEnv(0, 3, 100, t)

	if processed != 3 {
		t.Error("It should forward only 3 requests with rate-limiting, got:", processed)
	}
}

func (e *Env) startFileListener() (p int) {
	p = 50000 + envs*10

	e.ForwardPort = p + 2
	go e.startHTTP(p, http.HandlerFunc(e.ListenHandler))
	go e.startHTTP(p+2, http.HandlerFunc(e.ReplayHandler))
	go e.startFileUsingListener(p, p+1)

	// Time to start http and gor instances
	time.Sleep(time.Millisecond * 100)

	envs++

	return
}

func (e *Env) startFileUsingListener(port int, replayPort int) {
	listener.Settings.Verbose = e.Verbose
	listener.Settings.Address = "127.0.0.1"
	listener.Settings.FileToReplayPath = "integration_request.gor"
	listener.Settings.Port = port

	if e.ListenerLimit != 0 {
		listener.Settings.ReplayAddress += "|" + strconv.Itoa(e.ListenerLimit)
	}

	listener.Run()
}

func (e *Env) startFileUsingReplay() {
	replay.Settings.Verbose = e.Verbose
	replay.Settings.FileToReplayPath = "integration_request.gor"
	replay.Settings.ForwardAddress = "127.0.0.1:" + strconv.Itoa(e.ForwardPort)

	if e.ReplayLimit != 0 {
		replay.Settings.ForwardAddress += "|" + strconv.Itoa(e.ReplayLimit)
	}

	replay.Run()
}

func TestSavingRequestToFileAndReplayThem(t *testing.T) {
	processed := make(chan int)

	listenHandler := func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "OK", http.StatusNotFound)
	}

	requestsCount := 0
	var replayedRequests []*http.Request
	replayHandler := func(w http.ResponseWriter, r *http.Request) {
		requestsCount++

		isEqual(t, r.URL.Path, "/test")
		isEqual(t, r.Cookies()[0].Value, "value")

		http.Error(w, "404 page not found", http.StatusNotFound)

		replayedRequests = append(replayedRequests, r)
		if t.Failed() {
			fmt.Println("\nReplayed:", r)
		}

		if requestsCount > 1 {
			processed <- 1
		}
	}

	env := &Env{
		Verbose:       true,
		ListenHandler: listenHandler,
		ReplayHandler: replayHandler,
	}

	p := env.startFileListener()

	for i := 0; i < 30; i++ {
		request := getRequest(p)

		go func() {
			_, err := http.DefaultClient.Do(request)

			if err != nil {
				t.Error("Can't make request", err)
			}
		}()
	}

	// TODO: wait until gor will process response, should be kind of flag/semaphore
	time.Sleep(time.Millisecond * 700)
	go env.startFileUsingReplay()

	select {
	case <-processed:
	case <-time.After(2 * time.Second):
		for _, value := range replayedRequests {
			fmt.Println(value)
		}
		t.Error("Timeout error")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/spf13/cobra"

	"github.com/lxc/lxd/lxc/utils"
	"github.com/lxc/lxd/shared/api"
	cli "github.com/lxc/lxd/shared/cmd"
	"github.com/lxc/lxd/shared/i18n"
)

type cmdLaunch struct {
	global *cmdGlobal
	init   *cmdInit
}

func (c *cmdLaunch) Command() *cobra.Command {
	cmd := c.init.Command()
	cmd.Use = i18n.G("launch [<remote>:]<image> [<remote>:][<name>]")
	cmd.Short = i18n.G("Create and start instances from images")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Create and start instances from images`))
	cmd.Example = cli.FormatSection("", i18n.G(
		`lxc launch ubuntu:18.04 u1

lxc launch ubuntu:18.04 u1 < config.yaml
    Create and start the instance with configuration from config.yaml`))
	cmd.Hidden = false

	cmd.RunE = c.Run

	return cmd
}

func (c *cmdLaunch) Run(cmd *cobra.Command, args []string) error {
	conf := c.global.conf

	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 2)
	if exit {
		return err
	}

	// Call the matching code from init
	d, name, err := c.init.create(conf, args)
	if err != nil {
		return err
	}

	// Get the remote
	var remote string
	if len(args) == 2 {
		remote, _, err = conf.ParseRemote(args[1])
		if err != nil {
			return err
		}
	} else {
		remote, _, err = conf.ParseRemote("")
		if err != nil {
			return err
		}
	}

	// Start the instance
	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Starting %s")+"\n", name)
	}

	req := api.InstanceStatePut{
		Action:  "start",
		Timeout: -1,
	}

	op, err := d.UpdateInstanceState(name, req, "")
	if err != nil {
		return err
	}

	progress := utils.ProgressRenderer{
		Quiet: c.global.flagQuiet,
	}
	_, err = op.AddHandler(progress.UpdateOp)
	if err != nil {
		progress.Done("")
		return err
	}

	// Wait for operation to finish
	err = utils.CancelableWait(op, &progress)
	if err != nil {
		progress.Done("")
		prettyName := name
		if remote != "" {
			prettyName = fmt.Sprintf("%s:%s", remote, name)
		}

		return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, prettyName)
	}

	progress.Done("")
	return nil
}
<commit_msg>lxc/launch: Add --console<commit_after>package main

import (
	"fmt"

	"github.com/spf13/cobra"

	"github.com/lxc/lxd/lxc/utils"
	"github.com/lxc/lxd/shared/api"
	cli "github.com/lxc/lxd/shared/cmd"
	"github.com/lxc/lxd/shared/i18n"
)

type cmdLaunch struct {
	global *cmdGlobal
	init   *cmdInit

	flagConsole bool
}

func (c *cmdLaunch) Command() *cobra.Command {
	cmd := c.init.Command()
	cmd.Use = i18n.G("launch [<remote>:]<image> [<remote>:][<name>]")
	cmd.Short = i18n.G("Create and start instances from images")
	cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
		`Create and start instances from images`))
	cmd.Example = cli.FormatSection("", i18n.G(
		`lxc launch ubuntu:18.04 u1

lxc launch ubuntu:18.04 u1 < config.yaml
    Create and start the instance with configuration from config.yaml`))
	cmd.Hidden = false

	cmd.RunE = c.Run

	cmd.Flags().BoolVar(&c.flagConsole, "console", false, i18n.G("Immediately attach to the console"))

	return cmd
}

func (c *cmdLaunch) Run(cmd *cobra.Command, args []string) error {
	conf := c.global.conf

	// Sanity checks
	exit, err := c.global.CheckArgs(cmd, args, 1, 2)
	if exit {
		return err
	}

	// Call the matching code from init
	d, name, err := c.init.create(conf, args)
	if err != nil {
		return err
	}

	// Get the remote
	var remote string
	if len(args) == 2 {
		remote, _, err = conf.ParseRemote(args[1])
		if err != nil {
			return err
		}
	} else {
		remote, _, err = conf.ParseRemote("")
		if err != nil {
			return err
		}
	}

	// Start the instance
	if !c.global.flagQuiet {
		fmt.Printf(i18n.G("Starting %s")+"\n", name)
	}

	req := api.InstanceStatePut{
		Action:  "start",
		Timeout: -1,
	}

	op, err := d.UpdateInstanceState(name, req, "")
	if err != nil {
		return err
	}

	progress := utils.ProgressRenderer{
		Quiet: c.global.flagQuiet,
	}
	_, err = op.AddHandler(progress.UpdateOp)
	if err != nil {
		progress.Done("")
		return err
	}

	// Wait for operation to finish
	err = utils.CancelableWait(op, &progress)
	if err != nil {
		progress.Done("")
		prettyName := name
		if remote != "" {
			prettyName = fmt.Sprintf("%s:%s", remote, name)
		}

		return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, prettyName)
	}
	progress.Done("")

	// Handle console attach
	if c.flagConsole {
		console := cmdConsole{}
		console.global = c.global
		return console.Console(d, name)
	}

	return nil
}
<|endoftext|>