<commit_before>// entry.go
//
// Copyright (c) 2016, Ayke van Laethem
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package dtdiff

import (
	"bytes"
	"sort"
	"strconv"
	"time"

	"github.com/aykevl/dtsync/tree"
)

type revision struct {
	identity   string // random string as identifier for the replica
	generation int    // starts at 1, 0 means 'no generation'
}

// An Entry is one object (row) in a Replica. It belongs to one Replica.
type Entry struct {
	name     string
	revision // last content (hash) change
	fileType tree.Type
	modTime  time.Time
	size     int64
	mode     tree.Mode
	hasMode  tree.Mode
	hash     []byte
	children map[string]*Entry
	parent   *Entry
	replica  *Replica
	removed  time.Time
}

// String function, for debugging purposes
func (e *Entry) String() string {
	return "dtdiff.Entry(" + e.name + "," + e.identity + ":" + strconv.Itoa(e.generation) + ")"
}

// Name returns the name of this entry
func (e *Entry) Name() string {
	return e.name
}

// RelativePath returns the path relative to the root
func (e *Entry) RelativePath() []string {
	if e.parent == nil {
		return nil
	} else {
		return append(e.parent.RelativePath(), e.name)
	}
}

// Hash returns the hash of the status entry, if one is known.
func (e *Entry) Hash() []byte {
	return e.hash
}

// Type returns the tree.Type filetype.
func (e *Entry) Type() tree.Type {
	return e.fileType
}

// Mode returns the permission bits for this entry.
func (e *Entry) Mode() tree.Mode {
	return e.mode
}

// HasMode returns the permission bits this entry supports.
func (e *Entry) HasMode() tree.Mode {
	return e.hasMode
}

// ModTime returns the last modification time.
func (e *Entry) ModTime() time.Time {
	return e.modTime
}

// Size returns the filesize for regular files, or 0.
func (e *Entry) Size() int64 {
	return e.size
}

// Add new entry by recursively finding the parent
func (e *Entry) add(path []string, rev revision, fingerprint string, mode tree.Mode, hash []byte) (*Entry, error) {
	if path[0] == "" {
		return nil, ErrInvalidPath
	}
	if len(path) > 1 {
		child, ok := e.children[path[0]]
		if !ok {
			// child does not exist
			// or: the path has a parent that hasn't yet been scanned
			return nil, ErrInvalidPath
		}
		return child.add(path[1:], rev, fingerprint, mode, hash)
	} else {
		fileInfo, err := parseFingerprint(fingerprint)
		if err != nil {
			return nil, err
		}
		return e.addChild(path[0], rev, fileInfo, mode, hash)
	}
}

func (e *Entry) addChild(name string, rev revision, fileInfo fingerprintInfo, mode tree.Mode, hash []byte) (*Entry, error) {
	if _, ok := e.children[name]; ok {
		// duplicate path
		return nil, ErrExists
	}
	newEntry := &Entry{
		name:     name,
		revision: rev,
		fileType: fileInfo.fileType,
		modTime:  fileInfo.modTime,
		size:     fileInfo.size,
		mode:     mode,
		hash:     hash,
		children: make(map[string]*Entry),
		parent:   e,
		replica:  e.replica,
	}
	e.children[newEntry.name] = newEntry
	return newEntry, nil
}

// Get returns the named child, or nil if it doesn't exist.
func (e *Entry) Get(name string) *Entry {
	return e.children[name]
}

// HasRevision returns true if this file (actually, this replica) includes the
// revision the other entry is at.
func (e *Entry) HasRevision(other *Entry) bool {
	return e.replica.knowledge[other.identity] >= other.generation
}

// Equal returns true if both entries are of the same revision (replica and
// generation). Not recursive.
func (e *Entry) Equal(e2 *Entry) bool {
	if e.revision == e2.revision {
		return true
	}
	if tree.MatchFingerprint(e, e2) {
		return true
	}
	if len(e.hash) > 0 && bytes.Equal(e.hash, e2.hash) {
		return true
	}
	return false
}

// After returns true if this entry was modified after the other.
func (e *Entry) After(e2 *Entry) bool {
	return e.generation > e2.replica.knowledge[e.identity]
}

// Before returns true if this entry is modified before the other.
func (e *Entry) Before(e2 *Entry) bool {
	return e2.After(e)
}

// Conflict returns true if both entries are modified.
func (e *Entry) Conflict(e2 *Entry) bool {
	return e.After(e2) && e2.After(e)
}

// Includes returns true if this entry includes all revisions from the other
// entry (recursively: children are also compared).
//
// FIXME: It does not always work when one file is removed. It does work however
// to check for equality, though.
func (e *Entry) Includes(e2 *Entry) bool {
	if e2.After(e) && !e.isRoot() {
		return false
	}

	for name, child2 := range e2.children {
		_, ok := e.children[name]
		if !ok {
			// if child2 has all revisions, that means it is deleted here, not
			// new there.
			if child2.HasRevision(e) {
				// their child was removed
				return false
			}
		}
	}
	for name, child := range e.children {
		child2, ok := e2.children[name]
		if !ok {
			if !child.HasRevision(e2) {
				// our child is outdated and to-be-removed
				return false
			}
		} else {
			if !child.Includes(child2) {
				return false
			}
		}
	}
	return true
}

func (e *Entry) isRoot() bool {
	return e.parent == nil
}

func (e *Entry) List() []*Entry {
	list := make([]*Entry, 0, len(e.children))
	for _, entry := range e.children {
		list = append(list, entry)
	}

	// Remove removed children from the list.
	p := 0
	for i, child := range list {
		if i != p {
			list[p] = list[i]
		}
		if child.removed.IsZero() {
			// go to next if not removed
			p++
		}
	}
	list = list[:p]

	sortEntries(list)
	return list
}

// Add a new status entry.
func (e *Entry) Add(info tree.FileInfo) (*Entry, error) {
	e.replica.markChanged()
	fileInfo := fingerprintInfo{info.Type(), info.ModTime(), info.Size()}
	if fileInfo.fileType != tree.TYPE_REGULAR {
		// Maybe not necessary, but just to be safe...
		fileInfo.size = 0
	}
	return e.addChild(info.Name(), e.replica.revision, fileInfo, info.Mode(), info.Hash())
}

// Update updates the revision if the file was changed. The file is not changed
// if the fingerprint but not the hash changed.
func (e *Entry) Update(info tree.FileInfo, hash []byte) {
	if !tree.MatchFingerprint(e, info) {
		e.fileType = info.Type()
		e.modTime = info.ModTime()
		e.size = info.Size()
		e.mode = info.Mode()
		e.hasMode = info.HasMode()
		if e.Type() == tree.TYPE_SYMLINK {
			// Changes in fingerprints of symbolic links must be tracked. For
			// regular files we look at the hash and for directories fingerprint
			// changes do not cause updates at all (but are still tracked).
			e.replica.markChanged()
			e.revision = e.replica.revision
		} else {
			e.replica.markMetaChanged()
		}
	}
	e.UpdateHash(hash)
}

// UpdateHash sets the new hash from the parameter, marking this file as changed
// if it is different from the existing one.
func (e *Entry) UpdateHash(hash []byte) {
	if !bytes.Equal(e.hash, hash) {
		e.replica.markChanged()
		e.hash = hash
		e.revision = e.replica.revision
	}
}

// Remove this entry.
func (e *Entry) Remove() {
	e.replica.markChanged()
	// simply make it unreachable
	delete(e.parent.children, e.name)
}

type entrySlice []*Entry

func (es entrySlice) Len() int {
	return len(es)
}

func (es entrySlice) Less(i, j int) bool {
	return es[i].name < es[j].name
}

func (es entrySlice) Swap(i, j int) {
	es[i], es[j] = es[j], es[i]
}

func sortEntries(list []*Entry) {
	sort.Sort(entrySlice(list))
}

// IterateEntries returns a channel, reads from the channel will return each
// entry in the slice.
func IterateEntries(list []*Entry) chan *Entry {
	c := make(chan *Entry)
	go func() {
		for _, entry := range list {
			c <- entry
		}
		close(c)
	}()
	return c
}
<commit_msg>dtdiff: code clean<commit_after>// entry.go
//
// Copyright (c) 2016, Ayke van Laethem
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package dtdiff

import (
	"bytes"
	"sort"
	"strconv"
	"time"

	"github.com/aykevl/dtsync/tree"
)

type revision struct {
	identity   string // random string as identifier for the replica
	generation int    // starts at 1, 0 means 'no generation'
}

// An Entry is one object (row) in a Replica. It belongs to one Replica.
type Entry struct {
	name     string
	revision // last content (hash) change
	fileType tree.Type
	modTime  time.Time
	size     int64
	mode     tree.Mode
	hasMode  tree.Mode
	hash     []byte
	children map[string]*Entry
	parent   *Entry
	replica  *Replica
	removed  time.Time
}

// String function, for debugging purposes
func (e *Entry) String() string {
	return "dtdiff.Entry(" + e.name + "," + e.identity + ":" + strconv.Itoa(e.generation) + ")"
}

// Name returns the name of this entry
func (e *Entry) Name() string {
	return e.name
}

// RelativePath returns the path relative to the root
func (e *Entry) RelativePath() []string {
	if e.parent == nil {
		return nil
	} else {
		return append(e.parent.RelativePath(), e.name)
	}
}

// Hash returns the hash of the status entry, if one is known.
func (e *Entry) Hash() []byte {
	return e.hash
}

// Type returns the tree.Type filetype.
func (e *Entry) Type() tree.Type {
	return e.fileType
}

// Mode returns the permission bits for this entry.
func (e *Entry) Mode() tree.Mode {
	return e.mode
}

// HasMode returns the permission bits this entry supports.
func (e *Entry) HasMode() tree.Mode {
	return e.hasMode
}

// ModTime returns the last modification time.
func (e *Entry) ModTime() time.Time {
	return e.modTime
}

// Size returns the filesize for regular files, or 0.
func (e *Entry) Size() int64 {
	return e.size
}

// Add new entry by recursively finding the parent
func (e *Entry) add(path []string, rev revision, fingerprint string, mode tree.Mode, hash []byte) (*Entry, error) {
	if path[0] == "" {
		return nil, ErrInvalidPath
	}
	if len(path) > 1 {
		child, ok := e.children[path[0]]
		if !ok {
			// child does not exist
			// or: the path has a parent that hasn't yet been scanned
			return nil, ErrInvalidPath
		}
		return child.add(path[1:], rev, fingerprint, mode, hash)
	} else {
		fileInfo, err := parseFingerprint(fingerprint)
		if err != nil {
			return nil, err
		}
		return e.addChild(path[0], rev, fileInfo, mode, hash)
	}
}

func (e *Entry) addChild(name string, rev revision, fileInfo fingerprintInfo, mode tree.Mode, hash []byte) (*Entry, error) {
	if _, ok := e.children[name]; ok {
		// duplicate path
		return nil, ErrExists
	}
	newEntry := &Entry{
		name:     name,
		revision: rev,
		fileType: fileInfo.fileType,
		modTime:  fileInfo.modTime,
		size:     fileInfo.size,
		mode:     mode,
		hash:     hash,
		children: make(map[string]*Entry),
		parent:   e,
		replica:  e.replica,
	}
	e.children[newEntry.name] = newEntry
	return newEntry, nil
}

// Get returns the named child, or nil if it doesn't exist.
func (e *Entry) Get(name string) *Entry {
	return e.children[name]
}

// HasRevision returns true if this file (actually, this replica) includes the
// revision the other entry is at.
func (e *Entry) HasRevision(other *Entry) bool {
	return e.replica.knowledge[other.identity] >= other.generation
}

// Equal returns true if both entries are of the same revision (replica and
// generation). Not recursive.
func (e *Entry) Equal(e2 *Entry) bool {
	if e.revision == e2.revision {
		return true
	}
	if tree.MatchFingerprint(e, e2) {
		return true
	}
	if len(e.hash) > 0 && bytes.Equal(e.hash, e2.hash) {
		return true
	}
	return false
}

// After returns true if this entry was modified after the other.
func (e *Entry) After(e2 *Entry) bool {
	return e.generation > e2.replica.knowledge[e.identity]
}

// Before returns true if this entry is modified before the other.
func (e *Entry) Before(e2 *Entry) bool {
	return e2.After(e)
}

// Conflict returns true if both entries are modified.
func (e *Entry) Conflict(e2 *Entry) bool {
	return e.After(e2) && e2.After(e)
}

// Includes returns true if this entry includes all revisions from the other
// entry (recursively: children are also compared).
//
// FIXME: It does not always work when one file is removed. It does work however
// to check for equality, though.
func (e *Entry) Includes(e2 *Entry) bool {
	if e2.After(e) && !e.isRoot() {
		return false
	}

	for name, child2 := range e2.children {
		_, ok := e.children[name]
		if !ok {
			// if child2 has all revisions, that means it is deleted here, not
			// new there.
			if child2.HasRevision(e) {
				// their child was removed
				return false
			}
		}
	}
	for name, child := range e.children {
		child2, ok := e2.children[name]
		if !ok {
			if !child.HasRevision(e2) {
				// our child is outdated and to-be-removed
				return false
			}
		} else {
			if !child.Includes(child2) {
				return false
			}
		}
	}
	return true
}

func (e *Entry) isRoot() bool {
	return e.parent == nil
}

func (e *Entry) List() []*Entry {
	list := make([]*Entry, 0, len(e.children))
	for _, entry := range e.children {
		list = append(list, entry)
	}

	// Remove removed children from the list.
	p := 0
	for i, child := range list {
		if i != p {
			list[p] = list[i]
		}
		if child.removed.IsZero() {
			// go to next if not removed
			p++
		}
	}
	list = list[:p]

	sortEntries(list)
	return list
}

// Add a new status entry.
func (e *Entry) Add(info tree.FileInfo) (*Entry, error) {
	e.replica.markChanged()
	fileInfo := fingerprintInfo{info.Type(), info.ModTime(), info.Size()}
	if fileInfo.fileType != tree.TYPE_REGULAR {
		// Maybe not necessary, but just to be safe...
		fileInfo.size = 0
	}
	return e.addChild(info.Name(), e.replica.revision, fileInfo, info.Mode(), info.Hash())
}

// Update updates the revision if the file was changed. The file is not changed
// if the fingerprint but not the hash changed.
func (e *Entry) Update(info tree.FileInfo, hash []byte) {
	if !tree.MatchFingerprint(e, info) {
		e.fileType = info.Type()
		e.modTime = info.ModTime()
		e.size = info.Size()
		e.mode = info.Mode()
		e.hasMode = info.HasMode()
		if e.Type() == tree.TYPE_SYMLINK {
			// Changes in fingerprints of symbolic links must be tracked. For
			// regular files we look at the hash and for directories fingerprint
			// changes do not cause updates at all (but are still tracked).
			e.replica.markChanged()
			e.revision = e.replica.revision
		} else {
			e.replica.markMetaChanged()
		}
	}
	e.UpdateHash(hash)
}

// UpdateHash sets the new hash from the parameter, marking this file as changed
// if it is different from the existing one.
func (e *Entry) UpdateHash(hash []byte) {
	if !bytes.Equal(e.hash, hash) {
		e.replica.markChanged()
		e.revision = e.replica.revision
		e.hash = hash
	}
}

// Remove this entry.
func (e *Entry) Remove() {
	e.replica.markChanged()
	// simply make it unreachable
	delete(e.parent.children, e.name)
}

type entrySlice []*Entry

func (es entrySlice) Len() int {
	return len(es)
}

func (es entrySlice) Less(i, j int) bool {
	return es[i].name < es[j].name
}

func (es entrySlice) Swap(i, j int) {
	es[i], es[j] = es[j], es[i]
}

func sortEntries(list []*Entry) {
	sort.Sort(entrySlice(list))
}

// IterateEntries returns a channel, reads from the channel will return each
// entry in the slice.
func IterateEntries(list []*Entry) chan *Entry {
	c := make(chan *Entry)
	go func() {
		for _, entry := range list {
			c <- entry
		}
		close(c)
	}()
	return c
}
<|endoftext|>


<commit_before><commit_msg>Add support for multiple redis (for sharding)<commit_after><|endoftext|>


<commit_before><commit_msg>cmd/vcrypt: graph display for inspect plan<commit_after><|endoftext|>


<commit_before>package commandHandlers

import (
	"fmt"
	"log"
	"math/rand"
	"strings"
	"unicode/utf8"

	"html"

	"github.com/hoisie/mustache"
	"github.com/khades/servbot/ircClient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func Short(s string, i int) string {
	runes := []rune(s)
	if len(runes) > i {
		return string(runes[:i])
	}
	return s
}

// Custom handler checks if input command has template and then fills it in with mustache templating and sends to a specified/user
func Custom(online bool, chatMessage *models.ChatMessage, chatCommand models.ChatCommand, ircClient *ircClient.IrcClient) {
	channelInfo, error := repos.GetChannelInfo(&chatMessage.ChannelID)
	if error != nil {
		return
	}
	channelStatus := &models.ChannelInfoForTemplate{ChannelInfo: *channelInfo, IsMod: chatMessage.IsMod}
	channelStatus.IsMod = chatMessage.IsMod
	channelStatus.IsSub = chatMessage.IsSub
	template, err := repos.GetChannelTemplate(&chatMessage.ChannelID, &chatCommand.Command)
	user := chatMessage.User
	if err != nil || template.Template == "" {
		return
	}

	if chatMessage.IsMod == false {
		if channelStatus.StreamStatus.Online == true && template.ShowOnline == false {
			return
		}
		if channelStatus.StreamStatus.Online == false && template.ShowOffline == false {
			return
		}
	}
	if template.IntegerRandomizer.Enabled == true && template.IntegerRandomizer.UpperLimit > template.IntegerRandomizer.LowerLimit {
		channelStatus.RandomInteger = template.IntegerRandomizer.LowerLimit + rand.Intn(template.IntegerRandomizer.UpperLimit-template.IntegerRandomizer.LowerLimit)
		if channelStatus.RandomInteger == template.IntegerRandomizer.LowerLimit {
			channelStatus.RandomIntegerIsMinimal = true
		}
		if channelStatus.RandomInteger == template.IntegerRandomizer.UpperLimit {
			channelStatus.RandomIntegerIsMaximal = true
		}
		if channelStatus.RandomInteger == 0 {
			channelStatus.RandomIntegerIsMinimal = true
		}
		if template.IntegerRandomizer.TimeoutAfter == true && channelStatus.RandomInteger > 0 {
			if chatMessage.IsMod == false {
				ircClient.SendPublic(&models.OutgoingMessage{
					Channel: chatMessage.Channel,
					Body:    fmt.Sprintf("/timeout %s %d ", user, channelStatus.RandomInteger)})
			} else {
				ircClient.SendPublic(&models.OutgoingMessage{
					Channel: chatMessage.Channel,
					User:    user,
					Body:    "Модератора нельзя затаймаутить SMOrc"})
				return
			}

		}
	}

	if template.StringRandomizer.Enabled == true {
		if len(template.StringRandomizer.Strings) == 0 {
			commandValues := strings.Split(chatCommand.Body, ",")
			if len(commandValues) != 0 {
				channelStatus.RandomString = strings.TrimSpace(commandValues[rand.Intn(len(commandValues)-1)])

			}
		} else {
			channelStatus.RandomString = strings.TrimSpace(template.StringRandomizer.Strings[rand.Intn(len(template.StringRandomizer.Strings)-1)])
		}
	}

	message := mustache.Render(template.Template, channelStatus)
	log.Println("Debug template output")
	log.Println("User: ", chatMessage.User)
	log.Println(template.Template)
	log.Println(channelStatus)
	log.Println(message)
	if utf8.RuneCountInString(message) > 400 {
		message = Short(message, 397) + "..."
	}
	if message == "" {
		return
	}
	redirectTo := chatMessage.User
	if chatCommand.Body != "" && !(template.StringRandomizer.Enabled == true && len(template.StringRandomizer.Strings) == 0) && template.PreventRedirect == false {
		if strings.HasPrefix(chatCommand.Body, "@") {
			redirectTo = chatCommand.Body[1:]
		} else {
			redirectTo = chatCommand.Body

		}
	}
	if template.OnlyPrivate == true {
		ircClient.SendPrivate(&models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)})
		return
	}

	if template.PreventDebounce == true {
		ircClient.SendPublic(&models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)})
		return
	}

	ircClient.SendDebounced(models.OutgoingDebouncedMessage{
		Message: models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)},
		Command:    template.AliasTo,
		RedirectTo: redirectTo})

}
<commit_msg>Fix: Small fix for templates<commit_after>package commandHandlers

import (
	"fmt"
	"math/rand"
	"strings"
	"unicode/utf8"

	"html"

	"github.com/hoisie/mustache"
	"github.com/khades/servbot/ircClient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func Short(s string, i int) string {
	runes := []rune(s)
	if len(runes) > i {
		return string(runes[:i])
	}
	return s
}

// Custom handler checks if input command has template and then fills it in with mustache templating and sends to a specified/user
func Custom(online bool, chatMessage *models.ChatMessage, chatCommand models.ChatCommand, ircClient *ircClient.IrcClient) {
	channelInfo, error := repos.GetChannelInfo(&chatMessage.ChannelID)
	if error != nil {
		return
	}
	channelStatus := &models.ChannelInfoForTemplate{ChannelInfo: *channelInfo, IsMod: chatMessage.IsMod, CommandBody: chatCommand.Body}
	channelStatus.IsMod = chatMessage.IsMod
	channelStatus.IsSub = chatMessage.IsSub
	template, err := repos.GetChannelTemplate(&chatMessage.ChannelID, &chatCommand.Command)
	user := chatMessage.User
	if err != nil || template.Template == "" {
		return
	}

	if chatMessage.IsMod == false {
		if channelStatus.StreamStatus.Online == true && template.ShowOnline == false {
			return
		}
		if channelStatus.StreamStatus.Online == false && template.ShowOffline == false {
			return
		}
	}
	if template.IntegerRandomizer.Enabled == true && template.IntegerRandomizer.UpperLimit > template.IntegerRandomizer.LowerLimit {
		channelStatus.RandomInteger = template.IntegerRandomizer.LowerLimit + rand.Intn(template.IntegerRandomizer.UpperLimit-template.IntegerRandomizer.LowerLimit)
		if channelStatus.RandomInteger == template.IntegerRandomizer.LowerLimit {
			channelStatus.RandomIntegerIsMinimal = true
		}
		if channelStatus.RandomInteger == template.IntegerRandomizer.UpperLimit {
			channelStatus.RandomIntegerIsMaximal = true
		}
		if channelStatus.RandomInteger == 0 {
			channelStatus.RandomIntegerIsMinimal = true
		}
		if template.IntegerRandomizer.TimeoutAfter == true && channelStatus.RandomInteger > 0 {
			if chatMessage.IsMod == false {
				ircClient.SendPublic(&models.OutgoingMessage{
					Channel: chatMessage.Channel,
					Body:    fmt.Sprintf("/timeout %s %d ", user, channelStatus.RandomInteger)})
			} else {
				ircClient.SendPublic(&models.OutgoingMessage{
					Channel: chatMessage.Channel,
					User:    user,
					Body:    "Модератора нельзя затаймаутить SMOrc"})
				return
			}

		}
	}

	if template.StringRandomizer.Enabled == true {
		if len(template.StringRandomizer.Strings) == 0 {
			commandValues := strings.Split(chatCommand.Body, ",")
			if len(commandValues) != 0 {
				channelStatus.RandomString = strings.TrimSpace(commandValues[rand.Intn(len(commandValues)-1)])

			}
		} else {
			channelStatus.RandomString = strings.TrimSpace(template.StringRandomizer.Strings[rand.Intn(len(template.StringRandomizer.Strings)-1)])
		}
	}

	message := mustache.Render(template.Template, channelStatus)

	if utf8.RuneCountInString(message) > 400 {
		message = Short(message, 397) + "..."
	}
	if message == "" {
		return
	}
	redirectTo := chatMessage.User
	if chatCommand.Body != "" && !(template.StringRandomizer.Enabled == true && len(template.StringRandomizer.Strings) == 0) && template.PreventRedirect == false {
		if strings.HasPrefix(chatCommand.Body, "@") {
			redirectTo = chatCommand.Body[1:]
		} else {
			redirectTo = chatCommand.Body

		}
	}
	if template.OnlyPrivate == true {
		ircClient.SendPrivate(&models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)})
		return
	}

	if template.PreventDebounce == true {
		ircClient.SendPublic(&models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)})
		return
	}

	ircClient.SendDebounced(models.OutgoingDebouncedMessage{
		Message: models.OutgoingMessage{
			Channel: chatMessage.Channel,
			User:    user,
			Body:    html.UnescapeString(message)},
		Command:    template.AliasTo,
		RedirectTo: redirectTo})

}
<|endoftext|>


<commit_before>// Package pastebin is a simple modern and powerful pastebin service
package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	duration "github.com/channelmeter/iso8601duration"
	// uniuri is used for easy random string generation
	"github.com/dchest/uniuri"
	// pygments is used for syntax highlighting
	"github.com/ewhal/pygments"
	// mysql driver
	_ "github.com/go-sql-driver/mysql"
	// mux is used for url routing
	"github.com/gorilla/mux"
)

type Configuration struct {
	// ADDRESS that pastebin will return links for
	Address string
	// LENGTH of paste id
	Length int
	// PORT that pastebin will listen on
	Port string
	// USERNAME for database
	Username string
	// PASS database password
	Password string
	// NAME database name
	Name string
}

var configuration Configuration

// DATABASE connection String
var DATABASE string

// Template pages
var templates = template.Must(template.ParseFiles("assets/paste.html", "assets/index.html", "assets/clone.html"))
var syntax, _ = ioutil.ReadFile("assets/syntax.html")

// Response API struct
type Response struct {
	SUCCESS bool   `json:"success"`
	STATUS  string `json:"status"`
	ID      string `json:"id"`
	TITLE   string `json:"title"`
	SHA1    string `json:"sha1"`
	URL     string `json:"url"`
	SIZE    int    `json:"size"`
	DELKEY  string `json:"delkey"`
}

// Page generation struct
type Page struct {
	Title    string
	Body     []byte
	Raw      string
	Home     string
	Download string
	Clone    string
}

// check error handling function
func Check(err error) {
	if err != nil {
		log.Println(err)
	}
}

// GenerateName uses uniuri to generate a random string that isn't in the
// database
func GenerateName() string {
	// use uniuri to generate random string
	id := uniuri.NewLen(configuration.Length)

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	// query database if id exists and if it does call generateName again
	query, err := db.Query("select id from pastebin where id=?", id)
	if err != sql.ErrNoRows {
		for query.Next() {
			GenerateName()
		}
	}

	return id

}

// Sha1 hashes paste into a sha1 hash
func Sha1(paste string) string {
	hasher := sha1.New()

	hasher.Write([]byte(paste))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

// DurationFromExpiry takes the expiry in string format and returns the duration
// that the paste will exist for
func DurationFromExpiry(expiry string) time.Duration {
	if expiry == "" {
		expiry = "P20Y"
	}
	dura, err := duration.FromString(expiry) // dura is time.Duration type
	Check(err)

	duration := dura.ToDuration()

	return duration
}

// Save function handles the saving of each paste.
// raw string is the raw paste input
// lang string is the user specified language for syntax highlighting
// title string user customized title
// expiry string duration that the paste will exist for
// Returns Response struct
func Save(raw string, lang string, title string, expiry string) Response {

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	// hash paste data and query database to see if paste exists
	sha := Sha1(raw)
	query, err := db.Query("select id, title, hash, data, delkey from pastebin where hash=?", sha)

	if err != sql.ErrNoRows {
		for query.Next() {
			var id, title, hash, paste, delkey string
			err := query.Scan(&id, &title, &hash, &paste, &delkey)
			Check(err)
			url := configuration.Address + "/p/" + id
			return Response{true, "saved", id, title, hash, url, len(paste), delkey}
		}
	}
	id := GenerateName()
	url := configuration.Address + "/p/" + id
	if lang != "" {
		url += "/" + lang
	}

	const timeFormat = "2006-01-02 15:04:05"
	expiryTime := time.Now().Add(DurationFromExpiry(expiry)).Format(timeFormat)

	delKey := uniuri.NewLen(40)
	dataEscaped := html.EscapeString(raw)

	stmt, err := db.Prepare("INSERT INTO pastebin(id, title, hash, data, delkey, expiry) values(?,?,?,?,?,?)")
	Check(err)
	if title == "" {
		title = id
	}
	_, err = stmt.Exec(id, html.EscapeString(title), sha, dataEscaped, delKey, expiryTime)
	Check(err)

	return Response{true, "saved", id, title, sha, url, len(dataEscaped), delKey}
}

// DelHandler checks to see if delkey and pasteid exist in the database.
// if both exist and are correct the paste will be removed.
func DelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["pasteId"]
	delkey := r.FormValue("delkey")

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	stmt, err := db.Prepare("delete from pastebin where delkey=? and id=?")
	Check(err)

	res, err := stmt.Exec(html.EscapeString(delkey), html.EscapeString(id))
	Check(err)

	_, err = res.RowsAffected()
	if err != sql.ErrNoRows {
		w.Header().Set("Content-Type", "application/json")
		b := Response{STATUS: "DELETED " + id}
		err := json.NewEncoder(w).Encode(b)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

// SaveHandler Handles saving pastes and outputing responses
func SaveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		paste := r.FormValue("p")
		lang := r.FormValue("lang")
		title := r.FormValue("title")
		expiry := r.FormValue("expiry")
		if paste == "" {
			http.Error(w, "Empty paste", 500)
			return
		}
		b := Save(paste, lang, title, expiry)

		switch output {
		case "redirect":
			http.Redirect(w, r, b.URL, 301)

		default:
			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

		}
	}

}

// Highlight uses user specified input to call pygments library to highlight the
// paste
func Highlight(s string, lang string) (string, error) {

	highlight, err := pygments.Highlight(html.UnescapeString(s), html.EscapeString(lang), "html", "style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,noclasses=True,", "utf-8")
	if err != nil {
		return "", err
	}
	return highlight, nil

}

// GetPaste takes pasteid and language
// queries the database and returns paste data
func GetPaste(paste string, lang string) (string, string) {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	var title, s string
	var expiry string
	err = db.QueryRow("select title, data, expiry from pastebin where id=?", param1).Scan(&title, &s, &expiry)
	Check(err)
	if time.Now().Format("2006-01-02 15:04:05") >= expiry {
		stmt, err := db.Prepare("delete from pastebin where id=?")
		Check(err)
		_, err = stmt.Exec(param1)
		Check(err)
		return "Error invalid paste", ""
	}

	if err == sql.ErrNoRows {
		return "Error invalid paste", ""
	}
	if lang != "" {
		high, err := Highlight(s, lang)
		Check(err)
		return high, html.UnescapeString(title)
	}
	return html.UnescapeString(s), html.UnescapeString(title)
}

// APIHandler handles get requests of pastes
func APIHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	b, _ := GetPaste(paste, "")
	w.Header().Set("Content-Type", "application/json")
	err := json.NewEncoder(w).Encode(b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}

// PasteHandler handles the generation of paste pages with the links
func PasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]

	s, title := GetPaste(paste, lang)

	// button links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste
	// Page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	if lang == "" {

		err := templates.ExecuteTemplate(w, "paste.html", p)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

	} else {
		fmt.Fprintf(w, string(syntax), p.Title, p.Title, s, p.Home, p.Download, p.Raw, p.Clone)

	}
}

// CloneHandler handles generating the clone pages
func CloneHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	s, title := GetPaste(paste, "")

	// Page links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste

	// Clone page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	err := templates.ExecuteTemplate(w, "clone.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

}

// DownloadHandler forces downloads of selected pastes
func DownloadHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	// Set header to an attachment so browser will automatically download it
	w.Header().Set("Content-Disposition", "attachment; filename="+paste)
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	io.WriteString(w, s)

}

// RawHandler displays the pastes in text/plain format
func RawHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	w.Header().Set("Content-Type", "text/plain; charset=UTF-8; imeanit=yes")
	// simply write string to browser
	io.WriteString(w, s)

}

// RootHandler handles generating the root page
func RootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", &Page{})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	file, err := os.Open("config.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err = decoder.Decode(&configuration)
	if err != nil {
		panic(err)
	}

	DATABASE = configuration.Username + ":" + configuration.Password + "@/" + configuration.Name + "?charset=utf8"
	// create new mux router
	router := mux.NewRouter()

	// serverside rending stuff
	router.HandleFunc("/p/{pasteId}", PasteHandler).Methods("GET")
	router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
	router.HandleFunc("/p/{pasteId}/{lang}", PasteHandler).Methods("GET")
	router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
	router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
	// api
	router.HandleFunc("/api", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{output}", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{pasteid}", APIHandler).Methods("GET")
	router.HandleFunc("/api/{pasteId}", DelHandler).Methods("DELETE")
	router.HandleFunc("/", RootHandler)
	err = http.ListenAndServe(configuration.Port, router)
	if err != nil {
		log.Fatal(err)
	}

}
<commit_msg>Remove unneeded variable<commit_after>// Package pastebin is a simple modern and powerful pastebin service
package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	duration "github.com/channelmeter/iso8601duration"
	// uniuri is used for easy random string generation
	"github.com/dchest/uniuri"
	// pygments is used for syntax highlighting
	"github.com/ewhal/pygments"
	// mysql driver
	_ "github.com/go-sql-driver/mysql"
	// mux is used for url routing
	"github.com/gorilla/mux"
)

type Configuration struct {
	// ADDRESS that pastebin will return links for
	Address string
	// LENGTH of paste id
	Length int
	// PORT that pastebin will listen on
	Port string
	// USERNAME for database
	Username string
	// PASS database password
	Password string
	// NAME database name
	Name string
}

var configuration Configuration

// DATABASE connection String
var DATABASE string

// Template pages
var templates = template.Must(template.ParseFiles("assets/paste.html", "assets/index.html", "assets/clone.html"))
var syntax, _ = ioutil.ReadFile("assets/syntax.html")

// Response API struct
type Response struct {
	SUCCESS bool   `json:"success"`
	STATUS  string `json:"status"`
	ID      string `json:"id"`
	TITLE   string `json:"title"`
	SHA1    string `json:"sha1"`
	URL     string `json:"url"`
	SIZE    int    `json:"size"`
	DELKEY  string `json:"delkey"`
}

// Page generation struct
type Page struct {
	Title    string
	Body     []byte
	Raw      string
	Home     string
	Download string
	Clone    string
}

// check error handling function
func Check(err error) {
	if err != nil {
		log.Println(err)
	}
}

// GenerateName uses uniuri to generate a random string that isn't in the
// database
func GenerateName() string {
	// use uniuri to generate random string
	id := uniuri.NewLen(configuration.Length)

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	// query database if id exists and if it does call generateName again
	_, err = db.Query("select id from pastebin where id=?", id)
	if err != sql.ErrNoRows {
		GenerateName()
	}

	return id

}

// Sha1 hashes paste into a sha1 hash
func Sha1(paste string) string {
	hasher := sha1.New()

	hasher.Write([]byte(paste))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

// DurationFromExpiry takes the expiry in string format and returns the duration
// that the paste will exist for
func DurationFromExpiry(expiry string) time.Duration {
	if expiry == "" {
		expiry = "P20Y"
	}
	dura, err := duration.FromString(expiry) // dura is time.Duration type
	Check(err)

	duration := dura.ToDuration()

	return duration
}

// Save function handles the saving of each paste.
// raw string is the raw paste input
// lang string is the user specified language for syntax highlighting
// title string user customized title
// expiry string duration that the paste will exist for
// Returns Response struct
func Save(raw string, lang string, title string, expiry string) Response {

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	// hash paste data and query database to see if paste exists
	sha := Sha1(raw)
	query, err := db.Query("select id, title, hash, data, delkey from pastebin where hash=?", sha)

	if err != sql.ErrNoRows {
		for query.Next() {
			var id, title, hash, paste, delkey string
			err := query.Scan(&id, &title, &hash, &paste, &delkey)
			Check(err)
			url := configuration.Address + "/p/" + id
			return Response{true, "saved", id, title, hash, url, len(paste), delkey}
		}
	}
	id := GenerateName()
	url := configuration.Address + "/p/" + id
	if lang != "" {
		url += "/" + lang
	}

	const timeFormat = "2006-01-02 15:04:05"
	expiryTime := time.Now().Add(DurationFromExpiry(expiry)).Format(timeFormat)

	delKey := uniuri.NewLen(40)
	dataEscaped := html.EscapeString(raw)

	stmt, err := db.Prepare("INSERT INTO pastebin(id, title, hash, data, delkey, expiry) values(?,?,?,?,?,?)")
	Check(err)
	if title == "" {
		title = id
	}
	_, err = stmt.Exec(id, html.EscapeString(title), sha, dataEscaped, delKey, expiryTime)
	Check(err)

	return Response{true, "saved", id, title, sha, url, len(dataEscaped), delKey}
}

// DelHandler checks to see if delkey and pasteid exist in the database.
// if both exist and are correct the paste will be removed.
func DelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["pasteId"]
	delkey := r.FormValue("delkey")

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	stmt, err := db.Prepare("delete from pastebin where delkey=? and id=?")
	Check(err)

	res, err := stmt.Exec(html.EscapeString(delkey), html.EscapeString(id))
	Check(err)

	_, err = res.RowsAffected()
	if err != sql.ErrNoRows {
		w.Header().Set("Content-Type", "application/json")
		b := Response{STATUS: "DELETED " + id}
		err := json.NewEncoder(w).Encode(b)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

// SaveHandler Handles saving pastes and outputing responses
func SaveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		paste := r.FormValue("p")
		lang := r.FormValue("lang")
		title := r.FormValue("title")
		expiry := r.FormValue("expiry")
		if paste == "" {
			http.Error(w, "Empty paste", 500)
			return
		}
		b := Save(paste, lang, title, expiry)

		switch output {
		case "redirect":
			http.Redirect(w, r, b.URL, 301)

		default:
			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

		}
	}

}

// Highlight uses user specified input to call pygments library to highlight the
// paste
func Highlight(s string, lang string) (string, error) {

	highlight, err := pygments.Highlight(html.UnescapeString(s), html.EscapeString(lang), "html", "style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,noclasses=True,", "utf-8")
	if err != nil {
		return "", err
	}
	return highlight, nil

}

// GetPaste takes pasteid and language
// queries the database and returns paste data
func GetPaste(paste string, lang string) (string, string) {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	var title, s string
	var expiry string
	err = db.QueryRow("select title, data, expiry from pastebin where id=?", param1).Scan(&title, &s, &expiry)
	Check(err)
	if time.Now().Format("2006-01-02 15:04:05") >= expiry {
		stmt, err := db.Prepare("delete from pastebin where id=?")
		Check(err)
		_, err = stmt.Exec(param1)
		Check(err)
		return "Error invalid paste", ""
	}

	if err == sql.ErrNoRows {
		return "Error invalid paste", ""
	}
	if lang != "" {
		high, err := Highlight(s, lang)
		Check(err)
		return high, html.UnescapeString(title)
	}
	return html.UnescapeString(s), html.UnescapeString(title)
}

// APIHandler handles get requests of pastes
func APIHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	b, _ := GetPaste(paste, "")
	w.Header().Set("Content-Type", "application/json")
	err := json.NewEncoder(w).Encode(b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}

// PasteHandler handles the generation of paste pages with the links
func PasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]

	s, title := GetPaste(paste, lang)

	// button links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste
	// Page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	if lang == "" {

		err := templates.ExecuteTemplate(w, "paste.html", p)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

	} else {
		fmt.Fprintf(w, string(syntax), p.Title, p.Title, s, p.Home, p.Download, p.Raw, p.Clone)

	}
}

// CloneHandler handles generating the clone pages
func CloneHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	s, title := GetPaste(paste, "")

	// Page links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste

	// Clone page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	err := templates.ExecuteTemplate(w, "clone.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

}

// DownloadHandler forces downloads of selected pastes
func DownloadHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	// Set header to an attachment so browser will automatically download it
	w.Header().Set("Content-Disposition", "attachment; filename="+paste)
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	io.WriteString(w, s)

}

// RawHandler displays the pastes in text/plain format
func RawHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	w.Header().Set("Content-Type", "text/plain; charset=UTF-8; imeanit=yes")
	// simply write string to browser
	io.WriteString(w, s)

}

// RootHandler handles generating the root page
func RootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", &Page{})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	file, err := os.Open("config.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err = decoder.Decode(&configuration)
	if err != nil {
		panic(err)
	}

	DATABASE = configuration.Username + ":" + configuration.Password + "@/" + configuration.Name + "?charset=utf8"
	// create new mux router
	router := mux.NewRouter()

	// serverside rending stuff
	router.HandleFunc("/p/{pasteId}", PasteHandler).Methods("GET")
	router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
	router.HandleFunc("/p/{pasteId}/{lang}", PasteHandler).Methods("GET")
	router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
	router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
	// api
	router.HandleFunc("/api", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{output}", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{pasteid}", APIHandler).Methods("GET")
	router.HandleFunc("/api/{pasteId}", DelHandler).Methods("DELETE")
	router.HandleFunc("/", RootHandler)
	err = http.ListenAndServe(configuration.Port, router)
	if err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package cfhttp_test

import (
	"crypto/tls"
	"net/http"
	"time"

	"code.cloudfoundry.org/cfhttp/v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
)

var _ = Describe("NewClient", func() {
	var server *ghttp.Server

	BeforeEach(func() {
		server = ghttp.NewServer()
		server.AppendHandlers(
			ghttp.RespondWith(http.StatusOK, nil),
		)
	})

	AfterEach(func() {
		server.Close()
	})

	It("returns an HTTP client with default settings", func() {
		client := cfhttp.NewClient()
		transport := client.Transport.(*http.Transport)
		Expect(transport.DialContext).NotTo(BeNil())
		Expect(transport.IdleConnTimeout).To(Equal(90 * time.Second))
		Expect(transport.DisableKeepAlives).To(BeFalse())
	})

	It("returns an HTTP client that works on an HTTP Client", func() {
		client := cfhttp.NewClient()
		resp, err := client.Get(server.URL())
		Expect(err).NotTo(HaveOccurred())
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
	})

	Describe(`with the "WithStreaming" option`, func() {
		It("returns an HTTP client with streaming default settings", func() {
			client := cfhttp.NewClient(cfhttp.WithStreamingDefaults())
			transport := client.Transport.(*http.Transport)
			Expect(transport.DialContext).NotTo(BeNil())
			Expect(transport.IdleConnTimeout).To(Equal(90 * time.Second))
			Expect(transport.DisableKeepAlives).To(BeFalse())
		})
	})

	Describe(`with the "WithRequestTimeout" option`, func() {
		It("returns an HTTP client with a custom request timeout", func() {
			client := cfhttp.NewClient(cfhttp.WithRequestTimeout(1 * time.Nanosecond))
			Expect(client.Timeout).To(Equal(1 * time.Nanosecond))
		})
	})

	Describe(`with the "WithDialTimeout" option`, func() {
		It("returns an HTTP client with a custom DialTimeout", func() {
			client := cfhttp.NewClient(cfhttp.WithDialTimeout(1 * time.Nanosecond))
			_, err := client.Get(server.URL())
			Expect(err).To(HaveOccurred())
		})
	})

	Describe(`with the "WithTCPKeepAliveTimeout" option`, func() {
		It("returns an HTTP client with a custom TCP keepalive timeout", func() {
			// I don't think there's an easy way to test this behavior
			client := cfhttp.NewClient(
				cfhttp.WithStreamingDefaults(),
				cfhttp.WithTCPKeepAliveTimeout(10*time.Second),
			)
			transport := client.Transport.(*http.Transport)
			Expect(transport.DialContext).NotTo(BeNil())
		})
	})

	Describe(`with the "WithIdleConnTimeout" option`, func() {
		It("returns an HTTP client with a custom IdleConnTimeout", func() {
			client := cfhttp.NewClient(cfhttp.WithIdleConnTimeout(10 * time.Second))
			transport := client.Transport.(*http.Transport)
			Expect(transport.IdleConnTimeout).To(Equal(10 * time.Second))
			Expect(transport.DisableKeepAlives).To(BeFalse())
		})
	})

	Describe(`with the "WithDisableKeepAlives" option`, func() {
		It("returns an HTTP client with HTTP keepalives disabled", func() {
			client := cfhttp.NewClient(cfhttp.WithDisableKeepAlives())
			transport := client.Transport.(*http.Transport)
			Expect(transport.DisableKeepAlives).To(BeTrue())
		})
	})

	Describe(`with the "WithTLSConfig" option`, func() {
		It("returns a transport with the TLS config set", func() {
			t := &tls.Config{
				ServerName: "test-server.com",
			}
			client := cfhttp.NewClient(cfhttp.WithTLSConfig(t))
			transport := client.Transport.(*http.Transport)
			Expect(transport.TLSClientConfig).To(Equal(t))
		})
	})

	Describe(`with the "WithMaxIdleConnsPerHost" option`, func() {
		It("returns a transport with the MaxIdleConnsPerHost set", func() {
			client := cfhttp.NewClient(cfhttp.WithMaxIdleConnsPerHost(100))
			transport := client.Transport.(*http.Transport)
			Expect(transport.MaxIdleConnsPerHost).To(Equal(100))
		})
	})
})
<commit_msg>Ping somewhere further than localhost<commit_after>package cfhttp_test

import (
	"crypto/tls"
	"net/http"
	"time"

	"code.cloudfoundry.org/cfhttp/v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
)

var _ = Describe("NewClient", func() {
	var server *ghttp.Server

	BeforeEach(func() {
		server = ghttp.NewServer()
		server.AppendHandlers(
			ghttp.RespondWith(http.StatusOK, nil),
		)
	})

	AfterEach(func() {
		server.Close()
	})

	It("returns an HTTP client with default settings", func() {
		client := cfhttp.NewClient()
		transport := client.Transport.(*http.Transport)
		Expect(transport.DialContext).NotTo(BeNil())
		Expect(transport.IdleConnTimeout).To(Equal(90 * time.Second))
		Expect(transport.DisableKeepAlives).To(BeFalse())
	})

	It("returns an HTTP client that works on an HTTP Client", func() {
		client := cfhttp.NewClient()
		resp, err := client.Get(server.URL())
		Expect(err).NotTo(HaveOccurred())
		Expect(resp.StatusCode).To(Equal(http.StatusOK))
	})

	Describe(`with the "WithStreaming" option`, func() {
		It("returns an HTTP client with streaming default settings", func() {
			client := cfhttp.NewClient(cfhttp.WithStreamingDefaults())
			transport := client.Transport.(*http.Transport)
			Expect(transport.DialContext).NotTo(BeNil())
			Expect(transport.IdleConnTimeout).To(Equal(90 * time.Second))
			Expect(transport.DisableKeepAlives).To(BeFalse())
		})
	})

	Describe(`with the "WithRequestTimeout" option`, func() {
		It("returns an HTTP client with a custom request timeout", func() {
			client := cfhttp.NewClient(cfhttp.WithRequestTimeout(1 * time.Nanosecond))
			Expect(client.Timeout).To(Equal(1 * time.Nanosecond))
		})
	})

	Describe(`with the "WithDialTimeout" option`, func() {
		It("returns an HTTP client with a custom DialTimeout", func() {
			client := cfhttp.NewClient(cfhttp.WithDialTimeout(1 * time.Nanosecond))
			_, err := client.Get("https://google.com")
			Expect(err).To(HaveOccurred())
		})
	})

	Describe(`with the "WithTCPKeepAliveTimeout" option`, func() {
		It("returns an HTTP client with a custom TCP keepalive timeout", func() {
			// I don't think there's an easy way to test this behavior
			client := cfhttp.NewClient(
				cfhttp.WithStreamingDefaults(),
				cfhttp.WithTCPKeepAliveTimeout(10*time.Second),
			)
			transport := client.Transport.(*http.Transport)
			Expect(transport.DialContext).NotTo(BeNil())
		})
	})

	Describe(`with the "WithIdleConnTimeout" option`, func() {
		It("returns an HTTP client with a custom IdleConnTimeout", func() {
			client := cfhttp.NewClient(cfhttp.WithIdleConnTimeout(10 * time.Second))
			transport := client.Transport.(*http.Transport)
			Expect(transport.IdleConnTimeout).To(Equal(10 * time.Second))
			Expect(transport.DisableKeepAlives).To(BeFalse())
		})
	})

	Describe(`with the "WithDisableKeepAlives" option`, func() {
		It("returns an HTTP client with HTTP keepalives disabled", func() {
			client := cfhttp.NewClient(cfhttp.WithDisableKeepAlives())
			transport := client.Transport.(*http.Transport)
			Expect(transport.DisableKeepAlives).To(BeTrue())
		})
	})

	Describe(`with the "WithTLSConfig" option`, func() {
		It("returns a transport with the TLS config set", func() {
			t := &tls.Config{
				ServerName: "test-server.com",
			}
			client := cfhttp.NewClient(cfhttp.WithTLSConfig(t))
			transport := client.Transport.(*http.Transport)
			Expect(transport.TLSClientConfig).To(Equal(t))
		})
	})

	Describe(`with the "WithMaxIdleConnsPerHost" option`, func() {
		It("returns a transport with the MaxIdleConnsPerHost set", func() {
			client := cfhttp.NewClient(cfhttp.WithMaxIdleConnsPerHost(100))
			transport := client.Transport.(*http.Transport)
			Expect(transport.MaxIdleConnsPerHost).To(Equal(100))
		})
	})
})
<|endoftext|>


<commit_before>package commands

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	trackCmd = &cobra.Command{
		Use:   "track",
		Short: "Manipulate .gitattributes",
		Run:   trackCommand,
	}
)

func trackCommand(cmd *cobra.Command, args []string) {
	if lfs.LocalGitDir == "" {
		Print("Not a git repository.")
		os.Exit(128)
	}

	lfs.InstallHooks(false)
	knownPaths := findPaths()

	if len(args) == 0 {
		Print("Listing tracked paths")
		for _, t := range knownPaths {
			Print("    %s (%s)", t.Path, t.Source)
		}
		return
	}

	addTrailingLinebreak := needsTrailingLinebreak(".gitattributes")
	attributesFile, err := os.OpenFile(".gitattributes", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)
	if err != nil {
		Print("Error opening .gitattributes file")
		return
	}
	defer attributesFile.Close()

	if addTrailingLinebreak {
		if _, err := attributesFile.WriteString("\n"); err != nil {
			Print("Error writing to .gitattributes")
		}
	}

ArgsLoop:
	for _, t := range args {
		for _, k := range knownPaths {
			if t == k.Path {
				Print("%s already supported", t)
				continue ArgsLoop
			}
		}

		encodedArg := strings.Replace(t, " ", "[[:space:]]", -1)
		_, err := attributesFile.WriteString(fmt.Sprintf("%s filter=lfs diff=lfs merge=lfs -crlf\n", encodedArg))
		if err != nil {
			Print("Error adding path %s", t)
			continue
		}
		Print("Tracking %s", t)
	}
}

type mediaPath struct {
	Path   string
	Source string
}

func findPaths() []mediaPath {
	paths := make([]mediaPath, 0)
	wd, _ := os.Getwd()

	for _, path := range findAttributeFiles() {
		attributes, err := os.Open(path)
		if err != nil {
			continue
		}

		scanner := bufio.NewScanner(attributes)
		for scanner.Scan() {
			line := scanner.Text()
			if line == "" {
				continue
			}

			if strings.Contains(line, "filter=lfs") {
				fields := strings.Fields(line)
				relPath, _ := filepath.Rel(wd, path)
				paths = append(paths, mediaPath{Path: fields[0], Source: relPath})
			}
		}
	}

	return paths
}

func findAttributeFiles() []string {
	paths := make([]string, 0)

	repoAttributes := filepath.Join(lfs.LocalGitDir, "info", "attributes")
	if info, err := os.Stat(repoAttributes); err == nil && !info.IsDir() {
		paths = append(paths, repoAttributes)
	}

	filepath.Walk(lfs.LocalWorkingDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() && (filepath.Base(path) == ".gitattributes") {
			paths = append(paths, path)
		}
		return nil
	})

	return paths
}

func needsTrailingLinebreak(filename string) bool {
	file, err := os.Open(filename)
	if err != nil {
		return false
	}
	defer file.Close()

	buf := make([]byte, 16384)
	bytesRead := 0
	for {
		n, err := file.Read(buf)
		if err == io.EOF {
			break
		} else if err != nil {
			return false
		}
		bytesRead = n
	}

	return !strings.HasSuffix(string(buf[0:bytesRead]), "\n")
}

func init() {
	RootCmd.AddCommand(trackCmd)
}
<commit_msg>アーア アアアア アーアー<commit_after>package commands

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

var (
	trackCmd = &cobra.Command{
		Use:   "track",
		Short: "Manipulate .gitattributes",
		Run:   trackCommand,
	}
)

func trackCommand(cmd *cobra.Command, args []string) {
	if lfs.LocalGitDir == "" {
		Print("Not a git repository.")
		os.Exit(128)
	}

	lfs.InstallHooks(false)
	knownPaths := findPaths()

	if len(args) == 0 {
		Print("Listing tracked paths")
		for _, t := range knownPaths {
			Print("    %s (%s)", t.Path, t.Source)
		}
		return
	}

	addTrailingLinebreak := needsTrailingLinebreak(".gitattributes")
	attributesFile, err := os.OpenFile(".gitattributes", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)
	if err != nil {
		Print("Error opening .gitattributes file")
		return
	}
	defer attributesFile.Close()

	if addTrailingLinebreak {
		if _, err := attributesFile.WriteString("\n"); err != nil {
			Print("Error writing to .gitattributes")
		}
	}

ArgsLoop:
	for _, t := range args {
		for _, k := range knownPaths {
			if t == k.Path {
				Print("%s already supported", t)
				continue ArgsLoop
			}
		}

		encodedArg := strings.Replace(t, " ", "[[:space:]]", -1)
		_, err := attributesFile.WriteString(fmt.Sprintf("%s filter=lfs diff=lfs merge=lfs -crlf\n", encodedArg))
		if err != nil {
			Print("Error adding path %s", t)
			continue
		}
		Print("Tracking %s", t)
	}
}

type mediaPath struct {
	Path   string
	Source string
}

func findPaths() []mediaPath {
	paths := make([]mediaPath, 0)
	wd, _ := os.Getwd()

	for _, path := range findAttributeFiles() {
		attributes, err := os.Open(path)
		if err != nil {
			continue
		}

		scanner := bufio.NewScanner(attributes)
		for scanner.Scan() {
			line := scanner.Text()
			if strings.Contains(line, "filter=lfs") {
				fields := strings.Fields(line)
				relPath, _ := filepath.Rel(wd, path)
				paths = append(paths, mediaPath{Path: fields[0], Source: relPath})
			}
		}
	}

	return paths
}

func findAttributeFiles() []string {
	paths := make([]string, 0)

	repoAttributes := filepath.Join(lfs.LocalGitDir, "info", "attributes")
	if info, err := os.Stat(repoAttributes); err == nil && !info.IsDir() {
		paths = append(paths, repoAttributes)
	}

	filepath.Walk(lfs.LocalWorkingDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() && (filepath.Base(path) == ".gitattributes") {
			paths = append(paths, path)
		}
		return nil
	})

	return paths
}

func needsTrailingLinebreak(filename string) bool {
	file, err := os.Open(filename)
	if err != nil {
		return false
	}
	defer file.Close()

	buf := make([]byte, 16384)
	bytesRead := 0
	for {
		n, err := file.Read(buf)
		if err == io.EOF {
			break
		} else if err != nil {
			return false
		}
		bytesRead = n
	}

	return !strings.HasSuffix(string(buf[0:bytesRead]), "\n")
}

func init() {
	RootCmd.AddCommand(trackCmd)
}
<|endoftext|>


<commit_before>package gitmedia

import (
	_ "../gitconfig"
	"bufio"
	"fmt"
	"os"
	"strings"
)

type TypesCommand struct {
	*Command
}

func (c *TypesCommand) Run() {
	var sub string
	if len(c.SubCommands) > 0 {
		sub = c.SubCommands[0]
	}

	switch sub {
	case "add":
		fmt.Println("Adding type")
	case "remove":
		fmt.Println("Removing type")
	default:
		fmt.Println("Listing types")
		listTypes()
	}

}

func listTypes() {
	attributes, err := os.Open(".gitattributes")
	if err != nil {
		return // No .gitattibtues == no file types
	}

	scanner := bufio.NewScanner(attributes)
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			continue
		}

		if strings.Contains(line, "filter=media") {
			fields := strings.Fields(line)
			fmt.Println("   ", fields[0])
		}
	}

}

func init() {
	registerCommand("types", func(c *Command) RunnableCommand {
		return &TypesCommand{Command: c}
	})
}
<commit_msg>add a media type<commit_after>package gitmedia

import (
	_ "../gitconfig"
	"bufio"
	"fmt"
	"os"
	"strings"
)

type TypesCommand struct {
	*Command
}

func (c *TypesCommand) Run() {
	var sub string
	if len(c.SubCommands) > 0 {
		sub = c.SubCommands[0]
	}

	switch sub {
	case "add":
		c.addType()
	case "remove":
		fmt.Println("Removing type")
	default:
		c.listTypes()
	}

}

func (c *TypesCommand) addType() {
	if len(c.SubCommands) < 2 {
		fmt.Println("git media types add <type> [type]*")
		return
	}

	knownTypes := findTypes()
	attributesFile, err := os.OpenFile(".gitattributes", os.O_RDWR|os.O_APPEND, 0660)
	if err != nil {
		fmt.Println("Error opening .gitattributes file")
		return
	}

	for _, t := range c.SubCommands[1:] {
		isKnownType := false
		for _, k := range knownTypes {
			if t == k {
				isKnownType = true
			}
		}

		if isKnownType {
			fmt.Println(t, "already supported")
			continue
		}

		_, err := attributesFile.WriteString(fmt.Sprintf("%s filter=media -crlf", t))
		if err != nil {
			fmt.Println("Error adding type", t)
			continue
		}
		fmt.Println("Adding type", t)
	}

	attributesFile.Close()
}

func (c *TypesCommand) listTypes() {
	fmt.Println("Listing types")
	knownTypes := findTypes()
	for _, t := range knownTypes {
		fmt.Println("    ", t)
	}
}

func findTypes() []string {
	types := make([]string, 0)

	attributes, err := os.Open(".gitattributes")
	if err != nil {
		return types // No .gitattibtues == no file types
	}

	scanner := bufio.NewScanner(attributes)
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			continue
		}

		if strings.Contains(line, "filter=media") {
			fields := strings.Fields(line)
			types = append(types, fields[0])
		}
	}

	return types
}

func init() {
	registerCommand("types", func(c *Command) RunnableCommand {
		return &TypesCommand{Command: c}
	})
}
<|endoftext|>


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

package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"gopkg.in/gcfg.v1"
	"net/http"
	"path/filepath"
	"strings"
	"testing"
	"time"

	_ "github.com/lib/pq"
)

const migAPIPort uint16 = 12345

type heartbeatResponse struct {
	Error *string `json:"error"`
}

func postHeartbeat(port uint16, body string) (int, heartbeatResponse, error) {
	response, err := http.Post(
		fmt.Sprintf("http://127.0.0.1:%d/api/v1/heartbeat", port),
		"application/json",
		strings.NewReader(body))
	if err != nil {
		return 0, heartbeatResponse{nil}, err
	}

	respData := heartbeatResponse{}
	decoder := json.NewDecoder(response.Body)
	decodeErr := decoder.Decode(&respData)

	response.Body.Close()

	if decodeErr != nil {
		return 0, heartbeatResponse{nil}, decodeErr
	}

	return response.StatusCode, respData, nil
}

type Config struct {
	Postgres struct {
		Host, User, Password, DBName, SSLMode string
		Port, MaxConn                         int
	}
}

func TestPostHeartbeatWithValidRequest(t *testing.T) {
	agentName := "testagent123"
	statusCode, response, err := postHeartbeat(migAPIPort, fmt.Sprintf(`{
    "name": "%s",
    "mode": "checkin",
    "version": "20181012-0.abc123.dev",
    "pid": 1234,
    "queueLoc": "testagent",
    "startTime": "%s",
    "environment": {
      "init": "systemd",
      "ident": "Ubuntu 16.04",
      "os": "linux",
      "arch": "x86_64",
      "proxied": false,
      "proxy": "",
      "addresses": ["127.0.0.1"],
      "publicIP": "127.0.0.1",
      "modules": ["memory", "file"]
    },
    "tags": [
      {
        "name": "operator",
        "value": "tester"
      }
    ]
  }`, agentName, time.Now().Format(time.RFC3339)))

	errMsg := ""
	if response.Error != nil {
		errMsg = *response.Error
	}

	if err != nil {
		t.Fatalf("Failed to make request or decode response: %s", err.Error())
	}
	if statusCode != http.StatusOK {
		t.Errorf("Expected status code %d, got %d", http.StatusOK, statusCode)
	}
	if errMsg != "" {
		t.Errorf("Did not expect an error from API, got '%s'", errMsg)
	}

	path, err := filepath.Abs("../../api.cfg")
	if err != nil {
		panic(err)
	}

	cfg := Config{}
	err = gcfg.FatalOnly(gcfg.ReadFileInto(&cfg, path))
	if err != nil {
		panic(err)
	}

	user := cfg.Postgres.User
	password := cfg.Postgres.Password
	host := cfg.Postgres.Host
	port := cfg.Postgres.Port
	dbname := cfg.Postgres.DBName
	sslmode := cfg.Postgres.SSLMode

	url := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s", user, password, host, port, dbname, sslmode)
	db_conn, err := sql.Open("postgres", url)
	if err != nil {
		t.Fatalf("Failed to connect to postgresl DB: %s", err.Error())
	}

	defer db_conn.Close()

	rows, err := db_conn.Query("SELECT name FROM agents WHERE mode='checkin'")
	if err != nil {
		t.Fatalf("Received error when querying for heartbeats: %v", err)
	}

	if rows != nil {
		defer rows.Close()
	}

	numRows := 0
	for rows.Next() {
		numRows++
		var name string
		err = rows.Scan(&name)
		if err != nil {
			err = fmt.Errorf("Error while parsing name: '%v'", err)
			return
		}
		if name != agentName {
			t.Fatalf("Expected heartbeat with agent name: %s got %s", agentName, name)
		}
	}
}
<commit_msg>Add missing check for num rows<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Zack Mullaly zmullaly@mozilla.com [:zack]

package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"gopkg.in/gcfg.v1"
	"net/http"
	"path/filepath"
	"strings"
	"testing"
	"time"

	_ "github.com/lib/pq"
)

const migAPIPort uint16 = 12345

type heartbeatResponse struct {
	Error *string `json:"error"`
}

func postHeartbeat(port uint16, body string) (int, heartbeatResponse, error) {
	response, err := http.Post(
		fmt.Sprintf("http://127.0.0.1:%d/api/v1/heartbeat", port),
		"application/json",
		strings.NewReader(body))
	if err != nil {
		return 0, heartbeatResponse{nil}, err
	}

	respData := heartbeatResponse{}
	decoder := json.NewDecoder(response.Body)
	decodeErr := decoder.Decode(&respData)

	response.Body.Close()

	if decodeErr != nil {
		return 0, heartbeatResponse{nil}, decodeErr
	}

	return response.StatusCode, respData, nil
}

type Config struct {
	Postgres struct {
		Host, User, Password, DBName, SSLMode string
		Port, MaxConn                         int
	}
}

func TestPostHeartbeatWithValidRequest(t *testing.T) {
	agentName := "testagent123"
	statusCode, response, err := postHeartbeat(migAPIPort, fmt.Sprintf(`{
    "name": "%s",
    "mode": "checkin",
    "version": "20181012-0.abc123.dev",
    "pid": 1234,
    "queueLoc": "testagent",
    "startTime": "%s",
    "environment": {
      "init": "systemd",
      "ident": "Ubuntu 16.04",
      "os": "linux",
      "arch": "x86_64",
      "proxied": false,
      "proxy": "",
      "addresses": ["127.0.0.1"],
      "publicIP": "127.0.0.1",
      "modules": ["memory", "file"]
    },
    "tags": [
      {
        "name": "operator",
        "value": "tester"
      }
    ]
  }`, agentName, time.Now().Format(time.RFC3339)))

	errMsg := ""
	if response.Error != nil {
		errMsg = *response.Error
	}

	if err != nil {
		t.Fatalf("Failed to make request or decode response: %s", err.Error())
	}
	if statusCode != http.StatusOK {
		t.Errorf("Expected status code %d, got %d", http.StatusOK, statusCode)
	}
	if errMsg != "" {
		t.Errorf("Did not expect an error from API, got '%s'", errMsg)
	}

	path, err := filepath.Abs("../../api.cfg")
	if err != nil {
		panic(err)
	}

	cfg := Config{}
	err = gcfg.FatalOnly(gcfg.ReadFileInto(&cfg, path))
	if err != nil {
		panic(err)
	}

	user := cfg.Postgres.User
	password := cfg.Postgres.Password
	host := cfg.Postgres.Host
	port := cfg.Postgres.Port
	dbname := cfg.Postgres.DBName
	sslmode := cfg.Postgres.SSLMode

	url := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s", user, password, host, port, dbname, sslmode)
	db_conn, err := sql.Open("postgres", url)
	if err != nil {
		t.Fatalf("Failed to connect to postgresl DB: %s", err.Error())
	}

	defer db_conn.Close()

	rows, err := db_conn.Query("SELECT name FROM agents WHERE mode='checkin'")
	if err != nil {
		t.Fatalf("Received error when querying for heartbeats: %v", err)
	}

	if rows != nil {
		defer rows.Close()
	}

	numRows := 0
	for rows.Next() {
		numRows++
		var name string
		err = rows.Scan(&name)
		if err != nil {
			err = fmt.Errorf("Error while parsing name: '%v'", err)
			return
		}
		if name != agentName {
			t.Fatalf("Expected heartbeat with agent name: %s got %s", agentName, name)
		}
	}
	if numRows != 1 {
		t.Fatalf("Expected 1 row, got %d", numRows)
	}
}
<|endoftext|>


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

package gc

import (
	"bytes"
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// TODO: move all these tests elsewhere?
// Perhaps teach test/run.go how to run them with a new action verb.
func runTest(t *testing.T, filename string) {
	t.Parallel()
	doTest(t, filename, "run")
}
func buildTest(t *testing.T, filename string) {
	t.Parallel()
	doTest(t, filename, "build")
}
func doTest(t *testing.T, filename string, kind string) {
	testenv.MustHaveGoBuild(t)
	gotool := testenv.GoToolPath(t)
	tmpdir, ok := ioutil.TempDir("", "ssatest")
	if ok != nil {
		t.Fatalf("Failed to create temporary directory")
	}
	defer os.RemoveAll(tmpdir)

	var stdout, stderr bytes.Buffer
	cmd := exec.Command(gotool, kind, "-gcflags=-d=ssa/check/on", filepath.Join("testdata", filename))
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	if s := stdout.String(); s != "" {
		t.Errorf("Stdout = %s\nWant empty", s)
	}
	if s := stderr.String(); strings.Contains(s, "SSA unimplemented") {
		t.Errorf("Unimplemented message found in stderr:\n%s", s)
	}
}

// runGenTest runs a test-generator, then runs the generated test.
// Generated test can either fail in compilation or execution.
// The environment variable parameter(s) is passed to the run
// of the generated test.
func runGenTest(t *testing.T, filename, tmpname string, ev ...string) {
	testenv.MustHaveGoRun(t)
	gotool := testenv.GoToolPath(t)
	var stdout, stderr bytes.Buffer
	cmd := exec.Command(gotool, "run", filepath.Join("testdata", filename))
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	// Write stdout into a temporary file
	tmpdir, ok := ioutil.TempDir("", tmpname)
	if ok != nil {
		t.Fatalf("Failed to create temporary directory")
	}

	rungo := filepath.Join(tmpdir, "run.go")
	ok = ioutil.WriteFile(rungo, stdout.Bytes(), 0600)
	if ok != nil {
		t.Fatalf("Failed to create temporary file " + rungo)
	}

	stdout.Reset()
	stderr.Reset()
	cmd = exec.Command("go", "run", "-gcflags=-d=ssa/check/on", rungo)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	cmd.Env = append(cmd.Env, ev...)
	err := cmd.Run()
	if err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	if s := stderr.String(); s != "" {
		t.Errorf("Stderr = %s\nWant empty", s)
	}
	if s := stdout.String(); s != "" {
		t.Errorf("Stdout = %s\nWant empty", s)
	}
}

func TestGenFlowGraph(t *testing.T) {
	runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp1")
	if runtime.GOOS != "windows" {
		runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp2", "GO_SSA_PHI_LOC_CUTOFF=0")
	}
}

// TestShortCircuit tests OANDAND and OOROR expressions and short circuiting.
func TestShortCircuit(t *testing.T) { runTest(t, "short.go") }

// TestBreakContinue tests that continue and break statements do what they say.
func TestBreakContinue(t *testing.T) { runTest(t, "break.go") }

// TestTypeAssertion tests type assertions.
func TestTypeAssertion(t *testing.T) { runTest(t, "assert.go") }

// TestArithmetic tests that both backends have the same result for arithmetic expressions.
func TestArithmetic(t *testing.T) { runTest(t, "arith.go") }

// TestFP tests that both backends have the same result for floating point expressions.
func TestFP(t *testing.T) { runTest(t, "fp.go") }

// TestArithmeticBoundary tests boundary results for arithmetic operations.
func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary.go") }

// TestArithmeticConst tests results for arithmetic operations against constants.
func TestArithmeticConst(t *testing.T) { runTest(t, "arithConst.go") }

func TestChan(t *testing.T) { runTest(t, "chan.go") }

// TestComparisonsConst tests results for comparison operations against constants.
func TestComparisonsConst(t *testing.T) { runTest(t, "cmpConst.go") }

func TestCompound(t *testing.T) { runTest(t, "compound.go") }

func TestCtl(t *testing.T) { runTest(t, "ctl.go") }

func TestLoadStore(t *testing.T) { runTest(t, "loadstore.go") }

func TestMap(t *testing.T) { runTest(t, "map.go") }

func TestRegalloc(t *testing.T) { runTest(t, "regalloc.go") }

func TestString(t *testing.T) { runTest(t, "string.go") }

func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn.go") }

// TestClosure tests closure related behavior.
func TestClosure(t *testing.T) { runTest(t, "closure.go") }

func TestArray(t *testing.T) { runTest(t, "array.go") }

func TestAppend(t *testing.T) { runTest(t, "append.go") }

func TestZero(t *testing.T) { runTest(t, "zero.go") }

func TestAddressed(t *testing.T) { runTest(t, "addressed.go") }

func TestCopy(t *testing.T) { runTest(t, "copy.go") }

func TestUnsafe(t *testing.T) { runTest(t, "unsafe.go") }

func TestPhi(t *testing.T) { runTest(t, "phi.go") }

func TestSlice(t *testing.T) { runTest(t, "slice.go") }

func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") }

func TestDuplicateLoad(t *testing.T) { runTest(t, "dupLoad.go") }

func TestSqrt(t *testing.T) { runTest(t, "sqrt_const.go") }
<commit_msg>cmd/compile: remove unnecessary tmpdir in ssa_test<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gc

import (
	"bytes"
	"internal/testenv"
	"io/ioutil"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// TODO: move all these tests elsewhere?
// Perhaps teach test/run.go how to run them with a new action verb.
func runTest(t *testing.T, filename string) {
	t.Parallel()
	doTest(t, filename, "run")
}
func buildTest(t *testing.T, filename string) {
	t.Parallel()
	doTest(t, filename, "build")
}
func doTest(t *testing.T, filename string, kind string) {
	testenv.MustHaveGoBuild(t)
	gotool := testenv.GoToolPath(t)

	var stdout, stderr bytes.Buffer
	cmd := exec.Command(gotool, kind, "-gcflags=-d=ssa/check/on", filepath.Join("testdata", filename))
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	if s := stdout.String(); s != "" {
		t.Errorf("Stdout = %s\nWant empty", s)
	}
	if s := stderr.String(); strings.Contains(s, "SSA unimplemented") {
		t.Errorf("Unimplemented message found in stderr:\n%s", s)
	}
}

// runGenTest runs a test-generator, then runs the generated test.
// Generated test can either fail in compilation or execution.
// The environment variable parameter(s) is passed to the run
// of the generated test.
func runGenTest(t *testing.T, filename, tmpname string, ev ...string) {
	testenv.MustHaveGoRun(t)
	gotool := testenv.GoToolPath(t)
	var stdout, stderr bytes.Buffer
	cmd := exec.Command(gotool, "run", filepath.Join("testdata", filename))
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	// Write stdout into a temporary file
	tmpdir, ok := ioutil.TempDir("", tmpname)
	if ok != nil {
		t.Fatalf("Failed to create temporary directory")
	}

	rungo := filepath.Join(tmpdir, "run.go")
	ok = ioutil.WriteFile(rungo, stdout.Bytes(), 0600)
	if ok != nil {
		t.Fatalf("Failed to create temporary file " + rungo)
	}

	stdout.Reset()
	stderr.Reset()
	cmd = exec.Command("go", "run", "-gcflags=-d=ssa/check/on", rungo)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	cmd.Env = append(cmd.Env, ev...)
	err := cmd.Run()
	if err != nil {
		t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
	}
	if s := stderr.String(); s != "" {
		t.Errorf("Stderr = %s\nWant empty", s)
	}
	if s := stdout.String(); s != "" {
		t.Errorf("Stdout = %s\nWant empty", s)
	}
}

func TestGenFlowGraph(t *testing.T) {
	runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp1")
	if runtime.GOOS != "windows" {
		runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp2", "GO_SSA_PHI_LOC_CUTOFF=0")
	}
}

// TestShortCircuit tests OANDAND and OOROR expressions and short circuiting.
func TestShortCircuit(t *testing.T) { runTest(t, "short.go") }

// TestBreakContinue tests that continue and break statements do what they say.
func TestBreakContinue(t *testing.T) { runTest(t, "break.go") }

// TestTypeAssertion tests type assertions.
func TestTypeAssertion(t *testing.T) { runTest(t, "assert.go") }

// TestArithmetic tests that both backends have the same result for arithmetic expressions.
func TestArithmetic(t *testing.T) { runTest(t, "arith.go") }

// TestFP tests that both backends have the same result for floating point expressions.
func TestFP(t *testing.T) { runTest(t, "fp.go") }

// TestArithmeticBoundary tests boundary results for arithmetic operations.
func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary.go") }

// TestArithmeticConst tests results for arithmetic operations against constants.
func TestArithmeticConst(t *testing.T) { runTest(t, "arithConst.go") }

func TestChan(t *testing.T) { runTest(t, "chan.go") }

// TestComparisonsConst tests results for comparison operations against constants.
func TestComparisonsConst(t *testing.T) { runTest(t, "cmpConst.go") }

func TestCompound(t *testing.T) { runTest(t, "compound.go") }

func TestCtl(t *testing.T) { runTest(t, "ctl.go") }

func TestLoadStore(t *testing.T) { runTest(t, "loadstore.go") }

func TestMap(t *testing.T) { runTest(t, "map.go") }

func TestRegalloc(t *testing.T) { runTest(t, "regalloc.go") }

func TestString(t *testing.T) { runTest(t, "string.go") }

func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn.go") }

// TestClosure tests closure related behavior.
func TestClosure(t *testing.T) { runTest(t, "closure.go") }

func TestArray(t *testing.T) { runTest(t, "array.go") }

func TestAppend(t *testing.T) { runTest(t, "append.go") }

func TestZero(t *testing.T) { runTest(t, "zero.go") }

func TestAddressed(t *testing.T) { runTest(t, "addressed.go") }

func TestCopy(t *testing.T) { runTest(t, "copy.go") }

func TestUnsafe(t *testing.T) { runTest(t, "unsafe.go") }

func TestPhi(t *testing.T) { runTest(t, "phi.go") }

func TestSlice(t *testing.T) { runTest(t, "slice.go") }

func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") }

func TestDuplicateLoad(t *testing.T) { runTest(t, "dupLoad.go") }

func TestSqrt(t *testing.T) { runTest(t, "sqrt_const.go") }
<|endoftext|>


<commit_before><commit_msg>Fix issue #106. Cleanup Queue after resource removal<commit_after><|endoftext|>


<commit_before><commit_msg>Fixes CC-1202: Panic in go-dockerclient<commit_after><|endoftext|>


<commit_before>package inster

import (
	"sort"

	"github.com/catorpilor/leetcode/utils"
)

func createSortedArray(ins []int) int {
	return useBF(ins)
}

// useBF time complexity O(N^2*log(N)), space complexity O(N)
func useBF(instructions []int) int {
	n := len(instructions)
	nums := make([]int, 0, n)
	var ans int
	for _, num := range instructions {
		ans += cost(nums, num)
		nums = append(nums, num)
		sort.Ints(nums)
	}
	return ans
}

func cost(nums []int, target int) int {
	if len(nums) == 0 || nums[0] >= target || nums[len(nums)-1] <= target {
		return 0
	}
	return utils.Min(lb(nums, target), up(nums, target))
}

// lb lower_bound find the proper position for target, time complexity O(log(N))
func lb(nums []int, target int) int {
	l, r := 0, len(nums)-1
	for l < r {
		mid := l + (r-l)>>1
		if nums[mid] >= target {
			r = mid
		} else {
			l = mid + 1
		}
	}
	// fmt.Printf("lower_bound nums:%v with target: %d return: %d\n", nums, target, l)
	return l
}

// up upper_bound find the proper position for target, time complexity O(log(N))
func up(nums []int, target int) int {
	l, r := 0, len(nums)-1
	for l < r {
		mid := r - (r-l)>>1
		if nums[mid] <= target {
			l = mid
		} else {
			r = mid - 1
		}
	}
	// fmt.Printf("upper_bound nums:%v with target: %d return: %d\n", nums, target, l)
	return len(nums) - l - 1
}
<commit_msg>solve 1649 use slice tricks and fix upper_bound<commit_after>package inster

import (
	"github.com/catorpilor/leetcode/utils"
)

func createSortedArray(ins []int) int {
	return useBF(ins)
}

const (
	mod = int(1e9 + 7)
)

// useBF time complexity O(N^2*log(N)), space complexity O(N)
func useBF(instructions []int) int {
	n := len(instructions)
	nums := make([]int, 0, n)
	var ans int
	for i, num := range instructions {
		lc, rc := cost(nums, num)
		ans += utils.Min(lc, i-rc)
		nums = append(nums, 0)
		copy(nums[rc+1:], nums[rc:])
		nums[rc] = num
	}
	return ans % mod
}

func cost(nums []int, target int) (int, int) {
	if len(nums) == 0 {
		return 0, 0
	}
	return lb(nums, target), upper_bound(nums, target)
}

// lb lower_bound find the proper position for target, time complexity O(log(N))
func lb(nums []int, target int) int {
	l, r := 0, len(nums)-1
	for l < r {
		mid := l + (r-l)>>1
		if nums[mid] >= target {
			r = mid
		} else {
			l = mid + 1
		}
	}
	// fmt.Printf("lower_bound nums:%v with target: %d return: %d\n", nums, target, l)
	return l
}

// up upper_bound find the proper position for target, time complexity O(log(N))
// func up(nums []int, target int) int {
// 	l, r := 0, len(nums)-1
// 	if l == r && target > nums[l] {
// 		return l + 1
// 	}
// 	for l < r {
// 		mid := r - (r-l)>>1
// 		if nums[mid] <= target {
// 			l = mid
// 		} else {
// 			r = mid - 1
// 		}
// 	}
// 	fmt.Printf("upper_bound nums:%v with target: %d return: %d\n", nums, target, l)
// 	return l
// }

/*
template<class ForwardIt, class T, class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
    ForwardIt it;
    typename std::iterator_traits<ForwardIt>::difference_type count, step;
    count = std::distance(first, last);

    while (count > 0) {
        it = first;
        step = count / 2;
        std::advance(it, step);
        if (!comp(value, *it)) {
            first = ++it;
            count -= step + 1;
        }
        else
            count = step;
    }
    return first;
}
*/

func upper_bound(nums []int, target int) int {
	count := len(nums)
	l := 0
	for count > 0 {
		step := count >> 1
		mid := l + step
		if nums[mid] <= target {
			l = mid + 1
			count -= step + 1
		} else {
			count = step
		}
	}
	// fmt.Printf("upper_bound nums:%v with target: %d return: %d\n", nums, target, l)
	return l
}
<|endoftext|>


<commit_before>package values_test

import (
	"testing"

	"github.com/xgfone/go-tools/values"
)

func TestSlice(t *testing.T) {
	ms := []interface{}{"test"}
	ss := []interface{}{11, "aa", values.SMap{"abcd": 11, "ok": false, "slice": values.Slice(ms)}, true}
	s := values.Slice(ss)

	if _, ok := s.Int(0); !ok {
		t.Fail()
	}

	if _, ok := s.String(1); !ok {
		t.Fail()
	}

	if v, ok := s.SMap(2); !ok {
		t.Fail()
	} else {
		if _, ok := v.Int("abcd"); !ok {
			t.Fail()
		}

		if _, ok := v.Bool("ok"); !ok {
			t.Fail()
		}

		if _s, ok := v.Slice("slice"); !ok {
			t.Fail()
		} else {
			if _, ok := _s.String(0); !ok {
				t.Fail()
			}
		}
	}

	if _, ok := s.Bool(3); !ok {
		t.Fail()
	}
}
<commit_msg>Enhance the test of values<commit_after>package values_test

import (
	"testing"

	"github.com/xgfone/go-tools/values"
)

func TestSlice(t *testing.T) {
	ms := []interface{}{"test"}
	ss := []interface{}{11, "aa", values.SMap{"abcd": 11, "ok": false, "slice": values.Slice(ms)}, true}
	s := values.Slice(ss)

	if v, ok := s.Int(0); !ok || v != 11 {
		t.Fail()
	}

	if v, ok := s.String(1); !ok || v != "aa" {
		t.Fail()
	}

	if v, ok := s.SMap(2); !ok {
		t.Fail()
	} else {
		if vv, ok := v.Int("abcd"); !ok || vv != 11 {
			t.Fail()
		}

		if vv, ok := v.Bool("ok"); !ok || vv != false {
			t.Fail()
		}

		if _s, ok := v.Slice("slice"); !ok {
			t.Fail()
		} else {
			if v, ok := _s.String(0); !ok || v != "test" {
				t.Fail()
			}
		}
	}

	if _, ok := s.Bool(3); !ok {
		t.Fail()
	}
}
<|endoftext|>


<commit_before><commit_msg>corrected mistake<commit_after><|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Write out a file of a certain size, close it, then measure the performance
// of doing the following:
//
// 1.  Open the file.
// 2.  Read it from start to end with a configurable buffer size.
//
package main

import (
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"time"

	"github.com/googlecloudplatform/gcsfuse/benchmarks/internal/format"
	"github.com/googlecloudplatform/gcsfuse/benchmarks/internal/percentile"
)

var fDir = flag.String("dir", "", "Directory within which to write the file.")
var fDuration = flag.Duration("duration", 5*time.Second, "How long to run.")
var fFileSize = flag.Int64("file_size", 1<<20, "Size of file to use.")
var fReadSize = flag.Int64("read_size", 1<<14, "Size of each call to read(2).")

////////////////////////////////////////////////////////////////////////
// main logic
////////////////////////////////////////////////////////////////////////

func run() (err error) {
	if *fDir == "" {
		err = errors.New("You must set --dir.")
		return
	}

	// Create a temporary file.
	log.Printf("Creating a temporary file in %s.", *fDir)

	f, err := ioutil.TempFile(*fDir, "sequential_read")
	if err != nil {
		err = fmt.Errorf("TempFile: %v", err)
		return
	}

	path := f.Name()

	// Make sure we clean it up later.
	defer func() {
		log.Printf("Deleting %s.", path)
		os.Remove(path)
	}()

	// Fill it with random content.
	log.Printf("Writing %d random bytes.", *fFileSize)
	_, err = io.Copy(f, io.LimitReader(rand.Reader, *fFileSize))
	if err != nil {
		err = fmt.Errorf("Copying random bytes: %v", err)
		return
	}

	// Finish off the file.
	err = f.Close()
	if err != nil {
		err = fmt.Errorf("Closing file: %v", err)
		return
	}

	// Run several iterations.
	log.Printf("Measuring for %v...", *fDuration)

	var fullFileRead percentile.DurationSlice
	var singleReadCall percentile.DurationSlice
	buf := make([]byte, *fReadSize)

	overallStartTime := time.Now()
	for len(fullFileRead) == 0 || time.Since(overallStartTime) < *fDuration {
		// Open the file for reading.
		f, err = os.Open(path)
		if err != nil {
			err = fmt.Errorf("Opening file: %v", err)
			return
		}

		// Read the whole thing.
		fileStartTime := time.Now()
		for err == nil {
			readStartTime := time.Now()
			_, err = f.Read(buf)
			singleReadCall = append(singleReadCall, time.Since(readStartTime))
		}

		fullFileRead = append(fullFileRead, time.Since(fileStartTime))

		switch {
		case err == io.EOF:
			err = nil

		case err != nil:
			err = fmt.Errorf("Reading: %v", err)
			return
		}

		// Close the file.
		err = f.Close()
		if err != nil {
			err = fmt.Errorf("Closing file after reading: %v", err)
			return
		}
	}

	sort.Sort(fullFileRead)
	sort.Sort(singleReadCall)

	log.Printf(
		"Read the file %d times, using %d calls to read(2).",
		len(fullFileRead),
		len(singleReadCall))

	// Report.
	ptiles := []int{50, 90, 98}

	reportSlice := func(
		name string,
		bytesPerObservation int64,
		observations percentile.DurationSlice) {
		fmt.Printf("\n%s:\n", name)
		for _, ptile := range ptiles {
			d := percentile.Duration(observations, ptile)
			seconds := float64(d) / float64(time.Second)
			bandwidthBytesPerSec := float64(bytesPerObservation) / seconds

			fmt.Printf(
				"  %02dth ptile: %10v (%s/s)\n",
				ptile,
				d,
				format.Bytes(bandwidthBytesPerSec))
		}
	}

	reportSlice("Full-file read times", *fFileSize, fullFileRead)
	reportSlice("read(2) latencies", *fReadSize, singleReadCall)

	fmt.Println()

	return
}

func main() {
	log.SetFlags(log.Lmicroseconds | log.Lshortfile)
	flag.Parse()

	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Improved flag defaults for read_full_file.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Write out a file of a certain size, close it, then measure the performance
// of doing the following:
//
// 1.  Open the file.
// 2.  Read it from start to end with a configurable buffer size.
//
package main

import (
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"time"

	"github.com/googlecloudplatform/gcsfuse/benchmarks/internal/format"
	"github.com/googlecloudplatform/gcsfuse/benchmarks/internal/percentile"
)

var fDir = flag.String("dir", "", "Directory within which to write the file.")
var fDuration = flag.Duration("duration", 10*time.Second, "How long to run.")
var fFileSize = flag.Int64("file_size", 1<<26, "Size of file to use.")
var fReadSize = flag.Int64("read_size", 1<<20, "Size of each call to read(2).")

////////////////////////////////////////////////////////////////////////
// main logic
////////////////////////////////////////////////////////////////////////

func run() (err error) {
	if *fDir == "" {
		err = errors.New("You must set --dir.")
		return
	}

	// Create a temporary file.
	log.Printf("Creating a temporary file in %s.", *fDir)

	f, err := ioutil.TempFile(*fDir, "sequential_read")
	if err != nil {
		err = fmt.Errorf("TempFile: %v", err)
		return
	}

	path := f.Name()

	// Make sure we clean it up later.
	defer func() {
		log.Printf("Deleting %s.", path)
		os.Remove(path)
	}()

	// Fill it with random content.
	log.Printf("Writing %d random bytes.", *fFileSize)
	_, err = io.Copy(f, io.LimitReader(rand.Reader, *fFileSize))
	if err != nil {
		err = fmt.Errorf("Copying random bytes: %v", err)
		return
	}

	// Finish off the file.
	err = f.Close()
	if err != nil {
		err = fmt.Errorf("Closing file: %v", err)
		return
	}

	// Run several iterations.
	log.Printf("Measuring for %v...", *fDuration)

	var fullFileRead percentile.DurationSlice
	var singleReadCall percentile.DurationSlice
	buf := make([]byte, *fReadSize)

	overallStartTime := time.Now()
	for len(fullFileRead) == 0 || time.Since(overallStartTime) < *fDuration {
		// Open the file for reading.
		f, err = os.Open(path)
		if err != nil {
			err = fmt.Errorf("Opening file: %v", err)
			return
		}

		// Read the whole thing.
		fileStartTime := time.Now()
		for err == nil {
			readStartTime := time.Now()
			_, err = f.Read(buf)
			singleReadCall = append(singleReadCall, time.Since(readStartTime))
		}

		fullFileRead = append(fullFileRead, time.Since(fileStartTime))

		switch {
		case err == io.EOF:
			err = nil

		case err != nil:
			err = fmt.Errorf("Reading: %v", err)
			return
		}

		// Close the file.
		err = f.Close()
		if err != nil {
			err = fmt.Errorf("Closing file after reading: %v", err)
			return
		}
	}

	sort.Sort(fullFileRead)
	sort.Sort(singleReadCall)

	log.Printf(
		"Read the file %d times, using %d calls to read(2).",
		len(fullFileRead),
		len(singleReadCall))

	// Report.
	ptiles := []int{50, 90, 98}

	reportSlice := func(
		name string,
		bytesPerObservation int64,
		observations percentile.DurationSlice) {
		fmt.Printf("\n%s:\n", name)
		for _, ptile := range ptiles {
			d := percentile.Duration(observations, ptile)
			seconds := float64(d) / float64(time.Second)
			bandwidthBytesPerSec := float64(bytesPerObservation) / seconds

			fmt.Printf(
				"  %02dth ptile: %10v (%s/s)\n",
				ptile,
				d,
				format.Bytes(bandwidthBytesPerSec))
		}
	}

	reportSlice("Full-file read times", *fFileSize, fullFileRead)
	reportSlice("read(2) latencies", *fReadSize, singleReadCall)

	fmt.Println()

	return
}

func main() {
	log.SetFlags(log.Lmicroseconds | log.Lshortfile)
	flag.Parse()

	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>