<commit_before>package aat

import (
	"context"
	"testing"
	"time"

	"github.com/fortytw2/leaktest"
	"github.com/gammazero/nexus/v3/client"
	"github.com/gammazero/nexus/v3/wamp"
)

const (
	metaKill           = string(wamp.MetaProcSessionKill)
	metaKillByAuthid   = string(wamp.MetaProcSessionKillByAuthid)
	metaKillByAuthrole = string(wamp.MetaProcSessionKillByAuthrole)
	metaKillAll        = string(wamp.MetaProcSessionKillAll)

	metaModifyDetails = string(wamp.MetaProcSessionModifyDetails)
)

func TestSessionKill(t *testing.T) {
	defer leaktest.Check(t)()

	cli1, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	cli2, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	cli3, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill a client-3
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	args := wamp.List{cli3.ID()}
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-3 was booted.
	select {
	case <-cli3.Done():
	case <-time.After(time.Second):
		t.Fatal("Client 3 did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := cli3.RouterGoodbye()
	if goodbye == nil {
		t.Error("Did not receive goodbye from router")
	}
	if goodbye.Reason != reason {
		t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
	}
	if gm, ok := wamp.AsString(goodbye.Details["message"]); ok {
		if gm != message {
			t.Error("Did not get expected goodbye message, got:", gm)
		}
	} else {
		t.Error("Expected message in GOODBYE")
	}

	// Check that client-2 is still connected.
	select {
	case <-cli2.Done():
		t.Fatal("Client 2 should still be connected")
	default:
	}

	// Test that trying to kill self receives error.
	args = wamp.List{cli1.ID}
	result, err = cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err == nil {
		t.Fatal("Expected error")
	}
	rpcErr, ok := err.(client.RPCError)
	if !ok {
		t.Fatal("Expected RPCError")
	}
	if rpcErr.Err.Error != wamp.ErrNoSuchSession {
		t.Error("Wrong error, got", rpcErr.Err.Error, "expected", wamp.ErrNoSuchSession)
	}

	// Test that killing a sesson that does not exist works correctly.
	ctx, c2 := context.WithTimeout(context.Background(), time.Second)
	defer c2()
	args = wamp.List{wamp.ID(12345)}
	kwArgs = wamp.Dict{"reason": reason, "message": message}
	result, err = cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err == nil {
		t.Error("Expected error")
	} else if _, ok := err.(client.RPCError); !ok {
		t.Fatal("Expected RPCError")
	}

	// Make sure everything closes correctly.
	if err = cli3.Close(); err != nil {
		t.Error(err)
	}
	if err = cli2.Close(); err != nil {
		t.Error(err)
	}
	if err = cli1.Close(); err != nil {
		t.Error(err)
	}
}

func TestSessionKillAll(t *testing.T) {
	defer leaktest.Check(t)()

	cli1, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli1.Close()

	cli2, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli2.Close()

	cli3, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli3.Close()

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill a client-3
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := cli1.Call(ctx, metaKillAll, nil, nil, kwArgs, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-3 was booted.
	select {
	case <-cli3.Done():
	case <-time.After(time.Second):
		t.Fatal("Client 3 did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := cli3.RouterGoodbye()
	if goodbye == nil {
		t.Error("Did not receive goodbye from router")
	}
	if goodbye.Reason != reason {
		t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
	}
	gm, ok := wamp.AsString(goodbye.Details["message"])
	if !ok {
		t.Error("Expected message in GOODBYE")
	} else if gm != message {
		t.Error("Did not get expected goodbye message, got:", gm)
	}

	// Check that client-2 was booted.
	select {
	case <-cli2.Done():
	case <-time.After(time.Second):
		t.Fatal("Client 2 did not shutdown")
	}

	// Test that client-1 still connected.
	select {
	case <-cli1.Done():
		t.Fatal("Client 1 should still be connected")
	default:
	}

	cli4, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli4.Close()

	// Call killall again, with no reason.
	ctx, c2 := context.WithTimeout(context.Background(), time.Second)
	defer c2()
	result, err = cli1.Call(ctx, metaKillAll, nil, nil, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-4 was booted.
	select {
	case <-cli4.Done():
	case <-time.After(time.Second):
		t.Fatal("Client 4 did not shutdown")
	}

	// Check for expected GOODBYE message.
	goodbye = cli4.RouterGoodbye()
	if goodbye == nil {
		t.Error("Did not receive goodbye from router")
	}
	if goodbye.Reason != wamp.CloseNormal {
		t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
	}
	if _, ok = goodbye.Details["message"]; ok {
		t.Error("Should not have received message in GOODBYE.Details")
	}
}

func TestSessionModifyDetails(t *testing.T) {
	defer leaktest.Check(t)()

	cli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli.Close()

	// Call meta procedure to modify details.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	delta := wamp.Dict{"pi": 3.14, "authid": "bob"}
	args := wamp.List{cli.ID(), delta}
	result, err := cli.Call(ctx, metaModifyDetails, nil, args, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Call session meta-procedure to get session information.
	ctx = context.Background()
	args = wamp.List{cli.ID()}
	result, err = cli.Call(ctx, metaGet, nil, args, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if len(result.Arguments) == 0 {
		t.Fatal("Missing result argument")
	}
	details, ok := wamp.AsDict(result.Arguments[0])
	if !ok {
		t.Fatal("Could not convert result to wamp.Dict")
	}
	pi, _ := wamp.AsFloat64(details["pi"])
	if pi != 3.14 {
		t.Fatal("Wrong value for detail pi, got", details["pi"])
	}
	authid, _ := wamp.AsString(details["authid"])
	if authid != "bob" {
		t.Fatal("Wrong value for detail authid")
	}
}

func TestSessionKillDeadlock(t *testing.T) {
	// Test fix for co-recursive deadlock between dealer goroutine and meta
	// session inbound message handler (issue #180)

	remoteCli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	// Register procedure
	handler := func(ctx context.Context, inv *wamp.Invocation) client.InvokeResult {
		return client.InvokeResult{Args: wamp.List{"done"}}
	}
	const procName = "dostuff"
	if err = remoteCli.Register(procName, handler, nil); err != nil {
		t.Fatal("Failed to register procedure:", err)
	}

	localCli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	// Subscribe to event.  Note this needs to be a buffered channel so that
	// event can be "handled" while the test is waiting for a response.
	onUnregEvents := make(chan *wamp.Event, 1)
	err = localCli.SubscribeChan(string(wamp.MetaEventRegOnUnregister), onUnregEvents, nil)
	if err != nil {
		t.Fatal("subscribe error:", err)
	}

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill client-2
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	args := wamp.List{remoteCli.ID()}
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := localCli.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err != nil {
		t.Fatal(err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that remote client was booted.
	select {
	case <-remoteCli.Done():
	case <-time.After(time.Second):
		t.Fatal("remote client did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := remoteCli.RouterGoodbye()
	if goodbye != nil {
		if goodbye.Reason != reason {
			t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
		}
		if gm, ok := wamp.AsString(goodbye.Details["message"]); ok {
			if gm != message {
				t.Error("Did not get expected goodbye message, got:", gm)
			}
		} else {
			t.Error("Expected message in GOODBYE")
		}
	}
	select {
	case <-onUnregEvents:
	case <-time.After(5 * time.Second):
		t.Error("Timed out waiting for local client to get on unregister event")
	}

	// Make sure everything closes correctly.
	if err = localCli.Close(); err != nil {
		t.Error(err)
	}
	if err = remoteCli.Close(); err != nil {
		t.Error(err)
	}
}
<commit_msg>fix test timeout<commit_after>package aat

import (
	"context"
	"testing"
	"time"

	"github.com/fortytw2/leaktest"
	"github.com/gammazero/nexus/v3/client"
	"github.com/gammazero/nexus/v3/wamp"
)

const (
	metaKill           = string(wamp.MetaProcSessionKill)
	metaKillByAuthid   = string(wamp.MetaProcSessionKillByAuthid)
	metaKillByAuthrole = string(wamp.MetaProcSessionKillByAuthrole)
	metaKillAll        = string(wamp.MetaProcSessionKillAll)

	metaModifyDetails = string(wamp.MetaProcSessionModifyDetails)
)

func TestSessionKill(t *testing.T) {
	defer leaktest.Check(t)()

	cli1, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	cli2, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	cli3, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill a client-3
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	args := wamp.List{cli3.ID()}
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-3 was booted.
	select {
	case <-cli3.Done():
	case <-time.After(time.Second):
		t.Fatal("Client 3 did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := cli3.RouterGoodbye()
	if goodbye == nil {
		t.Error("Did not receive goodbye from router")
	}
	if goodbye.Reason != reason {
		t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
	}
	if gm, ok := wamp.AsString(goodbye.Details["message"]); ok {
		if gm != message {
			t.Error("Did not get expected goodbye message, got:", gm)
		}
	} else {
		t.Error("Expected message in GOODBYE")
	}

	// Check that client-2 is still connected.
	select {
	case <-cli2.Done():
		t.Fatal("Client 2 should still be connected")
	default:
	}

	// Test that trying to kill self receives error.
	args = wamp.List{cli1.ID}
	result, err = cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err == nil {
		t.Fatal("Expected error")
	}
	rpcErr, ok := err.(client.RPCError)
	if !ok {
		t.Fatal("Expected RPCError")
	}
	if rpcErr.Err.Error != wamp.ErrNoSuchSession {
		t.Error("Wrong error, got", rpcErr.Err.Error, "expected", wamp.ErrNoSuchSession)
	}

	// Test that killing a sesson that does not exist works correctly.
	ctx, c2 := context.WithTimeout(context.Background(), time.Second)
	defer c2()
	args = wamp.List{wamp.ID(12345)}
	kwArgs = wamp.Dict{"reason": reason, "message": message}
	result, err = cli1.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err == nil {
		t.Error("Expected error")
	} else if _, ok := err.(client.RPCError); !ok {
		t.Fatal("Expected RPCError")
	}

	// Make sure everything closes correctly.
	if err = cli3.Close(); err != nil {
		t.Error(err)
	}
	if err = cli2.Close(); err != nil {
		t.Error(err)
	}
	if err = cli1.Close(); err != nil {
		t.Error(err)
	}
}

func TestSessionKillAll(t *testing.T) {
	defer leaktest.Check(t)()

	cli1, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli1.Close()

	cli2, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli2.Close()

	cli3, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli3.Close()

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill a client-3
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := cli1.Call(ctx, metaKillAll, nil, nil, kwArgs, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-3 was booted.
	select {
	case <-cli3.Done():
	case <-time.After(3 * time.Second):
		t.Fatal("Client 3 did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := cli3.RouterGoodbye()
	if goodbye == nil {
		t.Error("Did not receive goodbye from router")
	} else {
		if goodbye.Reason != reason {
			t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
		}
		gm, ok := wamp.AsString(goodbye.Details["message"])
		if !ok {
			t.Error("Expected message in GOODBYE")
		} else if gm != message {
			t.Error("Did not get expected goodbye message, got:", gm)
		}
	}

	// Check that client-2 was booted.
	select {
	case <-cli2.Done():
	case <-time.After(3 * time.Second):
		t.Fatal("Client 2 did not shutdown")
	}

	// Test that client-1 still connected.
	select {
	case <-cli1.Done():
		t.Fatal("Client 1 should still be connected")
	default:
	}

	cli4, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli4.Close()

	// Call killall again, with no reason.
	ctx, c2 := context.WithTimeout(context.Background(), time.Second)
	defer c2()
	result, err = cli1.Call(ctx, metaKillAll, nil, nil, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that client-4 was booted.
	select {
	case <-cli4.Done():
	case <-time.After(3 * time.Second):
		t.Fatal("Client 4 did not shutdown")
	}

	// Check for expected GOODBYE message.
	goodbye = cli4.RouterGoodbye()
	if goodbye == nil {
		t.Fatal("Did not receive goodbye from router")
	}
	if goodbye.Reason != wamp.CloseNormal {
		t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
	}
	if _, ok := goodbye.Details["message"]; ok {
		t.Error("Should not have received message in GOODBYE.Details")
	}
}

func TestSessionModifyDetails(t *testing.T) {
	defer leaktest.Check(t)()

	cli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}
	defer cli.Close()

	// Call meta procedure to modify details.
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	delta := wamp.Dict{"pi": 3.14, "authid": "bob"}
	args := wamp.List{cli.ID(), delta}
	result, err := cli.Call(ctx, metaModifyDetails, nil, args, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Call session meta-procedure to get session information.
	ctx = context.Background()
	args = wamp.List{cli.ID()}
	result, err = cli.Call(ctx, metaGet, nil, args, nil, nil)
	if err != nil {
		t.Fatal("Call error:", err)
	}
	if len(result.Arguments) == 0 {
		t.Fatal("Missing result argument")
	}
	details, ok := wamp.AsDict(result.Arguments[0])
	if !ok {
		t.Fatal("Could not convert result to wamp.Dict")
	}
	pi, _ := wamp.AsFloat64(details["pi"])
	if pi != 3.14 {
		t.Fatal("Wrong value for detail pi, got", details["pi"])
	}
	authid, _ := wamp.AsString(details["authid"])
	if authid != "bob" {
		t.Fatal("Wrong value for detail authid")
	}
}

func TestSessionKillDeadlock(t *testing.T) {
	// Test fix for co-recursive deadlock between dealer goroutine and meta
	// session inbound message handler (issue #180)

	remoteCli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	// Register procedure
	handler := func(ctx context.Context, inv *wamp.Invocation) client.InvokeResult {
		return client.InvokeResult{Args: wamp.List{"done"}}
	}
	const procName = "dostuff"
	if err = remoteCli.Register(procName, handler, nil); err != nil {
		t.Fatal("Failed to register procedure:", err)
	}

	localCli, err := connectClient()
	if err != nil {
		t.Fatal("Failed to connect client:", err)
	}

	// Subscribe to event.  Note this needs to be a buffered channel so that
	// event can be "handled" while the test is waiting for a response.
	onUnregEvents := make(chan *wamp.Event, 1)
	err = localCli.SubscribeChan(string(wamp.MetaEventRegOnUnregister), onUnregEvents, nil)
	if err != nil {
		t.Fatal("subscribe error:", err)
	}

	reason := wamp.URI("test.session.kill")
	message := "this is a test"

	// Call meta procedure to kill client-2
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	args := wamp.List{remoteCli.ID()}
	kwArgs := wamp.Dict{"reason": reason, "message": message}
	result, err := localCli.Call(ctx, metaKill, nil, args, kwArgs, nil)
	if err != nil {
		t.Fatal(err)
	}
	if result == nil {
		t.Error("Did not receive result")
	}

	// Check that remote client was booted.
	select {
	case <-remoteCli.Done():
	case <-time.After(time.Second):
		t.Fatal("remote client did not shutdown")
	}
	// Check for expected GOODBYE message.
	goodbye := remoteCli.RouterGoodbye()
	if goodbye != nil {
		if goodbye.Reason != reason {
			t.Error("Did not get expected GOODBYE.Reason, got:", goodbye.Reason)
		}
		if gm, ok := wamp.AsString(goodbye.Details["message"]); ok {
			if gm != message {
				t.Error("Did not get expected goodbye message, got:", gm)
			}
		} else {
			t.Error("Expected message in GOODBYE")
		}
	}
	select {
	case <-onUnregEvents:
	case <-time.After(5 * time.Second):
		t.Error("Timed out waiting for local client to get on unregister event")
	}

	// Make sure everything closes correctly.
	if err = localCli.Close(); err != nil {
		t.Error(err)
	}
	if err = remoteCli.Close(); err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package events

import (
	"fmt"
	"os"
	"runtime"
	"time"
)

// Signal triggers events on handler for every signal that arrives on sigchan.
// The function returns a channel on which signals are forwarded, the program
// should use this channel instead of sigchan to receive signals.
func Signal(sigchan <-chan os.Signal, handler Handler) <-chan os.Signal {
	output := make(chan os.Signal)

	// We capture the stack frame here instead of in the goroutine because it
	// gives a more meaningful value (the caller of Signal, which usually is
	// the application itself).
	var pc [1]uintptr
	runtime.Callers(2, pc[:])
	file, line := SourceForPC(pc[0])

	go func() {
		for sig := range sigchan {
			h := handler

			if h == nil {
				h = DefaultHandler
			}

			h.HandleEvent(&Event{
				Message: sig.String(),
				Source:  fmt.Sprintf("%s:%d", file, line),
				Time:    time.Now(),
				Args:    Args{{"signal", sig}},
			})

			// Limits to 1s the attempt to publish to the output channel, this
			// is a safeguard for programs that don't consume from the output
			// channel (event though they should).
			select {
			case output <- sig:
			case <-time.After(time.Second):
			}
		}
	}()

	return output
}
<commit_msg>close signal output channel<commit_after>package events

import (
	"fmt"
	"os"
	"runtime"
	"time"
)

// Signal triggers events on handler for every signal that arrives on sigchan.
// The function returns a channel on which signals are forwarded, the program
// should use this channel instead of sigchan to receive signals.
func Signal(sigchan <-chan os.Signal, handler Handler) <-chan os.Signal {
	output := make(chan os.Signal)

	// We capture the stack frame here instead of in the goroutine because it
	// gives a more meaningful value (the caller of Signal, which usually is
	// the application itself).
	var pc [1]uintptr
	runtime.Callers(2, pc[:])
	file, line := SourceForPC(pc[0])

	go func() {
		defer close(output)

		for sig := range sigchan {
			h := handler

			if h == nil {
				h = DefaultHandler
			}

			h.HandleEvent(&Event{
				Message: sig.String(),
				Source:  fmt.Sprintf("%s:%d", file, line),
				Time:    time.Now(),
				Args:    Args{{"signal", sig}},
			})

			// Limits to 1s the attempt to publish to the output channel, this
			// is a safeguard for programs that don't consume from the output
			// channel (event though they should).
			select {
			case output <- sig:
			case <-time.After(time.Second):
			}
		}
	}()

	return output
}
<|endoftext|>


<commit_before>package node

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"syscall"
)

type Node struct {
	os.FileInfo
	path  string
	depth int
	err   error
	nodes Nodes
}

type Nodes []*Node

func (n Nodes) Len() int      { return len(n) }
func (n Nodes) Swap(i, j int) { n[i], n[j] = n[j], n[i] }

type Fs interface {
	Stat(path string) (os.FileInfo, error)
	ReadDir(path string) ([]string, error)
}

type Options struct {
	Fs Fs
	// List
	All       bool
	DirsOnly  bool
	FullPath  bool
	DeepLevel int
	// File
	ByteSize bool
	UnitSize bool
	FileMode bool
	ShowUid  bool
	ShowGid  bool
	LastMod  bool
	Quotes   bool
	Inodes   bool
	Device   bool
	// Sort
	NoSort    bool
	VerSort   bool
	ModSort   bool
	DirSort   bool
	NameSort  bool
	SizeSort  bool
	CTimeSort bool
	ReverSort bool
	// Graphics
	NoIndent bool
}

// New get path and create new node
func New(path string) *Node {
	return &Node{path: path}
}

// Visit fn
func (node *Node) Visit(opts *Options) (dirs, files int) {
	fi, err := opts.Fs.Stat(node.path)
	if err != nil {
		node.err = err
		return
	}
	node.FileInfo = fi
	if !fi.IsDir() {
		return 0, 1
	}
	names, err := opts.Fs.ReadDir(node.path)
	if err != nil {
		node.err = err
		return
	}
	node.nodes = make(Nodes, 0)
	// DeepLevel option
	if opts.DeepLevel > 0 && opts.DeepLevel <= node.depth {
		return 1, 0
	}
	for _, name := range names {
		// "all" option
		if !opts.All && strings.HasPrefix(name, ".") {
			continue
		}
		nnode := &Node{
			path:  filepath.Join(node.path, name),
			depth: node.depth + 1,
		}
		d, f := nnode.Visit(opts)
		// "dirs only" option
		if opts.DirsOnly && !nnode.IsDir() {
			continue
		}
		node.nodes = append(node.nodes, nnode)
		dirs, files = dirs+d, files+f
	}
	// Sorting
	if !opts.NoSort {
		node.sort(opts)
	}
	return dirs + 1, files
}

func (node *Node) sort(opts *Options) {
	var fn SortFunc
	switch {
	case opts.ModSort:
		fn = ModSort
	case opts.CTimeSort:
		fn = CTimeSort
	case opts.DirSort:
		fn = DirSort
	case opts.VerSort:
		fn = VerSort
	case opts.SizeSort:
		fn = SizeSort
	case opts.NameSort:
		fn = NameSort
	}
	if fn != nil {
		if opts.ReverSort {
			sort.Sort(sort.Reverse(ByFunc{node.nodes, fn}))
		} else {
			sort.Sort(ByFunc{node.nodes, fn})
		}
	}
}

func (node *Node) Print(indent string, opts *Options) {
	if node.err != nil {
		err := strings.Split(node.err.Error(), ": ")[1]
		fmt.Printf("%s [%s]\n", node.path, err)
		return
	}
	if !node.IsDir() {
		var props []string
		var stat = node.Sys().(*syscall.Stat_t)
		// inodes
		if opts.Inodes {
			props = append(props, fmt.Sprintf("%d", stat.Ino))
		}
		// device
		if opts.Device {
			props = append(props, fmt.Sprintf("%3d", stat.Dev))
		}
		// Mode
		if opts.FileMode {
			props = append(props, node.Mode().String())
		}
		// Owner/Uid
		if opts.ShowUid {
			uid := strconv.Itoa(int(stat.Uid))
			if u, err := user.LookupId(uid); err != nil {
				props = append(props, fmt.Sprintf("%-8s", uid))
			} else {
				props = append(props, fmt.Sprintf("%-8s", u.Username))
			}
		}
		// Gorup/Gid
		// TODO: support groupname
		if opts.ShowGid {
			gid := strconv.Itoa(int(stat.Gid))
			props = append(props, fmt.Sprintf("%-4s", gid))
		}
		// Size
		if opts.ByteSize || opts.UnitSize {
			var size string
			if opts.UnitSize {
				size = fmt.Sprintf("%4s", formatBytes(node.Size()))
			} else {
				size = fmt.Sprintf("%11d", node.Size())
			}
			props = append(props, size)
		}
		// Last modification
		if opts.LastMod {
			props = append(props, node.ModTime().Format("Jan 02 15:04"))
		}
		// Print properties
		if len(props) > 0 {
			fmt.Printf("[%s]  ", strings.Join(props, " "))
		}
	}
	// name/path
	var name string
	if node.depth == 0 || opts.FullPath {
		name = node.path
	} else {
		name = node.Name()
	}
	// Quotes
	if opts.Quotes {
		name = fmt.Sprintf("\"%s\"", name)
	}
	// Print file details
	fmt.Println(name)
	add := "│   "
	for i, nnode := range node.nodes {
		if opts.NoIndent {
			add = ""
		} else {
			if i == len(node.nodes)-1 {
				fmt.Printf(indent + "└── ")
				add = "    "
			} else {
				fmt.Printf(indent + "├── ")
			}
		}
		nnode.Print(indent+add, opts)
	}
}

// Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B
func formatBytes(i int64) (result string) {
	var n float64
	sFmt, eFmt := "%.01f", ""
	switch {
	case i > (1024 * 1024 * 1024):
		eFmt = "G"
		n = float64(i) / 1024 / 1024 / 1024
	case i > (1024 * 1024):
		eFmt = "M"
		n = float64(i) / 1024 / 1024
	case i > 1024:
		eFmt = "K"
		n = float64(i) / 1024
	default:
		sFmt = "%.0f"
		n = float64(i)
	}
	if eFmt != "" && n >= 10 {
		sFmt = "%.0f"
	}
	result = fmt.Sprintf(sFmt+eFmt, n)
	result = strings.Trim(result, " ")
	return
}
<commit_msg>feat(node): add pattern and ipattern<commit_after>package node

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"syscall"
)

type Node struct {
	os.FileInfo
	path  string
	depth int
	err   error
	nodes Nodes
}

type Nodes []*Node

func (n Nodes) Len() int      { return len(n) }
func (n Nodes) Swap(i, j int) { n[i], n[j] = n[j], n[i] }

type Fs interface {
	Stat(path string) (os.FileInfo, error)
	ReadDir(path string) ([]string, error)
}

type Options struct {
	Fs Fs
	// List
	All       bool
	DirsOnly  bool
	FullPath  bool
	DeepLevel int
	Pattern   string
	IPattern  string
	// File
	ByteSize bool
	UnitSize bool
	FileMode bool
	ShowUid  bool
	ShowGid  bool
	LastMod  bool
	Quotes   bool
	Inodes   bool
	Device   bool
	// Sort
	NoSort    bool
	VerSort   bool
	ModSort   bool
	DirSort   bool
	NameSort  bool
	SizeSort  bool
	CTimeSort bool
	ReverSort bool
	// Graphics
	NoIndent bool
}

// New get path and create new node
func New(path string) *Node {
	return &Node{path: path}
}

// Visit fn
func (node *Node) Visit(opts *Options) (dirs, files int) {
	fi, err := opts.Fs.Stat(node.path)
	if err != nil {
		node.err = err
		return
	}
	node.FileInfo = fi
	if !fi.IsDir() {
		return 0, 1
	}
	// DeepLevel option
	if opts.DeepLevel > 0 && opts.DeepLevel <= node.depth {
		return 1, 0
	}
	names, err := opts.Fs.ReadDir(node.path)
	if err != nil {
		node.err = err
		return
	}
	node.nodes = make(Nodes, 0)
	for _, name := range names {
		// "all" option
		if !opts.All && strings.HasPrefix(name, ".") {
			continue
		}
		nnode := &Node{
			path:  filepath.Join(node.path, name),
			depth: node.depth + 1,
		}
		d, f := nnode.Visit(opts)
		if !nnode.IsDir() {
			// "dirs only" option
			if opts.DirsOnly {
				continue
			}
			// Pattern matching
			if opts.Pattern != "" {
				re, err := regexp.Compile(opts.Pattern)
				if err == nil && !re.MatchString(name) {
					continue
				}
			}
			// IPattern matching
			if opts.IPattern != "" {
				re, err := regexp.Compile(opts.IPattern)
				if err == nil && re.MatchString(name) {
					continue
				}
			}
		}
		node.nodes = append(node.nodes, nnode)
		dirs, files = dirs+d, files+f
	}
	// Sorting
	if !opts.NoSort {
		node.sort(opts)
	}
	return dirs + 1, files
}

func (node *Node) sort(opts *Options) {
	var fn SortFunc
	switch {
	case opts.ModSort:
		fn = ModSort
	case opts.CTimeSort:
		fn = CTimeSort
	case opts.DirSort:
		fn = DirSort
	case opts.VerSort:
		fn = VerSort
	case opts.SizeSort:
		fn = SizeSort
	case opts.NameSort:
		fn = NameSort
	}
	if fn != nil {
		if opts.ReverSort {
			sort.Sort(sort.Reverse(ByFunc{node.nodes, fn}))
		} else {
			sort.Sort(ByFunc{node.nodes, fn})
		}
	}
}

func (node *Node) Print(indent string, opts *Options) {
	if node.err != nil {
		err := strings.Split(node.err.Error(), ": ")[1]
		fmt.Printf("%s [%s]\n", node.path, err)
		return
	}
	if !node.IsDir() {
		var props []string
		var stat = node.Sys().(*syscall.Stat_t)
		// inodes
		if opts.Inodes {
			props = append(props, fmt.Sprintf("%d", stat.Ino))
		}
		// device
		if opts.Device {
			props = append(props, fmt.Sprintf("%3d", stat.Dev))
		}
		// Mode
		if opts.FileMode {
			props = append(props, node.Mode().String())
		}
		// Owner/Uid
		if opts.ShowUid {
			uid := strconv.Itoa(int(stat.Uid))
			if u, err := user.LookupId(uid); err != nil {
				props = append(props, fmt.Sprintf("%-8s", uid))
			} else {
				props = append(props, fmt.Sprintf("%-8s", u.Username))
			}
		}
		// Gorup/Gid
		// TODO: support groupname
		if opts.ShowGid {
			gid := strconv.Itoa(int(stat.Gid))
			props = append(props, fmt.Sprintf("%-4s", gid))
		}
		// Size
		if opts.ByteSize || opts.UnitSize {
			var size string
			if opts.UnitSize {
				size = fmt.Sprintf("%4s", formatBytes(node.Size()))
			} else {
				size = fmt.Sprintf("%11d", node.Size())
			}
			props = append(props, size)
		}
		// Last modification
		if opts.LastMod {
			props = append(props, node.ModTime().Format("Jan 02 15:04"))
		}
		// Print properties
		if len(props) > 0 {
			fmt.Printf("[%s]  ", strings.Join(props, " "))
		}
	}
	// name/path
	var name string
	if node.depth == 0 || opts.FullPath {
		name = node.path
	} else {
		name = node.Name()
	}
	// Quotes
	if opts.Quotes {
		name = fmt.Sprintf("\"%s\"", name)
	}
	// Print file details
	fmt.Println(name)
	add := "│   "
	for i, nnode := range node.nodes {
		if opts.NoIndent {
			add = ""
		} else {
			if i == len(node.nodes)-1 {
				fmt.Printf(indent + "└── ")
				add = "    "
			} else {
				fmt.Printf(indent + "├── ")
			}
		}
		nnode.Print(indent+add, opts)
	}
}

// Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B
func formatBytes(i int64) (result string) {
	var n float64
	sFmt, eFmt := "%.01f", ""
	switch {
	case i > (1024 * 1024 * 1024):
		eFmt = "G"
		n = float64(i) / 1024 / 1024 / 1024
	case i > (1024 * 1024):
		eFmt = "M"
		n = float64(i) / 1024 / 1024
	case i > 1024:
		eFmt = "K"
		n = float64(i) / 1024
	default:
		sFmt = "%.0f"
		n = float64(i)
	}
	if eFmt != "" && n >= 10 {
		sFmt = "%.0f"
	}
	result = fmt.Sprintf(sFmt+eFmt, n)
	result = strings.Trim(result, " ")
	return
}
<|endoftext|>


<commit_before>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
	"log"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func TestXnorNetwork(t *testing.T) {

	// create network nodes
	input_neuron1 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	input_neuron2 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: -10, ActivationFunction: sigmoid}

	sensor1 := &Sensor{}
	sensor2 := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector1 := &Injector{}
	injector2 := &Injector{}

	sensor1.Name = "sensor1"
	sensor2.Name = "sensor2"
	input_neuron1.Name = "input_neuron1"
	input_neuron2.Name = "input_neuron2"
	hidden_neuron1.Name = "hidden_neuron1"
	hidden_neuron2.Name = "hidden_neuron2"
	output_neuron.Name = "output_neuron"
	actuator.Name = "actuator_neuron"

	// connect nodes together
	injector1.ConnectBidirectional(sensor1)
	injector2.ConnectBidirectional(sensor2)
	sensor1.ConnectBidirectionalWeighted(input_neuron1, []float64{1})
	sensor2.ConnectBidirectionalWeighted(input_neuron2, []float64{1})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{input_neuron1, input_neuron2, hidden_neuron1, hidden_neuron2, output_neuron, sensor1, sensor2, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue1 := []float64{0}
		injector1.outbound[0].channel <- testValue1
		testValue2 := []float64{1}
		injector2.outbound[0].channel <- testValue2

		//testValue1b := []float64{1}
		//injector1.outbound[0].channel <- testValue1b
		//testValue2b := []float64{1}
		//injector2.outbound[0].channel <- testValue2b

		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		resultVector := <- wiretap.inbound[0].channel
		result := resultVector[0]
		assert.True(t, equalsWithMaxDelta(result, 0.00000, .01))
		log.Printf("Xnor - Got value from wiretap: %v", result)

		//resultVector2 := <- wiretap.inbound[0].channel
		//result2 := resultVector2[0]
		//log.Printf("Xnor - Got value2 from wiretap: %v", result2)

		wg.Done()
	}()

	wg.Wait()

}

func identity_activation(x float64) float64 {
	return x
}
<commit_msg>Make tests a bit more table based<commit_after>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
	"log"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func TestXnorNetwork(t *testing.T) {

	// create network nodes
	input_neuron1 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	input_neuron2 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: -10, ActivationFunction: sigmoid}

	sensor1 := &Sensor{}
	sensor2 := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector1 := &Injector{}
	injector2 := &Injector{}

	sensor1.Name = "sensor1"
	sensor2.Name = "sensor2"
	input_neuron1.Name = "input_neuron1"
	input_neuron2.Name = "input_neuron2"
	hidden_neuron1.Name = "hidden_neuron1"
	hidden_neuron2.Name = "hidden_neuron2"
	output_neuron.Name = "output_neuron"
	actuator.Name = "actuator_neuron"

	// connect nodes together
	injector1.ConnectBidirectional(sensor1)
	injector2.ConnectBidirectional(sensor2)
	sensor1.ConnectBidirectionalWeighted(input_neuron1, []float64{1})
	sensor2.ConnectBidirectionalWeighted(input_neuron2, []float64{1})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{input_neuron1, input_neuron2, hidden_neuron1, hidden_neuron2, output_neuron, sensor1, sensor2, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	testInputs := []struct{
		x1 []float64
		x2 []float64
	}{ {x1: []float64{0}, x2: []float64{1}},
	   {x1: []float64{1}, x2: []float64{1}}}

	expectedOutputs := []float64{ 0.0000, 1.00000 }

	// inject a value into sensor
	go func() {

		for _, inputPair := range testInputs {
			injector1.outbound[0].channel <- inputPair.x1
			injector2.outbound[0].channel <- inputPair.x2
		}

		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {

		for _, expectedOuput := range expectedOutputs {
			resultVector := <- wiretap.inbound[0].channel
			result := resultVector[0]
			assert.True(t, equalsWithMaxDelta(result, expectedOuput, .01))
		}

		wg.Done()
	}()

	wg.Wait()

	log.Printf("Done")

}

func identity_activation(x float64) float64 {
	return x
}
<|endoftext|>


<commit_before>// Copyright 2017 Kaur Kuut
//
// 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.

package estflag

import (
	"github.com/xStrom/patriot/art"
)

//const x0, y0 = 75, 36
const x0, y0 = 740, 900
const x1, y1 = x0 + 33 - 1, y0 + 21 - 1

// Fixes any broken pixels in the provided image
func GetWork(image *art.Image, ignorePixels map[int]bool) *art.Pixel {
	for x := x0; x <= x1; x++ {
		for y := y0; y <= y1; y++ {
			if ignorePixels[x|(y<<16)] {
				continue
			}

			c := image.At(x, y)

			switch (y - y0) / 7 {
			case 0:
				if c != art.DarkBlue {
					return &art.Pixel{x, y, art.DarkBlue}
				}
				break
			case 1:
				if c != art.Black {
					return &art.Pixel{x, y, art.Black}
				}
				break
			case 2:
				if c != art.White {
					return &art.Pixel{x, y, art.White}
				}
				break
			}
		}
	}
	return nil
}

// TODO: Bounds check function, so that not every art needs to be looped through after every pixel update --- make a dirty region system
func CheckPixel(x, y, c int) {
	// Make sure the pixel is even in bounds
	if x >= x0 && x <= x1 && y >= y0 && y <= y1 {

	}
}
<commit_msg>Added a light gray border around the flag.<commit_after>// Copyright 2017 Kaur Kuut
//
// 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.

package estflag

import (
	"github.com/xStrom/patriot/art"
)

//const x0, y0 = 74, 35
const x0, y0 = 739, 899
const x1, y1 = x0 + 35 - 1, y0 + 23 - 1

// Fixes any broken pixels in the provided image
func GetWork(image *art.Image, ignorePixels map[int]bool) *art.Pixel {
	for x := x0; x <= x1; x++ {
		for y := y0; y <= y1; y++ {
			if ignorePixels[x|(y<<16)] {
				continue
			}

			c := image.At(x, y)

			// Border
			if x == x0 || x == x1 || y == y0 || y == y1 {
				if c != art.LightGray {
					return &art.Pixel{x, y, art.LightGray}
				}
			} else {
				// Flag itself
				switch (y - y0 - 1) / 7 {
				case 0:
					if c != art.DarkBlue {
						return &art.Pixel{x, y, art.DarkBlue}
					}
					break
				case 1:
					if c != art.Black {
						return &art.Pixel{x, y, art.Black}
					}
					break
				case 2:
					if c != art.White {
						return &art.Pixel{x, y, art.White}
					}
					break
				}
			}
		}
	}
	return nil
}

// TODO: Bounds check function, so that not every art needs to be looped through after every pixel update --- make a dirty region system
func CheckPixel(x, y, c int) {
	// Make sure the pixel is even in bounds
	if x >= x0 && x <= x1 && y >= y0 && y <= y1 {

	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.

// Package daemon linux systemD version
package daemon

import (
	"errors"
	"os"
	"os/exec"
	"regexp"
	"text/template"
)

// SystemDRecord - standard record (struct) for linux systemD version of daemon package
type SystemDRecord struct {
	name        string
	description string
}

// Standard service path for systemD daemons
func (linux *SystemDRecord) servicePath() string {
	return "/etc/systemd/system/" + linux.name + ".service"
}

// Check service is installed
func (linux *SystemDRecord) checkInstalled() bool {

	if _, err := os.Stat(linux.servicePath()); err == nil {
		return true
	}

	return false
}

// Check service is running
func (linux *SystemDRecord) checkRunning() (string, bool) {
	output, err := exec.Command("systemctl", "status", linux.name+".service").Output()
	if err == nil {
		if matched, err := regexp.MatchString(linux.name, string(output)); err == nil && matched {
			reg := regexp.MustCompile("PID: ([0-9]+)")
			data := reg.FindStringSubmatch(string(output))
			if len(data) > 1 {
				return "Service (pid  " + data[1] + ") is running...", true
			}
			return "Service is running...", true
		}
	}

	return "Service is stoped", false
}

// Install the service
func (linux *SystemDRecord) Install() (string, error) {
	installAction := "Install " + linux.description + ":"

	if checkPrivileges() == false {
		return installAction + failed, errors.New(rootPrivileges)
	}

	srvPath := linux.servicePath()

	if linux.checkInstalled() == true {
		return installAction + failed, errors.New(linux.description + " already installed")
	}

	file, err := os.Create(srvPath)
	if err != nil {
		return installAction + failed, err
	}
	defer file.Close()

	execPatch, err := executablePath(linux.name)
	if err != nil {
		return installAction + failed, err
	}

	templ, err := template.New("systemDConfig").Parse(systemDConfig)
	if err != nil {
		return installAction + failed, err
	}

	if err := templ.Execute(
		file,
		&struct {
			Name, Description, Path string
		}{linux.name, linux.description, execPatch},
	); err != nil {
		return installAction + failed, err
	}

	if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
		return installAction + failed, err
	}

	if err := exec.Command("systemctl", "enable", linux.name+".service").Run(); err != nil {
		return installAction + failed, err
	}

	return installAction + success, nil
}

// Remove the service
func (linux *SystemDRecord) Remove() (string, error) {
	removeAction := "Removing " + linux.description + ":"

	if checkPrivileges() == false {
		return removeAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return removeAction + failed, errors.New(linux.description + " is not installed")
	}

	if err := exec.Command("systemctl", "disable", linux.name+".service").Run(); err != nil {
		return removeAction + failed, err
	}

	if err := os.Remove(linux.servicePath()); err != nil {
		return removeAction + failed, err
	}

	return removeAction + success, nil
}

// Start the service
func (linux *SystemDRecord) Start() (string, error) {
	startAction := "Starting " + linux.description + ":"

	if checkPrivileges() == false {
		return startAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return startAction + failed, errors.New(linux.description + " is not installed")
	}

	if _, status := linux.checkRunning(); status == true {
		return startAction + failed, errors.New("service already running")
	}

	if err := exec.Command("systemctl", "start", linux.name+".service").Run(); err != nil {
		return startAction + failed, err
	}

	return startAction + success, nil
}

// Stop the service
func (linux *SystemDRecord) Stop() (string, error) {
	stopAction := "Stopping " + linux.description + ":"

	if checkPrivileges() == false {
		return stopAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return stopAction + failed, errors.New(linux.description + " is not installed")
	}

	if _, status := linux.checkRunning(); status == false {
		return stopAction + failed, errors.New("service already stopped")
	}

	if err := exec.Command("systemctl", "stop", linux.name+".service").Run(); err != nil {
		return stopAction + failed, err
	}

	return stopAction + success, nil
}

// Status - Get service status
func (linux *SystemDRecord) Status() (string, error) {

	if checkPrivileges() == false {
		return "", errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return "Status could not defined", errors.New(linux.description + " is not installed")
	}

	statusAction, _ := linux.checkRunning()

	return statusAction, nil
}

var systemDConfig = `[Unit]
Description={{.Description}}

[Service]
PIDFile=/var/run/{{.Name}}.pid
ExecStartPre=/bin/rm -f /var/run/{{.Name}}.pid
ExecStart={{.Path}}
Restart=on-abort

[Install]
WantedBy=multi-user.target
`
<commit_msg>checkRunnig systemd enhancement<commit_after>// Copyright 2014 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.

// Package daemon linux systemD version
package daemon

import (
	"errors"
	"os"
	"os/exec"
	"regexp"
	"text/template"
)

// SystemDRecord - standard record (struct) for linux systemD version of daemon package
type SystemDRecord struct {
	name        string
	description string
}

// Standard service path for systemD daemons
func (linux *SystemDRecord) servicePath() string {
	return "/etc/systemd/system/" + linux.name + ".service"
}

// Check service is installed
func (linux *SystemDRecord) checkInstalled() bool {

	if _, err := os.Stat(linux.servicePath()); err == nil {
		return true
	}

	return false
}

// Check service is running
func (linux *SystemDRecord) checkRunning() (string, bool) {
	output, err := exec.Command("systemctl", "status", linux.name+".service").Output()
	if err == nil {
		if matched, err := regexp.MatchString("Active: active", string(output)); err == nil && matched {
			reg := regexp.MustCompile("Main PID: ([0-9]+)")
			data := reg.FindStringSubmatch(string(output))
			if len(data) > 1 {
				return "Service (pid  " + data[1] + ") is running...", true
			}
			return "Service is running...", true
		}
	}

	return "Service is stoped", false
}

// Install the service
func (linux *SystemDRecord) Install() (string, error) {
	installAction := "Install " + linux.description + ":"

	if checkPrivileges() == false {
		return installAction + failed, errors.New(rootPrivileges)
	}

	srvPath := linux.servicePath()

	if linux.checkInstalled() == true {
		return installAction + failed, errors.New(linux.description + " already installed")
	}

	file, err := os.Create(srvPath)
	if err != nil {
		return installAction + failed, err
	}
	defer file.Close()

	execPatch, err := executablePath(linux.name)
	if err != nil {
		return installAction + failed, err
	}

	templ, err := template.New("systemDConfig").Parse(systemDConfig)
	if err != nil {
		return installAction + failed, err
	}

	if err := templ.Execute(
		file,
		&struct {
			Name, Description, Path string
		}{linux.name, linux.description, execPatch},
	); err != nil {
		return installAction + failed, err
	}

	if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
		return installAction + failed, err
	}

	if err := exec.Command("systemctl", "enable", linux.name+".service").Run(); err != nil {
		return installAction + failed, err
	}

	return installAction + success, nil
}

// Remove the service
func (linux *SystemDRecord) Remove() (string, error) {
	removeAction := "Removing " + linux.description + ":"

	if checkPrivileges() == false {
		return removeAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return removeAction + failed, errors.New(linux.description + " is not installed")
	}

	if err := exec.Command("systemctl", "disable", linux.name+".service").Run(); err != nil {
		return removeAction + failed, err
	}

	if err := os.Remove(linux.servicePath()); err != nil {
		return removeAction + failed, err
	}

	return removeAction + success, nil
}

// Start the service
func (linux *SystemDRecord) Start() (string, error) {
	startAction := "Starting " + linux.description + ":"

	if checkPrivileges() == false {
		return startAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return startAction + failed, errors.New(linux.description + " is not installed")
	}

	if _, status := linux.checkRunning(); status == true {
		return startAction + failed, errors.New("service already running")
	}

	if err := exec.Command("systemctl", "start", linux.name+".service").Run(); err != nil {
		return startAction + failed, err
	}

	return startAction + success, nil
}

// Stop the service
func (linux *SystemDRecord) Stop() (string, error) {
	stopAction := "Stopping " + linux.description + ":"

	if checkPrivileges() == false {
		return stopAction + failed, errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return stopAction + failed, errors.New(linux.description + " is not installed")
	}

	if _, status := linux.checkRunning(); status == false {
		return stopAction + failed, errors.New("service already stopped")
	}

	if err := exec.Command("systemctl", "stop", linux.name+".service").Run(); err != nil {
		return stopAction + failed, err
	}

	return stopAction + success, nil
}

// Status - Get service status
func (linux *SystemDRecord) Status() (string, error) {

	if checkPrivileges() == false {
		return "", errors.New(rootPrivileges)
	}

	if linux.checkInstalled() == false {
		return "Status could not defined", errors.New(linux.description + " is not installed")
	}

	statusAction, _ := linux.checkRunning()

	return statusAction, nil
}

var systemDConfig = `[Unit]
Description={{.Description}}

[Service]
PIDFile=/var/run/{{.Name}}.pid
ExecStartPre=/bin/rm -f /var/run/{{.Name}}.pid
ExecStart={{.Path}}
Restart=on-abort

[Install]
WantedBy=multi-user.target
`
<|endoftext|>


<commit_before>package server

import (
	"github.com/smancke/guble/protocol"
	"net"
	"net/http"
	"strings"
	"time"
)

type WebServer struct {
	server *http.Server
	ln     net.Listener
	mux    *http.ServeMux
	addr   string
}

func NewWebServer(addr string) *WebServer {
	return &WebServer{
		mux:  http.NewServeMux(),
		addr: addr,
	}
}

func (ws *WebServer) Start() error {
	protocol.Info("starting up at %v", ws.addr)
	ws.server = &http.Server{Addr: ws.addr, Handler: ws.mux}
	var err error
	ws.ln, err = net.Listen("tcp", ws.addr)
	if err != nil {
		return err
	}

	go func() {
		err = ws.server.Serve(tcpKeepAliveListener{ws.ln.(*net.TCPListener)})

		if err != nil && !strings.HasSuffix(err.Error(), "use of closed network connection") {
			protocol.Err("ListenAndServe %s", err.Error())
		}
		protocol.Info("http server stopped")
	}()
	return nil
}

func (ws *WebServer) Stop() error {
	if ws.ln != nil {
		return ws.ln.Close()
	}
	return nil
}

func (ws *WebServer) Handle(prefix string, handler http.Handler) {
	ws.mux.Handle(prefix, handler)
}

func (ws *WebServer) GetAddr() string {
	if ws.ln == nil {
		return "::unknown::"
	}
	return ws.ln.Addr().String()
}

// parsed the userid out of an uri
func extractUserId(requestUri string) string {
	uriParts := strings.SplitN(requestUri, "/user/", 2)
	if len(uriParts) != 2 {
		return ""
	}
	return uriParts[1]
}

// copied from golang: net/http/server.go
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(10 * time.Second)
	return tc, nil
}
<commit_msg>adding check for web_server<commit_after>package server

import (
	"github.com/smancke/guble/protocol"
	"net"
	"net/http"
	"strings"
	"time"
)

type WebServer struct {
	server *http.Server
	ln     net.Listener
	mux    *http.ServeMux
	addr   string
}

func NewWebServer(addr string) *WebServer {
	return &WebServer{
		mux:  http.NewServeMux(),
		addr: addr,
	}
}

func (ws *WebServer) Start() error {
	protocol.Info("starting up at %v", ws.addr)
	ws.server = &http.Server{Addr: ws.addr, Handler: ws.mux}
	var err error
	ws.ln, err = net.Listen("tcp", ws.addr)
	if err != nil {
		return err
	}

	go func() {
		err = ws.server.Serve(tcpKeepAliveListener{ws.ln.(*net.TCPListener)})

		if err != nil && !strings.HasSuffix(err.Error(), "use of closed network connection") {
			protocol.Err("ListenAndServe %s", err.Error())
		}
		protocol.Info("http server stopped")
	}()
	return nil
}

func (ws *WebServer) Stop() error {
	if ws.ln != nil {
		return ws.ln.Close()
	}
	return nil
}

func (ws *WebServer) Check() error {
	return nil
}

func (ws *WebServer) Handle(prefix string, handler http.Handler) {
	ws.mux.Handle(prefix, handler)
}

func (ws *WebServer) GetAddr() string {
	if ws.ln == nil {
		return "::unknown::"
	}
	return ws.ln.Addr().String()
}

// parsed the userid out of an uri
func extractUserId(requestUri string) string {
	uriParts := strings.SplitN(requestUri, "/user/", 2)
	if len(uriParts) != 2 {
		return ""
	}
	return uriParts[1]
}

// copied from golang: net/http/server.go
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(10 * time.Second)
	return tc, nil
}
<|endoftext|>


<commit_before>package gitfile

import (
	"github.com/hashicorp/errwrap"
	"os/exec"
	"fmt"
	"github.com/hashicorp/terraform/helper/hashcode"
	"io/ioutil"
	"os"
	"path"
	"github.com/hashicorp/terraform/helper/schema"
	"strings"
	"syscall"
	"github.com/hashicorp/terraform/terraform"
)

const CommitBodyHeader string = "The following files are managed by terraform:"

func Provider() terraform.ResourceProvider {
	file_resource := fileResource()
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"workdir": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"bogus_filename": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: ".gitignore",
			},
		},
		ResourcesMap: map[string]*schema.Resource{
			"gitfile_checkout": checkoutResource(),
			"gitfile_commit": commitResource(file_resource),
		},
		ConfigureFunc: gitfileConfigure,
	}
}

func gitfileConfigure(data *schema.ResourceData) (interface{}, error) {
	config := &gitfileConfig {
		workDir: data.Get("workdir").(string),
		bogusFilename: data.Get("bogus_filename").(string),
	}
	return config, nil
}

type gitfileConfig struct {
	workDir string
	bogusFilename string
}

func fileResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema{
			"path": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"contents": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
		},
	}
}

func fileCreateUpdate(checkout_dir, filepath, contents string) error {
	if err := ioutil.WriteFile(path.Join(checkout_dir, filepath), []byte(contents), 0666); err != nil {
		return err
	}

	return nil
}

func fileRead(checkout_dir, filepath string) (map[string]interface{}, error) {
	if content_bytes, err := ioutil.ReadFile(path.Join(checkout_dir, filepath)); err != nil {
		return nil, err
	} else {
		return map[string]interface{}{
			"contents": string(content_bytes),
			"path": filepath,
		}, nil
	}

	return nil, nil
}

func checkoutResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema{
			"path": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
			},
			"repo": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"branch": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "master",
			},
			"head": &schema.Schema{
				Type: schema.TypeString,
				Computed: true,
			},
		},
		Create: CheckoutCreate,
		Read: CheckoutRead,
		Update: nil,
		Delete: CheckoutDelete,
	}
}

func CheckoutCreate(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Get("path").(string)
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)

	if err := os.MkdirAll(checkout_dir, 0755); err != nil {
		return err
	}

	if _, err := gitCommand(checkout_dir, "clone", "-b", branch, "--", repo, "."); err != nil {
		return err
	}
	var head string
	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	d.Set("head", head)
	d.SetId(checkout_dir)
	return nil
}

func CheckoutRead(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Id()
	var repo string
	var branch string
	var head string

	if out, err := gitCommand(checkout_dir, "config", "--get", "remote.origin.url"); err != nil {
		return err
	} else {
		repo = strings.TrimRight(string(out), "\n")
	}
	if out, err := gitCommand(checkout_dir, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	} else {
		branch = strings.TrimRight(string(out), "\n")
	}

	if _, err := gitCommand(checkout_dir, "pull", "--ff-only", "origin"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	d.Set("path", checkout_dir)
	d.Set("repo", repo)
	d.Set("branch", branch)
	d.Set("head", head)
	return nil
}

func CheckoutDelete(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Id()
	expected_repo := d.Get("repo").(string)
	expected_branch := d.Get("branch").(string)
	expected_head := d.Get("head").(string)

	// sanity check
	var repo string
	var branch string
	var head string

	if out, err := gitCommand(checkout_dir, "config", "--get", "remote.origin.url"); err != nil {
		return err
	} else {
		repo = strings.TrimRight(string(out), "\n")
	}
	if out, err := gitCommand(checkout_dir, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	} else {
		branch = strings.TrimRight(string(out), "\n")
	}

	if _, err := gitCommand(checkout_dir, "pull", "--ff-only", "origin"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	if expected_repo != repo {
		return fmt.Errorf("expected repo to be %s, was %s", expected_repo, repo)
	}
	if expected_branch != branch {
		return fmt.Errorf("expected branch to be %s, was %s", expected_branch, branch)
	}
	if expected_head != head {
		return fmt.Errorf("expected head to be %s, was %s", expected_head, head)
	}

	// more sanity checks
	if out, err := gitCommand(checkout_dir, "clean", "-dn"); err != nil {
		return err
	} else {
		if out != nil && string(out) != "" {
			return fmt.Errorf("Refusing to delete checkout %s with untracked files: %s", checkout_dir, string(out))
		}
	}
	if out, err := gitCommand(checkout_dir, "diff-index", "--exit-code", "HEAD"); err != nil {
		exitErr, isExitErr := err.(*exec.ExitError)
		if isExitErr {
			if exitErr.Sys().(syscall.WaitStatus).ExitStatus() != 1 {
				return err
			} else {
				return fmt.Errorf("Refusing to delete dirty checkout %s: %s", checkout_dir, string(out))
			}
		} else {
			return err
		}
	}

	// actually delete
	if err := os.RemoveAll(checkout_dir); err != nil {
		return err
	}

	return nil
}

func commitResource(file_resource *schema.Resource) *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema {
			"commit_message": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "Created by terraform gitfile_commit",
			},
			"checkout_dir": &schema.Schema {
				Type: schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"file": &schema.Schema {
				Type: schema.TypeSet,
				Required: true,
				Set: hashFile,
				Elem: file_resource,
			},
		},
		Create: CommitCreate,
		Read: CommitRead,
		Update: CommitCreate,
		Delete: CommitDelete,
	}
}

func CommitCreate(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Get("checkout_dir").(string)
	files := d.Get("file").(*schema.Set)
	commit_message := d.Get("commit_message").(string)
	filepaths := []string{}
	filepaths_to_commit := []string{}
	for _, file := range files.List() {
		filepath := file.(map[string]interface{})["path"].(string)
		filepaths = append(filepaths, filepath)

		if existing_content_bytes, err := ioutil.ReadFile(path.Join(checkout_dir, filepath)); err != nil && !os.IsNotExist(err) {
			return err;
		} else {
			contents := file.(map[string]interface{})["contents"].(string)
			// we only want to git add/git commit if we've changed this file
			// so if it existed before (err == nil) and the contents are the same
			// then don't bother.
			if !(err == nil && contents == string(existing_content_bytes)) {
				filepaths_to_commit = append(filepaths_to_commit, filepath)
			}
			if err := fileCreateUpdate(checkout_dir, filepath, contents); err != nil {
				return err
			}
		}
	}

	var sha string
	if _, err := gitCommand(checkout_dir, flatten("add", "--", filepaths_to_commit)...); err != nil {
		return err
	}

	commit_body := fmt.Sprintf("%s\n%s", CommitBodyHeader, strings.Join(filepaths, "\n"))
	if _, err := gitCommand(checkout_dir, flatten("commit", "-m", commit_message, "-m", commit_body, "--allow-empty", "--", filepaths_to_commit)...); err != nil {
		return err
	}

	if _, err := gitCommand(checkout_dir, "push", "origin", "HEAD"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		sha = strings.TrimRight(string(out), "\n")
	}

	d.SetId(fmt.Sprintf("%s %s", sha, checkout_dir))
	return nil
}

func getFilePathsFromCommit(checkout_dir, sha string) ([]string, error) {
	filepaths := []string{}

	if out, err := gitCommand(checkout_dir, "show", "-s", "--format=%b", sha); err != nil {
		return nil, err
	} else {
		for i, filepath := range strings.Split(string(out), "\n") {
			if i == 0 {
				if filepath != CommitBodyHeader {
					return nil, fmt.Errorf("Expected body of commit to contain %v, got %v", CommitBodyHeader, filepath)
				}
			} else {
				if filepath != "" {
					filepaths = append(filepaths, filepath)
				}
			}
		}
	}
	return filepaths, nil
}

func CommitRead(d *schema.ResourceData, meta interface{}) error {
	list := strings.SplitN(d.Id(), " ", 2)

	sha := list[0]
	checkout_dir := list[1]
	var filepaths []string
	if _filepaths, err := getFilePathsFromCommit(checkout_dir, sha); err != nil {
		return err
	} else {
		filepaths = _filepaths
	}

	d.Set("checkout_dir", checkout_dir)
	d.Set("sha", sha)

	files := []map[string]interface{}{}
	for _, filepath := range filepaths {
		if filedata, err := fileRead(checkout_dir, filepath); err != nil {
			return err
		} else {
			files = append(files, filedata)
		}
	}
	d.Set("file", files)

	commit_message := ""
	if out, err := gitCommand(checkout_dir, "show", "-s", "--format=%s", sha); err != nil {
		return err
	} else {
		commit_message = strings.TrimRight(string(out), "\n")
	}
	d.Set("commit_message", commit_message)

	return nil
}

func CommitDelete(d *schema.ResourceData, meta interface{}) error {
	return nil
}

func hashFile(v interface{}) int {
	switch v := v.(type) {
	default:
		panic(fmt.Sprintf("unexpectedtype %T", v))
	case map[string]string:
		return hashcode.String(v["path"])
	case map[string]interface{}:
		return hashcode.String(v["path"].(string))
	}
	return -1
}

func gitCommand(checkout_dir string, args ...string) ([]byte, error) {
	command := exec.Command("git", args...)
	command.Dir = checkout_dir
	out, err := command.CombinedOutput()
	if err != nil {
		return out, errwrap.Wrapf(fmt.Sprintf("Error while running git %s: {{err}}\nWorking dir: %s\nOutput: %s", strings.Join(args, " "), checkout_dir, string(out)), err)
	} else {
		return out, err
	}
}

func flatten(args ...interface{}) []string {
	ret := make([]string, 0, len(args))

	for _, arg := range args {
		switch arg := arg.(type) {
		default:
			panic("can only handle strings and []strings")
		case string:
			ret = append(ret, arg)
		case []string:
			ret = append(ret, arg...)
		}
	}

	return ret
}

<commit_msg>Remove orphaned config options.<commit_after>package gitfile

import (
	"github.com/hashicorp/errwrap"
	"os/exec"
	"fmt"
	"github.com/hashicorp/terraform/helper/hashcode"
	"io/ioutil"
	"os"
	"path"
	"github.com/hashicorp/terraform/helper/schema"
	"strings"
	"syscall"
	"github.com/hashicorp/terraform/terraform"
)

const CommitBodyHeader string = "The following files are managed by terraform:"

func Provider() terraform.ResourceProvider {
	file_resource := fileResource()
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
		},
		ResourcesMap: map[string]*schema.Resource{
			"gitfile_checkout": checkoutResource(),
			"gitfile_commit": commitResource(file_resource),
		},
		ConfigureFunc: gitfileConfigure,
	}
}

func gitfileConfigure(data *schema.ResourceData) (interface{}, error) {
	config := &gitfileConfig {
	}
	return config, nil
}

type gitfileConfig struct {
}

func fileResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema{
			"path": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"contents": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
		},
	}
}

func fileCreateUpdate(checkout_dir, filepath, contents string) error {
	if err := ioutil.WriteFile(path.Join(checkout_dir, filepath), []byte(contents), 0666); err != nil {
		return err
	}

	return nil
}

func fileRead(checkout_dir, filepath string) (map[string]interface{}, error) {
	if content_bytes, err := ioutil.ReadFile(path.Join(checkout_dir, filepath)); err != nil {
		return nil, err
	} else {
		return map[string]interface{}{
			"contents": string(content_bytes),
			"path": filepath,
		}, nil
	}

	return nil, nil
}

func checkoutResource() *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema{
			"path": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
			},
			"repo": &schema.Schema{
				Type: schema.TypeString,
				Required: true,
			},
			"branch": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "master",
			},
			"head": &schema.Schema{
				Type: schema.TypeString,
				Computed: true,
			},
		},
		Create: CheckoutCreate,
		Read: CheckoutRead,
		Update: nil,
		Delete: CheckoutDelete,
	}
}

func CheckoutCreate(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Get("path").(string)
	repo := d.Get("repo").(string)
	branch := d.Get("branch").(string)

	if err := os.MkdirAll(checkout_dir, 0755); err != nil {
		return err
	}

	if _, err := gitCommand(checkout_dir, "clone", "-b", branch, "--", repo, "."); err != nil {
		return err
	}
	var head string
	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	d.Set("head", head)
	d.SetId(checkout_dir)
	return nil
}

func CheckoutRead(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Id()
	var repo string
	var branch string
	var head string

	if out, err := gitCommand(checkout_dir, "config", "--get", "remote.origin.url"); err != nil {
		return err
	} else {
		repo = strings.TrimRight(string(out), "\n")
	}
	if out, err := gitCommand(checkout_dir, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	} else {
		branch = strings.TrimRight(string(out), "\n")
	}

	if _, err := gitCommand(checkout_dir, "pull", "--ff-only", "origin"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	d.Set("path", checkout_dir)
	d.Set("repo", repo)
	d.Set("branch", branch)
	d.Set("head", head)
	return nil
}

func CheckoutDelete(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Id()
	expected_repo := d.Get("repo").(string)
	expected_branch := d.Get("branch").(string)
	expected_head := d.Get("head").(string)

	// sanity check
	var repo string
	var branch string
	var head string

	if out, err := gitCommand(checkout_dir, "config", "--get", "remote.origin.url"); err != nil {
		return err
	} else {
		repo = strings.TrimRight(string(out), "\n")
	}
	if out, err := gitCommand(checkout_dir, "rev-parse", "--abbrev-ref", "HEAD"); err != nil {
		return err
	} else {
		branch = strings.TrimRight(string(out), "\n")
	}

	if _, err := gitCommand(checkout_dir, "pull", "--ff-only", "origin"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		head = strings.TrimRight(string(out), "\n")
	}

	if expected_repo != repo {
		return fmt.Errorf("expected repo to be %s, was %s", expected_repo, repo)
	}
	if expected_branch != branch {
		return fmt.Errorf("expected branch to be %s, was %s", expected_branch, branch)
	}
	if expected_head != head {
		return fmt.Errorf("expected head to be %s, was %s", expected_head, head)
	}

	// more sanity checks
	if out, err := gitCommand(checkout_dir, "clean", "-dn"); err != nil {
		return err
	} else {
		if out != nil && string(out) != "" {
			return fmt.Errorf("Refusing to delete checkout %s with untracked files: %s", checkout_dir, string(out))
		}
	}
	if out, err := gitCommand(checkout_dir, "diff-index", "--exit-code", "HEAD"); err != nil {
		exitErr, isExitErr := err.(*exec.ExitError)
		if isExitErr {
			if exitErr.Sys().(syscall.WaitStatus).ExitStatus() != 1 {
				return err
			} else {
				return fmt.Errorf("Refusing to delete dirty checkout %s: %s", checkout_dir, string(out))
			}
		} else {
			return err
		}
	}

	// actually delete
	if err := os.RemoveAll(checkout_dir); err != nil {
		return err
	}

	return nil
}

func commitResource(file_resource *schema.Resource) *schema.Resource {
	return &schema.Resource {
		Schema: map[string]*schema.Schema {
			"commit_message": &schema.Schema{
				Type: schema.TypeString,
				Optional: true,
				Default: "Created by terraform gitfile_commit",
			},
			"checkout_dir": &schema.Schema {
				Type: schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"file": &schema.Schema {
				Type: schema.TypeSet,
				Required: true,
				Set: hashFile,
				Elem: file_resource,
			},
		},
		Create: CommitCreate,
		Read: CommitRead,
		Update: CommitCreate,
		Delete: CommitDelete,
	}
}

func CommitCreate(d *schema.ResourceData, meta interface{}) error {
	checkout_dir := d.Get("checkout_dir").(string)
	files := d.Get("file").(*schema.Set)
	commit_message := d.Get("commit_message").(string)
	filepaths := []string{}
	filepaths_to_commit := []string{}
	for _, file := range files.List() {
		filepath := file.(map[string]interface{})["path"].(string)
		filepaths = append(filepaths, filepath)

		if existing_content_bytes, err := ioutil.ReadFile(path.Join(checkout_dir, filepath)); err != nil && !os.IsNotExist(err) {
			return err;
		} else {
			contents := file.(map[string]interface{})["contents"].(string)
			// we only want to git add/git commit if we've changed this file
			// so if it existed before (err == nil) and the contents are the same
			// then don't bother.
			if !(err == nil && contents == string(existing_content_bytes)) {
				filepaths_to_commit = append(filepaths_to_commit, filepath)
			}
			if err := fileCreateUpdate(checkout_dir, filepath, contents); err != nil {
				return err
			}
		}
	}

	var sha string
	if _, err := gitCommand(checkout_dir, flatten("add", "--", filepaths_to_commit)...); err != nil {
		return err
	}

	commit_body := fmt.Sprintf("%s\n%s", CommitBodyHeader, strings.Join(filepaths, "\n"))
	if _, err := gitCommand(checkout_dir, flatten("commit", "-m", commit_message, "-m", commit_body, "--allow-empty", "--", filepaths_to_commit)...); err != nil {
		return err
	}

	if _, err := gitCommand(checkout_dir, "push", "origin", "HEAD"); err != nil {
		return err
	}

	if out, err := gitCommand(checkout_dir, "rev-parse", "HEAD"); err != nil {
		return err
	} else {
		sha = strings.TrimRight(string(out), "\n")
	}

	d.SetId(fmt.Sprintf("%s %s", sha, checkout_dir))
	return nil
}

func getFilePathsFromCommit(checkout_dir, sha string) ([]string, error) {
	filepaths := []string{}

	if out, err := gitCommand(checkout_dir, "show", "-s", "--format=%b", sha); err != nil {
		return nil, err
	} else {
		for i, filepath := range strings.Split(string(out), "\n") {
			if i == 0 {
				if filepath != CommitBodyHeader {
					return nil, fmt.Errorf("Expected body of commit to contain %v, got %v", CommitBodyHeader, filepath)
				}
			} else {
				if filepath != "" {
					filepaths = append(filepaths, filepath)
				}
			}
		}
	}
	return filepaths, nil
}

func CommitRead(d *schema.ResourceData, meta interface{}) error {
	list := strings.SplitN(d.Id(), " ", 2)

	sha := list[0]
	checkout_dir := list[1]
	var filepaths []string
	if _filepaths, err := getFilePathsFromCommit(checkout_dir, sha); err != nil {
		return err
	} else {
		filepaths = _filepaths
	}

	d.Set("checkout_dir", checkout_dir)
	d.Set("sha", sha)

	files := []map[string]interface{}{}
	for _, filepath := range filepaths {
		if filedata, err := fileRead(checkout_dir, filepath); err != nil {
			return err
		} else {
			files = append(files, filedata)
		}
	}
	d.Set("file", files)

	commit_message := ""
	if out, err := gitCommand(checkout_dir, "show", "-s", "--format=%s", sha); err != nil {
		return err
	} else {
		commit_message = strings.TrimRight(string(out), "\n")
	}
	d.Set("commit_message", commit_message)

	return nil
}

func CommitDelete(d *schema.ResourceData, meta interface{}) error {
	return nil
}

func hashFile(v interface{}) int {
	switch v := v.(type) {
	default:
		panic(fmt.Sprintf("unexpectedtype %T", v))
	case map[string]string:
		return hashcode.String(v["path"])
	case map[string]interface{}:
		return hashcode.String(v["path"].(string))
	}
	return -1
}

func gitCommand(checkout_dir string, args ...string) ([]byte, error) {
	command := exec.Command("git", args...)
	command.Dir = checkout_dir
	out, err := command.CombinedOutput()
	if err != nil {
		return out, errwrap.Wrapf(fmt.Sprintf("Error while running git %s: {{err}}\nWorking dir: %s\nOutput: %s", strings.Join(args, " "), checkout_dir, string(out)), err)
	} else {
		return out, err
	}
}

func flatten(args ...interface{}) []string {
	ret := make([]string, 0, len(args))

	for _, arg := range args {
		switch arg := arg.(type) {
		default:
			panic("can only handle strings and []strings")
		case string:
			ret = append(ret, arg)
		case []string:
			ret = append(ret, arg...)
		}
	}

	return ret
}

<|endoftext|>


<commit_before>// Syslog interface for Unix variants only

// +build !windows,!nacl,!plan9

package log

import (
	"log"
	"log/syslog"
	"os"
	"path"

	"github.com/rclone/rclone/fs"
)

var (
	syslogFacilityMap = map[string]syslog.Priority{
		"KERN":     syslog.LOG_KERN,
		"USER":     syslog.LOG_USER,
		"MAIL":     syslog.LOG_MAIL,
		"DAEMON":   syslog.LOG_DAEMON,
		"AUTH":     syslog.LOG_AUTH,
		"SYSLOG":   syslog.LOG_SYSLOG,
		"LPR":      syslog.LOG_LPR,
		"NEWS":     syslog.LOG_NEWS,
		"UUCP":     syslog.LOG_UUCP,
		"CRON":     syslog.LOG_CRON,
		"AUTHPRIV": syslog.LOG_AUTHPRIV,
		"FTP":      syslog.LOG_FTP,
	}
)

// Starts syslog
func startSysLog() bool {
	facility, ok := syslogFacilityMap[Opt.SyslogFacility]
	if !ok {
		log.Fatalf("Unknown syslog facility %q - man syslog for list", Opt.SyslogFacility)
	}
	Me := path.Base(os.Args[0])
	w, err := syslog.New(syslog.LOG_NOTICE|facility, Me)
	if err != nil {
		log.Fatalf("Failed to start syslog: %v", err)
	}
	log.SetFlags(0)
	log.SetOutput(w)
	fs.LogPrint = func(level fs.LogLevel, text string) {
		switch level {
		case fs.LogLevelEmergency:
			_ = w.Emerg(text)
		case fs.LogLevelAlert:
			_ = w.Alert(text)
		case fs.LogLevelCritical:
			_ = w.Crit(text)
		case fs.LogLevelError:
			_ = w.Err(text)
		case fs.LogLevelWarning:
			_ = w.Warning(text)
		case fs.LogLevelNotice:
			_ = w.Notice(text)
		case fs.LogLevelInfo:
			_ = w.Info(text)
		case fs.LogLevelDebug:
			_ = w.Debug(text)
		}
	}
	return true
}
<commit_msg>fs/log: add support for syslog LOCAL facilities - fixes #4061<commit_after>// Syslog interface for Unix variants only

// +build !windows,!nacl,!plan9

package log

import (
	"log"
	"log/syslog"
	"os"
	"path"

	"github.com/rclone/rclone/fs"
)

var (
	syslogFacilityMap = map[string]syslog.Priority{
		"KERN":     syslog.LOG_KERN,
		"USER":     syslog.LOG_USER,
		"MAIL":     syslog.LOG_MAIL,
		"DAEMON":   syslog.LOG_DAEMON,
		"AUTH":     syslog.LOG_AUTH,
		"SYSLOG":   syslog.LOG_SYSLOG,
		"LPR":      syslog.LOG_LPR,
		"NEWS":     syslog.LOG_NEWS,
		"UUCP":     syslog.LOG_UUCP,
		"CRON":     syslog.LOG_CRON,
		"AUTHPRIV": syslog.LOG_AUTHPRIV,
		"FTP":      syslog.LOG_FTP,
		"LOCAL0":   syslog.LOG_LOCAL0,
		"LOCAL1":   syslog.LOG_LOCAL1,
		"LOCAL2":   syslog.LOG_LOCAL2,
		"LOCAL3":   syslog.LOG_LOCAL3,
		"LOCAL4":   syslog.LOG_LOCAL4,
		"LOCAL5":   syslog.LOG_LOCAL5,
		"LOCAL6":   syslog.LOG_LOCAL6,
		"LOCAL7":   syslog.LOG_LOCAL7,
	}
)

// Starts syslog
func startSysLog() bool {
	facility, ok := syslogFacilityMap[Opt.SyslogFacility]
	if !ok {
		log.Fatalf("Unknown syslog facility %q - man syslog for list", Opt.SyslogFacility)
	}
	Me := path.Base(os.Args[0])
	w, err := syslog.New(syslog.LOG_NOTICE|facility, Me)
	if err != nil {
		log.Fatalf("Failed to start syslog: %v", err)
	}
	log.SetFlags(0)
	log.SetOutput(w)
	fs.LogPrint = func(level fs.LogLevel, text string) {
		switch level {
		case fs.LogLevelEmergency:
			_ = w.Emerg(text)
		case fs.LogLevelAlert:
			_ = w.Alert(text)
		case fs.LogLevelCritical:
			_ = w.Crit(text)
		case fs.LogLevelError:
			_ = w.Err(text)
		case fs.LogLevelWarning:
			_ = w.Warning(text)
		case fs.LogLevelNotice:
			_ = w.Notice(text)
		case fs.LogLevelInfo:
			_ = w.Info(text)
		case fs.LogLevelDebug:
			_ = w.Debug(text)
		}
	}
	return true
}
<|endoftext|>


<commit_before>package test

import (
	"path/filepath"
	"runtime"
	"testing"

	. "github.com/QQorp/QQat/models"
	"github.com/astaxie/beego"
	. "github.com/smartystreets/goconvey/convey"
)

func init() {
	_, file, _, _ := runtime.Caller(1)
	apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
	beego.TestBeegoInit(apppath)
}

// TestMain is a sample to run an endpoint test
func TestChannel(t *testing.T) {
	Convey("Testing channel model", t, func() {
		Reset(ResetRedis)
		Convey("Testing CreateChannel", func() {
			Convey("Creating a channel with blank name, should return an error", func() {
				channel, err := CreateChannel("")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Creating a channel with a name, should return a Channel", func() {
				channelName := "QQ"
				channel, err := CreateChannel(channelName)

				So(channel, ShouldNotBeNil)
				So(channel.ChannelName, ShouldEqual, channelName)
				So(err, ShouldBeNil)
			})
			Convey("Creating two channels with the same name, should return different channels", func() {
				channelName := "QQ"
				channel1, err1 := CreateChannel(channelName)
				channel2, err2 := CreateChannel(channelName)

				So(channel1, ShouldNotBeNil)
				So(channel2, ShouldNotBeNil)
				So(channel1.ChannelName, ShouldEqual, channelName)
				So(channel1.ChannelName, ShouldEqual, channel2.ChannelName)
				So(channel1.ChannelUID, ShouldNotEqual, channel2.ChannelUID)
				So(err1, ShouldBeNil)
				So(err2, ShouldBeNil)
			})
		})
		Convey("Testing GetChannel", func() {
			Convey("Getting channel with an empty string, should return error", func() {
				channel, err := GetChannel("")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Getting channel that does not exists, should return error", func() {
				channel, err := GetChannel("AAA")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Creating a channel and getting it, should return the channel", func() {
				channelName := "lel"
				createdChannel, _ := CreateChannel(channelName)
				channel, err := GetChannel(createdChannel.ChannelUID)

				So(channel, ShouldNotBeNil)
				So(err, ShouldBeNil)
				So(channel.ChannelName, ShouldEqual, channelName)
				So(channel.ChannelUID, ShouldEqual, createdChannel.ChannelUID)
			})
		})
	})
}
<commit_msg>Tests: Models: Channels: Added tests related to GetAllChannels()<commit_after>package test

import (
	"path/filepath"
	"runtime"
	"testing"

	. "github.com/QQorp/QQat/models"
	"github.com/astaxie/beego"
	. "github.com/smartystreets/goconvey/convey"
)

func init() {
	_, file, _, _ := runtime.Caller(1)
	apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
	beego.TestBeegoInit(apppath)
}

// TestMain is a sample to run an endpoint test
func TestChannel(t *testing.T) {
	Convey("Testing channel model", t, func() {
		Reset(ResetRedis)
		Convey("Testing CreateChannel", func() {
			Convey("Creating a channel with blank name, should return an error", func() {
				channel, err := CreateChannel("")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Creating a channel with a name, should return a Channel", func() {
				channelName := "QQ"
				channel, err := CreateChannel(channelName)

				So(channel, ShouldNotBeNil)
				So(channel.ChannelName, ShouldEqual, channelName)
				So(err, ShouldBeNil)
			})
			Convey("Creating two channels with the same name, should return different channels", func() {
				channelName := "QQ"
				channel1, err1 := CreateChannel(channelName)
				channel2, err2 := CreateChannel(channelName)

				So(channel1, ShouldNotBeNil)
				So(channel2, ShouldNotBeNil)
				So(channel1.ChannelName, ShouldEqual, channelName)
				So(channel1.ChannelName, ShouldEqual, channel2.ChannelName)
				So(channel1.ChannelUID, ShouldNotEqual, channel2.ChannelUID)
				So(err1, ShouldBeNil)
				So(err2, ShouldBeNil)
			})
		})
		Convey("Testing GetChannel", func() {
			Convey("Getting channel with an empty string, should return error", func() {
				channel, err := GetChannel("")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Getting channel that does not exists, should return error", func() {
				channel, err := GetChannel("AAA")

				So(channel, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})
			Convey("Creating a channel and getting it, should return the channel", func() {
				channelName := "lel"
				createdChannel, _ := CreateChannel(channelName)
				channel, err := GetChannel(createdChannel.ChannelUID)

				So(channel, ShouldNotBeNil)
				So(err, ShouldBeNil)
				So(channel.ChannelName, ShouldEqual, channelName)
				So(channel.ChannelUID, ShouldEqual, createdChannel.ChannelUID)
			})
		})
		Convey("Testing GetAllChannels", func() {
			Convey("Getting all channels with 0 channels, should return empty array", func() {
				channels, err := GetAllChannels()

				So(channels, ShouldBeEmpty)
				So(err, ShouldBeNil)
			})
			Convey("Getting all channels with 1 channel created, should return array with 1 element", func() {
				CreateChannel("lel")
				channels, err := GetAllChannels()

				So(len(channels), ShouldEqual, 1)
				So(err, ShouldBeNil)
			})
			Convey("Getting all channels with 5 channels created, should return array with 5 elements", func() {
				var nbElements = 5
				for index := 0; index < nbElements; index++ {
					CreateChannel("lel")
				}
				channels, err := GetAllChannels()

				So(len(channels), ShouldEqual, nbElements)
				So(err, ShouldBeNil)
			})
			Convey("Getting all channels with 500 channels created, should return array with 500 elements", func() {
				var nbElements = 500
				for index := 0; index < nbElements; index++ {
					CreateChannel("lel")
				}
				channels, err := GetAllChannels()

				So(len(channels), ShouldEqual, nbElements)
				So(err, ShouldBeNil)
			})
			Convey("Getting all channels with 1000 channels created, should return array with 1000 elements", func() {
				var nbElements = 1000
				for index := 0; index < nbElements; index++ {
					CreateChannel("lel")
				}
				channels, err := GetAllChannels()

				So(len(channels), ShouldEqual, nbElements)
				So(err, ShouldBeNil)
			})
		})
	})
}
<|endoftext|>


<commit_before>package authenticators

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"strconv"

	"github.com/cloudfoundry-incubator/receptor"
	"github.com/pivotal-golang/lager"
	"golang.org/x/crypto/ssh"
)

const CF_REALM = "cf"

type CFAuthenticator struct {
	logger         lager.Logger
	ccClient       *http.Client
	ccURL          string
	receptorClient receptor.Client
}

var CFPrincipalRegex *regexp.Regexp = regexp.MustCompile(`(.*)/(\d+)`)
var CFRealmRegex *regexp.Regexp = regexp.MustCompile(CF_REALM + `:(.*)`)

func NewCFAuthenticator(
	logger lager.Logger,
	ccClient *http.Client,
	ccURL string,
	receptorClient receptor.Client,
) *CFAuthenticator {
	return &CFAuthenticator{
		logger:         logger,
		ccClient:       ccClient,
		ccURL:          ccURL,
		receptorClient: receptorClient,
	}
}

func (cfa *CFAuthenticator) Realm() string {
	return CF_REALM
}

type AppSSHResponse struct {
	ProcessGuid string `json:"process_guid"`
}

func (cfa *CFAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
	logger := cfa.logger.Session("authenticate")
	if !CFRealmRegex.Match([]byte(metadata.User())) {
		return nil, InvalidDomainErr
	}

	principal := CFRealmRegex.FindStringSubmatch(metadata.User())[1]
	if !CFPrincipalRegex.Match([]byte(principal)) {
		return nil, InvalidCredentialsErr
	}

	guidAndIndex := CFPrincipalRegex.FindStringSubmatch(principal)

	index, err := strconv.Atoi(guidAndIndex[2])
	if err != nil {
		logger.Error("atoi-failed", err)
		return nil, InvalidCredentialsErr
	}

	appGuid := guidAndIndex[1]
	path := fmt.Sprintf("%s/internal/apps/%s/ssh_access", cfa.ccURL, appGuid)

	req, err := http.NewRequest("GET", path, nil)
	if err != nil {
		logger.Error("creating-request-failed", InvalidRequestErr)
		return nil, InvalidRequestErr
	}
	req.Header.Add("Authorization", string(password))

	resp, err := cfa.ccClient.Do(req)
	if err != nil {
		logger.Error("fetching-app-failed", err)
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		logger.Error("fetching-app-failed", FetchAppFailedErr, lager.Data{
			"StatusCode":   resp.Status,
			"ResponseBody": resp.Body,
		})
		return nil, FetchAppFailedErr
	}

	var app AppSSHResponse
	err = json.NewDecoder(resp.Body).Decode(&app)
	if err != nil {
		logger.Error("invalid-cc-response", err)
		return nil, InvalidCCResponse
	}

	permissions, err := sshPermissionsFromProcess(app.ProcessGuid, index, cfa.receptorClient, metadata.RemoteAddr())
	if err != nil {
		logger.Error("building-ssh-permissions-failed", err)
	}

	return permissions, err
}
<commit_msg>Close response body when getting ssh_access from CC<commit_after>package authenticators

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"strconv"

	"github.com/cloudfoundry-incubator/receptor"
	"github.com/pivotal-golang/lager"
	"golang.org/x/crypto/ssh"
)

const CF_REALM = "cf"

type CFAuthenticator struct {
	logger         lager.Logger
	ccClient       *http.Client
	ccURL          string
	receptorClient receptor.Client
}

var CFPrincipalRegex *regexp.Regexp = regexp.MustCompile(`(.*)/(\d+)`)
var CFRealmRegex *regexp.Regexp = regexp.MustCompile(CF_REALM + `:(.*)`)

func NewCFAuthenticator(
	logger lager.Logger,
	ccClient *http.Client,
	ccURL string,
	receptorClient receptor.Client,
) *CFAuthenticator {
	return &CFAuthenticator{
		logger:         logger,
		ccClient:       ccClient,
		ccURL:          ccURL,
		receptorClient: receptorClient,
	}
}

func (cfa *CFAuthenticator) Realm() string {
	return CF_REALM
}

type AppSSHResponse struct {
	ProcessGuid string `json:"process_guid"`
}

func (cfa *CFAuthenticator) Authenticate(metadata ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
	logger := cfa.logger.Session("authenticate")
	if !CFRealmRegex.Match([]byte(metadata.User())) {
		return nil, InvalidDomainErr
	}

	principal := CFRealmRegex.FindStringSubmatch(metadata.User())[1]
	if !CFPrincipalRegex.Match([]byte(principal)) {
		return nil, InvalidCredentialsErr
	}

	guidAndIndex := CFPrincipalRegex.FindStringSubmatch(principal)

	index, err := strconv.Atoi(guidAndIndex[2])
	if err != nil {
		logger.Error("atoi-failed", err)
		return nil, InvalidCredentialsErr
	}

	appGuid := guidAndIndex[1]
	path := fmt.Sprintf("%s/internal/apps/%s/ssh_access", cfa.ccURL, appGuid)

	req, err := http.NewRequest("GET", path, nil)
	if err != nil {
		logger.Error("creating-request-failed", InvalidRequestErr)
		return nil, InvalidRequestErr
	}
	req.Header.Add("Authorization", string(password))

	resp, err := cfa.ccClient.Do(req)
	if err != nil {
		logger.Error("fetching-app-failed", err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		logger.Error("fetching-app-failed", FetchAppFailedErr, lager.Data{
			"StatusCode":   resp.Status,
			"ResponseBody": resp.Body,
		})
		return nil, FetchAppFailedErr
	}

	var app AppSSHResponse
	err = json.NewDecoder(resp.Body).Decode(&app)
	if err != nil {
		logger.Error("invalid-cc-response", err)
		return nil, InvalidCCResponse
	}

	permissions, err := sshPermissionsFromProcess(app.ProcessGuid, index, cfa.receptorClient, metadata.RemoteAddr())
	if err != nil {
		logger.Error("building-ssh-permissions-failed", err)
	}

	return permissions, err
}
<|endoftext|>