<commit_before>package irc

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

var messageTests = []struct {
	// Message parsing
	Prefix, Cmd string
	Params      []string

	// Tag parsing
	Tags Tags

	// Prefix parsing
	Name, User, Host string

	// Total output
	Expect   string
	ExpectIn []string
	Err      error

	// FromChannel
	FromChan bool
}{
	{
		Err: ErrZeroLengthMessage,
	},
	{
		Expect: ":asd  :",
		Err:    ErrMissingCommand,
	},
	{
		Expect: ":A",
		Err:    ErrMissingDataAfterPrefix,
	},
	{
		Expect: "@A",
		Err:    ErrMissingDataAfterTags,
	},
	{
		Prefix: "server.kevlar.net",
		Cmd:    "PING",
		Params: []string{},

		Name: "server.kevlar.net",

		Expect: ":server.kevlar.net PING\n",
	},
	{
		Prefix: "server.kevlar.net",
		Cmd:    "NOTICE",
		Params: []string{"user", "*** This is a test"},

		Name: "server.kevlar.net",

		Expect: ":server.kevlar.net NOTICE user :*** This is a test\n",
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"#somewhere", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG #somewhere :*** This is a test\n",
		FromChan: true,
	},
	{
		Prefix: "freenode",
		Cmd:    "005",
		Params: []string{"starkbot", "CHANLIMIT=#:120", "MORE", "are supported by this server"},

		Name: "freenode",

		Expect: ":freenode 005 starkbot CHANLIMIT=#:120 MORE :are supported by this server\n",
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"&somewhere", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG &somewhere :*** This is a test\n",
		FromChan: true,
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"belak", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect: ":belakA!belakB@a.host.com PRIVMSG belak :*** This is a test\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Params: []string{"C"},

		Name: "A",

		Expect: ":A B C\n",
	},
	{
		Prefix: "A@B",
		Cmd:    "C",
		Params: []string{"D"},

		Name: "A",
		Host: "B",

		Expect: ":A@B C D\n",
	},
	{
		Cmd:    "B",
		Params: []string{"C"},
		Expect: "B C\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Params: []string{"C", "D"},

		Name: "A",

		Expect: ":A B C D\n",
	},
	{
		Cmd:    "A",
		Params: []string{""},

		Expect: "A :\n",
	},
	{
		Tags: Tags{
			"tag": "value",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=value A\n",
	},
	{
		Tags: Tags{
			"tag": "\n",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=\\n A\n",
	},
	{
		Tags: Tags{
			"tag": "\\",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=\\ A\n",
		ExpectIn: []string{"@tag=\\\\ A\n"},
	},
	{
		Tags: Tags{
			"tag": ";",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=\\: A\n",
	},
	{
		Tags: Tags{
			"tag": "",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag A\n",
	},
	{
		Tags: Tags{
			"tag": "\\&",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=\\& A\n",
		ExpectIn: []string{"@tag=\\\\& A\n"},
	},
	{
		Tags: Tags{
			"tag":  "x",
			"tag2": "asd",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=x;tag2=asd A\n",
		ExpectIn: []string{"@tag=x;tag2=asd A\n", "@tag2=asd;tag=x A\n"},
	},
	{
		Tags: Tags{
			"tag": "; \\\r\n",
		},

		Params: []string{},
		Cmd:    "A",
		Expect: "@tag=\\:\\s\\\\\\r\\n A\n",
	},
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			assert.Panics(t, func() {
				MustParseMessage(test.Expect)
			}, "%d. Didn't get expected panic", i)
		} else {
			assert.NotPanics(t, func() {
				MustParseMessage(test.Expect)
			}, "%d. Got unexpected panic", i)
		}
	}
}

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

	for i, test := range messageTests {
		m, err := ParseMessage(test.Expect)
		if test.Err != nil {
			assert.Equal(t, test.Err, err, "%d. Didn't get correct error for invalid message.", i)
		} else {
			assert.NotNil(t, m, "%d. Got nil for valid message.", i)
		}

		if m == nil {
			continue
		}

		assert.Equal(t, test.Cmd, m.Command, "%d. Command doesn't match.", i)
		assert.EqualValues(t, test.Params, m.Params, "%d. Params don't match.", i)
	}
}

func BenchmarkParseMessage(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseMessage(messageTests[i%len(messageTests)].Prefix)
	}
}

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

	for i, test := range messageTests {
		pi := ParsePrefix(test.Prefix)
		if pi == nil {
			t.Errorf("%d. Got nil for valid identity", i)
			continue
		}

		assert.EqualValues(t, &Prefix{
			Name: test.Name,
			User: test.User,
			Host: test.Host,
		}, pi, "%d. Identity did not match", i)
	}
}

func BenchmarkParsePrefix(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParsePrefix(messageTests[i%len(messageTests)].Expect)
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		tr := m.Trailing()
		if len(test.Params) < 1 {
			assert.Equal(t, "", tr, "%d. Expected empty trailing", i)
		} else {
			assert.Equal(t, test.Params[len(test.Params)-1], tr, "%d. Expected matching traling", i)
		}
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		assert.Equal(t, test.FromChan, m.FromChannel(), "%d. Wrong FromChannel value", i)
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)

		c := m.Copy()
		assert.EqualValues(t, m, c, "%d. Copied values are not equal", i)

		if len(m.Tags) > 0 {
			c = m.Copy()
			for k := range c.Tags {
				c.Tags[k] += "junk"
			}

			assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with modified tags should not match", i)
		}

		c = m.Copy()
		c.Prefix.Name += "junk"
		assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with modified identity should not match", i)

		c = m.Copy()
		c.Params = append(c.Params, "junk")
		assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with additional params should not match", i)
	}

	// The message itself doesn't matter, we just need to make sure we
	// don't error if the user does something crazy and makes Params
	// nil.
	m, _ := ParseMessage("PING :hello world")
	m.Prefix = nil
	c := m.Copy()

	assert.EqualValues(t, m, c, "nil prefix copy failed")
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		if test.ExpectIn != nil {
			assert.Contains(t, test.ExpectIn, m.String()+"\n", "%d. Message Stringification failed", i)
		} else {
			assert.Equal(t, test.Expect, m.String()+"\n", "%d. Message Stringification failed", i)
		}
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil || test.Tags == nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		assert.EqualValues(t, test.Tags, m.Tags, "%d. Tag parsing failed", i)

		// Ensure we have all the tags we expected.
		for k, v := range test.Tags {
			tag, ok := m.GetTag(k)
			assert.True(t, ok, "%d. Missing tag %q", i, k)
			assert.EqualValues(t, v, tag, "%d. Wrong tag value", i)
		}

		assert.EqualValues(t, test.Tags, m.Tags, "%d. Tags don't match", i)
	}
}
<commit_msg>Add comments for all test messages<commit_after>package irc

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

var messageTests = []struct {
	// Message parsing
	Prefix, Cmd string
	Params      []string

	// Tag parsing
	Tags Tags

	// Prefix parsing
	Name, User, Host string

	// Total output
	Expect   string
	ExpectIn []string
	Err      error

	// FromChannel
	FromChan bool
}{
	{ // Empty message should error
		Err: ErrZeroLengthMessage,
	},
	{ // Make sure we've got a command
		Expect: ":asd  :",
		Err:    ErrMissingCommand,
	},
	{ // Need data after tags
		Expect: "@A",
		Err:    ErrMissingDataAfterTags,
	},
	{ // Need data after prefix
		Expect: ":A",
		Err:    ErrMissingDataAfterPrefix,
	},
	{ // Basic prefix test
		Prefix: "server.kevlar.net",
		Cmd:    "PING",
		Params: []string{},

		Name: "server.kevlar.net",

		Expect: ":server.kevlar.net PING\n",
	},
	{ // Trailing argument test
		Prefix: "server.kevlar.net",
		Cmd:    "NOTICE",
		Params: []string{"user", "*** This is a test"},

		Name: "server.kevlar.net",

		Expect: ":server.kevlar.net NOTICE user :*** This is a test\n",
	},
	{ // Full prefix test
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"#somewhere", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG #somewhere :*** This is a test\n",
		FromChan: true,
	},
	{ // Test : in the middle of a param
		Prefix: "freenode",
		Cmd:    "005",
		Params: []string{"starkbot", "CHANLIMIT=#:120", "MORE", "are supported by this server"},

		Name: "freenode",

		Expect: ":freenode 005 starkbot CHANLIMIT=#:120 MORE :are supported by this server\n",
	},
	{ // Test FromChannel on a different channel prefix
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"&somewhere", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG &somewhere :*** This is a test\n",
		FromChan: true,
	},
	{ // Test FromChannel on a single user
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Params: []string{"belak", "*** This is a test"},

		Name: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect: ":belakA!belakB@a.host.com PRIVMSG belak :*** This is a test\n",
	},
	{ // Simple message
		Cmd:    "B",
		Params: []string{"C"},
		Expect: "B C\n",
	},
	{ // Simple message with tags
		Prefix: "A@B",
		Cmd:    "C",
		Params: []string{"D"},

		Name: "A",
		Host: "B",

		Expect: ":A@B C D\n",
	},
	{ // Simple message with prefix
		Prefix: "A",
		Cmd:    "B",
		Params: []string{"C"},

		Name: "A",

		Expect: ":A B C\n",
	},
	{ // Message with prefix and multiple params
		Prefix: "A",
		Cmd:    "B",
		Params: []string{"C", "D"},

		Name: "A",

		Expect: ":A B C D\n",
	},
	{ // Message with empty trailing
		Cmd:    "A",
		Params: []string{""},

		Expect: "A :\n",
	},
	{ // Test basic tag parsing
		Tags: Tags{
			"tag": "value",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=value A\n",
	},
	{ // Escaped \n in tag
		Tags: Tags{
			"tag": "\n",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=\\n A\n",
	},
	{ // Escaped \ in tag
		Tags: Tags{
			"tag": "\\",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=\\ A\n",
		ExpectIn: []string{"@tag=\\\\ A\n"},
	},
	{ // Escaped ; in tag
		Tags: Tags{
			"tag": ";",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag=\\: A\n",
	},
	{ // Empty tag
		Tags: Tags{
			"tag": "",
		},

		Params: []string{},
		Cmd:    "A",

		Expect: "@tag A\n",
	},
	{ // Escaped & in tag
		Tags: Tags{
			"tag": "\\&",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=\\& A\n",
		ExpectIn: []string{"@tag=\\\\& A\n"},
	},
	{ // Multiple simple tags
		Tags: Tags{
			"tag":  "x",
			"tag2": "asd",
		},

		Params: []string{},
		Cmd:    "A",

		Expect:   "@tag=x;tag2=asd A\n",
		ExpectIn: []string{"@tag=x;tag2=asd A\n", "@tag2=asd;tag=x A\n"},
	},
	{ // Complicated escaped tag
		Tags: Tags{
			"tag": "; \\\r\n",
		},

		Params: []string{},
		Cmd:    "A",
		Expect: "@tag=\\:\\s\\\\\\r\\n A\n",
	},
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			assert.Panics(t, func() {
				MustParseMessage(test.Expect)
			}, "%d. Didn't get expected panic", i)
		} else {
			assert.NotPanics(t, func() {
				MustParseMessage(test.Expect)
			}, "%d. Got unexpected panic", i)
		}
	}
}

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

	for i, test := range messageTests {
		m, err := ParseMessage(test.Expect)
		if test.Err != nil {
			assert.Equal(t, test.Err, err, "%d. Didn't get correct error for invalid message.", i)
		} else {
			assert.NotNil(t, m, "%d. Got nil for valid message.", i)
		}

		if m == nil {
			continue
		}

		assert.Equal(t, test.Cmd, m.Command, "%d. Command doesn't match.", i)
		assert.EqualValues(t, test.Params, m.Params, "%d. Params don't match.", i)
	}
}

func BenchmarkParseMessage(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseMessage(messageTests[i%len(messageTests)].Prefix)
	}
}

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

	for i, test := range messageTests {
		pi := ParsePrefix(test.Prefix)
		if pi == nil {
			t.Errorf("%d. Got nil for valid identity", i)
			continue
		}

		assert.EqualValues(t, &Prefix{
			Name: test.Name,
			User: test.User,
			Host: test.Host,
		}, pi, "%d. Identity did not match", i)
	}
}

func BenchmarkParsePrefix(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParsePrefix(messageTests[i%len(messageTests)].Expect)
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		tr := m.Trailing()
		if len(test.Params) < 1 {
			assert.Equal(t, "", tr, "%d. Expected empty trailing", i)
		} else {
			assert.Equal(t, test.Params[len(test.Params)-1], tr, "%d. Expected matching traling", i)
		}
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		assert.Equal(t, test.FromChan, m.FromChannel(), "%d. Wrong FromChannel value", i)
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)

		c := m.Copy()
		assert.EqualValues(t, m, c, "%d. Copied values are not equal", i)

		if len(m.Tags) > 0 {
			c = m.Copy()
			for k := range c.Tags {
				c.Tags[k] += "junk"
			}

			assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with modified tags should not match", i)
		}

		c = m.Copy()
		c.Prefix.Name += "junk"
		assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with modified identity should not match", i)

		c = m.Copy()
		c.Params = append(c.Params, "junk")
		assert.False(t, assert.ObjectsAreEqualValues(m, c), "%d. Copied with additional params should not match", i)
	}

	// The message itself doesn't matter, we just need to make sure we
	// don't error if the user does something crazy and makes Params
	// nil.
	m, _ := ParseMessage("PING :hello world")
	m.Prefix = nil
	c := m.Copy()

	assert.EqualValues(t, m, c, "nil prefix copy failed")
}

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

	for i, test := range messageTests {
		if test.Err != nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		if test.ExpectIn != nil {
			assert.Contains(t, test.ExpectIn, m.String()+"\n", "%d. Message Stringification failed", i)
		} else {
			assert.Equal(t, test.Expect, m.String()+"\n", "%d. Message Stringification failed", i)
		}
	}
}

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

	for i, test := range messageTests {
		if test.Err != nil || test.Tags == nil {
			continue
		}

		m, _ := ParseMessage(test.Expect)
		assert.EqualValues(t, test.Tags, m.Tags, "%d. Tag parsing failed", i)

		// Ensure we have all the tags we expected.
		for k, v := range test.Tags {
			tag, ok := m.GetTag(k)
			assert.True(t, ok, "%d. Missing tag %q", i, k)
			assert.EqualValues(t, v, tag, "%d. Wrong tag value", i)
		}

		assert.EqualValues(t, test.Tags, m.Tags, "%d. Tags don't match", i)
	}
}
<|endoftext|>


<commit_before>// Test suite for vfs

package vfs

import (
	"io"
	"os"
	"testing"

	_ "github.com/ncw/rclone/backend/all" // import all the backends
	"github.com/ncw/rclone/fstest"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// Some times used in the tests
var (
	t1 = fstest.Time("2001-02-03T04:05:06.499999999Z")
	t2 = fstest.Time("2011-12-25T12:59:59.123456789Z")
	t3 = fstest.Time("2011-12-30T12:59:59.000000000Z")
)

// TestMain drives the tests
func TestMain(m *testing.M) {
	fstest.TestMain(m)
}

// Check baseHandle performs as advertised
func TestVFSbaseHandle(t *testing.T) {
	fh := baseHandle{}

	err := fh.Chdir()
	assert.Equal(t, ENOSYS, err)

	err = fh.Chmod(0)
	assert.Equal(t, ENOSYS, err)

	err = fh.Chown(0, 0)
	assert.Equal(t, ENOSYS, err)

	err = fh.Close()
	assert.Equal(t, ENOSYS, err)

	fd := fh.Fd()
	assert.Equal(t, uintptr(0), fd)

	name := fh.Name()
	assert.Equal(t, "", name)

	_, err = fh.Read(nil)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.ReadAt(nil, 0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Readdir(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Readdirnames(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Seek(0, io.SeekStart)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Stat()
	assert.Equal(t, ENOSYS, err)

	err = fh.Sync()
	assert.Equal(t, nil, err)

	err = fh.Truncate(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Write(nil)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.WriteAt(nil, 0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.WriteString("")
	assert.Equal(t, ENOSYS, err)

	err = fh.Flush()
	assert.Equal(t, ENOSYS, err)

	err = fh.Release()
	assert.Equal(t, ENOSYS, err)

	node := fh.Node()
	assert.Nil(t, node)
}

// TestNew sees if the New command works properly
func TestVFSNew(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()

	// Check making a VFS with nil options
	vfs := New(r.Fremote, nil)
	var defaultOpt = DefaultOpt
	defaultOpt.DirPerms |= os.ModeDir
	assert.Equal(t, vfs.Opt, defaultOpt)
	assert.Equal(t, vfs.f, r.Fremote)

	// Check the initialisation
	var opt = DefaultOpt
	opt.DirPerms = 0777
	opt.FilePerms = 0666
	opt.Umask = 0002
	vfs = New(r.Fremote, &opt)
	assert.Equal(t, os.FileMode(0775)|os.ModeDir, vfs.Opt.DirPerms)
	assert.Equal(t, os.FileMode(0664), vfs.Opt.FilePerms)
}

// TestRoot checks root directory is present and correct
func TestVFSRoot(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	root, err := vfs.Root()
	require.NoError(t, err)
	assert.Equal(t, vfs.root, root)
	assert.True(t, root.IsDir())
	assert.Equal(t, vfs.Opt.DirPerms.Perm(), root.Mode().Perm())
}

func TestVFSStat(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	node, err := vfs.Stat("file1")
	require.NoError(t, err)
	assert.True(t, node.IsFile())
	assert.Equal(t, "file1", node.Name())

	node, err = vfs.Stat("dir")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "dir", node.Name())

	node, err = vfs.Stat("dir/file2")
	require.NoError(t, err)
	assert.True(t, node.IsFile())
	assert.Equal(t, "file2", node.Name())

	node, err = vfs.Stat("not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("dir/not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("not found/not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("file1/under a file")
	assert.Equal(t, os.ErrNotExist, err)
}

func TestVFSStatParent(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	node, leaf, err := vfs.StatParent("file1")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "/", node.Name())
	assert.Equal(t, "file1", leaf)

	node, leaf, err = vfs.StatParent("dir/file2")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "dir", node.Name())
	assert.Equal(t, "file2", leaf)

	node, leaf, err = vfs.StatParent("not found")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "/", node.Name())
	assert.Equal(t, "not found", leaf)

	_, _, err = vfs.StatParent("not found dir/not found")
	assert.Equal(t, os.ErrNotExist, err)

	_, _, err = vfs.StatParent("file1/under a file")
	assert.Equal(t, os.ErrExist, err)
}

func TestVFSOpenFile(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	fd, err := vfs.OpenFile("file1", os.O_RDONLY, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("dir", os.O_RDONLY, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_RDONLY, 0777)
	assert.Equal(t, os.ErrNotExist, err)
	assert.Nil(t, fd)

	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("not found/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
	assert.Equal(t, os.ErrNotExist, err)
	assert.Nil(t, fd)
}

func TestVFSRename(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1)

	err := vfs.Rename("dir/file2", "dir/file1")
	require.NoError(t, err)
	file1.Path = "dir/file1"
	fstest.CheckItems(t, r.Fremote, file1)

	err = vfs.Rename("dir/file1", "file0")
	require.NoError(t, err)
	file1.Path = "file0"
	fstest.CheckItems(t, r.Fremote, file1)

	err = vfs.Rename("not found/file0", "file0")
	assert.Equal(t, os.ErrNotExist, err)

	err = vfs.Rename("file0", "not found/file0")
	assert.Equal(t, os.ErrNotExist, err)
}

func TestVFSStatfs(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	// pre-conditions
	assert.Nil(t, vfs.usage)
	assert.True(t, vfs.usageTime.IsZero())

	// read
	total, used, free := vfs.Statfs()
	require.NotNil(t, vfs.usage)
	assert.False(t, vfs.usageTime.IsZero())
	if vfs.usage.Total != nil {
		assert.Equal(t, *vfs.usage.Total, total)
	} else {
		assert.Equal(t, -1, total)
	}
	if vfs.usage.Free != nil {
		assert.Equal(t, *vfs.usage.Free, free)
	} else {
		assert.Equal(t, -1, free)
	}
	if vfs.usage.Used != nil {
		assert.Equal(t, *vfs.usage.Used, used)
	} else {
		assert.Equal(t, -1, used)
	}

	// read cached
	oldUsage := vfs.usage
	oldTime := vfs.usageTime
	total2, used2, free2 := vfs.Statfs()
	assert.Equal(t, oldUsage, vfs.usage)
	assert.Equal(t, total, total2)
	assert.Equal(t, used, used2)
	assert.Equal(t, free, free2)
	assert.Equal(t, oldTime, vfs.usageTime)
}
<commit_msg>vfs: make tests work on remotes which don't support About<commit_after>// Test suite for vfs

package vfs

import (
	"io"
	"os"
	"testing"

	_ "github.com/ncw/rclone/backend/all" // import all the backends
	"github.com/ncw/rclone/fstest"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// Some times used in the tests
var (
	t1 = fstest.Time("2001-02-03T04:05:06.499999999Z")
	t2 = fstest.Time("2011-12-25T12:59:59.123456789Z")
	t3 = fstest.Time("2011-12-30T12:59:59.000000000Z")
)

// TestMain drives the tests
func TestMain(m *testing.M) {
	fstest.TestMain(m)
}

// Check baseHandle performs as advertised
func TestVFSbaseHandle(t *testing.T) {
	fh := baseHandle{}

	err := fh.Chdir()
	assert.Equal(t, ENOSYS, err)

	err = fh.Chmod(0)
	assert.Equal(t, ENOSYS, err)

	err = fh.Chown(0, 0)
	assert.Equal(t, ENOSYS, err)

	err = fh.Close()
	assert.Equal(t, ENOSYS, err)

	fd := fh.Fd()
	assert.Equal(t, uintptr(0), fd)

	name := fh.Name()
	assert.Equal(t, "", name)

	_, err = fh.Read(nil)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.ReadAt(nil, 0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Readdir(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Readdirnames(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Seek(0, io.SeekStart)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Stat()
	assert.Equal(t, ENOSYS, err)

	err = fh.Sync()
	assert.Equal(t, nil, err)

	err = fh.Truncate(0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.Write(nil)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.WriteAt(nil, 0)
	assert.Equal(t, ENOSYS, err)

	_, err = fh.WriteString("")
	assert.Equal(t, ENOSYS, err)

	err = fh.Flush()
	assert.Equal(t, ENOSYS, err)

	err = fh.Release()
	assert.Equal(t, ENOSYS, err)

	node := fh.Node()
	assert.Nil(t, node)
}

// TestNew sees if the New command works properly
func TestVFSNew(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()

	// Check making a VFS with nil options
	vfs := New(r.Fremote, nil)
	var defaultOpt = DefaultOpt
	defaultOpt.DirPerms |= os.ModeDir
	assert.Equal(t, vfs.Opt, defaultOpt)
	assert.Equal(t, vfs.f, r.Fremote)

	// Check the initialisation
	var opt = DefaultOpt
	opt.DirPerms = 0777
	opt.FilePerms = 0666
	opt.Umask = 0002
	vfs = New(r.Fremote, &opt)
	assert.Equal(t, os.FileMode(0775)|os.ModeDir, vfs.Opt.DirPerms)
	assert.Equal(t, os.FileMode(0664), vfs.Opt.FilePerms)
}

// TestRoot checks root directory is present and correct
func TestVFSRoot(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	root, err := vfs.Root()
	require.NoError(t, err)
	assert.Equal(t, vfs.root, root)
	assert.True(t, root.IsDir())
	assert.Equal(t, vfs.Opt.DirPerms.Perm(), root.Mode().Perm())
}

func TestVFSStat(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	node, err := vfs.Stat("file1")
	require.NoError(t, err)
	assert.True(t, node.IsFile())
	assert.Equal(t, "file1", node.Name())

	node, err = vfs.Stat("dir")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "dir", node.Name())

	node, err = vfs.Stat("dir/file2")
	require.NoError(t, err)
	assert.True(t, node.IsFile())
	assert.Equal(t, "file2", node.Name())

	node, err = vfs.Stat("not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("dir/not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("not found/not found")
	assert.Equal(t, os.ErrNotExist, err)

	node, err = vfs.Stat("file1/under a file")
	assert.Equal(t, os.ErrNotExist, err)
}

func TestVFSStatParent(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	node, leaf, err := vfs.StatParent("file1")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "/", node.Name())
	assert.Equal(t, "file1", leaf)

	node, leaf, err = vfs.StatParent("dir/file2")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "dir", node.Name())
	assert.Equal(t, "file2", leaf)

	node, leaf, err = vfs.StatParent("not found")
	require.NoError(t, err)
	assert.True(t, node.IsDir())
	assert.Equal(t, "/", node.Name())
	assert.Equal(t, "not found", leaf)

	_, _, err = vfs.StatParent("not found dir/not found")
	assert.Equal(t, os.ErrNotExist, err)

	_, _, err = vfs.StatParent("file1/under a file")
	assert.Equal(t, os.ErrExist, err)
}

func TestVFSOpenFile(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("file1", "file1 contents", t1)
	file2 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1, file2)

	fd, err := vfs.OpenFile("file1", os.O_RDONLY, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("dir", os.O_RDONLY, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_RDONLY, 0777)
	assert.Equal(t, os.ErrNotExist, err)
	assert.Nil(t, fd)

	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
	require.NoError(t, err)
	assert.NotNil(t, fd)
	require.NoError(t, fd.Close())

	fd, err = vfs.OpenFile("not found/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
	assert.Equal(t, os.ErrNotExist, err)
	assert.Nil(t, fd)
}

func TestVFSRename(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	file1 := r.WriteObject("dir/file2", "file2 contents", t2)
	fstest.CheckItems(t, r.Fremote, file1)

	err := vfs.Rename("dir/file2", "dir/file1")
	require.NoError(t, err)
	file1.Path = "dir/file1"
	fstest.CheckItems(t, r.Fremote, file1)

	err = vfs.Rename("dir/file1", "file0")
	require.NoError(t, err)
	file1.Path = "file0"
	fstest.CheckItems(t, r.Fremote, file1)

	err = vfs.Rename("not found/file0", "file0")
	assert.Equal(t, os.ErrNotExist, err)

	err = vfs.Rename("file0", "not found/file0")
	assert.Equal(t, os.ErrNotExist, err)
}

func TestVFSStatfs(t *testing.T) {
	r := fstest.NewRun(t)
	defer r.Finalise()
	vfs := New(r.Fremote, nil)

	// pre-conditions
	assert.Nil(t, vfs.usage)
	assert.True(t, vfs.usageTime.IsZero())

	aboutSupported := r.Fremote.Features().About != nil

	// read
	total, used, free := vfs.Statfs()
	if !aboutSupported {
		assert.Equal(t, int64(-1), total)
		assert.Equal(t, int64(-1), free)
		assert.Equal(t, int64(-1), used)
		return // can't test anything else if About not supported
	}
	require.NotNil(t, vfs.usage)
	assert.False(t, vfs.usageTime.IsZero())
	if vfs.usage.Total != nil {
		assert.Equal(t, *vfs.usage.Total, total)
	} else {
		assert.Equal(t, int64(-1), total)
	}
	if vfs.usage.Free != nil {
		assert.Equal(t, *vfs.usage.Free, free)
	} else {
		assert.Equal(t, int64(-1), free)
	}
	if vfs.usage.Used != nil {
		assert.Equal(t, *vfs.usage.Used, used)
	} else {
		assert.Equal(t, int64(-1), used)
	}

	// read cached
	oldUsage := vfs.usage
	oldTime := vfs.usageTime
	total2, used2, free2 := vfs.Statfs()
	assert.Equal(t, oldUsage, vfs.usage)
	assert.Equal(t, total, total2)
	assert.Equal(t, used, used2)
	assert.Equal(t, free, free2)
	assert.Equal(t, oldTime, vfs.usageTime)
}
<|endoftext|>


<commit_before>package views

const header = `

{{.Title}}

{{.TotalPlays}} plays

  {{ if .NowPlaying }}

    ♫
    {{.NowPlaying.Artist}}
    {{.NowPlaying.Track}}

  {{ end }}
`
<commit_msg>Fix header display<commit_after>package views

const header = `

{{.Title}}

{{.TotalPlays}} plays

  {{ if .NowPlaying }}

    ♫
    {{linkArtist .NowPlaying.Artist}}
    {{linkTrack .NowPlaying.Artist .NowPlaying.Album .NowPlaying.Track}}

  {{ end }}
`
<|endoftext|>


<commit_before>package views

import (
	"fmt"
	"html/template"
	"io"
	"time"
)

func datetime(t int64) string {
	return time.Unix(t, 0).Format(time.RFC3339)
}

func readable(t int64) string {
	n := time.Now()
	u := time.Unix(t, 0)
	d := n.Sub(u)

	if d.Hours() < 24 && n.Weekday() == u.Weekday() {
		if d.Hours() < 1 {
			return fmt.Sprintf("%d mintues ago", int(d.Minutes()))
		}
		return fmt.Sprintf("%d hours ago", int(d.Hours()))
	}

	if d.Hours() < 48 && n.Weekday() == u.Weekday()+1 {
		return u.Format("Yesterday at 15:04pm")
	}

	if n.Year() == u.Year() {
		return u.Format("02 Jan 15:04pm")
	}

	return u.Format("02 Jan 2006")
}

type Pair struct {
	Name string
	Hide bool
	Data interface{}
}

func pair(name string, show bool, data interface{}) *Pair {
	return &Pair{name, !show, data}
}

var Played interface {
	Execute(io.Writer, interface{}) error
}

func init() {
	var tmpl = template.Must(template.New("played").Funcs(template.FuncMap{
		"datetime": datetime,
		"readable": readable,
		"pair":     pair,
	}).Parse(played))
	tmpl = template.Must(tmpl.New("artistTab").Parse(artistTab))
	tmpl = template.Must(tmpl.New("trackTab").Parse(trackTab))

	Played = &wrappedTemplate{tmpl, "played"}
}

type wrappedTemplate struct {
	t *template.Template
	n string
}

func (w *wrappedTemplate) Execute(wr io.Writer, data interface{}) error {
	return w.t.ExecuteTemplate(wr, w.n, data)
}

const artistTab = `

    {{ range .Data }}

      {{.Artist}}
      {{.Count}} plays

    {{ end }}

`

const trackTab = `

    {{ range .Data }}

      {{.Artist}}
      {{.Track}}
      {{.Count}} plays

    {{ end }}

`

const played = `<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>{{.Title}}</title>
    <link rel="alternate" type="application/rss+xml" href="/feed" />

{{.Title}}

{{.TotalPlays}} plays

      {{ if .NowPlaying }}

        ♫
        {{.NowPlaying.Artist}}
        {{.NowPlaying.Track}}

      {{ end }}

Recently played

        {{ range .RecentlyPlayed }}

            {{.Artist}}
            {{.Track}}

          <time datetime="{{.Timestamp | datetime}}">{{.Timestamp | readable}}</time>

        {{ end }}

Top Artists

Overall

Year

Month

Week

        {{ template "artistTab" pair "tab-artists-overall" false .TopArtists.Overall }}
        {{ template "artistTab" pair "tab-artists-year"    false .TopArtists.Year    }}
        {{ template "artistTab" pair "tab-artists-month"   true  .TopArtists.Month   }}
        {{ template "artistTab" pair "tab-artists-week"    false .TopArtists.Week    }}

Top Tracks

Overall

Year

Month

Week

        {{ template "trackTab" pair "tab-tracks-overall" false .TopTracks.Overall }}
        {{ template "trackTab" pair "tab-tracks-year"    false .TopTracks.Year    }}
        {{ template "trackTab" pair "tab-tracks-month"   true  .TopTracks.Month   }}
        {{ template "trackTab" pair "tab-tracks-week"    false .TopTracks.Week    }}

`
<commit_msg>Use
 for top tracks<commit_after>package views

import (
	"fmt"
	"html/template"
	"io"
	"time"
)

func datetime(t int64) string {
	return time.Unix(t, 0).Format(time.RFC3339)
}

func readable(t int64) string {
	n := time.Now()
	u := time.Unix(t, 0)
	d := n.Sub(u)

	if d.Hours() < 24 && n.Weekday() == u.Weekday() {
		if d.Hours() < 1 {
			return fmt.Sprintf("%d mintues ago", int(d.Minutes()))
		}
		return fmt.Sprintf("%d hours ago", int(d.Hours()))
	}

	if d.Hours() < 48 && n.Weekday() == u.Weekday()+1 {
		return u.Format("Yesterday at 15:04pm")
	}

	if n.Year() == u.Year() {
		return u.Format("02 Jan 15:04pm")
	}

	return u.Format("02 Jan 2006")
}

type Pair struct {
	Name string
	Hide bool
	Data interface{}
}

func pair(name string, show bool, data interface{}) *Pair {
	return &Pair{name, !show, data}
}

var Played interface {
	Execute(io.Writer, interface{}) error
}

func init() {
	var tmpl = template.Must(template.New("played").Funcs(template.FuncMap{
		"datetime": datetime,
		"readable": readable,
		"pair":     pair,
	}).Parse(played))
	tmpl = template.Must(tmpl.New("artistTab").Parse(artistTab))
	tmpl = template.Must(tmpl.New("trackTab").Parse(trackTab))

	Played = &wrappedTemplate{tmpl, "played"}
}

type wrappedTemplate struct {
	t *template.Template
	n string
}

func (w *wrappedTemplate) Execute(wr io.Writer, data interface{}) error {
	return w.t.ExecuteTemplate(wr, w.n, data)
}

const artistTab = `

    {{ range .Data }}

      {{.Artist}}
      {{.Count}} plays

    {{ end }}

`

const trackTab = `

    {{ range .Data }}

        {{.Artist}}
        {{.Track}}

      {{.Count}} plays

    {{ end }}

`

const played = `<!DOCTYPE html>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>{{.Title}}</title>
    <link rel="alternate" type="application/rss+xml" href="/feed" />

{{.Title}}

{{.TotalPlays}} plays

      {{ if .NowPlaying }}

        ♫
        {{.NowPlaying.Artist}}
        {{.NowPlaying.Track}}

      {{ end }}

Recently played

        {{ range .RecentlyPlayed }}

            {{.Artist}}
            {{.Track}}

          <time datetime="{{.Timestamp | datetime}}">{{.Timestamp | readable}}</time>

        {{ end }}

Top Artists

Overall

Year

Month

Week

        {{ template "artistTab" pair "tab-artists-overall" false .TopArtists.Overall }}
        {{ template "artistTab" pair "tab-artists-year"    false .TopArtists.Year    }}
        {{ template "artistTab" pair "tab-artists-month"   true  .TopArtists.Month   }}
        {{ template "artistTab" pair "tab-artists-week"    false .TopArtists.Week    }}

Top Tracks

Overall

Year

Month

Week

        {{ template "trackTab" pair "tab-tracks-overall" false .TopTracks.Overall }}
        {{ template "trackTab" pair "tab-tracks-year"    false .TopTracks.Year    }}
        {{ template "trackTab" pair "tab-tracks-month"   true  .TopTracks.Month   }}
        {{ template "trackTab" pair "tab-tracks-week"    false .TopTracks.Week    }}

`
<|endoftext|>


<commit_before>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// +build darwin windows

package robotgo

import (
	"testing"

	"github.com/vcaesar/tt"
)

func TestMoveMouse(t *testing.T) {
	MoveMouse(20, 20)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 20, x)
	tt.Equal(t, 20, y)
}

func TestMoveMouseSmooth(t *testing.T) {
	MoveMouseSmooth(100, 100)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 100, x)
	tt.Equal(t, 100, y)
}

func TestDragMouse(t *testing.T) {
	DragMouse(500, 500)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 500, x)
	tt.Equal(t, 500, y)
}

func TestScrollMouse(t *testing.T) {
	ScrollMouse(120, "up")
	MilliSleep(100)

	Scroll(210, 210)
}

func TestMoveRelative(t *testing.T) {
	Move(200, 200)
	MilliSleep(10)

	MoveRelative(10, -10)
	MilliSleep(10)

	x, y := GetMousePos()
	tt.Equal(t, 210, x)
	tt.Equal(t, 190, y)
}

func TestMoveSmoothRelative(t *testing.T) {
	Move(200, 200)
	MilliSleep(10)

	MoveSmoothRelative(10, -10)
	MilliSleep(10)

	x, y := GetMousePos()
	tt.Equal(t, 210, x)
	tt.Equal(t, 190, y)
}

func TestBitmap(t *testing.T) {
	bit := CaptureScreen()
	tt.NotNil(t, bit)
	e := SaveBitmap(bit, "robot_test.png")
	tt.Empty(t, e)
}
<commit_msg>add more bitmap test code<commit_after>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// +build darwin windows

package robotgo

import (
	"testing"

	"github.com/vcaesar/tt"
)

func TestMoveMouse(t *testing.T) {
	MoveMouse(20, 20)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 20, x)
	tt.Equal(t, 20, y)
}

func TestMoveMouseSmooth(t *testing.T) {
	MoveMouseSmooth(100, 100)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 100, x)
	tt.Equal(t, 100, y)
}

func TestDragMouse(t *testing.T) {
	DragMouse(500, 500)
	MilliSleep(10)
	x, y := GetMousePos()

	tt.Equal(t, 500, x)
	tt.Equal(t, 500, y)
}

func TestScrollMouse(t *testing.T) {
	ScrollMouse(120, "up")
	MilliSleep(100)

	Scroll(210, 210)
}

func TestMoveRelative(t *testing.T) {
	Move(200, 200)
	MilliSleep(10)

	MoveRelative(10, -10)
	MilliSleep(10)

	x, y := GetMousePos()
	tt.Equal(t, 210, x)
	tt.Equal(t, 190, y)
}

func TestMoveSmoothRelative(t *testing.T) {
	Move(200, 200)
	MilliSleep(10)

	MoveSmoothRelative(10, -10)
	MilliSleep(10)

	x, y := GetMousePos()
	tt.Equal(t, 210, x)
	tt.Equal(t, 190, y)
}

func TestBitmap(t *testing.T) {
	bit := CaptureScreen()
	tt.NotNil(t, bit)
	e := SaveBitmap(bit, "robot_test.png")
	tt.Empty(t, e)

	bit1 := OpenBitmap("robot_test.png")
	b := tt.TypeOf(bit, bit1)
	tt.True(t, b)
	tt.NotNil(t, bit1)
}
<|endoftext|>


<commit_before>package transmitter

import (
	"errors"
	"github.com/RomanSaveljev/android-symbols/receiver/src/lib"
)

var ErrBufferIsFull = errors.New("Buffer is full")

type Chunker interface {
	Flush() (err error)
	WriteSignature(rolling []byte, strong []byte) (err error)
	Write(b byte) (err error)
	Close() (err error)
}

//go:generate $GOPATH/bin/mockgen -package mock_transmitter -destination mock/mock_chunker.go github.com/RomanSaveljev/android-symbols/transmitter/src/lib Chunker

type realChunker struct {
	buffer   []byte
	encoder  Encoder
	receiver Receiver
}

func NewChunker(encoder Encoder, rcv Receiver) Chunker {
	var chunker = realChunker{encoder: encoder, receiver: rcv}
	chunker.buffer = make([]byte, 0, receiver.CHUNK_SIZE)
	return &chunker
}

func (this *realChunker) emptyBuffer() {
	this.buffer = this.buffer[:0]
}

func (this *realChunker) isFull() bool {
	return len(this.buffer) == receiver.CHUNK_SIZE
}

func (this *realChunker) Flush() (err error) {
	if this.isFull() {
		rolling := CountRolling(this.buffer)
		strong := CountStrong(this.buffer)
		if err = this.receiver.SaveChunk(rolling, strong, this.buffer); err == nil {
			if err = this.writeSignature(rolling, strong); err == nil {
				this.emptyBuffer()
			}
		}
	} else {
		err = this.justFlush()
	}
	return
}

func (this *realChunker) justFlush() (err error) {
	if len(this.buffer) == 0 {
		return
	}
	var n int
	n, err = this.encoder.Write(this.buffer)
	if n > 0 && n < len(this.buffer) {
		copy(this.buffer[:len(this.buffer)-n], this.buffer[n:len(this.buffer)])
	}
	this.buffer = this.buffer[:len(this.buffer)-n]
	return
}

func (this *realChunker) WriteSignature(rolling []byte, strong []byte) (err error) {
	if err = this.justFlush(); err == nil {
		err = this.writeSignature(rolling, strong)
	}
	return
}

func (this *realChunker) writeSignature(rolling []byte, strong []byte) error {
	return this.encoder.WriteSignature(rolling, strong)
}

func (this *realChunker) Write(b byte) (err error) {
	this.buffer = append(this.buffer, b)
	if this.isFull() {
		if err = this.Flush(); err != nil {
			this.buffer = this.buffer[:len(this.buffer) - 1]
		}
	}
	return
}

func (this *realChunker) Close() (err error) {
	if err = this.Flush(); err == nil {
		err = this.encoder.Close()
	}
	return
}<commit_msg>Use proper CountRolling and CountStrong invocation in Chunker<commit_after>package transmitter

import (
	"errors"
	"github.com/RomanSaveljev/android-symbols/receiver/src/lib"
)

var ErrBufferIsFull = errors.New("Buffer is full")

type Chunker interface {
	Flush() (err error)
	WriteSignature(rolling []byte, strong []byte) (err error)
	Write(b byte) (err error)
	Close() (err error)
}

//go:generate $GOPATH/bin/mockgen -package mock_transmitter -destination mock/mock_chunker.go github.com/RomanSaveljev/android-symbols/transmitter/src/lib Chunker

type realChunker struct {
	buffer   []byte
	encoder  Encoder
	receiver Receiver
}

func NewChunker(encoder Encoder, rcv Receiver) Chunker {
	var chunker = realChunker{encoder: encoder, receiver: rcv}
	chunker.buffer = make([]byte, 0, receiver.CHUNK_SIZE)
	return &chunker
}

func (this *realChunker) emptyBuffer() {
	this.buffer = this.buffer[:0]
}

func (this *realChunker) isFull() bool {
	return len(this.buffer) == receiver.CHUNK_SIZE
}

func (this *realChunker) Flush() (err error) {
	if this.isFull() {
		rolling := CountRolling(this.buffer, []byte{})
		strong := CountStrong(this.buffer, []byte{})
		if err = this.receiver.SaveChunk(rolling, strong, this.buffer); err == nil {
			if err = this.writeSignature(rolling, strong); err == nil {
				this.emptyBuffer()
			}
		}
	} else {
		err = this.justFlush()
	}
	return
}

func (this *realChunker) justFlush() (err error) {
	if len(this.buffer) == 0 {
		return
	}
	var n int
	n, err = this.encoder.Write(this.buffer)
	if n > 0 && n < len(this.buffer) {
		copy(this.buffer[:len(this.buffer)-n], this.buffer[n:len(this.buffer)])
	}
	this.buffer = this.buffer[:len(this.buffer)-n]
	return
}

func (this *realChunker) WriteSignature(rolling []byte, strong []byte) (err error) {
	if err = this.justFlush(); err == nil {
		err = this.writeSignature(rolling, strong)
	}
	return
}

func (this *realChunker) writeSignature(rolling []byte, strong []byte) error {
	return this.encoder.WriteSignature(rolling, strong)
}

func (this *realChunker) Write(b byte) (err error) {
	this.buffer = append(this.buffer, b)
	if this.isFull() {
		if err = this.Flush(); err != nil {
			this.buffer = this.buffer[:len(this.buffer) - 1]
		}
	}
	return
}

func (this *realChunker) Close() (err error) {
	if err = this.Flush(); err == nil {
		err = this.encoder.Close()
	}
	return
}<|endoftext|>


<commit_before>package analyzer_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/rafecolton/docker-builder/analyzer"
	"testing"
)

import (
	"github.com/rafecolton/docker-builder/builderfile"
)

func TestBuilder(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Analyzer Specs")
}

var _ = Describe("Analysis Parsing", func() {
	var (
		subject *SpecRepoAnalysis
		outfile *builderfile.Builderfile
	)

	BeforeEach(func() {
		subject = &SpecRepoAnalysis{
			remotes: `origin	git@github.com:rafecolton/bob.git (fetch)
					  origin	git@github.com:rafecolton/bob.git (push)`,
			dockerfilePresent: true,
			isGitRepo:         true,
			repoBasename:      "fake-repo",
		}
		outfile = &builderfile.Builderfile{
			Version: 1,
			Docker: *&builderfile.Docker{
				BuildOpts: []string{"--rm", "--no-cache"},
				TagOpts:   []string{"--force"},
			},
			ContainerArr: []*builderfile.ContainerSection{
				&builderfile.ContainerSection{
					Name:     "app",
					Registry: "rafecolton",
					Project:  "fake-repo",
					Tags: []string{
						"git:branch",
						"git:rev",
						"git:short",
						"latest",
					},
					Dockerfile: "Dockerfile",
					SkipPush:   false,
				},
			},
		}
	})

	Context("when given valid data", func() {
		It("correctly parses the repo analysis results", func() {
			out, err := ParseAnalysis(subject)

			Expect(out).To(Equal(outfile))
			Expect(err).To(BeNil())
		})
	})

	Context("when no Dockerfile is present", func() {
		It("produces an error", func() {
			subject.dockerfilePresent = false
			out, err := ParseAnalysis(subject)

			Expect(out).To(BeNil())
			Expect(err).ToNot(BeNil())
		})
	})

	Context("when the given directory is not a git repo", func() {
		It("only has `latest` tag and default registry", func() {
			subject.isGitRepo = false
			subject.remotes = ""
			outfile.ContainerArr = []*builderfile.ContainerSection{
				&builderfile.ContainerSection{
					Name:       "app",
					Registry:   "my-registry",
					Project:    "fake-repo",
					Tags:       []string{"latest"},
					Dockerfile: "Dockerfile",
					SkipPush:   false,
				},
			}
			out, err := ParseAnalysis(subject)

			Expect(out).To(Equal(outfile))
			Expect(err).To(BeNil())

		})
	})
})
<commit_msg>Not recommending --rm and --no-cache with `docker-builder init`<commit_after>package analyzer_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/rafecolton/docker-builder/analyzer"
	"testing"
)

import (
	"github.com/rafecolton/docker-builder/builderfile"
)

func TestBuilder(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Analyzer Specs")
}

var _ = Describe("Analysis Parsing", func() {
	var (
		subject *SpecRepoAnalysis
		outfile *builderfile.Builderfile
	)

	BeforeEach(func() {
		subject = &SpecRepoAnalysis{
			remotes: `origin	git@github.com:rafecolton/bob.git (fetch)
					  origin	git@github.com:rafecolton/bob.git (push)`,
			dockerfilePresent: true,
			isGitRepo:         true,
			repoBasename:      "fake-repo",
		}
		outfile = &builderfile.Builderfile{
			Version: 1,
			Docker: *&builderfile.Docker{
				TagOpts: []string{"--force"},
			},
			ContainerArr: []*builderfile.ContainerSection{
				&builderfile.ContainerSection{
					Name:     "app",
					Registry: "rafecolton",
					Project:  "fake-repo",
					Tags: []string{
						"git:branch",
						"git:rev",
						"git:short",
						"latest",
					},
					Dockerfile: "Dockerfile",
					SkipPush:   false,
				},
			},
		}
	})

	Context("when given valid data", func() {
		It("correctly parses the repo analysis results", func() {
			out, err := ParseAnalysis(subject)

			Expect(out).To(Equal(outfile))
			Expect(err).To(BeNil())
		})
	})

	Context("when no Dockerfile is present", func() {
		It("produces an error", func() {
			subject.dockerfilePresent = false
			out, err := ParseAnalysis(subject)

			Expect(out).To(BeNil())
			Expect(err).ToNot(BeNil())
		})
	})

	Context("when the given directory is not a git repo", func() {
		It("only has `latest` tag and default registry", func() {
			subject.isGitRepo = false
			subject.remotes = ""
			outfile.ContainerArr = []*builderfile.ContainerSection{
				&builderfile.ContainerSection{
					Name:       "app",
					Registry:   "my-registry",
					Project:    "fake-repo",
					Tags:       []string{"latest"},
					Dockerfile: "Dockerfile",
					SkipPush:   false,
				},
			}
			out, err := ParseAnalysis(subject)

			Expect(out).To(Equal(outfile))
			Expect(err).To(BeNil())

		})
	})
})
<|endoftext|>


<commit_before>package deepstylelib

import (
	"fmt"
	"log"
	"os/exec"
	"path"

	"github.com/tleyden/go-couch"
)

const (
	SourceImageAttachment = "source_image"
	StyleImageAttachment  = "style_image"
	ResultImageAttachment = "result_image"
)

type configuration struct {
	Database     couch.Database
	TempDir      string // Where to store attachments and output
	UnitTestMode bool   // Are we in "Unit Test Mode"?
}

type DeepStyleJob struct {
	config configuration
	jobDoc JobDocument
}

func NewDeepStyleJob(jobDoc JobDocument, config configuration) *DeepStyleJob {
	return &DeepStyleJob{
		config: config,
		jobDoc: jobDoc,
	}
}

func (d DeepStyleJob) Execute() (err error, outputFilePath, stdOutAndErr string) {

	if d.config.UnitTestMode == true {
		return nil, "/tmp/foo", "/tmp"
	}

	err, sourceImagePath, styleImagePath := d.DownloadAttachments()

	if err != nil {
		return err, "", ""
	}

	outputFilename := fmt.Sprintf(
		"%v_%v.jpg",
		d.jobDoc.Id,
		ResultImageAttachment,
	)
	outputFilePath = path.Join(
		d.config.TempDir,
		outputFilename,
	)

	stdOutAndErrByteSlice, err := d.executeNeuralStyle(
		sourceImagePath,
		styleImagePath,
		outputFilePath,
	)

	return err, outputFilePath, string(stdOutAndErrByteSlice)

}

func (d DeepStyleJob) executeNeuralStyle(sourceImagePath, styleImagePath, outputFilePath string) (stdOutAndErr []byte, err error) {

	torchInstalled := torchInstalled()

	if torchInstalled {
		useGpu := hasGPU()
		cmd := d.generateNeuralStyleCommand(
			sourceImagePath,
			styleImagePath,
			outputFilePath,
			useGpu,
		)
		// set the current working directory to ~/neural_style
		cmd.Dir = "/home/ubuntu/neural-style"

		// Execute the command and get the output
		log.Printf("Invoking neural-style")
		return cmd.CombinedOutput()

	} else {
		useGpu := hasGPU()
		log.Printf("useGpu: %v", useGpu)
		// copy the sourceImagePath to the outputFilePath
		cp(outputFilePath, sourceImagePath)
		return []byte("Torch not installed, just created a fake output file"), nil
	}

}

func (d DeepStyleJob) generateNeuralStyleCommand(sourceImagePath, styleImagePath, outputFilePath string, useGpu bool) (cmd *exec.Cmd) {

	gpuId := "-1"
	if useGpu {
		gpuId = "0"
	}

	return exec.Command(
		"th",
		"neural_style.lua",
		"-gpu",
		gpuId,
		"-style_image",
		styleImagePath,
		"-content_image",
		sourceImagePath,
		"-output_image",
		outputFilePath,
	)

}

func (d DeepStyleJob) DownloadAttachments() (err error, sourceImagePath, styleImagePath string) {

	attachmentNames := []string{SourceImageAttachment, StyleImageAttachment}
	attachmentPaths := []string{}

	for _, attachmentName := range attachmentNames {

		attachmentReader, err := d.jobDoc.RetrieveAttachment(attachmentName)
		if err != nil {
			return fmt.Errorf("Error retrieving attachment: %v", err), "", ""
		}

		filename := fmt.Sprintf(
			"%v_%v.jpg",
			d.jobDoc.Id,
			attachmentName,
		)
		attachmentFilepath := path.Join(
			d.config.TempDir,
			filename,
		)
		attachmentPaths = append(attachmentPaths, attachmentFilepath)

		err = writeToFile(attachmentReader, attachmentFilepath)
		if err != nil {
			return fmt.Errorf("Error writing file: %v", err), "", ""
		}

	}
	return err, attachmentPaths[0], attachmentPaths[1]

}

func executeDeepStyleJob(config configuration, jobDoc JobDocument) error {

	jobDoc.SetConfiguration(config)
	deepStyleJob := NewDeepStyleJob(jobDoc, config)
	err, outputFilePath, stdOutAndErr := deepStyleJob.Execute()

	// Did the job fail?
	if err != nil {
		// Record failure
		log.Printf("Job failed with error: %v", err)
		jobDoc.UpdateState(StateProcessingFailed)
		jobDoc.SetErrorMessage(err)
		jobDoc.SetStdOutAndErr(stdOutAndErr)
		return err
	}

	// Try to attach the result image, otherwise consider it a failure
	if err := jobDoc.AddAttachment(ResultImageAttachment, outputFilePath); err != nil {
		jobDoc.UpdateState(StateProcessingFailed)
		log.Printf("Set err message to: %v", err)
		updated, errSet := jobDoc.SetErrorMessage(err)
		log.Printf("setErrorMessage updated: %v errSet: %v", updated, errSet)
		updated, errSet = jobDoc.SetStdOutAndErr(stdOutAndErr)
		log.Printf("SetStdOutAndErr updated: %v errSet: %v", updated, errSet)
		return err
	}

	// Record successful result in job
	jobDoc.SetStdOutAndErr(stdOutAndErr)
	jobDoc.UpdateState(StateProcessingSuccessful)

	// TODO: Delete all temp files

	return nil
}
<commit_msg>Set state to being processed<commit_after>package deepstylelib

import (
	"fmt"
	"log"
	"os/exec"
	"path"

	"github.com/tleyden/go-couch"
)

const (
	SourceImageAttachment = "source_image"
	StyleImageAttachment  = "style_image"
	ResultImageAttachment = "result_image"
)

type configuration struct {
	Database     couch.Database
	TempDir      string // Where to store attachments and output
	UnitTestMode bool   // Are we in "Unit Test Mode"?
}

type DeepStyleJob struct {
	config configuration
	jobDoc JobDocument
}

func NewDeepStyleJob(jobDoc JobDocument, config configuration) *DeepStyleJob {
	return &DeepStyleJob{
		config: config,
		jobDoc: jobDoc,
	}
}

func (d DeepStyleJob) Execute() (err error, outputFilePath, stdOutAndErr string) {

	if d.config.UnitTestMode == true {
		return nil, "/tmp/foo", "/tmp"
	}

	err, sourceImagePath, styleImagePath := d.DownloadAttachments()

	if err != nil {
		return err, "", ""
	}

	outputFilename := fmt.Sprintf(
		"%v_%v.jpg",
		d.jobDoc.Id,
		ResultImageAttachment,
	)
	outputFilePath = path.Join(
		d.config.TempDir,
		outputFilename,
	)

	jobDoc.UpdateState(StateBeingProcessed)

	stdOutAndErrByteSlice, err := d.executeNeuralStyle(
		sourceImagePath,
		styleImagePath,
		outputFilePath,
	)

	return err, outputFilePath, string(stdOutAndErrByteSlice)

}

func (d DeepStyleJob) executeNeuralStyle(sourceImagePath, styleImagePath, outputFilePath string) (stdOutAndErr []byte, err error) {

	torchInstalled := torchInstalled()

	if torchInstalled {
		useGpu := hasGPU()
		cmd := d.generateNeuralStyleCommand(
			sourceImagePath,
			styleImagePath,
			outputFilePath,
			useGpu,
		)
		// set the current working directory to ~/neural_style
		cmd.Dir = "/home/ubuntu/neural-style"

		// Execute the command and get the output
		log.Printf("Invoking neural-style")
		return cmd.CombinedOutput()

	} else {
		useGpu := hasGPU()
		log.Printf("useGpu: %v", useGpu)
		// copy the sourceImagePath to the outputFilePath
		cp(outputFilePath, sourceImagePath)
		return []byte("Torch not installed, just created a fake output file"), nil
	}

}

func (d DeepStyleJob) generateNeuralStyleCommand(sourceImagePath, styleImagePath, outputFilePath string, useGpu bool) (cmd *exec.Cmd) {

	gpuId := "-1"
	if useGpu {
		gpuId = "0"
	}

	return exec.Command(
		"th",
		"neural_style.lua",
		"-gpu",
		gpuId,
		"-style_image",
		styleImagePath,
		"-content_image",
		sourceImagePath,
		"-output_image",
		outputFilePath,
	)

}

func (d DeepStyleJob) DownloadAttachments() (err error, sourceImagePath, styleImagePath string) {

	attachmentNames := []string{SourceImageAttachment, StyleImageAttachment}
	attachmentPaths := []string{}

	for _, attachmentName := range attachmentNames {

		attachmentReader, err := d.jobDoc.RetrieveAttachment(attachmentName)
		if err != nil {
			return fmt.Errorf("Error retrieving attachment: %v", err), "", ""
		}

		filename := fmt.Sprintf(
			"%v_%v.jpg",
			d.jobDoc.Id,
			attachmentName,
		)
		attachmentFilepath := path.Join(
			d.config.TempDir,
			filename,
		)
		attachmentPaths = append(attachmentPaths, attachmentFilepath)

		err = writeToFile(attachmentReader, attachmentFilepath)
		if err != nil {
			return fmt.Errorf("Error writing file: %v", err), "", ""
		}

	}
	return err, attachmentPaths[0], attachmentPaths[1]

}

func executeDeepStyleJob(config configuration, jobDoc JobDocument) error {

	jobDoc.SetConfiguration(config)
	deepStyleJob := NewDeepStyleJob(jobDoc, config)
	err, outputFilePath, stdOutAndErr := deepStyleJob.Execute()

	// Did the job fail?
	if err != nil {
		// Record failure
		log.Printf("Job failed with error: %v", err)
		jobDoc.UpdateState(StateProcessingFailed)
		jobDoc.SetErrorMessage(err)
		jobDoc.SetStdOutAndErr(stdOutAndErr)
		return err
	}

	// Try to attach the result image, otherwise consider it a failure
	if err := jobDoc.AddAttachment(ResultImageAttachment, outputFilePath); err != nil {
		jobDoc.UpdateState(StateProcessingFailed)
		log.Printf("Set err message to: %v", err)
		updated, errSet := jobDoc.SetErrorMessage(err)
		log.Printf("setErrorMessage updated: %v errSet: %v", updated, errSet)
		updated, errSet = jobDoc.SetStdOutAndErr(stdOutAndErr)
		log.Printf("SetStdOutAndErr updated: %v errSet: %v", updated, errSet)
		return err
	}

	// Record successful result in job
	jobDoc.SetStdOutAndErr(stdOutAndErr)
	jobDoc.UpdateState(StateProcessingSuccessful)

	// TODO: Delete all temp files

	return nil
}
<|endoftext|>


<commit_before>package actions

import (
	"errors"
	"fmt"
	"github.com/containrrr/watchtower/pkg/filters"
	"github.com/containrrr/watchtower/pkg/sorter"
	"sort"
	"strings"
	"time"

	"github.com/opencontainers/runc/Godeps/_workspace/src/github.com/Sirupsen/logrus"

	log "github.com/sirupsen/logrus"

	"github.com/containrrr/watchtower/pkg/container"
)

// CheckForMultipleWatchtowerInstances will ensure that there are not multiple instances of the
// watchtower running simultaneously. If multiple watchtower containers are detected, this function
// will stop and remove all but the most recently started container.
func CheckForMultipleWatchtowerInstances(client container.Client, cleanup bool) error {
	awaitDockerClient()
	containers, err := client.ListContainers(filters.WatchtowerContainersFilter)

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

	if len(containers) <= 1 {
		log.Debug("There are no additional watchtower containers")
		return nil
	}

	log.Info("Found multiple running watchtower instances. Cleaning up.")
	return cleanupExcessWatchtowers(containers, client, cleanup)
}

func cleanupExcessWatchtowers(containers []container.Container, client container.Client, cleanup bool) error {
	var cleanupErrors int
	var stopErrors int

	sort.Sort(sorter.ByCreated(containers))
	allContainersExceptLast := containers[0 : len(containers)-1]

	for _, c := range allContainersExceptLast {
		if err := client.StopContainer(c, 600); err != nil {
			// logging the original here as we're just returning a count
			logrus.Error(err)
			stopErrors++
			continue
		}

		if cleanup {
			if err := client.RemoveImageByID(c.ImageID()); err != nil {
				// logging the original here as we're just returning a count
				logrus.Error(err)
				cleanupErrors++
			}
		}
	}

	return createErrorIfAnyHaveOccurred(stopErrors, cleanupErrors)
}

func createErrorIfAnyHaveOccurred(c int, i int) error {
	if c == 0 && i == 0 {
		return nil
	}

	var output strings.Builder

	if c > 0 {
		output.WriteString(fmt.Sprintf("%d errors while stopping containers", c))
	}
	if i > 0 {
		output.WriteString(fmt.Sprintf("%d errors while cleaning up images", c))
	}
	return errors.New(output.String())
}

func awaitDockerClient() {
	log.Debug("Sleeping for a second to ensure the docker api client has been properly initialized.")
	time.Sleep(1 * time.Second)
}
<commit_msg>Increases stopContainer timeout to 10min (#528)<commit_after>package actions

import (
	"errors"
	"fmt"
	"sort"
	"strings"
	"time"

	"github.com/containrrr/watchtower/pkg/filters"
	"github.com/containrrr/watchtower/pkg/sorter"

	"github.com/opencontainers/runc/Godeps/_workspace/src/github.com/Sirupsen/logrus"

	log "github.com/sirupsen/logrus"

	"github.com/containrrr/watchtower/pkg/container"
)

// CheckForMultipleWatchtowerInstances will ensure that there are not multiple instances of the
// watchtower running simultaneously. If multiple watchtower containers are detected, this function
// will stop and remove all but the most recently started container.
func CheckForMultipleWatchtowerInstances(client container.Client, cleanup bool) error {
	awaitDockerClient()
	containers, err := client.ListContainers(filters.WatchtowerContainersFilter)

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

	if len(containers) <= 1 {
		log.Debug("There are no additional watchtower containers")
		return nil
	}

	log.Info("Found multiple running watchtower instances. Cleaning up.")
	return cleanupExcessWatchtowers(containers, client, cleanup)
}

func cleanupExcessWatchtowers(containers []container.Container, client container.Client, cleanup bool) error {
	var cleanupErrors int
	var stopErrors int

	sort.Sort(sorter.ByCreated(containers))
	allContainersExceptLast := containers[0 : len(containers)-1]

	for _, c := range allContainersExceptLast {
		if err := client.StopContainer(c, 10*time.Minute); err != nil {
			// logging the original here as we're just returning a count
			logrus.Error(err)
			stopErrors++
			continue
		}

		if cleanup {
			if err := client.RemoveImageByID(c.ImageID()); err != nil {
				// logging the original here as we're just returning a count
				logrus.Error(err)
				cleanupErrors++
			}
		}
	}

	return createErrorIfAnyHaveOccurred(stopErrors, cleanupErrors)
}

func createErrorIfAnyHaveOccurred(c int, i int) error {
	if c == 0 && i == 0 {
		return nil
	}

	var output strings.Builder

	if c > 0 {
		output.WriteString(fmt.Sprintf("%d errors while stopping containers", c))
	}
	if i > 0 {
		output.WriteString(fmt.Sprintf("%d errors while cleaning up images", c))
	}
	return errors.New(output.String())
}

func awaitDockerClient() {
	log.Debug("Sleeping for a second to ensure the docker api client has been properly initialized.")
	time.Sleep(1 * time.Second)
}
<|endoftext|>


<commit_before>package jsontree

import (
	"bytes"
	"errors"
	"io"
	"strings"
	"testing"
)

func TestDeserializeError(t *testing.T) {
	err := &DeserializeError{
		Got:  '?',
		Want: []byte{'a', 'b', 'c'},
	}
	want := "Read '?', expected 'a' or 'b' or 'c'"
	if err.Error() != want {
		t.Errorf("Error() = %v, want %v", err.Error(), want)
	}
}

func TestParserScan(t *testing.T) {
	// Scan() returns false if error
	{
		p := parser{err: fmt.Errorf("Err")}
		if p.Scan() {
			t.Errorf("Scan() returned true when parser has error. Should return false.")
		}
	}
}

func TestDeserializeNode(t *testing.T) {
	tests := []struct {
		in    string
		weird bool // signal not to try creating invalid JSON out of this test input
		want  *Node
		err   error
	}{
		{
			// Top level is leaf
			in:   `{"a":"b"}`,
			want: &Node{Key: "a", Value: val("b")},
		},
		{
			// Sibling leaf nodes
			in: `{"root":{"a":"b","c":"d"}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Value: val("b")},
				{Key: "c", Value: val("d")},
			}},
		},
		{
			// Sibling non-leaf nodes
			in: `{"root":{"a":{"a1":"v1"},"b":{"b1":"v2"}}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Nodes: []*Node{
					{Key: "a1", Value: val("v1")},
				}},
				{Key: "b", Nodes: []*Node{
					{Key: "b1", Value: val("v2")},
				}},
			}},
		},
		{
			// Leaf nodes on different levels
			in: `{"root":{"a":"v1","b":{"b1":{"b11":"v3"},"b2":"v2"}}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Value: val("v1")},
				{Key: "b", Nodes: []*Node{
					{Key: "b1", Nodes: []*Node{
						{Key: "b11", Value: val("v3")},
					}},
					{Key: "b2", Value: val("v2")},
				}},
			}},
		},
		{
			// Nodes are ordered non-alphabetically
			in: `{"root":{"b":"3","c":"1","a":"2"}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "b", Value: val("3")},
				{Key: "c", Value: val("1")},
				{Key: "a", Value: val("2")},
			}},
		},
		// Weird but valid input
		{
			in:    `{"ro\"ot":{"{a}":"\"hello\"","b}":"\\backslash\nnewline"}}`,
			weird: true,
			want: &Node{Key: `ro\"ot`, Nodes: []*Node{
				{Key: `{a}`, Value: val(`\"hello\"`)},
				{Key: `b}`, Value: val(`\\backslash\nnewline`)},
			}},
		},
		// Handling invalid input. See also section Test unexpected tokens (invalid JSON) below
		// -- JSON syntax error
		{
			in:  `{"a":"b"},`, // extra, invalid comma
			err: fmt.Errorf("expected end of input. Got ','"),
		},
		{
			in:  `{"a":"b"`, // json ends abruptly
			err: fmt.Errorf("reader returned io.EOF before expected"),
		},
		{
			in:  `{"a`, // key is never closed
			err: fmt.Errorf("reader returned io.EOF before expected"),
		},
		// -- Semantic error
		{
			in:  `{"a":"b","c":"d"}`,
			err: fmt.Errorf("invalid json. Expected 1 root node"),
		},
	}
	getValFn := func() Value { return new(testValue) }
	for _, test := range tests {
		r := bytes.NewReader([]byte(test.in))
		node, err := DeserializeNode(r, getValFn)
		if test.err != nil {
			if !errEqual(test.err, err) {
				t.Errorf("%s\nWrong error.\nWant %v\nGot  %v", test.in, test.err, err)
			}
			continue
		} else {
			if err != nil {
				t.Errorf("%s\nUnexpected error %v", test.in, err)
				continue
			}
		}
		if !nodeEqual(node, test.want) {
			t.Errorf("%s: Node was not as expected\nWant %v\nGot  %v", test.in, nodeString(test.want), nodeString(node))
		}

		// Test reader error
		{
			// Error after x bytes read
			for i := 0; i <= len(test.in); i++ {
				wantErr := fmt.Errorf("Reader test error")
				r := &readPeeker{
					r: &errReader{
						br:       bytes.NewReader([]byte(test.in)),
						errIndex: i,
						err:      wantErr,
					},
				}
				_, gotErr := DeserializeNode(r, getValFn)
				if !errEqual(wantErr, gotErr) {
					t.Errorf("%s (errReader(%d)\nWrong error.\nWant %v\nGot  %v", test.in, i, wantErr, gotErr)
				}
			}
			// Error on ReadByte() after successful call to Peek()
			for i := 1; i <= len(test.in); i++ {
				wantErr := fmt.Errorf("ReadByte() test error")
				r := &readPeeker{
					r:        bytes.NewReader([]byte(test.in)),
					readErr:  wantErr,
					errIndex: i,
				}
				_, gotErr := DeserializeNode(r, getValFn)
				if r.peekCount < i {
					// we've reached the max number of Peek() calls for this input
					break
				}
				if !errEqual(wantErr, gotErr) {
					t.Errorf("%s (ReadByte() error)\nWrong error.\nWant %v\nGot  %v", test.in, wantErr, gotErr)
				}
			}
		}
		// Test unexpected tokens (invalid JSON)
		if test.err == nil && !test.weird {
			validJSON := test.in
			var prev rune
			for i, char := range validJSON {
				switch char {
				case '{', '}', '[', ']', ':', '"', '-', ',':
					if char == '"' && isAlphanumeric(prev) {
						continue // its the end of a key or value string. This is handled in another test.
					}
					// Replace the character with a ?. Eg for {"a":"b"}, we test [?, {?, {"a?, {"a"?, {"a":?, ...]
					invalidJSON := validJSON[:i] + "?"
					r := strings.NewReader(invalidJSON)
					_, err := DeserializeNode(r, getValFn)
					if _, ok := err.(*DeserializeError); !ok {
						t.Errorf(`DeserializeNode(%s): Wrong error type. Want DeserializeError, got %T ("%v")`, invalidJSON, err, err)
					}
				}
				prev = char
			}
		}
	}
}

// ========== Benchmarking ==========

func benchmarkNodeDeserialization(n int, b *testing.B) {
	for i := 0; i < b.N; i++ {
		r := bytes.NewBuffer(benchmarks.deserialization.ins[n-1])
		getValFn := func() Value { return new(testValue) }
		if _, err := DeserializeNode(r, getValFn); err != nil {
			b.Fatalf("Error: %v", err)
		}
	}
}

func BenchmarkNodeDeserialization1(b *testing.B) { benchmarkNodeDeserialization(1, b) }
func BenchmarkNodeDeserialization2(b *testing.B) { benchmarkNodeDeserialization(2, b) }
func BenchmarkNodeDeserialization3(b *testing.B) { benchmarkNodeDeserialization(3, b) }
func BenchmarkNodeDeserialization4(b *testing.B) { benchmarkNodeDeserialization(4, b) }
func BenchmarkNodeDeserialization5(b *testing.B) { benchmarkNodeDeserialization(5, b) }

// ========== Utility ==========

func nodeString(node *Node) string {
	if node == nil {
		return "<nil>"
	}
	var buf bytes.Buffer
	if err := SerializeNode(node, &buf); err != nil {
		return "<unserializable node>"
	} else {
		return buf.String()
	}
}

func nodesString(nodes []*Node) string {
	s := make([]string, len(nodes))
	for i, node := range nodes {
		s[i] = nodeString(node)
	}
	return "\t" + strings.Join(s, "\n\t")
}

func errEqual(want, got error) bool {
	return got != nil && want.Error() == got.Error()
}

func nodeEqual(want, got *Node) bool {
	if got == nil {
		return false
	}
	if got.Key != want.Key {
		return false
	}
	if (got.Value == nil && want.Value != nil) || (got.Value != nil && want.Value == nil) {
		return false
	}
	if got.Value != nil && !got.Value.(*testValue).Equal(want.Value.(*testValue)) {
		return false
	}
	return nodesEqual(want.Nodes, got.Nodes)
}

func nodesEqual(want, got []*Node) bool {
	if len(got) != len(want) || (got == nil && want != nil) || (got != nil && want == nil) {
		return false
	}
	for i := range want {
		if !nodeEqual(want[i], got[i]) {
			return false
		}
	}
	return true
}

func isAlphanumeric(r rune) bool {
	return (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9')
}

// errReader reads from the underlying reader until a certain number of
// bytes has been read.
type errReader struct {
	br       *bytes.Reader
	errIndex int   // number of bytes to read successfully, without returning error
	err      error // error to return
	count    int   // current number of bytes read
}

func (r *errReader) Read(b []byte) (int, error) {
	r.count += len(b)
	if r.hasError() {
		return 0, r.err
	}
	return r.br.Read(b)
}

func (r *errReader) hasError() bool {
	return r.count >= r.errIndex
}

// readPeeker is a custom implementation of the ReadSeeker inferface,
// to escape the buffering of bufio and control when errors are returned
// when using errReader as the underlying reader
type readPeeker struct {
	peek      []byte
	r         io.Reader
	readErr   error // the error to be returned by ReadByte()
	errIndex  int   // after what number of calls to Peek() should ReadByte() return an error
	peekCount int   // number of times Peek() has been called
}

func (rp *readPeeker) Read([]byte) (int, error) {
	panic("Read is not implemented")
}

func (rp *readPeeker) ReadByte() (b byte, err error) {
	defer func() { rp.peek = nil }()
	if rp.shouldReturnReadError() {
		return b, rp.readErr
	}
	if len(rp.peek) > 0 {
		return rp.peek[0], nil
	}
	p := make([]byte, 1)
	if _, err = rp.r.Read(p); err != nil {
		return b, err
	}
	return p[0], nil
}

func (rp *readPeeker) Peek(n int) (b []byte, err error) {
	b = make([]byte, n)
	_, err = rp.r.Read(b)
	rp.peek = b
	rp.peekCount += 1
	return b, err
}

func (rp *readPeeker) lastActionWasPeek() bool {
	return rp.peek != nil
}

func (rp *readPeeker) shouldReturnReadError() bool {
	return rp.readErr != nil && rp.lastActionWasPeek() && rp.peekCount >= rp.errIndex
}
<commit_msg>Fix correct import<commit_after>package jsontree

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"testing"
)

func TestDeserializeError(t *testing.T) {
	err := &DeserializeError{
		Got:  '?',
		Want: []byte{'a', 'b', 'c'},
	}
	want := "Read '?', expected 'a' or 'b' or 'c'"
	if err.Error() != want {
		t.Errorf("Error() = %v, want %v", err.Error(), want)
	}
}

func TestParserScan(t *testing.T) {
	// Scan() returns false if error
	{
		p := parser{err: fmt.Errorf("Err")}
		if p.Scan() {
			t.Errorf("Scan() returned true when parser has error. Should return false.")
		}
	}
}

func TestDeserializeNode(t *testing.T) {
	tests := []struct {
		in    string
		weird bool // signal not to try creating invalid JSON out of this test input
		want  *Node
		err   error
	}{
		{
			// Top level is leaf
			in:   `{"a":"b"}`,
			want: &Node{Key: "a", Value: val("b")},
		},
		{
			// Sibling leaf nodes
			in: `{"root":{"a":"b","c":"d"}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Value: val("b")},
				{Key: "c", Value: val("d")},
			}},
		},
		{
			// Sibling non-leaf nodes
			in: `{"root":{"a":{"a1":"v1"},"b":{"b1":"v2"}}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Nodes: []*Node{
					{Key: "a1", Value: val("v1")},
				}},
				{Key: "b", Nodes: []*Node{
					{Key: "b1", Value: val("v2")},
				}},
			}},
		},
		{
			// Leaf nodes on different levels
			in: `{"root":{"a":"v1","b":{"b1":{"b11":"v3"},"b2":"v2"}}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "a", Value: val("v1")},
				{Key: "b", Nodes: []*Node{
					{Key: "b1", Nodes: []*Node{
						{Key: "b11", Value: val("v3")},
					}},
					{Key: "b2", Value: val("v2")},
				}},
			}},
		},
		{
			// Nodes are ordered non-alphabetically
			in: `{"root":{"b":"3","c":"1","a":"2"}}`,
			want: &Node{Key: "root", Nodes: []*Node{
				{Key: "b", Value: val("3")},
				{Key: "c", Value: val("1")},
				{Key: "a", Value: val("2")},
			}},
		},
		// Weird but valid input
		{
			in:    `{"ro\"ot":{"{a}":"\"hello\"","b}":"\\backslash\nnewline"}}`,
			weird: true,
			want: &Node{Key: `ro\"ot`, Nodes: []*Node{
				{Key: `{a}`, Value: val(`\"hello\"`)},
				{Key: `b}`, Value: val(`\\backslash\nnewline`)},
			}},
		},
		// Handling invalid input. See also section Test unexpected tokens (invalid JSON) below
		// -- JSON syntax error
		{
			in:  `{"a":"b"},`, // extra, invalid comma
			err: fmt.Errorf("expected end of input. Got ','"),
		},
		{
			in:  `{"a":"b"`, // json ends abruptly
			err: fmt.Errorf("reader returned io.EOF before expected"),
		},
		{
			in:  `{"a`, // key is never closed
			err: fmt.Errorf("reader returned io.EOF before expected"),
		},
		// -- Semantic error
		{
			in:  `{"a":"b","c":"d"}`,
			err: fmt.Errorf("invalid json. Expected 1 root node"),
		},
	}
	getValFn := func() Value { return new(testValue) }
	for _, test := range tests {
		r := bytes.NewReader([]byte(test.in))
		node, err := DeserializeNode(r, getValFn)
		if test.err != nil {
			if !errEqual(test.err, err) {
				t.Errorf("%s\nWrong error.\nWant %v\nGot  %v", test.in, test.err, err)
			}
			continue
		} else {
			if err != nil {
				t.Errorf("%s\nUnexpected error %v", test.in, err)
				continue
			}
		}
		if !nodeEqual(node, test.want) {
			t.Errorf("%s: Node was not as expected\nWant %v\nGot  %v", test.in, nodeString(test.want), nodeString(node))
		}

		// Test reader error
		{
			// Error after x bytes read
			for i := 0; i <= len(test.in); i++ {
				wantErr := fmt.Errorf("Reader test error")
				r := &readPeeker{
					r: &errReader{
						br:       bytes.NewReader([]byte(test.in)),
						errIndex: i,
						err:      wantErr,
					},
				}
				_, gotErr := DeserializeNode(r, getValFn)
				if !errEqual(wantErr, gotErr) {
					t.Errorf("%s (errReader(%d)\nWrong error.\nWant %v\nGot  %v", test.in, i, wantErr, gotErr)
				}
			}
			// Error on ReadByte() after successful call to Peek()
			for i := 1; i <= len(test.in); i++ {
				wantErr := fmt.Errorf("ReadByte() test error")
				r := &readPeeker{
					r:        bytes.NewReader([]byte(test.in)),
					readErr:  wantErr,
					errIndex: i,
				}
				_, gotErr := DeserializeNode(r, getValFn)
				if r.peekCount < i {
					// we've reached the max number of Peek() calls for this input
					break
				}
				if !errEqual(wantErr, gotErr) {
					t.Errorf("%s (ReadByte() error)\nWrong error.\nWant %v\nGot  %v", test.in, wantErr, gotErr)
				}
			}
		}
		// Test unexpected tokens (invalid JSON)
		if test.err == nil && !test.weird {
			validJSON := test.in
			var prev rune
			for i, char := range validJSON {
				switch char {
				case '{', '}', '[', ']', ':', '"', '-', ',':
					if char == '"' && isAlphanumeric(prev) {
						continue // its the end of a key or value string. This is handled in another test.
					}
					// Replace the character with a ?. Eg for {"a":"b"}, we test [?, {?, {"a?, {"a"?, {"a":?, ...]
					invalidJSON := validJSON[:i] + "?"
					r := strings.NewReader(invalidJSON)
					_, err := DeserializeNode(r, getValFn)
					if _, ok := err.(*DeserializeError); !ok {
						t.Errorf(`DeserializeNode(%s): Wrong error type. Want DeserializeError, got %T ("%v")`, invalidJSON, err, err)
					}
				}
				prev = char
			}
		}
	}
}

// ========== Benchmarking ==========

func benchmarkNodeDeserialization(n int, b *testing.B) {
	for i := 0; i < b.N; i++ {
		r := bytes.NewBuffer(benchmarks.deserialization.ins[n-1])
		getValFn := func() Value { return new(testValue) }
		if _, err := DeserializeNode(r, getValFn); err != nil {
			b.Fatalf("Error: %v", err)
		}
	}
}

func BenchmarkNodeDeserialization1(b *testing.B) { benchmarkNodeDeserialization(1, b) }
func BenchmarkNodeDeserialization2(b *testing.B) { benchmarkNodeDeserialization(2, b) }
func BenchmarkNodeDeserialization3(b *testing.B) { benchmarkNodeDeserialization(3, b) }
func BenchmarkNodeDeserialization4(b *testing.B) { benchmarkNodeDeserialization(4, b) }
func BenchmarkNodeDeserialization5(b *testing.B) { benchmarkNodeDeserialization(5, b) }

// ========== Utility ==========

func nodeString(node *Node) string {
	if node == nil {
		return "<nil>"
	}
	var buf bytes.Buffer
	if err := SerializeNode(node, &buf); err != nil {
		return "<unserializable node>"
	} else {
		return buf.String()
	}
}

func nodesString(nodes []*Node) string {
	s := make([]string, len(nodes))
	for i, node := range nodes {
		s[i] = nodeString(node)
	}
	return "\t" + strings.Join(s, "\n\t")
}

func errEqual(want, got error) bool {
	return got != nil && want.Error() == got.Error()
}

func nodeEqual(want, got *Node) bool {
	if got == nil {
		return false
	}
	if got.Key != want.Key {
		return false
	}
	if (got.Value == nil && want.Value != nil) || (got.Value != nil && want.Value == nil) {
		return false
	}
	if got.Value != nil && !got.Value.(*testValue).Equal(want.Value.(*testValue)) {
		return false
	}
	return nodesEqual(want.Nodes, got.Nodes)
}

func nodesEqual(want, got []*Node) bool {
	if len(got) != len(want) || (got == nil && want != nil) || (got != nil && want == nil) {
		return false
	}
	for i := range want {
		if !nodeEqual(want[i], got[i]) {
			return false
		}
	}
	return true
}

func isAlphanumeric(r rune) bool {
	return (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9')
}

// errReader reads from the underlying reader until a certain number of
// bytes has been read.
type errReader struct {
	br       *bytes.Reader
	errIndex int   // number of bytes to read successfully, without returning error
	err      error // error to return
	count    int   // current number of bytes read
}

func (r *errReader) Read(b []byte) (int, error) {
	r.count += len(b)
	if r.hasError() {
		return 0, r.err
	}
	return r.br.Read(b)
}

func (r *errReader) hasError() bool {
	return r.count >= r.errIndex
}

// readPeeker is a custom implementation of the ReadSeeker inferface,
// to escape the buffering of bufio and control when errors are returned
// when using errReader as the underlying reader
type readPeeker struct {
	peek      []byte
	r         io.Reader
	readErr   error // the error to be returned by ReadByte()
	errIndex  int   // after what number of calls to Peek() should ReadByte() return an error
	peekCount int   // number of times Peek() has been called
}

func (rp *readPeeker) Read([]byte) (int, error) {
	panic("Read is not implemented")
}

func (rp *readPeeker) ReadByte() (b byte, err error) {
	defer func() { rp.peek = nil }()
	if rp.shouldReturnReadError() {
		return b, rp.readErr
	}
	if len(rp.peek) > 0 {
		return rp.peek[0], nil
	}
	p := make([]byte, 1)
	if _, err = rp.r.Read(p); err != nil {
		return b, err
	}
	return p[0], nil
}

func (rp *readPeeker) Peek(n int) (b []byte, err error) {
	b = make([]byte, n)
	_, err = rp.r.Read(b)
	rp.peek = b
	rp.peekCount += 1
	return b, err
}

func (rp *readPeeker) lastActionWasPeek() bool {
	return rp.peek != nil
}

func (rp *readPeeker) shouldReturnReadError() bool {
	return rp.readErr != nil && rp.lastActionWasPeek() && rp.peekCount >= rp.errIndex
}
<|endoftext|>