<commit_before>package checks

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"time"

	"github.com/Knetic/govaluate"

	"github.com/abrander/gansoi/agents"
	"github.com/abrander/gansoi/database"
)

type (
	// Check defines a check to be conducted by Gansoi.
	Check struct {
		ID          string          `json:"id"`
		AgentID     string          `json:"agent"`
		Interval    time.Duration   `json:"interval"`
		Node        string          `json:"node"`
		Arguments   json.RawMessage `json:"arguments"`
		Agent       agents.Agent    `json:"-"`
		Expressions []string        `json:"expressions"`
	}

	checkProxy struct {
		ID          string          `json:"id"`
		AgentID     string          `json:"agent"`
		Interval    time.Duration   `json:"interval"`
		Node        string          `json:"node"`
		Arguments   json.RawMessage `json:"arguments"`
		Expressions []string        `json:"expressions"`
	}
)

func init() {
	database.RegisterType(Check{})
}

// UnmarshalJSON implements json.Unmarshaler.
func (c *Check) UnmarshalJSON(data []byte) error {
	proxy := checkProxy{}

	err := json.Unmarshal(data, &proxy)
	if err != nil {
		return err
	}

	c.ID = proxy.ID
	c.AgentID = proxy.AgentID
	c.Interval = proxy.Interval
	c.Node = proxy.Node
	c.Arguments = proxy.Arguments
	c.Expressions = proxy.Expressions

	c.Agent = agents.GetAgent(c.AgentID)
	if c.Agent == nil {
		return errors.New("Agent not found")
	}

	err = json.Unmarshal(c.Arguments, &c.Agent)
	if err != nil {
		return err
	}

	return nil
}

// RunCheck will run a check and return a CheckResult.
func RunCheck(check *Check) *database.CheckResult {
	result, e := check.Agent.Check()

	checkResult := &database.CheckResult{
		CheckID:   check.ID,
		TimeStamp: time.Now(),
		Results:   result,
	}

	// If any expressions is defined, we try to evaluate them until one fails.
	if len(check.Expressions) > 0 && e == nil {
		e = check.Evaluate(result)
	}

	if e != nil {
		checkResult.Error = e.Error()
	}

	return checkResult
}

func newStructMap(in interface{}) map[string]interface{} {
	r := make(map[string]interface{})
	v := reflect.ValueOf(in)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	// We only accept structs, return an empty map we're served anything else.
	if v.Kind() != reflect.Struct {
		return r
	}

	typ := v.Type()
	for i := 0; i < v.NumField(); i++ {
		fi := typ.Field(i)
		r[fi.Name] = v.Field(i).Interface()
	}

	return r
}

// Evaluate will evaluate the CheckResult based on a slice of expressions.
func (c *Check) Evaluate(results interface{}) error {
	// govaluate expects a map of values.
	m := newStructMap(results)

	for _, exp := range c.Expressions {
		e, err := govaluate.NewEvaluableExpression(exp)
		if err != nil {
			break
		}

		result, err := e.Evaluate(m)
		if err != nil {
			break
		}

		// This is a nifty go trick. If result is NOT a bool, this will assign
		// a default bool (false) value to checkResult.Passed - and not panic.
		passed, _ := result.(bool)

		// On first false evaluation, we skip the rest of the tests. We already
		// failed.
		if !passed {
			return fmt.Errorf("(%s) failed", exp)
		}
	}

	return nil
}
<commit_msg>Removed Node from Check (for now).<commit_after>package checks

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"time"

	"github.com/Knetic/govaluate"

	"github.com/abrander/gansoi/agents"
	"github.com/abrander/gansoi/database"
)

type (
	// Check defines a check to be conducted by Gansoi.
	Check struct {
		ID          string          `json:"id"`
		AgentID     string          `json:"agent"`
		Interval    time.Duration   `json:"interval"`
		Arguments   json.RawMessage `json:"arguments"`
		Agent       agents.Agent    `json:"-"`
		Expressions []string        `json:"expressions"`
	}

	checkProxy struct {
		ID          string          `json:"id"`
		AgentID     string          `json:"agent"`
		Interval    time.Duration   `json:"interval"`
		Node        string          `json:"node"`
		Arguments   json.RawMessage `json:"arguments"`
		Expressions []string        `json:"expressions"`
	}
)

func init() {
	database.RegisterType(Check{})
}

// UnmarshalJSON implements json.Unmarshaler.
func (c *Check) UnmarshalJSON(data []byte) error {
	proxy := checkProxy{}

	err := json.Unmarshal(data, &proxy)
	if err != nil {
		return err
	}

	c.ID = proxy.ID
	c.AgentID = proxy.AgentID
	c.Interval = proxy.Interval
	c.Arguments = proxy.Arguments
	c.Expressions = proxy.Expressions

	c.Agent = agents.GetAgent(c.AgentID)
	if c.Agent == nil {
		return errors.New("Agent not found")
	}

	err = json.Unmarshal(c.Arguments, &c.Agent)
	if err != nil {
		return err
	}

	return nil
}

// RunCheck will run a check and return a CheckResult.
func RunCheck(check *Check) *database.CheckResult {
	result, e := check.Agent.Check()

	checkResult := &database.CheckResult{
		CheckID:   check.ID,
		TimeStamp: time.Now(),
		Results:   result,
	}

	// If any expressions is defined, we try to evaluate them until one fails.
	if len(check.Expressions) > 0 && e == nil {
		e = check.Evaluate(result)
	}

	if e != nil {
		checkResult.Error = e.Error()
	}

	return checkResult
}

func newStructMap(in interface{}) map[string]interface{} {
	r := make(map[string]interface{})
	v := reflect.ValueOf(in)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	// We only accept structs, return an empty map we're served anything else.
	if v.Kind() != reflect.Struct {
		return r
	}

	typ := v.Type()
	for i := 0; i < v.NumField(); i++ {
		fi := typ.Field(i)
		r[fi.Name] = v.Field(i).Interface()
	}

	return r
}

// Evaluate will evaluate the CheckResult based on a slice of expressions.
func (c *Check) Evaluate(results interface{}) error {
	// govaluate expects a map of values.
	m := newStructMap(results)

	for _, exp := range c.Expressions {
		e, err := govaluate.NewEvaluableExpression(exp)
		if err != nil {
			break
		}

		result, err := e.Evaluate(m)
		if err != nil {
			break
		}

		// This is a nifty go trick. If result is NOT a bool, this will assign
		// a default bool (false) value to checkResult.Passed - and not panic.
		passed, _ := result.(bool)

		// On first false evaluation, we skip the rest of the tests. We already
		// failed.
		if !passed {
			return fmt.Errorf("(%s) failed", exp)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package service

import (
	"errors"
	"os/exec"
	"strconv"
	"strings"
)

func (e *Execution) status() (Status, error) {
	var st Status
	var out []byte
	var err error
	if e.sudo {
		out, err = exec.Command("sudo", "service", e.ServiceName, "status").CombinedOutput()
	} else {
		out, err = exec.Command("service", e.ServiceName, "status").CombinedOutput()
	}
	if err != nil {
		err = errors.New(string(out))
	} else {
		lines := strings.Split(string(out), " ")
		if len(lines) == 4 {
			if strings.HasPrefix(lines[1], "start/running") {
				st.Running = true
				pid := lines[3][0 : len(lines[3])-1]
				st.PID, err = strconv.Atoi(pid)
				if err != nil {
					panic(err)
				}
			}
		}
	}
	return st, err
}

func (e *Execution) callService(cmd string) (string, error) {
	if e.sudo {
		return execCmd("sudo", "service", e.ServiceName, cmd)
	}
	return execCmd("service", e.ServiceName, cmd)
}

func sudoDefault() bool {
	return true
}
<commit_msg> Implementing SYSV<commit_after>package service

import (
	"errors"
	"os/exec"
	"strconv"
	"strings"
)

func (e *Execution) status() (Status, error) {
	var st Status
	var out []byte
	var err error
	if e.sudo {
		out, err = exec.Command("sudo", "service", e.ServiceName, "status").CombinedOutput()
	} else {
		out, err = exec.Command("service", e.ServiceName, "status").CombinedOutput()
	}
	if err != nil {
		err = errors.New(string(out))
	} else {
		sOut := string(out)
		lines := strings.Split(sOut, "\n")
		// Upstart
		if len(lines) == 1 {
			words := strings.Split(string(out), " ")
			if len(words) == 4 {
				if strings.HasPrefix(words[1], "start/running") {
					st.Running = true
					pid := words[3][0 : len(words[3])-1]
					st.PID, err = strconv.Atoi(pid)
					if err != nil {
						panic(err)
					}
				}
			}
		} else if strings.HasPrefix(strings.Trim(lines[1], " "), "Loaded") {
			// SystemV
			for _, line := range lines {
				line = strings.Trim(line, " ")
				if strings.HasPrefix(line, "Active") {
					st.Running = strings.Contains(line, "active (running)")
				} else if strings.HasPrefix(line, "Main PID") {
					// Parse MAIN PID
				}
			}
		}
	}
	return st, err
}

func (e *Execution) callService(cmd string) (string, error) {
	if e.sudo {
		return execCmd("sudo", "service", e.ServiceName, cmd)
	}
	return execCmd("service", e.ServiceName, cmd)
}

func sudoDefault() bool {
	return true
}
<|endoftext|>


<commit_before>/*

	gamepkg is a package that helps locate, validate, and modify game package
	imports.

*/
package gamepkg

import (
	"errors"
	"github.com/jkomoros/boardgame/boardgame-util/lib/path"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
)

type GamePkg struct {
	//Every contstructo sets absolutePath to something that at least exists on
	//disk.
	absolutePath         string
	importPath           string
	calculatedIsGamePkg  bool
	memoizedIsGamePkg    bool
	memoizedIsGamePkgErr error
}

//New tries to interpret the input as an import. If that files, tries to
//interpret it as a path (rel or absolute), and if that fails, bails.
func New(importOrPath string) (*GamePkg, error) {
	pkg, err := NewFromImport(importOrPath)
	if err == nil {
		return pkg, nil
	}
	return NewFromPath(importOrPath)
}

//NewFromPath takes path (either relative or absolute path) and returns a new
//GamePkg. Will error if the given path does not appear to denote a valid game
//package for any reason.
func NewFromPath(path string) (*GamePkg, error) {

	if !filepath.IsAbs(path) {

		cwd, err := os.Getwd()

		if err != nil {
			return nil, errors.New("Couldn't get working directory: " + err.Error())
		}

		path = filepath.Join(cwd, path)
	}

	return newGamePkg(path, "")

}

//NewFromImport will return a new GamePkg pointing to that import. Will error
//if the given path does not appear to denote a valid game package for any
//reason.
func NewFromImport(importPath string) (*GamePkg, error) {

	absPath, err := path.AbsoluteGoPkgPath(importPath)

	if err != nil {
		return nil, errors.New("Absolute path couldn't be found: " + err.Error())
	}

	//If no error, then absPath must point to a valid thing

	return newGamePkg(absPath, importPath)

}

func newGamePkg(absPath, importPath string) (*GamePkg, error) {
	result := &GamePkg{
		absolutePath: absPath,
		importPath:   importPath,
	}

	if info, err := os.Stat(absPath); err != nil {
		return nil, errors.New("Path doesn't point to valid location on disk: " + err.Error())
	} else if !info.IsDir() {
		return nil, errors.New("Path points to an object but it's not a directory.")
	}

	if !result.goPkg() {
		return nil, errors.New(absPath + " denotes a folder with no go source files")
	}

	isGamePkg, err := result.isGamePkg()

	if !isGamePkg {
		return nil, errors.New(absPath + " was not a valid game package: " + err.Error())
	}

	return result, nil
}

//AbsolutePath returns the absolute path where the package in question resides
//on disk. All constructors will have errored if AbsolutePath doesn't at the
//very least point to a valid location on disk.
func (g *GamePkg) AbsolutePath() string {
	return g.absolutePath
}

//goPkg validates that the absolutePath denotes a package with at least one go
//file. If there's an error will default to false.
func (g *GamePkg) goPkg() bool {

	infos, _ := ioutil.ReadDir(g.AbsolutePath())

	for _, info := range infos {
		if filepath.Ext(info.Name()) == ".go" {
			return true
		}
	}

	return false

}

func (g *GamePkg) Import() (string, error) {
	//Calculate it if not already calculated (for example via NewFromImport constructor)
	if g.importPath == "" {

		goPkg, err := build.ImportDir(g.AbsolutePath(), 0)

		if err != nil {
			return "", errors.New("Couldn't read package: " + err.Error())
		}

		//TODO: factor this into a helper that also sets the package name in
		//case it's asked for later.
		g.importPath = goPkg.ImportPath
	}

	return g.importPath, nil
}

//isGamePkg verifies that the package appears to be a valid game package.
//Specifically it checks for
func (g *GamePkg) isGamePkg() (bool, error) {
	if !g.calculatedIsGamePkg {
		g.memoizedIsGamePkg, g.memoizedIsGamePkgErr = g.calculateIsGamePkg()
	}
	return g.memoizedIsGamePkg, g.memoizedIsGamePkgErr
}

func (g *GamePkg) calculateIsGamePkg() (bool, error) {
	pkgs, err := parser.ParseDir(token.NewFileSet(), g.AbsolutePath(), nil, 0)

	if err != nil {
		return false, errors.New("Couldn't parse folder: " + err.Error())
	}

	if len(pkgs) < 1 {
		return false, errors.New("No packages in that directory")
	}

	if len(pkgs) > 1 {
		return false, errors.New("More than one package in that directory")
	}

	var pkg *ast.Package

	for _, p := range pkgs {
		pkg = p
	}

	foundNewDelegate := false

	for _, file := range pkg.Files {
		for _, decl := range file.Decls {
			fun, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}

			if fun.Name.String() != "NewDelegate" {
				continue
			}

			//OK, it might be the function. Does it have the right signature?

			if fun.Recv != nil {
				return false, errors.New("NewDelegate had a receiver")
			}

			if fun.Type.Params.NumFields() > 0 {
				return false, errors.New("NewDelegate took more than 0 items")
			}

			if fun.Type.Results.NumFields() != 1 {
				return false, errors.New("NewDelegate didn't return exactly one item")
			}

			//TODO: check that the returned item implements
			//boardgame.GameDelegate.

			foundNewDelegate = true
			break

		}

		if foundNewDelegate {
			break
		}
	}

	if !foundNewDelegate {
		return false, errors.New("Couldn't find NewDelegate")
	}

	return true, nil
}
<commit_msg>Simple documentation for Import(). Part of #694.<commit_after>/*

	gamepkg is a package that helps locate, validate, and modify game package
	imports.

*/
package gamepkg

import (
	"errors"
	"github.com/jkomoros/boardgame/boardgame-util/lib/path"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
)

type GamePkg struct {
	//Every contstructo sets absolutePath to something that at least exists on
	//disk.
	absolutePath         string
	importPath           string
	calculatedIsGamePkg  bool
	memoizedIsGamePkg    bool
	memoizedIsGamePkgErr error
}

//New tries to interpret the input as an import. If that files, tries to
//interpret it as a path (rel or absolute), and if that fails, bails.
func New(importOrPath string) (*GamePkg, error) {
	pkg, err := NewFromImport(importOrPath)
	if err == nil {
		return pkg, nil
	}
	return NewFromPath(importOrPath)
}

//NewFromPath takes path (either relative or absolute path) and returns a new
//GamePkg. Will error if the given path does not appear to denote a valid game
//package for any reason.
func NewFromPath(path string) (*GamePkg, error) {

	if !filepath.IsAbs(path) {

		cwd, err := os.Getwd()

		if err != nil {
			return nil, errors.New("Couldn't get working directory: " + err.Error())
		}

		path = filepath.Join(cwd, path)
	}

	return newGamePkg(path, "")

}

//NewFromImport will return a new GamePkg pointing to that import. Will error
//if the given path does not appear to denote a valid game package for any
//reason.
func NewFromImport(importPath string) (*GamePkg, error) {

	absPath, err := path.AbsoluteGoPkgPath(importPath)

	if err != nil {
		return nil, errors.New("Absolute path couldn't be found: " + err.Error())
	}

	//If no error, then absPath must point to a valid thing

	return newGamePkg(absPath, importPath)

}

func newGamePkg(absPath, importPath string) (*GamePkg, error) {
	result := &GamePkg{
		absolutePath: absPath,
		importPath:   importPath,
	}

	if info, err := os.Stat(absPath); err != nil {
		return nil, errors.New("Path doesn't point to valid location on disk: " + err.Error())
	} else if !info.IsDir() {
		return nil, errors.New("Path points to an object but it's not a directory.")
	}

	if !result.goPkg() {
		return nil, errors.New(absPath + " denotes a folder with no go source files")
	}

	isGamePkg, err := result.isGamePkg()

	if !isGamePkg {
		return nil, errors.New(absPath + " was not a valid game package: " + err.Error())
	}

	return result, nil
}

//AbsolutePath returns the absolute path where the package in question resides
//on disk. All constructors will have errored if AbsolutePath doesn't at the
//very least point to a valid location on disk.
func (g *GamePkg) AbsolutePath() string {
	return g.absolutePath
}

//goPkg validates that the absolutePath denotes a package with at least one go
//file. If there's an error will default to false.
func (g *GamePkg) goPkg() bool {

	infos, _ := ioutil.ReadDir(g.AbsolutePath())

	for _, info := range infos {
		if filepath.Ext(info.Name()) == ".go" {
			return true
		}
	}

	return false

}

//Import returns the string that could be used in your source to import this
//package.
func (g *GamePkg) Import() (string, error) {
	//Calculate it if not already calculated (for example via NewFromImport constructor)
	if g.importPath == "" {

		goPkg, err := build.ImportDir(g.AbsolutePath(), 0)

		if err != nil {
			return "", errors.New("Couldn't read package: " + err.Error())
		}

		//TODO: factor this into a helper that also sets the package name in
		//case it's asked for later.
		g.importPath = goPkg.ImportPath
	}

	return g.importPath, nil
}

//isGamePkg verifies that the package appears to be a valid game package.
//Specifically it checks for
func (g *GamePkg) isGamePkg() (bool, error) {
	if !g.calculatedIsGamePkg {
		g.memoizedIsGamePkg, g.memoizedIsGamePkgErr = g.calculateIsGamePkg()
	}
	return g.memoizedIsGamePkg, g.memoizedIsGamePkgErr
}

func (g *GamePkg) calculateIsGamePkg() (bool, error) {
	pkgs, err := parser.ParseDir(token.NewFileSet(), g.AbsolutePath(), nil, 0)

	if err != nil {
		return false, errors.New("Couldn't parse folder: " + err.Error())
	}

	if len(pkgs) < 1 {
		return false, errors.New("No packages in that directory")
	}

	if len(pkgs) > 1 {
		return false, errors.New("More than one package in that directory")
	}

	var pkg *ast.Package

	for _, p := range pkgs {
		pkg = p
	}

	foundNewDelegate := false

	for _, file := range pkg.Files {
		for _, decl := range file.Decls {
			fun, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}

			if fun.Name.String() != "NewDelegate" {
				continue
			}

			//OK, it might be the function. Does it have the right signature?

			if fun.Recv != nil {
				return false, errors.New("NewDelegate had a receiver")
			}

			if fun.Type.Params.NumFields() > 0 {
				return false, errors.New("NewDelegate took more than 0 items")
			}

			if fun.Type.Results.NumFields() != 1 {
				return false, errors.New("NewDelegate didn't return exactly one item")
			}

			//TODO: check that the returned item implements
			//boardgame.GameDelegate.

			foundNewDelegate = true
			break

		}

		if foundNewDelegate {
			break
		}
	}

	if !foundNewDelegate {
		return false, errors.New("Couldn't find NewDelegate")
	}

	return true, nil
}
<|endoftext|>


<commit_before>package client

import (
	"github.com/gopherjs/jquery"
)

//NarrowDom is a narrow interface to accessing the DOM that can be
//simulated for test purposes.
type NarrowDom interface {
	SetData(string, string)
	Data(string) string
	RemoveData(string)
	Css(string) string
	SetCss(string, string)
	Text() string
	SetText(string)
	Attr(string) string
	SetAttr(string, string)
	Prop(string) bool
	SetProp(string, bool)
	On(EventName, EventFunc)
	HasClass(string) bool
	AddClass(string)
	RemoveClass(string)
	Val() string
	SetVal(string)
	Append(NarrowDom)
}

type jqueryWrapper struct {
	jq jquery.JQuery
}

func wrap(j jquery.JQuery) NarrowDom {
	return jqueryWrapper{j}
}

type testOpsImpl struct {
	data     map[string]string
	css      map[string]string
	text     string
	val      string
	attr     map[string]string
	prop     map[string]bool
	radio    map[string]string
	classes  map[string]int
	parent   *testOpsImpl //need the nil
	children []*testOpsImpl
}

func newTestOps() NarrowDom {
	result := testOpsImpl{
		data:    make(map[string]string),
		css:     make(map[string]string),
		attr:    make(map[string]string),
		prop:    make(map[string]bool),
		classes: make(map[string]int),
	}
	return &result
}

func (self *testOpsImpl) SetData(k string, v string) {
	self.data[k] = v
}

func (self jqueryWrapper) SetData(k string, v string) {
	self.jq.SetData(k, v)
}

func (self *testOpsImpl) RemoveData(k string) {
	delete(self.data, k)
}

func (self jqueryWrapper) RemoveData(k string) {
	self.jq.RemoveData(k)
}

func (self *testOpsImpl) Data(k string) string {
	return self.data[k]
}

func (self jqueryWrapper) Data(k string) string {
	i := self.jq.Data(k)
	if i == nil {
		return ""
	}
	return i.(string)
}

func (self *testOpsImpl) Css(k string) string {
	return self.css[k]
}
func (self jqueryWrapper) Css(k string) string {
	return self.jq.Css(k)
}

func (self *testOpsImpl) SetCss(k string, v string) {
	self.css[k] = v
}
func (self jqueryWrapper) SetCss(k string, v string) {
	self.jq.SetCss(k, v)
}

func (self *testOpsImpl) Text() string {
	return self.text
}

func (self jqueryWrapper) Text() string {
	return self.jq.Text()
}

func (self *testOpsImpl) SetText(v string) {
	self.text = v
}

func (self jqueryWrapper) SetText(v string) {
	self.jq.SetText(v)
}

func (self *testOpsImpl) Attr(k string) string {
	return self.attr[k]
}
func (self jqueryWrapper) Attr(k string) string {
	return self.jq.Attr(k)
}

func (self *testOpsImpl) SetAttr(k string, v string) {
	self.attr[k] = v
}
func (self jqueryWrapper) SetAttr(k string, v string) {
	self.jq.SetAttr(k, v)
}

func (self *testOpsImpl) Prop(k string) bool {
	return self.prop[k]
}
func (self jqueryWrapper) Prop(k string) bool {
	return self.jq.Prop(k).(bool)
}

func (self *testOpsImpl) SetProp(k string, v bool) {
	self.prop[k] = v
}
func (self jqueryWrapper) SetProp(k string, v bool) {
	self.jq.SetProp(k, v)
}

func (self *testOpsImpl) On(EventName, EventFunc) {
	panic("not implemented")
}

func (self jqueryWrapper) On(n EventName, fn EventFunc) {
	self.jq.On(n.String(), fn)
}

func (self *testOpsImpl) HasClass(k string) bool {
	_, ok := self.classes[k]
	return ok
}

func (self jqueryWrapper) HasClass(k string) bool {
	return self.jq.HasClass(k)
}

func (self *testOpsImpl) Val() string {
	return self.val
}

func (self jqueryWrapper) Val() string {
	v := self.jq.Val()
	return v
}

func (self *testOpsImpl) SetVal(s string) {
	self.val = s
}

func (self jqueryWrapper) SetVal(s string) {
	self.jq.SetVal(s)
}

func (self *testOpsImpl) AddClass(s string) {
	self.classes[s] = 0
}

func (self jqueryWrapper) AddClass(s string) {
	self.jq.AddClass(s)
}

func (self *testOpsImpl) RemoveClass(s string) {
	delete(self.classes, s)
}

func (self jqueryWrapper) RemoveClass(s string) {
	self.jq.RemoveClass(s)
}

func (self *testOpsImpl) Append(nd NarrowDom) {
	child := nd.(*testOpsImpl)
	if child.parent != nil {
		panic("can't add a child, it already has a parent!")
	}
	child.parent = self
	self.children = append(self.children, child)
}

func (self jqueryWrapper) Append(nd NarrowDom) {
	self.jq.Append(nd.(jqueryWrapper).jq)
}

func (self *testOpsImpl) SetRadioButton(groupName string, value string) {
	self.radio[groupName] = value
}

func (self *testOpsImpl) RadioButton(groupName string) string {
	return self.radio[groupName]
}

func (self jqueryWrapper) SetRadioButton(groupName string, value string) {
	selector := "input[name=\"" + groupName + "\"][type=\"radio\"]"
	print("selector is ", selector)
	jq := jquery.NewJQuery(selector)
	jq.SetVal(value)
}

func (self jqueryWrapper) RadioButton(groupName string) string {
	selector := "input[name=\"" + groupName + "\"][type=\"radio\"]" + ":checked"
	print("selector is ", selector)
	jq := jquery.NewJQuery(selector)
	return jq.Val()
}
<commit_msg>Added support for radiogroup.<commit_after>package client

import (
	"github.com/gopherjs/jquery"
)

//NarrowDom is a narrow interface to accessing the DOM that can be
//simulated for test purposes.
type NarrowDom interface {
	SetData(string, string)
	Data(string) string
	RemoveData(string)
	Css(string) string
	SetCss(string, string)
	Text() string
	SetText(string)
	Attr(string) string
	SetAttr(string, string)
	Prop(string) bool
	SetProp(string, bool)
	On(EventName, EventFunc)
	Trigger(EventName)
	HasClass(string) bool
	AddClass(string)
	RemoveClass(string)
	Val() string
	SetVal(string)
	Append(NarrowDom)
}

type jqueryWrapper struct {
	jq jquery.JQuery
}

func wrap(j jquery.JQuery) NarrowDom {
	return jqueryWrapper{j}
}

type testOpsImpl struct {
	data     map[string]string
	css      map[string]string
	text     string
	val      string
	attr     map[string]string
	prop     map[string]bool
	radio    map[string]string
	classes  map[string]int
	event    map[EventName]EventFunc
	parent   *testOpsImpl //need the nil
	children []*testOpsImpl
}

func newTestOps() NarrowDom {
	result := testOpsImpl{
		data:    make(map[string]string),
		css:     make(map[string]string),
		attr:    make(map[string]string),
		prop:    make(map[string]bool),
		classes: make(map[string]int),
		event : make(map[EventName]EventFunc),
	}
	return &result
}

func (self *testOpsImpl) SetData(k string, v string) {
	self.data[k] = v
}

func (self jqueryWrapper) SetData(k string, v string) {
	self.jq.SetData(k, v)
}

func (self *testOpsImpl) RemoveData(k string) {
	delete(self.data, k)
}

func (self jqueryWrapper) RemoveData(k string) {
	self.jq.RemoveData(k)
}

func (self *testOpsImpl) Data(k string) string {
	return self.data[k]
}

func (self jqueryWrapper) Data(k string) string {
	i := self.jq.Data(k)
	if i == nil {
		return ""
	}
	return i.(string)
}

func (self *testOpsImpl) Css(k string) string {
	return self.css[k]
}
func (self jqueryWrapper) Css(k string) string {
	return self.jq.Css(k)
}

func (self *testOpsImpl) SetCss(k string, v string) {
	self.css[k] = v
}
func (self jqueryWrapper) SetCss(k string, v string) {
	self.jq.SetCss(k, v)
}

func (self *testOpsImpl) Text() string {
	return self.text
}

func (self jqueryWrapper) Text() string {
	return self.jq.Text()
}

func (self *testOpsImpl) SetText(v string) {
	self.text = v
}

func (self jqueryWrapper) SetText(v string) {
	self.jq.SetText(v)
}

func (self *testOpsImpl) Attr(k string) string {
	return self.attr[k]
}
func (self jqueryWrapper) Attr(k string) string {
	return self.jq.Attr(k)
}

func (self *testOpsImpl) SetAttr(k string, v string) {
	self.attr[k] = v
}
func (self jqueryWrapper) SetAttr(k string, v string) {
	self.jq.SetAttr(k, v)
}

func (self *testOpsImpl) Prop(k string) bool {
	return self.prop[k]
}
func (self jqueryWrapper) Prop(k string) bool {
	return self.jq.Prop(k).(bool)
}

func (self *testOpsImpl) SetProp(k string, v bool) {
	self.prop[k] = v
}
func (self jqueryWrapper) SetProp(k string, v bool) {
	self.jq.SetProp(k, v)
}

func (self *testOpsImpl) On(name EventName, fn EventFunc) {
	self.event[name]=fn
}

func (self jqueryWrapper) On(n EventName, fn EventFunc) {
	self.jq.On(n.String(),fn)
}

func (self *testOpsImpl) Trigger(name EventName) {
	fn, ok:=self.event[name]
	if ok {
		fn(jquery.Event{Type:name.String()})
	}
}

func (self jqueryWrapper) Trigger(n EventName) {
	self.jq.Trigger(n)
}

func (self *testOpsImpl) HasClass(k string) bool {
	_, ok := self.classes[k]
	return ok
}

func (self jqueryWrapper) HasClass(k string) bool {
	return self.jq.HasClass(k)
}

func (self *testOpsImpl) Val() string {
	return self.val
}

func (self jqueryWrapper) Val() string {
	v := self.jq.Val()
	return v
}

func (self *testOpsImpl) SetVal(s string) {
	self.val = s
}

func (self jqueryWrapper) SetVal(s string) {
	self.jq.SetVal(s)
}

func (self *testOpsImpl) AddClass(s string) {
	self.classes[s] = 0
}

func (self jqueryWrapper) AddClass(s string) {
	self.jq.AddClass(s)
}

func (self *testOpsImpl) RemoveClass(s string) {
	delete(self.classes, s)
}

func (self jqueryWrapper) RemoveClass(s string) {
	self.jq.RemoveClass(s)
}

func (self *testOpsImpl) Append(nd NarrowDom) {
	child := nd.(*testOpsImpl)
	if child.parent != nil {
		panic("can't add a child, it already has a parent!")
	}
	child.parent = self
	self.children = append(self.children, child)
}

func (self jqueryWrapper) Append(nd NarrowDom) {
	self.jq.Append(nd.(jqueryWrapper).jq)
}

func (self *testOpsImpl) SetRadioButton(groupName string, value string) {
	self.radio[groupName] = value
}

func (self *testOpsImpl) RadioButton(groupName string) string {
	return self.radio[groupName]
}

func (self jqueryWrapper) SetRadioButton(groupName string, value string) {
	selector := "input[name=\"" + groupName + "\"][type=\"radio\"]"
	print("selector is ", selector)
	jq := jquery.NewJQuery(selector)
	jq.SetVal(value)
}

func (self jqueryWrapper) RadioButton(groupName string) string {
	selector := "input[name=\"" + groupName + "\"][type=\"radio\"]" + ":checked"
	print("selector is ", selector)
	jq := jquery.NewJQuery(selector)
	return jq.Val()
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"math/rand"
	"sync"
	"unsafe"

	"github.com/thinkofdeath/steven/render"
	"github.com/thinkofdeath/steven/render/builder"
	"github.com/thinkofdeath/steven/type/bit"
	"github.com/thinkofdeath/steven/type/direction"
)

type chunkVertex struct {
	X, Y, Z                    float32
	TX, TY, TW, TH             uint16
	TOffsetX, TOffsetY, TAtlas int16
	Pad0                       int16
	R, G, B                    byte
	Pad1                       byte
	BlockLight, SkyLight       uint16
	Pad2, Pad3                 uint16
}

type buildPos struct {
	X, Y, Z int
}

var (
	_, chunkVertexType = builder.Struct(chunkVertex{})
	builderPool        = sync.Pool{
		New: func() interface{} {
			return []chunkVertex(nil)
		},
	}
)

func (cs *chunkSection) build(complete chan<- buildPos) {
	ox, oy, oz := (cs.chunk.X<<4)-2, (cs.Y<<4)-2, (cs.chunk.Z<<4)-2
	bs := getPooledSnapshot(ox, oy, oz)
	// Make relative
	bs.x = -2
	bs.y = -2
	bs.z = -2
	go func() {
		bO := builderPool.Get().([]chunkVertex)[:0]
		bT := builderPool.Get().([]chunkVertex)[:0]
		bOI := new(int)
		bTI := new(int)

		r := rand.New(rand.NewSource(int64(cs.chunk.X) | (int64(cs.chunk.Z) << 32)))
		var tInfo []render.ObjectInfo

		for y := 0; y < 16; y++ {
			for x := 0; x < 16; x++ {
				for z := 0; z < 16; z++ {

					bl := bs.block(x, y, z)
					if !bl.Renderable() {
						// Use one step of the rng so that
						// if a block is placed in an empty
						// location is variant doesn't change
						r.Int()
						continue
					}
					bI := bOI
					// Translucent models need special handling
					if bl.IsTranslucent() {
						bI = bTI
					}
					offset := *bI

					// Liquids can't be represented by the model system
					// due to the number of possible states they have
					if l, ok := bl.(*blockLiquid); ok {
						if bl.IsTranslucent() {
							bT = l.renderLiquid(bs, x, y, z, bT, bI)
						} else {
							bO = l.renderLiquid(bs, x, y, z, bO, bI)
						}
						r.Int() // See the comment above for air
						count := *bI - offset
						if bl.IsTranslucent() && count > 0 {
							tInfo = append(tInfo, render.ObjectInfo{
								X:      (cs.chunk.X << 4) + x,
								Y:      (cs.Y << 4) + y,
								Z:      (cs.chunk.Z << 4) + z,
								Offset: offset,
								Count:  count,
							})
						}
						continue
					}

					// The index is used to select a 'random' variant which is
					// constant for that position.
					index := r.Intn(len(bl.Models()))

					if variant := bl.Models().selectModel(index); variant != nil {
						if bl.IsTranslucent() {
							bT = variant.Render(x, y, z, bs, bT, bI)
						} else {
							bO = variant.Render(x, y, z, bs, bO, bI)
						}
						count := *bI - offset
						if bl.IsTranslucent() && count > 0 {
							tInfo = append(tInfo, render.ObjectInfo{
								X:      (cs.chunk.X << 4) + x,
								Y:      (cs.Y << 4) + y,
								Z:      (cs.chunk.Z << 4) + z,
								Offset: offset,
								Count:  count,
							})
						}
					}
				}
			}
		}

		// Update culling information
		cullBits := buildCullBits(bs)
		snapshotPool.Put(bs)

		// Upload the buffers on the render goroutine
		render.Sync(func() {
			var data, dataT []byte
			if len(bO) > 0 {
				size := len(bO) * int(unsafe.Sizeof(bO[0]))
				data = (*[1 << 31]byte)(unsafe.Pointer(&bO[0]))[:size]
			}
			if len(bT) > 0 {
				size := len(bT) * int(unsafe.Sizeof(bT[0]))
				dataT = (*[1 << 31]byte)(unsafe.Pointer(&bT[0]))[:size]
			}
			cs.Buffer.Upload(data, *bOI, cullBits)
			cs.Buffer.UploadTrans(tInfo, dataT, *bTI)

			builderPool.Put(bO)
			builderPool.Put(bT)
		})
		// Free up the builder
		complete <- buildPos{cs.chunk.X, cs.Y, cs.chunk.Z}
	}()
}

func buildCullBits(bs *blocksSnapshot) uint64 {
	bits := uint64(0)
	set := func(from, to direction.Type) {
		bits |= 1 << (from*6 + to)
	}

	visited := bit.NewSet(16 * 16 * 16)
	// This tries a flood fill on every block in the chunk
	// section with an optimization of not visiting a block
	// that was visited in a previous fill (as it would already
	// be accounted for).
	for y := 0; y < 16; y++ {
		for z := 0; z < 16; z++ {
			for x := 0; x < 16; x++ {
				if visited.Get(x | (z << 4) | (y << 8)) {
					continue
				}
				touched := floodFill(bs, visited, x, y, z)
				// Minor optimization for a common case
				if touched == 0 {
					continue
				}
				// Mark each face in the set as visible through
				// each other
				for _, d := range direction.Values {
					if touched&(1<<d) != 0 {
						for _, d2 := range direction.Values {
							if touched&(1<<d2) != 0 {
								set(d, d2)
							}
						}
					}
				}
			}
		}
	}

	return bits
}

func floodFill(bs *blocksSnapshot, visited bit.Set, x, y, z int) uint8 {
	i := x | (z << 4) | (y << 8)
	// Make sure we aren't filling the same spot repeatedly or
	// going out of bounds.
	if x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15 || visited.Get(i) {
		return 0
	}
	visited.Set(i, true)

	// Can't fill into 'solid' spaces (ones that completely fill
	// the block)
	if bs.block(x, y, z).ShouldCullAgainst() {
		return 0
	}

	// bits are used to represent touched faces
	touched := uint8(0)
	if x == 0 {
		touched |= 1 << direction.West
	} else if x == 15 {
		touched |= 1 << direction.East
	}
	if y == 0 {
		touched |= 1 << direction.Down
	} else if y == 15 {
		touched |= 1 << direction.Up
	}
	if z == 0 {
		touched |= 1 << direction.North
	} else if z == 15 {
		touched |= 1 << direction.South
	}

	// Fill around us and add the touched faces to our
	// bits
	for _, d := range direction.Values {
		ox, oy, oz := d.Offset()
		touched |= floodFill(bs, visited, x+ox, y+oy, z+oz)
	}

	return touched
}

// builder.Struct works by reflection which is to slow for this
// as its called so often.
func buildVertex(b *builder.Buffer, v chunkVertex) {
	b.Float(v.X)
	b.Float(v.Y)
	b.Float(v.Z)
	b.UnsignedShort(v.TX)
	b.UnsignedShort(v.TY)
	b.UnsignedShort(v.TW)
	b.UnsignedShort(v.TH)
	b.Short(v.TOffsetX)
	b.Short(v.TOffsetY)
	b.Short(v.TAtlas)
	b.Short(0)
	b.UnsignedByte(v.R)
	b.UnsignedByte(v.G)
	b.UnsignedByte(v.B)
	b.UnsignedByte(255)
	b.UnsignedShort(v.BlockLight)
	b.UnsignedShort(v.SkyLight)
	b.UnsignedShort(0)
	b.UnsignedShort(0)
}
<commit_msg>steven: reduce the array size for go 1.4<commit_after>// Copyright 2015 Matthew Collins
//
// 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 steven

import (
	"math/rand"
	"sync"
	"unsafe"

	"github.com/thinkofdeath/steven/render"
	"github.com/thinkofdeath/steven/render/builder"
	"github.com/thinkofdeath/steven/type/bit"
	"github.com/thinkofdeath/steven/type/direction"
)

type chunkVertex struct {
	X, Y, Z                    float32
	TX, TY, TW, TH             uint16
	TOffsetX, TOffsetY, TAtlas int16
	Pad0                       int16
	R, G, B                    byte
	Pad1                       byte
	BlockLight, SkyLight       uint16
	Pad2, Pad3                 uint16
}

type buildPos struct {
	X, Y, Z int
}

var (
	_, chunkVertexType = builder.Struct(chunkVertex{})
	builderPool        = sync.Pool{
		New: func() interface{} {
			return []chunkVertex(nil)
		},
	}
)

func (cs *chunkSection) build(complete chan<- buildPos) {
	ox, oy, oz := (cs.chunk.X<<4)-2, (cs.Y<<4)-2, (cs.chunk.Z<<4)-2
	bs := getPooledSnapshot(ox, oy, oz)
	// Make relative
	bs.x = -2
	bs.y = -2
	bs.z = -2
	go func() {
		bO := builderPool.Get().([]chunkVertex)[:0]
		bT := builderPool.Get().([]chunkVertex)[:0]
		bOI := new(int)
		bTI := new(int)

		r := rand.New(rand.NewSource(int64(cs.chunk.X) | (int64(cs.chunk.Z) << 32)))
		var tInfo []render.ObjectInfo

		for y := 0; y < 16; y++ {
			for x := 0; x < 16; x++ {
				for z := 0; z < 16; z++ {

					bl := bs.block(x, y, z)
					if !bl.Renderable() {
						// Use one step of the rng so that
						// if a block is placed in an empty
						// location is variant doesn't change
						r.Int()
						continue
					}
					bI := bOI
					// Translucent models need special handling
					if bl.IsTranslucent() {
						bI = bTI
					}
					offset := *bI

					// Liquids can't be represented by the model system
					// due to the number of possible states they have
					if l, ok := bl.(*blockLiquid); ok {
						if bl.IsTranslucent() {
							bT = l.renderLiquid(bs, x, y, z, bT, bI)
						} else {
							bO = l.renderLiquid(bs, x, y, z, bO, bI)
						}
						r.Int() // See the comment above for air
						count := *bI - offset
						if bl.IsTranslucent() && count > 0 {
							tInfo = append(tInfo, render.ObjectInfo{
								X:      (cs.chunk.X << 4) + x,
								Y:      (cs.Y << 4) + y,
								Z:      (cs.chunk.Z << 4) + z,
								Offset: offset,
								Count:  count,
							})
						}
						continue
					}

					// The index is used to select a 'random' variant which is
					// constant for that position.
					index := r.Intn(len(bl.Models()))

					if variant := bl.Models().selectModel(index); variant != nil {
						if bl.IsTranslucent() {
							bT = variant.Render(x, y, z, bs, bT, bI)
						} else {
							bO = variant.Render(x, y, z, bs, bO, bI)
						}
						count := *bI - offset
						if bl.IsTranslucent() && count > 0 {
							tInfo = append(tInfo, render.ObjectInfo{
								X:      (cs.chunk.X << 4) + x,
								Y:      (cs.Y << 4) + y,
								Z:      (cs.chunk.Z << 4) + z,
								Offset: offset,
								Count:  count,
							})
						}
					}
				}
			}
		}

		// Update culling information
		cullBits := buildCullBits(bs)
		snapshotPool.Put(bs)

		// Upload the buffers on the render goroutine
		render.Sync(func() {
			var data, dataT []byte
			if len(bO) > 0 {
				size := len(bO) * int(unsafe.Sizeof(bO[0]))
				data = (*[1 << 28]byte)(unsafe.Pointer(&bO[0]))[:size]
			}
			if len(bT) > 0 {
				size := len(bT) * int(unsafe.Sizeof(bT[0]))
				dataT = (*[1 << 28]byte)(unsafe.Pointer(&bT[0]))[:size]
			}
			cs.Buffer.Upload(data, *bOI, cullBits)
			cs.Buffer.UploadTrans(tInfo, dataT, *bTI)

			builderPool.Put(bO)
			builderPool.Put(bT)
		})
		// Free up the builder
		complete <- buildPos{cs.chunk.X, cs.Y, cs.chunk.Z}
	}()
}

func buildCullBits(bs *blocksSnapshot) uint64 {
	bits := uint64(0)
	set := func(from, to direction.Type) {
		bits |= 1 << (from*6 + to)
	}

	visited := bit.NewSet(16 * 16 * 16)
	// This tries a flood fill on every block in the chunk
	// section with an optimization of not visiting a block
	// that was visited in a previous fill (as it would already
	// be accounted for).
	for y := 0; y < 16; y++ {
		for z := 0; z < 16; z++ {
			for x := 0; x < 16; x++ {
				if visited.Get(x | (z << 4) | (y << 8)) {
					continue
				}
				touched := floodFill(bs, visited, x, y, z)
				// Minor optimization for a common case
				if touched == 0 {
					continue
				}
				// Mark each face in the set as visible through
				// each other
				for _, d := range direction.Values {
					if touched&(1<<d) != 0 {
						for _, d2 := range direction.Values {
							if touched&(1<<d2) != 0 {
								set(d, d2)
							}
						}
					}
				}
			}
		}
	}

	return bits
}

func floodFill(bs *blocksSnapshot, visited bit.Set, x, y, z int) uint8 {
	i := x | (z << 4) | (y << 8)
	// Make sure we aren't filling the same spot repeatedly or
	// going out of bounds.
	if x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15 || visited.Get(i) {
		return 0
	}
	visited.Set(i, true)

	// Can't fill into 'solid' spaces (ones that completely fill
	// the block)
	if bs.block(x, y, z).ShouldCullAgainst() {
		return 0
	}

	// bits are used to represent touched faces
	touched := uint8(0)
	if x == 0 {
		touched |= 1 << direction.West
	} else if x == 15 {
		touched |= 1 << direction.East
	}
	if y == 0 {
		touched |= 1 << direction.Down
	} else if y == 15 {
		touched |= 1 << direction.Up
	}
	if z == 0 {
		touched |= 1 << direction.North
	} else if z == 15 {
		touched |= 1 << direction.South
	}

	// Fill around us and add the touched faces to our
	// bits
	for _, d := range direction.Values {
		ox, oy, oz := d.Offset()
		touched |= floodFill(bs, visited, x+ox, y+oy, z+oz)
	}

	return touched
}

// builder.Struct works by reflection which is to slow for this
// as its called so often.
func buildVertex(b *builder.Buffer, v chunkVertex) {
	b.Float(v.X)
	b.Float(v.Y)
	b.Float(v.Z)
	b.UnsignedShort(v.TX)
	b.UnsignedShort(v.TY)
	b.UnsignedShort(v.TW)
	b.UnsignedShort(v.TH)
	b.Short(v.TOffsetX)
	b.Short(v.TOffsetY)
	b.Short(v.TAtlas)
	b.Short(0)
	b.UnsignedByte(v.R)
	b.UnsignedByte(v.G)
	b.UnsignedByte(v.B)
	b.UnsignedByte(255)
	b.UnsignedShort(v.BlockLight)
	b.UnsignedShort(v.SkyLight)
	b.UnsignedShort(0)
	b.UnsignedShort(0)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/ChimeraCoder/anaconda"
	"github.com/gorilla/mux"
	"github.com/rs/cors"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

//	Tweet holds everything about a single news item
type Tweet struct {
	Id         int64  `json:"id"`
	CreateTime int64  `json:"createtime"`
	Text       string `json:text`
	MediaUrl   string `json:url`
}

func main() {
	//	Set up our flags
	port := flag.Int("port", 3000, "The port to listen on")
	allowedOrigins := flag.String("allowedOrigins", "*", "A comma-separated list of valid CORS origins")
	consumerKey := flag.String("consumerKey", "", "Your twitter consumer key")
	consumerSecret := flag.String("consumerSecret", "", "Your twitter consumer secret")
	authToken := flag.String("authToken", "", "Your twitter auth token")
	authSecret := flag.String("authSecret", "", "Your twitter auth secret")

	//	Parse the command line for flags:
	flag.Parse()

	//	Create twitter api client:
	anaconda.SetConsumerKey(*consumerKey)
	anaconda.SetConsumerSecret(*consumerSecret)
	api := anaconda.NewTwitterApi(*authToken, *authSecret)

	r := mux.NewRouter()
	r.HandleFunc("/news/{twitterName}", func(w http.ResponseWriter, r *http.Request) {

		//	Parse the twitter name from the url
		twitterName := mux.Vars(r)["twitterName"]

		//	Our return values:
		tweets := []Tweet{}

		//	Set some url values:
		v := url.Values{}
		v.Set("screen_name", twitterName)
		v.Set("exclude_replies", "1")
		v.Set("include_rts", "false")
		v.Set("count", "50")

		timeline, _ := api.GetUserTimeline(v)

		//	Get the tweets with media (photos) and return them
		for _, tweet := range timeline {
			for _, media := range tweet.Entities.Media {

				//	If we found one with media, write out the
				//	tweet and the media and break out of the
				//	outer range loop
				tweetedTime, err := tweet.CreatedAtTime()

				if err == nil {
					tweets = append(tweets, Tweet{
						Id:         tweet.Id,
						CreateTime: tweetedTime.Unix(),
						Text:       tweet.Text,
						MediaUrl:   media.Media_url})
				}
			}
		}

		//	Set the content type header and return the JSON
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(tweets)
	})

	//	CORS handler
	c := cors.New(cors.Options{
		AllowedOrigins:   strings.Split(*allowedOrigins, ","),
		AllowCredentials: true,
	})
	handler := c.Handler(r)

	//	Indicate what port we're starting the service on
	portString := strconv.Itoa(*port)
	fmt.Println("Allowed origins: ", *allowedOrigins)
	fmt.Println("Starting server on :", portString)
	http.ListenAndServe(":"+portString, handler)
}
<commit_msg>Added environment config options<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/ChimeraCoder/anaconda"
	"github.com/gorilla/mux"
	"github.com/rs/cors"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
)

//	Tweet holds everything about a single news item
type Tweet struct {
	Id         int64  `json:"id"`
	CreateTime int64  `json:"createtime"`
	Text       string `json:text`
	MediaUrl   string `json:url`
}

//	Set up our flags
var (
	port           = flag.Int("port", 3000, "The port to listen on")
	allowedOrigins = flag.String("allowedOrigins", "*", "A comma-separated list of valid CORS origins")
	consumerKey    = flag.String("consumerKey", "", "Your twitter consumer key")
	consumerSecret = flag.String("consumerSecret", "", "Your twitter consumer secret")
	authToken      = flag.String("authToken", "", "Your twitter auth token")
	authSecret     = flag.String("authSecret", "", "Your twitter auth secret")
)

func parseEnvironment() {
	//	Check for the listen port
	if env_port := os.Getenv("TWITTER_PORT"); env_port != "" {
		*port, _ = strconv.Atoi(env_port)
	}

	//	Check for allowed origins
	if env_origins := os.Getenv("TWITTER_ALLOWED_ORIGINS"); env_origins != "" {
		*allowedOrigins = env_origins
	}

	//	Check for consumer key
	if env_consumer_key := os.Getenv("TWITTER_CONSUMER_KEY"); env_consumer_key != "" {
		*consumerKey = env_consumer_key
	}

	//	Check for consumer secret
	if env_consumer_secret := os.Getenv("TWITTER_CONSUMER_SECRET"); env_consumer_secret != "" {
		*consumerSecret = env_consumer_secret
	}

	//	Check for auth token
	if env_auth_token := os.Getenv("TWITTER_AUTH_TOKEN"); env_auth_token != "" {
		*authToken = env_auth_token
	}

	//	Check for auth secret
	if env_auth_secret := os.Getenv("TWITTER_AUTH_SECRET"); env_auth_secret != "" {
		*authSecret = env_auth_secret
	}
}

func main() {

	//	Parse environment variables:
	parseEnvironment()

	//	Parse the command line for flags:
	flag.Parse()

	//	Create twitter api client:
	anaconda.SetConsumerKey(*consumerKey)
	anaconda.SetConsumerSecret(*consumerSecret)
	api := anaconda.NewTwitterApi(*authToken, *authSecret)

	r := mux.NewRouter()
	r.HandleFunc("/news/{twitterName}", func(w http.ResponseWriter, r *http.Request) {

		//	Parse the twitter name from the url
		twitterName := mux.Vars(r)["twitterName"]

		//	Our return values:
		tweets := []Tweet{}

		//	Set some url values:
		v := url.Values{}
		v.Set("screen_name", twitterName)
		v.Set("exclude_replies", "1")
		v.Set("include_rts", "false")
		v.Set("count", "50")

		timeline, _ := api.GetUserTimeline(v)

		//	Get the tweets with media (photos) and return them
		for _, tweet := range timeline {
			for _, media := range tweet.Entities.Media {

				//	If we found one with media, write out the
				//	tweet and the media and break out of the
				//	outer range loop
				tweetedTime, err := tweet.CreatedAtTime()

				if err == nil {
					tweets = append(tweets, Tweet{
						Id:         tweet.Id,
						CreateTime: tweetedTime.Unix(),
						Text:       tweet.Text,
						MediaUrl:   media.Media_url})
				}
			}
		}

		//	Set the content type header and return the JSON
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(tweets)
	})

	//	CORS handler
	c := cors.New(cors.Options{
		AllowedOrigins:   strings.Split(*allowedOrigins, ","),
		AllowCredentials: true,
	})
	handler := c.Handler(r)

	//	Indicate what port we're starting the service on
	portString := strconv.Itoa(*port)
	fmt.Println("Allowed origins: ", *allowedOrigins)
	fmt.Println("Starting server on :", portString)
	http.ListenAndServe(":"+portString, handler)
}
<|endoftext|>


<commit_before>// Copyright 2014 The Mangos Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 tlstcp implements the TLS over TCP transport for mangos.
package tlstcp

import (
	"github.com/gdamore/mangos"
	"crypto/tls"
	"net"
)

type tlsDialer struct {
	addr   *net.TCPAddr
	config *tls.Config
	proto  uint16
}

func (d *tlsDialer) Dial() (mangos.Pipe, error) {

	tconn, err := net.DialTCP("tcp", nil, d.addr)
	if err != nil {
		return nil, err
	}
	conn := tls.Client(tconn, d.config)
	return mangos.NewConnPipe(conn, d.proto)
}

type tlsAccepter struct {
	addr     *net.TCPAddr
	proto    uint16
	listener net.Listener
}

func (a *tlsAccepter) Accept() (mangos.Pipe, error) {

	conn, err := a.listener.Accept()
	if err != nil {
		return nil, err
	}

	return mangos.NewConnPipe(conn, a.proto)
}

func (a *tlsAccepter) Close() error {
	a.listener.Close()
	return nil
}

type tlsTran struct {
	config *tls.Config
}

func (t *tlsTran) Scheme() string {
	return "tls+tcp"
}

func (t *tlsTran) NewDialer(addr string, proto uint16) (mangos.PipeDialer, error) {
	var err error
	d := &tlsDialer{}
	d.proto = proto
	d.config = t.config
	if d.addr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, err
	}
	return d, nil
}

// NewAccepter implements the Transport NewAccepter method.
func (t *tlsTran) NewAccepter(addr string, proto uint16) (mangos.PipeAccepter, error) {
	var err error
	a := &tlsAccepter{}
	a.proto = proto

	if a.addr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, err
	}

	var tlistener net.Listener
	if tlistener, err = net.ListenTCP("tcp", a.addr); err != nil {
		return nil, err
	}
	a.listener = tls.NewListener(tlistener, t.config)

	return a, nil
}

// SetOption implements the Transport SetOption method. We support a single
// option, TLSOptionConfig, which takes a single value, a *tls.Config.
// Note that we force the use of TLS1.2, as other versions have known
// weaknesses, and we have no compatibility concerns.
func (t *tlsTran) SetOption(name string, val interface{}) error {
	switch name {
	case mangos.OptionTLSConfig:
		switch v := val.(type) {
		case *tls.Config:
			// Force TLS 1.2, others have weaknesses
			v.MinVersion = tls.VersionTLS12;
			v.MaxVersion = tls.VersionTLS12;
			t.config = v
			return nil
		default:
			return mangos.ErrBadValue
		}
	default:
		return mangos.ErrBadOption
	}
}

// SetOption implements the Transport SetOption method. We support a single
// option, TLSOptionConfig, which takes a single value, a *tls.Config.
func (t *tlsTran) GetOption(name string) (interface{}, error) {
	switch name {
	case mangos.OptionTLSConfig:
		return t.config, nil
	default:
		return nil, mangos.ErrBadOption
	}
}

// NewTransport allocates a new inproc transport.
func NewTransport() mangos.Transport {
	return &tlsTran{}
}
<commit_msg>Implement OptionLocalAddress option for tlstcp transport<commit_after>// Copyright 2014 The Mangos Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 tlstcp implements the TLS over TCP transport for mangos.
package tlstcp

import (
	"crypto/tls"
	"net"

	"github.com/gdamore/mangos"
)

type tlsDialer struct {
	addr   *net.TCPAddr
	config *tls.Config
	proto  uint16
}

func (d *tlsDialer) Dial() (mangos.Pipe, error) {

	tconn, err := net.DialTCP("tcp", nil, d.addr)
	if err != nil {
		return nil, err
	}
	conn := tls.Client(tconn, d.config)
	return mangos.NewConnPipe(conn, d.proto)
}

type tlsAccepter struct {
	addr     *net.TCPAddr
	proto    uint16
	listener net.Listener
}

func (a *tlsAccepter) Accept() (mangos.Pipe, error) {

	conn, err := a.listener.Accept()
	if err != nil {
		return nil, err
	}

	return mangos.NewConnPipe(conn, a.proto)
}

func (a *tlsAccepter) Close() error {
	a.listener.Close()
	return nil
}

type tlsTran struct {
	config    *tls.Config
	localAddr net.Addr
}

func (t *tlsTran) Scheme() string {
	return "tls+tcp"
}

func (t *tlsTran) NewDialer(addr string, proto uint16) (mangos.PipeDialer, error) {
	var err error
	d := &tlsDialer{}
	d.proto = proto
	d.config = t.config
	if d.addr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, err
	}
	return d, nil
}

// NewAccepter implements the Transport NewAccepter method.
func (t *tlsTran) NewAccepter(addr string, proto uint16) (mangos.PipeAccepter, error) {
	var err error
	a := &tlsAccepter{}
	a.proto = proto

	if a.addr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
		return nil, err
	}

	var tlistener net.Listener
	if tlistener, err = net.ListenTCP("tcp", a.addr); err != nil {
		return nil, err
	}
	a.listener = tls.NewListener(tlistener, t.config)
	t.localAddr = tlistener.Addr()

	return a, nil
}

// SetOption implements the Transport SetOption method. We support a single
// option, OptionTLSConfig, which takes a single value, a *tls.Config.
// Note that we force the use of TLS1.2, as other versions have known
// weaknesses, and we have no compatibility concerns.
func (t *tlsTran) SetOption(name string, val interface{}) error {
	switch name {
	case mangos.OptionTLSConfig:
		switch v := val.(type) {
		case *tls.Config:
			// Force TLS 1.2, others have weaknesses
			v.MinVersion = tls.VersionTLS12
			v.MaxVersion = tls.VersionTLS12
			t.config = v
			return nil
		default:
			return mangos.ErrBadValue
		}
	default:
		return mangos.ErrBadOption
	}
}

// GetOption implements the Transport GetOption method. We support two options,
// OptionTLSConfig, which is a *tls.Config, and OptionLocalAddress, which is a
// string.
func (t *tlsTran) GetOption(name string) (interface{}, error) {
	switch name {
	case mangos.OptionTLSConfig:
		return t.config, nil
	case mangos.OptionLocalAddress:
		if t.localAddr == nil {
			return nil, mangos.ErrBadOption
		}
		return t.localAddr.String(), nil
	default:
		return nil, mangos.ErrBadOption
	}
}

// NewTransport allocates a new inproc transport.
func NewTransport() mangos.Transport {
	return &tlsTran{}
}
<|endoftext|>


<commit_before>package chronos

import (
	"container/heap"
	"fmt"
	"github.com/squioc/axis"
	"testing"
	"time"
)

/****************************************
*                                       *
*                 Tests                 *
*                                       *
****************************************/

func expect(t *testing.T, expected Item, actual Entry, stopChan chan bool) {
	if actual == nil {
		stopChan <- true
		t.Fatalf("The actual element wasn't expected to be nil")
	}
	if actual.(*Item).Value != expected.Value {
		stopChan <- true
		t.Fatalf("The actual element wasn't the expected one. actual=%v expected=%v", actual.(*Item), expected)
	}
}

func waitUntil(t *testing.T, workerChan chan Entry, timeout time.Duration) Entry {
	select {
	case value := <-workerChan:
		return value
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
	return nil
}

func TestRunWithJobsInOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in order should send in order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstValue := <-workerChan
	expect(t, *firstEntry, firstValue, stopChan)
	secondValue := <-workerChan
	expect(t, *secondEntry, secondValue, stopChan)
	stopChan <- true
}

func TestRunWithJobsInReverseOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in reverse order should send in reverse order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(500),
		Value:    "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstValue := <-workerChan
	expect(t, *secondEntry, firstValue, stopChan)
	secondValue := <-workerChan
	expect(t, *firstEntry, secondValue, stopChan)
	stopChan <- true
}

func TestRunWithStop(t *testing.T) {
	fmt.Println("Test Run with Stop should exit")
	// Arrange
	position := axis.Position(0)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "First",
	}

	// Act
	exitChan := make(chan bool, 1)
	// go routine to check that we leave the Run method when we send a booleen on stopChan
	go func(exitChan chan bool) {
		chronos.Run(pushChan, workerChan, stopChan)
		// sends boolean on the channel when the Run method exits
		exitChan <- true
	}(exitChan)
	// stops the goroutine
	stopChan <- true
	// sends an entry to the goroutine
	pushChan <- firstEntry

	// Assert
	select {
	case <-exitChan:
		// PASS
		return
	case <-workerChan:
		// FAIL, we expected to exit, not to receive an item
		t.Fatalf("Expected exit, not item")
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
}

func TestRunWithJobsIn2Sets(t *testing.T) {
	fmt.Println("Test Run with jobs in 2 sets")
	// Arrange
	position := axis.Position(0)
	intermediatePosition := axis.Position(1500)
	terminalPosition := axis.Position(3000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "Second",
	}
	thirdEntry := &Item{
		Priority: axis.Position(2000),
		Value:    "Third",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// pushes the first set (firstEntry, secondEntry
	pushChan <- firstEntry
	pushChan <- secondEntry
	// lets the goroutine starts then updates the position
	time.Sleep(5 * time.Millisecond)
	provider.Update(intermediatePosition)
	time.Sleep(5 * time.Millisecond)
	// pushes the second set (thridEntry)
	pushChan <- thirdEntry
	time.Sleep(5 * time.Millisecond)
	provider.Update(terminalPosition)

	// Assert
	firstValue := <-workerChan
	expect(t, *firstEntry, firstValue, stopChan)
	secondValue := <-workerChan
	expect(t, *secondEntry, secondValue, stopChan)
	thirdValue := <-workerChan
	expect(t, *thirdEntry, thirdValue, stopChan)
	stopChan <- true
}

func TestRunWithJobInPast(t *testing.T) {
	fmt.Println("Test Run with a job in a past position")
	// Arrange
	position := axis.Position(1000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: 500,
		Value:    "First",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// pushes the item
	pushChan <- firstEntry

	// Assert
	firstValue := <-workerChan
	expect(t, *firstEntry, firstValue, stopChan)
	stopChan <- true
}

func TestRunWithANonEmptyQueue(t *testing.T) {
	fmt.Println("Test Run with a non empty queue should pop until the next delay")
	// Arrange
	position := axis.Position(1000)
	newPosition := axis.Position(2000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	firstEntry := &Item{
		Priority: axis.Position(1500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(500),
		Value:    "Second",
	}
	heap.Push(pq, secondEntry)
	heap.Push(pq, firstEntry)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// Should return the first Entry immediately
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	expect(t, *secondEntry, firstValue, stopChan)
	secondValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, secondValue, stopChan)
	stopChan <- true
}
<commit_msg>Replace channel fetching with the WaitUntil function<commit_after>package chronos

import (
	"container/heap"
	"fmt"
	"github.com/squioc/axis"
	"testing"
	"time"
)

/****************************************
*                                       *
*                 Tests                 *
*                                       *
****************************************/

func expect(t *testing.T, expected Item, actual Entry, stopChan chan bool) {
	if actual == nil {
		stopChan <- true
		t.Fatalf("The actual element wasn't expected to be nil")
	}
	if actual.(*Item).Value != expected.Value {
		stopChan <- true
		t.Fatalf("The actual element wasn't the expected one. actual=%v expected=%v", actual.(*Item), expected)
	}
}

func waitUntil(t *testing.T, workerChan chan Entry, timeout time.Duration) Entry {
	select {
	case value := <-workerChan:
		return value
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
	return nil
}

func TestRunWithJobsInOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in order should send in order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, firstValue, stopChan)
	secondValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *secondEntry, secondValue, stopChan)
	stopChan <- true
}

func TestRunWithJobsInReverseOrder(t *testing.T) {
	fmt.Println("Test Run with jobs in reverse order should send in reverse order")
	// Arrange
	position := axis.Position(0)
	newPosition := axis.Position(1500)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(500),
		Value:    "Second",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	pushChan <- firstEntry
	pushChan <- secondEntry
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *secondEntry, firstValue, stopChan)
	secondValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, secondValue, stopChan)
	stopChan <- true
}

func TestRunWithStop(t *testing.T) {
	fmt.Println("Test Run with Stop should exit")
	// Arrange
	position := axis.Position(0)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "First",
	}

	// Act
	exitChan := make(chan bool, 1)
	// go routine to check that we leave the Run method when we send a booleen on stopChan
	go func(exitChan chan bool) {
		chronos.Run(pushChan, workerChan, stopChan)
		// sends boolean on the channel when the Run method exits
		exitChan <- true
	}(exitChan)
	// stops the goroutine
	stopChan <- true
	// sends an entry to the goroutine
	pushChan <- firstEntry

	// Assert
	select {
	case <-exitChan:
		// PASS
		return
	case <-workerChan:
		// FAIL, we expected to exit, not to receive an item
		t.Fatalf("Expected exit, not item")
	case <-time.After(2 * time.Second):
		// FAIL, timeout
		t.Fatalf("Timeout. the test exceed the expected duration")
	}
}

func TestRunWithJobsIn2Sets(t *testing.T) {
	fmt.Println("Test Run with jobs in 2 sets")
	// Arrange
	position := axis.Position(0)
	intermediatePosition := axis.Position(1500)
	terminalPosition := axis.Position(3000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: axis.Position(500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(1000),
		Value:    "Second",
	}
	thirdEntry := &Item{
		Priority: axis.Position(2000),
		Value:    "Third",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// pushes the first set (firstEntry, secondEntry
	pushChan <- firstEntry
	pushChan <- secondEntry
	// lets the goroutine starts then updates the position
	time.Sleep(5 * time.Millisecond)
	provider.Update(intermediatePosition)
	time.Sleep(5 * time.Millisecond)
	// pushes the second set (thridEntry)
	pushChan <- thirdEntry
	time.Sleep(5 * time.Millisecond)
	provider.Update(terminalPosition)

	// Assert
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, firstValue, stopChan)
	secondValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *secondEntry, secondValue, stopChan)
	thirdValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *thirdEntry, thirdValue, stopChan)
	stopChan <- true
}

func TestRunWithJobInPast(t *testing.T) {
	fmt.Println("Test Run with a job in a past position")
	// Arrange
	position := axis.Position(1000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)
	firstEntry := &Item{
		Priority: 500,
		Value:    "First",
	}

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// pushes the item
	pushChan <- firstEntry

	// Assert
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, firstValue, stopChan)
	stopChan <- true
}

func TestRunWithANonEmptyQueue(t *testing.T) {
	fmt.Println("Test Run with a non empty queue should pop until the next delay")
	// Arrange
	position := axis.Position(1000)
	newPosition := axis.Position(2000)
	provider := axis.NewFakeTime(position)
	pq := new(PriorityQueue)
	firstEntry := &Item{
		Priority: axis.Position(1500),
		Value:    "First",
	}
	secondEntry := &Item{
		Priority: axis.Position(500),
		Value:    "Second",
	}
	heap.Push(pq, secondEntry)
	heap.Push(pq, firstEntry)
	chronos := NewChronos(provider, pq)
	pushChan := make(chan Entry, 2)
	workerChan := make(chan Entry, 2)
	stopChan := make(chan bool, 1)

	// Act
	go chronos.Run(pushChan, workerChan, stopChan)
	// Should return the first Entry immediately
	firstValue := waitUntil(t, workerChan, 2*time.Second)
	// Updates the position
	go provider.Update(newPosition)

	// Assert
	expect(t, *secondEntry, firstValue, stopChan)
	secondValue := waitUntil(t, workerChan, 2*time.Second)
	expect(t, *firstEntry, secondValue, stopChan)
	stopChan <- true
}
<|endoftext|>


<commit_before>package syslogs

import (
	"fmt"
	"strconv"
	"time"

	"github.com/TIBCOSoftware/flogo-lib/core/action"
	"github.com/TIBCOSoftware/flogo-lib/core/trigger"
	"github.com/TIBCOSoftware/flogo-lib/logger"
	"github.com/davecgh/go-spew/spew"
	syslog "gopkg.in/mcuadros/go-syslog.v2"
	"gopkg.in/mcuadros/go-syslog.v2/format"
)

// log is the default package logger
var log = logger.GetLogger("trigger-syslogs")

// MyTriggerFactory My Syslogs Trigger factory
type MyTriggerFactory struct {
	metadata *trigger.Metadata
}

//NewFactory create a new Trigger factory
func NewFactory(md *trigger.Metadata) trigger.Factory {
	return &MyTriggerFactory{metadata: md}
}

// New -> Creates a new trigger instance for a given id
func (t *MyTriggerFactory) New(config *trigger.Config) trigger.Trigger {
	return &MyTrigger{metadata: t.metadata, config: config}
}

// MyTrigger is a stub for your Trigger implementation
type MyTrigger struct {
	metadata *trigger.Metadata
	runner   action.Runner
	config   *trigger.Config
	server   *syslog.Server
}

// Init implements trigger.Trigger.Init
func (t *MyTrigger) Init(runner action.Runner) {
	t.runner = runner
}

// Metadata implements trigger.Trigger.Metadata
func (t *MyTrigger) Metadata() *trigger.Metadata {
	return t.metadata
}

// Start implements trigger.Trigger.Start
func (t *MyTrigger) Start() error {
	// start the trigger

	if t.config.Settings == nil {
		panic(fmt.Sprintf("No Settings found for trigger '%s'", t.config.Id))
	}

	port := "514"

	if _, ok := t.config.Settings["port"]; !ok {
		log.Infof("No Port found for syslogs trigger '%s' in settings. Using default 514", t.config.Id)
	} else {
		port = t.config.GetSetting("port")
	}

	udp := true
	if _, ok := t.config.Settings["UDP"]; ok {
		udpConfig, err := strconv.ParseBool(t.config.GetSetting("UDP"))
		if err != nil {
			log.Warnf("Value set for UDP '%s' is not a boolean. Using default 'true'. Trigger '%s'",
				t.config.GetSetting("UDP"),
				t.config.Id)
		} else {
			udp = udpConfig
		}
	}
	tcp := false
	if _, ok := t.config.Settings["TCP"]; ok {
		tcpConfig, err := strconv.ParseBool(t.config.GetSetting("TCP"))
		if err != nil {
			log.Warnf("Value set for TCP '%s' is not a boolean. Using default 'false'. Trigger '%s'",
				t.config.GetSetting("TCP"),
				t.config.Id)
		} else {
			tcp = tcpConfig
		}
	}

	if !udp && !tcp {
		panic(fmt.Sprintf("At least one of UDP or TCP needs to be enabled for trigger '%s'", t.config.Id))
	}

	server := syslog.NewServer()
	server.SetFormat(syslog.Automatic)

	for _, handlerCfg := range t.config.Handlers {
		handler := new(MySyslogHandler)
		handler.t = t
		handler.ActionID = handlerCfg.ActionId
		handler.handlerCfg = handlerCfg
		server.SetHandler(handler)
	}

	if udp {
		server.ListenUDP("0.0.0.0:" + port)
	}
	if tcp {
		server.ListenTCP("0.0.0.0:" + port)
	}

	server.Boot()

	t.server = server
	server.Wait()
	return nil
}

// Stop implements trigger.Trigger.Start
func (t *MyTrigger) Stop() error {
	// stop the trigger
	t.server.Kill()
	return nil
}

// MySyslogHandler : My trigger's syslogs handler
type MySyslogHandler struct {
	t          *MyTrigger
	ActionID   string
	handlerCfg *trigger.HandlerConfig
}

// Handle : processing of each received syslogs
func (s *MySyslogHandler) Handle(logParts format.LogParts, msgLen int64, err error) {

	if err != nil {
		log.Errorf("Syslogs Handler for ActionID [%s] received error [%s]", s.ActionID, err)
	}

	//TODO how to handle reply to, reply feature
	req := &StartRequest{}
	data := make(map[string]interface{})
	for key, value := range logParts {
		if key != "timestamp" {
			data[key] = value
		} else {
			ts, ok := value.(time.Time)
			if ok {
				data[key] = ts.Format(time.RFC3339)
			}
		}
	}
	req.Data = data

	md := s.t.Metadata()
	startAttrs, errorAttrs := md.OutputsToAttrs(req.Data, false)
	/*
		for _, attr := range startAttrs {
			spew.Dump(&attr)
		}
	*/
	if errorAttrs != nil || startAttrs == nil {
		log.Errorf("Failed to create output attributes for syslogs message for ActionID [%s] for reason [%s] message lost", s.ActionID, errorAttrs)
	}

	ctx := trigger.NewInitialContext(startAttrs, s.handlerCfg)

	spew.Dump(action.Actions())
	action := action.Get(s.ActionID)
	fmt.Println(s.ActionID)

	_, errRun := s.t.runner.RunAction(ctx, action, nil)

	if errRun != nil {
		log.Errorf("Failed to process syslogs message for ActionID [%s] for reason [%s] message lost", s.ActionID, errRun)
	}
}

// StartRequest describes a request for starting a ProcessInstance
type StartRequest struct {
	ProcessURI string                 `json:"flowUri"`
	Data       map[string]interface{} `json:"data"`
	ReplyTo    string                 `json:"replyTo"`
}
<commit_msg>Added logging<commit_after>package syslogs

import (
	"fmt"
	"strconv"
	"time"

	"github.com/TIBCOSoftware/flogo-lib/core/action"
	"github.com/TIBCOSoftware/flogo-lib/core/trigger"
	"github.com/TIBCOSoftware/flogo-lib/logger"
	syslog "gopkg.in/mcuadros/go-syslog.v2"
	"gopkg.in/mcuadros/go-syslog.v2/format"
)

// log is the default package logger
var log = logger.GetLogger("trigger-syslogs")

// MyTriggerFactory My Syslogs Trigger factory
type MyTriggerFactory struct {
	metadata *trigger.Metadata
}

//NewFactory create a new Trigger factory
func NewFactory(md *trigger.Metadata) trigger.Factory {
	return &MyTriggerFactory{metadata: md}
}

// New -> Creates a new trigger instance for a given id
func (t *MyTriggerFactory) New(config *trigger.Config) trigger.Trigger {
	return &MyTrigger{metadata: t.metadata, config: config}
}

// MyTrigger is a stub for your Trigger implementation
type MyTrigger struct {
	metadata *trigger.Metadata
	runner   action.Runner
	config   *trigger.Config
	server   *syslog.Server
}

// Init implements trigger.Trigger.Init
func (t *MyTrigger) Init(runner action.Runner) {
	t.runner = runner
}

// Metadata implements trigger.Trigger.Metadata
func (t *MyTrigger) Metadata() *trigger.Metadata {
	return t.metadata
}

// Start implements trigger.Trigger.Start
func (t *MyTrigger) Start() error {
	// start the trigger

	if t.config.Settings == nil {
		panic(fmt.Sprintf("No Settings found for trigger '%s'", t.config.Id))
	}

	port := "514"

	if _, ok := t.config.Settings["port"]; !ok {
		log.Infof("No Port found for syslogs trigger '%s' in settings. Using default 514", t.config.Id)
	} else {
		port = t.config.GetSetting("port")
	}

	udp := true
	if _, ok := t.config.Settings["UDP"]; ok {
		udpConfig, err := strconv.ParseBool(t.config.GetSetting("UDP"))
		if err != nil {
			log.Warnf("Value set for UDP '%s' is not a boolean. Using default 'true'. Trigger '%s'",
				t.config.GetSetting("UDP"),
				t.config.Id)
		} else {
			udp = udpConfig
		}
	}
	tcp := false
	if _, ok := t.config.Settings["TCP"]; ok {
		tcpConfig, err := strconv.ParseBool(t.config.GetSetting("TCP"))
		if err != nil {
			log.Warnf("Value set for TCP '%s' is not a boolean. Using default 'false'. Trigger '%s'",
				t.config.GetSetting("TCP"),
				t.config.Id)
		} else {
			tcp = tcpConfig
		}
	}

	if !udp && !tcp {
		panic(fmt.Sprintf("At least one of UDP or TCP needs to be enabled for trigger '%s'", t.config.Id))
	}

	server := syslog.NewServer()
	server.SetFormat(syslog.Automatic)

	for _, handlerCfg := range t.config.Handlers {
		handler := new(MySyslogHandler)
		handler.t = t
		handler.ActionID = handlerCfg.ActionId
		handler.handlerCfg = handlerCfg
		server.SetHandler(handler)
	}

	if udp {
		server.ListenUDP("0.0.0.0:" + port)
	}
	if tcp {
		server.ListenTCP("0.0.0.0:" + port)
	}

	server.Boot()

	t.server = server
	server.Wait()
	return nil
}

// Stop implements trigger.Trigger.Start
func (t *MyTrigger) Stop() error {
	// stop the trigger
	t.server.Kill()
	return nil
}

// MySyslogHandler : My trigger's syslogs handler
type MySyslogHandler struct {
	t          *MyTrigger
	ActionID   string
	handlerCfg *trigger.HandlerConfig
}

// Handle : processing of each received syslogs
func (s *MySyslogHandler) Handle(logParts format.LogParts, msgLen int64, err error) {

	if err != nil {
		log.Errorf("Syslogs Handler for ActionID [%s] received error [%s]", s.ActionID, err)
	}

	log.Debug("New syslogs message received")
	//TODO how to handle reply to, reply feature
	req := &StartRequest{}
	data := make(map[string]interface{})
	for key, value := range logParts {
		if key != "timestamp" {
			data[key] = value
		} else {
			ts, ok := value.(time.Time)
			if ok {
				data[key] = ts.Format(time.RFC3339)
			}
		}
		log.Debugf("Syslogs Message Field [%s] -> Value [%v]", key, data[key])
	}
	req.Data = data

	md := s.t.Metadata()
	startAttrs, errorAttrs := md.OutputsToAttrs(req.Data, false)

	if errorAttrs != nil || startAttrs == nil {
		log.Errorf("Failed to create output attributes for syslogs message for ActionID [%s] for reason [%s] message lost", s.ActionID, errorAttrs)
	}

	ctx := trigger.NewInitialContext(startAttrs, s.handlerCfg)

	action := action.Get(s.ActionID)

	_, errRun := s.t.runner.RunAction(ctx, action, nil)

	if errRun != nil {
		log.Errorf("Failed to process syslogs message for ActionID [%s] for reason [%s] message lost", s.ActionID, errRun)
	} else {
		log.Debugf("Syslogs Trigger Started Action [%s]", s.ActionID)
	}
}

// StartRequest describes a request for starting a ProcessInstance
type StartRequest struct {
	ProcessURI string                 `json:"flowUri"`
	Data       map[string]interface{} `json:"data"`
	ReplyTo    string                 `json:"replyTo"`
}
<|endoftext|>


<commit_before>package writer

import (
	"sync"
)

const bufferSize = 1024 * 8

type InsertBatch struct {
	Table string
	Rows  [][]interface{}
}

type InsertElement struct {
	Table string
	Row   []interface{}
}

type InsertBuffer struct {
	In  chan InsertElement
	Out chan InsertBatch
	wg  *sync.WaitGroup
}

func NewInsertBuffer() *InsertBuffer {
	ib := InsertBuffer{
		In:  make(chan InsertElement, 256),
		Out: make(chan InsertBatch, 8),
		wg:  &sync.WaitGroup{},
	}
	ib.wg.Add(1)
	go ib.loop()
	return &ib
}

func (ib *InsertBuffer) Close() {
	close(ib.In)
	ib.wg.Wait()
	close(ib.Out)
}

func (ib *InsertBuffer) Insert(table string, row []interface{}) {
	ib.In <- InsertElement{table, row}
}

func (ib *InsertBuffer) loop() {
	buffer := make(map[string]*InsertBatch)

	for elem := range ib.In {
		if batch, ok := buffer[elem.Table]; ok {
			batch.Rows = append(batch.Rows, elem.Row)
		} else {
			buffer[elem.Table] = &InsertBatch{elem.Table, [][]interface{}{elem.Row}}
		}
		if len(buffer[elem.Table].Rows) > bufferSize {
			batch := buffer[elem.Table]
			delete(buffer, elem.Table)
			ib.Out <- *batch
		}
	}
	for table, batch := range buffer {
		delete(buffer, table)
		ib.Out <- *batch
	}
	ib.wg.Done()
}
<commit_msg>reduce buffer sizes<commit_after>package writer

import (
	"sync"
)

const bufferSize = 1024 * 8

type InsertBatch struct {
	Table string
	Rows  [][]interface{}
}

type InsertElement struct {
	Table string
	Row   []interface{}
}

type InsertBuffer struct {
	In  chan InsertElement
	Out chan InsertBatch
	wg  *sync.WaitGroup
}

func NewInsertBuffer() *InsertBuffer {
	ib := InsertBuffer{
		In:  make(chan InsertElement, 64),
		Out: make(chan InsertBatch, 1),
		wg:  &sync.WaitGroup{},
	}
	ib.wg.Add(1)
	go ib.loop()
	return &ib
}

func (ib *InsertBuffer) Close() {
	close(ib.In)
	ib.wg.Wait()
	close(ib.Out)
}

func (ib *InsertBuffer) Insert(table string, row []interface{}) {
	ib.In <- InsertElement{table, row}
}

func (ib *InsertBuffer) loop() {
	buffer := make(map[string]*InsertBatch)

	for elem := range ib.In {
		if batch, ok := buffer[elem.Table]; ok {
			batch.Rows = append(batch.Rows, elem.Row)
		} else {
			buffer[elem.Table] = &InsertBatch{elem.Table, [][]interface{}{elem.Row}}
		}
		if len(buffer[elem.Table].Rows) > bufferSize {
			batch := buffer[elem.Table]
			delete(buffer, elem.Table)
			ib.Out <- *batch
		}
	}
	for table, batch := range buffer {
		delete(buffer, table)
		ib.Out <- *batch
	}
	ib.wg.Done()
}
<|endoftext|>


<commit_before>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package cookie

import (
	"net/http"
	"time"
)

// Cookie names.
const (
	CookieSessionID     = "sessionID"
	CookieUserSessionID = "userSessionID"
)

// New create a new cookie.
func New(name, value string, isHTTPS bool) *http.Cookie {
	return &http.Cookie{
		Name:     name,
		Value:    value,
		Path:     "/",
		Secure:   isHTTPS,
		HttpOnly: true,
	}
}

// Expired returns an expired cookie.
func Expired(name string, isHTTPS bool) *http.Cookie {
	return &http.Cookie{
		Name:     name,
		Value:    "",
		Path:     "/",
		Secure:   isHTTPS,
		HttpOnly: true,
		MaxAge:   -1,
		Expires:  time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
	}
}
<commit_msg>Increase session cookies expiration<commit_after>// Copyright 2017 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package cookie

import (
	"net/http"
	"time"
)

// Cookie names.
const (
	CookieSessionID     = "sessionID"
	CookieUserSessionID = "userSessionID"

	// Cookie duration in days.
	cookieDuration = 30
)

// New creates a new cookie.
func New(name, value string, isHTTPS bool) *http.Cookie {
	return &http.Cookie{
		Name:     name,
		Value:    value,
		Path:     "/",
		Secure:   isHTTPS,
		HttpOnly: true,
		Expires:  time.Now().Add(cookieDuration * 24 * time.Hour),
	}
}

// Expired returns an expired cookie.
func Expired(name string, isHTTPS bool) *http.Cookie {
	return &http.Cookie{
		Name:     name,
		Value:    "",
		Path:     "/",
		Secure:   isHTTPS,
		HttpOnly: true,
		MaxAge:   -1,
		Expires:  time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
	}
}
<|endoftext|>


<commit_before>package golog

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

type GoLogger struct {
	Mutex         sync.Mutex
	InfoLogger    *log.Logger
	WarningLogger *log.Logger
	ErrorLogger   *log.Logger
	FatalLogger   *log.Logger
	DebugLogger   *log.Logger
}

func getStack(all bool) []string {
	buf := make([]byte, 1<<8)
	for {
		n := runtime.Stack(buf, all)
		if n < len(buf) {
			break
		}
		buf = make([]byte, len(buf)*2)
	}
	return strings.Split(string(buf), "\n")
}

func NewGoLogger(output *os.File) *GoLogger {
	logger := new(GoLogger)

	logger.InfoLogger = log.New(output, "[ INFO  ]", log.LstdFlags)
	logger.WarningLogger = log.New(output, "[WARNING]", log.LstdFlags)
	logger.ErrorLogger = log.New(output, "[ ERROR ]", log.LstdFlags)
	logger.FatalLogger = log.New(output, "[ FATAL ]", log.LstdFlags)
	logger.DebugLogger = log.New(output, "[ DEBUG ]", log.LstdFlags)

	return logger
}

func (l *GoLogger) Infoln(v ...interface{}) {
	l.Mutex.Lock()
	l.InfoLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Infof(format string, v ...interface{}) {
	l.Infoln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) Warningln(v ...interface{}) {
	l.Mutex.Lock()
	l.WarningLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Warningf(format string, v ...interface{}) {
	l.Warningln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) errorln(v ...interface{}) {
	_, file, line, _ := runtime.Caller(2)
	caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
	v = append([]interface{}{caller}, v...)
	l.Mutex.Lock()
	l.ErrorLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Errorln(v ...interface{}) {
	l.errorln(v...)
}

func (l *GoLogger) Errorf(format string, v ...interface{}) {
	l.errorln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) Fatalln(v ...interface{}) {
	l.Mutex.Lock()
	l.FatalLogger.Println(v...)
	for _, v := range getStack(false) {
		l.FatalLogger.Println(v)
	}
	l.Mutex.Unlock()
	os.Exit(1)
}

func (l *GoLogger) Fatalf(format string, v ...interface{}) {
	l.Fatalln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) debugln(v ...interface{}) {
	_, file, line, _ := runtime.Caller(2)
	caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
	v = append([]interface{}{caller}, v...)
	l.Mutex.Lock()
	l.DebugLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Debugln(debug bool, v ...interface{}) {
	if !debug {
		return
	}
	l.debugln(v...)
}

func (l *GoLogger) Debugf(debug bool, format string, v ...interface{}) {
	if !debug {
		return
	}
	l.debugln(fmt.Sprintf(format, v...))
}
<commit_msg>Change NewGoLogger to New<commit_after>package golog

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

type GoLogger struct {
	Mutex         sync.Mutex
	InfoLogger    *log.Logger
	WarningLogger *log.Logger
	ErrorLogger   *log.Logger
	FatalLogger   *log.Logger
	DebugLogger   *log.Logger
}

func getStack(all bool) []string {
	buf := make([]byte, 1<<8)
	for {
		n := runtime.Stack(buf, all)
		if n < len(buf) {
			break
		}
		buf = make([]byte, len(buf)*2)
	}
	return strings.Split(string(buf), "\n")
}

func New(output *os.File) *GoLogger {
	logger := new(GoLogger)

	logger.InfoLogger = log.New(output, "[ INFO  ]", log.LstdFlags)
	logger.WarningLogger = log.New(output, "[WARNING]", log.LstdFlags)
	logger.ErrorLogger = log.New(output, "[ ERROR ]", log.LstdFlags)
	logger.FatalLogger = log.New(output, "[ FATAL ]", log.LstdFlags)
	logger.DebugLogger = log.New(output, "[ DEBUG ]", log.LstdFlags)

	return logger
}

func (l *GoLogger) Infoln(v ...interface{}) {
	l.Mutex.Lock()
	l.InfoLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Infof(format string, v ...interface{}) {
	l.Infoln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) Warningln(v ...interface{}) {
	l.Mutex.Lock()
	l.WarningLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Warningf(format string, v ...interface{}) {
	l.Warningln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) errorln(v ...interface{}) {
	_, file, line, _ := runtime.Caller(2)
	caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
	v = append([]interface{}{caller}, v...)
	l.Mutex.Lock()
	l.ErrorLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Errorln(v ...interface{}) {
	l.errorln(v...)
}

func (l *GoLogger) Errorf(format string, v ...interface{}) {
	l.errorln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) Fatalln(v ...interface{}) {
	l.Mutex.Lock()
	l.FatalLogger.Println(v...)
	for _, v := range getStack(false) {
		l.FatalLogger.Println(v)
	}
	l.Mutex.Unlock()
	os.Exit(1)
}

func (l *GoLogger) Fatalf(format string, v ...interface{}) {
	l.Fatalln(fmt.Sprintf(format, v...))
}

func (l *GoLogger) debugln(v ...interface{}) {
	_, file, line, _ := runtime.Caller(2)
	caller := fmt.Sprintf("%s:%d", filepath.Base(file), line)
	v = append([]interface{}{caller}, v...)
	l.Mutex.Lock()
	l.DebugLogger.Println(v...)
	l.Mutex.Unlock()
}

func (l *GoLogger) Debugln(debug bool, v ...interface{}) {
	if !debug {
		return
	}
	l.debugln(v...)
}

func (l *GoLogger) Debugf(debug bool, format string, v ...interface{}) {
	if !debug {
		return
	}
	l.debugln(fmt.Sprintf(format, v...))
}
<|endoftext|>


<commit_before>package golog

import (
	"os"
)

const (
	INFO = iota
	WARNING
	ERROR
	FATAL
)

var Global LevelLogger = DefaultLevelLogger

func exitNow() {
	os.Exit(1)
}

func Info(vals ...interface{}) {
	Global.Log(INFO, vals...)
}

func Infof(f string, args ...interface{}) {
	Global.Logf(INFO, f, args...)
}

func Infoc(closure func() string) {
	Global.Logc(INFO, closure)
}

func Warning(vals ...interface{}) {
	Global.Log(WARNING, vals...)
}

func Warningf(f string, args ...interface{}) {
	Global.Logf(WARNING, f, args...)
}

func Warningc(closure func() string) {
	Global.Logc(WARNING, closure)
}

func Error(vals ...interface{}) {
	Global.Log(ERROR, vals...)
}

func Errorf(f string, args ...interface{}) {
	Global.Logf(ERROR, f, args...)
}

func Errorc(closure func() string) {
	Global.Logc(ERROR, closure)
}

func Fatal(vals ...interface{}) {
	Global.Log(FATAL, vals...)
	exitNow()
}

func Fatalf(f string, args ...interface{}) {
	Global.Logf(FATAL, f, args...)
	exitNow()
}

func Fatalc(closure func() string) {
	Global.Logc(FATAL, closure)
	exitNow()
}

func StartTestLogging(t TestController) {
	defaultLogOuters.AddLogOuter("testing", NewTestLogOuter(t))
	// TODO Replace exitNow
}

func StopTestLogging() {
	defaultLogOuters.RemoveLogOuter("testing")
	// TODO Replace exitNow
}
<commit_msg>Replace failNow for logger<commit_after>package golog

import (
	"os"
)

const (
	INFO = iota
	WARNING
	ERROR
	FATAL
)

var Global LevelLogger = DefaultLevelLogger

func exitNow() {
	os.Exit(1)
}

func Info(vals ...interface{}) {
	Global.Log(INFO, vals...)
}

func Infof(f string, args ...interface{}) {
	Global.Logf(INFO, f, args...)
}

func Infoc(closure func() string) {
	Global.Logc(INFO, closure)
}

func Warning(vals ...interface{}) {
	Global.Log(WARNING, vals...)
}

func Warningf(f string, args ...interface{}) {
	Global.Logf(WARNING, f, args...)
}

func Warningc(closure func() string) {
	Global.Logc(WARNING, closure)
}

func Error(vals ...interface{}) {
	Global.Log(ERROR, vals...)
}

func Errorf(f string, args ...interface{}) {
	Global.Logf(ERROR, f, args...)
}

func Errorc(closure func() string) {
	Global.Logc(ERROR, closure)
}

func Fatal(vals ...interface{}) {
	Global.Log(FATAL, vals...)
	exitNow()
}

func Fatalf(f string, args ...interface{}) {
	Global.Logf(FATAL, f, args...)
	exitNow()
}

func Fatalc(closure func() string) {
	Global.Logc(FATAL, closure)
	exitNow()
}

func StartTestLogging(t TestController) {
	defaultLogOuters.AddLogOuter("testing", NewTestLogOuter(t))
	DefaultLogger.(*loggerImpl).failFunc = func () { t.FailNow() }
}

func StopTestLogging() {
	defaultLogOuters.RemoveLogOuter("testing")
	DefaultLogger.(*loggerImpl).failFunc = exitNow
}
<|endoftext|>