<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"
	"time"

	"github.com/cortesi/modd"
	"github.com/cortesi/termlog"
	"gopkg.in/alecthomas/kingpin.v2"
)

const lullTime = time.Millisecond * 300

func main() {
	paths := kingpin.Arg(
		"path",
		"Paths to monitor for changes.",
	).Required().Strings()

	beep := kingpin.Flag("beep", "Beep if any command returned an error").
		Short('b').
		Bool()

	nocommon := kingpin.Flag("nocommon", "Don't exclude commonly ignored files").
		Short('c').
		Bool()

	daemons := kingpin.Flag("daemon", "Daemon to keep running").
		PlaceHolder("CMD").
		Short('d').
		Strings()

	prep := kingpin.Flag("prep", "Prep command to run before daemons are restarted").
		PlaceHolder("CMD").
		Short('p').
		Strings()

	cmdstats := kingpin.Flag("cmdstats", "Show stats on command execution").
		Short('s').
		Default("false").
		Bool()

	excludes := kingpin.Flag("exclude", "Glob pattern for files to exclude from monitoring").
		PlaceHolder("PATTERN").
		Short('x').
		Strings()

	debug := kingpin.Flag("debug", "Debugging for devd development").
		Default("false").
		Bool()

	kingpin.Version(modd.Version)
	kingpin.Parse()
	log := termlog.NewLog()
	log.Notice("modd v%s", modd.Version)

	if *debug {
		log.Enable("debug")
		modd.Logger = log
	}
	if *cmdstats {
		log.Enable("cmdstats")
	}

	modchan := make(chan modd.Mod)
	exc := *excludes
	if !*nocommon {
		exc = append(*excludes, modd.CommonExcludes...)
	}
	err := modd.Watch(*paths, exc, lullTime, modchan)
	if err != nil {
		kingpin.Fatalf("Fatal error: %s", err)
	}
	err = modd.RunProcs(*prep, log)
	if err != nil {
		if *beep {
			fmt.Print("\a")
		}
	}
	d := modd.DaemonPen{}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	go func() {
		d.Shutdown(<-c)
		os.Exit(0)
	}()
	d.Start(*daemons, log)
	for mod := range modchan {
		log.SayAs("debug", "Delta: \n%s", mod.String())
		err := modd.RunProcs(*prep, log)
		if err != nil {
			if *beep {
				fmt.Print("\a")
			}
			continue
		}
		d.Restart()
	}
}
<commit_msg>We don't need to print the version on startup<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"
	"time"

	"github.com/cortesi/modd"
	"github.com/cortesi/termlog"
	"gopkg.in/alecthomas/kingpin.v2"
)

const lullTime = time.Millisecond * 300

func main() {
	paths := kingpin.Arg(
		"path",
		"Paths to monitor for changes.",
	).Required().Strings()

	beep := kingpin.Flag("beep", "Beep if any command returned an error").
		Short('b').
		Bool()

	nocommon := kingpin.Flag("nocommon", "Don't exclude commonly ignored files").
		Short('c').
		Bool()

	daemons := kingpin.Flag("daemon", "Daemon to keep running").
		PlaceHolder("CMD").
		Short('d').
		Strings()

	prep := kingpin.Flag("prep", "Prep command to run before daemons are restarted").
		PlaceHolder("CMD").
		Short('p').
		Strings()

	cmdstats := kingpin.Flag("cmdstats", "Show stats on command execution").
		Short('s').
		Default("false").
		Bool()

	excludes := kingpin.Flag("exclude", "Glob pattern for files to exclude from monitoring").
		PlaceHolder("PATTERN").
		Short('x').
		Strings()

	debug := kingpin.Flag("debug", "Debugging for devd development").
		Default("false").
		Bool()

	kingpin.Version(modd.Version)
	kingpin.Parse()
	log := termlog.NewLog()

	if *debug {
		log.Enable("debug")
		modd.Logger = log
	}
	if *cmdstats {
		log.Enable("cmdstats")
	}

	modchan := make(chan modd.Mod)
	exc := *excludes
	if !*nocommon {
		exc = append(*excludes, modd.CommonExcludes...)
	}
	err := modd.Watch(*paths, exc, lullTime, modchan)
	if err != nil {
		kingpin.Fatalf("Fatal error: %s", err)
	}
	err = modd.RunProcs(*prep, log)
	if err != nil {
		if *beep {
			fmt.Print("\a")
		}
	}
	d := modd.DaemonPen{}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	go func() {
		d.Shutdown(<-c)
		os.Exit(0)
	}()
	d.Start(*daemons, log)
	for mod := range modchan {
		log.SayAs("debug", "Delta: \n%s", mod.String())
		err := modd.RunProcs(*prep, log)
		if err != nil {
			if *beep {
				fmt.Print("\a")
			}
			continue
		}
		d.Restart()
	}
}
<|endoftext|>


<commit_before>/*
Command line utility for the Moon configuration language.

Purpose

The moon utility (moon) is a command line tool for working with moon files.  It
can be used to read values from moon files, evaluate moon files to remove
variables, convert moon files to json where possible, and verify that a given
moon file is syntactically valid.

The following is taken to be the contents of a file named ex.moon:

  # the whole document is implicitly a namespace, so you can set key value pairs
  # at the top level.
  first_name: "jordan"
  last_name: "orelli"

  # lists of things should be supported
  items: [
      "one"
      2
      3.4
      ["five" 6 7.8]
  ]

  # objects should be supported
  hash: {key: "value" other_key: "other_value"}

  other_hash: {
      key_1: "one"
      key_2: 2
      key_3: 3.4
      key_4: ["five" 6 7.8]
  }

  # we may reference an item that was defined earlier
  repeat_hash: hash

  # items can be hidden.  i.e., they're only valid in the parse and eval stage as
  # intermediate values internal to the config file; they are *not* visible to
  # the host program.  This is generally useful for composing larger, more
  # complicated things.
  .hidden_item: "it has a value"

  visible_item: .hidden_item

  .person_one: {
      name: "the first name here"
      age: 28
      hometown: "crooklyn"
  }

  .person_two: {
      name: "the second name here"
      age: 30
      hometown: "tha bronx"
  }

  people: [.person_one .person_two]

Subcommands

check:  used to syntax check a given file.  To check a given file, in this case ex.moon, to see if it is syntactically valid, one would invoke the following command:

  moon check ex.moon

If the file is syntactically valid, moon will print nothing and exit with a
status of 0.  If the file is invalid, moon will print a cryptic error message
that won't help you fix the file and exit with a status of 1.

eval:  evaluates a given moon file.  The file is parsed and evaluated, and its result is printed on stdout, itself in the moon format.  Invoking the following command:

  moon eval ex.moon

would produce the following output:

  first_name: "jordan"
  items: ["one" 2 3.4 ["five" 6 7.8]]
  other_hash: {key_3: 3.4 key_4: ["five" 6 7.8] key_1: "one" key_2: 2}
  repeat_hash: {key: "value" other_key: "other_value"}
  people: [{age: 28 hometown: "crooklyn" name: "the first name here"} {hometown: "tha bronx" name: "the second name here" age: 30}]
  last_name: "orelli"
  hash: {key: "value" other_key: "other_value"}
  visible_item: "it has a value"

to:  used to convert moon files to other formats.  Right now, the only
supported format is json.  To convert a given moon file to json, one would invoke the following command:

  moon to json ex.moon

If the file is valid and can be converted to json (i.e., only involves types
that are also supported by json or readily convertible to json types), the
file's json representation will be printed on stdout.

The "to" subcommand can also take its input from stdin by omitting a file name, as in one of the following invocations:

  cat ex.moon | moon to json
  moon to json < ex.moon

Either invocation would have the same effect.

get:  evaluates a moon file and retrieves a value, printing it on stdout out.
The file is parsed and evaluated, meaning that get will fail if executed
against an invalid moon file; this is a search on an evaluated moon document,
not a textual search.  The general format of invocation is as follows:

  moon get $search_term $file

Where $search_term refers to a key or a path, and $file refers to the name of a
file to be searched.  Given the moon file ex.moon:

  > moon get first_name ex.moon
  "jordan"

  > moon get visible_item ex.moon
  "it has a value"

  > moon get people ex.moon
  [{hometown: "crooklyn" name: "the first name here" age: 28} {name: "the second name here" age: 30 hometown: "tha bronx"}]

The search term may involve a path, allowing one to reach into an Object or List and retrieve individual items:

  > moon get hash/other_key ex.moon
  "other_value"

  > moon get people/1/name ex.moon
  "the second name here"

*/
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/jordanorelli/moon/lib"
	"io"
	"os"
)

func input(n int) io.ReadCloser {
	if flag.Arg(n) == "" {
		return os.Stdin
	} else {
		f, err := os.Open(flag.Arg(n))
		if err != nil {
			bail(1, "input error: %s", err)
		}
		return f
	}
}

func check() {
	r := input(1)
	defer r.Close()

	_, err := moon.Read(r)
	if err != nil {
		bail(1, "parse error: %s", err)
	}
}

func to() {
	switch flag.Arg(1) {
	case "json":
		to_json(2)
	default:
		fmt.Fprintf(os.Stderr, "%s is not a valid output format\n", flag.Arg(1))
		fmt.Fprintln(os.Stderr, "valid output formats: json")
		os.Exit(1)
	}
}

func to_json(n int) {
	in := input(n)
	defer in.Close()
	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	b, err := json.MarshalIndent(doc, "", "    ")
	if err != nil {
		bail(1, "encode error: %s", err)
	}
	os.Stdout.Write(b)
}

func get() {
	docpath := flag.Arg(1)
	in := input(2)
	defer in.Close()

	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	var v interface{}
	if err := doc.Get(docpath, &v); err != nil {
		bail(1, "error reading value at path %s: %s", docpath, err)
	}
	b, err := moon.Encode(v)
	if err != nil {
		bail(1, "error encoding value: %s", err)
	}
	os.Stdout.Write(b)
}

func eval() {
	in := input(1)
	defer in.Close()

	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	b, err := moon.Encode(doc)
	if err != nil {
		bail(1, "output error: %s", err)
	}
	os.Stdout.Write(b)
}

func bail(status int, t string, args ...interface{}) {
	var w io.Writer
	if status == 0 {
		w = os.Stdout
	} else {
		w = os.Stderr
	}
	fmt.Fprintf(w, t+"\n", args...)
	os.Exit(status)
}

func main() {
	flag.Parse()
	switch flag.Arg(0) {
	case "check":
		check()
	case "to":
		to()
	case "get":
		get()
	case "eval":
		eval()
	case "":
		bail(1, "must specify an action.\nvalid actions: check to get eval")
	default:
		bail(1, "no such action:%s", flag.Arg(0))
	}
}
<commit_msg>add documentation info<commit_after>/*
Command line utility for the Moon configuration language.

Purpose

The moon utility (moon) is a command line tool for working with moon files.  It
can be used to read values from moon files, evaluate moon files to remove
variables, convert moon files to json where possible, and verify that a given
moon file is syntactically valid.

The following is taken to be the contents of a file named ex.moon:

  # ------------------------------------------------------------------------------
  # example config format
  #
  # this is a working draft of things that are valid in a new config language to
  # replace json as a config language for Go projects.
  #
  # comments are a thing now!
  # ------------------------------------------------------------------------------

  # the whole document is implicitly a namespace, so you can set key value pairs
  # at the top level.
  first_name: jordan
  last_name: orelli

  # lists of things should be supported
  items: [
      one
      2
      3.4
      [five; 6 7.8]
  ]

  # objects should be supported
  hash: {key: value; other_key: other_value}

  other_hash: {
      key_1: one
      key_2: 2
      key_3: 3.4
      key_4: [five; 6 7.8]
  }

  # we may reference an item that was defined earlier using a sigil
  repeat_hash: @hash

  # items can be hidden.  i.e., they're only valid in the parse and eval stage as
  # intermediate values internal to the config file; they are *not* visible to
  # the host program.  This is generally useful for composing larger, more
  # complicated things.
  @hidden_item: it has a value
  visible_item: @hidden_item

  @person_one: {
      name: the first name here
      age: 28
      hometown: crooklyn
  }

  @person_two: {
      name: the second name here
      age: 30
      hometown: tha bronx
  }

  people: [@person_one @person_two]

Subcommands

check:  used to syntax check a given file.  To check a given file, in this case ex.moon, to see if it is syntactically valid, one would invoke the following command:

  moon check ex.moon

If the file is syntactically valid, moon will print nothing and exit with a
status of 0.  If the file is invalid, moon will print a cryptic error message
that won't help you fix the file and exit with a status of 1.

eval:  evaluates a given moon file.  The file is parsed and evaluated, and its result is printed on stdout, itself in the moon format.  Invoking the following command:

  moon eval ex.moon

would produce the following output:

  first_name: "jordan"
  items: ["one" 2 3.4 ["five" 6 7.8]]
  other_hash: {key_3: 3.4 key_4: ["five" 6 7.8] key_1: "one" key_2: 2}
  repeat_hash: {key: "value" other_key: "other_value"}
  people: [{age: 28 hometown: "crooklyn" name: "the first name here"} {hometown: "tha bronx" name: "the second name here" age: 30}]
  last_name: "orelli"
  hash: {key: "value" other_key: "other_value"}
  visible_item: "it has a value"

to:  used to convert moon files to other formats.  Right now, the only
supported format is json.  To convert a given moon file to json, one would invoke the following command:

  moon to json ex.moon

If the file is valid and can be converted to json (i.e., only involves types
that are also supported by json or readily convertible to json types), the
file's json representation will be printed on stdout.

The "to" subcommand can also take its input from stdin by omitting a file name, as in one of the following invocations:

  cat ex.moon | moon to json
  moon to json < ex.moon

Either invocation would have the same effect.

get:  evaluates a moon file and retrieves a value, printing it on stdout out.
The file is parsed and evaluated, meaning that get will fail if executed
against an invalid moon file; this is a search on an evaluated moon document,
not a textual search.  The general format of invocation is as follows:

  moon get $search_term $file

Where $search_term refers to a key or a path, and $file refers to the name of a
file to be searched.  Given the moon file ex.moon:

  > moon get first_name ex.moon
  "jordan"

  > moon get visible_item ex.moon
  "it has a value"

  > moon get people ex.moon
  [{hometown: "crooklyn" name: "the first name here" age: 28} {name: "the second name here" age: 30 hometown: "tha bronx"}]

The search term may involve a path, allowing one to reach into an Object or List and retrieve individual items:

  > moon get hash/other_key ex.moon
  "other_value"

  > moon get people/1/name ex.moon
  "the second name here"

*/
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/jordanorelli/moon/lib"
	"io"
	"os"
)

func input(n int) io.ReadCloser {
	if flag.Arg(n) == "" {
		return os.Stdin
	} else {
		f, err := os.Open(flag.Arg(n))
		if err != nil {
			bail(1, "input error: %s", err)
		}
		return f
	}
}

func check() {
	r := input(1)
	defer r.Close()

	_, err := moon.Read(r)
	if err != nil {
		bail(1, "parse error: %s", err)
	}
}

func to() {
	switch flag.Arg(1) {
	case "json":
		to_json(2)
	default:
		fmt.Fprintf(os.Stderr, "%s is not a valid output format\n", flag.Arg(1))
		fmt.Fprintln(os.Stderr, "valid output formats: json")
		os.Exit(1)
	}
}

func to_json(n int) {
	in := input(n)
	defer in.Close()
	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	b, err := json.MarshalIndent(doc, "", "    ")
	if err != nil {
		bail(1, "encode error: %s", err)
	}
	os.Stdout.Write(b)
}

func get() {
	docpath := flag.Arg(1)
	in := input(2)
	defer in.Close()

	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	var v interface{}
	if err := doc.Get(docpath, &v); err != nil {
		bail(1, "error reading value at path %s: %s", docpath, err)
	}
	b, err := moon.Encode(v)
	if err != nil {
		bail(1, "error encoding value: %s", err)
	}
	os.Stdout.Write(b)
}

func eval() {
	in := input(1)
	defer in.Close()

	doc, err := moon.Read(in)
	if err != nil {
		bail(1, "input error: %s", err)
	}
	b, err := moon.Encode(doc)
	if err != nil {
		bail(1, "output error: %s", err)
	}
	os.Stdout.Write(b)
}

func bail(status int, t string, args ...interface{}) {
	var w io.Writer
	if status == 0 {
		w = os.Stdout
	} else {
		w = os.Stderr
	}
	fmt.Fprintf(w, t+"\n", args...)
	os.Exit(status)
}

func main() {
	flag.Parse()
	switch flag.Arg(0) {
	case "check":
		check()
	case "to":
		to()
	case "get":
		get()
	case "eval":
		eval()
	case "":
		bail(1, "must specify an action.\nvalid actions: check to get eval")
	default:
		bail(1, "no such action:%s", flag.Arg(0))
	}
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package apiserver_test

import (
	"time"

	"github.com/juju/loggo"
	gitjujutesting "github.com/juju/testing"
	"github.com/juju/utils"
	gc "launchpad.net/gocheck"

	"github.com/juju/juju/juju/testing"
	"github.com/juju/juju/rpc"
	"github.com/juju/juju/state/api"
	"github.com/juju/juju/state/apiserver"
	coretesting "github.com/juju/juju/testing"
)

type stateSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&stateSuite{})

var testPingPeriod = 100 * time.Millisecond

func (s *stateSuite) TestConnectionBrokenDetection(c *gc.C) {
	s.PatchValue(&api.PingPeriod, testPingPeriod)

	st, _ := s.OpenAPIAsNewMachine(c)

	// Connection still alive
	select {
	case <-time.After(testPingPeriod):
	case <-st.Broken():
		c.Fatalf("connection should be alive still")
	}

	// Close the connection and see if we detect this
	go st.Close()

	// Check it's detected
	select {
	case <-time.After(testPingPeriod + time.Second):
		c.Fatalf("connection not closed as expected")
	case <-st.Broken():
		return
	}
}

func (s *stateSuite) TestPing(c *gc.C) {
	tw := &loggo.TestWriter{}
	c.Assert(loggo.RegisterWriter("ping-tester", tw, loggo.DEBUG), gc.IsNil)
	defer loggo.RemoveWriter("ping-tester")

	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	err = st.Close()
	c.Assert(err, gc.IsNil)
	err = st.Ping()
	c.Assert(err, gc.Equals, rpc.ErrShutdown)

	// Make sure that ping messages have not been logged.
	for _, m := range tw.Log {
		c.Logf("checking %q", m.Message)
		c.Check(m.Message, gc.Not(gc.Matches), `.*"Request":"Ping".*`)
	}
}

func (s *stateSuite) TestClientNoNeedToPing(c *gc.C) {
	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
	st, err := api.Open(s.APIInfo(c), api.DefaultDialOpts())
	c.Assert(err, gc.IsNil)
	defer st.Close()
	time.Sleep(coretesting.ShortWait)
	err = st.Ping()
	c.Assert(err, gc.IsNil)
}

func (s *stateSuite) TestAgentConnectionShutsDownWithNoPing(c *gc.C) {
	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
	st, _ := s.OpenAPIAsNewMachine(c)
	time.Sleep(coretesting.ShortWait)
	err := st.Ping()
	c.Assert(err, gc.ErrorMatches, "connection is shut down")
}

func (s *stateSuite) TestAgentConnectionDelaysShutdownWithPing(c *gc.C) {
	// We have to be careful, because Login can take 25ms, so we ping
	// immediately after connecting.
	s.PatchValue(apiserver.MaxClientPingInterval, 50*time.Millisecond)
	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	// As long as we don't wait too long, the connection stays open
	for i := 0; i < 10; i++ {
		time.Sleep(10 * time.Millisecond)
		err = st.Ping()
		c.Assert(err, gc.IsNil)
	}
	// However, once we stop pinging for too long, the connection dies
	time.Sleep(75 * time.Millisecond)
	err = st.Ping()
	c.Assert(err, gc.ErrorMatches, "connection is shut down")
}

type mongoPingerSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&mongoPingerSuite{})

func (s *mongoPingerSuite) SetUpTest(c *gc.C) {
	// We need to set the ping interval before the server is started.
	s.PatchValue(apiserver.MongoPingInterval, coretesting.ShortWait)
	s.JujuConnSuite.SetUpTest(c)
}

func (s *mongoPingerSuite) TestAgentConnectionsShutDownWhenStateDies(c *gc.C) {
	s.PatchValue(apiserver.MongoPingInterval, coretesting.ShortWait)
	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	gitjujutesting.MgoServer.Destroy()

	attempt := utils.AttemptStrategy{
		Total: coretesting.LongWait,
		Delay: coretesting.ShortWait,
	}
	for a := attempt.Start(); a.Next(); {
		if err := st.Ping(); err != nil {
			c.Assert(err, gc.ErrorMatches, "connection is shut down")
			return
		}
	}
	c.Fatalf("timed out waiting for API server to die")
}
<commit_msg>Patching values twice is bad, m'kay<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package apiserver_test

import (
	"time"

	"github.com/juju/loggo"
	gitjujutesting "github.com/juju/testing"
	"github.com/juju/utils"
	gc "launchpad.net/gocheck"

	"github.com/juju/juju/juju/testing"
	"github.com/juju/juju/rpc"
	"github.com/juju/juju/state/api"
	"github.com/juju/juju/state/apiserver"
	coretesting "github.com/juju/juju/testing"
)

type stateSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&stateSuite{})

var testPingPeriod = 100 * time.Millisecond

func (s *stateSuite) TestConnectionBrokenDetection(c *gc.C) {
	s.PatchValue(&api.PingPeriod, testPingPeriod)

	st, _ := s.OpenAPIAsNewMachine(c)

	// Connection still alive
	select {
	case <-time.After(testPingPeriod):
	case <-st.Broken():
		c.Fatalf("connection should be alive still")
	}

	// Close the connection and see if we detect this
	go st.Close()

	// Check it's detected
	select {
	case <-time.After(testPingPeriod + time.Second):
		c.Fatalf("connection not closed as expected")
	case <-st.Broken():
		return
	}
}

func (s *stateSuite) TestPing(c *gc.C) {
	tw := &loggo.TestWriter{}
	c.Assert(loggo.RegisterWriter("ping-tester", tw, loggo.DEBUG), gc.IsNil)
	defer loggo.RemoveWriter("ping-tester")

	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	err = st.Close()
	c.Assert(err, gc.IsNil)
	err = st.Ping()
	c.Assert(err, gc.Equals, rpc.ErrShutdown)

	// Make sure that ping messages have not been logged.
	for _, m := range tw.Log {
		c.Logf("checking %q", m.Message)
		c.Check(m.Message, gc.Not(gc.Matches), `.*"Request":"Ping".*`)
	}
}

func (s *stateSuite) TestClientNoNeedToPing(c *gc.C) {
	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
	st, err := api.Open(s.APIInfo(c), api.DefaultDialOpts())
	c.Assert(err, gc.IsNil)
	defer st.Close()
	time.Sleep(coretesting.ShortWait)
	err = st.Ping()
	c.Assert(err, gc.IsNil)
}

func (s *stateSuite) TestAgentConnectionShutsDownWithNoPing(c *gc.C) {
	s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
	st, _ := s.OpenAPIAsNewMachine(c)
	time.Sleep(coretesting.ShortWait)
	err := st.Ping()
	c.Assert(err, gc.ErrorMatches, "connection is shut down")
}

func (s *stateSuite) TestAgentConnectionDelaysShutdownWithPing(c *gc.C) {
	// We have to be careful, because Login can take 25ms, so we ping
	// immediately after connecting.
	s.PatchValue(apiserver.MaxClientPingInterval, 50*time.Millisecond)
	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	// As long as we don't wait too long, the connection stays open
	for i := 0; i < 10; i++ {
		time.Sleep(10 * time.Millisecond)
		err = st.Ping()
		c.Assert(err, gc.IsNil)
	}
	// However, once we stop pinging for too long, the connection dies
	time.Sleep(75 * time.Millisecond)
	err = st.Ping()
	c.Assert(err, gc.ErrorMatches, "connection is shut down")
}

type mongoPingerSuite struct {
	testing.JujuConnSuite
}

var _ = gc.Suite(&mongoPingerSuite{})

func (s *mongoPingerSuite) SetUpTest(c *gc.C) {
	// We need to set the ping interval before the server is started.
	s.PatchValue(apiserver.MongoPingInterval, coretesting.ShortWait)
	s.JujuConnSuite.SetUpTest(c)
}

func (s *mongoPingerSuite) TestAgentConnectionsShutDownWhenStateDies(c *gc.C) {
	st, _ := s.OpenAPIAsNewMachine(c)
	err := st.Ping()
	c.Assert(err, gc.IsNil)
	gitjujutesting.MgoServer.Destroy()

	attempt := utils.AttemptStrategy{
		Total: coretesting.LongWait,
		Delay: coretesting.ShortWait,
	}
	for a := attempt.Start(); a.Next(); {
		if err := st.Ping(); err != nil {
			c.Assert(err, gc.ErrorMatches, "connection is shut down")
			return
		}
	}
	c.Fatalf("timed out waiting for API server to die")
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"sort"

	"github.com/aptly-dev/aptly/deb"
	"github.com/smira/commander"
)

func aptlyRepoList(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 0 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	raw := cmd.Flag.Lookup("raw").Value.Get().(bool)
	jsonFlag := cmd.Flag.Lookup("json").Value.Get().(bool)

	repos := make([]string, context.CollectionFactory().LocalRepoCollection().Len())
	jsonRepos := make([]*deb.LocalRepo, context.CollectionFactory().LocalRepoCollection().Len())
	i := 0
	context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
		if raw {
			repos[i] = repo.Name
		} else {
			e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
			if e != nil {
				return e
			}

			if jsonFlag {
				jsonRepos[i] = repo
			} else {
				repos[i] = fmt.Sprintf(" * %s (packages: %d)", repo.String(), repo.NumPackages())
			}
		}
		i++
		return nil
	})

	context.CloseDatabase()

	if raw {
		sort.Strings(repos)
		for _, repo := range repos {
			fmt.Printf("%s\n", repo)
		}
	} else if jsonFlag {
		sort.Slice(jsonRepos, func(i, j int) bool {
			return jsonRepos[i].Name < jsonRepos[j].Name
		})
		if output, e := json.MarshalIndent(jsonRepos, "", "  "); e == nil {
			fmt.Println(string(output))
		} else {
			err = e
		}
	} else {
		sort.Strings(repos)
		if len(repos) > 0 {
			fmt.Printf("List of local repos:\n")
			for _, repo := range repos {
				fmt.Println(repo)
			}

			fmt.Printf("\nTo get more information about local repository, run `aptly repo show <name>`.\n")
		} else {
			fmt.Printf("No local repositories found, create one with `aptly repo create ...`.\n")
		}
	}

	return err
}

func makeCmdRepoList() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlyRepoList,
		UsageLine: "list",
		Short:     "list local repositories",
		Long: `
List command shows full list of local package repositories.

Example:

  $ aptly repo list
`,
	}

	cmd.Flag.Bool("json", false, "display list in JSON format")
	cmd.Flag.Bool("raw", false, "display list in machine-readable format")

	return cmd
}
<commit_msg>Refactor repo list into json and txt output<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"sort"

	"github.com/aptly-dev/aptly/deb"
	"github.com/smira/commander"
)

func aptlyRepoList(cmd *commander.Command, args []string) error {
	if len(args) != 0 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	jsonFlag := cmd.Flag.Lookup("json").Value.Get().(bool)

	if jsonFlag {
		return aptlyRepoListJson(cmd, args)
	}

	return aptlyRepoListTxt(cmd, args)
}

func aptlyRepoListTxt(cmd *commander.Command, args []string) error {
	var err error

	raw := cmd.Flag.Lookup("raw").Value.Get().(bool)

	repos := make([]string, context.CollectionFactory().LocalRepoCollection().Len())
	i := 0
	context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
		if raw {
			repos[i] = repo.Name
		} else {
			e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
			if e != nil {
				return e
			}

			repos[i] = fmt.Sprintf(" * %s (packages: %d)", repo.String(), repo.NumPackages())
		}
		i++
		return nil
	})

	context.CloseDatabase()

	if raw {
		sort.Strings(repos)
		for _, repo := range repos {
			fmt.Printf("%s\n", repo)
		}
	} else {
		sort.Strings(repos)
		if len(repos) > 0 {
			fmt.Printf("List of local repos:\n")
			for _, repo := range repos {
				fmt.Println(repo)
			}

			fmt.Printf("\nTo get more information about local repository, run `aptly repo show <name>`.\n")
		} else {
			fmt.Printf("No local repositories found, create one with `aptly repo create ...`.\n")
		}
	}

	return err
}

func aptlyRepoListJson(cmd *commander.Command, args []string) error {
	var err error

	jsonRepos := make([]*deb.LocalRepo, context.CollectionFactory().LocalRepoCollection().Len())
	i := 0
	context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
		e := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
		if e != nil {
			return e
		}

		jsonRepos[i] = repo
		i++
		return nil
	})

	context.CloseDatabase()

	sort.Slice(jsonRepos, func(i, j int) bool {
		return jsonRepos[i].Name < jsonRepos[j].Name
	})
	if output, e := json.MarshalIndent(jsonRepos, "", "  "); e == nil {
		fmt.Println(string(output))
	} else {
		err = e
	}

	return err
}

func makeCmdRepoList() *commander.Command {
	cmd := &commander.Command{
		Run:       aptlyRepoList,
		UsageLine: "list",
		Short:     "list local repositories",
		Long: `
List command shows full list of local package repositories.

Example:

  $ aptly repo list
`,
	}

	cmd.Flag.Bool("json", false, "display list in JSON format")
	cmd.Flag.Bool("raw", false, "display list in machine-readable format")

	return cmd
}
<|endoftext|>


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

package installer

import (
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/defaultconfig"
	"gopkg.in/check.v1"
)

func (s *S) TestResolverConfig(c *check.C) {
	tt := []struct {
		Description string
		Base        string
		Config      map[string]string
		Result      string
		ErrMsg      string
	}{
		{"invalid path", "invalid", nil, "", "no such file or directory"},
		{"default configuration", "", nil, defaultconfig.Compose, ""},
		{"custom parameter", "", map[string]string{"TSURU_API_IMAGE": "INJECT_TEST"}, "INJECT_TEST", ""},
	}

	for _, tc := range tt {
		result, err := resolveConfig(tc.Base, tc.Config)
		if len(tc.ErrMsg) > 0 {
			contains := strings.Contains(err.Error(), tc.ErrMsg)
			c.Assert(contains, check.Equals, true)
		} else {
			c.Assert(err, check.IsNil)
		}
		c.Assert(strings.Contains(result, tc.Result), check.Equals, true)
	}
}
<commit_msg>installer: fix test error message check on windows<commit_after>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package installer

import (
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/defaultconfig"
	"gopkg.in/check.v1"
)

func (s *S) TestResolverConfig(c *check.C) {
	tt := []struct {
		Description string
		Base        string
		Config      map[string]string
		Result      string
		ErrMsg      string
	}{
		{"invalid path", "invalid", nil, "", ".*(cannot find the file|no such file).*"},
		{"default configuration", "", nil, defaultconfig.Compose, ""},
		{"custom parameter", "", map[string]string{"TSURU_API_IMAGE": "INJECT_TEST"}, "INJECT_TEST", ""},
	}

	for _, tc := range tt {
		result, err := resolveConfig(tc.Base, tc.Config)
		if len(tc.ErrMsg) > 0 {
			c.Assert(err, check.ErrorMatches, tc.ErrMsg)
		} else {
			c.Assert(err, check.IsNil)
		}
		c.Assert(strings.Contains(result, tc.Result), check.Equals, true)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/JonLundy/go-totp/totp"
	"bufio"
	"os"
	"encoding/base32"
	"time"
	"crypto/sha1"
	"fmt"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	key, _ := reader.ReadString('\n')

	k, _ := base32.StdEncoding.DecodeString(key)

	code, _ := totp.Totp(k, time.Now().Unix(), sha1.New, 6)
	fmt.Print(code)
}<commit_msg>add padding handling<commit_after>package main

import (
	"github.com/JonLundy/go-totp/pkg/totp"
	"bufio"
	"os"
	"encoding/base32"
	"time"
	"crypto/sha1"
	"fmt"
        "strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	key, _ := reader.ReadString('\n')

	key = strings.Trim(key, "=\n")

        if i := len(key) % 8; i != 0 {
           key += strings.Repeat("=", 8-i)
        }

        k, err := base32.StdEncoding.DecodeString(key)

	code, _ := totp.Totp(k, time.Now().Unix(), sha1.New, 6)
	fmt.Print(code)
}

<|endoftext|>


<commit_before>package marathon

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Event struct {
	EventType  string    `json:eventType`
	Timestamp  time.Time `json:timestamp`
	SlaveID    string    `json:slaveId`
	TaskID     string    `json:taskId`
	TaskStatus string    `json:taskStatus`
	AppID      string    `json:appId`
	Host       string    `json:host`
	Ports      []int     `json:ports`
	Version    string    `json:version`
}

type Listener struct {
	events       chan Event
	host         string
	internalPort string // Internal/external ports are relative
	externalPort string // to the container this process runs in.
}

func NewListener(host string, internalPort, externalPort string) *Listener {
	listener := &Listener{
		events:       make(chan Event),
		host:         host,
		internalPort: internalPort,
		externalPort: externalPort,
	}
	http.HandleFunc("/push-listener", listener.handler)
	go http.ListenAndServe(":"+internalPort, nil)

	return listener
}

func (l *Listener) handler(res http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)

	var event Event
	if err := decoder.Decode(&event); err != nil {
		log.Fatal(err)
	}

	if event.EventType == "status_update_event" { // We only care about container change events
		l.events <- event
	}

	res.Write([]byte("Thanks.")) // Marathon ignores replies.  Just being polite.
}

func (l *Listener) Events() <-chan Event {
	return l.events
}

func (l *Listener) Subscribe(marathonHost string) error {
	marathonURL := url.URL{Scheme: "http", Host: marathonHost, Path: "/v2/eventSubscriptions"}
	q := marathonURL.Query()
	q.Set("callbackUrl", fmt.Sprintf("http://%s:%s/push-listener", l.host, l.externalPort))
	marathonURL.RawQuery = q.Encode()

	res, err := http.Post(marathonURL.String(), "application/json", strings.NewReader(""))
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("Bad status code while subscribing to marathon events: " + res.Status)
	}

	var data map[string]interface{}
	decoder := json.NewDecoder(res.Body)
	if err := decoder.Decode(&data); err != nil {
		return err
	}

	return nil
}
<commit_msg>Added quotes around json descriptions in Event struct.<commit_after>package marathon

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Event struct {
	EventType  string    `json:"eventType"`
	Timestamp  time.Time `json:"timestamp"`
	SlaveID    string    `json:"slaveId"`
	TaskID     string    `json:"taskId"`
	TaskStatus string    `json:"taskStatus"`
	AppID      string    `json:"appId"`
	Host       string    `json:"host"`
	Ports      []int     `json:"ports"`
	Version    string    `json:"version"`
}

type Listener struct {
	events       chan Event
	host         string
	internalPort string // Internal/external ports are relative
	externalPort string // to the container this process runs in.
}

func NewListener(host string, internalPort, externalPort string) *Listener {
	listener := &Listener{
		events:       make(chan Event),
		host:         host,
		internalPort: internalPort,
		externalPort: externalPort,
	}
	http.HandleFunc("/push-listener", listener.handler)
	go http.ListenAndServe(":"+internalPort, nil)

	return listener
}

func (l *Listener) handler(res http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)

	var event Event
	if err := decoder.Decode(&event); err != nil {
		log.Fatal(err)
	}

	if event.EventType == "status_update_event" { // We only care about container change events
		l.events <- event
	}

	res.Write([]byte("Thanks.")) // Marathon ignores replies.  Just being polite.
}

func (l *Listener) Events() <-chan Event {
	return l.events
}

func (l *Listener) Subscribe(marathonHost string) error {
	marathonURL := url.URL{Scheme: "http", Host: marathonHost, Path: "/v2/eventSubscriptions"}
	q := marathonURL.Query()
	q.Set("callbackUrl", fmt.Sprintf("http://%s:%s/push-listener", l.host, l.externalPort))
	marathonURL.RawQuery = q.Encode()

	res, err := http.Post(marathonURL.String(), "application/json", strings.NewReader(""))
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("Bad status code while subscribing to marathon events: " + res.Status)
	}

	var data map[string]interface{}
	decoder := json.NewDecoder(res.Body)
	if err := decoder.Decode(&data); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


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

package models

import (
	"fmt"

	"github.com/Unknwon/com"

	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/markup"
	"code.gitea.io/gitea/modules/setting"
)

func (issue *Issue) mailSubject() string {
	return fmt.Sprintf("[%s] %s (#%d)", issue.Repo.Name, issue.Title, issue.Index)
}

// mailIssueCommentToParticipants can be used for both new issue creation and comment.
// This function sends two list of emails:
// 1. Repository watchers and users who are participated in comments.
// 2. Users who are not in 1. but get mentioned in current issue/comment.
func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content string, comment *Comment, mentions []string) error {
	if !setting.Service.EnableNotifyMail {
		return nil
	}

	watchers, err := getWatchers(e, issue.RepoID)
	if err != nil {
		return fmt.Errorf("getWatchers [repo_id: %d]: %v", issue.RepoID, err)
	}
	participants, err := getParticipantsByIssueID(e, issue.ID)
	if err != nil {
		return fmt.Errorf("getParticipantsByIssueID [issue_id: %d]: %v", issue.ID, err)
	}

	// In case the issue poster is not watching the repository and is active,
	// even if we have duplicated in watchers, can be safely filtered out.
	poster, err := GetUserByID(issue.PosterID)
	if err != nil {
		return fmt.Errorf("GetUserByID [%d]: %v", issue.PosterID, err)
	}
	if issue.PosterID != doer.ID && poster.IsActive && !poster.ProhibitLogin {
		participants = append(participants, issue.Poster)
	}

	// Assignees must receive any communications
	assignees, err := GetAssigneesByIssue(issue)
	if err != nil {
		return err
	}

	for _, assignee := range assignees {
		if assignee.ID != doer.ID {
			participants = append(participants, assignee)
		}
	}

	tos := make([]string, 0, len(watchers)) // List of email addresses.
	names := make([]string, 0, len(watchers))
	for i := range watchers {
		if watchers[i].UserID == doer.ID {
			continue
		}

		to, err := getUserByID(e, watchers[i].UserID)
		if err != nil {
			return fmt.Errorf("GetUserByID [%d]: %v", watchers[i].UserID, err)
		}
		if to.IsOrganization() {
			continue
		}

		tos = append(tos, to.Email)
		names = append(names, to.Name)
	}
	for i := range participants {
		if participants[i].ID == doer.ID {
			continue
		} else if com.IsSliceContainsStr(names, participants[i].Name) {
			continue
		}

		tos = append(tos, participants[i].Email)
		names = append(names, participants[i].Name)
	}

	SendIssueCommentMail(issue, doer, content, comment, tos)

	// Mail mentioned people and exclude watchers.
	names = append(names, doer.Name)
	tos = make([]string, 0, len(mentions)) // list of user names.
	for i := range mentions {
		if com.IsSliceContainsStr(names, mentions[i]) {
			continue
		}

		tos = append(tos, mentions[i])
	}
	SendIssueMentionMail(issue, doer, content, comment, getUserEmailsByNames(e, tos))

	return nil
}

// MailParticipants sends new issue thread created emails to repository watchers
// and mentioned people.
func (issue *Issue) MailParticipants() (err error) {
	return issue.mailParticipants(x)
}

func (issue *Issue) mailParticipants(e Engine) (err error) {
	mentions := markup.FindAllMentions(issue.Content)
	if err = UpdateIssueMentions(e, issue.ID, mentions); err != nil {
		return fmt.Errorf("UpdateIssueMentions [%d]: %v", issue.ID, err)
	}

	if err = mailIssueCommentToParticipants(e, issue, issue.Poster, issue.Content, nil, mentions); err != nil {
		log.Error(4, "mailIssueCommentToParticipants: %v", err)
	}

	return nil
}
<commit_msg>Don't disclose emails of all users when sending out emails (#4664)<commit_after>// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models

import (
	"fmt"

	"github.com/Unknwon/com"

	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/markup"
	"code.gitea.io/gitea/modules/setting"
)

func (issue *Issue) mailSubject() string {
	return fmt.Sprintf("[%s] %s (#%d)", issue.Repo.Name, issue.Title, issue.Index)
}

// mailIssueCommentToParticipants can be used for both new issue creation and comment.
// This function sends two list of emails:
// 1. Repository watchers and users who are participated in comments.
// 2. Users who are not in 1. but get mentioned in current issue/comment.
func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content string, comment *Comment, mentions []string) error {
	if !setting.Service.EnableNotifyMail {
		return nil
	}

	watchers, err := getWatchers(e, issue.RepoID)
	if err != nil {
		return fmt.Errorf("getWatchers [repo_id: %d]: %v", issue.RepoID, err)
	}
	participants, err := getParticipantsByIssueID(e, issue.ID)
	if err != nil {
		return fmt.Errorf("getParticipantsByIssueID [issue_id: %d]: %v", issue.ID, err)
	}

	// In case the issue poster is not watching the repository and is active,
	// even if we have duplicated in watchers, can be safely filtered out.
	poster, err := GetUserByID(issue.PosterID)
	if err != nil {
		return fmt.Errorf("GetUserByID [%d]: %v", issue.PosterID, err)
	}
	if issue.PosterID != doer.ID && poster.IsActive && !poster.ProhibitLogin {
		participants = append(participants, issue.Poster)
	}

	// Assignees must receive any communications
	assignees, err := GetAssigneesByIssue(issue)
	if err != nil {
		return err
	}

	for _, assignee := range assignees {
		if assignee.ID != doer.ID {
			participants = append(participants, assignee)
		}
	}

	tos := make([]string, 0, len(watchers)) // List of email addresses.
	names := make([]string, 0, len(watchers))
	for i := range watchers {
		if watchers[i].UserID == doer.ID {
			continue
		}

		to, err := getUserByID(e, watchers[i].UserID)
		if err != nil {
			return fmt.Errorf("GetUserByID [%d]: %v", watchers[i].UserID, err)
		}
		if to.IsOrganization() {
			continue
		}

		tos = append(tos, to.Email)
		names = append(names, to.Name)
	}
	for i := range participants {
		if participants[i].ID == doer.ID {
			continue
		} else if com.IsSliceContainsStr(names, participants[i].Name) {
			continue
		}

		tos = append(tos, participants[i].Email)
		names = append(names, participants[i].Name)
	}

	for _, to := range tos {
		SendIssueCommentMail(issue, doer, content, comment, []string{to})
	}

	// Mail mentioned people and exclude watchers.
	names = append(names, doer.Name)
	tos = make([]string, 0, len(mentions)) // list of user names.
	for i := range mentions {
		if com.IsSliceContainsStr(names, mentions[i]) {
			continue
		}

		tos = append(tos, mentions[i])
	}

	emails := getUserEmailsByNames(e, tos)

	for _, to := range emails {
		SendIssueMentionMail(issue, doer, content, comment, []string{to})
	}

	return nil
}

// MailParticipants sends new issue thread created emails to repository watchers
// and mentioned people.
func (issue *Issue) MailParticipants() (err error) {
	return issue.mailParticipants(x)
}

func (issue *Issue) mailParticipants(e Engine) (err error) {
	mentions := markup.FindAllMentions(issue.Content)
	if err = UpdateIssueMentions(e, issue.ID, mentions); err != nil {
		return fmt.Errorf("UpdateIssueMentions [%d]: %v", issue.ID, err)
	}

	if err = mailIssueCommentToParticipants(e, issue, issue.Poster, issue.Content, nil, mentions); err != nil {
		log.Error(4, "mailIssueCommentToParticipants: %v", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package models

import (
	"testing"

	"bitbucket.org/mundipagg/boletoapi/test"
)

func TestShouldReturnValidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCPF() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CNPJ"}
	if document.IsCPF() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CnpJ"}
	if document.IsCNPJ() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCNPJ() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564fas", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err != nil {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564asdf22", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err == nil {
		t.Fail()
	}
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: "200", Message: "Hue2"})
	e.Append("100", "Hue")
	test.ExpectTrue(len(e) == 2, t)
}

func TestShouldCreateNewSingleErrorCollection(t *testing.T) {
	e := NewSingleErrorCollection("200", "Hue2")
	test.ExpectTrue(len(e) == 1, t)
}

func TestIsAgencyValid(t *testing.T) {
	a := Agreement{
		Agency: "234-2a",
	}
	err := a.IsAgencyValid()
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Agency == "2342", t)
}

func TestIsAgencyInValid(t *testing.T) {
	a := Agreement{
		Agency: "234-2222a",
	}
	err := a.IsAgencyValid()
	test.ExpectError(err, t)
}

func TestIsAgencyValidWithLessThan4Digits(t *testing.T) {
	a := Agreement{
		Agency: "321",
	}
	err := a.IsAgencyValid()
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Agency == "0321", t)
}

func TestCalculateAgencyDigit(t *testing.T) {
	a := new(Agreement)
	a.AccountDigit = "1sssss"
	c := func(s string) string {
		return "1"
	}
	a.CalculateAgencyDigit(c)
	test.ExpectTrue(a.AgencyDigit == "1", t)
}

func WTestCalculateAgencyDigitWithInvalidDigit(t *testing.T) {
	a := Agreement{
		AgencyDigit: "",
	}
	c := func(s string) string {
		return "1"
	}
	a.CalculateAgencyDigit(c)
	test.ExpectTrue(a.AgencyDigit == "1", t)
}

func TestIsAccountValid(t *testing.T) {
	a := Agreement{
		Account: "1234fff",
	}
	err := a.IsAccountValid(8)
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Account == "00001234", t)
}

func TestIsAccountInValid(t *testing.T) {
	a := Agreement{
		Account: "123456789",
	}
	err := a.IsAccountValid(8)
	test.ExpectError(err, t)
}
<commit_msg>:art: Muda nome de método no teste<commit_after>package models

import (
	"testing"

	"bitbucket.org/mundipagg/boletoapi/test"
)

func TestShouldReturnValidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCPF() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCpfOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CNPJ"}
	if document.IsCNPJ() == false {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "1234567890132", Type: "CnpJ"}
	if document.IsCNPJ() == false {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentType(t *testing.T) {
	document := Document{Number: "12345678901", Type: "CPF"}
	if document.IsCNPJ() {
		t.Fail()
	}
}

func TestShouldReturnValidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564fas", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err != nil {
		t.Fail()
	}
}

func TestShouldReturnInvalidCnpjOnDocumentNumber(t *testing.T) {
	document := Document{Number: "12345678901564asdf22", Type: "CNPJ"}
	if err := document.ValidateCNPJ(); err == nil {
		t.Fail()
	}
}

func TestShouldReturnBankNumberIsValid(t *testing.T) {
	var b BankNumber = 237

	if b.IsBankNumberValid() == false {
		t.Fail()
	}
}

func TestShouldAppendCollectionOfErrrors(t *testing.T) {
	e := NewErrorCollection(ErrorResponse{Code: "200", Message: "Hue2"})
	e.Append("100", "Hue")
	test.ExpectTrue(len(e) == 2, t)
}

func TestShouldCreateNewSingleErrorCollection(t *testing.T) {
	e := NewSingleErrorCollection("200", "Hue2")
	test.ExpectTrue(len(e) == 1, t)
}

func TestIsAgencyValid(t *testing.T) {
	a := Agreement{
		Agency: "234-2a",
	}
	err := a.IsAgencyValid()
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Agency == "2342", t)
}

func TestIsAgencyInValid(t *testing.T) {
	a := Agreement{
		Agency: "234-2222a",
	}
	err := a.IsAgencyValid()
	test.ExpectError(err, t)
}

func TestIsAgencyValidWithLessThan4Digits(t *testing.T) {
	a := Agreement{
		Agency: "321",
	}
	err := a.IsAgencyValid()
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Agency == "0321", t)
}

func TestCalculateAgencyDigit(t *testing.T) {
	a := new(Agreement)
	a.AccountDigit = "1sssss"
	c := func(s string) string {
		return "1"
	}
	a.CalculateAgencyDigit(c)
	test.ExpectTrue(a.AgencyDigit == "1", t)
}

func WTestCalculateAgencyDigitWithInvalidDigit(t *testing.T) {
	a := Agreement{
		AgencyDigit: "",
	}
	c := func(s string) string {
		return "1"
	}
	a.CalculateAgencyDigit(c)
	test.ExpectTrue(a.AgencyDigit == "1", t)
}

func TestIsAccountValid(t *testing.T) {
	a := Agreement{
		Account: "1234fff",
	}
	err := a.IsAccountValid(8)
	test.ExpectNoError(err, t)
	test.ExpectTrue(a.Account == "00001234", t)
}

func TestIsAccountInValid(t *testing.T) {
	a := Agreement{
		Account: "123456789",
	}
	err := a.IsAccountValid(8)
	test.ExpectError(err, t)
}
<|endoftext|>


<commit_before>package argot

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/xeipuuv/gojsonschema"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

type Step interface {
	Go() error
}

type Steps []Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (ss Steps) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, len(ss))
	for _, step := range ss {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

type StepFunc func() error

func (sf StepFunc) Go() error {
	return sf()
}

type HttpCall struct {
	Client       *http.Client
	Request      *http.Request
	Response     *http.Response
	ResponseBody []byte
}

// client can be nil. If it is nil, a new http.Client is used.
func NewHttpCall(client *http.Client) *HttpCall {
	if client == nil {
		client = new(http.Client)
	}
	return &HttpCall{
		Client: client,
	}
}

func (hc *HttpCall) AssertNoRequest() error {
	if hc.Request == nil {
		return nil
	} else {
		return errors.New("Request already set")
	}
}

func (hc *HttpCall) AssertRequest() error {
	if hc.Request == nil {
		return errors.New("No Request set")
	} else {
		return nil
	}
}

func (hc *HttpCall) AssertNoRespose() error {
	if hc.Response == nil {
		return nil
	} else {
		return errors.New("Response already set")
	}
}

func (hc *HttpCall) EnsureResponse() error {
	if hc.Response != nil {
		return nil
	} else if hc.Request == nil {
		return errors.New("Cannot ensure response: no request.")
	} else if response, err := hc.Client.Do(hc.Request); err != nil {
		return fmt.Errorf("Error when making call of %v: %v", hc.Request, err)
	} else {
		hc.Response = response
		return nil
	}
}

// Idempotent.
func (hc *HttpCall) ReceiveBody() error {
	if err := hc.EnsureResponse(); err != nil {
		return err
	} else if hc.ResponseBody != nil {
		return nil
	} else {
		defer hc.Response.Body.Close()
		bites := new(bytes.Buffer)
		if _, err = io.Copy(bites, hc.Response.Body); err != nil {
			return err
		} else {
			hc.ResponseBody = bites.Bytes()
			return nil
		}
	}
}

// Idempotent. You should ensure this is called at the end of life for
// each HttpCall. It drains bodies and generally sweeps up the mess.
func (hc *HttpCall) Reset() error {
	hc.Request = nil
	if hc.Response != nil && hc.ResponseBody == nil {
		io.Copy(ioutil.Discard, hc.Response.Body)
		hc.Response.Body.Close()
		hc.Response = nil
	}
	hc.ResponseBody = nil
	return nil
}

// This will automatically call HttpCall.Reset to ensure it's safe to
// create a new request.
func NewRequest(hc *HttpCall, method, urlStr string, body io.Reader) Step {
	return StepFunc(func() error {
		if err := hc.Reset(); err != nil {
			return err
		} else if req, err := http.NewRequest(method, urlStr, body); err != nil {
			return err
		} else {
			hc.Request = req
			return nil
		}
	})
}

func RequestHeader(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := AnyError(hc.AssertRequest(), hc.AssertNoRespose()); err != nil {
			return err
		} else {
			hc.Request.Header.Set(key, value)
			return nil
		}
	})
}

func ResponseStatusEquals(hc *HttpCall, status int) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if hc.Response.StatusCode != status {
			return fmt.Errorf("Status: Expected %d; found %d.", status, hc.Response.StatusCode)
		} else {
			return nil
		}
	})
}

func ResponseHeaderEquals(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); header != value {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func ResponseHeaderContains(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); !strings.Contains(header, value) {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func ResponseBodyEquals(hc *HttpCall, value string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if string(hc.ResponseBody) != value {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func ResponseBodyContains(hc *HttpCall, value string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if !strings.Contains(string(hc.ResponseBody), value) {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func ResponseBodyJSONSchema(hc *HttpCall, schema string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else {
			schemaLoader := gojsonschema.NewStringLoader(schema)
			bodyLoader := gojsonschema.NewStringLoader(string(hc.ResponseBody))
			if result, err := gojsonschema.Validate(schemaLoader, bodyLoader); err != nil {
				return err
			} else if !result.Valid() {
				msg := "Validation failure:\n"
				for _, err := range result.Errors() {
					msg += fmt.Sprintf("\t%v\n", err)
				}
				return errors.New(msg[:len(msg)-1])
			} else {
				return nil
			}
		}
	})
}

func AnyError(errs ...error) error {
	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Support using a chan as well as a slice for steps. Lazy+++.<commit_after>package argot

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/xeipuuv/gojsonschema"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"testing"
)

type Step interface {
	Go() error
}

type Steps []Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (ss Steps) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, len(ss))
	for _, step := range ss {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

// Use a chan to indicate the steps to carry out rather than a
// slice. The advantage of a chan is that it allows more laziness:
// steps can even be responsible for issuing their own subsequent
// steps.
type StepsChan <-chan Step

// t can be nil. If t is not nil and an error occurs, then t.Fatal
// will be called. The steps returned represent the steps that were
// executed, including the step that errored, if an error occurred.
func (sc StepsChan) Go(t *testing.T) (results Steps, err error) {
	if t != nil {
		defer func() {
			if err != nil {
				t.Fatalf("Achieved Steps: %v; Error: %v", results, err)
			}
		}()
	}
	results = make([]Step, 0, 16)
	for step := range sc {
		results = append(results, step)
		err = step.Go()
		if err != nil {
			return results, err
		}
	}
	return results, nil
}

type StepFunc func() error

func (sf StepFunc) Go() error {
	return sf()
}

type HttpCall struct {
	Client       *http.Client
	Request      *http.Request
	Response     *http.Response
	ResponseBody []byte
}

// client can be nil. If it is nil, a new http.Client is used.
func NewHttpCall(client *http.Client) *HttpCall {
	if client == nil {
		client = new(http.Client)
	}
	return &HttpCall{
		Client: client,
	}
}

func (hc *HttpCall) AssertNoRequest() error {
	if hc.Request == nil {
		return nil
	} else {
		return errors.New("Request already set")
	}
}

func (hc *HttpCall) AssertRequest() error {
	if hc.Request == nil {
		return errors.New("No Request set")
	} else {
		return nil
	}
}

func (hc *HttpCall) AssertNoRespose() error {
	if hc.Response == nil {
		return nil
	} else {
		return errors.New("Response already set")
	}
}

func (hc *HttpCall) EnsureResponse() error {
	if hc.Response != nil {
		return nil
	} else if hc.Request == nil {
		return errors.New("Cannot ensure response: no request.")
	} else if response, err := hc.Client.Do(hc.Request); err != nil {
		return fmt.Errorf("Error when making call of %v: %v", hc.Request, err)
	} else {
		hc.Response = response
		return nil
	}
}

// Idempotent.
func (hc *HttpCall) ReceiveBody() error {
	if err := hc.EnsureResponse(); err != nil {
		return err
	} else if hc.ResponseBody != nil {
		return nil
	} else {
		defer hc.Response.Body.Close()
		bites := new(bytes.Buffer)
		if _, err = io.Copy(bites, hc.Response.Body); err != nil {
			return err
		} else {
			hc.ResponseBody = bites.Bytes()
			return nil
		}
	}
}

// Idempotent. You should ensure this is called at the end of life for
// each HttpCall. It drains bodies and generally sweeps up the mess.
func (hc *HttpCall) Reset() error {
	hc.Request = nil
	if hc.Response != nil && hc.ResponseBody == nil {
		io.Copy(ioutil.Discard, hc.Response.Body)
		hc.Response.Body.Close()
		hc.Response = nil
	}
	hc.ResponseBody = nil
	return nil
}

// This will automatically call HttpCall.Reset to ensure it's safe to
// create a new request.
func NewRequest(hc *HttpCall, method, urlStr string, body io.Reader) Step {
	return StepFunc(func() error {
		if err := hc.Reset(); err != nil {
			return err
		} else if req, err := http.NewRequest(method, urlStr, body); err != nil {
			return err
		} else {
			hc.Request = req
			return nil
		}
	})
}

func RequestHeader(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := AnyError(hc.AssertRequest(), hc.AssertNoRespose()); err != nil {
			return err
		} else {
			hc.Request.Header.Set(key, value)
			return nil
		}
	})
}

func ResponseStatusEquals(hc *HttpCall, status int) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if hc.Response.StatusCode != status {
			return fmt.Errorf("Status: Expected %d; found %d.", status, hc.Response.StatusCode)
		} else {
			return nil
		}
	})
}

func ResponseHeaderEquals(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); header != value {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func ResponseHeaderContains(hc *HttpCall, key, value string) Step {
	return StepFunc(func() error {
		if err := hc.EnsureResponse(); err != nil {
			return err
		} else if header := hc.Response.Header.Get(key); !strings.Contains(header, value) {
			return fmt.Errorf("Header '%s': Expected '%s'; found '%s'.", key, value, header)
		} else {
			return nil
		}
	})
}

func ResponseBodyEquals(hc *HttpCall, value string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if string(hc.ResponseBody) != value {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func ResponseBodyContains(hc *HttpCall, value string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else if !strings.Contains(string(hc.ResponseBody), value) {
			return fmt.Errorf("Body: Expected '%s'; found '%s'.", value, string(hc.ResponseBody))
		} else {
			return nil
		}
	})
}

func ResponseBodyJSONSchema(hc *HttpCall, schema string) Step {
	return StepFunc(func() error {
		if err := hc.ReceiveBody(); err != nil {
			return err
		} else {
			schemaLoader := gojsonschema.NewStringLoader(schema)
			bodyLoader := gojsonschema.NewStringLoader(string(hc.ResponseBody))
			if result, err := gojsonschema.Validate(schemaLoader, bodyLoader); err != nil {
				return err
			} else if !result.Valid() {
				msg := "Validation failure:\n"
				for _, err := range result.Errors() {
					msg += fmt.Sprintf("\t%v\n", err)
				}
				return errors.New(msg[:len(msg)-1])
			} else {
				return nil
			}
		}
	})
}

func AnyError(errs ...error) error {
	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package unsplash

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/joho/godotenv"
)

func readEnv() {
	err := godotenv.Load("../.env")

	if err != nil {
		log.Fatal("Error loading .env file")
	}
}

var imageIds = []struct {
	id         string
	statusCode int
}{
	{"bWI4Vd4vI3w", 200},
	{"xjQhTrxyVBw", 200},
	{"7NcGuPF5NU0", 200},
	{"oeks929jesj", 422},
	{"9jdwnduwwen", 422},
	{"aaaaa1aaaaa", 422},
}

func TestDownloadPhoto(t *testing.T) {
	readEnv()

	for _, value := range imageIds {
		path := fmt.Sprintf("/download-photo?id=%s", value.id)

		req, err := http.NewRequest("GET", path, nil)

		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		handler := http.HandlerFunc(DownloadPhoto)

		handler.ServeHTTP(rr, req)

		if rr.Code != value.statusCode {
			t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
		}
	}
}

func TestGetPhotoDownloadLocation(t *testing.T) {
	readEnv()

	for _, value := range imageIds {
		s, err := GetPhotoDownloadLocation(value.id)

		if err != nil {
			t.Fatal(err)
		}

		if value.statusCode == 200 && s.URL == "" {
			t.Errorf("Expected UnsplashResponse URL field to be non-empty, got %s", s.URL)
		}

		if value.statusCode == 422 && s.Errors == nil {
			t.Errorf("Expected UnsplashResponse to contains Errors, got %v", s.Errors)
		}
	}
}

func makeRequest(t *testing.T, path string, h func(http.ResponseWriter, *http.Request)) {
	readEnv()

	req, err := http.NewRequest("GET", path, nil)

	if err != nil {
		t.Fatal(err)
	}

	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(h)

	handler.ServeHTTP(rr, req)

	if rr.Code != http.StatusOK {
		t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
	}
}

var searchTable = []struct {
	key  string
	page int
}{
	{"cars", 1},
	{"house", 6},
	{"animal", 10},
}

func TestSearchUnsplash(t *testing.T) {
	for _, value := range searchTable {
		makeRequest(t, fmt.Sprintf("/search-unsplash?key=%s&page=%d", value.key, value.page), SearchUnsplash)
	}
}

func TestGetRandomPhoto(t *testing.T) {
	makeRequest(t, "/random-photo?collections=998309", GetRandomPhoto)
}

var collectionsTable = []struct {
	ids        string
	statusCode int
}{
	{"998309,317099", 200},
	{"39843782,4993402", 400},
	{"151521,9829382", 400},
	{"175083,762960", 200},
}

func TestValidateCollections(t *testing.T) {
	readEnv()

	for _, value := range collectionsTable {
		path := fmt.Sprintf("/validate-collections?collections=%s", value.ids)
		req, err := http.NewRequest("GET", path, nil)

		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		handler := http.HandlerFunc(ValidateCollections)

		handler.ServeHTTP(rr, req)

		if rr.Code != value.statusCode {
			t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
		}
	}
}
<commit_msg>Fix failing tests<commit_after>package unsplash

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/joho/godotenv"
)

func readEnv() {
	err := godotenv.Load("../.env")

	if err != nil {
		log.Fatal("Error loading .env file")
	}
}

var imageIds = []struct {
	id         string
	statusCode int
}{
	{"bWI4Vd4vI3w", 200},
	{"xjQhTrxyVBw", 200},
	{"7NcGuPF5NU0", 200},
	{"oeks929jesj", 500},
	{"9jdwnduwwen", 500},
	{"aaaaa1aaaaa", 500},
}

func TestDownloadPhoto(t *testing.T) {
	readEnv()

	for _, value := range imageIds {
		path := fmt.Sprintf("/download-photo?id=%s", value.id)

		req, err := http.NewRequest("GET", path, nil)

		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		handler := http.HandlerFunc(DownloadPhoto)

		handler.ServeHTTP(rr, req)

		if rr.Code != value.statusCode {
			t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
		}
	}
}

func TestGetPhotoDownloadLocation(t *testing.T) {
	readEnv()

	for _, value := range imageIds {
		s, err := GetPhotoDownloadLocation(value.id)

		if err != nil && value.statusCode == 200 {
			t.Errorf("Expect no errors from GetPhotoDownloadLocation for a valid photo id")
		}

		if err == nil && value.statusCode == 500 {
			t.Errorf("Expected GetPhotoDownloadLocation to throw an error for an invalid photo id")
		}

		if value.statusCode == 200 && s.URL == "" {
			t.Errorf("Expected UnsplashResponse URL field to be non-empty, got %s", s.URL)
		}
	}
}

func makeRequest(t *testing.T, path string, h func(http.ResponseWriter, *http.Request)) {
	readEnv()

	req, err := http.NewRequest("GET", path, nil)

	if err != nil {
		t.Fatal(err)
	}

	rr := httptest.NewRecorder()
	handler := http.HandlerFunc(h)

	handler.ServeHTTP(rr, req)

	if rr.Code != http.StatusOK {
		t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
	}
}

var searchTable = []struct {
	key  string
	page int
}{
	{"cars", 1},
	{"house", 6},
	{"animal", 10},
}

func TestSearchUnsplash(t *testing.T) {
	for _, value := range searchTable {
		makeRequest(t, fmt.Sprintf("/search-unsplash?key=%s&page=%d", value.key, value.page), SearchUnsplash)
	}
}

func TestGetRandomPhoto(t *testing.T) {
	makeRequest(t, "/random-photo?collections=998309", GetRandomPhoto)
}

var collectionsTable = []struct {
	ids        string
	statusCode int
}{
	{"998309,317099", 200},
	{"39843782,4993402", 500},
	{"151521,9829382", 500},
	{"175083,762960", 200},
}

func TestValidateCollections(t *testing.T) {
	readEnv()

	for _, value := range collectionsTable {
		path := fmt.Sprintf("/validate-collections?collections=%s", value.ids)
		req, err := http.NewRequest("GET", path, nil)

		if err != nil {
			t.Fatal(err)
		}

		rr := httptest.NewRecorder()
		handler := http.HandlerFunc(ValidateCollections)

		handler.ServeHTTP(rr, req)

		if rr.Code != value.statusCode {
			t.Errorf("Status should be %d, got %d", http.StatusOK, rr.Code)
		}
	}
}
<|endoftext|>


<commit_before>package mbotapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
)

// This defines a bot
// Set Debug to true for debugging
type BotAPI struct {
	Token       string
	VerifyToken string
	Debug       bool
	Client      *http.Client
}

// This helps create a BotAPI instance with token, verify_token
// By default Debug is set to false
func NewBotAPI(token string, vtoken string) *BotAPI {
	return &BotAPI{
		Token:       token,
		VerifyToken: vtoken,
		Debug:       false,
		Client:      &http.Client{},
	}
}

// This helps send request (send messages to users)
// It takes Request struct encoded into a buffer of json bytes
// The APIResponse contains the error from FB if any
// Should NOT be directly used, Use Send / SendFile
func (bot *BotAPI) MakeRequest(b *bytes.Buffer) (APIResponse, error) {
	uri := fmt.Sprintf(APIEndpoint, bot.Token)

	req, _ := http.NewRequest("POST", uri, b)
	req.Header.Set("Content-Type", "application/json")
	resp, err := bot.Client.Do(req)
	if err != nil {
		return APIResponse{}, err
	}
	defer resp.Body.Close()

	var rsp APIResponse
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(&rsp)
	if err != nil {
		return APIResponse{}, nil
	}

	if resp.StatusCode != 200 {
		return rsp, errors.New(http.StatusText(resp.StatusCode))
	}
	return rsp, nil
}

// This function helps send messages to users
// It takes Message / GenericTemplate / ButtonTemplate / ReceiptTemplate and
// sends it to the user
func (bot *BotAPI) Send(u User, c interface{}, notif string) (APIResponse, error) {
	var r Request

	n := RegularNotif
	if notif != "" {
		n = notif
	}

	switch c.(type) {
	case Request:
		return APIResponse{}, errors.New("Use MakeRequest to send Request!!")
	case Message:
		r = Request{
			Recipient: u,
			Message:   c.(Message),
			NotifType: n,
		}

	case GenericTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(GenericTemplate),
				},
			},
		}

	case ButtonTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(ButtonTemplate),
				},
			},
		}

	case ReceiptTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(ReceiptTemplate),
				},
			},
		}

	default:
		return APIResponse{}, errors.New("Type is not supported")
	}

	if r == (Request{}) {
		return APIResponse{}, errors.New("Unknown Error")
	}
	payl, _ := json.Marshal(r)
	if bot.Debug {
		log.Printf("[INFO] Payload: %s", string(payl))
	}
	return bot.MakeRequest(bytes.NewBuffer(payl))
}

// This helps to send local images (currently) to users
// TODO: not tested yet!
func (bot *BotAPI) SendFile(u User, path string) (APIResponse, error) {
	file, err := os.Open(path)
	if err != nil {
		return APIResponse{}, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile("filedata", filepath.Base(path))
	if err != nil {
		return APIResponse{}, err
	}
	_, err = io.Copy(part, file)

	usr, _ := json.Marshal(u)
	_ = writer.WriteField("recipient", string(usr))
	img := NewImageMessage("")
	im, _ := json.Marshal(img)
	_ = writer.WriteField("message", string(im))

	err = writer.Close()
	if err != nil {
		return APIResponse{}, err
	}

	return bot.MakeRequest(body)
}

// This function registers the handlers for
// - webhook verification
// - all callbacks made on the webhhoks
// It loops over all entries in the callback and
// pushes to the Callback channel
// This also return a *http.ServeMux which can be used to listenAndServe
func (bot *BotAPI) SetWebhook(pattern string) (<-chan Callback, *http.ServeMux) {
	callbackChan := make(chan Callback, 100)

	mux := http.NewServeMux()
	mux.HandleFunc(pattern, func(w http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			if req.FormValue("hub.verify_token") == bot.VerifyToken {
				w.Write([]byte(req.FormValue("hub.challenge")))
				return
			}
			w.WriteHeader(http.StatusUnauthorized)
			return

		case "POST":
			defer req.Body.Close()

			var rsp Response
			if bot.Debug {
				body, _ := ioutil.ReadAll(response.Body)
				log.Printf("[INFO]%s", body)
			}
			decoder := json.NewDecoder(req.Body)
			decoder.Decode(&rsp)

			if rsp.Object == "page" {
				for _, e := range rsp.Entries {
					for _, c := range e.Messaging {
						callbackChan <- c
					}
				}
			}
			w.WriteHeader(http.StatusOK)
			return

		default:
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
	})

	return callbackChan, mux

}
<commit_msg>debug<commit_after>package mbotapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
)

// This defines a bot
// Set Debug to true for debugging
type BotAPI struct {
	Token       string
	VerifyToken string
	Debug       bool
	Client      *http.Client
}

// This helps create a BotAPI instance with token, verify_token
// By default Debug is set to false
func NewBotAPI(token string, vtoken string) *BotAPI {
	return &BotAPI{
		Token:       token,
		VerifyToken: vtoken,
		Debug:       false,
		Client:      &http.Client{},
	}
}

// This helps send request (send messages to users)
// It takes Request struct encoded into a buffer of json bytes
// The APIResponse contains the error from FB if any
// Should NOT be directly used, Use Send / SendFile
func (bot *BotAPI) MakeRequest(b *bytes.Buffer) (APIResponse, error) {
	uri := fmt.Sprintf(APIEndpoint, bot.Token)

	req, _ := http.NewRequest("POST", uri, b)
	req.Header.Set("Content-Type", "application/json")
	resp, err := bot.Client.Do(req)
	if err != nil {
		return APIResponse{}, err
	}
	defer resp.Body.Close()

	var rsp APIResponse
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(&rsp)
	if err != nil {
		return APIResponse{}, nil
	}

	if resp.StatusCode != 200 {
		return rsp, errors.New(http.StatusText(resp.StatusCode))
	}
	return rsp, nil
}

// This function helps send messages to users
// It takes Message / GenericTemplate / ButtonTemplate / ReceiptTemplate and
// sends it to the user
func (bot *BotAPI) Send(u User, c interface{}, notif string) (APIResponse, error) {
	var r Request

	n := RegularNotif
	if notif != "" {
		n = notif
	}

	switch c.(type) {
	case Request:
		return APIResponse{}, errors.New("Use MakeRequest to send Request!!")
	case Message:
		r = Request{
			Recipient: u,
			Message:   c.(Message),
			NotifType: n,
		}

	case GenericTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(GenericTemplate),
				},
			},
		}

	case ButtonTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(ButtonTemplate),
				},
			},
		}

	case ReceiptTemplate:
		r = Request{
			Recipient: u,
			NotifType: n,
			Message: Message{
				Attachment: &Attachment{
					Type:    "template",
					Payload: c.(ReceiptTemplate),
				},
			},
		}

	default:
		return APIResponse{}, errors.New("Type is not supported")
	}

	if r == (Request{}) {
		return APIResponse{}, errors.New("Unknown Error")
	}
	payl, _ := json.Marshal(r)
	if bot.Debug {
		log.Printf("[INFO] Payload: %s", string(payl))
	}
	return bot.MakeRequest(bytes.NewBuffer(payl))
}

// This helps to send local images (currently) to users
// TODO: not tested yet!
func (bot *BotAPI) SendFile(u User, path string) (APIResponse, error) {
	file, err := os.Open(path)
	if err != nil {
		return APIResponse{}, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile("filedata", filepath.Base(path))
	if err != nil {
		return APIResponse{}, err
	}
	_, err = io.Copy(part, file)

	usr, _ := json.Marshal(u)
	_ = writer.WriteField("recipient", string(usr))
	img := NewImageMessage("")
	im, _ := json.Marshal(img)
	_ = writer.WriteField("message", string(im))

	err = writer.Close()
	if err != nil {
		return APIResponse{}, err
	}

	return bot.MakeRequest(body)
}

// This function registers the handlers for
// - webhook verification
// - all callbacks made on the webhhoks
// It loops over all entries in the callback and
// pushes to the Callback channel
// This also return a *http.ServeMux which can be used to listenAndServe
func (bot *BotAPI) SetWebhook(pattern string) (<-chan Callback, *http.ServeMux) {
	callbackChan := make(chan Callback, 100)

	mux := http.NewServeMux()
	mux.HandleFunc(pattern, func(w http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			if req.FormValue("hub.verify_token") == bot.VerifyToken {
				w.Write([]byte(req.FormValue("hub.challenge")))
				return
			}
			w.WriteHeader(http.StatusUnauthorized)
			return

		case "POST":
			defer req.Body.Close()

			var rsp Response
			if bot.Debug {
				body, _ := ioutil.ReadAll(req.Body)
				log.Printf("[INFO]%s", body)
			}
			decoder := json.NewDecoder(req.Body)
			decoder.Decode(&rsp)

			if rsp.Object == "page" {
				for _, e := range rsp.Entries {
					for _, c := range e.Messaging {
						callbackChan <- c
					}
				}
			}
			w.WriteHeader(http.StatusOK)
			return

		default:
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
	})

	return callbackChan, mux

}
<|endoftext|>


<commit_before>package jira

import (
	"fmt"
	"github.com/trivago/tgo/tcontainer"
	"strings"
)

// CreateMeta contains information about fields and their attributed to create a ticket.
type CreateMetaInfo struct {
	Expand   string         `json:"expand,omitempty"`
	Projects []*MetaProject `json:"projects,omitempty"`
}

// MetaProject is the meta information about a project returned from createmeta api
type MetaProject struct {
	Expand string `json:"expand,omitempty"`
	Self   string `json:"self, omitempty"`
	Id     string `json:"id,omitempty"`
	Key    string `json:"key,omitempty"`
	Name   string `json:"name,omitempty"`
	// omitted avatarUrls
	IssueTypes []*MetaIssueTypes `json:"issuetypes,omitempty"`
}

// metaIssueTypes represents the different issue types a project has.
//
// Note: Fields is interface because this is an object which can
// have arbitraty keys related to customfields. It is not possible to
// expect these for a general way. This will be returning a map.
// Further processing must be done depending on what is required.
type MetaIssueTypes struct {
	Self        string                `json:"expand,omitempty"`
	Id          string                `json:"id,omitempty"`
	Description string                `json:"description,omitempty"`
	IconUrl     string                `json:"iconurl,omitempty"`
	Name        string                `json:"name,omitempty"`
	Subtasks    bool                  `json:"subtask,omitempty"`
	Expand      string                `json:"expand,omitempty"`
	Fields      tcontainer.MarshalMap `json:"fields,omitempty"`
}

// GetCreateMeta makes the api call to get the meta information required to create a ticket
func (s *IssueService) GetCreateMeta(projectkey string) (*CreateMetaInfo, *Response, error) {

	apiEndpoint := fmt.Sprintf("/rest/api/2/issue/createmeta?projectKeys=%s&expand=projects.issuetypes.fields", projectkey)

	req, err := s.client.NewRequest("GET", apiEndpoint, nil)
	if err != nil {
		return nil, nil, err
	}
	fmt.Println(req.URL)
	meta := new(CreateMetaInfo)
	resp, err := s.client.Do(req, meta)

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

	return meta, resp, nil
}

// GetProjectWithName returns a project with "name" from the meta information recieved. If not found, this returns nil.
// The comparision of the name is case insensitive.
func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject {
	for _, m := range m.Projects {
		if strings.ToLower(m.Name) == strings.ToLower(name) {
			return m
		}
	}
	return nil
}

// GetIssueWithName returns an IssueType with name from a given MetaProject. If not found, this returns nil.
// The comparision of the name is case insensitive
func (p *MetaProject) GetIssueTypeWithName(name string) *MetaIssueTypes {
	for _, m := range p.IssueTypes {
		if strings.ToLower(m.Name) == strings.ToLower(name) {
			return m
		}
	}
	return nil
}

// GetMandatoryFields returns a map of all the required fields from the MetaIssueTypes.
// if a frield returned by the api was:
// "customfield_10806": {
//					"required": true,
//					"schema": {
//						"type": "any",
//						"custom": "com.pyxis.greenhopper.jira:gh-epic-link",
//						"customId": 10806
//					},
//					"name": "Epic Link",
//					"hasDefaultValue": false,
//					"operations": [
//						"set"
//					]
//				}
// the returned map would have "Epic Link" as the key and "customfield_10806" as value.
// This choice has been made so that the it is easier to generate the create api request later.
func (t *MetaIssueTypes) GetMandatoryFields() (map[string]string, error) {
	ret := make(map[string]string)
	for key, _ := range t.Fields {
		required, err := t.Fields.Bool(key + "/required")
		if err != nil {
			return nil, err
		}
		if required {
			name, err := t.Fields.String(key + "/name")
			if err != nil {
				return nil, err
			}
			ret[name] = key
		}
	}
	return ret, nil
}

// GetAllFields returns a map of all the fields for an IssueType. This includes all required and not required.
// The key of the returned map is what you see in the form and the value is how it is representated in the jira schema.
func (t *MetaIssueTypes) GetAllFields() (map[string]string, error) {
	ret := make(map[string]string)
	for key, _ := range t.Fields {

		name, err := t.Fields.String(key + "/name")
		if err != nil {
			return nil, err
		}
		ret[name] = key
	}
	return ret, nil
}
<commit_msg>Rename MetaIssueTypes to MetaIssueType<commit_after>package jira

import (
	"fmt"
	"github.com/trivago/tgo/tcontainer"
	"strings"
)

// CreateMeta contains information about fields and their attributed to create a ticket.
type CreateMetaInfo struct {
	Expand   string         `json:"expand,omitempty"`
	Projects []*MetaProject `json:"projects,omitempty"`
}

// MetaProject is the meta information about a project returned from createmeta api
type MetaProject struct {
	Expand string `json:"expand,omitempty"`
	Self   string `json:"self, omitempty"`
	Id     string `json:"id,omitempty"`
	Key    string `json:"key,omitempty"`
	Name   string `json:"name,omitempty"`
	// omitted avatarUrls
	IssueTypes []*MetaIssueType `json:"issuetypes,omitempty"`
}

// metaIssueTypes represents the different issue types a project has.
//
// Note: Fields is interface because this is an object which can
// have arbitraty keys related to customfields. It is not possible to
// expect these for a general way. This will be returning a map.
// Further processing must be done depending on what is required.
type MetaIssueType struct {
	Self        string                `json:"expand,omitempty"`
	Id          string                `json:"id,omitempty"`
	Description string                `json:"description,omitempty"`
	IconUrl     string                `json:"iconurl,omitempty"`
	Name        string                `json:"name,omitempty"`
	Subtasks    bool                  `json:"subtask,omitempty"`
	Expand      string                `json:"expand,omitempty"`
	Fields      tcontainer.MarshalMap `json:"fields,omitempty"`
}

// GetCreateMeta makes the api call to get the meta information required to create a ticket
func (s *IssueService) GetCreateMeta(projectkey string) (*CreateMetaInfo, *Response, error) {

	apiEndpoint := fmt.Sprintf("/rest/api/2/issue/createmeta?projectKeys=%s&expand=projects.issuetypes.fields", projectkey)

	req, err := s.client.NewRequest("GET", apiEndpoint, nil)
	if err != nil {
		return nil, nil, err
	}
	fmt.Println(req.URL)
	meta := new(CreateMetaInfo)
	resp, err := s.client.Do(req, meta)

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

	return meta, resp, nil
}

// GetProjectWithName returns a project with "name" from the meta information recieved. If not found, this returns nil.
// The comparision of the name is case insensitive.
func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject {
	for _, m := range m.Projects {
		if strings.ToLower(m.Name) == strings.ToLower(name) {
			return m
		}
	}
	return nil
}

// GetIssueWithName returns an IssueType with name from a given MetaProject. If not found, this returns nil.
// The comparision of the name is case insensitive
func (p *MetaProject) GetIssueTypeWithName(name string) *MetaIssueType {
	for _, m := range p.IssueTypes {
		if strings.ToLower(m.Name) == strings.ToLower(name) {
			return m
		}
	}
	return nil
}

// GetMandatoryFields returns a map of all the required fields from the MetaIssueTypes.
// if a frield returned by the api was:
// "customfield_10806": {
//					"required": true,
//					"schema": {
//						"type": "any",
//						"custom": "com.pyxis.greenhopper.jira:gh-epic-link",
//						"customId": 10806
//					},
//					"name": "Epic Link",
//					"hasDefaultValue": false,
//					"operations": [
//						"set"
//					]
//				}
// the returned map would have "Epic Link" as the key and "customfield_10806" as value.
// This choice has been made so that the it is easier to generate the create api request later.
func (t *MetaIssueType) GetMandatoryFields() (map[string]string, error) {
	ret := make(map[string]string)
	for key, _ := range t.Fields {
		required, err := t.Fields.Bool(key + "/required")
		if err != nil {
			return nil, err
		}
		if required {
			name, err := t.Fields.String(key + "/name")
			if err != nil {
				return nil, err
			}
			ret[name] = key
		}
	}
	return ret, nil
}

// GetAllFields returns a map of all the fields for an IssueType. This includes all required and not required.
// The key of the returned map is what you see in the form and the value is how it is representated in the jira schema.
func (t *MetaIssueType) GetAllFields() (map[string]string, error) {
	ret := make(map[string]string)
	for key, _ := range t.Fields {

		name, err := t.Fields.String(key + "/name")
		if err != nil {
			return nil, err
		}
		ret[name] = key
	}
	return ret, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/lambrospetrou/gomicroblog/auth"
	"github.com/lambrospetrou/gomicroblog/gen"
	"github.com/lambrospetrou/gomicroblog/view"
	"net/http"
	"regexp"
	"runtime"
	"time"
)

var validPath = regexp.MustCompile("^/blog/(view|edit|save|del)/([a-zA-Z0-9_-]+)$")

// BLOG HANDLERS
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r, m[2])
	}
}

// show all posts
func rootHandler(w http.ResponseWriter, r *http.Request) {
	//fmt.Fprintf(w, "Hi there, I love you %s\n", r.URL.Path)
	/*
		posts, err := LoadAllBlogPosts()
		if err != nil {
			http.Error(w, "Could not load blog posts", http.StatusInternalServerError)
			return
		}
	*/
	bundle := &view.TemplateBundleIndex{
		Footer: &view.FooterStruct{Year: time.Now().Year()},
		Header: &view.HeaderStruct{Title: "All posts"},
		//Posts:  posts,
		Posts: nil,
	}
	view.Render(w, "index", bundle)
}

func main() {
	fmt.Println("Go Microblog service started!")

	// use all the available cores
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Blog endpoints
	http.HandleFunc("/gen-site", auth.BasicHandler(gen.GenerateHandler))
	http.HandleFunc("/", rootHandler)

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/s/", http.StripPrefix("/s/", fs))

	http.ListenAndServe(":40080", nil)

}
<commit_msg>added logging for the server<commit_after>package main

import (
	"fmt"
	"github.com/lambrospetrou/gomicroblog/auth"
	"github.com/lambrospetrou/gomicroblog/gen"
	"github.com/lambrospetrou/gomicroblog/view"
	"log"
	"net/http"
	"regexp"
	"runtime"
	"time"
)

var validPath = regexp.MustCompile("^/blog/(view|edit|save|del)/([a-zA-Z0-9_-]+)$")

// BLOG HANDLERS
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r, m[2])
	}
}

// show all posts
func rootHandler(w http.ResponseWriter, r *http.Request) {
	//fmt.Fprintf(w, "Hi there, I love you %s\n", r.URL.Path)
	/*
		posts, err := LoadAllBlogPosts()
		if err != nil {
			http.Error(w, "Could not load blog posts", http.StatusInternalServerError)
			return
		}
	*/
	bundle := &view.TemplateBundleIndex{
		Footer: &view.FooterStruct{Year: time.Now().Year()},
		Header: &view.HeaderStruct{Title: "All posts"},
		//Posts:  posts,
		Posts: nil,
	}
	view.Render(w, "index", bundle)
}

func main() {
	fmt.Println("Go Microblog service started!")

	// use all the available cores
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Blog endpoints
	http.HandleFunc("/gen-site", auth.BasicHandler(gen.GenerateHandler))
	http.HandleFunc("/", rootHandler)

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/s/", http.StripPrefix("/s/", fs))

	log.Fatal(http.ListenAndServe(":40080", nil))

}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package test

import (
	"github.com/bboozzoo/q3stats/store"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/pkg/errors"
	"testing"
)

type DB struct {
	db *gorm.DB
}

func (d *DB) Open() error {
	db, err := gorm.Open("sqlite3", ":memory:")
	if err != nil {
		return errors.Wrap(err, "failed to open DB")
	}

	d.db = db

	return nil
}

func (d *DB) Conn() *gorm.DB {
	return d.db
}

func (d *DB) Close() {
	if d.db != nil {
		d.db.Close()
	}
}

func GetStore(t *testing.T) store.DB {
	db := &DB{}

	if err := db.Open(); err != nil {
		t.Fatalf("failed to open DB: %s", err)
	}
	return db
}
<commit_msg>models/test/store: implement connectable and transactional interfaces<commit_after>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package test

import (
	"github.com/bboozzoo/q3stats/store"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/pkg/errors"
	"testing"
)

type DB struct {
	db *gorm.DB
}

func (d *DB) Open() error {
	db, err := gorm.Open("sqlite3", ":memory:")
	if err != nil {
		return errors.Wrap(err, "failed to open DB")
	}

	d.db = db

	return nil
}

func (d *DB) Conn() *gorm.DB {
	return d.db
}

func (d *DB) Close() {
	if d.db != nil {
		d.db.Close()
	}
}

func GetStore(t *testing.T) store.DB {
	db := &DB{}

	if err := db.Open(); err != nil {
		t.Fatalf("failed to open DB: %s", err)
	}
	return db
}

func (d *DB) Begin() store.DBTransaction {
	return &dbTx{
		db: d.db.Begin(),
	}
}

type dbTx struct {
	db *gorm.DB
}

func (dbt *dbTx) Conn() *gorm.DB {
	return dbt.db
}

func (dbt *dbTx) Commit() {
	dbt.db.Commit()
}
<|endoftext|>


<commit_before>package elk

import (
	"errors"
	// "fmt"
	"io"
	"io/ioutil"
	// "log/syslog"
	"net"
	"os"
	"strings"
	// "time"
	"encoding/json"

	"github.com/delectable/logspout/router"
)

var HOSTNAME string

func init() {
	router.AdapterFactories.Register(NewElkAdapter, "elk")

	hostname_bytestring, _ := ioutil.ReadFile("/etc/hostname")
	HOSTNAME = strings.TrimSpace(string(hostname_bytestring))

}

func getopt(name, dfault string) string {
	value := os.Getenv(name)
	if value == "" {
		value = dfault
	}
	return value
}

func NewElkAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &ElkAdapter{
		route: route,
		conn:  conn,
	}, nil
}

type ElkAdapter struct {
	conn  net.Conn
	route *router.Route
}

func (adapter *ElkAdapter) Stream(logstream chan *router.Message) {
	for message := range logstream {
		elkMessage := NewElkMessage(message)
		io.WriteString(adapter.conn, elkMessage.ToString())
	}
}

type ElkMessage struct {
	routerMessage *router.Message
	Object        struct {
		Time     int64  `json: "time"`
		Message  string `json: "message"`
		Hostname string `json: "hostname"`
		Image    string `json: "image"`
		App      string `json: "app"`
		Env      string `json: "env"`
	}
}

func NewElkMessage(routerMessage *router.Message) *ElkMessage {
	elkMessage := &ElkMessage{
		routerMessage: routerMessage,
	}

	elkMessage.Object.Time = routerMessage.Time.Unix()
	elkMessage.Object.Message = routerMessage.Data

	elkMessage.Object.Hostname = HOSTNAME
	elkMessage.Object.Hostname = getopt("ENV", "development")

	elkMessage.Object.Image = routerMessage.Container.Config.Image

	env_map := make(map[string]string)
	for _, blob := range routerMessage.Container.Config.Env {
		split_blob := strings.Split(blob, "=")
		env_map[split_blob[0]] = split_blob[1]
	}

	elkMessage.Object.App = env_map["MARATHON_APP_ID"][1:] // Marathon, for some reason, prepends MARATHON_APP_ID with a '/'

	return elkMessage
}

func (elkMessage *ElkMessage) ToString() string {
	return_string, _ := json.Marshal(elkMessage.Object)
	return string(return_string)
}
<commit_msg>Hostname -> Env<commit_after>package elk

import (
	"errors"
	// "fmt"
	"io"
	"io/ioutil"
	// "log/syslog"
	"net"
	"os"
	"strings"
	// "time"
	"encoding/json"

	"github.com/delectable/logspout/router"
)

var HOSTNAME string

func init() {
	router.AdapterFactories.Register(NewElkAdapter, "elk")

	hostname_bytestring, _ := ioutil.ReadFile("/etc/hostname")
	HOSTNAME = strings.TrimSpace(string(hostname_bytestring))

}

func getopt(name, dfault string) string {
	value := os.Getenv(name)
	if value == "" {
		value = dfault
	}
	return value
}

func NewElkAdapter(route *router.Route) (router.LogAdapter, error) {
	transport, found := router.AdapterTransports.Lookup(route.AdapterTransport("udp"))
	if !found {
		return nil, errors.New("unable to find adapter: " + route.Adapter)
	}

	conn, err := transport.Dial(route.Address, route.Options)
	if err != nil {
		return nil, err
	}

	return &ElkAdapter{
		route: route,
		conn:  conn,
	}, nil
}

type ElkAdapter struct {
	conn  net.Conn
	route *router.Route
}

func (adapter *ElkAdapter) Stream(logstream chan *router.Message) {
	for message := range logstream {
		elkMessage := NewElkMessage(message)
		io.WriteString(adapter.conn, elkMessage.ToString())
	}
}

type ElkMessage struct {
	routerMessage *router.Message
	Object        struct {
		Time     int64  `json: "time"`
		Message  string `json: "message"`
		Hostname string `json: "hostname"`
		Image    string `json: "image"`
		App      string `json: "app"`
		Env      string `json: "env"`
	}
}

func NewElkMessage(routerMessage *router.Message) *ElkMessage {
	elkMessage := &ElkMessage{
		routerMessage: routerMessage,
	}

	elkMessage.Object.Time = routerMessage.Time.Unix()
	elkMessage.Object.Message = routerMessage.Data

	elkMessage.Object.Hostname = HOSTNAME
	elkMessage.Object.Env = getopt("ENV", "development")

	elkMessage.Object.Image = routerMessage.Container.Config.Image

	env_map := make(map[string]string)
	for _, blob := range routerMessage.Container.Config.Env {
		split_blob := strings.Split(blob, "=")
		env_map[split_blob[0]] = split_blob[1]
	}

	elkMessage.Object.App = env_map["MARATHON_APP_ID"][1:] // Marathon, for some reason, prepends MARATHON_APP_ID with a '/'

	return elkMessage
}

func (elkMessage *ElkMessage) ToString() string {
	return_string, _ := json.Marshal(elkMessage.Object)
	return string(return_string)
}
<|endoftext|>