<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"encoding"

	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-codec/codec"
	"github.com/keybase/kbfs/kbfscrypto"
	"github.com/keybase/kbfs/kbfshash"
)

// TLFReaderKeyBundleV3 is an alias to a TLFReaderKeyBundleV2 for clarity.
type TLFReaderKeyBundleV3 struct {
	TLFReaderKeyBundleV2
}

// TLFWriterKeyBundleV3 is a bundle of writer keys and historic symmetric encryption
// keys for a top-level folder.
type TLFWriterKeyBundleV3 struct {
	// Maps from each user to their crypt key bundle for the current generation.
	Keys UserDeviceKeyInfoMap

	// M_e as described in 4.1.1 of https://keybase.io/blog/kbfs-crypto.
	// Because devices can be added into the key generation after it
	// is initially created (so those devices can get access to
	// existing data), we track multiple ephemeral public keys; the
	// one used by a particular device is specified by EPubKeyIndex in
	// its TLFCryptoKeyInfo struct.
	TLFEphemeralPublicKeys kbfscrypto.TLFEphemeralPublicKeys `codec:"ePubKey"`

	// M_f as described in 4.1.1 of https://keybase.io/blog/kbfs-crypto.
	TLFPublicKeys []kbfscrypto.TLFPublicKey `codec:"pubKey"`

	// This is a time-ordered encrypted list of historic key generations.
	// It is encrypted with the latest generation of the TLF crypt key.
	EncryptedHistoricTLFCryptKeys EncryptedTLFCryptKeys `codec:"oldKeys"`

	codec.UnknownFieldSetHandler
}

// IsWriter returns true if the given user device is in the device set.
func (wkb TLFWriterKeyBundleV3) IsWriter(user keybase1.UID, deviceKID keybase1.KID) bool {
	_, ok := wkb.Keys[user][deviceKID]
	return ok
}

// TLFReaderKeyBundleID is the hash of a serialized TLFReaderKeyBundle.
type TLFReaderKeyBundleID struct {
	h kbfshash.Hash
}

var _ encoding.BinaryMarshaler = TLFReaderKeyBundleID{}
var _ encoding.BinaryUnmarshaler = (*TLFReaderKeyBundleID)(nil)

// TLFReaderKeyBundleIDFromBytes creates a new TLFReaderKeyBundleID from the given bytes.
// If the returned error is nil, the returned TLFReaderKeyBundleID is valid.
func TLFReaderKeyBundleIDFromBytes(data []byte) (TLFReaderKeyBundleID, error) {
	h, err := kbfshash.HashFromBytes(data)
	if err != nil {
		return TLFReaderKeyBundleID{}, err
	}
	return TLFReaderKeyBundleID{h}, nil
}

// Bytes returns the bytes of the TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) Bytes() []byte {
	return h.h.Bytes()
}

// String returns the string form of the TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) String() string {
	return h.h.String()
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for
// TLFReaderKeyBundleID. Returns an error if the TLFReaderKeyBundleID is invalid and not the
// zero TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) MarshalBinary() (data []byte, err error) {
	return h.h.MarshalBinary()
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for TLFReaderKeyBundleID. Returns an error if the given byte array is non-empty and
// the TLFReaderKeyBundleID is invalid.
func (h *TLFReaderKeyBundleID) UnmarshalBinary(data []byte) error {
	return h.h.UnmarshalBinary(data)
}

// TLFWriterKeyBundleID is the hash of a serialized TLFWriterKeyBundle.
type TLFWriterKeyBundleID struct {
	h kbfshash.Hash
}

var _ encoding.BinaryMarshaler = TLFWriterKeyBundleID{}
var _ encoding.BinaryUnmarshaler = (*TLFWriterKeyBundleID)(nil)

// TLFWriterKeyBundleIDFromBytes creates a new TLFWriterKeyBundleID from the given bytes.
// If the returned error is nil, the returned TLFWriterKeyBundleID is valid.
func TLFWriterKeyBundleIDFromBytes(data []byte) (TLFWriterKeyBundleID, error) {
	h, err := kbfshash.HashFromBytes(data)
	if err != nil {
		return TLFWriterKeyBundleID{}, err
	}
	return TLFWriterKeyBundleID{h}, nil
}

// Bytes returns the bytes of the TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) Bytes() []byte {
	return h.h.Bytes()
}

// String returns the string form of the TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) String() string {
	return h.h.String()
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for
// TLFWriterKeyBundleID. Returns an error if the TLFWriterKeyBundleID is invalid and not the
// zero TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) MarshalBinary() (data []byte, err error) {
	return h.h.MarshalBinary()
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for TLFWriterKeyBundleID. Returns an error if the given byte array is non-empty and
// the TLFWriterKeyBundleID is invalid.
func (h *TLFWriterKeyBundleID) UnmarshalBinary(data []byte) error {
	return h.h.UnmarshalBinary(data)
}
<commit_msg>libkbfs: add TLF{Reader,Writer}KeyBundleIDFromString<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"encoding"

	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-codec/codec"
	"github.com/keybase/kbfs/kbfscrypto"
	"github.com/keybase/kbfs/kbfshash"
)

// TLFReaderKeyBundleV3 is an alias to a TLFReaderKeyBundleV2 for clarity.
type TLFReaderKeyBundleV3 struct {
	TLFReaderKeyBundleV2
}

// TLFWriterKeyBundleV3 is a bundle of writer keys and historic symmetric encryption
// keys for a top-level folder.
type TLFWriterKeyBundleV3 struct {
	// Maps from each user to their crypt key bundle for the current generation.
	Keys UserDeviceKeyInfoMap

	// M_e as described in 4.1.1 of https://keybase.io/blog/kbfs-crypto.
	// Because devices can be added into the key generation after it
	// is initially created (so those devices can get access to
	// existing data), we track multiple ephemeral public keys; the
	// one used by a particular device is specified by EPubKeyIndex in
	// its TLFCryptoKeyInfo struct.
	TLFEphemeralPublicKeys kbfscrypto.TLFEphemeralPublicKeys `codec:"ePubKey"`

	// M_f as described in 4.1.1 of https://keybase.io/blog/kbfs-crypto.
	TLFPublicKeys []kbfscrypto.TLFPublicKey `codec:"pubKey"`

	// This is a time-ordered encrypted list of historic key generations.
	// It is encrypted with the latest generation of the TLF crypt key.
	EncryptedHistoricTLFCryptKeys EncryptedTLFCryptKeys `codec:"oldKeys"`

	codec.UnknownFieldSetHandler
}

// IsWriter returns true if the given user device is in the device set.
func (wkb TLFWriterKeyBundleV3) IsWriter(user keybase1.UID, deviceKID keybase1.KID) bool {
	_, ok := wkb.Keys[user][deviceKID]
	return ok
}

// TLFReaderKeyBundleID is the hash of a serialized TLFReaderKeyBundle.
type TLFReaderKeyBundleID struct {
	h kbfshash.Hash
}

var _ encoding.BinaryMarshaler = TLFReaderKeyBundleID{}
var _ encoding.BinaryUnmarshaler = (*TLFReaderKeyBundleID)(nil)

// TLFReaderKeyBundleIDFromBytes creates a new TLFReaderKeyBundleID from the given bytes.
// If the returned error is nil, the returned TLFReaderKeyBundleID is valid.
func TLFReaderKeyBundleIDFromBytes(data []byte) (TLFReaderKeyBundleID, error) {
	h, err := kbfshash.HashFromBytes(data)
	if err != nil {
		return TLFReaderKeyBundleID{}, err
	}
	return TLFReaderKeyBundleID{h}, nil
}

// TLFReaderKeyBundleIDFromString creates a new TLFReaderKeyBundleID from the given string.
// If the returned error is nil, the returned TLFReaderKeyBundleID is valid.
func TLFReaderKeyBundleIDFromString(id string) (TLFReaderKeyBundleID, error) {
	h, err := kbfshash.HashFromString(id)
	if err != nil {
		return TLFReaderKeyBundleID{}, err
	}
	return TLFReaderKeyBundleID{h}, nil
}

// Bytes returns the bytes of the TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) Bytes() []byte {
	return h.h.Bytes()
}

// String returns the string form of the TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) String() string {
	return h.h.String()
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for
// TLFReaderKeyBundleID. Returns an error if the TLFReaderKeyBundleID is invalid and not the
// zero TLFReaderKeyBundleID.
func (h TLFReaderKeyBundleID) MarshalBinary() (data []byte, err error) {
	return h.h.MarshalBinary()
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for TLFReaderKeyBundleID. Returns an error if the given byte array is non-empty and
// the TLFReaderKeyBundleID is invalid.
func (h *TLFReaderKeyBundleID) UnmarshalBinary(data []byte) error {
	return h.h.UnmarshalBinary(data)
}

// TLFWriterKeyBundleID is the hash of a serialized TLFWriterKeyBundle.
type TLFWriterKeyBundleID struct {
	h kbfshash.Hash
}

var _ encoding.BinaryMarshaler = TLFWriterKeyBundleID{}
var _ encoding.BinaryUnmarshaler = (*TLFWriterKeyBundleID)(nil)

// TLFWriterKeyBundleIDFromBytes creates a new TLFWriterKeyBundleID from the given bytes.
// If the returned error is nil, the returned TLFWriterKeyBundleID is valid.
func TLFWriterKeyBundleIDFromBytes(data []byte) (TLFWriterKeyBundleID, error) {
	h, err := kbfshash.HashFromBytes(data)
	if err != nil {
		return TLFWriterKeyBundleID{}, err
	}
	return TLFWriterKeyBundleID{h}, nil
}

// TLFWriterKeyBundleIDFromString creates a new TLFWriterKeyBundleID from the given string.
// If the returned error is nil, the returned TLFWriterKeyBundleID is valid.
func TLFWriterKeyBundleIDFromString(id string) (TLFWriterKeyBundleID, error) {
	h, err := kbfshash.HashFromString(id)
	if err != nil {
		return TLFWriterKeyBundleID{}, err
	}
	return TLFWriterKeyBundleID{h}, nil
}

// Bytes returns the bytes of the TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) Bytes() []byte {
	return h.h.Bytes()
}

// String returns the string form of the TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) String() string {
	return h.h.String()
}

// MarshalBinary implements the encoding.BinaryMarshaler interface for
// TLFWriterKeyBundleID. Returns an error if the TLFWriterKeyBundleID is invalid and not the
// zero TLFWriterKeyBundleID.
func (h TLFWriterKeyBundleID) MarshalBinary() (data []byte, err error) {
	return h.h.MarshalBinary()
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
// for TLFWriterKeyBundleID. Returns an error if the given byte array is non-empty and
// the TLFWriterKeyBundleID is invalid.
func (h *TLFWriterKeyBundleID) UnmarshalBinary(data []byte) error {
	return h.h.UnmarshalBinary(data)
}
<|endoftext|>


<commit_before><commit_msg>actually create an identifierList<commit_after><|endoftext|>


<commit_before><commit_msg>Add V3Organization payloads<commit_after><|endoftext|>


<commit_before>// Copyright 2014 tsuru 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 testing

import (
	"github.com/tsuru/tsuru/queue"
	"launchpad.net/gocheck"
)

func (s *S) TestFakeQPutAndGet(c *gocheck.C) {
	q := FakeQ{}
	msg := queue.Message{Action: "do-something"}
	err := q.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	m, err := q.Get(1e6)
	c.Assert(err, gocheck.IsNil)
	c.Assert(m.Action, gocheck.Equals, msg.Action)
}

func (s *S) TestFakeQPutAndGetMultipleMessages(c *gocheck.C) {
	q := FakeQ{}
	messages := []queue.Message{
		{Action: "do-something"},
		{Action: "do-otherthing"},
		{Action: "do-all-things"},
		{Action: "do-anything"},
	}
	for _, m := range messages {
		copy := m
		q.Put(&copy, 0)
	}
	got := make([]queue.Message, len(messages))
	for i := range got {
		msg, err := q.Get(1e6)
		c.Check(err, gocheck.IsNil)
		got[i] = *msg
	}
	c.Assert(got, gocheck.DeepEquals, messages)
}

func (s *S) TestFakeQGetTimeout(c *gocheck.C) {
	q := FakeQ{}
	m, err := q.Get(1e6)
	c.Assert(m, gocheck.IsNil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "Timed out.")
}

func (s *S) TestFakeQPutWithTimeout(c *gocheck.C) {
	q := FakeQ{}
	msg := queue.Message{Action: "do-something"}
	err := q.Put(&msg, 1e6)
	c.Assert(err, gocheck.IsNil)
	_, err = q.Get(1e3)
	c.Assert(err, gocheck.NotNil)
	_, err = q.Get(1e9)
	c.Assert(err, gocheck.IsNil)
}

func (s *S) TestFakeHandlerStart(c *gocheck.C) {
	h := fakeHandler{}
	c.Assert(h.running, gocheck.Equals, int32(0))
	h.Start()
	c.Assert(h.running, gocheck.Equals, int32(1))
}

func (s *S) TestFakeHandlerStop(c *gocheck.C) {
	h := fakeHandler{}
	h.Start()
	h.Stop()
	c.Assert(h.running, gocheck.Equals, int32(0))
}

func (s *S) TestFakeQFactoryGet(c *gocheck.C) {
	f := NewFakeQFactory()
	q, err := f.Get("default")
	c.Assert(err, gocheck.IsNil)
	_, ok := q.(*FakeQ)
	c.Assert(ok, gocheck.Equals, true)
	q2, err := f.Get("default")
	c.Assert(err, gocheck.IsNil)
	c.Assert(q, gocheck.Equals, q2)
	q3, err := f.Get("non-default")
	c.Assert(err, gocheck.IsNil)
	c.Assert(q, gocheck.Not(gocheck.Equals), q3)
}

func (s *S) TestFakeQFactoryHandler(c *gocheck.C) {
	f := NewFakeQFactory()
	h, err := f.Handler(nil)
	c.Assert(err, gocheck.IsNil)
	_, ok := h.(*fakeHandler)
	c.Assert(ok, gocheck.Equals, true)
}

func (s *S) TestCleanQ(c *gocheck.C) {
	msg := queue.Message{Action: "do-something", Args: []string{"wat"}}
	q, err := factory.Get("firedance")
	c.Assert(err, gocheck.IsNil)
	err = q.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	q2, err := factory.Get("hush")
	c.Assert(err, gocheck.IsNil)
	err = q2.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	q3, err := factory.Get("rocket")
	c.Assert(err, gocheck.IsNil)
	err = q3.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	CleanQ("firedance", "hush")
	_, err = q.Get(1e6)
	c.Assert(err, gocheck.NotNil)
	_, err = q2.Get(1e6)
	c.Assert(err, gocheck.NotNil)
	_, err = q3.Get(1e6)
	c.Assert(err, gocheck.IsNil)
}
<commit_msg>testing: testing the testing code for queues<commit_after>// Copyright 2014 tsuru 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 testing

import (
	"github.com/tsuru/tsuru/queue"
	"launchpad.net/gocheck"
	"time"
)

func (s *S) TestFakeQPutAndGet(c *gocheck.C) {
	q := FakeQ{}
	msg := queue.Message{Action: "do-something"}
	err := q.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	m, err := q.Get(1e6)
	c.Assert(err, gocheck.IsNil)
	c.Assert(m.Action, gocheck.Equals, msg.Action)
}

func (s *S) TestFakeQPutAndGetMultipleMessages(c *gocheck.C) {
	q := FakeQ{}
	messages := []queue.Message{
		{Action: "do-something"},
		{Action: "do-otherthing"},
		{Action: "do-all-things"},
		{Action: "do-anything"},
	}
	for _, m := range messages {
		copy := m
		q.Put(&copy, 0)
	}
	got := make([]queue.Message, len(messages))
	for i := range got {
		msg, err := q.Get(1e6)
		c.Check(err, gocheck.IsNil)
		got[i] = *msg
	}
	c.Assert(got, gocheck.DeepEquals, messages)
}

func (s *S) TestFakeQGetTimeout(c *gocheck.C) {
	q := FakeQ{}
	m, err := q.Get(1e6)
	c.Assert(m, gocheck.IsNil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "Timed out.")
}

func (s *S) TestFakeQPutWithTimeout(c *gocheck.C) {
	q := FakeQ{}
	msg := queue.Message{Action: "do-something"}
	err := q.Put(&msg, 1e6)
	c.Assert(err, gocheck.IsNil)
	_, err = q.Get(1e3)
	c.Assert(err, gocheck.NotNil)
	_, err = q.Get(1e9)
	c.Assert(err, gocheck.IsNil)
}

func (s *S) TestFakeQPubSub(c *gocheck.C) {
	q := FakePubSubQ{}
	msgChan, err := q.Sub()
	c.Assert(err, gocheck.IsNil)
	err = q.Pub([]byte("muad'dib"))
	c.Assert(err, gocheck.IsNil)
	c.Assert(<-msgChan, gocheck.DeepEquals, []byte("muad'dib"))
}

func (s *S) TestFakeQPubSubUnSub(c *gocheck.C) {
	q := FakePubSubQ{}
	msgChan, err := q.Sub()
	c.Assert(err, gocheck.IsNil)
	err = q.Pub([]byte("arrakis"))
	c.Assert(err, gocheck.IsNil)
	done := make(chan bool)
	go func() {
		time.Sleep(5e8)
		q.UnSub()
	}()
	go func() {
		msgs := make([][]byte, 0)
		for msg := range msgChan {
			msgs = append(msgs, msg)
		}
		c.Assert(msgs, gocheck.DeepEquals, [][]byte{[]byte("arrakis")})
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(1e9):
		c.Error("Timeout waiting for message.")
	}
}

func (s *S) TestFakeHandlerStart(c *gocheck.C) {
	h := fakeHandler{}
	c.Assert(h.running, gocheck.Equals, int32(0))
	h.Start()
	c.Assert(h.running, gocheck.Equals, int32(1))
}

func (s *S) TestFakeHandlerStop(c *gocheck.C) {
	h := fakeHandler{}
	h.Start()
	h.Stop()
	c.Assert(h.running, gocheck.Equals, int32(0))
}

func (s *S) TestFakeQFactoryGet(c *gocheck.C) {
	f := NewFakeQFactory()
	q, err := f.Get("default")
	c.Assert(err, gocheck.IsNil)
	_, ok := q.(*FakeQ)
	c.Assert(ok, gocheck.Equals, true)
	q2, err := f.Get("default")
	c.Assert(err, gocheck.IsNil)
	c.Assert(q, gocheck.Equals, q2)
	q3, err := f.Get("non-default")
	c.Assert(err, gocheck.IsNil)
	c.Assert(q, gocheck.Not(gocheck.Equals), q3)
}

func (s *S) TestFakeQFactoryHandler(c *gocheck.C) {
	f := NewFakeQFactory()
	h, err := f.Handler(nil)
	c.Assert(err, gocheck.IsNil)
	_, ok := h.(*fakeHandler)
	c.Assert(ok, gocheck.Equals, true)
}

func (s *S) TestCleanQ(c *gocheck.C) {
	msg := queue.Message{Action: "do-something", Args: []string{"wat"}}
	q, err := factory.Get("firedance")
	c.Assert(err, gocheck.IsNil)
	err = q.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	q2, err := factory.Get("hush")
	c.Assert(err, gocheck.IsNil)
	err = q2.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	q3, err := factory.Get("rocket")
	c.Assert(err, gocheck.IsNil)
	err = q3.Put(&msg, 0)
	c.Assert(err, gocheck.IsNil)
	CleanQ("firedance", "hush")
	_, err = q.Get(1e6)
	c.Assert(err, gocheck.NotNil)
	_, err = q2.Get(1e6)
	c.Assert(err, gocheck.NotNil)
	_, err = q3.Get(1e6)
	c.Assert(err, gocheck.IsNil)
}
<|endoftext|>


<commit_before>package request

import (
    "testing"
    . "github.com/onsi/gomega"
    . "github.com/franela/goblin"
    "net/http/httptest"
    "net/http"
    "fmt"
    "io/ioutil"
    "strings"
)

func TestRequest(t *testing.T) {
    g := Goblin(t)

    RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

    g.Describe("Request", func() {

        g.Describe("General request methods", func() {
            var ts *httptest.Server

            g.Before(func() {
                ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                    if r.Method == "GET" && r.URL.Path == "/foo" {
                        w.WriteHeader(200)
                        fmt.Fprint(w, "bar")
                    }
                    if r.Method == "POST" && r.URL.Path == "/" {
                        body, _ := ioutil.ReadAll(r.Body)
                        w.Header().Add("Location", ts.URL + "/123")
                        w.WriteHeader(201)
                        fmt.Fprint(w, string(body))
                    }
                }))
            })

            g.After(func() {
                ts.Close()
            })

            g.It("Should do a GET", func() {
                res, err := Get{ Uri: ts.URL + "/foo" }.Do()

                Expect(err).Should(BeNil())
                Expect(res.Body).Should(Equal("bar"))
                Expect(res.StatusCode).Should(Equal(200))
            })

            g.Describe("Should be able to POST", func() {
                g.It("a string", func() {
                    res, err := Post{ Uri: ts.URL, Body: "foo" }.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal("foo"))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })

                g.It("a Reader", func() {
                    res, err := Post{ Uri: ts.URL, Body: strings.NewReader("foo") }.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal("foo"))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })

                g.It("any other json valid structure", func() {
                    obj := map[string]string {"foo": "bar"}
                    res, err := Post{ Uri: ts.URL, Body: obj}.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal(`{"foo":"bar"}`))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })
            })

            g.It("Should do a PUT")
            g.It("Should do a DELETE")
            g.It("Should do a OPTIONS")
            g.It("Should do a PATCH")
            g.It("Should do a TRACE")
            g.It("Should do a custom method")
        })

        g.Describe("Timeouts", func() {
            g.It("Should timeout after a specified amount of ms")
            g.It("Should connect timeout after a specified amount of ms")
        })

        g.Describe("Misc", func() {
            g.It("Should offer to set request headers")
        })
    })
}
<commit_msg>change tets names, as they are more understandable<commit_after>package request

import (
    "testing"
    . "github.com/onsi/gomega"
    . "github.com/franela/goblin"
    "net/http/httptest"
    "net/http"
    "fmt"
    "io/ioutil"
    "strings"
)

func TestRequest(t *testing.T) {
    g := Goblin(t)

    RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

    g.Describe("Request", func() {

        g.Describe("General request methods", func() {
            var ts *httptest.Server

            g.Before(func() {
                ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                    if r.Method == "GET" && r.URL.Path == "/foo" {
                        w.WriteHeader(200)
                        fmt.Fprint(w, "bar")
                    }
                    if r.Method == "POST" && r.URL.Path == "/" {
                        body, _ := ioutil.ReadAll(r.Body)
                        w.Header().Add("Location", ts.URL + "/123")
                        w.WriteHeader(201)
                        fmt.Fprint(w, string(body))
                    }
                }))
            })

            g.After(func() {
                ts.Close()
            })

            g.It("Should do a GET", func() {
                res, err := Get{ Uri: ts.URL + "/foo" }.Do()

                Expect(err).Should(BeNil())
                Expect(res.Body).Should(Equal("bar"))
                Expect(res.StatusCode).Should(Equal(200))
            })

            g.Describe("POST", func() {
                g.It("Should send a string", func() {
                    res, err := Post{ Uri: ts.URL, Body: "foo" }.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal("foo"))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })

                g.It("Should send a Reader", func() {
                    res, err := Post{ Uri: ts.URL, Body: strings.NewReader("foo") }.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal("foo"))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })

                g.It("Send any object that is json encodable", func() {
                    obj := map[string]string {"foo": "bar"}
                    res, err := Post{ Uri: ts.URL, Body: obj}.Do()

                    Expect(err).Should(BeNil())
                    Expect(res.Body).Should(Equal(`{"foo":"bar"}`))
                    Expect(res.StatusCode).Should(Equal(201))
                    Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123"))
                })
            })

            g.It("Should do a PUT")
            g.It("Should do a DELETE")
            g.It("Should do a OPTIONS")
            g.It("Should do a PATCH")
            g.It("Should do a TRACE")
            g.It("Should do a custom method")
        })

        g.Describe("Timeouts", func() {
            g.It("Should timeout after a specified amount of ms")
            g.It("Should connect timeout after a specified amount of ms")
        })

        g.Describe("Misc", func() {
            g.It("Should offer to set request headers")
        })
    })
}
<|endoftext|>


<commit_before>package rapi

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"runtime"
	"strings"
	"testing"
)

var httpWriter http.ResponseWriter

// newRequest is a helper function to create a new request with a method and url
func newRequest(method, url string, body string) *http.Request {
	req, err := http.NewRequest(method, url, strings.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", "token1")
	return req
}

func newRecorder() *httptest.ResponseRecorder {
	return httptest.NewRecorder()
}

func assertEqual(t *testing.T, expect interface{}, v interface{}) {
	if v != expect {
		_, fname, lineno, ok := runtime.Caller(1)
		if !ok {
			fname, lineno = "<UNKNOWN>", -1
		}
		t.Errorf("FAIL: %s:%d\nExpected: %#v\nReceived: %#v", fname, lineno, expect, v)
	}
}

func assertNotEqual(t *testing.T, expect interface{}, v interface{}) {
	if v == expect {
		_, fname, lineno, ok := runtime.Caller(1)
		if !ok {
			fname, lineno = "<UNKNOWN>", -1
		}
		t.Errorf("FAIL: %s:%d\nExpected: %#v\nReceived: %#v", fname, lineno, expect, v)
	}
}

func TestMakeAction(t *testing.T) {
	r := Request{}

	r.ID = 10
	act := r.makeAction("GET", urlParts("/10"))
	assertEqual(t, "Show", act)
	act = r.makeAction("POST", urlParts("/10"))
	assertEqual(t, "Update", act)
	act = r.makeAction("PUT", urlParts("/10"))
	assertEqual(t, "Update", act)
	act = r.makeAction("DELETE", urlParts("/10"))
	assertEqual(t, "Destroy", act)
	act = r.makeAction("GET", urlParts("/10/edit"))
	assertEqual(t, "GETEdit", act)
	act = r.makeAction("POST", urlParts("/10/edit"))
	assertEqual(t, "POSTEdit", act)
	act = r.makeAction("PUT", urlParts("/10/edit"))
	assertEqual(t, "PUTEdit", act)
	act = r.makeAction("DELETE", urlParts("/10/edit"))
	assertEqual(t, "DELETEEdit", act)

	r.ID = 0
	act = r.makeAction("GET", urlParts("/action"))
	assertEqual(t, "GETAction", act)
	act = r.makeAction("POST", urlParts("/action"))
	assertEqual(t, "POSTAction", act)
	act = r.makeAction("PUT", urlParts("/action"))
	assertEqual(t, "PUTAction", act)
	act = r.makeAction("DELETE", urlParts("/action"))
	assertEqual(t, "DELETEAction", act)
}

func TestQueryParams(t *testing.T) {
	req := newRequest("GET", "http://localhost/?p1=1&p2=2", "{}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	assertEqual(t, "1", r.QueryParam("p1"))
	assertEqual(t, "2", r.QueryParam("p2"))
	assertEqual(t, "", r.QueryParam("p3"))
}

func TestHeader(t *testing.T) {
	req := newRequest("GET", "http://localhost", "{}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	assertEqual(t, "token1", r.Header("X-API-Token"))
	assertEqual(t, "", r.Header("X-API-Token1"))
}

func TestBody(t *testing.T) {
	req := newRequest("GET", "http://localhost/", "{\"id\":2}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	var res interface{}
	res = nil
	r.LoadJSONRequest("", &res)
	in := fmt.Sprintf("%#v", res)
	out := fmt.Sprintf("%#v", map[string]interface{}{"id": 2})
	assertEqual(t, out, in)

	req = newRequest("GET", "http://localhost/", "{\"id\":2}")
	r = Request{}
	r.Init(httpWriter, req, "root")
	res = nil
	r.LoadJSONRequest("id", &res)
	in = fmt.Sprintf("%#v", res)
	assertEqual(t, "2", in)

	req = newRequest("GET", "http://localhost/", "{\"id\":2}")
	r = Request{}
	r.Init(httpWriter, req, "root")
	res = nil
	r.LoadJSONRequest("id1", &res)
	assertEqual(t, nil, res)
}
<commit_msg>adding benchmark for controller action<commit_after>package rapi

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"runtime"
	"strings"
	"testing"
)

var httpWriter http.ResponseWriter

// newRequest is a helper function to create a new request with a method and url
func newRequest(method, url string, body string) *http.Request {
	req, err := http.NewRequest(method, url, strings.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Token", "token1")
	return req
}

func newRecorder() *httptest.ResponseRecorder {
	return httptest.NewRecorder()
}

func assertEqual(t *testing.T, expect interface{}, v interface{}) {
	if v != expect {
		_, fname, lineno, ok := runtime.Caller(1)
		if !ok {
			fname, lineno = "<UNKNOWN>", -1
		}
		t.Errorf("FAIL: %s:%d\nExpected: %#v\nReceived: %#v", fname, lineno, expect, v)
	}
}

func assertNotEqual(t *testing.T, expect interface{}, v interface{}) {
	if v == expect {
		_, fname, lineno, ok := runtime.Caller(1)
		if !ok {
			fname, lineno = "<UNKNOWN>", -1
		}
		t.Errorf("FAIL: %s:%d\nExpected: %#v\nReceived: %#v", fname, lineno, expect, v)
	}
}

func TestMakeAction(t *testing.T) {
	r := Request{}

	r.ID = 10
	act := r.makeAction("GET", urlParts("/10"))
	assertEqual(t, "Show", act)
	act = r.makeAction("POST", urlParts("/10"))
	assertEqual(t, "Update", act)
	act = r.makeAction("PUT", urlParts("/10"))
	assertEqual(t, "Update", act)
	act = r.makeAction("DELETE", urlParts("/10"))
	assertEqual(t, "Destroy", act)
	act = r.makeAction("GET", urlParts("/10/edit"))
	assertEqual(t, "GETEdit", act)
	act = r.makeAction("POST", urlParts("/10/edit"))
	assertEqual(t, "POSTEdit", act)
	act = r.makeAction("PUT", urlParts("/10/edit"))
	assertEqual(t, "PUTEdit", act)
	act = r.makeAction("DELETE", urlParts("/10/edit"))
	assertEqual(t, "DELETEEdit", act)

	r.ID = 0
	act = r.makeAction("GET", urlParts("/action"))
	assertEqual(t, "GETAction", act)
	act = r.makeAction("POST", urlParts("/action"))
	assertEqual(t, "POSTAction", act)
	act = r.makeAction("PUT", urlParts("/action"))
	assertEqual(t, "PUTAction", act)
	act = r.makeAction("DELETE", urlParts("/action"))
	assertEqual(t, "DELETEAction", act)
}

func TestQueryParams(t *testing.T) {
	req := newRequest("GET", "http://localhost/?p1=1&p2=2", "{}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	assertEqual(t, "1", r.QueryParam("p1"))
	assertEqual(t, "2", r.QueryParam("p2"))
	assertEqual(t, "", r.QueryParam("p3"))
}

func TestHeader(t *testing.T) {
	req := newRequest("GET", "http://localhost", "{}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	assertEqual(t, "token1", r.Header("X-API-Token"))
	assertEqual(t, "", r.Header("X-API-Token1"))
}

func TestBody(t *testing.T) {
	req := newRequest("GET", "http://localhost/", "{\"id\":2}")
	r := Request{}
	r.Init(httpWriter, req, "root")
	var res interface{}
	res = nil
	r.LoadJSONRequest("", &res)
	in := fmt.Sprintf("%#v", res)
	out := fmt.Sprintf("%#v", map[string]interface{}{"id": 2})
	assertEqual(t, out, in)

	req = newRequest("GET", "http://localhost/", "{\"id\":2}")
	r = Request{}
	r.Init(httpWriter, req, "root")
	res = nil
	r.LoadJSONRequest("id", &res)
	in = fmt.Sprintf("%#v", res)
	assertEqual(t, "2", in)

	req = newRequest("GET", "http://localhost/", "{\"id\":2}")
	r = Request{}
	r.Init(httpWriter, req, "root")
	res = nil
	r.LoadJSONRequest("id1", &res)
	assertEqual(t, nil, res)
}

type TestC struct {
	Request
}

func (t *TestC) Index() {
	t.RenderJSON(200, JSONData{})
}

func BenchmarkIndexAction(b *testing.B) {
	req := newRequest("GET", "http://localhost/pages/", "{}")
	handler := handle(&TestC{}, "page", []ReqFunc{})

	for n := 0; n < b.N; n++ {
		handler(newRecorder(), req)
	}
}
<|endoftext|>


<commit_before>//go:generate go get github.com/jteeuwen/go-bindata
//go:generate go install github.com/jteeuwen/go-bindata/go-bindata
//go:generate go-bindata -pkg assets -ignore .jsbeautifyrc -prefix "_embed" -o assets/binary.go _embed/...

// Package filemanager provides middleware for managing files in a directory
// when directory path is requested instead of a specific file. Based on browse
// middleware.
package filemanager

import (
	e "errors"
	"net/http"
	"strings"

	"github.com/hacdias/caddy-filemanager/assets"
	"github.com/hacdias/caddy-filemanager/config"
	"github.com/hacdias/caddy-filemanager/file"
	"github.com/hacdias/caddy-filemanager/handlers"
	"github.com/hacdias/caddy-filemanager/page"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

// FileManager is an http.Handler that can show a file listing when
// directories in the given paths are specified.
type FileManager struct {
	Next    httpserver.Handler
	Configs []config.Config
}
asas
// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	var (
		c    *config.Config
		fi   *file.Info
		code int
		err  error
		user *config.User
	)

	for i := range f.Configs {
		// Checks if this Path should be handled by File Manager.
		if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
			return f.Next.ServeHTTP(w, r)
		}

		w.Header().Set("x-frame-options", "SAMEORIGIN")
		w.Header().Set("x-content-type", "nosniff")
		w.Header().Set("x-xss-protection", "1; mode=block")

		c = &f.Configs[i]

		// Checks if the URL matches the Assets URL. Returns the asset if the
		// method is GET and Status Forbidden otherwise.
		if httpserver.Path(r.URL.Path).Matches(c.BaseURL + assets.BaseURL) {
			if r.Method == http.MethodGet {
				return assets.Serve(w, r, c)
			}

			return http.StatusForbidden, nil
		}

		// Obtains the user
		username, _, _ := r.BasicAuth()
		if _, ok := c.Users[username]; ok {
			user = c.Users[username]
		} else {
			user = c.User
		}

		if r.URL.Query().Get("command") != "" {
			return handlers.Command(w, r, c, user)
		}

		// Checks if the request URL is for the WebDav server
		if strings.HasPrefix(r.URL.Path, c.WebDavURL) {
			// Checks for user permissions relatively to this PATH
			if !user.Allowed(strings.TrimPrefix(r.URL.Path, c.WebDavURL)) {
				return http.StatusForbidden, nil
			}

			switch r.Method {
			case "PROPPATCH", "MOVE", "PATCH", "PUT", "DELETE":
				if !user.AllowEdit {
					return http.StatusForbidden, nil
				}
			case "MKCOL", "COPY":
				if !user.AllowNew {
					return http.StatusForbidden, nil
				}
			}

			// Preprocess the PUT request if it's the case
			if r.Method == http.MethodPut {
				if handlers.PreProccessPUT(w, r, c, user, fi) != nil {
					return http.StatusInternalServerError, err
				}
			}

			c.Handler.ServeHTTP(w, r)
			return 0, nil
		}

		// Checks if the User is allowed to access this file
		if !user.Allowed(strings.TrimPrefix(r.URL.Path, c.BaseURL)) {
			if r.Method == http.MethodGet {
				return page.PrintErrorHTML(
					w, http.StatusForbidden,
					e.New("You don't have permission to access this page."),
				)
			}

			return http.StatusForbidden, nil
		}

		if r.Method == http.MethodGet {
			// Gets the information of the directory/file
			fi, code, err = file.GetInfo(r.URL, c, user)
			if err != nil {
				if r.Method == http.MethodGet {
					return page.PrintErrorHTML(w, code, err)
				}
				return code, err
			}

			// If it's a dir and the path doesn't end with a trailing slash,
			// redirect the user.
			if fi.IsDir() && !strings.HasSuffix(r.URL.Path, "/") {
				http.Redirect(w, r, c.AddrPath+r.URL.Path+"/", http.StatusTemporaryRedirect)
				return 0, nil
			}

			switch {
			case r.URL.Query().Get("download") != "":
				code, err = handlers.Download(w, r, c, fi)
			case r.URL.Query().Get("raw") == "true" && !fi.IsDir():
				http.ServeFile(w, r, fi.Path)
				code, err = 0, nil
			case fi.IsDir():
				code, err = handlers.ServeListing(w, r, c, user, fi)
			default:
				code, err = handlers.ServeSingle(w, r, c, user, fi)
			}

			if err != nil {
				code, err = page.PrintErrorHTML(w, code, err)
			}

			return code, err
		}

		return http.StatusNotImplemented, nil

	}

	return f.Next.ServeHTTP(w, r)
}
<commit_msg>remove error<commit_after>//go:generate go get github.com/jteeuwen/go-bindata
//go:generate go install github.com/jteeuwen/go-bindata/go-bindata
//go:generate go-bindata -pkg assets -ignore .jsbeautifyrc -prefix "_embed" -o assets/binary.go _embed/...

// Package filemanager provides middleware for managing files in a directory
// when directory path is requested instead of a specific file. Based on browse
// middleware.
package filemanager

import (
	e "errors"
	"net/http"
	"strings"

	"github.com/hacdias/caddy-filemanager/assets"
	"github.com/hacdias/caddy-filemanager/config"
	"github.com/hacdias/caddy-filemanager/file"
	"github.com/hacdias/caddy-filemanager/handlers"
	"github.com/hacdias/caddy-filemanager/page"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

// FileManager is an http.Handler that can show a file listing when
// directories in the given paths are specified.
type FileManager struct {
	Next    httpserver.Handler
	Configs []config.Config
}

// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	var (
		c    *config.Config
		fi   *file.Info
		code int
		err  error
		user *config.User
	)

	for i := range f.Configs {
		// Checks if this Path should be handled by File Manager.
		if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
			return f.Next.ServeHTTP(w, r)
		}

		w.Header().Set("x-frame-options", "SAMEORIGIN")
		w.Header().Set("x-content-type", "nosniff")
		w.Header().Set("x-xss-protection", "1; mode=block")

		c = &f.Configs[i]

		// Checks if the URL matches the Assets URL. Returns the asset if the
		// method is GET and Status Forbidden otherwise.
		if httpserver.Path(r.URL.Path).Matches(c.BaseURL + assets.BaseURL) {
			if r.Method == http.MethodGet {
				return assets.Serve(w, r, c)
			}

			return http.StatusForbidden, nil
		}

		// Obtains the user
		username, _, _ := r.BasicAuth()
		if _, ok := c.Users[username]; ok {
			user = c.Users[username]
		} else {
			user = c.User
		}

		if r.URL.Query().Get("command") != "" {
			return handlers.Command(w, r, c, user)
		}

		// Checks if the request URL is for the WebDav server
		if strings.HasPrefix(r.URL.Path, c.WebDavURL) {
			// Checks for user permissions relatively to this PATH
			if !user.Allowed(strings.TrimPrefix(r.URL.Path, c.WebDavURL)) {
				return http.StatusForbidden, nil
			}

			switch r.Method {
			case "PROPPATCH", "MOVE", "PATCH", "PUT", "DELETE":
				if !user.AllowEdit {
					return http.StatusForbidden, nil
				}
			case "MKCOL", "COPY":
				if !user.AllowNew {
					return http.StatusForbidden, nil
				}
			}

			// Preprocess the PUT request if it's the case
			if r.Method == http.MethodPut {
				if handlers.PreProccessPUT(w, r, c, user, fi) != nil {
					return http.StatusInternalServerError, err
				}
			}

			c.Handler.ServeHTTP(w, r)
			return 0, nil
		}

		// Checks if the User is allowed to access this file
		if !user.Allowed(strings.TrimPrefix(r.URL.Path, c.BaseURL)) {
			if r.Method == http.MethodGet {
				return page.PrintErrorHTML(
					w, http.StatusForbidden,
					e.New("You don't have permission to access this page."),
				)
			}

			return http.StatusForbidden, nil
		}

		if r.Method == http.MethodGet {
			// Gets the information of the directory/file
			fi, code, err = file.GetInfo(r.URL, c, user)
			if err != nil {
				if r.Method == http.MethodGet {
					return page.PrintErrorHTML(w, code, err)
				}
				return code, err
			}

			// If it's a dir and the path doesn't end with a trailing slash,
			// redirect the user.
			if fi.IsDir() && !strings.HasSuffix(r.URL.Path, "/") {
				http.Redirect(w, r, c.AddrPath+r.URL.Path+"/", http.StatusTemporaryRedirect)
				return 0, nil
			}

			switch {
			case r.URL.Query().Get("download") != "":
				code, err = handlers.Download(w, r, c, fi)
			case r.URL.Query().Get("raw") == "true" && !fi.IsDir():
				http.ServeFile(w, r, fi.Path)
				code, err = 0, nil
			case fi.IsDir():
				code, err = handlers.ServeListing(w, r, c, user, fi)
			default:
				code, err = handlers.ServeSingle(w, r, c, user, fi)
			}

			if err != nil {
				code, err = page.PrintErrorHTML(w, code, err)
			}

			return code, err
		}

		return http.StatusNotImplemented, nil

	}

	return f.Next.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>package testutil

import (
	"context"
	"database/sql"
	"fmt"
	"io"
	"os"
	"reflect"
	"testing"

	"github.com/jackc/pgx"
	"github.com/jackc/pgx/pgtype"
	_ "github.com/jackc/pgx/stdlib"
	_ "github.com/lib/pq"
)

func MustConnectDatabaseSQL(t testing.TB, driverName string) *sql.DB {
	var sqlDriverName string
	switch driverName {
	case "github.com/lib/pq":
		sqlDriverName = "postgres"
	case "github.com/jackc/pgx/stdlib":
		sqlDriverName = "pgx"
	default:
		t.Fatalf("Unknown driver %v", driverName)
	}

	db, err := sql.Open(sqlDriverName, os.Getenv("DATABASE_URL"))
	if err != nil {
		t.Fatal(err)
	}

	return db
}

func MustConnectPgx(t testing.TB) *pgx.Conn {
	config, err := pgx.ParseURI(os.Getenv("DATABASE_URL"))
	if err != nil {
		t.Fatal(err)
	}

	conn, err := pgx.Connect(config)
	if err != nil {
		t.Fatal(err)
	}

	return conn
}

func MustClose(t testing.TB, conn interface {
	Close() error
}) {
	err := conn.Close()
	if err != nil {
		t.Fatal(err)
	}
}

type forceTextEncoder struct {
	e pgtype.TextEncoder
}

func (f forceTextEncoder) EncodeText(ci *pgtype.ConnInfo, w io.Writer) (bool, error) {
	return f.e.EncodeText(ci, w)
}

type forceBinaryEncoder struct {
	e pgtype.BinaryEncoder
}

func (f forceBinaryEncoder) EncodeBinary(ci *pgtype.ConnInfo, w io.Writer) (bool, error) {
	return f.e.EncodeBinary(ci, w)
}

func ForceEncoder(e interface{}, formatCode int16) interface{} {
	switch formatCode {
	case pgx.TextFormatCode:
		if e, ok := e.(pgtype.TextEncoder); ok {
			return forceTextEncoder{e: e}
		}
	case pgx.BinaryFormatCode:
		if e, ok := e.(pgtype.BinaryEncoder); ok {
			return forceBinaryEncoder{e: e.(pgtype.BinaryEncoder)}
		}
	}
	return nil
}

func TestSuccessfulTranscode(t testing.TB, pgTypeName string, values []interface{}) {
	TestSuccessfulTranscodeEqFunc(t, pgTypeName, values, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
	}
}

func TestPgxSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	ps, err := conn.Prepare("test", fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, v := range values {
		for _, fc := range formats {
			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			vEncoder := ForceEncoder(v, fc.formatCode)
			if vEncoder == nil {
				t.Logf("Skipping: %#v does not implement %v", v, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := v
			refVal := reflect.ValueOf(v)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err := conn.QueryRow("test", ForceEncoder(v, fc.formatCode)).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := conn.QueryRowEx(
			context.Background(),
			fmt.Sprintf("select ($1)::%s", pgTypeName),
			&pgx.QueryExOptions{SimpleProtocol: true},
			v,
		).Scan(result.Interface())
		if err != nil {
			t.Errorf("Simple protocol %d: %v", i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("Simple protocol %d: expected %v, got %v", i, derefV, result.Elem().Interface())
		}
	}
}

func TestDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	ps, err := conn.Prepare(fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := ps.QueryRow(v).Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}

type NormalizeTest struct {
	SQL   string
	Value interface{}
}

func TestSuccessfulNormalize(t testing.TB, tests []NormalizeTest) {
	TestSuccessfulNormalizeEqFunc(t, tests, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulNormalizeEqFunc(t, tests, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulNormalizeEqFunc(t, driverName, tests, eqFunc)
	}
}

func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, tt := range tests {
		for _, fc := range formats {
			psName := fmt.Sprintf("test%d", i)
			ps, err := conn.Prepare(psName, tt.SQL)
			if err != nil {
				t.Fatal(err)
			}

			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			if ForceEncoder(tt.Value, fc.formatCode) == nil {
				t.Logf("Skipping: %#v does not implement %v", tt.Value, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := tt.Value
			refVal := reflect.ValueOf(tt.Value)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err = conn.QueryRow(psName).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestDatabaseSQLSuccessfulNormalizeEqFunc(t testing.TB, driverName string, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	for i, tt := range tests {
		ps, err := conn.Prepare(tt.SQL)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		// Derefence value if it is a pointer
		derefV := tt.Value
		refVal := reflect.ValueOf(tt.Value)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err = ps.QueryRow().Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}
<commit_msg>Replace DATABASE_URL with PGX_TEST_DATABASE<commit_after>package testutil

import (
	"context"
	"database/sql"
	"fmt"
	"io"
	"os"
	"reflect"
	"testing"

	"github.com/jackc/pgx"
	"github.com/jackc/pgx/pgtype"
	_ "github.com/jackc/pgx/stdlib"
	_ "github.com/lib/pq"
)

func MustConnectDatabaseSQL(t testing.TB, driverName string) *sql.DB {
	var sqlDriverName string
	switch driverName {
	case "github.com/lib/pq":
		sqlDriverName = "postgres"
	case "github.com/jackc/pgx/stdlib":
		sqlDriverName = "pgx"
	default:
		t.Fatalf("Unknown driver %v", driverName)
	}

	db, err := sql.Open(sqlDriverName, os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	return db
}

func MustConnectPgx(t testing.TB) *pgx.Conn {
	config, err := pgx.ParseURI(os.Getenv("PGX_TEST_DATABASE"))
	if err != nil {
		t.Fatal(err)
	}

	conn, err := pgx.Connect(config)
	if err != nil {
		t.Fatal(err)
	}

	return conn
}

func MustClose(t testing.TB, conn interface {
	Close() error
}) {
	err := conn.Close()
	if err != nil {
		t.Fatal(err)
	}
}

type forceTextEncoder struct {
	e pgtype.TextEncoder
}

func (f forceTextEncoder) EncodeText(ci *pgtype.ConnInfo, w io.Writer) (bool, error) {
	return f.e.EncodeText(ci, w)
}

type forceBinaryEncoder struct {
	e pgtype.BinaryEncoder
}

func (f forceBinaryEncoder) EncodeBinary(ci *pgtype.ConnInfo, w io.Writer) (bool, error) {
	return f.e.EncodeBinary(ci, w)
}

func ForceEncoder(e interface{}, formatCode int16) interface{} {
	switch formatCode {
	case pgx.TextFormatCode:
		if e, ok := e.(pgtype.TextEncoder); ok {
			return forceTextEncoder{e: e}
		}
	case pgx.BinaryFormatCode:
		if e, ok := e.(pgtype.BinaryEncoder); ok {
			return forceBinaryEncoder{e: e.(pgtype.BinaryEncoder)}
		}
	}
	return nil
}

func TestSuccessfulTranscode(t testing.TB, pgTypeName string, values []interface{}) {
	TestSuccessfulTranscodeEqFunc(t, pgTypeName, values, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t, pgTypeName, values, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulTranscodeEqFunc(t, driverName, pgTypeName, values, eqFunc)
	}
}

func TestPgxSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	ps, err := conn.Prepare("test", fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, v := range values {
		for _, fc := range formats {
			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			vEncoder := ForceEncoder(v, fc.formatCode)
			if vEncoder == nil {
				t.Logf("Skipping: %#v does not implement %v", v, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := v
			refVal := reflect.ValueOf(v)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err := conn.QueryRow("test", ForceEncoder(v, fc.formatCode)).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestPgxSimpleProtocolSuccessfulTranscodeEqFunc(t testing.TB, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := conn.QueryRowEx(
			context.Background(),
			fmt.Sprintf("select ($1)::%s", pgTypeName),
			&pgx.QueryExOptions{SimpleProtocol: true},
			v,
		).Scan(result.Interface())
		if err != nil {
			t.Errorf("Simple protocol %d: %v", i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("Simple protocol %d: expected %v, got %v", i, derefV, result.Elem().Interface())
		}
	}
}

func TestDatabaseSQLSuccessfulTranscodeEqFunc(t testing.TB, driverName, pgTypeName string, values []interface{}, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	ps, err := conn.Prepare(fmt.Sprintf("select $1::%s", pgTypeName))
	if err != nil {
		t.Fatal(err)
	}

	for i, v := range values {
		// Derefence value if it is a pointer
		derefV := v
		refVal := reflect.ValueOf(v)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err := ps.QueryRow(v).Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}

type NormalizeTest struct {
	SQL   string
	Value interface{}
}

func TestSuccessfulNormalize(t testing.TB, tests []NormalizeTest) {
	TestSuccessfulNormalizeEqFunc(t, tests, func(a, b interface{}) bool {
		return reflect.DeepEqual(a, b)
	})
}

func TestSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	TestPgxSuccessfulNormalizeEqFunc(t, tests, eqFunc)
	for _, driverName := range []string{"github.com/lib/pq", "github.com/jackc/pgx/stdlib"} {
		TestDatabaseSQLSuccessfulNormalizeEqFunc(t, driverName, tests, eqFunc)
	}
}

func TestPgxSuccessfulNormalizeEqFunc(t testing.TB, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectPgx(t)
	defer MustClose(t, conn)

	formats := []struct {
		name       string
		formatCode int16
	}{
		{name: "TextFormat", formatCode: pgx.TextFormatCode},
		{name: "BinaryFormat", formatCode: pgx.BinaryFormatCode},
	}

	for i, tt := range tests {
		for _, fc := range formats {
			psName := fmt.Sprintf("test%d", i)
			ps, err := conn.Prepare(psName, tt.SQL)
			if err != nil {
				t.Fatal(err)
			}

			ps.FieldDescriptions[0].FormatCode = fc.formatCode
			if ForceEncoder(tt.Value, fc.formatCode) == nil {
				t.Logf("Skipping: %#v does not implement %v", tt.Value, fc.name)
				continue
			}
			// Derefence value if it is a pointer
			derefV := tt.Value
			refVal := reflect.ValueOf(tt.Value)
			if refVal.Kind() == reflect.Ptr {
				derefV = refVal.Elem().Interface()
			}

			result := reflect.New(reflect.TypeOf(derefV))
			err = conn.QueryRow(psName).Scan(result.Interface())
			if err != nil {
				t.Errorf("%v %d: %v", fc.name, i, err)
			}

			if !eqFunc(result.Elem().Interface(), derefV) {
				t.Errorf("%v %d: expected %v, got %v", fc.name, i, derefV, result.Elem().Interface())
			}
		}
	}
}

func TestDatabaseSQLSuccessfulNormalizeEqFunc(t testing.TB, driverName string, tests []NormalizeTest, eqFunc func(a, b interface{}) bool) {
	conn := MustConnectDatabaseSQL(t, driverName)
	defer MustClose(t, conn)

	for i, tt := range tests {
		ps, err := conn.Prepare(tt.SQL)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		// Derefence value if it is a pointer
		derefV := tt.Value
		refVal := reflect.ValueOf(tt.Value)
		if refVal.Kind() == reflect.Ptr {
			derefV = refVal.Elem().Interface()
		}

		result := reflect.New(reflect.TypeOf(derefV))
		err = ps.QueryRow().Scan(result.Interface())
		if err != nil {
			t.Errorf("%v %d: %v", driverName, i, err)
		}

		if !eqFunc(result.Elem().Interface(), derefV) {
			t.Errorf("%v %d: expected %v, got %v", driverName, i, derefV, result.Elem().Interface())
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"regexp"
	"strconv"
	"time"

	"github.com/sachaos/todoist/lib"
)

var priorityRegex = regexp.MustCompile("^p([1-4])$")

func Eval(e Expression, item todoist.AbstractItem, projects todoist.Projects, labels todoist.Labels) (result bool, err error) {
	result = false
	switch e.(type) {
	case BoolInfixOpExpr:
		e := e.(BoolInfixOpExpr)
		lr, err := Eval(e.left, item, projects, labels)
		rr, err := Eval(e.right, item, projects, labels)
		if err != nil {
			return false, nil
		}
		switch e.operator {
		case '&':
			return lr && rr, nil
		case '|':
			return lr || rr, nil
		}
	case ProjectExpr:
		e := e.(ProjectExpr)
		return EvalProject(e, item.GetProjectID(), projects), err
	case LabelExpr:
		e := e.(LabelExpr)
		return EvalLabel(e, item.GetLabelIDs(), labels), err
	case StringExpr:
		switch item.(type) {
		case *todoist.Item:
			item := item.(*todoist.Item)
			e := e.(StringExpr)
			return EvalAsPriority(e, item), err
		default:
			return false, nil
		}
	case DateExpr:
		e := e.(DateExpr)
		return EvalDate(e, item.DateTime()), err
	case NotOpExpr:
		e := e.(NotOpExpr)
		r, err := Eval(e.expr, item, projects, labels)
		if err != nil {
			return false, nil
		}
		return !r, nil
	default:
		return true, err
	}
	return
}

func EvalDate(e DateExpr, itemDate time.Time) (result bool) {
	if (itemDate == time.Time{}) {
		if e.operation == NO_DUE_DATE {
			return true
		}
		return false
	}
	allDay := e.allDay
	dueDate := e.datetime
	switch e.operation {
	case DUE_ON:
		var startDate, endDate time.Time
		if allDay {
			startDate = dueDate
			endDate = dueDate.AddDate(0, 0, 1)
			if itemDate.Equal(startDate) || (itemDate.After(startDate) && itemDate.Before(endDate)) {
				return true
			}
		}
		return false
	case DUE_BEFORE:
		if itemDate.Before(dueDate) {
			return true
		}
		return false
	case DUE_AFTER:
		endDateTime := dueDate
		if allDay {
			endDateTime = dueDate.AddDate(0, 0, 1).Add(-time.Duration(time.Microsecond))
		}
		if itemDate.After(endDateTime) {
			return true
		}
		return false
	default:
		return false
	}
}

func EvalAsPriority(e StringExpr, item *todoist.Item) (result bool) {
	matched := priorityRegex.FindStringSubmatch(e.literal)
	if len(matched) == 0 {
		return false
	} else {
		p, _ := strconv.Atoi(matched[1])
		if p == priorityMapping[item.Priority] {
			return true
		}
	}
	return false
}

func EvalProject(e ProjectExpr, projectID int, projects todoist.Projects) bool {
	for _, id := range projects.GetIDsByName(e.name, e.isAll) {
		if id == projectID {
			return true
		}
	}
	return false
}

func EvalLabel(e LabelExpr, labelIDs []int, labels todoist.Labels) bool {
	if e.name == "" {
		if len(labelIDs) == 0 {
			return true
		} else {
			return false
		}
	}

	labelID := labels.GetIDByName(e.name)
	if labelID == 0 {
		return false
	}

	for _, id := range labelIDs {
		if id == labelID {
			return true
		}
	}

	return false
}
<commit_msg>simplified return on if-else statements<commit_after>package main

import (
	"regexp"
	"strconv"
	"time"

	"github.com/sachaos/todoist/lib"
)

var priorityRegex = regexp.MustCompile("^p([1-4])$")

func Eval(e Expression, item todoist.AbstractItem, projects todoist.Projects, labels todoist.Labels) (result bool, err error) {
	result = false
	switch e.(type) {
	case BoolInfixOpExpr:
		e := e.(BoolInfixOpExpr)
		lr, err := Eval(e.left, item, projects, labels)
		rr, err := Eval(e.right, item, projects, labels)
		if err != nil {
			return false, nil
		}
		switch e.operator {
		case '&':
			return lr && rr, nil
		case '|':
			return lr || rr, nil
		}
	case ProjectExpr:
		e := e.(ProjectExpr)
		return EvalProject(e, item.GetProjectID(), projects), err
	case LabelExpr:
		e := e.(LabelExpr)
		return EvalLabel(e, item.GetLabelIDs(), labels), err
	case StringExpr:
		switch item.(type) {
		case *todoist.Item:
			item := item.(*todoist.Item)
			e := e.(StringExpr)
			return EvalAsPriority(e, item), err
		default:
			return false, nil
		}
	case DateExpr:
		e := e.(DateExpr)
		return EvalDate(e, item.DateTime()), err
	case NotOpExpr:
		e := e.(NotOpExpr)
		r, err := Eval(e.expr, item, projects, labels)
		if err != nil {
			return false, nil
		}
		return !r, nil
	default:
		return true, err
	}
	return
}

func EvalDate(e DateExpr, itemDate time.Time) (result bool) {
	if (itemDate == time.Time{}) {
		return e.operation == NO_DUE_DATE
	}
	allDay := e.allDay
	dueDate := e.datetime
	switch e.operation {
	case DUE_ON:
		var startDate, endDate time.Time
		if allDay {
			startDate = dueDate
			endDate = dueDate.AddDate(0, 0, 1)
			if itemDate.Equal(startDate) || (itemDate.After(startDate) && itemDate.Before(endDate)) {
				return true
			}
		}
		return false
	case DUE_BEFORE:
		return itemDate.Before(dueDate)
	case DUE_AFTER:
		endDateTime := dueDate
		if allDay {
			endDateTime = dueDate.AddDate(0, 0, 1).Add(-time.Duration(time.Microsecond))
		}
		return itemDate.After(endDateTime)
	default:
		return false
	}
}

func EvalAsPriority(e StringExpr, item *todoist.Item) (result bool) {
	matched := priorityRegex.FindStringSubmatch(e.literal)
	if len(matched) == 0 {
		return false
	} else {
		p, _ := strconv.Atoi(matched[1])
		if p == priorityMapping[item.Priority] {
			return true
		}
	}
	return false
}

func EvalProject(e ProjectExpr, projectID int, projects todoist.Projects) bool {
	for _, id := range projects.GetIDsByName(e.name, e.isAll) {
		if id == projectID {
			return true
		}
	}
	return false
}

func EvalLabel(e LabelExpr, labelIDs []int, labels todoist.Labels) bool {
	if e.name == "" {
		return len(labelIDs) == 0
	}

	labelID := labels.GetIDByName(e.name)
	if labelID == 0 {
		return false
	}

	for _, id := range labelIDs {
		if id == labelID {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package main

import (
	"golang.org/x/sys/unix"
)

const (
	termiosIFlagRawTermInvMask = (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
	termiosOFlagRawTermInvMask = unix.OPOST
	termiosLFlagRawTermInvMask = (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
	termiosCFlagRawTermInvMask = unix.PARENB
	termiosCFlagRawTermMask    = unix.CS8
	termiosCcVMinRawTermVal    = 1
	termiosCcVTimeRawTermVal   = 0
)

func setupTerminal(fd int) (*unix.Termios, error) {
	termios, err := unix.IoctlGetTermios(fd, unix.TIOCGETA)
	if err != nil {
		return nil, err
	}

	var savedTermios unix.Termios
	savedTermios = *termios

	// Set the terminal in raw mode
	termios.Iflag &^= termiosIFlagRawTermInvMask
	termios.Oflag &^= termiosOFlagRawTermInvMask
	termios.Lflag &^= termiosLFlagRawTermInvMask
	termios.Cflag &^= termiosCFlagRawTermInvMask
	termios.Cflag |= termiosCFlagRawTermMask
	termios.Cc[unix.VMIN] = termiosCcVMinRawTermVal
	termios.Cc[unix.VTIME] = termiosCcVTimeRawTermVal

	if err := unix.IoctlSetTermios(fd, unix.TIOCSETA, termios); err != nil {
		return nil, err
	}

	return &savedTermios, nil
}

func restoreTerminal(fd int, termios *unix.Termios) error {
	return unix.IoctlSetTermios(fd, unix.TIOCSETA, termios)
}
<commit_msg>gosimple: merge variable declaration with assignment<commit_after>// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package main

import (
	"golang.org/x/sys/unix"
)

const (
	termiosIFlagRawTermInvMask = (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
	termiosOFlagRawTermInvMask = unix.OPOST
	termiosLFlagRawTermInvMask = (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN)
	termiosCFlagRawTermInvMask = unix.PARENB
	termiosCFlagRawTermMask    = unix.CS8
	termiosCcVMinRawTermVal    = 1
	termiosCcVTimeRawTermVal   = 0
)

func setupTerminal(fd int) (*unix.Termios, error) {
	termios, err := unix.IoctlGetTermios(fd, unix.TIOCGETA)
	if err != nil {
		return nil, err
	}

	savedTermios := *termios

	// Set the terminal in raw mode
	termios.Iflag &^= termiosIFlagRawTermInvMask
	termios.Oflag &^= termiosOFlagRawTermInvMask
	termios.Lflag &^= termiosLFlagRawTermInvMask
	termios.Cflag &^= termiosCFlagRawTermInvMask
	termios.Cflag |= termiosCFlagRawTermMask
	termios.Cc[unix.VMIN] = termiosCcVMinRawTermVal
	termios.Cc[unix.VTIME] = termiosCcVTimeRawTermVal

	if err := unix.IoctlSetTermios(fd, unix.TIOCSETA, termios); err != nil {
		return nil, err
	}

	return &savedTermios, nil
}

func restoreTerminal(fd int, termios *unix.Termios) error {
	return unix.IoctlSetTermios(fd, unix.TIOCSETA, termios)
}
<|endoftext|>


<commit_before>package log

import (
	"encoding/binary"
	"math"
	"time"
)

// MessagePack type tags.
// Only tags used in this code are defined.
const (
	mpNil      = 0xc0
	mpFalse    = 0xc2
	mpTrue     = 0xc3
	mpInt16    = 0xd1
	mpInt32    = 0xd2
	mpInt64    = 0xd3
	mpFixStr   = 0xa0
	mpStr8     = 0xd9
	mpStr16    = 0xda
	mpStr32    = 0xdb
	mpBin8     = 0xc4
	mpBin16    = 0xc5
	mpBin32    = 0xc6
	mpFixArray = 0x90
	mpArray16  = 0xdc
	mpArray32  = 0xdd
	mpFixMap   = 0x80
	mpMap16    = 0xde
)

func appendMsgpackInt64(b []byte, n int64) []byte {
	switch {
	case 0 <= n && n <= 127:
		return append(b, byte(n))
	case math.MinInt16 <= n && n <= math.MaxInt16:
		b = append(b, mpInt16, 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(n))
		return b
	case math.MinInt32 <= n && n <= math.MaxInt32:
		b = append(b, mpInt32, 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(n))
		return b
	default:
		b = append(b, mpInt64, 0, 0, 0, 0, 0, 0, 0, 0)
		binary.BigEndian.PutUint64(b[len(b)-8:], uint64(n))
		return b
	}
}

func appendMsgpackString(b []byte, s string) ([]byte, error) {
	switch {
	case len(s) >= maxLogSize:
		return nil, ErrTooLarge
	case len(s) <= 31:
		b = append(b, byte(mpFixStr+len(s)))
	case len(s) <= math.MaxUint8:
		b = append(b, byte(mpStr8))
		b = append(b, byte(len(s)))
	case len(s) <= math.MaxUint16:
		b = append(b, byte(mpStr16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(len(s)))
	case len(s) <= math.MaxUint32:
		b = append(b, byte(mpStr32), 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(len(s)))
	}
	return append(b, s...), nil
}

func appendMsgpackArray(b []byte, length int) ([]byte, error) {
	switch {
	case length <= 15:
		return append(b, byte(mpFixArray+length)), nil
	case length <= math.MaxUint16:
		b = append(b, byte(mpArray16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(length))
		return b, nil
	case length <= math.MaxUint32:
		b = append(b, byte(mpArray32), 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(length))
		return b, nil
	default:
		return nil, ErrTooLarge
	}
}

func appendMsgpack(b []byte, v interface{}) ([]byte, error) {
	switch t := v.(type) {
	case nil:
		return append(b, mpNil), nil
	case bool:
		if t {
			return append(b, mpTrue), nil
		}
		return append(b, mpFalse), nil
	case int:
		return appendMsgpackInt64(b, int64(t)), nil
	case int64:
		return appendMsgpackInt64(b, t), nil
	case time.Time:
		return appendMsgpackInt64(b, t.UnixNano()/1000), nil
	case string:
		return appendMsgpackString(b, t)
	case []byte:
		switch {
		case len(t) >= maxLogSize:
			return nil, ErrTooLarge
		case len(t) <= math.MaxUint8:
			b = append(b, byte(mpBin8))
			b = append(b, byte(len(t)))
		case len(t) <= math.MaxUint16:
			b = append(b, byte(mpBin16), 0, 0)
			binary.BigEndian.PutUint16(b[len(b)-2:], uint16(len(t)))
		case len(t) <= math.MaxUint32:
			b = append(b, byte(mpBin32), 0, 0, 0, 0)
			binary.BigEndian.PutUint32(b[len(b)-4:], uint32(len(t)))
		}
		return append(b, t...), nil
	case []int:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, n := range t {
			b = appendMsgpackInt64(b, int64(n))
		}
		return b, nil
	case []int64:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, n := range t {
			b = appendMsgpackInt64(b, n)
		}
		return b, nil
	case []string:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, s := range t {
			b, err = appendMsgpackString(b, s)
			if err != nil {
				return nil, err
			}
		}
		return b, nil
	default:
		return nil, ErrInvalidData
	}
}

// MsgPack implements Formatter for msgpack format.
//
// https://github.com/msgpack/msgpack/blob/master/spec.md
type MsgPack struct{}

// Format implements Formatter.Format.
func (m MsgPack) Format(b []byte, l *Logger, t time.Time, severity int, msg string,
	fields map[string]interface{}) ([]byte, error) {
	b = append(b, byte(mpFixArray+3))
	b, err := appendMsgpack(b, l.Topic())
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, t.Unix())
	if err != nil {
		return nil, err
	}

	// the log record consists of these objects:
	//     logged_at, severity, utsname, message, objects in fields,
	//     and objects in l.defaults excluding conflicting keys.
	var nFields uint64
	nFields += 4
	for k := range fields {
		if !ReservedKey(k) {
			nFields++
		}
	}
	for k := range l.defaults {
		if ReservedKey(k) {
			continue
		}
		if _, ok := fields[k]; ok {
			continue
		}
		nFields++
	}
	if nFields > math.MaxUint16 {
		return nil, ErrTooLarge
	}

	if nFields <= 15 {
		b = append(b, byte(mpFixMap+nFields))
	} else {
		b = append(b, byte(mpMap16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(nFields))
	}

	// logged_at
	b, err = appendMsgpack(b, FnLoggedAt)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, t.UnixNano()/1000)
	if err != nil {
		return nil, err
	}

	// severity
	b, err = appendMsgpack(b, FnSeverity)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, severity)
	if err != nil {
		return nil, err
	}

	// utsname
	b, err = appendMsgpack(b, FnUtsname)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, utsname)
	if err != nil {
		return nil, err
	}

	b, err = appendMsgpack(b, FnMessage)
	if err != nil {
		return nil, err
	}
	// message
	if len(b)+len(msg) > maxLogSize {
		return nil, ErrTooLarge
	}
	b, err = appendMsgpack(b, msg)
	if err != nil {
		return nil, err
	}

	// fields
	for k, v := range fields {
		if ReservedKey(k) {
			continue
		}
		if len(b)+len(k) > maxLogSize {
			return nil, ErrTooLarge
		}
		b, err = appendMsgpack(b, k)
		if err != nil {
			return nil, err
		}

		b, err = appendMsgpack(b, v)
		if err != nil {
			return nil, err
		}
	}

	// defaults
	for k, v := range l.Defaults() {
		if ReservedKey(k) {
			continue
		}
		if _, ok := fields[k]; ok {
			continue
		}
		if len(b)+len(k) > maxLogSize {
			return nil, ErrTooLarge
		}
		b, err = appendMsgpack(b, k)
		if err != nil {
			return nil, err
		}

		b, err = appendMsgpack(b, v)
		if err != nil {
			return nil, err
		}
	}

	return b, nil
}
<commit_msg>Fix for 32bit int.<commit_after>package log

import (
	"encoding/binary"
	"math"
	"time"
)

// MessagePack type tags.
// Only tags used in this code are defined.
const (
	mpNil      = 0xc0
	mpFalse    = 0xc2
	mpTrue     = 0xc3
	mpInt16    = 0xd1
	mpInt32    = 0xd2
	mpInt64    = 0xd3
	mpFixStr   = 0xa0
	mpStr8     = 0xd9
	mpStr16    = 0xda
	mpStr32    = 0xdb
	mpBin8     = 0xc4
	mpBin16    = 0xc5
	mpBin32    = 0xc6
	mpFixArray = 0x90
	mpArray16  = 0xdc
	mpArray32  = 0xdd
	mpFixMap   = 0x80
	mpMap16    = 0xde
)

func appendMsgpackInt64(b []byte, n int64) []byte {
	switch {
	case 0 <= n && n <= 127:
		return append(b, byte(n))
	case math.MinInt16 <= n && n <= math.MaxInt16:
		b = append(b, mpInt16, 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(n))
		return b
	case math.MinInt32 <= n && n <= math.MaxInt32:
		b = append(b, mpInt32, 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(n))
		return b
	default:
		b = append(b, mpInt64, 0, 0, 0, 0, 0, 0, 0, 0)
		binary.BigEndian.PutUint64(b[len(b)-8:], uint64(n))
		return b
	}
}

func appendMsgpackString(b []byte, s string) ([]byte, error) {
	switch {
	case len(s) >= maxLogSize:
		return nil, ErrTooLarge
	case len(s) <= 31:
		b = append(b, byte(mpFixStr+len(s)))
	case len(s) <= math.MaxUint8:
		b = append(b, byte(mpStr8))
		b = append(b, byte(len(s)))
	case len(s) <= math.MaxUint16:
		b = append(b, byte(mpStr16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(len(s)))
	case uint32(len(s)) <= math.MaxUint32:
		b = append(b, byte(mpStr32), 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(len(s)))
	}
	return append(b, s...), nil
}

func appendMsgpackArray(b []byte, length int) ([]byte, error) {
	switch {
	case length <= 15:
		return append(b, byte(mpFixArray+length)), nil
	case length <= math.MaxUint16:
		b = append(b, byte(mpArray16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(length))
		return b, nil
	case uint32(length) <= math.MaxUint32:
		b = append(b, byte(mpArray32), 0, 0, 0, 0)
		binary.BigEndian.PutUint32(b[len(b)-4:], uint32(length))
		return b, nil
	default:
		return nil, ErrTooLarge
	}
}

func appendMsgpack(b []byte, v interface{}) ([]byte, error) {
	switch t := v.(type) {
	case nil:
		return append(b, mpNil), nil
	case bool:
		if t {
			return append(b, mpTrue), nil
		}
		return append(b, mpFalse), nil
	case int:
		return appendMsgpackInt64(b, int64(t)), nil
	case int64:
		return appendMsgpackInt64(b, t), nil
	case time.Time:
		return appendMsgpackInt64(b, t.UnixNano()/1000), nil
	case string:
		return appendMsgpackString(b, t)
	case []byte:
		switch {
		case len(t) >= maxLogSize:
			return nil, ErrTooLarge
		case len(t) <= math.MaxUint8:
			b = append(b, byte(mpBin8))
			b = append(b, byte(len(t)))
		case len(t) <= math.MaxUint16:
			b = append(b, byte(mpBin16), 0, 0)
			binary.BigEndian.PutUint16(b[len(b)-2:], uint16(len(t)))
		case uint32(len(t)) <= math.MaxUint32:
			b = append(b, byte(mpBin32), 0, 0, 0, 0)
			binary.BigEndian.PutUint32(b[len(b)-4:], uint32(len(t)))
		}
		return append(b, t...), nil
	case []int:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, n := range t {
			b = appendMsgpackInt64(b, int64(n))
		}
		return b, nil
	case []int64:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, n := range t {
			b = appendMsgpackInt64(b, n)
		}
		return b, nil
	case []string:
		b, err := appendMsgpackArray(b, len(t))
		if err != nil {
			return nil, err
		}
		for _, s := range t {
			b, err = appendMsgpackString(b, s)
			if err != nil {
				return nil, err
			}
		}
		return b, nil
	default:
		return nil, ErrInvalidData
	}
}

// MsgPack implements Formatter for msgpack format.
//
// https://github.com/msgpack/msgpack/blob/master/spec.md
type MsgPack struct{}

// Format implements Formatter.Format.
func (m MsgPack) Format(b []byte, l *Logger, t time.Time, severity int, msg string,
	fields map[string]interface{}) ([]byte, error) {
	b = append(b, byte(mpFixArray+3))
	b, err := appendMsgpack(b, l.Topic())
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, t.Unix())
	if err != nil {
		return nil, err
	}

	// the log record consists of these objects:
	//     logged_at, severity, utsname, message, objects in fields,
	//     and objects in l.defaults excluding conflicting keys.
	var nFields uint64
	nFields += 4
	for k := range fields {
		if !ReservedKey(k) {
			nFields++
		}
	}
	for k := range l.defaults {
		if ReservedKey(k) {
			continue
		}
		if _, ok := fields[k]; ok {
			continue
		}
		nFields++
	}
	if nFields > math.MaxUint16 {
		return nil, ErrTooLarge
	}

	if nFields <= 15 {
		b = append(b, byte(mpFixMap+nFields))
	} else {
		b = append(b, byte(mpMap16), 0, 0)
		binary.BigEndian.PutUint16(b[len(b)-2:], uint16(nFields))
	}

	// logged_at
	b, err = appendMsgpack(b, FnLoggedAt)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, t.UnixNano()/1000)
	if err != nil {
		return nil, err
	}

	// severity
	b, err = appendMsgpack(b, FnSeverity)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, severity)
	if err != nil {
		return nil, err
	}

	// utsname
	b, err = appendMsgpack(b, FnUtsname)
	if err != nil {
		return nil, err
	}
	b, err = appendMsgpack(b, utsname)
	if err != nil {
		return nil, err
	}

	b, err = appendMsgpack(b, FnMessage)
	if err != nil {
		return nil, err
	}
	// message
	if len(b)+len(msg) > maxLogSize {
		return nil, ErrTooLarge
	}
	b, err = appendMsgpack(b, msg)
	if err != nil {
		return nil, err
	}

	// fields
	for k, v := range fields {
		if ReservedKey(k) {
			continue
		}
		if len(b)+len(k) > maxLogSize {
			return nil, ErrTooLarge
		}
		b, err = appendMsgpack(b, k)
		if err != nil {
			return nil, err
		}

		b, err = appendMsgpack(b, v)
		if err != nil {
			return nil, err
		}
	}

	// defaults
	for k, v := range l.Defaults() {
		if ReservedKey(k) {
			continue
		}
		if _, ok := fields[k]; ok {
			continue
		}
		if len(b)+len(k) > maxLogSize {
			return nil, ErrTooLarge
		}
		b, err = appendMsgpack(b, k)
		if err != nil {
			return nil, err
		}

		b, err = appendMsgpack(b, v)
		if err != nil {
			return nil, err
		}
	}

	return b, nil
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru 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 deploy

import (
	"bytes"
	"fmt"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/repository"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestDeploy(c *gocheck.C) {
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte("cloned"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, w)
	c.Assert(err, gocheck.IsNil)
	c.Assert(app.Commands, gocheck.DeepEquals, []string{"restart"})
	c.Assert(provisioner.InstalledDeps(app), gocheck.Equals, 1)
	cloneCommand := "git clone git://tsuruhost.com/cribcaged.git test/dir --depth 1"
	c.Assert(provisioner.GetCmds(cloneCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestDeployLogsActions(c *gocheck.C) {
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte(""))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, w)
	c.Assert(err, gocheck.IsNil)
	logs := w.String()
	expected := `
 ---> Tsuru receiving push

 ---> Replicating the application repository across units

 ---> Installing dependencies

 ---> Restarting application

 ---> Deploy done!

`
	c.Assert(logs, gocheck.Equals, expected)
}

func (s *S) TestCloneRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("something"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := clone(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "something")
	url := repository.ReadOnlyURL(app.GetName())
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("git clone %s %s --depth 1", url, path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCloneRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := clone(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestPullRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("pulled"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := pull(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "pulled")
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git pull origin master", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestPullRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := pull(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}
<commit_msg>deploy: fix build<commit_after>// Copyright 2013 tsuru 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 deploy

import (
	"bytes"
	"fmt"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/repository"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestDeploy(c *gocheck.C) {
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte("cloned"))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, w)
	c.Assert(err, gocheck.IsNil)
	c.Assert(app.Commands, gocheck.DeepEquals, []string{"restart"})
	c.Assert(provisioner.InstalledDeps(app), gocheck.Equals, 1)
	cloneCommand := "git clone git://tsuruhost.com/cribcaged.git test/dir --depth 1"
	c.Assert(provisioner.GetCmds(cloneCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestDeployLogsActions(c *gocheck.C) {
	provisioner := testing.NewFakeProvisioner()
	provisioner.PrepareOutput([]byte(""))
	app := testing.NewFakeApp("cribcaged", "python", 1)
	provisioner.Provision(app)
	w := &bytes.Buffer{}
	err := Git(provisioner, app, w)
	c.Assert(err, gocheck.IsNil)
	logs := w.String()
	expected := `
 ---> Tsuru receiving push

 ---> Replicating the application repository across units

 ---> Installing dependencies

 ---> Restarting application

 ---> Deploy done!

`
	c.Assert(logs, gocheck.Equals, expected)
}

func (s *S) TestCloneRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("something"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := clone(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "something")
	url := repository.ReadOnlyURL(app.GetName())
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("git clone %s %s --depth 1", url, path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestCloneRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := clone(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}

func (s *S) TestPullRepository(c *gocheck.C) {
	p := testing.NewFakeProvisioner()
	p.PrepareOutput([]byte("pulled"))
	app := testing.NewFakeApp("your", "python", 1)
	out, err := pull(p, app)
	c.Assert(err, gocheck.IsNil)
	c.Assert(string(out), gocheck.Equals, "pulled")
	path, _ := repository.GetPath()
	expectedCommand := fmt.Sprintf("cd %s && git pull origin master", path)
	c.Assert(p.GetCmds(expectedCommand, app), gocheck.HasLen, 1)
}

func (s *S) TestPullRepositoryUndefinedPath(c *gocheck.C) {
	old, _ := config.Get("git:unit-repo")
	config.Unset("git:unit-repo")
	defer config.Set("git:unit-repo", old)
	_, err := pull(nil, nil)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, `Tsuru is misconfigured: key "git:unit-repo" not found`)
}
<|endoftext|>


<commit_before>package depsync

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/micromdm/dep"
	"github.com/micromdm/micromdm/pubsub"
)

const (
	SyncTopic    = "mdm.DepSync"
	ConfigBucket = "mdm.DEPConfig"
)

type Syncer interface {
	privateDEPSyncer() bool
}

type watcher struct {
	client    dep.Client
	publisher pubsub.Publisher
	conf      *config
}

type cursor struct {
	Value     string    `json:"value"`
	CreatedAt time.Time `json:"created_at"`
}

// A cursor is valid for a week.
func (c cursor) Valid() bool {
	expiration := time.Now().Add(24 * 7 * time.Hour)
	if c.CreatedAt.After(expiration) {
		return false
	}
	return true
}

func New(client dep.Client, pub pubsub.Publisher, db *bolt.DB) (Syncer, error) {
	conf, err := LoadConfig(db)
	if err != nil {
		return nil, err
	}
	if conf.Cursor.Valid() {
		fmt.Printf("loaded dep config with cursor: %s\n", conf.Cursor.Value)
	} else {
		conf.Cursor.Value = ""
	}
	sync := &watcher{
		publisher: pub,
		client:    client,
		conf:      conf,
	}

	saveCursor := func() {
		if err := conf.Save(); err != nil {
			log.Printf("saving cursor %s\n", err)
			return
		}
		log.Printf("saved DEP cursor at value %s\n", conf.Cursor.Value)
	}

	go func() {
		defer saveCursor()
		if err := sync.Run(); err != nil {
			log.Println("DEP watcher failed: ", err)
		}
	}()
	return sync, nil
}

// TODO this is private temporarily until the interface can be defined
func (w *watcher) privateDEPSyncer() bool {
	return true
}

// TODO this needs to be a proper error in the micromdm/dep package.
func isCursorExhausted(err error) bool {
	return strings.Contains(err.Error(), "EXHAUSTED_CURSOR")
}

func (w *watcher) Run() error {
	ticker := time.NewTicker(30 * time.Minute).C
FETCH:
	for {
		resp, err := w.client.FetchDevices(dep.Limit(100), dep.Cursor(w.conf.Cursor.Value))
		if err != nil && isCursorExhausted(err) {
			goto SYNC
		} else if err != nil {
			return err
		}
		fmt.Printf("more=%v, cursor=%s, fetched=%v\n", resp.MoreToFollow, resp.Cursor, resp.FetchedUntil)
		w.conf.Cursor.Value = resp.Cursor
		e := NewEvent(resp.Devices)
		data, err := MarshalEvent(e)
		if err != nil {
			return err
		}
		if err := w.publisher.Publish(SyncTopic, data); err != nil {
			return err
		}
		if resp.MoreToFollow {
			break FETCH
		}
	}

SYNC:
	for {
		resp, err := w.client.SyncDevices(w.conf.Cursor.Value, dep.Cursor(w.conf.Cursor.Value))
		if err != nil {
			return err
		}
		if len(resp.Devices) != 0 {
			fmt.Printf("more=%v, cursor=%s, synced=%v\n", resp.MoreToFollow, resp.Cursor, resp.FetchedUntil)
		}
		// TODO handle sync response here.
		<-ticker
	}
	return nil
}
<commit_msg>save DEP cursor during fetch/sync ops (#159)<commit_after>package depsync

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/micromdm/dep"
	"github.com/micromdm/micromdm/pubsub"
	"github.com/pkg/errors"
)

const (
	SyncTopic    = "mdm.DepSync"
	ConfigBucket = "mdm.DEPConfig"
)

type Syncer interface {
	privateDEPSyncer() bool
}

type watcher struct {
	client    dep.Client
	publisher pubsub.Publisher
	conf      *config
}

type cursor struct {
	Value     string    `json:"value"`
	CreatedAt time.Time `json:"created_at"`
}

// A cursor is valid for a week.
func (c cursor) Valid() bool {
	expiration := time.Now().Add(24 * 7 * time.Hour)
	if c.CreatedAt.After(expiration) {
		return false
	}
	return true
}

func New(client dep.Client, pub pubsub.Publisher, db *bolt.DB) (Syncer, error) {
	conf, err := LoadConfig(db)
	if err != nil {
		return nil, err
	}
	if conf.Cursor.Valid() {
		fmt.Printf("loaded dep config with cursor: %s\n", conf.Cursor.Value)
	} else {
		conf.Cursor.Value = ""
	}
	sync := &watcher{
		publisher: pub,
		client:    client,
		conf:      conf,
	}

	saveCursor := func() {
		if err := conf.Save(); err != nil {
			log.Printf("saving cursor %s\n", err)
			return
		}
		log.Printf("saved DEP cursor at value %s\n", conf.Cursor.Value)
	}

	go func() {
		defer saveCursor()
		if err := sync.Run(); err != nil {
			log.Println("DEP watcher failed: ", err)
		}
	}()
	return sync, nil
}

// TODO this is private temporarily until the interface can be defined
func (w *watcher) privateDEPSyncer() bool {
	return true
}

// TODO this needs to be a proper error in the micromdm/dep package.
func isCursorExhausted(err error) bool {
	return strings.Contains(err.Error(), "EXHAUSTED_CURSOR")
}

func isCursorExpired(err error) bool {
	return strings.Contains(err.Error(), "EXPIRED_CURSOR")
}

func (w *watcher) Run() error {
	ticker := time.NewTicker(30 * time.Minute).C
FETCH:
	for {
		resp, err := w.client.FetchDevices(dep.Limit(100), dep.Cursor(w.conf.Cursor.Value))
		if err != nil && isCursorExhausted(err) {
			goto SYNC
		} else if err != nil {
			return err
		}
		fmt.Printf("more=%v, cursor=%s, fetched=%v\n", resp.MoreToFollow, resp.Cursor, resp.FetchedUntil)
		w.conf.Cursor = cursor{Value: resp.Cursor, CreatedAt: time.Now()}
		if err := w.conf.Save(); err != nil {
			return errors.Wrap(err, "saving cursor from fetch")
		}
		e := NewEvent(resp.Devices)
		data, err := MarshalEvent(e)
		if err != nil {
			return err
		}
		if err := w.publisher.Publish(SyncTopic, data); err != nil {
			return err
		}
		if !resp.MoreToFollow {
			goto SYNC
		}
	}

SYNC:
	for {
		resp, err := w.client.SyncDevices(w.conf.Cursor.Value, dep.Cursor(w.conf.Cursor.Value))
		if err != nil && isCursorExpired(err) {
			w.conf.Cursor.Value = ""
			goto FETCH
		} else if err != nil {
			return err
		}
		if len(resp.Devices) != 0 {
			fmt.Printf("more=%v, cursor=%s, synced=%v\n", resp.MoreToFollow, resp.Cursor, resp.FetchedUntil)
		}
		w.conf.Cursor = cursor{Value: resp.Cursor, CreatedAt: time.Now()}
		if err := w.conf.Save(); err != nil {
			return errors.Wrap(err, "saving cursor from sync")
		}

		// TODO handle sync response here.
		<-ticker
	}
}
<|endoftext|>