<commit_before>// Copyright 2016 The Cockroach 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.
//
// Author: Marc Berhault (marc@cockroachlabs.com)

// Package testserver provides helpers to run a cockroach binary within tests.
// It automatically downloads the latest cockroach binary for your platform
// (Linux-amd64 and Darwin-amd64 only for now), or attempts to run "cockroach"
// from your PATH.
//
// A normal invocation is (check err every time):
// ts, err := testserver.NewTestServer()
// err = ts.Start()
// defer ts.Stop()
// url := ts.PGURL()
//
// To use, run as follows:
//   import "github.com/cockroachdb/cockroach-go/testserver"
//   import "testing"
//   import "time"
//
//   func TestRunServer(t *testing.T) {
//      ts, err := testserver.NewTestServer()
//      if err != nil {
//        t.Fatal(err)
//      }
//      err := ts.Start()
//      if err != nil {
//        t.Fatal(err)
//      }
//      defer ts.Stop()
//
//      url := ts.PGURL()
//      if url != nil {
//        t.FatalF("url not found")
//      }
//      t.Logf("URL: %s", url.String())
//
//      db, err := sql.Open("postgres", url.String())
//      if err != nil {
//        t.Fatal(err)
//      }
//    }
package testserver

import (
	"database/sql"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"testing"
	"time"

	// Import postgres driver.

	_ "github.com/lib/pq"
)

var customBinary = flag.String("cockroach-binary", "", "Use specified cockroach binary")

const (
	stateNew = 1 + iota
	stateRunning
	stateStopped
	stateFailed
)

// TestServer is a helper to run a real cockroach node.
type TestServer struct {
	mu      sync.RWMutex
	state   int
	baseDir string
	pgURL   struct {
		set chan struct{}
		u   *url.URL
	}
	cmd              *exec.Cmd
	args             []string
	stdout           string
	stderr           string
	stdoutBuf        logWriter
	stderrBuf        logWriter
	listeningURLFile string
}

// NewDBForTest creates a new CockroachDB TestServer instance and
// opens a SQL database connection to it. Returns a sql *DB instance a
// shutdown function. The caller is responsible for executing the
// returned shutdown function on exit.
func NewDBForTest(t *testing.T) (*sql.DB, func()) {
	return NewDBForTestWithDatabase(t, "")
}

// NewDBForTestWithDatabase creates a new CockroachDB TestServer
// instance and opens a SQL database connection to it. If database is
// specified, the returned connection will explicitly connect to
// it. Returns a sql *DB instance a shutdown function. The caller is
// responsible for executing the returned shutdown function on exit.
func NewDBForTestWithDatabase(t *testing.T, database string) (*sql.DB, func()) {
	ts, err := NewTestServer()
	if err != nil {
		t.Fatal(err)
	}

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

	url := ts.PGURL()
	if url == nil {
		t.Fatalf("url not found")
	}
	if len(database) > 0 {
		url.Path = database
	}

	db, err := sql.Open("postgres", url.String())
	if err != nil {
		t.Fatal(err)
	}

	if err := ts.WaitForInit(db); err != nil {
		t.Fatal(err)
	}

	return db, func() {
		_ = db.Close()
		ts.Stop()
	}
}

// NewTestServer creates a new TestServer, but does not start it.
// The cockroach binary for your OS and ARCH is downloaded automatically.
// If the download fails, we attempt just call "cockroach", hoping it is
// found in your path.
func NewTestServer() (*TestServer, error) {
	var cockroachBinary string
	var err error
	if len(*customBinary) > 0 {
		cockroachBinary = *customBinary
		log.Printf("Using custom cockroach binary: %s", cockroachBinary)
	} else if cockroachBinary, err = downloadLatestBinary(); err != nil {
		log.Printf("Failed to fetch latest binary: %s, attempting to use cockroach binary from your PATH", err)
		cockroachBinary = "cockroach"
	} else {
		log.Printf("Using automatically-downloaded binary: %s", cockroachBinary)
	}

	// Force "/tmp/" so avoid OSX's really long temp directory names
	// which get us over the socket filename length limit.
	baseDir, err := ioutil.TempDir("/tmp", "cockroach-testserver")
	if err != nil {
		return nil, fmt.Errorf("could not create temp directory: %s", err)
	}

	logDir := filepath.Join(baseDir, "logs")
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("could not create logs directory: %s: %s", logDir, err)
	}

	listeningURLFile := filepath.Join(baseDir, "listen-url")

	args := []string{
		cockroachBinary,
		"start",
		"--logtostderr",
		"--insecure",
		"--host=localhost",
		"--port=0",
		"--http-port=0",
		"--store=" + baseDir,
		"--listening-url-file=" + listeningURLFile,
	}

	ts := &TestServer{
		state:            stateNew,
		baseDir:          baseDir,
		args:             args,
		stdout:           filepath.Join(logDir, "cockroach.stdout"),
		stderr:           filepath.Join(logDir, "cockroach.stderr"),
		listeningURLFile: listeningURLFile,
	}
	ts.pgURL.set = make(chan struct{})
	return ts, nil
}

// Stdout returns the entire contents of the process' stdout.
func (ts *TestServer) Stdout() string {
	return ts.stdoutBuf.String()
}

// Stderr returns the entire contents of the process' stderr.
func (ts *TestServer) Stderr() string {
	return ts.stderrBuf.String()
}

// PGURL returns the postgres connection URL to reach the started
// cockroach node.
//
// It blocks until the network URL is determined and does not timeout,
// relying instead on test timeouts.
func (ts *TestServer) PGURL() *url.URL {
	<-ts.pgURL.set
	return ts.pgURL.u
}

func (ts *TestServer) setPGURL(u *url.URL) {
	ts.pgURL.u = u
	close(ts.pgURL.set)
}

// WaitForInit retries until a connection is successfully established.
func (ts *TestServer) WaitForInit(db *sql.DB) error {
	var err error
	for i := 0; i < 50; i++ {
		if _, err = db.Query("SHOW DATABASES"); err == nil {
			return err
		}
		log.Printf("WaitForInit: %v", err)
		time.Sleep(time.Millisecond * 100)
	}
	return err
}

func (ts *TestServer) pollListeningURLFile() error {
	var data []byte
	for {
		ts.mu.Lock()
		state := ts.state
		ts.mu.Unlock()
		if state != stateRunning {
			return fmt.Errorf("server stopped or crashed before listening URL file was available")
		}

		var err error
		data, err = ioutil.ReadFile(ts.listeningURLFile)
		if err == nil {
			break
		} else if !os.IsNotExist(err) {
			return fmt.Errorf("unexpected error while reading listening URL file: %v", err)
		}
		time.Sleep(100 * time.Millisecond)
	}

	u, err := url.Parse(string(data))
	if err != nil {
		return fmt.Errorf("failed to parse SQL URL: %v", err)
	}
	ts.setPGURL(u)

	return nil
}

// Start runs the process, returning an error on any problems,
// including being unable to start, but not unexpected failure.
// It should only be called once in the lifetime of a TestServer object.
func (ts *TestServer) Start() error {
	ts.mu.Lock()
	if ts.state != stateNew {
		ts.mu.Unlock()
		return errors.New("Start() can only be called once")
	}
	ts.state = stateRunning
	ts.mu.Unlock()

	ts.cmd = exec.Command(ts.args[0], ts.args[1:]...)
	ts.cmd.Env = []string{"COCKROACH_MAX_OFFSET=1ns"}

	if len(ts.stdout) > 0 {
		wr, err := newFileLogWriter(ts.stdout)
		if err != nil {
			return fmt.Errorf("unable to open file %s: %s", ts.stdout, err)
		}
		ts.stdoutBuf = wr
	}
	ts.cmd.Stdout = ts.stdoutBuf

	if len(ts.stderr) > 0 {
		wr, err := newFileLogWriter(ts.stderr)
		if err != nil {
			return fmt.Errorf("unable to open file %s: %s", ts.stderr, err)
		}
		ts.stderrBuf = wr
	}
	ts.cmd.Stderr = ts.stderrBuf

	for k, v := range defaultEnv() {
		ts.cmd.Env = append(ts.cmd.Env, k+"="+v)
	}

	err := ts.cmd.Start()
	if ts.cmd.Process != nil {
		log.Printf("process %d started: %s", ts.cmd.Process.Pid, strings.Join(ts.args, " "))
	}
	if err != nil {
		log.Printf(err.Error())
		ts.stdoutBuf.Close()
		ts.stderrBuf.Close()

		ts.mu.Lock()
		ts.state = stateFailed
		ts.mu.Unlock()

		return fmt.Errorf("failure starting process: %s", err)
	}

	go func() {
		ts.cmd.Wait()

		ts.stdoutBuf.Close()
		ts.stderrBuf.Close()

		ps := ts.cmd.ProcessState
		sy := ps.Sys().(syscall.WaitStatus)

		log.Printf("Process %d exited with status %d", ps.Pid(), sy.ExitStatus())
		log.Printf(ps.String())

		ts.mu.Lock()
		if sy.ExitStatus() == 0 {
			ts.state = stateStopped
		} else {
			ts.state = stateFailed
		}
		ts.mu.Unlock()
	}()

	go func() {
		if err := ts.pollListeningURLFile(); err != nil {
			log.Printf("%v", err)
			close(ts.pgURL.set)
			ts.Stop()
		}
	}()

	return nil
}

// Stop kills the process if it is still running and cleans its directory.
// It should only be called once in the lifetime of a TestServer object.
// Logs fatal if the process has already failed.
func (ts *TestServer) Stop() {
	ts.mu.RLock()
	defer ts.mu.RUnlock()

	if ts.state == stateNew {
		log.Fatal("Stop() called, but Start() was never called")
	}
	if ts.state == stateFailed {
		log.Fatalf("Stop() called, but process exited unexpectedly. Stdout:\n%s\nStderr:\n%s\n",
			ts.Stdout(), ts.Stderr())
		return
	}

	if ts.state != stateStopped {
		// Only call kill if not running. It could have exited properly.
		ts.cmd.Process.Kill()
	}

	// Only cleanup on intentional stops.
	_ = os.RemoveAll(ts.baseDir)
}

type logWriter interface {
	Write(p []byte) (n int, err error)
	String() string
	Len() int64
	Close()
}

type fileLogWriter struct {
	filename string
	file     *os.File
}

func newFileLogWriter(file string) (*fileLogWriter, error) {
	f, err := os.Create(file)
	if err != nil {
		return nil, err
	}

	return &fileLogWriter{
		filename: file,
		file:     f,
	}, nil
}

func (w fileLogWriter) Close() {
	w.file.Close()
}

func (w fileLogWriter) Write(p []byte) (n int, err error) {
	return w.file.Write(p)
}

func (w fileLogWriter) String() string {
	b, err := ioutil.ReadFile(w.filename)
	if err == nil {
		return string(b)
	}
	return ""
}

func (w fileLogWriter) Len() int64 {
	s, err := os.Stat(w.filename)
	if err == nil {
		return s.Size()
	}
	return 0
}

func defaultEnv() map[string]string {
	vars := map[string]string{}
	u, err := user.Current()
	if err == nil {
		if _, ok := vars["USER"]; !ok {
			vars["USER"] = u.Username
		}
		if _, ok := vars["UID"]; !ok {
			vars["UID"] = u.Uid
		}
		if _, ok := vars["GID"]; !ok {
			vars["GID"] = u.Gid
		}
		if _, ok := vars["HOME"]; !ok {
			vars["HOME"] = u.HomeDir
		}
	}
	if _, ok := vars["PATH"]; !ok {
		vars["PATH"] = os.Getenv("PATH")
	}
	return vars
}
<commit_msg>remove stray whitespace<commit_after>// Copyright 2016 The Cockroach 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.
//
// Author: Marc Berhault (marc@cockroachlabs.com)

// Package testserver provides helpers to run a cockroach binary within tests.
// It automatically downloads the latest cockroach binary for your platform
// (Linux-amd64 and Darwin-amd64 only for now), or attempts to run "cockroach"
// from your PATH.
//
// A normal invocation is (check err every time):
// ts, err := testserver.NewTestServer()
// err = ts.Start()
// defer ts.Stop()
// url := ts.PGURL()
//
// To use, run as follows:
//   import "github.com/cockroachdb/cockroach-go/testserver"
//   import "testing"
//   import "time"
//
//   func TestRunServer(t *testing.T) {
//      ts, err := testserver.NewTestServer()
//      if err != nil {
//        t.Fatal(err)
//      }
//      err := ts.Start()
//      if err != nil {
//        t.Fatal(err)
//      }
//      defer ts.Stop()
//
//      url := ts.PGURL()
//      if url != nil {
//        t.FatalF("url not found")
//      }
//      t.Logf("URL: %s", url.String())
//
//      db, err := sql.Open("postgres", url.String())
//      if err != nil {
//        t.Fatal(err)
//      }
//    }
package testserver

import (
	"database/sql"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"testing"
	"time"

	// Import postgres driver.
	_ "github.com/lib/pq"
)

var customBinary = flag.String("cockroach-binary", "", "Use specified cockroach binary")

const (
	stateNew = 1 + iota
	stateRunning
	stateStopped
	stateFailed
)

// TestServer is a helper to run a real cockroach node.
type TestServer struct {
	mu      sync.RWMutex
	state   int
	baseDir string
	pgURL   struct {
		set chan struct{}
		u   *url.URL
	}
	cmd              *exec.Cmd
	args             []string
	stdout           string
	stderr           string
	stdoutBuf        logWriter
	stderrBuf        logWriter
	listeningURLFile string
}

// NewDBForTest creates a new CockroachDB TestServer instance and
// opens a SQL database connection to it. Returns a sql *DB instance a
// shutdown function. The caller is responsible for executing the
// returned shutdown function on exit.
func NewDBForTest(t *testing.T) (*sql.DB, func()) {
	return NewDBForTestWithDatabase(t, "")
}

// NewDBForTestWithDatabase creates a new CockroachDB TestServer
// instance and opens a SQL database connection to it. If database is
// specified, the returned connection will explicitly connect to
// it. Returns a sql *DB instance a shutdown function. The caller is
// responsible for executing the returned shutdown function on exit.
func NewDBForTestWithDatabase(t *testing.T, database string) (*sql.DB, func()) {
	ts, err := NewTestServer()
	if err != nil {
		t.Fatal(err)
	}

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

	url := ts.PGURL()
	if url == nil {
		t.Fatalf("url not found")
	}
	if len(database) > 0 {
		url.Path = database
	}

	db, err := sql.Open("postgres", url.String())
	if err != nil {
		t.Fatal(err)
	}

	if err := ts.WaitForInit(db); err != nil {
		t.Fatal(err)
	}

	return db, func() {
		_ = db.Close()
		ts.Stop()
	}
}

// NewTestServer creates a new TestServer, but does not start it.
// The cockroach binary for your OS and ARCH is downloaded automatically.
// If the download fails, we attempt just call "cockroach", hoping it is
// found in your path.
func NewTestServer() (*TestServer, error) {
	var cockroachBinary string
	var err error
	if len(*customBinary) > 0 {
		cockroachBinary = *customBinary
		log.Printf("Using custom cockroach binary: %s", cockroachBinary)
	} else if cockroachBinary, err = downloadLatestBinary(); err != nil {
		log.Printf("Failed to fetch latest binary: %s, attempting to use cockroach binary from your PATH", err)
		cockroachBinary = "cockroach"
	} else {
		log.Printf("Using automatically-downloaded binary: %s", cockroachBinary)
	}

	// Force "/tmp/" so avoid OSX's really long temp directory names
	// which get us over the socket filename length limit.
	baseDir, err := ioutil.TempDir("/tmp", "cockroach-testserver")
	if err != nil {
		return nil, fmt.Errorf("could not create temp directory: %s", err)
	}

	logDir := filepath.Join(baseDir, "logs")
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("could not create logs directory: %s: %s", logDir, err)
	}

	listeningURLFile := filepath.Join(baseDir, "listen-url")

	args := []string{
		cockroachBinary,
		"start",
		"--logtostderr",
		"--insecure",
		"--host=localhost",
		"--port=0",
		"--http-port=0",
		"--store=" + baseDir,
		"--listening-url-file=" + listeningURLFile,
	}

	ts := &TestServer{
		state:            stateNew,
		baseDir:          baseDir,
		args:             args,
		stdout:           filepath.Join(logDir, "cockroach.stdout"),
		stderr:           filepath.Join(logDir, "cockroach.stderr"),
		listeningURLFile: listeningURLFile,
	}
	ts.pgURL.set = make(chan struct{})
	return ts, nil
}

// Stdout returns the entire contents of the process' stdout.
func (ts *TestServer) Stdout() string {
	return ts.stdoutBuf.String()
}

// Stderr returns the entire contents of the process' stderr.
func (ts *TestServer) Stderr() string {
	return ts.stderrBuf.String()
}

// PGURL returns the postgres connection URL to reach the started
// cockroach node.
//
// It blocks until the network URL is determined and does not timeout,
// relying instead on test timeouts.
func (ts *TestServer) PGURL() *url.URL {
	<-ts.pgURL.set
	return ts.pgURL.u
}

func (ts *TestServer) setPGURL(u *url.URL) {
	ts.pgURL.u = u
	close(ts.pgURL.set)
}

// WaitForInit retries until a connection is successfully established.
func (ts *TestServer) WaitForInit(db *sql.DB) error {
	var err error
	for i := 0; i < 50; i++ {
		if _, err = db.Query("SHOW DATABASES"); err == nil {
			return err
		}
		log.Printf("WaitForInit: %v", err)
		time.Sleep(time.Millisecond * 100)
	}
	return err
}

func (ts *TestServer) pollListeningURLFile() error {
	var data []byte
	for {
		ts.mu.Lock()
		state := ts.state
		ts.mu.Unlock()
		if state != stateRunning {
			return fmt.Errorf("server stopped or crashed before listening URL file was available")
		}

		var err error
		data, err = ioutil.ReadFile(ts.listeningURLFile)
		if err == nil {
			break
		} else if !os.IsNotExist(err) {
			return fmt.Errorf("unexpected error while reading listening URL file: %v", err)
		}
		time.Sleep(100 * time.Millisecond)
	}

	u, err := url.Parse(string(data))
	if err != nil {
		return fmt.Errorf("failed to parse SQL URL: %v", err)
	}
	ts.setPGURL(u)

	return nil
}

// Start runs the process, returning an error on any problems,
// including being unable to start, but not unexpected failure.
// It should only be called once in the lifetime of a TestServer object.
func (ts *TestServer) Start() error {
	ts.mu.Lock()
	if ts.state != stateNew {
		ts.mu.Unlock()
		return errors.New("Start() can only be called once")
	}
	ts.state = stateRunning
	ts.mu.Unlock()

	ts.cmd = exec.Command(ts.args[0], ts.args[1:]...)
	ts.cmd.Env = []string{"COCKROACH_MAX_OFFSET=1ns"}

	if len(ts.stdout) > 0 {
		wr, err := newFileLogWriter(ts.stdout)
		if err != nil {
			return fmt.Errorf("unable to open file %s: %s", ts.stdout, err)
		}
		ts.stdoutBuf = wr
	}
	ts.cmd.Stdout = ts.stdoutBuf

	if len(ts.stderr) > 0 {
		wr, err := newFileLogWriter(ts.stderr)
		if err != nil {
			return fmt.Errorf("unable to open file %s: %s", ts.stderr, err)
		}
		ts.stderrBuf = wr
	}
	ts.cmd.Stderr = ts.stderrBuf

	for k, v := range defaultEnv() {
		ts.cmd.Env = append(ts.cmd.Env, k+"="+v)
	}

	err := ts.cmd.Start()
	if ts.cmd.Process != nil {
		log.Printf("process %d started: %s", ts.cmd.Process.Pid, strings.Join(ts.args, " "))
	}
	if err != nil {
		log.Printf(err.Error())
		ts.stdoutBuf.Close()
		ts.stderrBuf.Close()

		ts.mu.Lock()
		ts.state = stateFailed
		ts.mu.Unlock()

		return fmt.Errorf("failure starting process: %s", err)
	}

	go func() {
		ts.cmd.Wait()

		ts.stdoutBuf.Close()
		ts.stderrBuf.Close()

		ps := ts.cmd.ProcessState
		sy := ps.Sys().(syscall.WaitStatus)

		log.Printf("Process %d exited with status %d", ps.Pid(), sy.ExitStatus())
		log.Printf(ps.String())

		ts.mu.Lock()
		if sy.ExitStatus() == 0 {
			ts.state = stateStopped
		} else {
			ts.state = stateFailed
		}
		ts.mu.Unlock()
	}()

	go func() {
		if err := ts.pollListeningURLFile(); err != nil {
			log.Printf("%v", err)
			close(ts.pgURL.set)
			ts.Stop()
		}
	}()

	return nil
}

// Stop kills the process if it is still running and cleans its directory.
// It should only be called once in the lifetime of a TestServer object.
// Logs fatal if the process has already failed.
func (ts *TestServer) Stop() {
	ts.mu.RLock()
	defer ts.mu.RUnlock()

	if ts.state == stateNew {
		log.Fatal("Stop() called, but Start() was never called")
	}
	if ts.state == stateFailed {
		log.Fatalf("Stop() called, but process exited unexpectedly. Stdout:\n%s\nStderr:\n%s\n",
			ts.Stdout(), ts.Stderr())
		return
	}

	if ts.state != stateStopped {
		// Only call kill if not running. It could have exited properly.
		ts.cmd.Process.Kill()
	}

	// Only cleanup on intentional stops.
	_ = os.RemoveAll(ts.baseDir)
}

type logWriter interface {
	Write(p []byte) (n int, err error)
	String() string
	Len() int64
	Close()
}

type fileLogWriter struct {
	filename string
	file     *os.File
}

func newFileLogWriter(file string) (*fileLogWriter, error) {
	f, err := os.Create(file)
	if err != nil {
		return nil, err
	}

	return &fileLogWriter{
		filename: file,
		file:     f,
	}, nil
}

func (w fileLogWriter) Close() {
	w.file.Close()
}

func (w fileLogWriter) Write(p []byte) (n int, err error) {
	return w.file.Write(p)
}

func (w fileLogWriter) String() string {
	b, err := ioutil.ReadFile(w.filename)
	if err == nil {
		return string(b)
	}
	return ""
}

func (w fileLogWriter) Len() int64 {
	s, err := os.Stat(w.filename)
	if err == nil {
		return s.Size()
	}
	return 0
}

func defaultEnv() map[string]string {
	vars := map[string]string{}
	u, err := user.Current()
	if err == nil {
		if _, ok := vars["USER"]; !ok {
			vars["USER"] = u.Username
		}
		if _, ok := vars["UID"]; !ok {
			vars["UID"] = u.Uid
		}
		if _, ok := vars["GID"]; !ok {
			vars["GID"] = u.Gid
		}
		if _, ok := vars["HOME"]; !ok {
			vars["HOME"] = u.HomeDir
		}
	}
	if _, ok := vars["PATH"]; !ok {
		vars["PATH"] = os.Getenv("PATH")
	}
	return vars
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"code.google.com/p/go-commander"

	s "github.com/thinxer/gocoins"
)

func init() {
	cmd := newCmd("balance", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		b, err := client.Balance()
		check(err)
		for k, v := range b {
			fmt.Printf("%v:%v\n", k, v)
		}
	}
}

func trade(c s.Client, tradeType s.TradeType, args []string) {
	price := must(strconv.ParseFloat(args[0], 64)).(float64)
	amount := must(strconv.ParseFloat(args[1], 64)).(float64)
	id, err := client.Trade(tradeType, flagPair, price, amount)
	check(err)
	fmt.Println(id)
}

func init() {
	cmd := newCmd("buy", "price amount")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trade(client, s.Buy, args)
	}
}

func init() {
	cmd := newCmd("sell", "price amount")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trade(client, s.Sell, args)
	}
}

func init() {
	cmd := newCmd("orders", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orders, err := client.Orders()
		check(err)
		for _, o := range orders {
			fmt.Println(o)
		}
	}
}

func init() {
	cmd := newCmd("cancel", "orderid")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orderId := must(strconv.ParseInt(args[0], 10, 64)).(int64)
		ok, err := client.Cancel(orderId)
		check(err)
		fmt.Println(ok)
	}
}

func init() {
	cmd := newCmd("transactions", "[-limit 50]")
	limit := (&cmd.Flag).Int("limit", 50, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		tr, err := client.Transactions(*limit)
		check(err)
		for _, t := range tr {
			fmt.Println(t)
		}
	}
}

func init() {
	cmd := newCmd("history", "[-since=-1]")
	since := (&cmd.Flag).Int64("since", -1, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trades, _, err := client.History(flagPair, *since)
		check(err)
		for _, t := range trades {
			fmt.Println(t)
		}

	}
}

func init() {
	cmd := newCmd("orderbook", "[-limit 50]")
	limit := flag.Int("limit", 50, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orders, err := client.Orderbook(flagPair, *limit)
		check(err)
		fmt.Println("Asks:")
		for _, o := range orders.Asks {
			fmt.Printf("%v\t%v\n", o.Price, o.Amount)
		}
		fmt.Println("Bids:")
		for _, o := range orders.Bids {
			fmt.Printf("%v\t%v\n", o.Price, o.Amount)
		}

	}
}

func init() {
	cmd := newCmd("watch", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		ct := make(chan s.Trade)
		go client.Stream(flagPair, -1, ct)
		for t := range ct {
			fmt.Println(t)
		}
	}
}

func init() {
	cmd := newCmd("ticker", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		ticker, err := client.Ticker(flagPair)
		check(err)
		fmt.Printf("%+v\n", ticker)
	}
}

func check(err error) {
	if err != nil {
		_, file, line, _ := runtime.Caller(1)
		fmt.Fprintf(os.Stderr, "Error: %v [%s:%d]\n", err, file, line)
		os.Exit(2)
	}
}

func must(v interface{}, err error) interface{} {
	if err != nil {
		panic(err)
	}
	return v
}
<commit_msg>cli: make orderbook results readable<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"code.google.com/p/go-commander"

	s "github.com/thinxer/gocoins"
)

func init() {
	cmd := newCmd("balance", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		b, err := client.Balance()
		check(err)
		for k, v := range b {
			fmt.Printf("%v:%v\n", k, v)
		}
	}
}

func trade(c s.Client, tradeType s.TradeType, args []string) {
	price := must(strconv.ParseFloat(args[0], 64)).(float64)
	amount := must(strconv.ParseFloat(args[1], 64)).(float64)
	id, err := client.Trade(tradeType, flagPair, price, amount)
	check(err)
	fmt.Println(id)
}

func init() {
	cmd := newCmd("buy", "price amount")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trade(client, s.Buy, args)
	}
}

func init() {
	cmd := newCmd("sell", "price amount")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trade(client, s.Sell, args)
	}
}

func init() {
	cmd := newCmd("orders", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orders, err := client.Orders()
		check(err)
		for _, o := range orders {
			fmt.Println(o)
		}
	}
}

func init() {
	cmd := newCmd("cancel", "orderid")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orderId := must(strconv.ParseInt(args[0], 10, 64)).(int64)
		ok, err := client.Cancel(orderId)
		check(err)
		fmt.Println(ok)
	}
}

func init() {
	cmd := newCmd("transactions", "[-limit 50]")
	limit := (&cmd.Flag).Int("limit", 50, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		tr, err := client.Transactions(*limit)
		check(err)
		for _, t := range tr {
			fmt.Println(t)
		}
	}
}

func init() {
	cmd := newCmd("history", "[-since=-1]")
	since := (&cmd.Flag).Int64("since", -1, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		trades, _, err := client.History(flagPair, *since)
		check(err)
		for _, t := range trades {
			fmt.Println(t)
		}

	}
}

func init() {
	cmd := newCmd("orderbook", "[-limit 50]")
	limit := flag.Int("limit", 50, "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		orders, err := client.Orderbook(flagPair, *limit)
		check(err)
		fmt.Println("Amount\t\tAsks\t\tBids\t\tAmount")
		min := len(orders.Asks)
		if len(orders.Bids) < min {
			min = len(orders.Bids)
		}
		for i := 0; i < min; i++ {
			fmt.Printf("%-16.12g%-16.12g%-16.12g%-16.12g\n", orders.Asks[i].Amount, orders.Asks[i].Price, orders.Bids[i].Price, orders.Bids[i].Amount)
		}
	}
}

func init() {
	cmd := newCmd("watch", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		ct := make(chan s.Trade)
		go client.Stream(flagPair, -1, ct)
		for t := range ct {
			fmt.Println(t)
		}
	}
}

func init() {
	cmd := newCmd("ticker", "")
	cmd.Run = func(cmd *commander.Command, args []string) {
		ticker, err := client.Ticker(flagPair)
		check(err)
		fmt.Printf("%+v\n", ticker)
	}
}

func check(err error) {
	if err != nil {
		_, file, line, _ := runtime.Caller(1)
		fmt.Fprintf(os.Stderr, "Error: %v [%s:%d]\n", err, file, line)
		os.Exit(2)
	}
}

func must(v interface{}, err error) interface{} {
	if err != nil {
		panic(err)
	}
	return v
}
<|endoftext|>


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

package gohg_lib

import (
	"errors"
	// "log"
	"strconv"
	"strings"
)

// Version provides the 'hg version' command.
func (hgcl *HgClient) Version(args []string) (ver string, err error) {
	var data []byte
	var ret int32
	cmd_args := []string{"version"}
	// if args != "" {
	// log.Println(len(args))
	if len(args) > 0 {
		for _, a := range args {
			if a != "" {
				cmd_args = append(cmd_args, a)
			}
		}
	}
	// log.Println(cmd_args)
	data, ret, err = hgcl.run(cmd_args)
	if err != nil {
		return "", err
	}
	if ret != 0 {
		return "", errors.New("run(\"version\") returned: " + strconv.Itoa(int(ret)))
	}
	ver = strings.Split(string(data), "\n")[0]
	if len(ver) > 0 {
		ver = strings.Split(ver, "\n")[0]
		ver = ver[strings.LastIndex(ver, " ")+1 : len(ver)-1]
	}

	// This test first disturbed the call to getHgVersion() from Connect()
	// in gohg.go, because at that moment HgClient.hgVersion is not set yet
	// (in fact that call is exactly trying to do that).
	if hgcl.hgVersion != "" && ver != hgcl.hgVersion {
		return "", errors.New("run(\"version\"): expected '" + hgcl.hgVersion + "' and got '" + ver + "'")
	}

	return ver, nil
}
<commit_msg>Version: clean-up comments<commit_after>// Copyright 2012, The gohg Authors. All rights reserved.
// Use of this source code is governed by a BSD style license
// that can be found in the LICENSE.txt file.

package gohg_lib

import (
	"errors"
	"strconv"
	"strings"
)

// Version provides the 'hg version' command.
func (hgcl *HgClient) Version(args []string) (ver string, err error) {
	var data []byte
	var ret int32
	cmd_args := []string{"version"}
	if len(args) > 0 {
		for _, a := range args {
			if a != "" {
				cmd_args = append(cmd_args, a)
			}
		}
	}
	data, ret, err = hgcl.run(cmd_args)
	if err != nil {
		return "", err
	}
	if ret != 0 {
		return "", errors.New("run(\"version\") returned: " + strconv.Itoa(int(ret)))
	}
	ver = strings.Split(string(data), "\n")[0]
	if len(ver) > 0 {
		ver = strings.Split(ver, "\n")[0]
		ver = ver[strings.LastIndex(ver, " ")+1 : len(ver)-1]
	}

	// This test first disturbed the call to getHgVersion() from Connect()
	// in gohg.go, because at that moment HgClient.hgVersion is not set yet
	// (in fact that call is exactly trying to do that).
	if hgcl.hgVersion != "" && ver != hgcl.hgVersion {
		return "", errors.New("run(\"version\"): expected '" + hgcl.hgVersion + "' and got '" + ver + "'")
	}

	return ver, nil
}
<|endoftext|>


<commit_before>package ecsbackend

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws/awserr"
	awsecs "github.com/aws/aws-sdk-go/service/ecs"
	"github.com/quintilesims/layer0/api/backend/ecs/id"
	"github.com/quintilesims/layer0/common/aws/cloudwatchlogs"
	"github.com/quintilesims/layer0/common/aws/ecs"
	"github.com/quintilesims/layer0/common/config"
	"github.com/quintilesims/layer0/common/models"
	"strings"
)

const MAX_TASK_IDS = 100

func boolp(b bool) *bool {
	return &b
}

func pbool(b *bool) bool {
	if b == nil {
		return false
	}

	return *b
}

func stringp(s string) *string {
	return &s
}

func intp(i int) *int {
	return &i
}

func int64p(i int64) *int64 {
	return &i
}

func pstring(s *string) string {
	if s == nil {
		return ""
	}

	return *s
}

func pint(i *int) int {
	if i == nil {
		return 0
	}

	return *i
}

func pint64(i *int64) int64 {
	if i == nil {
		return 0
	}

	return *i
}

func stringOrEmpty(s *string) string {
	if s == nil {
		return ""
	}

	return *s
}

func int64OrZero(i *int64) int64 {
	if i == nil {
		return 0
	}

	return *i
}

func ContainsErrCode(err error, code string) bool {
	if err == nil {
		return false
	}

	awsErr, ok := err.(awserr.Error)
	if !ok {
		return false
	}

	return strings.ToLower(awsErr.Code()) == strings.ToLower(code)
}

func ContainsErrMsg(err error, msg string) bool {
	if err == nil {
		return false
	}

	return strings.Contains(
		strings.ToLower(err.Error()),
		strings.ToLower(msg))
}

// IteratePages performs a do-while loop on a paginatedf
// until nextToken is nil or an error is returned
type paginatedf func(*string) (*string, error)

func IteratePages(fn paginatedf) error {
	var err error
	var nextToken *string

	nextToken, err = fn(nextToken)
	if err != nil {
		return err
	}

	for nextToken != nil {
		nextToken, err = fn(nextToken)
		if err != nil {
			return err
		}
	}

	return nil
}

var CreateRenderedDeploy = func(body []byte) (*Deploy, error) {
	deploy, err := MarshalDeploy(body)
	if err != nil {
		return nil, err
	}

	for _, container := range deploy.ContainerDefinitions {
		if container.LogConfiguration == nil {
			container.LogConfiguration = &awsecs.LogConfiguration{
				LogDriver: stringp("awslogs"),
				Options: map[string]*string{
					"awslogs-group":         stringp(config.AWSLogGroupID()),
					"awslogs-region":        stringp(config.AWSRegion()),
					"awslogs-stream-prefix": stringp("l0"),
				},
			}
		}
	}

	return deploy, nil
}

var getTaskARNs = func(ecs ecs.Provider, ecsEnvironmentID id.ECSEnvironmentID, startedBy *string) ([]*string, error) {
	// we can only check each of the states individually, thus we must issue 3 API calls

	running := "RUNNING"
	tasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &running, startedBy, nil)
	if err != nil {
		return nil, err
	}

	stopped := "STOPPED"
	stoppedTasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &stopped, startedBy, nil)
	if err != nil {
		return nil, err
	}

	pending := "PENDING"
	pendingTasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &pending, startedBy, nil)
	if err != nil {
		return nil, err
	}

	tasks = append(tasks, stoppedTasks...)
	tasks = append(tasks, pendingTasks...)

	return tasks, nil
}

var GetLogs = func(cloudWatchLogs cloudwatchlogs.Provider, taskARNs []*string, tail int) ([]*models.LogFile, error) {
	taskIDCatalog := generateTaskIDCatalog(taskARNs)

	fmt.Println("Getting streams")

	orderBy := "LogStreamName"
	logStreams, err := cloudWatchLogs.DescribeLogStreams(config.AWSLogGroupID(), orderBy)
	if err != nil {
		return nil, err
	}
	fmt.Println("done")

	logFiles := []*models.LogFile{}
	for _, logStream := range logStreams {
		if *logStream.StoredBytes == 0 {
			continue
		}

		// filter by streams that have <prefix>/<container name>/<stream task id>
		streamNameSplit := strings.Split(*logStream.LogStreamName, "/")
		if len(streamNameSplit) != 3 {
			continue
		}

		streamTaskID := streamNameSplit[2]
		if _, ok := taskIDCatalog[streamTaskID]; !ok {
			continue
		}

		logFile := &models.LogFile{
			Name:  streamNameSplit[1],
			Lines: []string{},
		}

		fmt.Println("Getting events")
		// since the time range is exclusive, expand the range to get first/last events
		logEvents, err := cloudWatchLogs.GetLogEvents(
			config.AWSLogGroupID(),
			*logStream.LogStreamName,
			int64(tail))
		if err != nil {
			return nil, err
		}

		for _, logEvent := range logEvents {
			fmt.Println(*logEvent.Message)
			logFile.Lines = append(logFile.Lines, *logEvent.Message)
		}

		fmt.Println("done")
		logFiles = append(logFiles, logFile)
	}

	return logFiles, nil
}

func generateTaskIDCatalog(taskARNs []*string) map[string]bool {
	catalog := map[string]bool{}
	for _, taskARN := range taskARNs {
		taskID := strings.Split(*taskARN, "/")[1]
		catalog[taskID] = true
	}

	return catalog
}
<commit_msg>Removed storedBytes checked<commit_after>package ecsbackend

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws/awserr"
	awsecs "github.com/aws/aws-sdk-go/service/ecs"
	"github.com/quintilesims/layer0/api/backend/ecs/id"
	"github.com/quintilesims/layer0/common/aws/cloudwatchlogs"
	"github.com/quintilesims/layer0/common/aws/ecs"
	"github.com/quintilesims/layer0/common/config"
	"github.com/quintilesims/layer0/common/models"
)

const MAX_TASK_IDS = 100

func boolp(b bool) *bool {
	return &b
}

func pbool(b *bool) bool {
	if b == nil {
		return false
	}

	return *b
}

func stringp(s string) *string {
	return &s
}

func intp(i int) *int {
	return &i
}

func int64p(i int64) *int64 {
	return &i
}

func pstring(s *string) string {
	if s == nil {
		return ""
	}

	return *s
}

func pint(i *int) int {
	if i == nil {
		return 0
	}

	return *i
}

func pint64(i *int64) int64 {
	if i == nil {
		return 0
	}

	return *i
}

func stringOrEmpty(s *string) string {
	if s == nil {
		return ""
	}

	return *s
}

func int64OrZero(i *int64) int64 {
	if i == nil {
		return 0
	}

	return *i
}

func ContainsErrCode(err error, code string) bool {
	if err == nil {
		return false
	}

	awsErr, ok := err.(awserr.Error)
	if !ok {
		return false
	}

	return strings.ToLower(awsErr.Code()) == strings.ToLower(code)
}

func ContainsErrMsg(err error, msg string) bool {
	if err == nil {
		return false
	}

	return strings.Contains(
		strings.ToLower(err.Error()),
		strings.ToLower(msg))
}

// IteratePages performs a do-while loop on a paginatedf
// until nextToken is nil or an error is returned
type paginatedf func(*string) (*string, error)

func IteratePages(fn paginatedf) error {
	var err error
	var nextToken *string

	nextToken, err = fn(nextToken)
	if err != nil {
		return err
	}

	for nextToken != nil {
		nextToken, err = fn(nextToken)
		if err != nil {
			return err
		}
	}

	return nil
}

var CreateRenderedDeploy = func(body []byte) (*Deploy, error) {
	deploy, err := MarshalDeploy(body)
	if err != nil {
		return nil, err
	}

	for _, container := range deploy.ContainerDefinitions {
		if container.LogConfiguration == nil {
			container.LogConfiguration = &awsecs.LogConfiguration{
				LogDriver: stringp("awslogs"),
				Options: map[string]*string{
					"awslogs-group":         stringp(config.AWSLogGroupID()),
					"awslogs-region":        stringp(config.AWSRegion()),
					"awslogs-stream-prefix": stringp("l0"),
				},
			}
		}
	}

	return deploy, nil
}

var getTaskARNs = func(ecs ecs.Provider, ecsEnvironmentID id.ECSEnvironmentID, startedBy *string) ([]*string, error) {
	// we can only check each of the states individually, thus we must issue 3 API calls

	running := "RUNNING"
	tasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &running, startedBy, nil)
	if err != nil {
		return nil, err
	}

	stopped := "STOPPED"
	stoppedTasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &stopped, startedBy, nil)
	if err != nil {
		return nil, err
	}

	pending := "PENDING"
	pendingTasks, err := ecs.ListTasks(ecsEnvironmentID.String(), nil, &pending, startedBy, nil)
	if err != nil {
		return nil, err
	}

	tasks = append(tasks, stoppedTasks...)
	tasks = append(tasks, pendingTasks...)

	return tasks, nil
}

var GetLogs = func(cloudWatchLogs cloudwatchlogs.Provider, taskARNs []*string, tail int) ([]*models.LogFile, error) {
	taskIDCatalog := generateTaskIDCatalog(taskARNs)

	fmt.Println("Getting streams")

	orderBy := "LogStreamName"
	logStreams, err := cloudWatchLogs.DescribeLogStreams(config.AWSLogGroupID(), orderBy)
	if err != nil {
		return nil, err
	}
	fmt.Println("done")

	logFiles := []*models.LogFile{}
	for _, logStream := range logStreams {
		// filter by streams that have <prefix>/<container name>/<stream task id>
		streamNameSplit := strings.Split(*logStream.LogStreamName, "/")
		if len(streamNameSplit) != 3 {
			continue
		}

		streamTaskID := streamNameSplit[2]
		if _, ok := taskIDCatalog[streamTaskID]; !ok {
			continue
		}

		logFile := &models.LogFile{
			Name:  streamNameSplit[1],
			Lines: []string{},
		}

		fmt.Println("Getting events")
		// since the time range is exclusive, expand the range to get first/last events
		logEvents, err := cloudWatchLogs.GetLogEvents(
			config.AWSLogGroupID(),
			*logStream.LogStreamName,
			int64(tail))
		if err != nil {
			return nil, err
		}

		for _, logEvent := range logEvents {
			fmt.Println(*logEvent.Message)
			logFile.Lines = append(logFile.Lines, *logEvent.Message)
		}

		fmt.Println("done")
		logFiles = append(logFiles, logFile)
	}

	return logFiles, nil
}

func generateTaskIDCatalog(taskARNs []*string) map[string]bool {
	catalog := map[string]bool{}
	for _, taskARN := range taskARNs {
		taskID := strings.Split(*taskARN, "/")[1]
		catalog[taskID] = true
	}

	return catalog
}
<|endoftext|>


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

package service

import (
	stderrors "errors"
	"github.com/globocom/tsuru/api/bind"
	"github.com/globocom/tsuru/errors"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
)

type FakeUnit struct {
	ip string
}

func (a *FakeUnit) GetIp() string {
	return a.ip
}

type FakeApp struct {
	ip   string
	name string
}

func (a *FakeApp) GetName() string {
	return a.name
}

func (a *FakeApp) GetUnits() []bind.Unit {
	return []bind.Unit{
		&FakeUnit{ip: a.ip},
	}
}

func (a *FakeApp) InstanceEnv(name string) map[string]bind.EnvVar {
	return nil
}

func (a *FakeApp) SetEnvs(vars []bind.EnvVar, public bool) error {
	return nil
}

func (a *FakeApp) UnsetEnvs(vars []string, public bool) error {
	return nil
}

func noContentHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNoContent)
}

func failHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusInternalServerError)
	w.Write([]byte("Server failed to do its job."))
}

type TestHandler struct {
	body   []byte
	method string
	url    string
}

func (h *TestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	content := `{"MYSQL_DATABASE_NAME": "CHICO", "MYSQL_HOST": "localhost", "MYSQL_PORT": "3306"}`
	h.method = r.Method
	h.url = r.URL.String()
	h.body, _ = ioutil.ReadAll(r.Body)
	w.Write([]byte(content))
}

func (s *S) TestCreateShouldSendTheNameOfTheResourceToTheEndpoint(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Create(&instance)
	c.Assert(err, IsNil)
	expectedUrl := "/resources"
	c.Assert(h.url, Equals, expectedUrl)
	c.Assert(h.method, Equals, "POST")
	v, err := url.ParseQuery(string(h.body))
	c.Assert(err, IsNil)
	c.Assert(map[string][]string(v), DeepEquals, map[string][]string{"name": []string{"my-redis"}})
}

func (s *S) TestCreateShouldReturnErrorIfTheRequestFail(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Create(&instance)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to create the instance "+instance.Name+": Server failed to do its job.$")
}

func (s *S) TestDestroyShouldSendADELETERequestToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Destroy(&instance)
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/"+instance.Name)
	c.Assert(h.method, Equals, "DELETE")
}

func (s *S) TestDestroyShouldReturnErrorIfTheRequestFails(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Destroy(&instance)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to destroy the instance "+instance.Name+": Server failed to do its job.$")
}

func (s *S) TestBindShouldSendAPOSTToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/"+instance.Name)
	c.Assert(h.method, Equals, "POST")
	v, err := url.ParseQuery(string(h.body))
	c.Assert(err, IsNil)
	c.Assert(map[string][]string(v), DeepEquals, map[string][]string{"hostname": []string{"10.0.10.1"}})
}

func (s *S) TestBindShouldReturnMapWithTheEnvironmentVariable(c *C) {
	expected := map[string]string{
		"MYSQL_DATABASE_NAME": "CHICO",
		"MYSQL_HOST":          "localhost",
		"MYSQL_PORT":          "3306",
	}
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	env, err := client.Bind(&instance, &a)
	c.Assert(err, IsNil)
	c.Assert(env, DeepEquals, expected)
}

func (s *S) TestBindShouldReturnErrorIfTheRequestFail(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to bind instance her-redis to the app her-app: Server failed to do its job.$")
}

func (s *S) TestBindShouldReturnPreconditionFailedIfServiceAPIReturnPreconditionFailed(c *C) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(412)
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	c.Assert(err, NotNil)
	e, ok := err.(*errors.Http)
	c.Assert(ok, Equals, true)
	c.Assert(e.Message, Equals, "You cannot bind any app to this service instance because it is not ready yet.")
}

func (s *S) TestUnbindSendADELETERequestToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "heaven-can-wait", ServiceName: "heaven"}
	a := FakeApp{
		name: "arch-enemy",
		ip:   "2.2.2.2",
	}
	client := &Client{endpoint: ts.URL}
	err := client.Unbind(&instance, &a)
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/heaven-can-wait/hostname/2.2.2.2")
	c.Assert(h.method, Equals, "DELETE")
}

func (s *S) TestUnbindReturnsErrorIfTheRequestFails(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "heaven-can-wait", ServiceName: "heaven"}
	a := FakeApp{
		name: "arch-enemy",
		ip:   "2.2.2.2",
	}
	client := &Client{endpoint: ts.URL}
	err := client.Unbind(&instance, &a)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to unbind instance heaven-can-wait from the app arch-enemy: Server failed to do its job.$")
}

func (s *S) TestBuildErrorMessageWithNilResponse(c *C) {
	cli := Client{}
	err := stderrors.New("epic fail")
	c.Assert(cli.buildErrorMessage(err, nil), Equals, "epic fail")
}

func (s *S) TestBuildErrorMessageWithNilErrorAndNilResponse(c *C) {
	cli := Client{}
	c.Assert(cli.buildErrorMessage(nil, nil), Equals, "")
}

func (s *S) TestBuildErrorMessageWithNonNilResponseAndNilError(c *C) {
	cli := Client{}
	body := strings.NewReader("something went wrong")
	resp := &http.Response{Body: ioutil.NopCloser(body)}
	c.Assert(cli.buildErrorMessage(nil, resp), Equals, "something went wrong")
}

func (s *S) TestBuildErrorMessageWithNonNilResponseAndNonNilError(c *C) {
	cli := Client{}
	err := stderrors.New("epic fail")
	body := strings.NewReader("something went wrong")
	resp := &http.Response{Body: ioutil.NopCloser(body)}
	c.Assert(cli.buildErrorMessage(err, resp), Equals, "epic fail")
}

func (s *S) TestStatusShouldSendTheNameAndHostOfTheService(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(noContentHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "up")
}

func (s *S) TestStatusShouldReturnDownWhenApiReturns500(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "down")
}

func (s *S) TestStatusShouldReturnPendingWhenApiReturns202(c *C) {
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusAccepted)
	})
	ts := httptest.NewServer(h)
	defer ts.Close()
	instance := ServiceInstance{Name: "hi_there", ServiceName: "redis"}
	client := Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "pending")
}
<commit_msg>api/service: use a mutex to avoid data races in endpoint tests<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package service

import (
	stderrors "errors"
	"github.com/globocom/tsuru/api/bind"
	"github.com/globocom/tsuru/errors"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"sync"
)

type FakeUnit struct {
	ip string
}

func (a *FakeUnit) GetIp() string {
	return a.ip
}

type FakeApp struct {
	ip   string
	name string
}

func (a *FakeApp) GetName() string {
	return a.name
}

func (a *FakeApp) GetUnits() []bind.Unit {
	return []bind.Unit{
		&FakeUnit{ip: a.ip},
	}
}

func (a *FakeApp) InstanceEnv(name string) map[string]bind.EnvVar {
	return nil
}

func (a *FakeApp) SetEnvs(vars []bind.EnvVar, public bool) error {
	return nil
}

func (a *FakeApp) UnsetEnvs(vars []string, public bool) error {
	return nil
}

func noContentHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusNoContent)
}

func failHandler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusInternalServerError)
	w.Write([]byte("Server failed to do its job."))
}

type TestHandler struct {
	body   []byte
	method string
	url    string
	sync.Mutex
}

func (h *TestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h.Lock()
	defer h.Unlock()
	content := `{"MYSQL_DATABASE_NAME": "CHICO", "MYSQL_HOST": "localhost", "MYSQL_PORT": "3306"}`
	h.method = r.Method
	h.url = r.URL.String()
	h.body, _ = ioutil.ReadAll(r.Body)
	w.Write([]byte(content))
}

func (s *S) TestCreateShouldSendTheNameOfTheResourceToTheEndpoint(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Create(&instance)
	c.Assert(err, IsNil)
	expectedUrl := "/resources"
	h.Lock()
	defer h.Unlock()
	c.Assert(h.url, Equals, expectedUrl)
	c.Assert(h.method, Equals, "POST")
	v, err := url.ParseQuery(string(h.body))
	c.Assert(err, IsNil)
	c.Assert(map[string][]string(v), DeepEquals, map[string][]string{"name": []string{"my-redis"}})
}

func (s *S) TestCreateShouldReturnErrorIfTheRequestFail(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Create(&instance)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to create the instance "+instance.Name+": Server failed to do its job.$")
}

func (s *S) TestDestroyShouldSendADELETERequestToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Destroy(&instance)
	h.Lock()
	defer h.Unlock()
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/"+instance.Name)
	c.Assert(h.method, Equals, "DELETE")
}

func (s *S) TestDestroyShouldReturnErrorIfTheRequestFails(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "his-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	err := client.Destroy(&instance)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to destroy the instance "+instance.Name+": Server failed to do its job.$")
}

func (s *S) TestBindShouldSendAPOSTToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	h.Lock()
	defer h.Unlock()
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/"+instance.Name)
	c.Assert(h.method, Equals, "POST")
	v, err := url.ParseQuery(string(h.body))
	c.Assert(err, IsNil)
	c.Assert(map[string][]string(v), DeepEquals, map[string][]string{"hostname": []string{"10.0.10.1"}})
}

func (s *S) TestBindShouldReturnMapWithTheEnvironmentVariable(c *C) {
	expected := map[string]string{
		"MYSQL_DATABASE_NAME": "CHICO",
		"MYSQL_HOST":          "localhost",
		"MYSQL_PORT":          "3306",
	}
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	env, err := client.Bind(&instance, &a)
	c.Assert(err, IsNil)
	c.Assert(env, DeepEquals, expected)
}

func (s *S) TestBindShouldReturnErrorIfTheRequestFail(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to bind instance her-redis to the app her-app: Server failed to do its job.$")
}

func (s *S) TestBindShouldReturnPreconditionFailedIfServiceAPIReturnPreconditionFailed(c *C) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(412)
	})
	ts := httptest.NewServer(handler)
	defer ts.Close()
	instance := ServiceInstance{Name: "her-redis", ServiceName: "redis"}
	a := FakeApp{
		name: "her-app",
		ip:   "10.0.10.1",
	}
	client := &Client{endpoint: ts.URL}
	_, err := client.Bind(&instance, &a)
	c.Assert(err, NotNil)
	e, ok := err.(*errors.Http)
	c.Assert(ok, Equals, true)
	c.Assert(e.Message, Equals, "You cannot bind any app to this service instance because it is not ready yet.")
}

func (s *S) TestUnbindSendADELETERequestToTheResourceURL(c *C) {
	h := TestHandler{}
	ts := httptest.NewServer(&h)
	defer ts.Close()
	instance := ServiceInstance{Name: "heaven-can-wait", ServiceName: "heaven"}
	a := FakeApp{
		name: "arch-enemy",
		ip:   "2.2.2.2",
	}
	client := &Client{endpoint: ts.URL}
	err := client.Unbind(&instance, &a)
	h.Lock()
	defer h.Unlock()
	c.Assert(err, IsNil)
	c.Assert(h.url, Equals, "/resources/heaven-can-wait/hostname/2.2.2.2")
	c.Assert(h.method, Equals, "DELETE")
}

func (s *S) TestUnbindReturnsErrorIfTheRequestFails(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "heaven-can-wait", ServiceName: "heaven"}
	a := FakeApp{
		name: "arch-enemy",
		ip:   "2.2.2.2",
	}
	client := &Client{endpoint: ts.URL}
	err := client.Unbind(&instance, &a)
	c.Assert(err, NotNil)
	c.Assert(err, ErrorMatches, "^Failed to unbind instance heaven-can-wait from the app arch-enemy: Server failed to do its job.$")
}

func (s *S) TestBuildErrorMessageWithNilResponse(c *C) {
	cli := Client{}
	err := stderrors.New("epic fail")
	c.Assert(cli.buildErrorMessage(err, nil), Equals, "epic fail")
}

func (s *S) TestBuildErrorMessageWithNilErrorAndNilResponse(c *C) {
	cli := Client{}
	c.Assert(cli.buildErrorMessage(nil, nil), Equals, "")
}

func (s *S) TestBuildErrorMessageWithNonNilResponseAndNilError(c *C) {
	cli := Client{}
	body := strings.NewReader("something went wrong")
	resp := &http.Response{Body: ioutil.NopCloser(body)}
	c.Assert(cli.buildErrorMessage(nil, resp), Equals, "something went wrong")
}

func (s *S) TestBuildErrorMessageWithNonNilResponseAndNonNilError(c *C) {
	cli := Client{}
	err := stderrors.New("epic fail")
	body := strings.NewReader("something went wrong")
	resp := &http.Response{Body: ioutil.NopCloser(body)}
	c.Assert(cli.buildErrorMessage(err, resp), Equals, "epic fail")
}

func (s *S) TestStatusShouldSendTheNameAndHostOfTheService(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(noContentHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "up")
}

func (s *S) TestStatusShouldReturnDownWhenApiReturns500(c *C) {
	ts := httptest.NewServer(http.HandlerFunc(failHandler))
	defer ts.Close()
	instance := ServiceInstance{Name: "my-redis", ServiceName: "redis"}
	client := &Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "down")
}

func (s *S) TestStatusShouldReturnPendingWhenApiReturns202(c *C) {
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusAccepted)
	})
	ts := httptest.NewServer(h)
	defer ts.Close()
	instance := ServiceInstance{Name: "hi_there", ServiceName: "redis"}
	client := Client{endpoint: ts.URL}
	state, err := client.Status(&instance)
	c.Assert(err, IsNil)
	c.Assert(state, Equals, "pending")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	var (
		wg sync.WaitGroup
		ch = make(chan int, 1000)
	)

	wg.Add(102)
	go func() {
		for i := 0; i < 100; i++ {
			reqeust(ch, i)
			//time.Sleep(100 * time.Microsecond)
		}

		fmt.Println("send ok.")
		close(ch)
		wg.Done()
	}()

	go func() {
		task(&wg, ch, 10)
		wg.Done()
	}()

	wg.Wait()
	fmt.Println("task over")
}

func reqeust(ch chan int, i int) {
	ch <- i
}

func task(wg *sync.WaitGroup, ch chan int, cn int32) {
	var (
		c  int32
		c2 int32
		s  = make(chan struct{})
	)

	for i := range ch {
		//do something...
		go func(i int) {
			time.Sleep(time.Second)
			fmt.Println("->", i)
			wg.Done()

			atomic.AddInt32(&c2, 1)
			if c2 == cn {
				s <- struct{}{}
				atomic.StoreInt32(&c2, 0)
			}
		}(i)

		c++
		if c == cn {
			fmt.Println("->")
			<-s
			c = 0
		}
	}
}
<commit_msg>print<commit_after>package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

func main() {
	var (
		wg sync.WaitGroup
		ch = make(chan int, 1000)
	)

	wg.Add(102)
	go func() {
		for i := 0; i < 100; i++ {
			reqeust(ch, i)
			//time.Sleep(100 * time.Microsecond)
		}

		close(ch)
		fmt.Println("send ok.")
		wg.Done()
	}()

	go func() {
		task(&wg, ch, 10)
		wg.Done()
	}()

	wg.Wait()
	fmt.Println("over")
}

func reqeust(ch chan int, i int) {
	ch <- i
}

func task(wg *sync.WaitGroup, ch chan int, cn int32) {
	var (
		c  int32
		c2 int32
		s  = make(chan struct{})
	)

	for i := range ch {
		//do something...
		go func(i int) {
			time.Sleep(time.Second)
			fmt.Println("->", i)
			wg.Done()

			atomic.AddInt32(&c2, 1)
			if c2 == cn {
				s <- struct{}{}
				atomic.StoreInt32(&c2, 0)
			}
		}(i)

		c++
		if c == cn {
			fmt.Println("->")
			<-s
			c = 0
		}
	}

	fmt.Println("task over")
}
<|endoftext|>


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

// +build appengine

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net/http"

	"appengine"
	"appengine/urlfetch"
)

const runUrl = "http://golang.org/compile"

func init() {
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/compile", compileHandler)
	err := serveScripts("js", "playground.js")
	if err != nil {
		panic(err)
	}
	if err := initTour("."); err != nil {
		panic(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if err := renderTour(w); err != nil {
		c.Criticalf("template render: %v", err)
	}
}

func compileHandler(w http.ResponseWriter, r *http.Request) {
	if err := passThru(w, r); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, "Compile server error.")
	}
}

func passThru(w io.Writer, req *http.Request) error {
	c := appengine.NewContext(req)
	client := urlfetch.Client(c)
	defer req.Body.Close()
	r, err := client.Post(runUrl, req.Header.Get("Content-type"), req.Body)
	if err != nil {
		c.Errorf("making POST request:", err)
		return err
	}
	defer r.Body.Close()
	if _, err := io.Copy(w, r.Body); err != nil {
		c.Errorf("copying response Body:", err)
		return err
	}
	return nil
}

// prepContent returns a Reader that produces the content from the given
// Reader, but strips the prefix "#appengine: " from each line. It also drops
// any non-blank like that follows a series of 1 or more lines with the prefix.
func prepContent(in io.Reader) io.Reader {
	var prefix = []byte("#appengine: ")
	out, w := io.Pipe()
	go func() {
		r := bufio.NewReader(in)
		drop := false
		for {
			b, err := r.ReadBytes('\n')
			if err != nil && err != io.EOF {
				w.CloseWithError(err)
				return
			}
			if bytes.HasPrefix(b, prefix) {
				b = b[len(prefix):]
				drop = true
			} else if drop {
				if len(b) > 1 {
					b = nil
				}
				drop = false
			}
			if len(b) > 0 {
				w.Write(b)
			}
			if err == io.EOF {
				w.Close()
				return
			}
		}
	}()
	return out
}

// socketAddr returns the WebSocket handler address.
// The App Engine version does not provide a WebSocket handler.
func socketAddr() string { return "" }
<commit_msg>go-tour: use playground package from go.talks for /compile handler<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build appengine

package main

import (
	"bufio"
	"bytes"
	"io"
	"net/http"

	"appengine"

	_ "code.google.com/p/go.talks/pkg/playground"
)

const runUrl = "http://golang.org/compile"

func init() {
	http.HandleFunc("/", rootHandler)
	err := serveScripts("js", "playground.js")
	if err != nil {
		panic(err)
	}
	if err := initTour("."); err != nil {
		panic(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if err := renderTour(w); err != nil {
		c.Criticalf("template render: %v", err)
	}
}

// prepContent returns a Reader that produces the content from the given
// Reader, but strips the prefix "#appengine: " from each line. It also drops
// any non-blank like that follows a series of 1 or more lines with the prefix.
func prepContent(in io.Reader) io.Reader {
	var prefix = []byte("#appengine: ")
	out, w := io.Pipe()
	go func() {
		r := bufio.NewReader(in)
		drop := false
		for {
			b, err := r.ReadBytes('\n')
			if err != nil && err != io.EOF {
				w.CloseWithError(err)
				return
			}
			if bytes.HasPrefix(b, prefix) {
				b = b[len(prefix):]
				drop = true
			} else if drop {
				if len(b) > 1 {
					b = nil
				}
				drop = false
			}
			if len(b) > 0 {
				w.Write(b)
			}
			if err == io.EOF {
				w.Close()
				return
			}
		}
	}()
	return out
}

// socketAddr returns the WebSocket handler address.
// The App Engine version does not provide a WebSocket handler.
func socketAddr() string { return "" }
<|endoftext|>


<commit_before>package gist7480523

import (
	"fmt"
	"go/build"
	"os"
	"strings"

	"github.com/shurcooL/go/exp/12"

	. "github.com/shurcooL/go/gists/gist5504644"
	. "github.com/shurcooL/go/gists/gist7519227"
	. "github.com/shurcooL/go/gists/gist7802150"
)

type GoPackageStringer func(*GoPackage) string

// A GoPackage describes a single package found in a directory.
// This is partially a copy of "cmd/go".Package, except it can be imported and reused. =.=
// https://code.google.com/p/go/source/browse/src/cmd/go/pkg.go?name=release#24
type GoPackage struct {
	Bpkg     *build.Package
	BpkgErr  error
	Standard bool // is this package part of the standard Go library?

	Dir *exp12.Directory
}

func GoPackageFromImportPathFound(importPathFound ImportPathFound) *GoPackage {
	bpkg, err := BuildPackageFromSrcDir(importPathFound.FullPath())
	return goPackageFromBuildPackage(bpkg, err)
}

func GoPackageFromImportPath(importPath string) *GoPackage {
	bpkg, err := BuildPackageFromImportPath(importPath)
	return goPackageFromBuildPackage(bpkg, err)
}

func GoPackageFromPath(path, srcDir string) *GoPackage {
	bpkg, err := build.Import(path, srcDir, 0)
	return goPackageFromBuildPackage(bpkg, err)
}

func goPackageFromBuildPackage(bpkg *build.Package, bpkgErr error) *GoPackage {
	if bpkgErr != nil {
		if _, noGo := bpkgErr.(*build.NoGoError); noGo || bpkg.Dir == "" {
			return nil
		}
	}

	if bpkg.ConflictDir != "" {
		fmt.Fprintf(os.Stderr, "warning: ConflictDir=%q (Dir=%q)", bpkg.ConflictDir, bpkg.Dir)
		return nil
	}

	goPackage := &GoPackage{
		Bpkg:     bpkg,
		BpkgErr:  bpkgErr,
		Standard: bpkg.Goroot && bpkg.ImportPath != "" && !strings.Contains(bpkg.ImportPath, "."), // https://code.google.com/p/go/source/browse/src/cmd/go/pkg.go?name=release#110

		Dir: exp12.LookupDirectory(bpkg.Dir),
	}

	/*if goPackage.Bpkg.Goroot == false { // Optimization that assume packages under Goroot are not under vcs
		// TODO: markAsNotNeedToUpdate() because of external insight?
	}*/

	return goPackage
}

// This is okay to call concurrently (a mutex is used internally).
// Actually, not completely okay because MakeUpdated technology is not thread-safe.
func (this *GoPackage) UpdateVcs() {
	if this.Bpkg.Goroot == false { // Optimization that assume packages under Goroot are not under vcs
		MakeUpdated(this.Dir)
	}
}

func (this *GoPackage) UpdateVcsFields() {
	if this.Dir.Repo != nil {
		MakeUpdated(this.Dir.Repo.VcsLocal)
		MakeUpdated(this.Dir.Repo.VcsRemote)
	}
}

func GetRepoImportPath(repoPath, srcRoot string) (repoImportPath string) {
	// Detect and handle case mismatch in prefix.
	if prefixLen := len(srcRoot + "/"); len(repoPath) >= prefixLen && srcRoot+"/" != repoPath[:prefixLen] && strings.EqualFold(srcRoot+"/", repoPath[:prefixLen]) {
		fmt.Fprintln(os.Stderr, "warning: GetRepoImportPath: prefix case doesn't match")
		return repoPath[prefixLen:]
	}

	return strings.TrimPrefix(repoPath, srcRoot+"/")
}
func GetRepoImportPathPattern(repoPath, srcRoot string) (repoImportPathPattern string) {
	return GetRepoImportPath(repoPath, srcRoot) + "/..."
}

func (this *GoPackage) String() string {
	return this.Bpkg.ImportPath
}

// =====

// GoPackageRepo represents a collection of Go packages contained by one VCS repository.
type GoPackageRepo struct {
	rootPath   string
	goPackages []*GoPackage
}

func NewGoPackageRepo(rootPath string, goPackages []*GoPackage) GoPackageRepo {
	return GoPackageRepo{rootPath, goPackages}
}

// RepoImportPath returns what would be the import path of the root folder of the repository. It may or may not
// be an actual Go package. E.g.,
//
//	"github.com/owner/repo"
func (repo GoPackageRepo) RepoImportPath() string {
	return GetRepoImportPath(repo.rootPath, repo.goPackages[0].Bpkg.SrcRoot)
}

// ImportPathPattern returns an import path pattern that matches all of the Go packages in this repo.
// E.g.,
//
//	"github.com/owner/repo/..."
func (repo GoPackageRepo) ImportPathPattern() string {
	return GetRepoImportPathPattern(repo.rootPath, repo.goPackages[0].Bpkg.SrcRoot)
}

// RootPath returns the path to the root workdir folder of the repository.
func (repo GoPackageRepo) RootPath() string         { return repo.rootPath }
func (repo GoPackageRepo) GoPackages() []*GoPackage { return repo.goPackages }

// ImportPaths returns a newline separated list of all import paths.
func (repo GoPackageRepo) ImportPaths() string {
	var importPaths []string
	for _, goPackage := range repo.goPackages {
		importPaths = append(importPaths, goPackage.Bpkg.ImportPath)
	}
	return strings.Join(importPaths, "\n")
}
<commit_msg>Print newline after warning message.<commit_after>package gist7480523

import (
	"fmt"
	"go/build"
	"os"
	"strings"

	"github.com/shurcooL/go/exp/12"

	. "github.com/shurcooL/go/gists/gist5504644"
	. "github.com/shurcooL/go/gists/gist7519227"
	. "github.com/shurcooL/go/gists/gist7802150"
)

type GoPackageStringer func(*GoPackage) string

// A GoPackage describes a single package found in a directory.
// This is partially a copy of "cmd/go".Package, except it can be imported and reused. =.=
// https://code.google.com/p/go/source/browse/src/cmd/go/pkg.go?name=release#24
type GoPackage struct {
	Bpkg     *build.Package
	BpkgErr  error
	Standard bool // is this package part of the standard Go library?

	Dir *exp12.Directory
}

func GoPackageFromImportPathFound(importPathFound ImportPathFound) *GoPackage {
	bpkg, err := BuildPackageFromSrcDir(importPathFound.FullPath())
	return goPackageFromBuildPackage(bpkg, err)
}

func GoPackageFromImportPath(importPath string) *GoPackage {
	bpkg, err := BuildPackageFromImportPath(importPath)
	return goPackageFromBuildPackage(bpkg, err)
}

func GoPackageFromPath(path, srcDir string) *GoPackage {
	bpkg, err := build.Import(path, srcDir, 0)
	return goPackageFromBuildPackage(bpkg, err)
}

func goPackageFromBuildPackage(bpkg *build.Package, bpkgErr error) *GoPackage {
	if bpkgErr != nil {
		if _, noGo := bpkgErr.(*build.NoGoError); noGo || bpkg.Dir == "" {
			return nil
		}
	}

	if bpkg.ConflictDir != "" {
		fmt.Fprintf(os.Stderr, "warning: ConflictDir=%q (Dir=%q)\n", bpkg.ConflictDir, bpkg.Dir)
		return nil
	}

	goPackage := &GoPackage{
		Bpkg:     bpkg,
		BpkgErr:  bpkgErr,
		Standard: bpkg.Goroot && bpkg.ImportPath != "" && !strings.Contains(bpkg.ImportPath, "."), // https://code.google.com/p/go/source/browse/src/cmd/go/pkg.go?name=release#110

		Dir: exp12.LookupDirectory(bpkg.Dir),
	}

	/*if goPackage.Bpkg.Goroot == false { // Optimization that assume packages under Goroot are not under vcs
		// TODO: markAsNotNeedToUpdate() because of external insight?
	}*/

	return goPackage
}

// This is okay to call concurrently (a mutex is used internally).
// Actually, not completely okay because MakeUpdated technology is not thread-safe.
func (this *GoPackage) UpdateVcs() {
	if this.Bpkg.Goroot == false { // Optimization that assume packages under Goroot are not under vcs
		MakeUpdated(this.Dir)
	}
}

func (this *GoPackage) UpdateVcsFields() {
	if this.Dir.Repo != nil {
		MakeUpdated(this.Dir.Repo.VcsLocal)
		MakeUpdated(this.Dir.Repo.VcsRemote)
	}
}

func GetRepoImportPath(repoPath, srcRoot string) (repoImportPath string) {
	// Detect and handle case mismatch in prefix.
	if prefixLen := len(srcRoot + "/"); len(repoPath) >= prefixLen && srcRoot+"/" != repoPath[:prefixLen] && strings.EqualFold(srcRoot+"/", repoPath[:prefixLen]) {
		fmt.Fprintln(os.Stderr, "warning: GetRepoImportPath: prefix case doesn't match")
		return repoPath[prefixLen:]
	}

	return strings.TrimPrefix(repoPath, srcRoot+"/")
}
func GetRepoImportPathPattern(repoPath, srcRoot string) (repoImportPathPattern string) {
	return GetRepoImportPath(repoPath, srcRoot) + "/..."
}

func (this *GoPackage) String() string {
	return this.Bpkg.ImportPath
}

// =====

// GoPackageRepo represents a collection of Go packages contained by one VCS repository.
type GoPackageRepo struct {
	rootPath   string
	goPackages []*GoPackage
}

func NewGoPackageRepo(rootPath string, goPackages []*GoPackage) GoPackageRepo {
	return GoPackageRepo{rootPath, goPackages}
}

// RepoImportPath returns what would be the import path of the root folder of the repository. It may or may not
// be an actual Go package. E.g.,
//
//	"github.com/owner/repo"
func (repo GoPackageRepo) RepoImportPath() string {
	return GetRepoImportPath(repo.rootPath, repo.goPackages[0].Bpkg.SrcRoot)
}

// ImportPathPattern returns an import path pattern that matches all of the Go packages in this repo.
// E.g.,
//
//	"github.com/owner/repo/..."
func (repo GoPackageRepo) ImportPathPattern() string {
	return GetRepoImportPathPattern(repo.rootPath, repo.goPackages[0].Bpkg.SrcRoot)
}

// RootPath returns the path to the root workdir folder of the repository.
func (repo GoPackageRepo) RootPath() string         { return repo.rootPath }
func (repo GoPackageRepo) GoPackages() []*GoPackage { return repo.goPackages }

// ImportPaths returns a newline separated list of all import paths.
func (repo GoPackageRepo) ImportPaths() string {
	var importPaths []string
	for _, goPackage := range repo.goPackages {
		importPaths = append(importPaths, goPackage.Bpkg.ImportPath)
	}
	return strings.Join(importPaths, "\n")
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package yaml

import (
	"strings"
	"testing"

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

// Test that non-UTF8 characters in comments don't cause failures
func TestRNode_GetMeta_UTF16(t *testing.T) {
	sr, err := Parse(`apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRole
metadata:
  name: wildcard
  namespace: default
  # If set to [“*”], it refers to all services in the namespace
  annotations:
    foo: bar
spec:
  rules:
    # There is one service in default namespace, should not result in a validation error
    # If set to [“*”], it refers to all services in the namespace
    - services: ["*"]
      methods: ["GET", "HEAD"]
`)
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	actual, err := sr.GetMeta()
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	expected := ResourceMeta{
		APIVersion: "rbac.istio.io/v1alpha1",
		Kind:       "ServiceRole",
		ObjectMeta: ObjectMeta{
			Name:        "wildcard",
			Namespace:   "default",
			Annotations: map[string]string{"foo": "bar"},
		},
	}
	if !assert.Equal(t, expected, actual) {
		t.FailNow()
	}
}

func TestRNode_UnmarshalJSON(t *testing.T) {
	testCases := []struct {
		testName string
		input    string
		output   string
	}{
		{
			testName: "simple document",
			input:    `{"hello":"world"}`,
			output:   `hello: world`,
		},
		{
			testName: "nested structure",
			input: `
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "my-deployment",
    "namespace": "default"
  }
}
`,
			output: `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: default
`,
		},
	}

	for i := range testCases {
		tc := testCases[i]
		t.Run(tc.testName, func(t *testing.T) {
			instance := &RNode{}
			err := instance.UnmarshalJSON([]byte(tc.input))
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			actual, err := instance.String()
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			if !assert.Equal(t,
				strings.TrimSpace(tc.output), strings.TrimSpace(actual)) {
				t.FailNow()
			}
		})
	}
}

func TestRNode_MarshalJSON(t *testing.T) {
	tests := []struct {
		name string
		ydoc string
		want string
	}{
		{
			name: "object",
			ydoc: `
hello: world
`,
			want: `{"hello":"world"}`,
		},
		{
			name: "array",
			ydoc: `
- name: s1
- name: s2
`,
			want: `[{"name":"s1"},{"name":"s2"}]`,
		},
	}
	for idx := range tests {
		tt := tests[idx]
		t.Run(tt.name, func(t *testing.T) {
			instance, err := Parse(tt.ydoc)
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			actual, err := instance.MarshalJSON()
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			if !assert.Equal(t,
				strings.TrimSpace(tt.want), strings.TrimSpace(string(actual))) {
				t.FailNow()
			}
		})
	}
}

func TestConvertJSONToYamlNode(t *testing.T) {
	inputJSON := `{"type": "string", "maxLength": 15, "enum": ["allowedValue1", "allowedValue2"]}`
	expected := `enum:
- allowedValue1
- allowedValue2
maxLength: 15
type: string
`

	node, err := ConvertJSONToYamlNode(inputJSON)
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	actual, err := node.String()
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	assert.Equal(t, expected, actual)
}
<commit_msg>Add tests for IsEmpty and IsMissingorNull<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package yaml

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
	"gopkg.in/yaml.v3"
)

// Test that non-UTF8 characters in comments don't cause failures
func TestRNode_GetMeta_UTF16(t *testing.T) {
	sr, err := Parse(`apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRole
metadata:
  name: wildcard
  namespace: default
  # If set to [“*”], it refers to all services in the namespace
  annotations:
    foo: bar
spec:
  rules:
    # There is one service in default namespace, should not result in a validation error
    # If set to [“*”], it refers to all services in the namespace
    - services: ["*"]
      methods: ["GET", "HEAD"]
`)
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	actual, err := sr.GetMeta()
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	expected := ResourceMeta{
		APIVersion: "rbac.istio.io/v1alpha1",
		Kind:       "ServiceRole",
		ObjectMeta: ObjectMeta{
			Name:        "wildcard",
			Namespace:   "default",
			Annotations: map[string]string{"foo": "bar"},
		},
	}
	if !assert.Equal(t, expected, actual) {
		t.FailNow()
	}
}

func TestRNode_UnmarshalJSON(t *testing.T) {
	testCases := []struct {
		testName string
		input    string
		output   string
	}{
		{
			testName: "simple document",
			input:    `{"hello":"world"}`,
			output:   `hello: world`,
		},
		{
			testName: "nested structure",
			input: `
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "my-deployment",
    "namespace": "default"
  }
}
`,
			output: `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: default
`,
		},
	}

	for i := range testCases {
		tc := testCases[i]
		t.Run(tc.testName, func(t *testing.T) {
			instance := &RNode{}
			err := instance.UnmarshalJSON([]byte(tc.input))
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			actual, err := instance.String()
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			if !assert.Equal(t,
				strings.TrimSpace(tc.output), strings.TrimSpace(actual)) {
				t.FailNow()
			}
		})
	}
}

func TestRNode_MarshalJSON(t *testing.T) {
	tests := []struct {
		name string
		ydoc string
		want string
	}{
		{
			name: "object",
			ydoc: `
hello: world
`,
			want: `{"hello":"world"}`,
		},
		{
			name: "array",
			ydoc: `
- name: s1
- name: s2
`,
			want: `[{"name":"s1"},{"name":"s2"}]`,
		},
	}
	for idx := range tests {
		tt := tests[idx]
		t.Run(tt.name, func(t *testing.T) {
			instance, err := Parse(tt.ydoc)
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			actual, err := instance.MarshalJSON()
			if !assert.NoError(t, err) {
				t.FailNow()
			}

			if !assert.Equal(t,
				strings.TrimSpace(tt.want), strings.TrimSpace(string(actual))) {
				t.FailNow()
			}
		})
	}
}

func TestConvertJSONToYamlNode(t *testing.T) {
	inputJSON := `{"type": "string", "maxLength": 15, "enum": ["allowedValue1", "allowedValue2"]}`
	expected := `enum:
- allowedValue1
- allowedValue2
maxLength: 15
type: string
`

	node, err := ConvertJSONToYamlNode(inputJSON)
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	actual, err := node.String()
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	assert.Equal(t, expected, actual)
}

func TestIsMissingOrNull(t *testing.T) {
	if IsMissingOrNull(nil) != true {
		t.Fatalf("input: nil")
	}
	// missing value or null value
	node := &RNode{value: nil}
	if IsMissingOrNull(node) != true {
		t.Fatalf("input: nil value")
	}

	node.value = &yaml.Node{}
	if IsMissingOrNull(node) != false {
		t.Fatalf("input: valid node")
	}
	// node with NullNodeTag
	node.value.Tag = NullNodeTag
	if IsMissingOrNull(node) != true {
		t.Fatalf("input: with NullNodeTag")
	}

	node.value = &yaml.Node{}
	if IsMissingOrNull(node) != false {
		t.Fatalf("input: valid node")
	}
}

func TestIsEmpty(t *testing.T) {
	if IsEmpty(nil) != true {
		t.Fatalf("input: nil")
	}

	// missing value or null value
	node := &RNode{value: nil}
	if IsEmpty(node) != true {
		t.Fatalf("input: nil value")
	}
	// not array or map
	node.value = &yaml.Node{}
	if IsEmpty(node) != false {
		t.Fatalf("input: not array or map")
	}

	// === array tests ===
	node.value.Kind = yaml.SequenceNode
	// empty array. empty array is not expected as empty
	if IsEmpty(node) != false {
		t.Fatalf("input: empty array")
	}
	// array with 1 item
	node.value.Content = append(node.value.Content, &yaml.Node{})
	if IsEmpty(node) != false {
		t.Fatalf("input: array with 1 item")
	}
	// delete the item in array
	node.value.Content = node.value.Content[:len(node.value.Content)-1]
	if IsEmpty(node) != false {
		t.Fatalf("input: empty array")
	}

	// === map tests ===
	node.value = &yaml.Node{
		Kind: yaml.MappingNode,
	}
	// empty map
	if IsEmpty(node) != true {
		t.Fatalf("input: empty map")
	}
	// map with 1 item
	node.value.Content = append(node.value.Content, &yaml.Node{})
	if IsEmpty(node) != false {
		t.Fatalf("input: map with 1 item")
	}
	// delete the item in map
	node.value.Content = node.value.Content[:len(node.value.Content)-1]
	if IsEmpty(node) != true {
		t.Fatalf("input: empty map")
	}
}
<|endoftext|>