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

// +build linux
// +build amd64 arm64 ppc64el

package kvm

import (
	"os"

	"github.com/juju/errors"
	"github.com/juju/utils/packaging/manager"
	"github.com/juju/utils/series"

	"github.com/juju/juju/container"
	"github.com/juju/juju/juju/paths"
)

var requiredPackages = []string{
	"genisoimage",
	"libvirt-bin",
	"qemu-utils",
	"qemu-kvm",
}

type containerInitialiser struct{}

// containerInitialiser implements container.Initialiser.
var _ container.Initialiser = (*containerInitialiser)(nil)

// NewContainerInitialiser returns an instance used to perform the steps
// required to allow a host machine to run a KVM container.
func NewContainerInitialiser() container.Initialiser {
	return &containerInitialiser{}
}

// Initialise is specified on the container.Initialiser interface.
func (ci *containerInitialiser) Initialise() error {
	if err := ensureDependencies(); err != nil {
		return errors.Trace(err)
	}

	// Check if we've done this already.
	poolInfo, err := poolInfo(run)
	if err != nil {
		return errors.Trace(err)
	}
	if poolInfo == nil {
		if err := createPool(paths.DataDir, run, chownToLibvirt); err != nil {
			return errors.Trace(err)
		}
		return nil
	}
	logger.Debugf(`pool already initialised "%#v"`, poolInfo)

	return nil
}

// getPackageManager is a helper function which returns the
// package manager implementation for the current system.
func getPackageManager() (manager.PackageManager, error) {
	return manager.NewPackageManager(series.HostSeries())
}

func ensureDependencies() error {
	pacman, err := getPackageManager()
	if err != nil {
		return err
	}

	for _, pack := range requiredPackages {
		if err := pacman.Install(pack); err != nil {
			return err
		}
	}

	return nil
}

// createPool creates the libvirt storage pool directory. runCmd and chownFunc
// are here for testing. runCmd so we can check the right shell out calls are
// made, and chownFunc because we cannot chown unless we are root.
func createPool(pathfinder func(string) (string, error), runCmd runFunc, chownFunc func(string) error) error {
	poolDir, err := guestPath(pathfinder)
	if err != nil {
		return errors.Trace(err)
	}

	if err = definePool(poolDir, runCmd, chownFunc); err != nil {
		return errors.Trace(err)
	}
	if err = buildPool(runCmd); err != nil {
		return errors.Trace(err)
	}

	if err = startPool(runCmd); err != nil {
		return errors.Trace(err)
	}
	if err = autostartPool(runCmd); err != nil {
		return errors.Trace(err)
	}
	return nil
}

// definePool creates the required directories and changes ownershipt of the
// guest directory so that libvirt-qemu can read, write, and execute its
// guest volumes.
func definePool(dir string, runCmd runFunc, chownFunc func(string) error) error {
	// Permissions gleaned from https://goo.gl/SZIw14
	// The command itself would change the permissions to match anyhow.
	err := os.MkdirAll(dir, 0755)
	if err != nil {
		return errors.Trace(err)
	}

	output, err := runCmd(
		"virsh",
		"pool-define-as",
		poolName,
		"dir",
		"-", "-", "-", "-",
		dir)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-define-as ouput %s", output)

	// We have to set ownership of the guest pool directory after running virsh
	// define-pool-as, because it appears that the libvirt-bin version that
	// ships with trusty sets the ownership of the pool directory to the user
	// running the command -- root in our case. Which causes continer
	// initialization to fail as we couldn't write volumes to the pool. We
	// write them as libvirt-qemu:kvm so that libvirt -- which runs as that
	// user -- can read them to boot the domains.
	if err = chownFunc(dir); err != nil {
		return errors.Trace(err)
	}
	return nil
}

// chownToLibvirt changes ownership of the provided directory to
// libvirt-qemu:kvm.
func chownToLibvirt(dir string) error {
	uid, gid, err := getUserUIDGID(libvirtUser)
	if err != nil {
		logger.Errorf("failed to get livirt-qemu uid:gid %s", err)
		return errors.Trace(err)
	}

	err = os.Chown(dir, uid, gid)
	if err != nil {
		logger.Errorf("failed to change ownership of %q to uid:gid %d:%d %s", dir, uid, gid, err)
		return errors.Trace(err)
	}
	logger.Tracef("%q is now owned by %q %d:%d", dir, libvirtUser, uid, gid)
	return nil
}

// buildPool sets up libvirt internals for the guest pool.
func buildPool(runCmd runFunc) error {
	// This can run without errror if the pool isn't active.
	output, err := runCmd("virsh", "pool-build", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-build ouput %s", output)
	return nil
}

// startPool makes the pool available for use in libvirt.
func startPool(runCmd runFunc) error {
	output, err := runCmd("virsh", "pool-start", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-start ouput %s", output)

	return nil
}

// autostartPool sets up the pool to run automatically when libvirt starts.
func autostartPool(runCmd runFunc) error {
	output, err := runCmd("virsh", "pool-autostart", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-autostart ouput %s", output)

	return nil
}
<commit_msg>Move chown after all the libvirt commands<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build linux
// +build amd64 arm64 ppc64el

package kvm

import (
	"os"

	"github.com/juju/errors"
	"github.com/juju/utils/packaging/manager"
	"github.com/juju/utils/series"

	"github.com/juju/juju/container"
	"github.com/juju/juju/juju/paths"
)

var requiredPackages = []string{
	"genisoimage",
	"libvirt-bin",
	"qemu-utils",
	"qemu-kvm",
}

type containerInitialiser struct{}

// containerInitialiser implements container.Initialiser.
var _ container.Initialiser = (*containerInitialiser)(nil)

// NewContainerInitialiser returns an instance used to perform the steps
// required to allow a host machine to run a KVM container.
func NewContainerInitialiser() container.Initialiser {
	return &containerInitialiser{}
}

// Initialise is specified on the container.Initialiser interface.
func (ci *containerInitialiser) Initialise() error {
	if err := ensureDependencies(); err != nil {
		return errors.Trace(err)
	}

	// Check if we've done this already.
	poolInfo, err := poolInfo(run)
	if err != nil {
		return errors.Trace(err)
	}
	if poolInfo == nil {
		if err := createPool(paths.DataDir, run, chownToLibvirt); err != nil {
			return errors.Trace(err)
		}
		return nil
	}
	logger.Debugf(`pool already initialised "%#v"`, poolInfo)

	return nil
}

// getPackageManager is a helper function which returns the
// package manager implementation for the current system.
func getPackageManager() (manager.PackageManager, error) {
	return manager.NewPackageManager(series.HostSeries())
}

func ensureDependencies() error {
	pacman, err := getPackageManager()
	if err != nil {
		return err
	}

	for _, pack := range requiredPackages {
		if err := pacman.Install(pack); err != nil {
			return err
		}
	}

	return nil
}

// createPool creates the libvirt storage pool directory. runCmd and chownFunc
// are here for testing. runCmd so we can check the right shell out calls are
// made, and chownFunc because we cannot chown unless we are root.
func createPool(pathfinder func(string) (string, error), runCmd runFunc, chownFunc func(string) error) error {
	poolDir, err := guestPath(pathfinder)
	if err != nil {
		return errors.Trace(err)
	}

	if err = definePool(poolDir, runCmd, chownFunc); err != nil {
		return errors.Trace(err)
	}
	if err = buildPool(runCmd); err != nil {
		return errors.Trace(err)
	}

	if err = startPool(runCmd); err != nil {
		return errors.Trace(err)
	}
	if err = autostartPool(runCmd); err != nil {
		return errors.Trace(err)
	}

	// We have to set ownership of the guest pool directory after running virsh
	// commands above, because it appears that the libvirt-bin version that
	// ships with trusty sets the ownership of the pool directory to the user
	// running the commands -- root in our case. Which causes container
	// initialization to fail as we couldn't write volumes to the pool. We
	// write them as libvirt-qemu:kvm so that libvirt -- which runs as that
	// user -- can read them to boot the domains.
	if err = chownFunc(poolDir); err != nil {
		return errors.Trace(err)
	}

	return nil
}

// definePool creates the required directories and changes ownershipt of the
// guest directory so that libvirt-qemu can read, write, and execute its
// guest volumes.
func definePool(dir string, runCmd runFunc, chownFunc func(string) error) error {
	// Permissions gleaned from https://goo.gl/SZIw14
	// The command itself would change the permissions to match anyhow.
	err := os.MkdirAll(dir, 0755)
	if err != nil {
		return errors.Trace(err)
	}

	output, err := runCmd(
		"virsh",
		"pool-define-as",
		poolName,
		"dir",
		"-", "-", "-", "-",
		dir)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-define-as ouput %s", output)

	return nil
}

// chownToLibvirt changes ownership of the provided directory to
// libvirt-qemu:kvm.
func chownToLibvirt(dir string) error {
	uid, gid, err := getUserUIDGID(libvirtUser)
	if err != nil {
		logger.Errorf("failed to get livirt-qemu uid:gid %s", err)
		return errors.Trace(err)
	}

	err = os.Chown(dir, uid, gid)
	if err != nil {
		logger.Errorf("failed to change ownership of %q to uid:gid %d:%d %s", dir, uid, gid, err)
		return errors.Trace(err)
	}
	logger.Tracef("%q is now owned by %q %d:%d", dir, libvirtUser, uid, gid)
	return nil
}

// buildPool sets up libvirt internals for the guest pool.
func buildPool(runCmd runFunc) error {
	// This can run without errror if the pool isn't active.
	output, err := runCmd("virsh", "pool-build", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-build ouput %s", output)
	return nil
}

// startPool makes the pool available for use in libvirt.
func startPool(runCmd runFunc) error {
	output, err := runCmd("virsh", "pool-start", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-start ouput %s", output)

	return nil
}

// autostartPool sets up the pool to run automatically when libvirt starts.
func autostartPool(runCmd runFunc) error {
	output, err := runCmd("virsh", "pool-autostart", poolName)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("pool-autostart ouput %s", output)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"time"
)

type config struct {
	TwitterAuth twitterAuth `json:"twitterAuth"`
}

type twitterAuth struct {
	ConsumerKey       string `json:"consumerKey"`
	ConsumerSecret    string `json:"consumerSecret"`
	AccessToken       string `json:"accessToken"`
	AccessTokenSecret string `json:"accessTokenSecret"`
}

var configFile = flag.String("config", "config.json", "path to config file")
var dataFile = flag.String("data", "tweets.json", "path to json file containing tweets")
var frequency = flag.Int64("freq", 1440, "Frequency to post each tweet (in minutes)")

func main() {
	var fatalErr error
	defer func() {
		if fatalErr != nil {
			flag.PrintDefaults()
			log.Fatalln(fatalErr)
		}
	}()

	flag.Parse()

	var config config

	file, err := os.Open(*configFile)
	if err != nil {
		fatalErr = fmt.Errorf("can't open %s: %s", *configFile, err)
		return
	}

	if err := json.NewDecoder(file).Decode(&config); err != nil {
		fatalErr = fmt.Errorf("can't decode %s: %s", *configFile, err)
		return
	}

	fmt.Println("Go Twitter Bot is running...")

	ticker := time.NewTicker(time.Minute * time.Duration(*frequency))

	for range ticker.C {
		tweets, err := LoadTweets(*dataFile)
		if err != nil {
			fatalErr = fmt.Errorf("problem loading tweets: %s", err)
			return
		}

		tweet, err := getNextTweet(tweets)
		if err == errNoMoreTweetsToPost {
			fmt.Println("That's all the tweets")
			continue
		}

		fmt.Printf("Tweeting: %s\n\n", tweet.Text)

		err = postTweet(config.TwitterAuth, tweet.Text)
		if err != nil {
			fatalErr = err
			return
		}

		tweet.IsPosted = true

		err = SaveTweets(tweets, *dataFile)
		if err != nil {
			fatalErr = fmt.Errorf("problem saving tweets: %s", err)
			return
		}
	}
}

var errNoMoreTweetsToPost = errors.New("No more tweets left to be posted")

func getNextTweet(tweets []Tweet) (*Tweet, error) {
	for i := range tweets {
		tweet := &tweets[i]
		if !tweet.IsPosted {
			return tweet, nil
		}
	}

	return nil, errNoMoreTweetsToPost
}
<commit_msg>fixed: ensure tweet is posted immediately instead of waiting for first tick.<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"time"
)

type config struct {
	TwitterAuth twitterAuth `json:"twitterAuth"`
}

type twitterAuth struct {
	ConsumerKey       string `json:"consumerKey"`
	ConsumerSecret    string `json:"consumerSecret"`
	AccessToken       string `json:"accessToken"`
	AccessTokenSecret string `json:"accessTokenSecret"`
}

var configFile = flag.String("config", "config.json", "path to config file")
var dataFile = flag.String("data", "tweets.json", "path to json file containing tweets")
var frequency = flag.Int64("freq", 1440, "Frequency to post each tweet (in minutes)")

func main() {
	var fatalErr error
	defer func() {
		if fatalErr != nil {
			flag.PrintDefaults()
			log.Fatalln(fatalErr)
		}
	}()

	flag.Parse()

	var config config

	file, err := os.Open(*configFile)
	if err != nil {
		fatalErr = fmt.Errorf("can't open %s: %s", *configFile, err)
		return
	}

	if err := json.NewDecoder(file).Decode(&config); err != nil {
		fatalErr = fmt.Errorf("can't decode %s: %s", *configFile, err)
		return
	}

	fmt.Println("Go Twitter Bot is running...")

	fatalErr = postNextTweet(config)
	if fatalErr != nil {
		return
	}

	ticker := time.NewTicker(time.Minute * time.Duration(*frequency))
	for range ticker.C {
		fatalErr := postNextTweet(config)
		if fatalErr != nil {
			return
		}
	}
}

func postNextTweet(config config) error {
	tweets, err := LoadTweets(*dataFile)
	if err != nil {
		return fmt.Errorf("problem loading tweets: %s", err)
	}

	tweet, err := getNextTweet(tweets)
	if err == errNoMoreTweetsToPost {
		fmt.Println("That's all the tweets")
		return nil
	}

	fmt.Printf("Tweeting: %s\n\n", tweet.Text)

	err = postTweet(config.TwitterAuth, tweet.Text)
	if err != nil {
		return err
	}

	tweet.IsPosted = true

	err = SaveTweets(tweets, *dataFile)
	if err != nil {
		return fmt.Errorf("problem saving tweets: %s", err)
	}

	return nil
}

var errNoMoreTweetsToPost = errors.New("No more tweets left to be posted")

func getNextTweet(tweets []Tweet) (*Tweet, error) {
	for i := range tweets {
		tweet := &tweets[i]
		if !tweet.IsPosted {
			return tweet, nil
		}
	}

	return nil, errNoMoreTweetsToPost
}
<|endoftext|>


<commit_before>// Copyright 2015 The rkt Authors
//
// 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 networking

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strings"
	"syscall"

	"github.com/appc/spec/schema/types"
	cnitypes "github.com/containernetworking/cni/pkg/types"
	"github.com/hashicorp/errwrap"
	"github.com/vishvananda/netlink"

	"github.com/rkt/rkt/common"
	commonnet "github.com/rkt/rkt/common/networking"
	"github.com/rkt/rkt/networking/netinfo"
	"github.com/rkt/rkt/pkg/log"
)

const (
	IfNamePattern       = "eth%d"
	selfNetNS           = "/proc/self/ns/net"
	mountNetnsDirectory = "/var/run/netns"
)

// Networking describes the networking details of a pod.
type Networking struct {
	podEnv

	nets []activeNet
}

// NetConf local struct extends cnitypes.NetConf with information about masquerading
// similar to CNI plugins
type NetConf struct {
	cnitypes.NetConf
	IPMasq           bool `json:"ipMasq"`
	MTU              int  `json:"mtu"`
	IsDefaultGateway bool `json:"isDefaultGateway"`
}

var (
	stderr   *log.Logger
	debuglog bool
)

// Setup creates a new networking namespace and executes network plugins to
// set up networking. It returns in the new pod namespace
func Setup(podRoot string, podID types.UUID, fps []commonnet.ForwardedPort, netList common.NetList, localConfig, flavor string, noDNS, debug bool) (*Networking, error) {

	stderr = log.New(os.Stderr, "networking", debug)
	debuglog = debug

	if flavor == "kvm" {
		return kvmSetup(podRoot, podID, fps, netList, localConfig, noDNS)
	}

	// TODO(jonboulle): currently podRoot is _always_ ".", and behaviour in other
	// circumstances is untested. This should be cleaned up.
	n := Networking{
		podEnv: podEnv{
			podRoot:      podRoot,
			podID:        podID,
			netsLoadList: netList,
			localConfig:  localConfig,
		},
	}

	err := n.mountNetnsDirectory()
	if err != nil {
		return nil, err
	}

	// Create the network namespace (and save its name in a file)
	err = n.podNSCreate()
	if err != nil {
		return nil, err
	}

	n.nets, err = n.loadNets()
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error loading network definitions"), err)
	}

	if err := n.setupNets(n.nets, noDNS); err != nil {
		return nil, err
	}

	if len(fps) > 0 {
		if err = n.enableDefaultLocalnetRouting(); err != nil {
			return nil, err
		}
		podIP, err := n.GetForwardableNetPodIP()
		if err != nil {
			return nil, err
		}
		if err := n.setupForwarding(); err != nil {
			n.teardownForwarding()
			return nil, err
		}
		if err := n.forwardPorts(fps, podIP); err != nil {
			n.teardownForwarding()
			return nil, err
		}
	}

	// Switch to the podNS
	if err := n.podNS.Set(); err != nil {
		return nil, err
	}

	if err = loUp(); err != nil {
		return nil, err
	}

	return &n, nil
}

// enableDefaultLocalnetRouting enables the route_localnet attribute on the supposedly default network interface.
// This allows setting up loopback NAT so the host can access the pod's forwarded ports on the localhost address.
func (n *Networking) enableDefaultLocalnetRouting() error {
	routeLocalnetFormat := ""

	defaultHostIP, err := n.GetForwardableNetHostIP()
	if err != nil {
		return err
	}

	defaultHostIPstring := defaultHostIP.String()
	switch {
	case strings.Contains(defaultHostIPstring, "."):
		routeLocalnetFormat = "/proc/sys/net/ipv4/conf/%s/route_localnet"
	case strings.Contains(defaultHostIPstring, ":"):
		return fmt.Errorf("unexpected IPv6 Address returned for default host interface: %q", defaultHostIPstring)
	default:
		return fmt.Errorf("unknown type for default Host IP: %q", defaultHostIPstring)
	}

	hostIfaces, err := n.GetIfacesByIP(defaultHostIP)
	if err != nil {
		return err
	}

	for _, hostIface := range hostIfaces {
		routeLocalnetPath := fmt.Sprintf(routeLocalnetFormat, hostIface.Name)
		routeLocalnetValue, err := ioutil.ReadFile(routeLocalnetPath)
		if err != nil {
			return err
		}
		if string(routeLocalnetValue) != "1" {
			routeLocalnetFile, err := os.OpenFile(routeLocalnetPath, os.O_WRONLY, 0)
			if err != nil {
				return err
			}
			defer routeLocalnetFile.Close()

			if _, err = io.WriteString(routeLocalnetFile, "1"); err != nil {
				return err
			}
		}
	}

	return nil
}

// Load creates the Networking object from saved state.
// Assumes the current netns is that of the host.
func Load(podRoot string, podID *types.UUID, localConfig string) (*Networking, error) {
	// the current directory is pod root
	pdirfd, err := syscall.Open(podRoot, syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
	if err != nil {
		return nil, errwrap.Wrap(fmt.Errorf("failed to open pod root directory (%v)", podRoot), err)
	}
	defer syscall.Close(pdirfd)

	nis, err := netinfo.LoadAt(pdirfd)
	if err != nil {
		return nil, err
	}

	var nets []activeNet
	for _, ni := range nis {
		n, err := loadNet(ni.ConfPath)
		if err != nil {
			if !os.IsNotExist(err) {
				stderr.PrintE(fmt.Sprintf("error loading %q; ignoring", ni.ConfPath), err)
			}
			continue
		}

		// make a copy of ni to make it a unique object as it's saved via ptr
		rti := ni
		n.runtime = &rti
		nets = append(nets, *n)
	}

	p := podEnv{
		podRoot:     podRoot,
		podID:       *podID,
		localConfig: localConfig,
	}

	err = p.podNSLoad()
	if err != nil {
		return nil, err
	}

	return &Networking{
		podEnv: p,
		nets:   nets,
	}, nil
}

// GetIfacesByIP searches for and returns the interfaces with the given IP
// Disregards the subnet mask since not every net.IP object contains
// On success it will return the list of found interfaces
func (n *Networking) GetIfacesByIP(ifaceIP net.IP) ([]net.Interface, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}

	searchAddr := strings.Split(ifaceIP.String(), "/")[0]
	resultInterfaces := make([]net.Interface, 0)

	for _, iface := range ifaces {
		if iface.Flags&net.FlagLoopback != 0 {
			continue
		}

		addrs, err := iface.Addrs()
		if err != nil {
			return nil, errwrap.Wrap(fmt.Errorf("cannot get addresses for interface %v", iface.Name), err)
		}

		for _, addr := range addrs {
			currentAddr := strings.Split(addr.String(), "/")[0]
			if searchAddr == currentAddr {
				resultInterfaces = append(resultInterfaces, iface)
				break
			}
		}
	}

	if len(resultInterfaces) == 0 {
		return nil, fmt.Errorf("no interface found with IP %q", ifaceIP)
	}

	return resultInterfaces, nil
}

// Teardown cleans up a produced Networking object.
func (n *Networking) Teardown(flavor string, debug bool) {

	stderr = log.New(os.Stderr, "networking", debug)
	debuglog = debug

	// Teardown everything in reverse order of setup.
	// This should be idempotent -- be tolerant of missing stuff

	if flavor == "kvm" {
		n.kvmTeardown()
		return
	}

	if err := n.teardownForwarding(); err != nil {
		stderr.PrintE("error removing forwarded ports", err)
	}

	err := n.podNSLoad()
	if err != nil {
		stderr.PrintE("error loading podNS", err)
	}

	n.teardownNets(n.nets)
	n.podNSDestroy()
}

// Save writes out the info about active nets
// for "rkt list" and friends to display
func (e *Networking) Save() error {

	if e.podNS != nil {
		if err := e.podNSPathSave(); err != nil {
			return err
		}
	}

	var nis []netinfo.NetInfo
	for _, n := range e.nets {
		nis = append(nis, *n.runtime)
	}

	return netinfo.Save(e.podRoot, nis)
}

// CleanUpGarbage can be called when Load fails, but there may still
// be some garbage lying around. Right now, this deletes the namespace.
func CleanUpGarbage(podRoot string, podID *types.UUID) error {
	p := podEnv{
		podRoot: podRoot,
		podID:   *podID,
	}

	err := p.podNSLoad()
	if err != nil {
		return err
	}
	return p.podNSDestroy()
}

func loUp() error {
	lo, err := netlink.LinkByName("lo")
	if err != nil {
		return errwrap.Wrap(errors.New("failed to lookup lo"), err)
	}

	if err := netlink.LinkSetUp(lo); err != nil {
		return errwrap.Wrap(errors.New("failed to set lo up"), err)
	}

	return nil
}
<commit_msg>networking/portfwd: fix compare routeLocalnetValue<commit_after>// Copyright 2015 The rkt Authors
//
// 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 networking

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"strings"
	"syscall"

	"github.com/appc/spec/schema/types"
	cnitypes "github.com/containernetworking/cni/pkg/types"
	"github.com/hashicorp/errwrap"
	"github.com/vishvananda/netlink"

	"github.com/rkt/rkt/common"
	commonnet "github.com/rkt/rkt/common/networking"
	"github.com/rkt/rkt/networking/netinfo"
	"github.com/rkt/rkt/pkg/log"
)

const (
	IfNamePattern       = "eth%d"
	selfNetNS           = "/proc/self/ns/net"
	mountNetnsDirectory = "/var/run/netns"
)

// Networking describes the networking details of a pod.
type Networking struct {
	podEnv

	nets []activeNet
}

// NetConf local struct extends cnitypes.NetConf with information about masquerading
// similar to CNI plugins
type NetConf struct {
	cnitypes.NetConf
	IPMasq           bool `json:"ipMasq"`
	MTU              int  `json:"mtu"`
	IsDefaultGateway bool `json:"isDefaultGateway"`
}

var (
	stderr   *log.Logger
	debuglog bool
)

// Setup creates a new networking namespace and executes network plugins to
// set up networking. It returns in the new pod namespace
func Setup(podRoot string, podID types.UUID, fps []commonnet.ForwardedPort, netList common.NetList, localConfig, flavor string, noDNS, debug bool) (*Networking, error) {

	stderr = log.New(os.Stderr, "networking", debug)
	debuglog = debug

	if flavor == "kvm" {
		return kvmSetup(podRoot, podID, fps, netList, localConfig, noDNS)
	}

	// TODO(jonboulle): currently podRoot is _always_ ".", and behaviour in other
	// circumstances is untested. This should be cleaned up.
	n := Networking{
		podEnv: podEnv{
			podRoot:      podRoot,
			podID:        podID,
			netsLoadList: netList,
			localConfig:  localConfig,
		},
	}

	err := n.mountNetnsDirectory()
	if err != nil {
		return nil, err
	}

	// Create the network namespace (and save its name in a file)
	err = n.podNSCreate()
	if err != nil {
		return nil, err
	}

	n.nets, err = n.loadNets()
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error loading network definitions"), err)
	}

	if err := n.setupNets(n.nets, noDNS); err != nil {
		return nil, err
	}

	if len(fps) > 0 {
		if err = n.enableDefaultLocalnetRouting(); err != nil {
			return nil, err
		}
		podIP, err := n.GetForwardableNetPodIP()
		if err != nil {
			return nil, err
		}
		if err := n.setupForwarding(); err != nil {
			n.teardownForwarding()
			return nil, err
		}
		if err := n.forwardPorts(fps, podIP); err != nil {
			n.teardownForwarding()
			return nil, err
		}
	}

	// Switch to the podNS
	if err := n.podNS.Set(); err != nil {
		return nil, err
	}

	if err = loUp(); err != nil {
		return nil, err
	}

	return &n, nil
}

// enableDefaultLocalnetRouting enables the route_localnet attribute on the supposedly default network interface.
// This allows setting up loopback NAT so the host can access the pod's forwarded ports on the localhost address.
func (n *Networking) enableDefaultLocalnetRouting() error {
	routeLocalnetFormat := ""

	defaultHostIP, err := n.GetForwardableNetHostIP()
	if err != nil {
		return err
	}

	defaultHostIPstring := defaultHostIP.String()
	switch {
	case strings.Contains(defaultHostIPstring, "."):
		routeLocalnetFormat = "/proc/sys/net/ipv4/conf/%s/route_localnet"
	case strings.Contains(defaultHostIPstring, ":"):
		return fmt.Errorf("unexpected IPv6 Address returned for default host interface: %q", defaultHostIPstring)
	default:
		return fmt.Errorf("unknown type for default Host IP: %q", defaultHostIPstring)
	}

	hostIfaces, err := n.GetIfacesByIP(defaultHostIP)
	if err != nil {
		return err
	}

	for _, hostIface := range hostIfaces {
		routeLocalnetPath := fmt.Sprintf(routeLocalnetFormat, hostIface.Name)
		routeLocalnetValue, err := ioutil.ReadFile(routeLocalnetPath)
		if err != nil {
			return err
		}
		if strings.TrimSpace(string(routeLocalnetValue)) != "1" {
			routeLocalnetFile, err := os.OpenFile(routeLocalnetPath, os.O_WRONLY, 0)
			if err != nil {
				return err
			}
			defer routeLocalnetFile.Close()

			if _, err = io.WriteString(routeLocalnetFile, "1"); err != nil {
				return err
			}
		}
	}

	return nil
}

// Load creates the Networking object from saved state.
// Assumes the current netns is that of the host.
func Load(podRoot string, podID *types.UUID, localConfig string) (*Networking, error) {
	// the current directory is pod root
	pdirfd, err := syscall.Open(podRoot, syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
	if err != nil {
		return nil, errwrap.Wrap(fmt.Errorf("failed to open pod root directory (%v)", podRoot), err)
	}
	defer syscall.Close(pdirfd)

	nis, err := netinfo.LoadAt(pdirfd)
	if err != nil {
		return nil, err
	}

	var nets []activeNet
	for _, ni := range nis {
		n, err := loadNet(ni.ConfPath)
		if err != nil {
			if !os.IsNotExist(err) {
				stderr.PrintE(fmt.Sprintf("error loading %q; ignoring", ni.ConfPath), err)
			}
			continue
		}

		// make a copy of ni to make it a unique object as it's saved via ptr
		rti := ni
		n.runtime = &rti
		nets = append(nets, *n)
	}

	p := podEnv{
		podRoot:     podRoot,
		podID:       *podID,
		localConfig: localConfig,
	}

	err = p.podNSLoad()
	if err != nil {
		return nil, err
	}

	return &Networking{
		podEnv: p,
		nets:   nets,
	}, nil
}

// GetIfacesByIP searches for and returns the interfaces with the given IP
// Disregards the subnet mask since not every net.IP object contains
// On success it will return the list of found interfaces
func (n *Networking) GetIfacesByIP(ifaceIP net.IP) ([]net.Interface, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}

	searchAddr := strings.Split(ifaceIP.String(), "/")[0]
	resultInterfaces := make([]net.Interface, 0)

	for _, iface := range ifaces {
		if iface.Flags&net.FlagLoopback != 0 {
			continue
		}

		addrs, err := iface.Addrs()
		if err != nil {
			return nil, errwrap.Wrap(fmt.Errorf("cannot get addresses for interface %v", iface.Name), err)
		}

		for _, addr := range addrs {
			currentAddr := strings.Split(addr.String(), "/")[0]
			if searchAddr == currentAddr {
				resultInterfaces = append(resultInterfaces, iface)
				break
			}
		}
	}

	if len(resultInterfaces) == 0 {
		return nil, fmt.Errorf("no interface found with IP %q", ifaceIP)
	}

	return resultInterfaces, nil
}

// Teardown cleans up a produced Networking object.
func (n *Networking) Teardown(flavor string, debug bool) {

	stderr = log.New(os.Stderr, "networking", debug)
	debuglog = debug

	// Teardown everything in reverse order of setup.
	// This should be idempotent -- be tolerant of missing stuff

	if flavor == "kvm" {
		n.kvmTeardown()
		return
	}

	if err := n.teardownForwarding(); err != nil {
		stderr.PrintE("error removing forwarded ports", err)
	}

	err := n.podNSLoad()
	if err != nil {
		stderr.PrintE("error loading podNS", err)
	}

	n.teardownNets(n.nets)
	n.podNSDestroy()
}

// Save writes out the info about active nets
// for "rkt list" and friends to display
func (e *Networking) Save() error {

	if e.podNS != nil {
		if err := e.podNSPathSave(); err != nil {
			return err
		}
	}

	var nis []netinfo.NetInfo
	for _, n := range e.nets {
		nis = append(nis, *n.runtime)
	}

	return netinfo.Save(e.podRoot, nis)
}

// CleanUpGarbage can be called when Load fails, but there may still
// be some garbage lying around. Right now, this deletes the namespace.
func CleanUpGarbage(podRoot string, podID *types.UUID) error {
	p := podEnv{
		podRoot: podRoot,
		podID:   *podID,
	}

	err := p.podNSLoad()
	if err != nil {
		return err
	}
	return p.podNSDestroy()
}

func loUp() error {
	lo, err := netlink.LinkByName("lo")
	if err != nil {
		return errwrap.Wrap(errors.New("failed to lookup lo"), err)
	}

	if err := netlink.LinkSetUp(lo); err != nil {
		return errwrap.Wrap(errors.New("failed to set lo up"), err)
	}

	return nil
}
<|endoftext|>


<commit_before>package bst

import (
	"testing"
	"fmt"
)

func SetupBST() (tree *Tree) {
	tree = NewBST()

	values := []int{4, 3, 6, 2, 7, 5}

	for _, v := range values {
		if (tree.Insert(v) == false) {
			return nil
		}
	}

	// Test that tree structure is correct
	if (tree.root.value != 4 ||
		tree.root.left.value != 3 ||
		tree.root.right.value != 6 &&
		tree.root.left.left.value != 2 ||
		tree.root.right.left.value != 5 ||
		tree.root.right.right.value != 7) {
			return nil
	}

	// Test that node count is correct
	if (tree.nodes != 6) {
		return nil
	}

	return
}

func TestInsert(t *testing.T) {
	tree := NewBST()

	// Test normal inserts
	values := []int{4, 3, 6, 2, 7, 5}

	for _, v := range values {
		if (tree.Insert(v) == false) {
			t.Error("Node not inserted correctly")
		}
	}

	// Test insert of existing value (root)
	if (tree.Insert(4) == true) {
		t.Error("Existing node (root) inserted again")
	}

	// Test insert of existing value (non-root, non-leaf)
	if (tree.Insert(3) == true) {
		t.Error("Existing node (non-root, non-leaf) inserted again")
	}

	// Test insert of existing value (leaf)
	if (tree.Insert(7) == true) {
		t.Error("Existing node (leaf) inserted again")
	}

	// Test that tree structure is correct
	if (tree.root.value != 4 ||
		tree.root.left.value != 3 ||
		tree.root.right.value != 6 &&
		tree.root.left.left.value != 2 ||
		tree.root.right.left.value != 5 ||
		tree.root.right.right.value != 7) {
			t.Error("Tree structure is not correct")
	}

	// Test that node count is correct
	if (tree.nodes != 6) {
		t.Error("Tree node count is incorrect")
	}
}

func TestFind(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	// Find root node
	found, level := tree.Find(4)
	if found != true {
		t.Error("Root node 4 not found")
	} else if level != 1 {
		t.Error("Root node 4 found at incorrect level")
	}

	// Find node requiring traversal left and right to find
	found, level = tree.Find(5)
	if found != true {
		t.Error("Node 5 not found")
	} else if level != 3 {
		t.Error("Node 5 found at incorrect level")
	}
}

func TestDelete(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	// Delete root node
	if (!tree.Delete(4)) {
		t.Error("Could not delete root node")
	}

	// Delete non-root and non-leaf node
	if (!tree.Delete(3)) {
		t.Error("Could not delete non-root and non-leaf node")
	}

	// Delete leaf node
	if (!tree.Delete(7)) {
		t.Error("Could not delete leaf node")
	}

	// Check that tree structure is okay
	correct := []int{2,5,6}

	items := tree.InOrder()

	fmt.Println(items)

	if (len(items) != len(correct)) {
		t.Error("Tree structure is incorrect")
	} else {
		for k, v := range items {
			if v != correct[k] {
				t.Error("Tree structure is incorrect")
			}
		}
	}
}

func TestPreOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.PreOrder()

	correct := []int{4,3,2,6,5,7}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("PreOrder item at index", k, "is incorrect")
		}
	}
}

func TestInOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.InOrder()

	correct := []int{2,3,4,5,6,7}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("InOrder item at index", k, "is incorrect")
		}
	}
}

func TestPostOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.PostOrder()

	correct := []int{2,3,5,7,6,4}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("PostOrder item at index", k, "is incorrect")
		}
	}
}<commit_msg>Removed unnecessary print statement from tests<commit_after>package bst

import (
	"testing"
)

func SetupBST() (tree *Tree) {
	tree = NewBST()

	values := []int{4, 3, 6, 2, 7, 5}

	for _, v := range values {
		if (tree.Insert(v) == false) {
			return nil
		}
	}

	// Test that tree structure is correct
	if (tree.root.value != 4 ||
		tree.root.left.value != 3 ||
		tree.root.right.value != 6 &&
		tree.root.left.left.value != 2 ||
		tree.root.right.left.value != 5 ||
		tree.root.right.right.value != 7) {
			return nil
	}

	// Test that node count is correct
	if (tree.nodes != 6) {
		return nil
	}

	return
}

func TestInsert(t *testing.T) {
	tree := NewBST()

	// Test normal inserts
	values := []int{4, 3, 6, 2, 7, 5}

	for _, v := range values {
		if (tree.Insert(v) == false) {
			t.Error("Node not inserted correctly")
		}
	}

	// Test insert of existing value (root)
	if (tree.Insert(4) == true) {
		t.Error("Existing node (root) inserted again")
	}

	// Test insert of existing value (non-root, non-leaf)
	if (tree.Insert(3) == true) {
		t.Error("Existing node (non-root, non-leaf) inserted again")
	}

	// Test insert of existing value (leaf)
	if (tree.Insert(7) == true) {
		t.Error("Existing node (leaf) inserted again")
	}

	// Test that tree structure is correct
	if (tree.root.value != 4 ||
		tree.root.left.value != 3 ||
		tree.root.right.value != 6 &&
		tree.root.left.left.value != 2 ||
		tree.root.right.left.value != 5 ||
		tree.root.right.right.value != 7) {
			t.Error("Tree structure is not correct")
	}

	// Test that node count is correct
	if (tree.nodes != 6) {
		t.Error("Tree node count is incorrect")
	}
}

func TestFind(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	// Find root node
	found, level := tree.Find(4)
	if found != true {
		t.Error("Root node 4 not found")
	} else if level != 1 {
		t.Error("Root node 4 found at incorrect level")
	}

	// Find node requiring traversal left and right to find
	found, level = tree.Find(5)
	if found != true {
		t.Error("Node 5 not found")
	} else if level != 3 {
		t.Error("Node 5 found at incorrect level")
	}
}

func TestDelete(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	// Delete root node
	if (!tree.Delete(4)) {
		t.Error("Could not delete root node")
	}

	// Delete non-root and non-leaf node
	if (!tree.Delete(3)) {
		t.Error("Could not delete non-root and non-leaf node")
	}

	// Delete leaf node
	if (!tree.Delete(7)) {
		t.Error("Could not delete leaf node")
	}

	// Check that tree structure is okay
	correct := []int{2,5,6}

	items := tree.InOrder()

	if (len(items) != len(correct)) {
		t.Error("Tree structure is incorrect")
	} else {
		for k, v := range items {
			if v != correct[k] {
				t.Error("Tree structure is incorrect")
			}
		}
	}
}

func TestPreOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.PreOrder()

	correct := []int{4,3,2,6,5,7}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("PreOrder item at index", k, "is incorrect")
		}
	}
}

func TestInOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.InOrder()

	correct := []int{2,3,4,5,6,7}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("InOrder item at index", k, "is incorrect")
		}
	}
}

func TestPostOrder(t *testing.T) {
	tree := SetupBST()

	if (tree == nil) {
		t.Fatal("Setup failed")
	}

	items := tree.PostOrder()

	correct := []int{2,3,5,7,6,4}

	for k, v := range items {
		if (v != correct[k]) {
			t.Error("PostOrder item at index", k, "is incorrect")
		}
	}
}<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"io"
	"os"
	"time"

	"strings"

	"github.com/ncodes/cocoon/core/orderer"
	proto "github.com/ncodes/cocoon/core/runtime/golang/proto"
	"github.com/ncodes/cocoon/core/types"
	logging "github.com/op/go-logging"
	cmap "github.com/orcaman/concurrent-map"
	context "golang.org/x/net/context"
	"google.golang.org/grpc"
)

var log = logging.MustGetLogger("connector.client")

// txChannels holds the channels to send transaction responses to
var txRespChannels = cmap.New()

// Client represents a cocoon code GRPC client
// that interacts with a cocoon code.
type Client struct {
	ccodeAddr             string
	stub                  proto.StubClient
	conCtx                context.Context
	conCancel             context.CancelFunc
	orderDiscoTicker      *time.Ticker
	ordererAddrs          []string
	stream                proto.Stub_TransactClient
	cocoonID              string
	streamKeepAliveTicker *time.Ticker
	stopped               bool
}

// NewClient creates a new cocoon code client
func NewClient() *Client {
	return &Client{}
}

// SetCocoonID sets the cocoon id
func (c *Client) SetCocoonID(id string) {
	c.cocoonID = id
}

// SetCocoonCodeAddr sets the cocoon code bind address
func (c *Client) SetCocoonCodeAddr(ccAddr string) {
	c.ccodeAddr = ccAddr
}

// getCCAddr returns the cocoon code bind address.
// For development, if DEV_COCOON_ADDR is set, it connects to it.
func (c *Client) getCCAddr() string {
	if devCCodeAddr := os.Getenv("DEV_COCOON_ADDR"); len(devCCodeAddr) > 0 {
		return devCCodeAddr
	}
	return c.ccodeAddr
}

// Close the stream and cancel connections
func (c *Client) Close() {
	c.stopped = true
	if c.stream != nil {
		c.stream.CloseSend()
		c.stream = nil
	}
	if c.conCancel != nil {
		c.conCancel()
	}
	if c.orderDiscoTicker != nil {
		c.orderDiscoTicker.Stop()
	}
	if c.streamKeepAliveTicker != nil {
		c.streamKeepAliveTicker.Stop()
	}
}

// keepStreamAlive periodically sends a keep alive message to the stream
// to prevent transport from closing.
func (c *Client) keepStreamAlive() {
	c.streamKeepAliveTicker = time.NewTicker(30 * time.Second)
	for _ = range c.streamKeepAliveTicker.C {
		if c.stream != nil {
			c.stream.Send(&proto.Tx{
				Invoke: true,
				Status: -100,
			})
			log.Debug("Sent keep alive message to stream")
		}
	}
}

// GetStream returns the grpc stream connected to the grpc cocoon code server
func (c *Client) GetStream() proto.Stub_TransactClient {
	return c.stream
}

// Connect connects to a cocoon code server
// running on a known port
func (c *Client) Connect() error {

	log.Info("Starting cocoon code client")

	// start a ticker to continously discover orderer addreses
	go func() {
		c.orderDiscoTicker = time.NewTicker(60 * time.Second)
		for _ = range c.orderDiscoTicker.C {
			var ordererAddrs []string
			ordererAddrs, err := orderer.DiscoverOrderers()
			if err != nil {
				log.Error(err.Error())
				continue
			}
			c.ordererAddrs = ordererAddrs
		}
	}()

	var ordererAddrs []string
	ordererAddrs, err := orderer.DiscoverOrderers()
	if err != nil {
		return err
	}
	c.ordererAddrs = ordererAddrs

	if len(c.ordererAddrs) > 0 {
		log.Infof("Orderer address list updated. Contains %d orderer address(es)", len(c.ordererAddrs))
	} else {
		log.Warning("No orderer address was found. We won't be able to reach the orderer. ")
	}

	time.AfterFunc(2*time.Second, func() {
		log.Debugf("Now connected to cocoon code at port=%s", strings.Split(c.getCCAddr(), ":")[1])
	})

	for !c.stopped {

		conn, err := grpc.Dial(c.getCCAddr(), grpc.WithInsecure())
		if err != nil {
			return fmt.Errorf("failed to connect to cocoon code server. %s", err)
		}
		defer conn.Close()

		c.stub = proto.NewStubClient(conn)

		if err = c.Do(); err != nil {
			log.Error(err)
		}

		log.Debug("Redialling cocoon code")
	}

	return nil
}

// Do starts a request loop that continously asks the
// server for transactions. When it receives a transaction,
// it processes it and returns the result.
func (c *Client) Do() error {

	var err error

	// create a context so we have complete controll of the connection
	c.conCtx, c.conCancel = context.WithCancel(context.Background())

	// connect to the cocoon code
	c.stream, err = c.stub.Transact(c.conCtx)
	if err != nil {
		return fmt.Errorf("failed to start transaction stream with cocoon code. %s", err)
	}

	go c.keepStreamAlive()

	for {

		in, err := c.stream.Recv()
		if err == io.EOF {
			return fmt.Errorf("connection with cocoon code has ended")
		}
		if err != nil {
			return fmt.Errorf("failed to read message from cocoon code. %s", err)
		}

		switch in.Invoke {
		case true:
			go func() {
				log.Debugf("New invoke transaction (%s) from cocoon code", in.GetId())
				if err = c.handleInvokeTransaction(in); err != nil {
					log.Error(err.Error())
					c.stream.Send(&proto.Tx{
						Response: true,
						Id:       in.GetId(),
						Status:   500,
						Body:     []byte(err.Error()),
					})
				}
			}()
		case false:
			log.Debugf("New response transaction (%s) from cocoon code", in.GetId())
			go func() {
				if err = c.handleRespTransaction(in); err != nil {
					log.Error(err.Error())
					c.stream.Send(&proto.Tx{
						Response: true,
						Id:       in.GetId(),
						Status:   500,
						Body:     []byte(err.Error()),
					})
				}
			}()
		}
	}
}

// handleInvokeTransaction processes invoke transaction requests
func (c *Client) handleInvokeTransaction(tx *proto.Tx) error {
	switch tx.GetName() {
	case types.TxCreateLedger:
		return c.createLedger(tx)
	case types.TxPut:
		return c.put(tx)
	case types.TxGetLedger:
		return c.getLedger(tx)
	case types.TxGet:
		return c.get(tx, false)
	case types.TxGetByID:
		return c.get(tx, true)
	case types.TxGetBlockByID:
		return c.getBlock(tx)
	case types.TxRangeGet:
		return c.getRange(tx)
	default:
		return c.stream.Send(&proto.Tx{
			Id:       tx.GetId(),
			Response: true,
			Status:   500,
			Body:     []byte(fmt.Sprintf("unsupported transaction name (%s)", tx.GetName())),
		})
	}
}

// handleRespTransaction passes the transaction to a response
// channel with a matching transaction id and deletes the channel afterwards.
func (c *Client) handleRespTransaction(tx *proto.Tx) error {
	if !txRespChannels.Has(tx.GetId()) {
		return fmt.Errorf("response transaction (%s) does not have a corresponding response channel", tx.GetId())
	}

	txRespCh, _ := txRespChannels.Get(tx.GetId())
	txRespCh.(chan *proto.Tx) <- tx
	txRespChannels.Remove(tx.GetId())
	return nil
}

// SendTx sends a transaction to the cocoon code
// and saves the response channel. The response channel will
// be passed a response when it is available in the Transact loop.
func (c *Client) SendTx(tx *proto.Tx, respCh chan *proto.Tx) error {
	if c.stream != nil {
		txRespChannels.Set(tx.GetId(), respCh)
		if err := c.stream.Send(tx); err != nil {
			txRespChannels.Remove(tx.GetId())
			return err
		}
		log.Debugf("Successfully sent transaction (%s) to cocoon code", tx.GetId())
		return nil
	}
	return types.ErrUninitializedStream
}
<commit_msg>debug: remove redial<commit_after>package client

import (
	"fmt"
	"io"
	"os"
	"time"

	"strings"

	"github.com/ncodes/cocoon/core/orderer"
	proto "github.com/ncodes/cocoon/core/runtime/golang/proto"
	"github.com/ncodes/cocoon/core/types"
	logging "github.com/op/go-logging"
	cmap "github.com/orcaman/concurrent-map"
	context "golang.org/x/net/context"
	"google.golang.org/grpc"
)

var log = logging.MustGetLogger("connector.client")

// txChannels holds the channels to send transaction responses to
var txRespChannels = cmap.New()

// Client represents a cocoon code GRPC client
// that interacts with a cocoon code.
type Client struct {
	ccodeAddr             string
	stub                  proto.StubClient
	conCtx                context.Context
	conCancel             context.CancelFunc
	orderDiscoTicker      *time.Ticker
	ordererAddrs          []string
	stream                proto.Stub_TransactClient
	cocoonID              string
	streamKeepAliveTicker *time.Ticker
	stopped               bool
}

// NewClient creates a new cocoon code client
func NewClient() *Client {
	return &Client{}
}

// SetCocoonID sets the cocoon id
func (c *Client) SetCocoonID(id string) {
	c.cocoonID = id
}

// SetCocoonCodeAddr sets the cocoon code bind address
func (c *Client) SetCocoonCodeAddr(ccAddr string) {
	c.ccodeAddr = ccAddr
}

// getCCAddr returns the cocoon code bind address.
// For development, if DEV_COCOON_ADDR is set, it connects to it.
func (c *Client) getCCAddr() string {
	if devCCodeAddr := os.Getenv("DEV_COCOON_ADDR"); len(devCCodeAddr) > 0 {
		return devCCodeAddr
	}
	return c.ccodeAddr
}

// Close the stream and cancel connections
func (c *Client) Close() {
	c.stopped = true
	if c.stream != nil {
		c.stream.CloseSend()
		c.stream = nil
	}
	if c.conCancel != nil {
		c.conCancel()
	}
	if c.orderDiscoTicker != nil {
		c.orderDiscoTicker.Stop()
	}
	if c.streamKeepAliveTicker != nil {
		c.streamKeepAliveTicker.Stop()
	}
}

// keepStreamAlive periodically sends a keep alive message to the stream
// to prevent transport from closing.
func (c *Client) keepStreamAlive() {
	c.streamKeepAliveTicker = time.NewTicker(30 * time.Second)
	for _ = range c.streamKeepAliveTicker.C {
		if c.stream != nil {
			c.stream.Send(&proto.Tx{
				Invoke: true,
				Status: -100,
			})
			log.Debug("Sent keep alive message to stream")
		}
	}
}

// GetStream returns the grpc stream connected to the grpc cocoon code server
func (c *Client) GetStream() proto.Stub_TransactClient {
	return c.stream
}

// Connect connects to a cocoon code server
// running on a known port
func (c *Client) Connect() error {

	log.Info("Starting cocoon code client")

	// start a ticker to continously discover orderer addreses
	go func() {
		c.orderDiscoTicker = time.NewTicker(60 * time.Second)
		for _ = range c.orderDiscoTicker.C {
			var ordererAddrs []string
			ordererAddrs, err := orderer.DiscoverOrderers()
			if err != nil {
				log.Error(err.Error())
				continue
			}
			c.ordererAddrs = ordererAddrs
		}
	}()

	var ordererAddrs []string
	ordererAddrs, err := orderer.DiscoverOrderers()
	if err != nil {
		return err
	}
	c.ordererAddrs = ordererAddrs

	if len(c.ordererAddrs) > 0 {
		log.Infof("Orderer address list updated. Contains %d orderer address(es)", len(c.ordererAddrs))
	} else {
		log.Warning("No orderer address was found. We won't be able to reach the orderer. ")
	}

	time.AfterFunc(2*time.Second, func() {
		log.Debugf("Now connected to cocoon code at port=%s", strings.Split(c.getCCAddr(), ":")[1])
	})

	// for !c.stopped {

	conn, err := grpc.Dial(c.getCCAddr(), grpc.WithInsecure())
	if err != nil {
		return fmt.Errorf("failed to connect to cocoon code server. %s", err)
	}
	defer conn.Close()

	c.stub = proto.NewStubClient(conn)

	if err = c.Do(); err != nil {
		log.Error(err)
	}

	// log.Debug("Redialling cocoon code")
	// }

	return nil
}

// Do starts a request loop that continously asks the
// server for transactions. When it receives a transaction,
// it processes it and returns the result.
func (c *Client) Do() error {

	var err error

	// create a context so we have complete controll of the connection
	c.conCtx, c.conCancel = context.WithCancel(context.Background())

	// connect to the cocoon code
	c.stream, err = c.stub.Transact(c.conCtx)
	if err != nil {
		return fmt.Errorf("failed to start transaction stream with cocoon code. %s", err)
	}

	go c.keepStreamAlive()

	for {

		in, err := c.stream.Recv()
		if err == io.EOF {
			return fmt.Errorf("connection with cocoon code has ended")
		}
		if err != nil {
			return fmt.Errorf("failed to read message from cocoon code. %s", err)
		}

		switch in.Invoke {
		case true:
			go func() {
				log.Debugf("New invoke transaction (%s) from cocoon code", in.GetId())
				if err = c.handleInvokeTransaction(in); err != nil {
					log.Error(err.Error())
					c.stream.Send(&proto.Tx{
						Response: true,
						Id:       in.GetId(),
						Status:   500,
						Body:     []byte(err.Error()),
					})
				}
			}()
		case false:
			log.Debugf("New response transaction (%s) from cocoon code", in.GetId())
			go func() {
				if err = c.handleRespTransaction(in); err != nil {
					log.Error(err.Error())
					c.stream.Send(&proto.Tx{
						Response: true,
						Id:       in.GetId(),
						Status:   500,
						Body:     []byte(err.Error()),
					})
				}
			}()
		}
	}
}

// handleInvokeTransaction processes invoke transaction requests
func (c *Client) handleInvokeTransaction(tx *proto.Tx) error {
	switch tx.GetName() {
	case types.TxCreateLedger:
		return c.createLedger(tx)
	case types.TxPut:
		return c.put(tx)
	case types.TxGetLedger:
		return c.getLedger(tx)
	case types.TxGet:
		return c.get(tx, false)
	case types.TxGetByID:
		return c.get(tx, true)
	case types.TxGetBlockByID:
		return c.getBlock(tx)
	case types.TxRangeGet:
		return c.getRange(tx)
	default:
		return c.stream.Send(&proto.Tx{
			Id:       tx.GetId(),
			Response: true,
			Status:   500,
			Body:     []byte(fmt.Sprintf("unsupported transaction name (%s)", tx.GetName())),
		})
	}
}

// handleRespTransaction passes the transaction to a response
// channel with a matching transaction id and deletes the channel afterwards.
func (c *Client) handleRespTransaction(tx *proto.Tx) error {
	if !txRespChannels.Has(tx.GetId()) {
		return fmt.Errorf("response transaction (%s) does not have a corresponding response channel", tx.GetId())
	}

	txRespCh, _ := txRespChannels.Get(tx.GetId())
	txRespCh.(chan *proto.Tx) <- tx
	txRespChannels.Remove(tx.GetId())
	return nil
}

// SendTx sends a transaction to the cocoon code
// and saves the response channel. The response channel will
// be passed a response when it is available in the Transact loop.
func (c *Client) SendTx(tx *proto.Tx, respCh chan *proto.Tx) error {
	if c.stream != nil {
		txRespChannels.Set(tx.GetId(), respCh)
		if err := c.stream.Send(tx); err != nil {
			txRespChannels.Remove(tx.GetId())
			return err
		}
		log.Debugf("Successfully sent transaction (%s) to cocoon code", tx.GetId())
		return nil
	}
	return types.ErrUninitializedStream
}
<|endoftext|>


<commit_before>package sirius

import (
	"strings"
)

/*
TextEditAction represents a series of
edits to the message Text property

Usage:

var msg Message

edit := msg.EditText()
edit.Substitute("foo", "bar")
edit.Append("-ending")

 */
type TextEditAction struct {
	mutations []TextMutation
}

func (*Message) EditText() *TextEditAction {
	return &TextEditAction{}
}

func (edit *TextEditAction) Perform(msg *Message) error {
	for _, m := range edit.mutations {
		msg.Text = m.Apply(msg.Text)
	}

	return nil
}

func (edit *TextEditAction) Substitute(search string, sub string) *TextEditAction {
	edit.add(&SubMutation{
		Search: search,
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) Append(app string) *TextEditAction {
	edit.add(&AppendMutation{
		Appendix: app,
	})

	return edit
}

func (edit *TextEditAction) add(m TextMutation) {
	edit.mutations = append(edit.mutations, m)
}

/*
TextTransform represents a string mutation
*/
type TextMutation interface {
	Apply(text string) string
}

type SubMutation struct {
	Search string
	Sub    string
}

type AppendMutation struct {
	Appendix string
}

func (st *SubMutation) Apply(text string) string {
	return strings.Replace(text, st.Search, st.Sub, -1)
}

func (at *AppendMutation) Apply(text string) string {
	if len(at.Appendix) == 0 {
		return text
	}

	return text + at.Appendix
}
<commit_msg>Add ReplaceMutation<commit_after>package sirius

import (
	"strings"
)

/*
TextEditAction represents a series of
edits to the message Text property

Usage:

var msg Message

edit := msg.EditText()
edit.Substitute("foo", "bar")
edit.Append("-ending")

 */
type TextEditAction struct {
	mutations []TextMutation
}

func (*Message) EditText() *TextEditAction {
	return &TextEditAction{}
}

func (edit *TextEditAction) Perform(msg *Message) error {
	for _, m := range edit.mutations {
		msg.Text = m.Apply(msg.Text)
	}

	return nil
}

func (edit *TextEditAction) ReplaceWith(replacement string) *TextEditAction {
	edit.add(&ReplaceMutation{
		Replacement: replacement,
	})

	return edit
}

func (edit *TextEditAction) Substitute(search string, sub string) *TextEditAction {
	edit.add(&SubMutation{
		Search: search,
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) Append(app string) *TextEditAction {
	edit.add(&AppendMutation{
		Appendix: app,
	})

	return edit
}

func (edit *TextEditAction) add(m TextMutation) {
	edit.mutations = append(edit.mutations, m)
}

/*
TextTransform represents a string mutation
*/
type TextMutation interface {
	Apply(text string) string
}

type ReplaceMutation struct {
	Replacement string
}

type SubMutation struct {
	Search string
	Sub    string
}

type AppendMutation struct {
	Appendix string
}

func (rm *ReplaceMutation) Apply(text string) string {
	return rm.Replacement
}

func (sm *SubMutation) Apply(text string) string {
	return strings.Replace(text, sm.Search, sm.Sub, -1)
}

func (am *AppendMutation) Apply(text string) string {
	if len(am.Appendix) == 0 {
		return text
	}

	return text + am.Appendix
}
<|endoftext|>


<commit_before>package peco

import (
	"runtime"
	"testing"
	"time"
	"unicode/utf8"

	"github.com/nsf/termbox-go"
	"github.com/stretchr/testify/assert"
	"golang.org/x/net/context"
)

func TestActionFunc(t *testing.T) {
	called := 0
	af := ActionFunc(func(_ context.Context, _ *Peco, _ termbox.Event) {
		called++
	})
	af.Execute(nil, nil, termbox.Event{})
	if !assert.Equal(t, called, 1, "Expected ActionFunc to be called once, but it got called %d times", called) {
		return
	}
}

func TestActionNames(t *testing.T) {
	// These names MUST exist
	names := []string{
		"peco.ForwardChar",
		"peco.BackwardChar",
		"peco.ForwardWord",
		"peco.BackwardWord",
		"peco.BeginningOfLine",
		"peco.EndOfLine",
		"peco.EndOfFile",
		"peco.DeleteForwardChar",
		"peco.DeleteBackwardChar",
		"peco.DeleteForwardWord",
		"peco.DeleteBackwardWord",
		"peco.KillEndOfLine",
		"peco.DeleteAll",
		"peco.SelectPreviousPage",
		"peco.SelectNextPage",
		"peco.SelectPrevious",
		"peco.SelectNext",
		"peco.ToggleSelection",
		"peco.ToggleSelectionAndSelectNext",
		"peco.RotateMatcher",
		"peco.Finish",
		"peco.Cancel",
	}
	for _, name := range names {
		if _, ok := nameToActions[name]; !ok {
			t.Errorf("Action %s should exist, but it does not", name)
		}
	}
}

func expectCaretPos(t *testing.T, c *Caret, expect int) bool {
	return assert.Equal(t, expect, c.Pos(), "Expected caret position %d, got %d", expect, c.Pos())
}

func expectQueryString(t *testing.T, q *Query, expect string) bool {
	return assert.Equal(t, expect, q.String(), "Expected '%s', got '%s'", expect, q.String())
}

func TestDoDeleteForwardChar(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	doDeleteForwardChar(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "Hello World!") {
		return
	}
	if !expectCaretPos(t, c, 5) {
		return
	}

	c.SetPos(q.Len())
	doDeleteForwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hello World!")
	expectCaretPos(t, c, q.Len())

	c.SetPos(0)
	doDeleteForwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "ello World!")
	expectCaretPos(t, c, 0)
}

func TestDoDeleteForwardWord(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	// delete the comma
	doDeleteForwardWord(ctx, state, termbox.Event{})
	if !expectQueryString(t, q, "Hello World!") {
		return
	}

	if !expectCaretPos(t, c, 5) {
		return
	}

	// at the end of the query, should not delete anything
	c.SetPos(q.Len())
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "Hello World!") {
		return
	}
	if !expectCaretPos(t, c, q.Len()) {
		return
	}

	// back to the first column, should delete 'Hello'
	c.SetPos(0)
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " World!") {
		return
	}

	if !expectCaretPos(t, c, 0) {
		return
	}

	// should delete "World"
	c.SetPos(1)
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " ") {
		return
	}
}

func newPeco() *Peco {
	_, file, _, _ := runtime.Caller(0)
	state := New()
	state.args = []string{"peco", file}
	state.screen = NewDummyScreen()
	return state
}

func TestDoDeleteBackwardChar(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World!")
	expectCaretPos(t, c, 4)

	c.SetPos(q.Len())
	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World")
	expectCaretPos(t, c, q.Len())

	c.SetPos(0)
	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World")
	expectCaretPos(t, c, 0)
}

func TestDoDeleteBackwardWord(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	// In case of an overflow (bug)
	q.query = []rune("foo")
	c.SetPos(5)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	// https://github.com/peco/peco/pull/184#issuecomment-54026739

	// Case 1. " foo<caret>" -> " "
	q.query = []rune(" foo")
	c.SetPos(4)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " ") {
		return
	}

	if !expectCaretPos(t, c, 1) {
		return
	}

	// Case 2. "foo bar<caret>" -> "foo "
	q.query = []rune("foo bar")
	c.SetPos(7)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "foo ") {
		return
	}

	if !expectCaretPos(t, c, 4) {
		return
	}
}

func writeQueryToPrompt(t *testing.T, screen Screen, message string) {
	for str := message; true; {
		r, size := utf8.DecodeRuneInString(str)
		if r == utf8.RuneError {
			if size == 0 {
				t.Logf("End of string reached")
				break
			}
			t.Errorf("Failed to decode run in string: %#U", r)
			return
		}

		if r == ' ' {
			screen.SendEvent(termbox.Event{Key: termbox.KeySpace})
		} else {
			screen.SendEvent(termbox.Event{Ch: r})
		}
		str = str[size:]
	}
}

func TestDoAcceptChar(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	message := "Hello, World!"
	writeQueryToPrompt(t, state.screen, message)
	time.Sleep(500 * time.Millisecond)

	if qs := state.Query().String(); qs != message {
		t.Errorf("Expected query to be populated as '%s', but got '%s'", message, qs)
	}

	state.Caret().Move(-1 * len("World!"))
	writeQueryToPrompt(t, state.screen, "Cruel ")

	time.Sleep(500 * time.Millisecond)

	expected := "Hello, Cruel World!"
	if qs := state.Query().String(); qs != expected {
		t.Errorf("Expected query to be populated as '%s', but got '%s'", expected, qs)
	}
}

func TestRotateFilter(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	size := state.filters.Size()
	if size <= 1 {
		t.Skip("Can't proceed testing, only have 1 filter registered")
		return
	}

	var prev LineFilter
	first := state.Filters().Current()
	prev = first
	for i := 0; i < size; i++ {
		state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlR})

		time.Sleep(500 * time.Millisecond)
		f := state.Filters().Current()
		if f == prev {
			t.Errorf("failed to rotate")
		}
		prev = f
	}

	if first != prev {
		t.Errorf("should have rotated back to first one, but didn't")
	}

	// TODO toggle ExecQuery()
}

func TestBeginningOfLineAndEndOfLine(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	message := "Hello, World!"
	writeQueryToPrompt(t, state.screen, message)
	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlA})
	if cp := state.Caret().Pos(); cp != 0 {
		t.Errorf("Expected caret position to be 0, got %d", cp)
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlE})
	time.Sleep(time.Second)
	if cp := state.Caret().Pos(); cp != len(message) {
		t.Errorf("Expected caret position to be %d, got %d", len(message), cp)
	}

}

func TestBackToInitialFilter(t *testing.T) {
	t.Skip("Wait till we can fix how we set keymaps from the test")
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	state.config.Keymap["C-q"] = "peco.BackToInitialFilter"
	if !assert.Equal(t, state.Filters().current, 0, "Expected filter to be at position 0, got %d", state.Filters().current) {
		return
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlR})
	time.Sleep(time.Second)
	if !assert.Equal(t, state.Filters().current, 1, "Expected filter to be at position 1, got %d", state.Filters().current) {
		return
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlQ})
	time.Sleep(time.Second)
	if !assert.Equal(t, state.Filters().current, 0, "Expected filter to be at position 0, got %d", state.Filters().current) {
		return
	}
}
<commit_msg>Wait for key event to be delivered<commit_after>package peco

import (
	"runtime"
	"testing"
	"time"
	"unicode/utf8"

	"github.com/nsf/termbox-go"
	"github.com/stretchr/testify/assert"
	"golang.org/x/net/context"
)

func TestActionFunc(t *testing.T) {
	called := 0
	af := ActionFunc(func(_ context.Context, _ *Peco, _ termbox.Event) {
		called++
	})
	af.Execute(nil, nil, termbox.Event{})
	if !assert.Equal(t, called, 1, "Expected ActionFunc to be called once, but it got called %d times", called) {
		return
	}
}

func TestActionNames(t *testing.T) {
	// These names MUST exist
	names := []string{
		"peco.ForwardChar",
		"peco.BackwardChar",
		"peco.ForwardWord",
		"peco.BackwardWord",
		"peco.BeginningOfLine",
		"peco.EndOfLine",
		"peco.EndOfFile",
		"peco.DeleteForwardChar",
		"peco.DeleteBackwardChar",
		"peco.DeleteForwardWord",
		"peco.DeleteBackwardWord",
		"peco.KillEndOfLine",
		"peco.DeleteAll",
		"peco.SelectPreviousPage",
		"peco.SelectNextPage",
		"peco.SelectPrevious",
		"peco.SelectNext",
		"peco.ToggleSelection",
		"peco.ToggleSelectionAndSelectNext",
		"peco.RotateMatcher",
		"peco.Finish",
		"peco.Cancel",
	}
	for _, name := range names {
		if _, ok := nameToActions[name]; !ok {
			t.Errorf("Action %s should exist, but it does not", name)
		}
	}
}

func expectCaretPos(t *testing.T, c *Caret, expect int) bool {
	return assert.Equal(t, expect, c.Pos(), "Expected caret position %d, got %d", expect, c.Pos())
}

func expectQueryString(t *testing.T, q *Query, expect string) bool {
	return assert.Equal(t, expect, q.String(), "Expected '%s', got '%s'", expect, q.String())
}

func TestDoDeleteForwardChar(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	doDeleteForwardChar(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "Hello World!") {
		return
	}
	if !expectCaretPos(t, c, 5) {
		return
	}

	c.SetPos(q.Len())
	doDeleteForwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hello World!")
	expectCaretPos(t, c, q.Len())

	c.SetPos(0)
	doDeleteForwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "ello World!")
	expectCaretPos(t, c, 0)
}

func TestDoDeleteForwardWord(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	// delete the comma
	doDeleteForwardWord(ctx, state, termbox.Event{})
	if !expectQueryString(t, q, "Hello World!") {
		return
	}

	if !expectCaretPos(t, c, 5) {
		return
	}

	// at the end of the query, should not delete anything
	c.SetPos(q.Len())
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "Hello World!") {
		return
	}
	if !expectCaretPos(t, c, q.Len()) {
		return
	}

	// back to the first column, should delete 'Hello'
	c.SetPos(0)
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " World!") {
		return
	}

	if !expectCaretPos(t, c, 0) {
		return
	}

	// should delete "World"
	c.SetPos(1)
	doDeleteForwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " ") {
		return
	}
}

func newPeco() *Peco {
	_, file, _, _ := runtime.Caller(0)
	state := New()
	state.args = []string{"peco", file}
	state.screen = NewDummyScreen()
	return state
}

func TestDoDeleteBackwardChar(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	q.query = []rune("Hello, World!")
	c.SetPos(5)

	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World!")
	expectCaretPos(t, c, 4)

	c.SetPos(q.Len())
	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World")
	expectCaretPos(t, c, q.Len())

	c.SetPos(0)
	doDeleteBackwardChar(ctx, state, termbox.Event{})

	expectQueryString(t, q, "Hell, World")
	expectCaretPos(t, c, 0)
}

func TestDoDeleteBackwardWord(t *testing.T) {
	state := newPeco()
	q := state.Query()
	c := state.Caret()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	// In case of an overflow (bug)
	q.query = []rune("foo")
	c.SetPos(5)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	// https://github.com/peco/peco/pull/184#issuecomment-54026739

	// Case 1. " foo<caret>" -> " "
	q.query = []rune(" foo")
	c.SetPos(4)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, " ") {
		return
	}

	if !expectCaretPos(t, c, 1) {
		return
	}

	// Case 2. "foo bar<caret>" -> "foo "
	q.query = []rune("foo bar")
	c.SetPos(7)
	doDeleteBackwardWord(ctx, state, termbox.Event{})

	if !expectQueryString(t, q, "foo ") {
		return
	}

	if !expectCaretPos(t, c, 4) {
		return
	}
}

func writeQueryToPrompt(t *testing.T, screen Screen, message string) {
	for str := message; true; {
		r, size := utf8.DecodeRuneInString(str)
		if r == utf8.RuneError {
			assert.Equal(t, 0, size, "when in error, we should have size == 0")
			return
		}

		if r == ' ' {
			screen.SendEvent(termbox.Event{Key: termbox.KeySpace})
		} else {
			screen.SendEvent(termbox.Event{Ch: r})
		}
		str = str[size:]
	}
}

func TestDoAcceptChar(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	message := "Hello, World!"
	writeQueryToPrompt(t, state.screen, message)
	time.Sleep(500 * time.Millisecond)

	if qs := state.Query().String(); qs != message {
		t.Errorf("Expected query to be populated as '%s', but got '%s'", message, qs)
	}

	state.Caret().Move(-1 * len("World!"))
	writeQueryToPrompt(t, state.screen, "Cruel ")

	time.Sleep(500 * time.Millisecond)

	expected := "Hello, Cruel World!"
	if qs := state.Query().String(); qs != expected {
		t.Errorf("Expected query to be populated as '%s', but got '%s'", expected, qs)
	}
}

func TestRotateFilter(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	size := state.filters.Size()
	if size <= 1 {
		t.Skip("Can't proceed testing, only have 1 filter registered")
		return
	}

	var prev LineFilter
	first := state.Filters().Current()
	prev = first
	for i := 0; i < size; i++ {
		state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlR})

		time.Sleep(500 * time.Millisecond)
		f := state.Filters().Current()
		if f == prev {
			t.Errorf("failed to rotate")
		}
		prev = f
	}

	if first != prev {
		t.Errorf("should have rotated back to first one, but didn't")
	}

	// TODO toggle ExecQuery()
}

func TestBeginningOfLineAndEndOfLine(t *testing.T) {
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	message := "Hello, World!"
	writeQueryToPrompt(t, state.screen, message)
	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlA})

	time.Sleep(time.Second)
	if !assert.Equal(t, state.Caret().Pos(), 0, "Expected caret position to be 0, got %d", state.Caret().Pos()) {
		return
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlE})
	time.Sleep(time.Second)

	if !assert.Equal(t, state.Caret().Pos(), len(message), "Expected caret position to be %d, got %d", len(message), state.Caret().Pos()) {
		return
	}

}

func TestBackToInitialFilter(t *testing.T) {
	t.Skip("Wait till we can fix how we set keymaps from the test")
	state := newPeco()

	ctx, cancel := context.WithCancel(context.Background())
	go state.Run(ctx)
	defer cancel()

	<-state.Ready()

	state.config.Keymap["C-q"] = "peco.BackToInitialFilter"
	if !assert.Equal(t, state.Filters().current, 0, "Expected filter to be at position 0, got %d", state.Filters().current) {
		return
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlR})
	time.Sleep(time.Second)
	if !assert.Equal(t, state.Filters().current, 1, "Expected filter to be at position 1, got %d", state.Filters().current) {
		return
	}

	state.screen.SendEvent(termbox.Event{Key: termbox.KeyCtrlQ})
	time.Sleep(time.Second)
	if !assert.Equal(t, state.Filters().current, 0, "Expected filter to be at position 0, got %d", state.Filters().current) {
		return
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Google Inc.
//
// 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 deep

import (
	"fmt"
	"reflect"

	"github.com/google/gapid/core/data"
)

// Copy recursively copies all fields, map and slice elements from the value
// src to the pointer dst.
func Copy(dst, src interface{}) error {
	d, s := reflect.ValueOf(dst), reflect.ValueOf(src)
	if d.Kind() != reflect.Ptr {
		return fmt.Errorf("dst should be a pointer, got %T", dst)
	}
	return reflectCopy(d.Elem(), s, "val", map[reflect.Value]reflect.Value{})
}

func reflectCopy(d, s reflect.Value, path string, seen map[reflect.Value]reflect.Value) error {
	//	fmt.Printf("%v: d:%v (%v), s:%v (%v) %+v\n", path, d.Type(), d.Kind(), s.Type(), s.Kind(), s.Interface())
	if d.Kind() != s.Kind() && d.Kind() != reflect.Interface {
		if d.Kind() == reflect.Ptr && s.Kind() == reflect.Interface {
			// To workaround https://github.com/golang/go/issues/20013, cyclic
			// type declarations are declared using an interface{} for the
			// pointer.
			// See box.go.
			return reflectCopy(d, s.Elem(), path, seen)
		}
		return fmt.Errorf("Kind mismatch at %v. %v (%v) != %v (%v)",
			path, d.Kind(), d.Type(), s.Kind(), s.Type())
	}
	if !d.CanSet() {
		return fmt.Errorf("Cannot assign to %v", path)
	}

	if a, ok := d.Addr().Interface().(data.Assignable); ok && a.Assign(s.Interface()) {
		return nil
	}

	switch d.Kind() {
	case reflect.Struct:
		for i, c := 0, d.Type().NumField(); i < c; i++ {
			f := d.Type().Field(i)
			if f.PkgPath != "" {
				continue // Unexported.
			}
			d, s := d.Field(i), s.FieldByName(f.Name)
			if !s.IsValid() {
				continue // Source is missing field
			}
			if err := reflectCopy(d, s, path+"."+f.Name, seen); err != nil {
				return err
			}
		}
		return nil
	case reflect.Map:
		if s.IsNil() {
			d.Set(s)
			return nil
		}
		d.Set(reflect.MakeMap(d.Type()))
		for _, k := range s.MapKeys() {
			v := reflect.New(d.Type().Elem()).Elem()
			path := path + fmt.Sprintf("[%v]", k.Interface())
			if err := reflectCopy(v, s.MapIndex(k), path, seen); err != nil {
				return err
			}
			d.SetMapIndex(k, v)
		}
		return nil
	case reflect.Slice:
		if s.IsNil() {
			d.Set(reflect.New(d.Type()).Elem()) // Assign nil
			return nil
		}
		d.Set(reflect.MakeSlice(s.Type(), s.Len(), s.Len()))
		for i, c := 0, s.Len(); i < c; i++ {
			path := path + fmt.Sprintf("[%v]", i)
			if err := reflectCopy(d.Index(i), s.Index(i), path, seen); err != nil {
				return err
			}
		}
		return nil
	case reflect.Ptr:
		if s.IsNil() {
			d.Set(reflect.New(d.Type()).Elem()) // Assign nil
			return nil
		}
		d.Set(reflect.New(d.Type().Elem())) // Assign new(T)
		if s, cyclic := seen[s]; cyclic {
			d.Elem().Set(s.Elem())
			return nil
		}
		seen[s] = d
		return reflectCopy(d.Elem(), s.Elem(), path, seen)
	default:
		v := s.Convert(d.Type())
		d.Set(v)
		return nil
	}
}
<commit_msg>core/data/deep: Add Clone()<commit_after>// Copyright (C) 2017 Google Inc.
//
// 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 deep

import (
	"fmt"
	"reflect"

	"github.com/google/gapid/core/data"
)

// Clone makes a deep copy of v.
func Clone(v interface{}) (interface{}, error) {
	s := reflect.ValueOf(v)
	d := reflect.New(s.Type())
	if err := reflectCopy(d.Elem(), s, "val", map[reflect.Value]reflect.Value{}); err != nil {
		return nil, err
	}
	return d.Elem().Interface(), nil
}

// Copy recursively copies all fields, map and slice elements from the value
// src to the pointer dst.
func Copy(dst, src interface{}) error {
	d, s := reflect.ValueOf(dst), reflect.ValueOf(src)
	if d.Kind() != reflect.Ptr {
		return fmt.Errorf("dst should be a pointer, got %T", dst)
	}
	return reflectCopy(d.Elem(), s, "val", map[reflect.Value]reflect.Value{})
}

func reflectCopy(d, s reflect.Value, path string, seen map[reflect.Value]reflect.Value) error {
	//	fmt.Printf("%v: d:%v (%v), s:%v (%v) %+v\n", path, d.Type(), d.Kind(), s.Type(), s.Kind(), s.Interface())
	if d.Kind() != s.Kind() && d.Kind() != reflect.Interface {
		if d.Kind() == reflect.Ptr && s.Kind() == reflect.Interface {
			// To workaround https://github.com/golang/go/issues/20013, cyclic
			// type declarations are declared using an interface{} for the
			// pointer.
			// See box.go.
			return reflectCopy(d, s.Elem(), path, seen)
		}
		return fmt.Errorf("Kind mismatch at %v. %v (%v) != %v (%v)",
			path, d.Kind(), d.Type(), s.Kind(), s.Type())
	}
	if !d.CanSet() {
		return fmt.Errorf("Cannot assign to %v", path)
	}

	if a, ok := d.Addr().Interface().(data.Assignable); ok && a.Assign(s.Interface()) {
		return nil
	}

	switch d.Kind() {
	case reflect.Struct:
		for i, c := 0, d.Type().NumField(); i < c; i++ {
			f := d.Type().Field(i)
			if f.PkgPath != "" {
				continue // Unexported.
			}
			d, s := d.Field(i), s.FieldByName(f.Name)
			if !s.IsValid() {
				continue // Source is missing field
			}
			if err := reflectCopy(d, s, path+"."+f.Name, seen); err != nil {
				return err
			}
		}
		return nil
	case reflect.Map:
		if s.IsNil() {
			d.Set(s)
			return nil
		}
		d.Set(reflect.MakeMap(d.Type()))
		for _, k := range s.MapKeys() {
			v := reflect.New(d.Type().Elem()).Elem()
			path := path + fmt.Sprintf("[%v]", k.Interface())
			if err := reflectCopy(v, s.MapIndex(k), path, seen); err != nil {
				return err
			}
			d.SetMapIndex(k, v)
		}
		return nil
	case reflect.Slice:
		if s.IsNil() {
			d.Set(reflect.New(d.Type()).Elem()) // Assign nil
			return nil
		}
		d.Set(reflect.MakeSlice(s.Type(), s.Len(), s.Len()))
		for i, c := 0, s.Len(); i < c; i++ {
			path := path + fmt.Sprintf("[%v]", i)
			if err := reflectCopy(d.Index(i), s.Index(i), path, seen); err != nil {
				return err
			}
		}
		return nil
	case reflect.Ptr:
		if s.IsNil() {
			d.Set(reflect.New(d.Type()).Elem()) // Assign nil
			return nil
		}
		d.Set(reflect.New(d.Type().Elem())) // Assign new(T)
		if s, cyclic := seen[s]; cyclic {
			d.Elem().Set(s.Elem())
			return nil
		}
		seen[s] = d
		return reflectCopy(d.Elem(), s.Elem(), path, seen)
	default:
		v := s.Convert(d.Type())
		d.Set(v)
		return nil
	}
}
<|endoftext|>


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

package fakestorage_test

import (
	"context"
	"fmt"
	"io/ioutil"

	"github.com/fsouza/fake-gcs-server/fakestorage"
)

func ExampleServer_Client() {
	server := fakestorage.NewServer([]fakestorage.Object{
		{
			BucketName: "some-bucket",
			Name:       "some/object/file.txt",
			Content:    []byte("inside the file"),
		},
	})
	defer server.Stop()
	client := server.Client()
	object := client.Bucket("some-bucket").Object("some/object/file.txt")
	reader, err := object.NewReader(context.Background())
	if err != nil {
		panic(err)
	}
	defer reader.Close()
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", data)
	// Output: inside the file
}

func ExampleServer_with_host_port() {
	server, err := fakestorage.NewServerWithHostPort([]fakestorage.Object{
		{
			BucketName: "some-bucket",
			Name:       "some/object/file.txt",
			Content:    []byte("inside the file"),
		},
	}, "127.0.0.1", 8081)
	if err != nil {
		panic(err)
	}
	defer server.Stop()
	client := server.Client()
	object := client.Bucket("some-bucket").Object("some/object/file.txt")
	reader, err := object.NewReader(context.Background())
	if err != nil {
		panic(err)
	}
	defer reader.Close()
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", data)
	// Output: inside the file
}
<commit_msg>Update example test to use NewServerWithOptions (#156)<commit_after>// Copyright 2017 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fakestorage_test

import (
	"context"
	"fmt"
	"io/ioutil"

	"github.com/fsouza/fake-gcs-server/fakestorage"
)

func ExampleServer_Client() {
	server := fakestorage.NewServer([]fakestorage.Object{
		{
			BucketName: "some-bucket",
			Name:       "some/object/file.txt",
			Content:    []byte("inside the file"),
		},
	})
	defer server.Stop()
	client := server.Client()
	object := client.Bucket("some-bucket").Object("some/object/file.txt")
	reader, err := object.NewReader(context.Background())
	if err != nil {
		panic(err)
	}
	defer reader.Close()
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", data)
	// Output: inside the file
}

func ExampleServer_with_host_port() {
	server, err := fakestorage.NewServerWithOptions(fakestorage.Options{
		InitialObjects: []fakestorage.Object{
			{
				BucketName: "some-bucket",
				Name:       "some/object/file.txt",
				Content:    []byte("inside the file"),
			},
		},
		Host: "127.0.0.1",
		Port: 8081,
	})
	if err != nil {
		panic(err)
	}
	defer server.Stop()
	client := server.Client()
	object := client.Bucket("some-bucket").Object("some/object/file.txt")
	reader, err := object.NewReader(context.Background())
	if err != nil {
		panic(err)
	}
	defer reader.Close()
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", data)
	// Output: inside the file
}
<|endoftext|>


<commit_before>package cache

import (
	"io/ioutil"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
)

type S3Cache struct {
	cacheBucket string
	s3Client    *s3.S3
}

const (
	TemporaryCacheDir = "/tmp/risu/cache"
)

func NewS3Cache() Cache {
	if os.Getenv("AWS_ACCESS_KEY_ID") == "" || os.Getenv("AWS_SECRET_ACCESS_KEY") == "" {
		// TODO: raise error if AWS credentials are not set
		return nil
	}

	s3Client := s3.New(nil)

	var cacheBucket string

	if os.Getenv("RISU_CACHE_BUCKET") != "" {
		cacheBucket = os.Getenv("RISU_CACHE_BUCKET")
	}

	// TODO: raise error if bucket not found

	return &S3Cache{cacheBucket, s3Client}
}

func (c *S3Cache) Get(key string) (string, error) {
	temporaryCache := cacheFilePath(DefaultCacheDir, key)
	inflateDir := inflateDirPath(DefaultCacheDir, key)

	_, err := c.s3Client.HeadObject(
		&s3.HeadObjectInput{
			Bucket: aws.String(c.cacheBucket),
			Key:    aws.String(key),
		})

	if err != nil {
		if awsErr, ok := err.(awserr.RequestFailure); ok && awsErr.StatusCode() == 404 {
			return "", nil
		}

		return "", err
	}

	resp, err := c.s3Client.GetObject(
		&s3.GetObjectInput{
			Bucket: aws.String(c.cacheBucket),
			Key:    aws.String(key),
		})

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

	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)

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

	if err = ioutil.WriteFile(temporaryCache, data, 0644); err != nil {
		return "", err
	}

	if err = InflateTarGz(temporaryCache, inflateDir); err != nil {
		return "", err
	}

	return inflateDir, nil
}

func (c *S3Cache) Put(key, directory string) error {
	temporaryCache := cacheFilePath(DefaultCacheDir, key)

	if err := DeflateTarGz(temporaryCache, directory); err != nil {
		return err
	}

	file, err := os.Open(temporaryCache)

	if err != nil {
		return err
	}
	defer file.Close()

	_, err = c.s3Client.PutObject(
		&s3.PutObjectInput{
			ACL:    aws.String("private"),
			Bucket: aws.String(c.cacheBucket),
			Body:   file,
			Key:    aws.String(key),
		})

	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Check bucket exists<commit_after>package cache

import (
	"io/ioutil"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
)

type S3Cache struct {
	cacheBucket string
	s3Client    *s3.S3
}

const (
	TemporaryCacheDir = "/tmp/risu/cache"
)

func NewS3Cache() Cache {
	if os.Getenv("AWS_ACCESS_KEY_ID") == "" || os.Getenv("AWS_SECRET_ACCESS_KEY") == "" {
		// TODO: raise error if AWS credentials are not set
		return nil
	}

	s3Client := s3.New(nil)

	var cacheBucket string

	if os.Getenv("RISU_CACHE_BUCKET") != "" {
		cacheBucket = os.Getenv("RISU_CACHE_BUCKET")
	}

	_, err := s3Client.HeadBucket(
		&s3.HeadBucketInput{
			Bucket: aws.String(cacheBucket),
		})

	if err != nil {
		// TODO: raise error if bucket not found
		return nil
	}

	return &S3Cache{cacheBucket, s3Client}
}

func (c *S3Cache) Get(key string) (string, error) {
	temporaryCache := cacheFilePath(DefaultCacheDir, key)
	inflateDir := inflateDirPath(DefaultCacheDir, key)

	_, err := c.s3Client.HeadObject(
		&s3.HeadObjectInput{
			Bucket: aws.String(c.cacheBucket),
			Key:    aws.String(key),
		})

	if err != nil {
		if awsErr, ok := err.(awserr.RequestFailure); ok && awsErr.StatusCode() == 404 {
			return "", nil
		}

		return "", err
	}

	resp, err := c.s3Client.GetObject(
		&s3.GetObjectInput{
			Bucket: aws.String(c.cacheBucket),
			Key:    aws.String(key),
		})

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

	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)

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

	if err = ioutil.WriteFile(temporaryCache, data, 0644); err != nil {
		return "", err
	}

	if err = InflateTarGz(temporaryCache, inflateDir); err != nil {
		return "", err
	}

	return inflateDir, nil
}

func (c *S3Cache) Put(key, directory string) error {
	temporaryCache := cacheFilePath(DefaultCacheDir, key)

	if err := DeflateTarGz(temporaryCache, directory); err != nil {
		return err
	}

	file, err := os.Open(temporaryCache)

	if err != nil {
		return err
	}
	defer file.Close()

	_, err = c.s3Client.PutObject(
		&s3.PutObjectInput{
			ACL:    aws.String("private"),
			Bucket: aws.String(c.cacheBucket),
			Body:   file,
			Key:    aws.String(key),
		})

	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package tictactoe

import (
	"errors"

	"google.golang.org/appengine/datastore"
)

type Game struct {
	K            *datastore.Key `json:"-",datastore:"__key__"`
	UserX        string         `json:"userX"`
	UserO        string         `json:"userO"`
	Board        string         `json:"board"`
	MoveX        bool           `json:"moveX"`
	Winner       string         `json:"winner"`
	WinningBoard string         `json:"winningBoard"`
}

func NewGame() *Game {
	g := Game{}
	g.Board = "         " // 9 spaces
	g.MoveX = true
	return &g
}

// CheckWin returns "X" or "O", depending on who won. It will be empty if the game was a draw.
func (g *Game) CheckWin() (winner string, gameOver bool) {
	// Check horizontal/vertical
	for i := 0; i < 3; i++ {
		if g.Board[i+0] != ' ' && g.Board[i+0] == g.Board[i+3] && g.Board[i+3] == g.Board[i+6] {
			return string(g.Board[i+0]), true
		}
		j := i * 3
		if g.Board[j+0] != ' ' && g.Board[j+0] == g.Board[j+1] && g.Board[j+1] == g.Board[j+2] {
			return string(g.Board[j+0]), true
		}
	}
	// Check diagonals
	if g.Board[0] != ' ' && g.Board[0] == g.Board[4] && g.Board[4] == g.Board[8] {
		return string(g.Board[0]), true
	}
	if g.Board[2] != ' ' && g.Board[2] == g.Board[4] && g.Board[4] == g.Board[6] {
		return string(g.Board[2]), true
	}

	// Check draw
	for _, c := range g.Board {
		if c == ' ' {
			return "", false
		}
	}

	return "Draw", true
}

// MoveAt plays a move at the specified index.
// Input is assumed to be valid.
func (g *Game) MoveAt(index int) error {
	if g.Board[index] != ' ' {
		return errors.New("Not an empty space")
	}
	player := "X"
	if !g.MoveX {
		player = "O"
	}
	g.Board = g.Board[0:index] + player + g.Board[index+1:len(g.Board)]
	return nil
}
<commit_msg>appengine/firebase: fix struct tags (#192)<commit_after>// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package tictactoe

import (
	"errors"

	"google.golang.org/appengine/datastore"
)

type Game struct {
	K            *datastore.Key `json:"-" datastore:"__key__"`
	UserX        string         `json:"userX"`
	UserO        string         `json:"userO"`
	Board        string         `json:"board"`
	MoveX        bool           `json:"moveX"`
	Winner       string         `json:"winner"`
	WinningBoard string         `json:"winningBoard"`
}

func NewGame() *Game {
	g := Game{}
	g.Board = "         " // 9 spaces
	g.MoveX = true
	return &g
}

// CheckWin returns "X" or "O", depending on who won. It will be empty if the game was a draw.
func (g *Game) CheckWin() (winner string, gameOver bool) {
	// Check horizontal/vertical
	for i := 0; i < 3; i++ {
		if g.Board[i+0] != ' ' && g.Board[i+0] == g.Board[i+3] && g.Board[i+3] == g.Board[i+6] {
			return string(g.Board[i+0]), true
		}
		j := i * 3
		if g.Board[j+0] != ' ' && g.Board[j+0] == g.Board[j+1] && g.Board[j+1] == g.Board[j+2] {
			return string(g.Board[j+0]), true
		}
	}
	// Check diagonals
	if g.Board[0] != ' ' && g.Board[0] == g.Board[4] && g.Board[4] == g.Board[8] {
		return string(g.Board[0]), true
	}
	if g.Board[2] != ' ' && g.Board[2] == g.Board[4] && g.Board[4] == g.Board[6] {
		return string(g.Board[2]), true
	}

	// Check draw
	for _, c := range g.Board {
		if c == ' ' {
			return "", false
		}
	}

	return "Draw", true
}

// MoveAt plays a move at the specified index.
// Input is assumed to be valid.
func (g *Game) MoveAt(index int) error {
	if g.Board[index] != ' ' {
		return errors.New("Not an empty space")
	}
	player := "X"
	if !g.MoveX {
		player = "O"
	}
	g.Board = g.Board[0:index] + player + g.Board[index+1:len(g.Board)]
	return nil
}
<|endoftext|>


<commit_before>package environment

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"

	ini "github.com/vaughan0/go-ini"

	yaml "gopkg.in/yaml.v2"
)

func configFormatNoneParser(path string) (envs map[string]string, err error) {
	return make(map[string]string), nil
}

func configFormatJSONParser(filename string) (envs map[string]string, err error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	var unmarshalled interface{}
	err = json.Unmarshal(content, &unmarshalled)
	if err != nil {
		return
	}

	convertedMap, converted := unmarshalled.(map[string]interface{})
	if !converted {
		return nil, fmt.Errorf("Incorrect JSON content in file %s", filename)
	}

	envs = make(map[string]string)
	for key, value := range convertedMap {
		strValue, converted := value.(string)
		if !converted {
			return nil, fmt.Errorf("Cannot convert %v to string", value)
		}
		envs[key] = strValue
	}

	return
}

func configFormatYAMLParser(filename string) (envs map[string]string, err error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	var unmarshalled interface{}
	err = yaml.Unmarshal(content, &unmarshalled)
	if err != nil {
		return
	}

	convertedMap, converted := unmarshalled.(map[string]interface{})
	if !converted {
		return nil, fmt.Errorf("Incorrect YAML content in file %s", filename)
	}

	envs = make(map[string]string)
	for key, value := range convertedMap {
		strValue, converted := value.(string)
		if !converted {
			return nil, fmt.Errorf("Cannot convert %v to string", value)
		}
		envs[key] = strValue
	}

	return
}

func configFormatINIParser(filename string) (envs map[string]string, err error) {
	file, err := ini.LoadFile(filename)
	if err != nil {
		return
	}

	envs = make(map[string]string)
	for _, data := range file {
		for key, value := range data {
			envs[key] = value
		}
	}

	return
}

func configFormatEnvDirParser(dirname string) (envs map[string]string, err error) {
	files, err := ioutil.ReadDir(dirname)
	if err != nil {
		return
	}

	envs = make(map[string]string)
	for _, item := range files {
		if item.IsDir() || item.Size() == 0 {
			continue
		}

		path := filepath.Join(dirname, item.Name())
		content, err := ioutil.ReadFile(path)
		if err != nil {
			continue
		}

		envs[item.Name()] = strings.TrimSpace(string(content))
	}

	return
}
<commit_msg>Small fix<commit_after>package environment

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"

	ini "github.com/vaughan0/go-ini"

	yaml "gopkg.in/yaml.v2"
)

func configFormatNoneParser(path string) (envs map[string]string, err error) {
	return make(map[string]string), nil
}

func configFormatJSONParser(filename string) (envs map[string]string, err error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	var unmarshalled interface{}
	err = json.Unmarshal(content, &unmarshalled)
	if err != nil {
		return
	}

	convertedMap, converted := unmarshalled.(map[string]interface{})
	if !converted {
		return nil, fmt.Errorf("Incorrect JSON content in file %s", filename)
	}

	envs = make(map[string]string)
	for key, value := range convertedMap {
		strValue, converted := value.(string)
		if !converted {
			return nil, fmt.Errorf("Cannot convert %v to string", value)
		}
		envs[key] = strValue
	}

	return
}

func configFormatYAMLParser(filename string) (envs map[string]string, err error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	var unmarshalled interface{}
	err = yaml.Unmarshal(content, &unmarshalled)
	if err != nil {
		return
	}

	convertedMap, converted := unmarshalled.(map[string]interface{})
	if !converted {
		return nil, fmt.Errorf("Incorrect YAML content in file %s", filename)
	}

	envs = make(map[string]string)
	for key, value := range convertedMap {
		strValue, converted := value.(string)
		if !converted {
			return nil, fmt.Errorf("Cannot convert %v to string", value)
		}
		envs[key] = strValue
	}

	return
}

func configFormatINIParser(filename string) (envs map[string]string, err error) {
	file, err := ini.LoadFile(filename)
	if err != nil {
		return
	}

	envs = make(map[string]string)
	for _, data := range file {
		for key, value := range data {
			envs[key] = value
		}
	}

	return
}

func configFormatEnvDirParser(dirname string) (envs map[string]string, err error) {
	files, err := ioutil.ReadDir(dirname)
	if err != nil {
		return
	}

	envs = make(map[string]string)
	for _, item := range files {
		if item.IsDir() {
			continue
		}

		if item.Size() == 0 {
			env[item.Name()] = ""
			continue
		}

		path := filepath.Join(dirname, item.Name())
		content, err := ioutil.ReadFile(path)
		if err != nil {
			continue
		}

		envs[item.Name()] = strings.TrimSpace(string(content))
	}

	return
}
<|endoftext|>