<commit_before>// Copyright 2015 The go-python 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 main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func gopyMakeCmdBind() *commander.Command {
	cmd := &commander.Command{
		Run:       gopyRunCmdBind,
		UsageLine: "bind <go-package-name>",
		Short:     "generate and compile (C)Python language bindings for Go",
		Long: `
bind generates and compiles (C)Python language bindings for a Go package.

ex:
 $ gopy bind [options] <go-package-name>
 $ gopy bind github.com/go-python/gopy/_examples/hi
`,
		Flag: *flag.NewFlagSet("gopy-bind", flag.ExitOnError),
	}

	cmd.Flag.String("lang", defaultPyVersion, "python version to use for bindings (python2|py2|python3|py3)")
	cmd.Flag.String("output", "", "output directory for bindings")
	return cmd
}

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

	if len(args) != 1 {
		log.Printf("expect a fully qualified go package name as argument\n")
		return fmt.Errorf(
			"gopy-bind: expect a fully qualified go package name as argument",
		)
	}

	odir := cmdr.Flag.Lookup("output").Value.Get().(string)
	lang := cmdr.Flag.Lookup("lang").Value.Get().(string)

	cwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	if odir == "" {
		odir = cwd
	} else {
		err = os.MkdirAll(odir, 0755)
		if err != nil {
			return fmt.Errorf(
				"gopy-bind: could not create output directory: %v\n", err,
			)
		}
	}
	odir, err = filepath.Abs(odir)
	if err != nil {
		return err
	}

	path := args[0]
	pkg, err := newPackage(path)
	if err != nil {
		return fmt.Errorf(
			"gopy-bind: go/build.Import failed with path=%q: %v\n",
			path,
			err,
		)
	}

	// go-get it to tickle the GOPATH cache (and make sure it compiles
	// correctly)
	cmd := exec.Command(
		"go", "get", pkg.ImportPath(),
	)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		return err
	}

	work, err := ioutil.TempDir("", "gopy-")
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create temp-workdir (%v)", err)
	}
	log.Printf("work: %s\n", work)

	err = os.MkdirAll(work, 0644)
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create workdir (%v)", err)
	}
	//defer os.RemoveAll(work)

	err = genPkg(work, pkg, lang)
	if err != nil {
		return err
	}

	err = genPkg(work, pkg, "go")
	if err != nil {
		return err
	}

	wbind, err := ioutil.TempDir("", "gopy-")
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create temp-workdir (%v)", err)
	}

	err = os.MkdirAll(wbind, 0644)
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create workdir (%v)", err)
	}
	defer os.RemoveAll(wbind)

	buildname := pkg.Name()
	switch lang {
	case "cffi":
		/*
			Since Python importing module priority is XXXX.so > XXXX.py,
			We need to change shared module name from  'XXXX.so' to '_XXXX.so'.
			As the result, an user can import XXXX.py.
		*/
		buildname = "_" + buildname
		cmd = exec.Command(
			"go", "build", "-buildmode=c-shared",
			"-o", filepath.Join(wbind, buildname)+".so",
			".",
		)
		cmd.Dir = work
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(wbind, buildname)+".so",
			filepath.Join(odir, buildname)+".so",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(work, pkg.Name())+".py",
			filepath.Join(odir, pkg.Name())+".py",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}

	case "python2", "py2":
		cmd = exec.Command(
			"go", "build", "-buildmode=c-shared",
			"-o", filepath.Join(wbind, buildname)+".so",
			".",
		)
		cmd.Dir = work
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(wbind, buildname)+".so",
			filepath.Join(odir, buildname)+".so",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}
	case "python3", "py3":
		return fmt.Errorf("gopy: python-3 support not yet implemented")
	default:
		return fmt.Errorf("unknown target language: %q\n", lang)
	}
	return err
}
<commit_msg>bind: add support for symbol removal<commit_after>// Copyright 2015 The go-python 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 main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func gopyMakeCmdBind() *commander.Command {
	cmd := &commander.Command{
		Run:       gopyRunCmdBind,
		UsageLine: "bind <go-package-name>",
		Short:     "generate and compile (C)Python language bindings for Go",
		Long: `
bind generates and compiles (C)Python language bindings for a Go package.

ex:
 $ gopy bind [options] <go-package-name>
 $ gopy bind github.com/go-python/gopy/_examples/hi
`,
		Flag: *flag.NewFlagSet("gopy-bind", flag.ExitOnError),
	}

	cmd.Flag.String("lang", defaultPyVersion, "python version to use for bindings (python2|py2|python3|py3)")
	cmd.Flag.String("output", "", "output directory for bindings")
	cmd.Flag.Bool("symbols", true, "include symbols in output")
	return cmd
}

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

	if len(args) != 1 {
		log.Printf("expect a fully qualified go package name as argument\n")
		return fmt.Errorf(
			"gopy-bind: expect a fully qualified go package name as argument",
		)
	}

	odir := cmdr.Flag.Lookup("output").Value.Get().(string)
	lang := cmdr.Flag.Lookup("lang").Value.Get().(string)
	symbols := cmdr.Flag.Lookup("symbols").Value.Get().(bool)

	cwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	if odir == "" {
		odir = cwd
	} else {
		err = os.MkdirAll(odir, 0755)
		if err != nil {
			return fmt.Errorf(
				"gopy-bind: could not create output directory: %v\n", err,
			)
		}
	}
	odir, err = filepath.Abs(odir)
	if err != nil {
		return err
	}

	path := args[0]
	pkg, err := newPackage(path)
	if err != nil {
		return fmt.Errorf(
			"gopy-bind: go/build.Import failed with path=%q: %v\n",
			path,
			err,
		)
	}

	// go-get it to tickle the GOPATH cache (and make sure it compiles
	// correctly)
	cmd := exec.Command(
		"go", "get", pkg.ImportPath(),
	)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Run()
	if err != nil {
		return err
	}

	work, err := ioutil.TempDir("", "gopy-")
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create temp-workdir (%v)", err)
	}
	log.Printf("work: %s\n", work)

	err = os.MkdirAll(work, 0644)
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create workdir (%v)", err)
	}
	//defer os.RemoveAll(work)

	err = genPkg(work, pkg, lang)
	if err != nil {
		return err
	}

	err = genPkg(work, pkg, "go")
	if err != nil {
		return err
	}

	wbind, err := ioutil.TempDir("", "gopy-")
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create temp-workdir (%v)", err)
	}

	err = os.MkdirAll(wbind, 0644)
	if err != nil {
		return fmt.Errorf("gopy-bind: could not create workdir (%v)", err)
	}
	defer os.RemoveAll(wbind)

	buildname := pkg.Name()
	switch lang {
	case "cffi":
		/*
			Since Python importing module priority is XXXX.so > XXXX.py,
			We need to change shared module name from  'XXXX.so' to '_XXXX.so'.
			As the result, an user can import XXXX.py.
		*/
		buildname = "_" + buildname
		cmd = getBuildCommand(wbind, buildname, work, symbols)
		err = cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(wbind, buildname)+".so",
			filepath.Join(odir, buildname)+".so",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(work, pkg.Name())+".py",
			filepath.Join(odir, pkg.Name())+".py",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}

	case "python2", "py2":
		cmd = getBuildCommand(wbind, buildname, work, symbols)
		err = cmd.Run()
		if err != nil {
			return err
		}

		cmd = exec.Command(
			"/bin/cp",
			filepath.Join(wbind, buildname)+".so",
			filepath.Join(odir, buildname)+".so",
		)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return err
		}
	case "python3", "py3":
		return fmt.Errorf("gopy: python-3 support not yet implemented")
	default:
		return fmt.Errorf("unknown target language: %q\n", lang)
	}
	return err
}

func getBuildCommand(wbind string, buildname string, work string, symbols bool) (cmd *exec.Cmd) {
	args := []string{"build", "-buildmode=c-shared"}
	if !symbols {
		// These flags will omit the various symbol tables, thereby
		// reducing the final size of the binary. From https://golang.org/cmd/link/
		// -s Omit the symbol table and debug information
		// -w Omit the DWARF symbol table
		args = append(args, "-ldflags=-s -w")
	}
	args = append(args, "-o", filepath.Join(wbind, buildname)+".so", ".")
	cmd = exec.Command(
		"go", args...,
	)
	cmd.Dir = work
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/jlisee/cbd"
)

// Hold information about each command
type Command struct {
	fn    func()   // Function to execute
	help  string   // Help text to display to the user
	flags []string // The list of flags this command takes
	alias bool     // When true it's an alias for another
}

// Return true if the command uses this flag
func (c Command) hasFlag(flag string) bool {
	for _, v := range c.flags {
		if v == flag {
			return true
		}
	}
	return false
}

// Print the program usage header
func printUsage() {
	fmt.Printf(`cbd is a distributed C/C++ build tool.

Usage:
	cbd command [arguments]
`)
}

// Print the help information for each command
func printCommandHelp(cmds map[string]Command) {
	// Basic usage
	printUsage()

	// Find the longest command for formatting purposes
	l := 0

	for name, cmd := range cmds {
		if !cmd.alias {
			nl := len(name)
			if nl > l {
				l = nl
			}
		}
	}

	// Form our format string
	f := "  %" + strconv.Itoa(l) + "s - %s\n"

	// Print our commands
	fmt.Printf("\nThe commands are:\n\n")
	for name, cmd := range cmds {
		if !cmd.alias {
			fmt.Printf(f, name, cmd.help)
		}
	}
}

func main() {
	// Input arguments
	port := new(uint)

	// Command map
	commands := make(map[string]Command)
	cmdsPointer := &commands

	cmdUpdate := map[string]Command{
		"server": {
			fn: func() {
				runServer(int(*port))
			},
			help:  "Run central scheduler",
			flags: []string{"port"},
		},
		"worker": {
			fn: func() {
				runWorker(int(*port))
			},
			help:  "Run build slave",
			flags: []string{"port"},
		},
		"monitor": {
			fn: func() {
				runMonitor()
			},
			help: "Run monitoring CLI",
		},
		"help": {
			fn: func() {
				printCommandHelp(*cmdsPointer)
			},
			help: "Display help information",
		},
	}

	// Add in our helpful command aliases
	helpAliases := []string{"-help", "-h", "--help"}

	aliasCmd := cmdUpdate["help"]
	aliasCmd.alias = true

	for _, name := range helpAliases {
		cmdUpdate[name] = aliasCmd
	}

	// Update our main command list
	for name, cmd := range cmdUpdate {
		commands[name] = cmd
	}

	// Pull of the first argument as our command.  Fall back on help if needed,
	// otherwise this is the compiler the user wants to run.  (later make this
	// a just a configuration setting)
	command := "help"

	// Grab our command then Shift the args down one, to ignore the first
	// command, if we don't do this the flag package basically ignores all
	// arguments
	if len(os.Args) > 1 {
		command = os.Args[1]

		if len(os.Args) > 1 {
			os.Args = os.Args[1:]
		}
	}

	// Attempt to lookup the command, if it's not in the map, we treat it as the
	// compiler
	cmd, ok := commands[command]

	if ok {
		if cmd.hasFlag("port") {
			flag.UintVar(port, "port", cbd.DefaultPort, "Port to listen on")
		}
		//flag.BoolVar(&server, "server", false, "Run as a server instead of worker")

		flag.Parse()

		// Now run our command
		cmd.fn()
	} else {
		// We have to parse the arguments manually because the default flag
		// package stops parsing after positional args, and
		// github.com/ogier/pflag errors out on unknown arguments.
		runCompiler(command, os.Args[1:])
	}
}

func runWorker(port int) {
	log.Print("Worker starting, port: ", port)

	// Listen on any address
	address := "0.0.0.0:" + strconv.FormatUint(uint64(port), 10)

	ln, err := net.Listen("tcp", address)
	if err != nil {
		log.Fatal(err)
	}

	saddr := os.Getenv("CBD_SERVER")

	w, err := cbd.NewWorker(port, saddr)
	if err != nil {
		log.Fatal(err)
	}

	w.Serve(ln)
}

func runServer(port int) {
	log.Print("Server starting, port: ", port)

	// Listen on any address
	address := ":" + strconv.FormatUint(uint64(port), 10)
	ln, err := net.Listen("tcp", address)
	if err != nil {
		log.Fatal(err)
	}

	s := cbd.NewServerState()

	s.Serve(ln)
}

func runMonitor() {
	log.Print("Monitor starting")

	// Make connection to server
	server := os.Getenv("CBD_SERVER")

	m := cbd.NewMonitor(server)
	for {
		err := m.Connect()

		// Keep trying until we get a connection
		if err != nil {
			fmt.Printf("Can't connect to: %s\n", err)
			time.Sleep(time.Duration(1) * time.Second)
			continue
		}

		// Go into an infinite reporting loop
		err = m.BasicReport()

		// A clear exit from report means we should do a graceful shutdown
		if err == nil {
			break
		}
	}
}

func runCompiler(compiler string, args []string) {
	// Parse compiler arguments
	b := cbd.ParseArgs(args)

	// Setup logging if needed
	logpath := os.Getenv("CBD_LOGFILE")

	if len(logpath) > 0 {
		// Open the log file for appending
		f, err := os.OpenFile(logpath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)

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

		defer f.Close()

		log.SetOutput(f)

		cbd.DebugLogging = true
	}

	// Dump arguments
	cbd.DebugPrint("ARGS: ", args)
	cbd.DebugPrintf("  Distribute?: %t", b.Distributable)
	cbd.DebugPrintf("  Output path:  %s[%d]\n", b.Output(), b.Oindex)
	cbd.DebugPrintf("  Input path:   %s[%d]\n", b.Input(), b.Iindex)

	// TODO: Add in a local compile fast past
	if b.Distributable {
		// Pre-process the file into a compile job
		job, results, err := cbd.MakeCompileJob(compiler, b)

		if err != nil {
			fmt.Print(string(results.Output))
			cbd.DebugPrint("Preprocess Error: ", string(results.Output))
			os.Exit(results.Return)
		}

		// See if we have a remote host defined
		cresults, err := cbd.ClientBuildJob(job)

		if err != nil || cresults.Return != 0 {
			fmt.Print(string(cresults.Output))
			cbd.DebugPrint("Build Error: ", string(cresults.Output))
			os.Exit(cresults.Return)
		}

		// Now write the results to right output location
		f, err := os.Create(b.Output())

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

		defer f.Close()

		_, err = f.Write(cresults.ObjectCode)

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

		cbd.DebugPrint("Remote Success")

	} else {
		results, err := cbd.RunCmd(compiler, args)

		if err != nil {
			fmt.Print(string(results.Output))
			cbd.DebugPrint("Local Error: ", string(results.Output))
			os.Exit(results.Return)
		}

		cbd.DebugPrint("Success")
	}

}
<commit_msg>Add a server command line argument to worker and monitor commands<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"time"

	"github.com/jlisee/cbd"
)

// Hold information about each command
type Command struct {
	fn    func()   // Function to execute
	help  string   // Help text to display to the user
	flags []string // The list of flags this command takes
	alias bool     // When true it's an alias for another
}

// Return true if the command uses this flag
func (c Command) hasFlag(flag string) bool {
	for _, v := range c.flags {
		if v == flag {
			return true
		}
	}
	return false
}

// Print the program usage header
func printUsage() {
	fmt.Printf(`cbd is a distributed C/C++ build tool.

Usage:
	cbd command [arguments]
`)
}

// Print the help information for each command
func printCommandHelp(cmds map[string]Command) {
	// Basic usage
	printUsage()

	// Find the longest command for formatting purposes
	l := 0

	for name, cmd := range cmds {
		if !cmd.alias {
			nl := len(name)
			if nl > l {
				l = nl
			}
		}
	}

	// Form our format string
	f := "  %" + strconv.Itoa(l) + "s - %s\n"

	// Print our commands
	fmt.Printf("\nThe commands are:\n\n")
	for name, cmd := range cmds {
		if !cmd.alias {
			fmt.Printf(f, name, cmd.help)
		}
	}
}

func main() {
	// Input arguments
	port := new(uint)
	server := new(string)

	// Command map
	commands := make(map[string]Command)
	cmdsPointer := &commands

	cmdUpdate := map[string]Command{
		"server": {
			fn: func() {
				runServer(int(*port))
			},
			help:  "Run central scheduler",
			flags: []string{"port"},
		},
		"worker": {
			fn: func() {
				runWorker(int(*port), *server)
			},
			help:  "Run build slave",
			flags: []string{"port", "server"},
		},
		"monitor": {
			fn: func() {
				runMonitor(*server)
			},
			help:  "Run monitoring CLI",
			flags: []string{"server"},
		},
		"help": {
			fn: func() {
				printCommandHelp(*cmdsPointer)
			},
			help: "Display help information",
		},
	}

	// Add in our helpful command aliases
	helpAliases := []string{"-help", "-h", "--help"}

	aliasCmd := cmdUpdate["help"]
	aliasCmd.alias = true

	for _, name := range helpAliases {
		cmdUpdate[name] = aliasCmd
	}

	// Update our main command list
	for name, cmd := range cmdUpdate {
		commands[name] = cmd
	}

	// Pull of the first argument as our command.  Fall back on help if needed,
	// otherwise this is the compiler the user wants to run.  (later make this
	// a just a configuration setting)
	command := "help"

	// Grab our command then Shift the args down one, to ignore the first
	// command, if we don't do this the flag package basically ignores all
	// arguments
	if len(os.Args) > 1 {
		command = os.Args[1]

		if len(os.Args) > 1 {
			os.Args = os.Args[1:]
		}
	}

	// Attempt to lookup the command, if it's not in the map, we treat it as the
	// compiler
	cmd, ok := commands[command]

	if ok {
		if cmd.hasFlag("port") {
			flag.UintVar(port, "port", cbd.DefaultPort, "Port to listen on")
		}
		if cmd.hasFlag("server") {
			defS := os.Getenv("CBD_SERVER")
			flag.StringVar(server, "server", defS, "Address of the server")
		}

		flag.Parse()

		// Now run our command
		cmd.fn()
	} else {
		// We have to parse the arguments manually because the default flag
		// package stops parsing after positional args, and
		// github.com/ogier/pflag errors out on unknown arguments.
		runCompiler(command, os.Args[1:])
	}
}

func runWorker(port int, saddr string) {
	log.Print("Worker starting, port: ", port)

	// Listen on any address
	address := "0.0.0.0:" + strconv.FormatUint(uint64(port), 10)

	ln, err := net.Listen("tcp", address)
	if err != nil {
		log.Fatal(err)
	}

	w, err := cbd.NewWorker(port, saddr)
	if err != nil {
		log.Fatal(err)
	}

	w.Serve(ln)
}

func runServer(port int) {
	log.Print("Server starting, port: ", port)

	// Listen on any address
	address := ":" + strconv.FormatUint(uint64(port), 10)
	ln, err := net.Listen("tcp", address)
	if err != nil {
		log.Fatal(err)
	}

	s := cbd.NewServerState()

	s.Serve(ln)
}

func runMonitor(server string) {
	log.Print("Monitor starting")

	// Make connection to server
	m := cbd.NewMonitor(server)
	for {
		err := m.Connect()

		// Keep trying until we get a connection
		if err != nil {
			fmt.Printf("Can't connect to: %s\n", err)
			time.Sleep(time.Duration(1) * time.Second)
			continue
		}

		// Go into an infinite reporting loop
		err = m.BasicReport()

		// A clear exit from report means we should do a graceful shutdown
		if err == nil {
			break
		}
	}
}

func runCompiler(compiler string, args []string) {
	// Parse compiler arguments
	b := cbd.ParseArgs(args)

	// Setup logging if needed
	logpath := os.Getenv("CBD_LOGFILE")

	if len(logpath) > 0 {
		// Open the log file for appending
		f, err := os.OpenFile(logpath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)

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

		defer f.Close()

		log.SetOutput(f)

		cbd.DebugLogging = true
	}

	// Dump arguments
	cbd.DebugPrint("ARGS: ", args)
	cbd.DebugPrintf("  Distribute?: %t", b.Distributable)
	cbd.DebugPrintf("  Output path:  %s[%d]\n", b.Output(), b.Oindex)
	cbd.DebugPrintf("  Input path:   %s[%d]\n", b.Input(), b.Iindex)

	// TODO: Add in a local compile fast past
	if b.Distributable {
		// Pre-process the file into a compile job
		job, results, err := cbd.MakeCompileJob(compiler, b)

		if err != nil {
			fmt.Print(string(results.Output))
			cbd.DebugPrint("Preprocess Error: ", string(results.Output))
			os.Exit(results.Return)
		}

		// See if we have a remote host defined
		cresults, err := cbd.ClientBuildJob(job)

		if err != nil || cresults.Return != 0 {
			fmt.Print(string(cresults.Output))
			cbd.DebugPrint("Build Error: ", string(cresults.Output))
			os.Exit(cresults.Return)
		}

		// Now write the results to right output location
		f, err := os.Create(b.Output())

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

		defer f.Close()

		_, err = f.Write(cresults.ObjectCode)

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

		cbd.DebugPrint("Remote Success")

	} else {
		results, err := cbd.RunCmd(compiler, args)

		if err != nil {
			fmt.Print(string(results.Output))
			cbd.DebugPrint("Local Error: ", string(results.Output))
			os.Exit(results.Return)
		}

		cbd.DebugPrint("Success")
	}

}
<|endoftext|>


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

// Package context defines the Context type, which carries deadlines,
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context.  The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it.  The Context should be the first
// parameter, typically named ctx:
//
// 	func DoSomething(ctx context.Context, arg Arg) error {
// 		// ... use ctx ...
// 	}
//
// Do not pass a nil Context, even if a function permits it.  Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The same Context may be passed to functions running in different goroutines;
// Contexts are safe for simultaneous use by multiple goroutines.
//
// See http://blog.golang.org/context for example code for a server that uses
// Contexts.
package context // import "golang.org/x/net/context"

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
	// Deadline returns the time when work done on behalf of this context
	// should be canceled.  Deadline returns ok==false when no deadline is
	// set.  Successive calls to Deadline return the same results.
	Deadline() (deadline time.Time, ok bool)

	// Done returns a channel that's closed when work done on behalf of this
	// context should be canceled.  Done may return nil if this context can
	// never be canceled.  Successive calls to Done return the same value.
	//
	// WithCancel arranges for Done to be closed when cancel is called;
	// WithDeadline arranges for Done to be closed when the deadline
	// expires; WithTimeout arranges for Done to be closed when the timeout
	// elapses.
	//
	// Done is provided for use in select statements:
	//
	// 	// DoSomething calls DoSomethingSlow and returns as soon as
	// 	// it returns or ctx.Done is closed.
	// 	func DoSomething(ctx context.Context) (Result, error) {
	// 		c := make(chan Result, 1)
	// 		go func() { c <- DoSomethingSlow(ctx) }()
	// 		select {
	// 		case res := <-c:
	// 			return res, nil
	// 		case <-ctx.Done():
	// 			return nil, ctx.Err()
	// 		}
	// 	}
	//
	// See http://blog.golang.org/pipelines for more examples of how to use
	// a Done channel for cancelation.
	Done() <-chan struct{}

	// Err returns a non-nil error value after Done is closed.  Err returns
	// Canceled if the context was canceled or DeadlineExceeded if the
	// context's deadline passed.  No other values for Err are defined.
	// After Done is closed, successive calls to Err return the same value.
	Err() error

	// Value returns the value associated with this context for key, or nil
	// if no value is associated with key.  Successive calls to Value with
	// the same key returns the same result.
	//
	// Use context values only for request-scoped data that transits
	// processes and API boundaries, not for passing optional parameters to
	// functions.
	//
	// A key identifies a specific value in a Context.  Functions that wish
	// to store values in Context typically allocate a key in a global
	// variable then use that key as the argument to context.WithValue and
	// Context.Value.  A key can be any type that supports equality;
	// packages should define keys as an unexported type to avoid
	// collisions.
	//
	// Packages that define a Context key should provide type-safe accessors
	// for the values stores using that key:
	//
	// 	// Package user defines a User type that's stored in Contexts.
	// 	package user
	//
	// 	import "golang.org/x/net/context"
	//
	// 	// User is the type of value stored in the Contexts.
	// 	type User struct {...}
	//
	// 	// key is an unexported type for keys defined in this package.
	// 	// This prevents collisions with keys defined in other packages.
	// 	type key int
	//
	// 	// userKey is the key for user.User values in Contexts.  It is
	// 	// unexported; clients use user.NewContext and user.FromContext
	// 	// instead of using this key directly.
	// 	var userKey key = 0
	//
	// 	// NewContext returns a new Context that carries value u.
	// 	func NewContext(ctx context.Context, u *User) context.Context {
	// 		return context.WithValue(ctx, userKey, u)
	// 	}
	//
	// 	// FromContext returns the User value stored in ctx, if any.
	// 	func FromContext(ctx context.Context) (*User, bool) {
	// 		u, ok := ctx.Value(userKey).(*User)
	// 		return u, ok
	// 	}
	Value(key interface{}) interface{}
}

// Canceled is the error returned by Context.Err when the context is canceled.
var Canceled = errors.New("context canceled")

// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var DeadlineExceeded = errors.New("context deadline exceeded")

// An emptyCtx is never canceled, has no values, and has no deadline.  It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int

func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
	return
}

func (*emptyCtx) Done() <-chan struct{} {
	return nil
}

func (*emptyCtx) Err() error {
	return nil
}

func (*emptyCtx) Value(key interface{}) interface{} {
	return nil
}

func (e *emptyCtx) String() string {
	switch e {
	case background:
		return "context.Background"
	case todo:
		return "context.TODO"
	}
	return "unknown empty Context"
}

var (
	background = new(emptyCtx)
	todo       = new(emptyCtx)
)

// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline.  It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
	return background
}

// TODO returns a non-nil, empty Context.  Code should use context.TODO when
// it's unclear which Context to use or it's is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter).  TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
	return todo
}

// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()

// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	propagateCancel(parent, &c)
	return &c, func() { c.cancel(true, Canceled) }
}

// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
	return cancelCtx{
		Context: parent,
		done:    make(chan struct{}),
	}
}

// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel(parent Context, child canceler) {
	if parent.Done() == nil {
		return // parent is never canceled
	}
	if p, ok := parentCancelCtx(parent); ok {
		p.mu.Lock()
		if p.err != nil {
			// parent has already been canceled
			child.cancel(false, p.err)
		} else {
			if p.children == nil {
				p.children = make(map[canceler]bool)
			}
			p.children[child] = true
		}
		p.mu.Unlock()
	} else {
		go func() {
			select {
			case <-parent.Done():
				child.cancel(false, parent.Err())
			case <-child.Done():
			}
		}()
	}
}

// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx.  This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
	for {
		switch c := parent.(type) {
		case *cancelCtx:
			return c, true
		case *timerCtx:
			return &c.cancelCtx, true
		case *valueCtx:
			parent = c.Context
		default:
			return nil, false
		}
	}
}

// A canceler is a context type that can be canceled directly.  The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
	cancel(removeFromParent bool, err error)
	Done() <-chan struct{}
}

// A cancelCtx can be canceled.  When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
	Context

	done chan struct{} // closed by the first cancel call.

	mu       sync.Mutex
	children map[canceler]bool // set to nil by the first cancel call
	err      error             // set to non-nil by the first cancel call
}

func (c *cancelCtx) Done() <-chan struct{} {
	return c.done
}

func (c *cancelCtx) Err() error {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.err
}

func (c *cancelCtx) String() string {
	return fmt.Sprintf("%v.WithCancel", c.Context)
}

// cancel closes c.done, cancels each of c's children, and, if
// removeFromParent is true, removes c from its parent's children.
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
	if err == nil {
		panic("context: internal error: missing cancel error")
	}
	c.mu.Lock()
	if c.err != nil {
		c.mu.Unlock()
		return // already canceled
	}
	c.err = err
	close(c.done)
	for child := range c.children {
		// NOTE: acquiring the child's lock while holding parent's lock.
		child.cancel(false, err)
	}
	c.children = nil
	c.mu.Unlock()

	if removeFromParent {
		if p, ok := parentCancelCtx(c.Context); ok {
			p.mu.Lock()
			if p.children != nil {
				delete(p.children, c)
			}
			p.mu.Unlock()
		}
	}
}

// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d.  If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent.  The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with the deadline
// timer, so code should call cancel as soon as the operations running in this
// Context complete.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
	if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
		// The current deadline is already sooner than the new one.
		return WithCancel(parent)
	}
	c := &timerCtx{
		cancelCtx: newCancelCtx(parent),
		deadline:  deadline,
	}
	propagateCancel(parent, c)
	d := deadline.Sub(time.Now())
	if d <= 0 {
		c.cancel(true, DeadlineExceeded) // deadline has already passed
		return c, func() { c.cancel(true, Canceled) }
	}
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.err == nil {
		c.timer = time.AfterFunc(d, func() {
			c.cancel(true, DeadlineExceeded)
		})
	}
	return c, func() { c.cancel(true, Canceled) }
}

// A timerCtx carries a timer and a deadline.  It embeds a cancelCtx to
// implement Done and Err.  It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
	cancelCtx
	timer *time.Timer // Under cancelCtx.mu.

	deadline time.Time
}

func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
	return c.deadline, true
}

func (c *timerCtx) String() string {
	return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
}

func (c *timerCtx) cancel(removeFromParent bool, err error) {
	c.cancelCtx.cancel(removeFromParent, err)
	c.mu.Lock()
	if c.timer != nil {
		c.timer.Stop()
		c.timer = nil
	}
	c.mu.Unlock()
}

// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with the deadline
// timer, so code should call cancel as soon as the operations running in this
// Context complete:
//
// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
// 		return slowOperation(ctx)
// 	}
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
	return WithDeadline(parent, time.Now().Add(timeout))
}

// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key interface{}, val interface{}) Context {
	return &valueCtx{parent, key, val}
}

// A valueCtx carries a key-value pair.  It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
	Context
	key, val interface{}
}

func (c *valueCtx) String() string {
	return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}

func (c *valueCtx) Value(key interface{}) interface{} {
	if c.key == key {
		return c.val
	}
	return c.Context.Value(key)
}
<commit_msg>net/context: Don't accept a context in the DoSomethingSlow example.<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package context defines the Context type, which carries deadlines,
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context.  The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it.  The Context should be the first
// parameter, typically named ctx:
//
// 	func DoSomething(ctx context.Context, arg Arg) error {
// 		// ... use ctx ...
// 	}
//
// Do not pass a nil Context, even if a function permits it.  Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The same Context may be passed to functions running in different goroutines;
// Contexts are safe for simultaneous use by multiple goroutines.
//
// See http://blog.golang.org/context for example code for a server that uses
// Contexts.
package context // import "golang.org/x/net/context"

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
	// Deadline returns the time when work done on behalf of this context
	// should be canceled.  Deadline returns ok==false when no deadline is
	// set.  Successive calls to Deadline return the same results.
	Deadline() (deadline time.Time, ok bool)

	// Done returns a channel that's closed when work done on behalf of this
	// context should be canceled.  Done may return nil if this context can
	// never be canceled.  Successive calls to Done return the same value.
	//
	// WithCancel arranges for Done to be closed when cancel is called;
	// WithDeadline arranges for Done to be closed when the deadline
	// expires; WithTimeout arranges for Done to be closed when the timeout
	// elapses.
	//
	// Done is provided for use in select statements:
	//
	// 	// CancelableOperation calls UncancelableOperation and returns as soon as
	// 	// it returns or ctx.Done is closed.
	// 	func CancelableOperation(ctx context.Context) (Result, error) {
	// 		c := make(chan Result, 1)
	// 		go func() { c <- UncancelableOperation() }()
	// 		select {
	// 		case res := <-c:
	// 			return res, nil
	// 		case <-ctx.Done():
	// 			return nil, ctx.Err()
	// 		}
	// 	}
	//
	// See http://blog.golang.org/pipelines for more examples of how to use
	// a Done channel for cancelation.
	Done() <-chan struct{}

	// Err returns a non-nil error value after Done is closed.  Err returns
	// Canceled if the context was canceled or DeadlineExceeded if the
	// context's deadline passed.  No other values for Err are defined.
	// After Done is closed, successive calls to Err return the same value.
	Err() error

	// Value returns the value associated with this context for key, or nil
	// if no value is associated with key.  Successive calls to Value with
	// the same key returns the same result.
	//
	// Use context values only for request-scoped data that transits
	// processes and API boundaries, not for passing optional parameters to
	// functions.
	//
	// A key identifies a specific value in a Context.  Functions that wish
	// to store values in Context typically allocate a key in a global
	// variable then use that key as the argument to context.WithValue and
	// Context.Value.  A key can be any type that supports equality;
	// packages should define keys as an unexported type to avoid
	// collisions.
	//
	// Packages that define a Context key should provide type-safe accessors
	// for the values stores using that key:
	//
	// 	// Package user defines a User type that's stored in Contexts.
	// 	package user
	//
	// 	import "golang.org/x/net/context"
	//
	// 	// User is the type of value stored in the Contexts.
	// 	type User struct {...}
	//
	// 	// key is an unexported type for keys defined in this package.
	// 	// This prevents collisions with keys defined in other packages.
	// 	type key int
	//
	// 	// userKey is the key for user.User values in Contexts.  It is
	// 	// unexported; clients use user.NewContext and user.FromContext
	// 	// instead of using this key directly.
	// 	var userKey key = 0
	//
	// 	// NewContext returns a new Context that carries value u.
	// 	func NewContext(ctx context.Context, u *User) context.Context {
	// 		return context.WithValue(ctx, userKey, u)
	// 	}
	//
	// 	// FromContext returns the User value stored in ctx, if any.
	// 	func FromContext(ctx context.Context) (*User, bool) {
	// 		u, ok := ctx.Value(userKey).(*User)
	// 		return u, ok
	// 	}
	Value(key interface{}) interface{}
}

// Canceled is the error returned by Context.Err when the context is canceled.
var Canceled = errors.New("context canceled")

// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var DeadlineExceeded = errors.New("context deadline exceeded")

// An emptyCtx is never canceled, has no values, and has no deadline.  It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int

func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
	return
}

func (*emptyCtx) Done() <-chan struct{} {
	return nil
}

func (*emptyCtx) Err() error {
	return nil
}

func (*emptyCtx) Value(key interface{}) interface{} {
	return nil
}

func (e *emptyCtx) String() string {
	switch e {
	case background:
		return "context.Background"
	case todo:
		return "context.TODO"
	}
	return "unknown empty Context"
}

var (
	background = new(emptyCtx)
	todo       = new(emptyCtx)
)

// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline.  It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
	return background
}

// TODO returns a non-nil, empty Context.  Code should use context.TODO when
// it's unclear which Context to use or it's is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter).  TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
	return todo
}

// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()

// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
	c := newCancelCtx(parent)
	propagateCancel(parent, &c)
	return &c, func() { c.cancel(true, Canceled) }
}

// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
	return cancelCtx{
		Context: parent,
		done:    make(chan struct{}),
	}
}

// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel(parent Context, child canceler) {
	if parent.Done() == nil {
		return // parent is never canceled
	}
	if p, ok := parentCancelCtx(parent); ok {
		p.mu.Lock()
		if p.err != nil {
			// parent has already been canceled
			child.cancel(false, p.err)
		} else {
			if p.children == nil {
				p.children = make(map[canceler]bool)
			}
			p.children[child] = true
		}
		p.mu.Unlock()
	} else {
		go func() {
			select {
			case <-parent.Done():
				child.cancel(false, parent.Err())
			case <-child.Done():
			}
		}()
	}
}

// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx.  This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
	for {
		switch c := parent.(type) {
		case *cancelCtx:
			return c, true
		case *timerCtx:
			return &c.cancelCtx, true
		case *valueCtx:
			parent = c.Context
		default:
			return nil, false
		}
	}
}

// A canceler is a context type that can be canceled directly.  The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
	cancel(removeFromParent bool, err error)
	Done() <-chan struct{}
}

// A cancelCtx can be canceled.  When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
	Context

	done chan struct{} // closed by the first cancel call.

	mu       sync.Mutex
	children map[canceler]bool // set to nil by the first cancel call
	err      error             // set to non-nil by the first cancel call
}

func (c *cancelCtx) Done() <-chan struct{} {
	return c.done
}

func (c *cancelCtx) Err() error {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.err
}

func (c *cancelCtx) String() string {
	return fmt.Sprintf("%v.WithCancel", c.Context)
}

// cancel closes c.done, cancels each of c's children, and, if
// removeFromParent is true, removes c from its parent's children.
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
	if err == nil {
		panic("context: internal error: missing cancel error")
	}
	c.mu.Lock()
	if c.err != nil {
		c.mu.Unlock()
		return // already canceled
	}
	c.err = err
	close(c.done)
	for child := range c.children {
		// NOTE: acquiring the child's lock while holding parent's lock.
		child.cancel(false, err)
	}
	c.children = nil
	c.mu.Unlock()

	if removeFromParent {
		if p, ok := parentCancelCtx(c.Context); ok {
			p.mu.Lock()
			if p.children != nil {
				delete(p.children, c)
			}
			p.mu.Unlock()
		}
	}
}

// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d.  If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent.  The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with the deadline
// timer, so code should call cancel as soon as the operations running in this
// Context complete.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
	if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
		// The current deadline is already sooner than the new one.
		return WithCancel(parent)
	}
	c := &timerCtx{
		cancelCtx: newCancelCtx(parent),
		deadline:  deadline,
	}
	propagateCancel(parent, c)
	d := deadline.Sub(time.Now())
	if d <= 0 {
		c.cancel(true, DeadlineExceeded) // deadline has already passed
		return c, func() { c.cancel(true, Canceled) }
	}
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.err == nil {
		c.timer = time.AfterFunc(d, func() {
			c.cancel(true, DeadlineExceeded)
		})
	}
	return c, func() { c.cancel(true, Canceled) }
}

// A timerCtx carries a timer and a deadline.  It embeds a cancelCtx to
// implement Done and Err.  It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
	cancelCtx
	timer *time.Timer // Under cancelCtx.mu.

	deadline time.Time
}

func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
	return c.deadline, true
}

func (c *timerCtx) String() string {
	return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
}

func (c *timerCtx) cancel(removeFromParent bool, err error) {
	c.cancelCtx.cancel(removeFromParent, err)
	c.mu.Lock()
	if c.timer != nil {
		c.timer.Stop()
		c.timer = nil
	}
	c.mu.Unlock()
}

// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with the deadline
// timer, so code should call cancel as soon as the operations running in this
// Context complete:
//
// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
// 		return slowOperation(ctx)
// 	}
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
	return WithDeadline(parent, time.Now().Add(timeout))
}

// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key interface{}, val interface{}) Context {
	return &valueCtx{parent, key, val}
}

// A valueCtx carries a key-value pair.  It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
	Context
	key, val interface{}
}

func (c *valueCtx) String() string {
	return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}

func (c *valueCtx) Value(key interface{}) interface{} {
	if c.key == key {
		return c.val
	}
	return c.Context.Value(key)
}
<|endoftext|>


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

// Package firebase is the entry point to the Firebase Admin SDK. It provides functionality for initializing App
// instances, which serve as the central entities that provide access to various other Firebase services exposed
// from the SDK.
package firebase // import "firebase.google.com/go"

import (
	"context"
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"

	"cloud.google.com/go/firestore"
	"firebase.google.com/go/auth"
	"firebase.google.com/go/db"
	"firebase.google.com/go/iid"
	"firebase.google.com/go/internal"
	"firebase.google.com/go/messaging"
	"firebase.google.com/go/storage"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

var defaultAuthOverrides = make(map[string]interface{})

// Version of the Firebase Go Admin SDK.
const Version = "3.11.1"

// firebaseEnvName is the name of the environment variable with the Config.
const firebaseEnvName = "FIREBASE_CONFIG"

// An App holds configuration and state common to all Firebase services that are exposed from the SDK.
type App struct {
	authOverride     map[string]interface{}
	creds            *google.DefaultCredentials
	dbURL            string
	projectID        string
	serviceAccountID string
	storageBucket    string
	opts             []option.ClientOption
}

// Config represents the configuration used to initialize an App.
type Config struct {
	AuthOverride     *map[string]interface{} `json:"databaseAuthVariableOverride"`
	DatabaseURL      string                  `json:"databaseURL"`
	ProjectID        string                  `json:"projectId"`
	ServiceAccountID string                  `json:"serviceAccountId"`
	StorageBucket    string                  `json:"storageBucket"`
}

// Auth returns an instance of auth.Client.
func (a *App) Auth(ctx context.Context) (*auth.Client, error) {
	conf := &internal.AuthConfig{
		Creds:            a.creds,
		ProjectID:        a.projectID,
		Opts:             a.opts,
		ServiceAccountID: a.serviceAccountID,
		Version:          Version,
	}
	return auth.NewClient(ctx, conf)
}

// Database returns an instance of db.Client to interact with the default Firebase Database
// configured via Config.DatabaseURL.
func (a *App) Database(ctx context.Context) (*db.Client, error) {
	return a.DatabaseWithURL(ctx, a.dbURL)
}

// DatabaseWithURL returns an instance of db.Client to interact with the Firebase Database
// identified by the given URL.
func (a *App) DatabaseWithURL(ctx context.Context, url string) (*db.Client, error) {
	conf := &internal.DatabaseConfig{
		AuthOverride: a.authOverride,
		URL:          url,
		Opts:         a.opts,
		Version:      Version,
	}
	return db.NewClient(ctx, conf)
}

// Storage returns a new instance of storage.Client.
func (a *App) Storage(ctx context.Context) (*storage.Client, error) {
	conf := &internal.StorageConfig{
		Opts:   a.opts,
		Bucket: a.storageBucket,
	}
	return storage.NewClient(ctx, conf)
}

// Firestore returns a new firestore.Client instance from the https://godoc.org/cloud.google.com/go/firestore
// package.
func (a *App) Firestore(ctx context.Context) (*firestore.Client, error) {
	if a.projectID == "" {
		return nil, errors.New("project id is required to access Firestore")
	}
	return firestore.NewClient(ctx, a.projectID, a.opts...)
}

// InstanceID returns an instance of iid.Client.
func (a *App) InstanceID(ctx context.Context) (*iid.Client, error) {
	conf := &internal.InstanceIDConfig{
		ProjectID: a.projectID,
		Opts:      a.opts,
	}
	return iid.NewClient(ctx, conf)
}

// Messaging returns an instance of messaging.Client.
func (a *App) Messaging(ctx context.Context) (*messaging.Client, error) {
	conf := &internal.MessagingConfig{
		ProjectID: a.projectID,
		Opts:      a.opts,
		Version:   Version,
	}
	return messaging.NewClient(ctx, conf)
}

// NewApp creates a new App from the provided config and client options.
//
// If the client options contain a valid credential (a service account file, a refresh token
// file or an oauth2.TokenSource) the App will be authenticated using that credential. Otherwise,
// NewApp attempts to authenticate the App with Google application default credentials.
// If `config` is nil, the SDK will attempt to load the config options from the
// `FIREBASE_CONFIG` environment variable. If the value in it starts with a `{` it is parsed as a
// JSON object, otherwise it is assumed to be the name of the JSON file containing the options.
func NewApp(ctx context.Context, config *Config, opts ...option.ClientOption) (*App, error) {
	o := []option.ClientOption{option.WithScopes(internal.FirebaseScopes...)}
	o = append(o, opts...)
	creds, err := transport.Creds(ctx, o...)
	if err != nil {
		return nil, err
	}
	if config == nil {
		if config, err = getConfigDefaults(); err != nil {
			return nil, err
		}
	}

	var pid string
	if config.ProjectID != "" {
		pid = config.ProjectID
	} else if creds.ProjectID != "" {
		pid = creds.ProjectID
	} else {
		pid = os.Getenv("GOOGLE_CLOUD_PROJECT")
		if pid == "" {
			pid = os.Getenv("GCLOUD_PROJECT")
		}
	}

	ao := defaultAuthOverrides
	if config.AuthOverride != nil {
		ao = *config.AuthOverride
	}

	return &App{
		authOverride:     ao,
		creds:            creds,
		dbURL:            config.DatabaseURL,
		projectID:        pid,
		serviceAccountID: config.ServiceAccountID,
		storageBucket:    config.StorageBucket,
		opts:             o,
	}, nil
}

// getConfigDefaults reads the default config file, defined by the FIREBASE_CONFIG
// env variable, used only when options are nil.
func getConfigDefaults() (*Config, error) {
	fbc := &Config{}
	confFileName := os.Getenv(firebaseEnvName)
	if confFileName == "" {
		return fbc, nil
	}
	var dat []byte
	if confFileName[0] == byte('{') {
		dat = []byte(confFileName)
	} else {
		var err error
		if dat, err = ioutil.ReadFile(confFileName); err != nil {
			return nil, err
		}
	}
	if err := json.Unmarshal(dat, fbc); err != nil {
		return nil, err
	}

	// Some special handling necessary for db auth overrides
	var m map[string]interface{}
	if err := json.Unmarshal(dat, &m); err != nil {
		return nil, err
	}
	if ao, ok := m["databaseAuthVariableOverride"]; ok && ao == nil {
		// Auth overrides are explicitly set to null
		var nullMap map[string]interface{}
		fbc.AuthOverride = &nullMap
	}
	return fbc, nil
}
<commit_msg>Bumped version to 3.12.0 (#324)<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package firebase is the entry point to the Firebase Admin SDK. It provides functionality for initializing App
// instances, which serve as the central entities that provide access to various other Firebase services exposed
// from the SDK.
package firebase // import "firebase.google.com/go"

import (
	"context"
	"encoding/json"
	"errors"
	"io/ioutil"
	"os"

	"cloud.google.com/go/firestore"
	"firebase.google.com/go/auth"
	"firebase.google.com/go/db"
	"firebase.google.com/go/iid"
	"firebase.google.com/go/internal"
	"firebase.google.com/go/messaging"
	"firebase.google.com/go/storage"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

var defaultAuthOverrides = make(map[string]interface{})

// Version of the Firebase Go Admin SDK.
const Version = "3.12.0"

// firebaseEnvName is the name of the environment variable with the Config.
const firebaseEnvName = "FIREBASE_CONFIG"

// An App holds configuration and state common to all Firebase services that are exposed from the SDK.
type App struct {
	authOverride     map[string]interface{}
	creds            *google.DefaultCredentials
	dbURL            string
	projectID        string
	serviceAccountID string
	storageBucket    string
	opts             []option.ClientOption
}

// Config represents the configuration used to initialize an App.
type Config struct {
	AuthOverride     *map[string]interface{} `json:"databaseAuthVariableOverride"`
	DatabaseURL      string                  `json:"databaseURL"`
	ProjectID        string                  `json:"projectId"`
	ServiceAccountID string                  `json:"serviceAccountId"`
	StorageBucket    string                  `json:"storageBucket"`
}

// Auth returns an instance of auth.Client.
func (a *App) Auth(ctx context.Context) (*auth.Client, error) {
	conf := &internal.AuthConfig{
		Creds:            a.creds,
		ProjectID:        a.projectID,
		Opts:             a.opts,
		ServiceAccountID: a.serviceAccountID,
		Version:          Version,
	}
	return auth.NewClient(ctx, conf)
}

// Database returns an instance of db.Client to interact with the default Firebase Database
// configured via Config.DatabaseURL.
func (a *App) Database(ctx context.Context) (*db.Client, error) {
	return a.DatabaseWithURL(ctx, a.dbURL)
}

// DatabaseWithURL returns an instance of db.Client to interact with the Firebase Database
// identified by the given URL.
func (a *App) DatabaseWithURL(ctx context.Context, url string) (*db.Client, error) {
	conf := &internal.DatabaseConfig{
		AuthOverride: a.authOverride,
		URL:          url,
		Opts:         a.opts,
		Version:      Version,
	}
	return db.NewClient(ctx, conf)
}

// Storage returns a new instance of storage.Client.
func (a *App) Storage(ctx context.Context) (*storage.Client, error) {
	conf := &internal.StorageConfig{
		Opts:   a.opts,
		Bucket: a.storageBucket,
	}
	return storage.NewClient(ctx, conf)
}

// Firestore returns a new firestore.Client instance from the https://godoc.org/cloud.google.com/go/firestore
// package.
func (a *App) Firestore(ctx context.Context) (*firestore.Client, error) {
	if a.projectID == "" {
		return nil, errors.New("project id is required to access Firestore")
	}
	return firestore.NewClient(ctx, a.projectID, a.opts...)
}

// InstanceID returns an instance of iid.Client.
func (a *App) InstanceID(ctx context.Context) (*iid.Client, error) {
	conf := &internal.InstanceIDConfig{
		ProjectID: a.projectID,
		Opts:      a.opts,
	}
	return iid.NewClient(ctx, conf)
}

// Messaging returns an instance of messaging.Client.
func (a *App) Messaging(ctx context.Context) (*messaging.Client, error) {
	conf := &internal.MessagingConfig{
		ProjectID: a.projectID,
		Opts:      a.opts,
		Version:   Version,
	}
	return messaging.NewClient(ctx, conf)
}

// NewApp creates a new App from the provided config and client options.
//
// If the client options contain a valid credential (a service account file, a refresh token
// file or an oauth2.TokenSource) the App will be authenticated using that credential. Otherwise,
// NewApp attempts to authenticate the App with Google application default credentials.
// If `config` is nil, the SDK will attempt to load the config options from the
// `FIREBASE_CONFIG` environment variable. If the value in it starts with a `{` it is parsed as a
// JSON object, otherwise it is assumed to be the name of the JSON file containing the options.
func NewApp(ctx context.Context, config *Config, opts ...option.ClientOption) (*App, error) {
	o := []option.ClientOption{option.WithScopes(internal.FirebaseScopes...)}
	o = append(o, opts...)
	creds, err := transport.Creds(ctx, o...)
	if err != nil {
		return nil, err
	}
	if config == nil {
		if config, err = getConfigDefaults(); err != nil {
			return nil, err
		}
	}

	var pid string
	if config.ProjectID != "" {
		pid = config.ProjectID
	} else if creds.ProjectID != "" {
		pid = creds.ProjectID
	} else {
		pid = os.Getenv("GOOGLE_CLOUD_PROJECT")
		if pid == "" {
			pid = os.Getenv("GCLOUD_PROJECT")
		}
	}

	ao := defaultAuthOverrides
	if config.AuthOverride != nil {
		ao = *config.AuthOverride
	}

	return &App{
		authOverride:     ao,
		creds:            creds,
		dbURL:            config.DatabaseURL,
		projectID:        pid,
		serviceAccountID: config.ServiceAccountID,
		storageBucket:    config.StorageBucket,
		opts:             o,
	}, nil
}

// getConfigDefaults reads the default config file, defined by the FIREBASE_CONFIG
// env variable, used only when options are nil.
func getConfigDefaults() (*Config, error) {
	fbc := &Config{}
	confFileName := os.Getenv(firebaseEnvName)
	if confFileName == "" {
		return fbc, nil
	}
	var dat []byte
	if confFileName[0] == byte('{') {
		dat = []byte(confFileName)
	} else {
		var err error
		if dat, err = ioutil.ReadFile(confFileName); err != nil {
			return nil, err
		}
	}
	if err := json.Unmarshal(dat, fbc); err != nil {
		return nil, err
	}

	// Some special handling necessary for db auth overrides
	var m map[string]interface{}
	if err := json.Unmarshal(dat, &m); err != nil {
		return nil, err
	}
	if ao, ok := m["databaseAuthVariableOverride"]; ok && ao == nil {
		// Auth overrides are explicitly set to null
		var nullMap map[string]interface{}
		fbc.AuthOverride = &nullMap
	}
	return fbc, nil
}
<|endoftext|>


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

// Package firebase is the entry point to the Firebase Admin SDK. It provides functionality for initializing App
// instances, which serve as the central entities that provide access to various other Firebase services exposed
// from the SDK.
package firebase

import (
	"firebase.google.com/go/auth"
	"firebase.google.com/go/internal"
	"firebase.google.com/go/storage"

	"os"

	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

var firebaseScopes = []string{
	"https://www.googleapis.com/auth/devstorage.full_control",
	"https://www.googleapis.com/auth/firebase",
	"https://www.googleapis.com/auth/userinfo.email",
}

// Version of the Firebase Go Admin SDK.
const Version = "1.0.2"

// An App holds configuration and state common to all Firebase services that are exposed from the SDK.
type App struct {
	creds         *google.DefaultCredentials
	projectID     string
	storageBucket string
	opts          []option.ClientOption
}

// Config represents the configuration used to initialize an App.
type Config struct {
	ProjectID     string
	StorageBucket string
}

// Auth returns an instance of auth.Client.
func (a *App) Auth(ctx context.Context) (*auth.Client, error) {
	conf := &internal.AuthConfig{
		Creds:     a.creds,
		ProjectID: a.projectID,
		Opts:      a.opts,
	}
	return auth.NewClient(ctx, conf)
}

// Storage returns a new instance of storage.Client.
func (a *App) Storage(ctx context.Context) (*storage.Client, error) {
	conf := &internal.StorageConfig{
		Opts:   a.opts,
		Bucket: a.storageBucket,
	}
	return storage.NewClient(ctx, conf)
}

// NewApp creates a new App from the provided config and client options.
//
// If the client options contain a valid credential (a service account file, a refresh token file or an
// oauth2.TokenSource) the App will be authenticated using that credential. Otherwise, NewApp attempts to
// authenticate the App with Google application default credentials.
func NewApp(ctx context.Context, config *Config, opts ...option.ClientOption) (*App, error) {
	o := []option.ClientOption{option.WithScopes(firebaseScopes...)}
	o = append(o, opts...)

	creds, err := transport.Creds(ctx, o...)
	if err != nil {
		return nil, err
	}

	if config == nil {
		config = &Config{}
	}

	var pid string
	if config.ProjectID != "" {
		pid = config.ProjectID
	} else if creds.ProjectID != "" {
		pid = creds.ProjectID
	} else {
		pid = os.Getenv("GCLOUD_PROJECT")
	}

	return &App{
		creds:         creds,
		projectID:     pid,
		storageBucket: config.StorageBucket,
		opts:          o,
	}, nil
}
<commit_msg>Bumped version to 2.0.0 (#33)<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package firebase is the entry point to the Firebase Admin SDK. It provides functionality for initializing App
// instances, which serve as the central entities that provide access to various other Firebase services exposed
// from the SDK.
package firebase

import (
	"firebase.google.com/go/auth"
	"firebase.google.com/go/internal"
	"firebase.google.com/go/storage"

	"os"

	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"
	"google.golang.org/api/transport"
)

var firebaseScopes = []string{
	"https://www.googleapis.com/auth/devstorage.full_control",
	"https://www.googleapis.com/auth/firebase",
	"https://www.googleapis.com/auth/userinfo.email",
}

// Version of the Firebase Go Admin SDK.
const Version = "2.0.0"

// An App holds configuration and state common to all Firebase services that are exposed from the SDK.
type App struct {
	creds         *google.DefaultCredentials
	projectID     string
	storageBucket string
	opts          []option.ClientOption
}

// Config represents the configuration used to initialize an App.
type Config struct {
	ProjectID     string
	StorageBucket string
}

// Auth returns an instance of auth.Client.
func (a *App) Auth(ctx context.Context) (*auth.Client, error) {
	conf := &internal.AuthConfig{
		Creds:     a.creds,
		ProjectID: a.projectID,
		Opts:      a.opts,
	}
	return auth.NewClient(ctx, conf)
}

// Storage returns a new instance of storage.Client.
func (a *App) Storage(ctx context.Context) (*storage.Client, error) {
	conf := &internal.StorageConfig{
		Opts:   a.opts,
		Bucket: a.storageBucket,
	}
	return storage.NewClient(ctx, conf)
}

// NewApp creates a new App from the provided config and client options.
//
// If the client options contain a valid credential (a service account file, a refresh token file or an
// oauth2.TokenSource) the App will be authenticated using that credential. Otherwise, NewApp attempts to
// authenticate the App with Google application default credentials.
func NewApp(ctx context.Context, config *Config, opts ...option.ClientOption) (*App, error) {
	o := []option.ClientOption{option.WithScopes(firebaseScopes...)}
	o = append(o, opts...)

	creds, err := transport.Creds(ctx, o...)
	if err != nil {
		return nil, err
	}

	if config == nil {
		config = &Config{}
	}

	var pid string
	if config.ProjectID != "" {
		pid = config.ProjectID
	} else if creds.ProjectID != "" {
		pid = creds.ProjectID
	} else {
		pid = os.Getenv("GCLOUD_PROJECT")
	}

	return &App{
		creds:         creds,
		projectID:     pid,
		storageBucket: config.StorageBucket,
		opts:          o,
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/koding/kite"
	"fmt"
	"os"
	"sync"
	"log"
	"github.com/bitly/go-nsq"
	"runtime"
	"time"
	"github.com/nsabine/microservices/controller/controllerlib"
)

var GameState [][]string
var XSize int
var YSize int

func main() {
	fmt.Println("Starting Controller")
	XSize = 25
	YSize = 25
	reset()
	evaluate()
	runtime.GOMAXPROCS(2)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	go startKite()
	go startMessaging()
	wg.Wait()
}

func startKite() {
	fmt.Println("Controller starting kite")
	k := kite.New("controller", "1.0.0")
	k.Config.Port = 6001
	k.Config.DisableAuthentication = true
	k.HandleFunc("hello", hello)
	k.HandleFunc("getState", getState)
	k.HandleFunc("update", update)
	k.Run()
}

func startMessaging() {
	fmt.Println("Controller starting NSQ")
	config := nsq.NewConfig()

  	w, _ := nsq.NewProducer(os.Getenv("MESSAGING_SERVICE_HOST") + ":4150", config)

	for {
		tick(w)
		time.Sleep(time.Second * 10)
	}
	w.Stop()

}

func tick(w *nsq.Producer) {
	evaluate()
	err := w.Publish("tick", []byte("test"))
	if err != nil {
		log.Panic("Could not connect")
	}

}

func hello(r *kite.Request) (interface{}, error) {

	fmt.Println("Controller got hello")

	// You can return anything as result, as long as it is JSON marshalable.
	return nil, nil
}

func update(r *kite.Request) (interface{}, error) {
        fmt.Println("Controller received state update")

        // Unmarshal method arguments.
        var params controllerlib.UpdateRequest
        if err := r.Args.One().Unmarshal(&params); err != nil {
                return nil, err
        }

        fmt.Printf("Update received from %s: %s'\n", params.Type, params.MyName)

        // Print a log on remote Kite.
        // This message will be printed on client's console.
        r.Client.Go("kite.log", fmt.Sprintf("Message from %s: Update received", r.LocalKite.Kite().Name))

	GameState[params.XPos][params.YPos] = params.MyName

        return nil, nil
}

func getState(r *kite.Request) (interface{}, error) {
        fmt.Println("Controller received state request")
        return GameState, nil
}

func reset() {
	fmt.Println("Resetting Game State")
	// Allocate the top-level slice.
	GameState = make([][]string, YSize) // One row per unit of y.
	// Loop over the rows, allocating the slice for each row.
	for i := range GameState {
		GameState[i] = make([]string, XSize)
		for j := range GameState[i] {
			GameState[i][j] = controllerlib.UpdateRequest{nil,"Empty",i,j}
		}
	}
}

func evaluate() {
	fmt.Println("Evaluting Game State")
	for i := range GameState {
		for j := range GameState[i] {
			fmt.Print(controllerlib.GetGridCode(GameState[i][j]) + " ")
		}
		fmt.Println()
	}
}

<commit_msg>syntax<commit_after>package main

import (
	"github.com/koding/kite"
	"fmt"
	"os"
	"sync"
	"log"
	"github.com/bitly/go-nsq"
	"runtime"
	"time"
	"github.com/nsabine/microservices/controller/controllerlib"
)

var GameState [][]string
var XSize int
var YSize int

func main() {
	fmt.Println("Starting Controller")
	XSize = 25
	YSize = 25
	reset()
	evaluate()
	runtime.GOMAXPROCS(2)
	wg := &sync.WaitGroup{}
	wg.Add(2)
	go startKite()
	go startMessaging()
	wg.Wait()
}

func startKite() {
	fmt.Println("Controller starting kite")
	k := kite.New("controller", "1.0.0")
	k.Config.Port = 6001
	k.Config.DisableAuthentication = true
	k.HandleFunc("hello", hello)
	k.HandleFunc("getState", getState)
	k.HandleFunc("update", update)
	k.Run()
}

func startMessaging() {
	fmt.Println("Controller starting NSQ")
	config := nsq.NewConfig()

  	w, _ := nsq.NewProducer(os.Getenv("MESSAGING_SERVICE_HOST") + ":4150", config)

	for {
		tick(w)
		time.Sleep(time.Second * 10)
	}
	w.Stop()

}

func tick(w *nsq.Producer) {
	evaluate()
	err := w.Publish("tick", []byte("test"))
	if err != nil {
		log.Panic("Could not connect")
	}

}

func hello(r *kite.Request) (interface{}, error) {

	fmt.Println("Controller got hello")

	// You can return anything as result, as long as it is JSON marshalable.
	return nil, nil
}

func update(r *kite.Request) (interface{}, error) {
        fmt.Println("Controller received state update")

        // Unmarshal method arguments.
        var params controllerlib.UpdateRequest
        if err := r.Args.One().Unmarshal(&params); err != nil {
                return nil, err
        }

        fmt.Printf("Update received from %s: %s'\n", params.Type, params.MyName)

        // Print a log on remote Kite.
        // This message will be printed on client's console.
        r.Client.Go("kite.log", fmt.Sprintf("Message from %s: Update received", r.LocalKite.Kite().Name))

	GameState[params.XPos][params.YPos] = params.MyName

        return nil, nil
}

func getState(r *kite.Request) (interface{}, error) {
        fmt.Println("Controller received state request")
        return GameState, nil
}

func reset() {
	fmt.Println("Resetting Game State")
	// Allocate the top-level slice.
	GameState = make([][]string, YSize) // One row per unit of y.
	// Loop over the rows, allocating the slice for each row.
	for i := range GameState {
		GameState[i] = make([]string, XSize)
		for j := range GameState[i] {
			GameState[i][j] = controllerlib.UpdateRequest{"","Empty",i,j}
		}
	}
}

func evaluate() {
	fmt.Println("Evaluting Game State")
	for i := range GameState {
		for j := range GameState[i] {
			fmt.Print(controllerlib.GetGridCode(GameState[i][j]) + " ")
		}
		fmt.Println()
	}
}

<|endoftext|>


<commit_before>// Convert BlogSum DB (sqlite3) to JSON
package main

import (
	"database/sql"
	"encoding/gob"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

/*
BlogSum DB Schema:

CREATE TABLE articles (
	id integer primary key,
	date date,
	title text,
	uri text,
	body text,
	tags text,
	enabled boolean,
	author text);

CREATE TABLE comments (
	id integer primary key,
	article_id integer,
	date date,
	name text,
	email text,
	url text,
	comment text,
	enabled boolean);
*/

type Articles []Article

type Article struct {
	Date     time.Time
	Title    string
	Slug     string // Uri
	Body     string
	Tags     Tags
	Enabled  bool
	Author   string
	Comments Comments
}

type Tags []string

type Comments []Comment

type Comment struct {
	Date    time.Time
	Name    string
	Email   string
	URL     string
	Comment string
	Enabled bool
}

var (
	input  string
	output string
)

func writeGob(fname string, v interface{}) {
	w, err := os.Create(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()
	enc := gob.NewEncoder(w)
	err = enc.Encode(v)
	if err != nil {
		log.Fatal(err)
	}
}

func getTags(tags string) Tags {
	t := strings.Split(tags, ",")
	for i := range t {
		t[i] = strings.TrimSpace(t[i])
	}
	return t
}

func getDate(date string) time.Time {
	d, err := time.Parse("2006-01-02 15:04:05", date)
	if err != nil {
		log.Fatal(err)
	}
	return d
}

func (a Article) String() string {
	return fmt.Sprintf("%s %s %s", a.Date, a.Slug, a.Tags)
}

func (c Comment) String() string {
	return fmt.Sprintf("%s Comment: %s", c.Date, c.Name)
}

func getComments(db *sql.DB, id int) (C Comments) {
	rows, err := db.Query("SELECT date,name,email,url,comment,enabled FROM comments WHERE article_id=?", id)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			date    string
			name    string
			email   []byte
			url     []byte
			comment string
			enabled bool
		)

		err := rows.Scan(&date, &name, &email, &url, &comment, &enabled)
		if err != nil {
			log.Fatal(err)
		}

		c := Comment{
			Date:    getDate(date),
			Name:    name,
			Email:   string(email),
			URL:     string(url),
			Comment: comment,
			Enabled: enabled,
		}

		fmt.Println(c)

		C = append(C, c)
	}

	return C
}

func getArticles(db *sql.DB) (A Articles) {
	rows, err := db.Query("SELECT id,date,title,uri,body,tags,enabled,author FROM articles")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			id      int
			date    string
			title   string
			uri     string
			body    string
			tags    string
			enabled bool
			author  string
		)

		err := rows.Scan(&id, &date, &title, &uri, &body, &tags, &enabled, &author)
		if err != nil {
			log.Fatal(err)
		}

		a := Article{
			Date:     getDate(date),
			Title:    title,
			Slug:     uri,
			Body:     body,
			Tags:     getTags(tags),
			Enabled:  enabled,
			Author:   author,
			Comments: getComments(db, id),
		}

		fmt.Println(a)

		A = append(A, a)
	}

	return A
}

func init() {
	flag.StringVar(&input, "input", "site.db", "input file (sqlite3)")
	flag.StringVar(&output, "output", "site.gob", "output file (gob)")
	flag.Parse()
}

func main() {
	db, err := sql.Open("sqlite3", input)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	writeGob(output, getArticles(db))
}
<commit_msg>skip disabled<commit_after>// Convert BlogSum DB (sqlite3) to JSON
package main

import (
	"database/sql"
	"encoding/gob"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

/*
BlogSum DB Schema:

CREATE TABLE articles (
	id integer primary key,
	date date,
	title text,
	uri text,
	body text,
	tags text,
	enabled boolean,
	author text);

CREATE TABLE comments (
	id integer primary key,
	article_id integer,
	date date,
	name text,
	email text,
	url text,
	comment text,
	enabled boolean);
*/

type Articles []Article

type Article struct {
	Date     time.Time
	Title    string
	Slug     string // Uri
	Body     string
	Tags     Tags
	Enabled  bool
	Author   string
	Comments Comments
}

type Tags []string

type Comments []Comment

type Comment struct {
	Date    time.Time
	Name    string
	Email   string
	URL     string
	Comment string
	Enabled bool
}

var (
	input  string
	output string
)

func writeGob(fname string, v interface{}) {
	w, err := os.Create(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()
	enc := gob.NewEncoder(w)
	err = enc.Encode(v)
	if err != nil {
		log.Fatal(err)
	}
}

func getTags(tags string) Tags {
	t := strings.Split(tags, ",")
	for i := range t {
		t[i] = strings.TrimSpace(t[i])
	}
	return t
}

func getDate(date string) time.Time {
	d, err := time.Parse("2006-01-02 15:04:05", date)
	if err != nil {
		log.Fatal(err)
	}
	return d
}

func (a Article) String() string {
	return fmt.Sprintf("%s %s %s", a.Date, a.Slug, a.Tags)
}

func (c Comment) String() string {
	return fmt.Sprintf("%s Comment: %s", c.Date, c.Name)
}

func getComments(db *sql.DB, id int) (C Comments) {
	rows, err := db.Query("SELECT date,name,email,url,comment,enabled FROM comments WHERE article_id=?", id)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			date    string
			name    string
			email   []byte
			url     []byte
			comment string
			enabled bool
		)

		err := rows.Scan(&date, &name, &email, &url, &comment, &enabled)
		if err != nil {
			log.Fatal(err)
		}

		c := Comment{
			Date:    getDate(date),
			Name:    name,
			Email:   string(email),
			URL:     string(url),
			Comment: comment,
			Enabled: enabled,
		}

		if c.Enabled {
			fmt.Println(c)
			C = append(C, c)
		}
	}

	return C
}

func getArticles(db *sql.DB) (A Articles) {
	rows, err := db.Query("SELECT id,date,title,uri,body,tags,enabled,author FROM articles")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	for rows.Next() {
		var (
			id      int
			date    string
			title   string
			uri     string
			body    string
			tags    string
			enabled bool
			author  string
		)

		err := rows.Scan(&id, &date, &title, &uri, &body, &tags, &enabled, &author)
		if err != nil {
			log.Fatal(err)
		}

		a := Article{
			Date:     getDate(date),
			Title:    title,
			Slug:     uri,
			Body:     body,
			Tags:     getTags(tags),
			Enabled:  enabled,
			Author:   author,
			Comments: getComments(db, id),
		}

		if a.Enabled {
			fmt.Println(a)
			A = append(A, a)
		}
	}

	return A
}

func init() {
	flag.StringVar(&input, "input", "site.db", "input file (sqlite3)")
	flag.StringVar(&output, "output", "site.gob", "output file (gob)")
	flag.Parse()
}

func main() {
	db, err := sql.Open("sqlite3", input)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	writeGob(output, getArticles(db))
}
<|endoftext|>


<commit_before>package oauth

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

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

func (suite *OauthTestSuite) TestIntrospectResponseAccessToken() {
	at := AccessToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	ir := IntrospectResponse{
		Active:    true,
		Scope:     at.Scope,
		TokenType: TokenType,
		ExpiresAt: int(at.ExpiresAt.Unix()),
		ClientID:  at.Client.Key,
		Username:  at.User.Username,
	}
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))

	at.Client = nil
	ir.ClientID = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))

	at.User = nil
	ir.Username = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))
}

func (suite *OauthTestSuite) TestIntrospectResponseRefreshToken() {
	rt := RefreshToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	ir := IntrospectResponse{
		Active:    true,
		Scope:     rt.Scope,
		TokenType: TokenType,
		ExpiresAt: int(rt.ExpiresAt.Unix()),
		ClientID:  rt.Client.Key,
		Username:  rt.User.Username,
	}
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))

	rt.Client = nil
	ir.ClientID = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))

	rt.User = nil
	ir.Username = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))
}

func (suite *OauthTestSuite) TestHandleIntrospectMissingToken() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client", "test_secret")
	r.PostForm = url.Values{}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 400, w.Code)

	// Check the response body
	assert.Equal(
		suite.T(),
		fmt.Sprintf("{\"error\":\"%s\"}", errTokenMissing.Error()),
		strings.TrimSpace(w.Body.String()),
	)
}

func (suite *OauthTestSuite) TestHandleIntrospectInvailidTokenHint() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client", "test_secret")
	r.PostForm = url.Values{"token": {"token"}, "token_type_hint": {"wrong"}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 400, w.Code)

	// Check the response body
	assert.Equal(
		suite.T(),
		fmt.Sprintf("{\"error\":\"%s\"}", errTokenHintInvalid.Error()),
		strings.TrimSpace(w.Body.String()),
	)
}

func (suite *OauthTestSuite) TestHandleIntrospectAccessToken() {
	// Insert a test access token with a user
	at := &AccessToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	if err := suite.db.Create(at).Error; err != nil {
		log.Fatal(err)
	}

	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client", "test_secret")

	// With correct token hint
	r.PostForm = url.Values{"token": {at.Token}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With incorrect token hint
	r.PostForm = url.Values{"token": {at.Token}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {at.Token}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}

func (suite *OauthTestSuite) TestHandleIntrospectRefreshToken() {
	// Insert a test access token with a user
	rt := &RefreshToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	if err := suite.db.Create(rt).Error; err != nil {
		log.Fatal(err)
	}

	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client", "test_secret")

	// With correct token hint
	r.PostForm = url.Values{"token": {rt.Token}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With incorrect token hint
	r.PostForm = url.Values{"token": {rt.Token}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {rt.Token}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}

func (suite *OauthTestSuite) TestHandleIntrospectInactiveToken() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client", "test_secret")

	// With access token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With refresh token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}
<commit_msg>Fixed tests.<commit_after>package oauth

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

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

func (suite *OauthTestSuite) TestIntrospectResponseAccessToken() {
	at := AccessToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	ir := IntrospectResponse{
		Active:    true,
		Scope:     at.Scope,
		TokenType: TokenType,
		ExpiresAt: int(at.ExpiresAt.Unix()),
		ClientID:  at.Client.Key,
		Username:  at.User.Username,
	}
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))

	at.Client = nil
	ir.ClientID = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))

	at.User = nil
	ir.Username = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseAccessToken(&at))
}

func (suite *OauthTestSuite) TestIntrospectResponseRefreshToken() {
	rt := RefreshToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	ir := IntrospectResponse{
		Active:    true,
		Scope:     rt.Scope,
		TokenType: TokenType,
		ExpiresAt: int(rt.ExpiresAt.Unix()),
		ClientID:  rt.Client.Key,
		Username:  rt.User.Username,
	}
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))

	rt.Client = nil
	ir.ClientID = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))

	rt.User = nil
	ir.Username = ""
	assert.Equal(suite.T(), &ir, suite.service.IntrospectResponseRefreshToken(&rt))
}

func (suite *OauthTestSuite) TestHandleIntrospectMissingToken() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client_1", "test_secret")
	r.PostForm = url.Values{}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 400, w.Code)

	// Check the response body
	assert.Equal(
		suite.T(),
		fmt.Sprintf("{\"error\":\"%s\"}", errTokenMissing.Error()),
		strings.TrimSpace(w.Body.String()),
	)
}

func (suite *OauthTestSuite) TestHandleIntrospectInvailidTokenHint() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client_1", "test_secret")
	r.PostForm = url.Values{"token": {"token"}, "token_type_hint": {"wrong"}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 400, w.Code)

	// Check the response body
	assert.Equal(
		suite.T(),
		fmt.Sprintf("{\"error\":\"%s\"}", errTokenHintInvalid.Error()),
		strings.TrimSpace(w.Body.String()),
	)
}

func (suite *OauthTestSuite) TestHandleIntrospectAccessToken() {
	// Insert a test access token with a user
	at := &AccessToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	if err := suite.db.Create(at).Error; err != nil {
		log.Fatal(err)
	}

	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client_1", "test_secret")

	// With correct token hint
	r.PostForm = url.Values{"token": {at.Token}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With incorrect token hint
	r.PostForm = url.Values{"token": {at.Token}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {at.Token}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseAccessToken(at))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}

func (suite *OauthTestSuite) TestHandleIntrospectRefreshToken() {
	// Insert a test access token with a user
	rt := &RefreshToken{
		Token:     "test_token_introspect_1",
		ExpiresAt: time.Now().Add(+10 * time.Second),
		Client:    suite.clients[0],
		User:      suite.users[0],
		Scope:     "read_write",
	}
	if err := suite.db.Create(rt).Error; err != nil {
		log.Fatal(err)
	}

	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client_1", "test_secret")

	// With correct token hint
	r.PostForm = url.Values{"token": {rt.Token}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With incorrect token hint
	r.PostForm = url.Values{"token": {rt.Token}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {rt.Token}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(suite.service.IntrospectResponseRefreshToken(rt))
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}

func (suite *OauthTestSuite) TestHandleIntrospectInactiveToken() {
	// Make a request
	r, err := http.NewRequest("POST", "http://1.2.3.4/something", nil)
	if err != nil {
		log.Fatal(err)
	}
	r.SetBasicAuth("test_client_1", "test_secret")

	// With access token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}, "token_type_hint": {accessTokenHint}}

	// And run the function we want to test
	w := httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err := json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// With refresh token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}, "token_type_hint": {refreshTokenHint}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))

	// Without token hint
	r.PostForm = url.Values{"token": {"unexisting_token"}}

	// And run the function we want to test
	w = httptest.NewRecorder()
	suite.service.introspectHandler(w, r)

	// Check the status code
	assert.Equal(suite.T(), 200, w.Code)
	// Check the response body
	expected, err = json.Marshal(&IntrospectResponse{})
	if err != nil {
		log.Fatal(err)
	}
	assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String()))
}
<|endoftext|>