<commit_before>package goConsulRoundRobin

import (
	"sync"
	"time"
)

type serviceMap map[string]*serviceEndpoints

var services = make(serviceMap)
var requestLock = &sync.Mutex{}

//GetServiceEndpoint returns a healthy, round robbined service endpoint
func GetServiceEndpoint(service string) (endpoint string, err error) {
	//requestLock makes all requests synchronus as maps are not thread safe
	requestLock.Lock()
	defer requestLock.Unlock()

	//if new service request
	if _, present := services[service]; !present {
		//make new service and return endpoint
		err = services.newService(service)
		if err != nil {
			return "", err
		}
		endpoint = services[service].getAndInc()
		return endpoint, nil
	}

	//if timeout
	if services[service].timedOut() {
		//refresh endpoints
		err := services[service].refresh()
		if err != nil {
			return "", err
		}
	}

	//return endpoint
	endpoint = services[service].getAndInc()
	return endpoint, nil
}

//possible problem that serviceMap has no *
func (s serviceMap) newService(service string) error {
	endpoints, err := getHealthyEndpoints(service)
	if err != nil {
		return err
	}

	s[service] = &serviceEndpoints{
		name:      service,
		endpoints: endpoints,
		index:     0,
		timeout:   time.After(consulRefreshRate),
	}

	return nil
}
<commit_msg>added test mode<commit_after>package goConsulRoundRobin

import (
	"sync"
	"time"
)

type serviceMap map[string]*serviceEndpoints

var services = make(serviceMap)
var requestLock = &sync.Mutex{}

//TestURL is setable in test scenarios (set CONSUL_IP=testMode) and is what will return on a GetServiceEndpoint call
var TestURL string

//GetServiceEndpoint returns a healthy, round robbined service endpoint
func GetServiceEndpoint(service string) (endpoint string, err error) {
	if consulIP == "testMode" {
		return TestURL, nil
	}
	//requestLock makes all requests synchronus as maps are not thread safe
	requestLock.Lock()
	defer requestLock.Unlock()

	//if new service request
	if _, present := services[service]; !present {
		//make new service and return endpoint
		err = services.newService(service)
		if err != nil {
			return "", err
		}
		endpoint = services[service].getAndInc()
		return endpoint, nil
	}

	//if timeout
	if services[service].timedOut() {
		//refresh endpoints
		err := services[service].refresh()
		if err != nil {
			return "", err
		}
	}

	//return endpoint
	endpoint = services[service].getAndInc()
	return endpoint, nil
}

//possible problem that serviceMap has no *
func (s serviceMap) newService(service string) error {
	endpoints, err := getHealthyEndpoints(service)
	if err != nil {
		return err
	}

	s[service] = &serviceEndpoints{
		name:      service,
		endpoints: endpoints,
		index:     0,
		timeout:   time.After(consulRefreshRate),
	}

	return nil
}
<|endoftext|>


<commit_before>package gocode

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"testing"
)

const TestDirectory = "../_testing"

type Test struct {
	Name   string
	File   []byte
	Cursor int
	Result []string
}

func (t Test) Check(conf *Config) error {
	fn := filepath.Base(filepath.Dir(t.Name))
	cs := conf.Complete(t.File, t.Name, t.Cursor)
	if len(cs) != len(t.Result) {
		return fmt.Errorf("count: expected %d got %d: %s", len(t.Result), len(cs), fn)
	}
	for i, c := range cs {
		r := t.Result[i]
		if c.String() != r {
			return fmt.Errorf("candidate: expected '%s' got '%s': %s", r, c, fn)
		}
	}
	return nil
}

var (
	tests []Test
	conf  *Config
)

func init() {
	var err error
	conf, err = newConfig()
	if err != nil {
		panic(err)
	}
	tests, err = loadTests()
	if err != nil {
		panic(err)
	}
}

func TestInit(t *testing.T) {
	if _, err := newConfig(); err != nil {
		t.Fatal(err)
	}
	if _, err := loadTests(); err != nil {
		t.Fatal(err)
	}
}

func TestGocode(t *testing.T) {
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_1(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_2(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_3(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_4(t *testing.T) {
	t.Parallel()
	conf.GOPATH = "" // Alter GOPATH
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func loadTests() ([]Test, error) {
	var tests []Test
	list, err := ioutil.ReadDir(TestDirectory)
	if err != nil {
		return nil, err
	}
	for _, fi := range list {
		if fi.IsDir() {
			test, err := newTest(filepath.Join(TestDirectory, fi.Name()))
			if err != nil {
				return nil, err
			}
			tests = append(tests, *test)
		}
	}
	return tests, nil
}

func newTest(path string) (*Test, error) {
	list, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}
	t := Test{Cursor: -1}
	for _, fi := range list {
		fn := fi.Name()
		switch fn {
		case "test.go.in":
			t.Name = filepath.Join(path, fn)
			t.File, err = ioutil.ReadFile(t.Name)
			if err != nil {
				return nil, err
			}
		case "out.expected":
			t.Result, err = newResult(filepath.Join(path, fn))
			if err != nil {
				return nil, err
			}
		default:
			if strings.HasPrefix(fn, "cursor") {
				n := strings.IndexByte(fn, '.')
				if n == -1 {
					return nil, fmt.Errorf("error parsing cursor file: %s", fn)
				}
				t.Cursor, err = strconv.Atoi(fn[n+1:])
				if err != nil {
					return nil, err
				}
			}
		}
	}
	if t.Cursor == -1 {
		return nil, fmt.Errorf("no cursor file in directory: %s", path)
	}
	if t.Name == "" {
		return nil, fmt.Errorf("no test file in directory: %s", path)
	}
	if t.File == nil {
		return nil, fmt.Errorf("nil test file in directory: %s", path)
	}
	return &t, nil
}

func newResult(path string) ([]string, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	n := bytes.IndexByte(b, '\n')
	if n == len(b)-1 {
		return []string{}, nil
	}
	var s []string
	for _, b := range bytes.Split(b[n+1:], []byte{'\n'}) {
		if len(b) > 1 {
			s = append(s, string(bytes.TrimSpace(b)))
		}
	}
	return s, nil
}

func newConfig() (*Config, error) {
	c := Config{
		GOROOT: runtime.GOROOT(),
		GOPATH: os.Getenv("GOPATH"),
	}
	if c.GOROOT == "" {
		return nil, fmt.Errorf("GOROOT must be set")
	}
	if c.GOPATH == "" {
		return nil, fmt.Errorf("GOPATH must be set")
	}
	return &c, nil
}

func BenchmarkGocode(b *testing.B) {
	conf, err := newConfig()
	if err != nil {
		b.Fatal(err)
	}
	tests, err := loadTests()
	if err != nil {
		b.Fatal(err)
	}
	t := tests[0]
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = conf.Complete(t.File, t.Name, t.Cursor)
	}
}

func benchTest(t Test) {
	_ = conf.Complete(t.File, t.Name, t.Cursor)
}

func Benchmark_01(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[1-1])
		}
	}
}

func Benchmark_02(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[2-1])
		}
	}
}

func Benchmark_03(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[3-1])
		}
	}
}

func Benchmark_04(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[4-1])
		}
	}
}

func Benchmark_05(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[5-1])
		}
	}
}

func Benchmark_06(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[6-1])
		}
	}
}

func Benchmark_07(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[7-1])
		}
	}
}

func Benchmark_08(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[8-1])
		}
	}
}

func Benchmark_09(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[9-1])
		}
	}
}

func Benchmark_10(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[10-1])
		}
	}
}

func Benchmark_11(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[11-1])
		}
	}
}

func Benchmark_12(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[12-1])
		}
	}
}

func Benchmark_13(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[13-1])
		}
	}
}

func Benchmark_14(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[14-1])
		}
	}
}

func Benchmark_15(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[15-1])
		}
	}
}

func Benchmark_16(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[16-1])
		}
	}
}

func Benchmark_17(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[17-1])
		}
	}
}

func Benchmark_18(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[18-1])
		}
	}
}

func Benchmark_19(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[19-1])
		}
	}
}

func Benchmark_20(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[20-1])
		}
	}
}

func Benchmark_21(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[21-1])
		}
	}
}

func Benchmark_22(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[22-1])
		}
	}
}

func Benchmark_23(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[23-1])
		}
	}
}

func Benchmark_24(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[24-1])
		}
	}
}

func Benchmark_25(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[25-1])
		}
	}
}

func Benchmark_26(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[26-1])
		}
	}
}

func Benchmark_27(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[27-1])
		}
	}
}

func Benchmark_28(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[28-1])
		}
	}
}

func Benchmark_29(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[29-1])
		}
	}
}

func Benchmark_30(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[30-1])
		}
	}
}

func Benchmark_31(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[31-1])
		}
	}
}

func Benchmark_32(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[32-1])
		}
	}
}

func Benchmark_33(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[33-1])
		}
	}
}

func Benchmark_34(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[34-1])
		}
	}
}

func Benchmark_35(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[35-1])
		}
	}
}

func Benchmark_36(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[36-1])
		}
	}
}

func Benchmark_37(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[37-1])
		}
	}
}

func Benchmark_38(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[38-1])
		}
	}
}

func Benchmark_39(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[39-1])
		}
	}
}

func Benchmark_40(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[40-1])
		}
	}
}

func Benchmark_41(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[41-1])
		}
	}
}

func Benchmark_42(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[42-1])
		}
	}
}

func Benchmark_43(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[43-1])
		}
	}
}

func Benchmark_44(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[44-1])
		}
	}
}

func Benchmark_45(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[45-1])
		}
	}
}

func Benchmark_46(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[46-1])
		}
	}
}

func Benchmark_47(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[47-1])
		}
	}
}

func Benchmark_48(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[48-1])
		}
	}
}

func Benchmark_49(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[49-1])
		}
	}
}

func Benchmark_50(b *testing.B) {
	if !testing.Short() {
		for i := 0; i < b.N; i++ {
			benchTest(tests[50-1])
		}
	}
}
<commit_msg>update test<commit_after>package gocode

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"testing"
)

const TestDirectory = "../_testing"

var (
	tests []Test
	conf  *Config
)

func init() {
	var err error
	conf, err = newConfig()
	if err != nil {
		panic(err)
	}
	tests, err = loadTests()
	if err != nil {
		panic(err)
	}
}

func TestInit(t *testing.T) {
	if _, err := newConfig(); err != nil {
		t.Fatal(err)
	}
	if _, err := loadTests(); err != nil {
		t.Fatal(err)
	}
}

func TestGocode(t *testing.T) {
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_1(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_2(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_3(t *testing.T) {
	t.Parallel()
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func TestParallel_4(t *testing.T) {
	t.Parallel()
	conf.GOPATH = "" // Alter GOPATH
	for _, test := range tests {
		if err := test.Check(conf); err != nil {
			t.Fatal(err)
		}
	}
}

func BenchmarkOne(b *testing.B) {
	t := tests[0]
	for i := 0; i < b.N; i++ {
		_ = conf.Complete(t.File, t.Name, t.Cursor)
	}
}

func BenchmarkTen(b *testing.B) {
	if len(tests) < 10 {
		b.Fatal("Expected 10+ test cases")
	}
	tt := tests[:10]
	for i := 0; i < b.N; i++ {
		for _, t := range tt {
			_ = conf.Complete(t.File, t.Name, t.Cursor)
		}
	}
}

func BenchmarkAll(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, t := range tests {
			_ = conf.Complete(t.File, t.Name, t.Cursor)
		}
	}
}

type Test struct {
	Name   string
	File   []byte
	Cursor int
	Result []string
}

func (t Test) Check(conf *Config) error {
	fn := filepath.Base(filepath.Dir(t.Name))
	cs := conf.Complete(t.File, t.Name, t.Cursor)
	if len(cs) != len(t.Result) {
		return fmt.Errorf("count: expected %d got %d: %s", len(t.Result), len(cs), fn)
	}
	for i, c := range cs {
		r := t.Result[i]
		if c.String() != r {
			return fmt.Errorf("candidate: expected '%s' got '%s': %s", r, c, fn)
		}
	}
	return nil
}

func loadTests() ([]Test, error) {
	var tests []Test
	list, err := ioutil.ReadDir(TestDirectory)
	if err != nil {
		return nil, err
	}
	for _, fi := range list {
		if fi.IsDir() {
			test, err := newTest(filepath.Join(TestDirectory, fi.Name()))
			if err != nil {
				return nil, err
			}
			tests = append(tests, *test)
		}
	}
	return tests, nil
}

func newTest(path string) (*Test, error) {
	list, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}
	t := Test{Cursor: -1}
	for _, fi := range list {
		fn := fi.Name()
		switch fn {
		case "test.go.in":
			t.Name = filepath.Join(path, fn)
			t.File, err = ioutil.ReadFile(t.Name)
			if err != nil {
				return nil, err
			}
		case "out.expected":
			t.Result, err = newResult(filepath.Join(path, fn))
			if err != nil {
				return nil, err
			}
		default:
			if strings.HasPrefix(fn, "cursor") {
				n := strings.IndexByte(fn, '.')
				if n == -1 {
					return nil, fmt.Errorf("error parsing cursor file: %s", fn)
				}
				t.Cursor, err = strconv.Atoi(fn[n+1:])
				if err != nil {
					return nil, err
				}
			}
		}
	}
	if t.Cursor == -1 {
		return nil, fmt.Errorf("no cursor file in directory: %s", path)
	}
	if t.Name == "" {
		return nil, fmt.Errorf("no test file in directory: %s", path)
	}
	if t.File == nil {
		return nil, fmt.Errorf("nil test file in directory: %s", path)
	}
	return &t, nil
}

func newResult(path string) ([]string, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	n := bytes.IndexByte(b, '\n')
	if n == len(b)-1 {
		return []string{}, nil
	}
	var s []string
	for _, b := range bytes.Split(b[n+1:], []byte{'\n'}) {
		if len(b) > 1 {
			s = append(s, string(bytes.TrimSpace(b)))
		}
	}
	return s, nil
}

func newConfig() (*Config, error) {
	c := Config{
		GOROOT: runtime.GOROOT(),
		GOPATH: os.Getenv("GOPATH"),
	}
	if c.GOROOT == "" {
		return nil, fmt.Errorf("GOROOT must be set")
	}
	if c.GOPATH == "" {
		return nil, fmt.Errorf("GOPATH must be set")
	}
	return &c, nil
}
<|endoftext|>


<commit_before>package commands

import (
	"log"

	"github.com/dolab/logger"
)

var (
	stderr *logger.Logger

	envTemplate = `#!/usr/bin/env bash

# adjust GOPATH
case ":$GOPATH:" in
    *":$(pwd):"*) :;;
    *) GOPATH=$(pwd):$GOPATH;;
esac
export GOPATH

# adjust PATH
while IFS=':' read -ra ADDR; do
    for i in "${ADDR[@]}"; do
        case ":$PATH:" in
            *":$i/bin:"*) :;;
            *) PATH=$i/bin:$PATH
        esac
    done
done <<< "$GOPATH"
export PATH

# mock development && test envs
if [ ! -d "$(pwd)/src/{{.Namespace}}/{{.Application}}" ];
then
    mkdir -p "$(pwd)/src/{{.Namespace}}"
    ln -s "$(pwd)/gogo" "$(pwd)/src/{{.Namespace}}/{{.Application}}"
fi
`

	makefileTemplate = `all: gobuild gotest

godev:
    cd gogo && go run main.go

gobuild: goclean goinstall

gorebuild: goclean goreinstall

goclean:
    rm -rf bin
    rm -rf pkg

goinstall:
    cd gogo && go get -t -v ./...

goreinstall:
    cd gogo && go get -t -a -v ./...

gotest:
    go test {{.Namespace}}/{{.Application}}/app/controllers
    go test {{.Namespace}}/{{.Application}}/app/middlewares
    go test {{.Namespace}}/{{.Application}}/app/models

gopackage:
    mkdir -p bin && go build -a -o bin/{{.Application}} src/{{.Namespace}}/{{.Application}}/main.go

travis: gobuild gotest
`

	gitIgnoreTemplate = `# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test
bin
pkg
src

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof

# development & test config files
*.development.json
*.test.json
`

	applicationTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"

    "{{.Namespace}}/{{.Application}}/app/middlewares"
)

type Application struct {
    *gogo.AppServer
}

func New(runMode, srcPath string) *Application {
    appServer := gogo.New(runMode, srcPath)

    err := NewAppConfig(appServer.Config())
    if err != nil {
        panic(err.Error())
    }

    return &Application{appServer}
}

// Middlerwares implements gogo.Middlewarer
// NOTE: DO NOT change the method name, its required by gogo!
func (app *Application) Middlewares() {
    // apply your middlewares

    // panic recovery
    app.Use(middlewares.Recovery())
}

// Resources implements gogo.Resourcer
// NOTE: DO NOT change the method name, its required by gogo!
func (app *Application) Resources() {
    // register your resources
    // app.GET("/", handler)

    app.GET("/@getting_start/hello", GettingStart.Hello)
}

// Run runs application after registering middelwares and resources
func (app *Application) Run() {
    // register middlewares
    app.Middlewares()

    // register resources
    app.Resources()

    // run server
    app.AppServer.Run()
}
`, `package controllers

import (
    "net/http/httptest"
    "os"
    "path"
    "testing"

    "github.com/dolab/httptesting"
)

var (
    testServer *httptest.Server
    testClient *httptesting.Client
)

func TestMain(m *testing.M) {
    var (
        runMode = "test"
        srcPath = path.Clean("../../")
    )

    app := New(runMode, srcPath)
    app.Resources()

    testServer = httptest.NewServer(app)
    testClient = httptesting.New(testServer.URL, false)

    code := m.Run()

    testServer.Close()

    os.Exit(code)
}
`}

	configTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"
)

var (
    Config *AppConfig
)

// Application configuration specs
type AppConfig struct {
    Domain       string              ` + "`" + `json:"domain"` + "`" + `
    GettingStart *GettingStartConfig ` + "`" + `json:"getting_start"` + "`" + `
}

// NewAppConfig apply application config from *gogo.AppConfig
func NewAppConfig(config *gogo.AppConfig) error {
    return config.UnmarshalJSON(&Config)
}

// Sample application config for illustration
type GettingStartConfig struct {
    Greeting string ` + "`" + `json:"greeting"` + "`" + `
}
`, `package controllers

import (
    "testing"

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

func Test_AppConfig(t *testing.T) {
    assertion := assert.New(t)

    assertion.NotEmpty(Config.Domain)
    assertion.NotNil(Config.GettingStart)
}
`}

	gettingStartTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"
)

var (
    GettingStart *_GettingStart
)

type _GettingStart struct{}

// @route GET /@getting_start/hello
func (_ *_GettingStart) Hello(ctx *gogo.Context) {
    ctx.Logger.Warnf("Visiting domain is: %s", Config.Domain)

    ctx.Text(Config.GettingStart.Greeting)
}
`, `package controllers

import (
    "testing"
)

func Test_ExampleHello(t *testing.T) {
    testClient.Get(t, "/@getting_start/hello")

    testClient.AssertOK()
    testClient.AssertContains(Config.GettingStart.Greeting)
}
`}

	middlewareTemplate = []string{`package middlewares

import (
    "runtime"
    "strings"

    "github.com/dolab/gogo"
)

func Recovery() gogo.Middleware {
    return func(ctx *gogo.Context) {
        defer func() {
            if panicErr := recover(); panicErr != nil {
                // where does panic occur? try max 20 depths
                pcs := make([]uintptr, 20)
                max := runtime.Callers(2, pcs)
                for i := 0; i < max; i++ {
                    pcfunc := runtime.FuncForPC(pcs[i])
                    if strings.HasPrefix(pcfunc.Name(), "runtime.") {
                        continue
                    }

                    pcfile, pcline := pcfunc.FileLine(pcs[i])

                    tmp := strings.SplitN(pcfile, "/src/", 2)
                    if len(tmp) == 2 {
                        pcfile = "src/" + tmp[1]
                    }
                    ctx.Logger.Errorf("(%s:%d: %v)", pcfile, pcline, panicErr)

                    break
                }

                ctx.Abort()
            }
        }()

        ctx.Next()
    }
}
`, `package middlewares

import (
    "testing"

    "github.com/dolab/gogo"
)

func Test_Recovery(t *testing.T) {
    testApp.Use(Recovery())
    defer testApp.Clean()

    // register temp resource for testing
    testApp.GET("/middlewares/recovery", func(ctx *gogo.Context) {
        panic("Recover testing")
    })

    testClient.Get(t, "/middlewares/recovery", nil)
    testClient.AssertOK()
}
`, `package middlewares

import (
    "net/http/httptest"
    "os"
    "path"
    "testing"

    "github.com/dolab/gogo"
    "github.com/dolab/httptesting"
)

var (
    testApp    *gogo.AppServer
    testServer *httptest.Server
    testClient *httptesting.Client
)

func TestMain(m *testing.M) {
    var (
        runMode = "test"
        srcPath = path.Clean("../../")
    )

    testApp = gogo.New(runMode, srcPath)
    testServer = httptest.NewServer(testApp)
    testClient = httptesting.New(testServer.URL, false)

    code := m.Run()

    testServer.Close()

    os.Exit(code)
}
`}

	jsonTemplate = `{
    "name": "{{.Application}}",
    "mode": "test",
    "sections": {
        "development": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": false,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "debug",
                "filter_params": ["password", "password_confirmation"]
            },
            "domain": "https://example.com",
            "getting_start": {
                "greeting": "Hello, gogo!"
            }
        },

        "test": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": false,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "info",
                "filter_params": ["password", "password_confirmation"]
            },
            "domain": "https://example.com",
            "getting_start": {
                "greeting": "Hello, gogo!"
            }
        },

        "production": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": true,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "warn",
                "filter_params": ["password", "password_confirmation"]
            }
        }
    }
}
`

	mainTemplate = `package main

import (
    "flag"
    "os"
    "path"

    "github.com/dolab/gogo"

    "{{.Namespace}}/{{.Application}}/app/controllers"
)

var (
    runMode string // app run mode, available values are [development|test|production], default to development
    srcPath string // app source path, e.g. /home/deploy/websites/helloapp
)

func main() {
    flag.StringVar(&runMode, "runMode", "development", "{{.Application}} -runMode=[development|test|production]")
    flag.StringVar(&srcPath, "srcPath", "", "{{.Application}} -srcPath=/path/to/source")
    flag.Parse()

    // verify run mode
    if mode := gogo.RunMode(runMode); !mode.IsValid() {
        flag.PrintDefaults()
        return
    }

    // adjust src path
    if srcPath == "" {
        var err error

        srcPath, err = os.Getwd()
        if err != nil {
            panic(err)
        }
    } else {
        srcPath = path.Clean(srcPath)
    }

    controllers.New(runMode, srcPath).Run()
}
`
)

type templateData struct {
	Namespace   string
	Application string
}

func init() {
	var err error

	// setup logger
	stderr, err = logger.New("stderr")
	if err != nil {
		panic(err.Error())
	}

	stderr.SetLevelByName("info")
	stderr.SetFlag(log.Lshortfile)
}
<commit_msg>fix env.sh template issue<commit_after>package commands

import (
	"log"

	"github.com/dolab/logger"
)

var (
	stderr *logger.Logger

	envTemplate = `#!/usr/bin/env bash

# adjust GOPATH
case ":$GOPATH:" in
    *":$(pwd):"*) :;;
    *) GOPATH=$(pwd):$GOPATH;;
esac
export GOPATH

# adjust PATH
while IFS=':' read -ra ADDR; do
    for i in "${ADDR[@]}"; do
        case ":$PATH:" in
            *":$i/bin:"*) :;;
            *) PATH=$i/bin:$PATH
        esac
    done
done <<< "$GOPATH"
export PATH

# mock development && test envs
if [ ! -d "$(pwd)/src/{{.Namespace}}/{{.Application}}" ];
then
    mkdir -p "$(pwd)/src/{{.Namespace}}"
    ln -s "$(pwd)/gogo/" "$(pwd)/src/{{.Namespace}}/{{.Application}}"
fi
`

	makefileTemplate = `all: gobuild gotest

godev:
    cd gogo && go run main.go

gobuild: goclean goinstall

gorebuild: goclean goreinstall

goclean:
    rm -rf bin
    rm -rf pkg

goinstall:
    cd gogo && go get -t -v ./...

goreinstall:
    cd gogo && go get -t -a -v ./...

gotest:
    go test {{.Namespace}}/{{.Application}}/app/controllers
    go test {{.Namespace}}/{{.Application}}/app/middlewares
    # go test {{.Namespace}}/{{.Application}}/app/models

gopackage:
    mkdir -p bin && go build -a -o bin/{{.Application}} src/{{.Namespace}}/{{.Application}}/main.go

travis: gobuild gotest
`

	gitIgnoreTemplate = `# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test
bin
pkg
src

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof

# development & test config files
*.development.json
*.test.json
`

	applicationTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"

    "{{.Namespace}}/{{.Application}}/app/middlewares"
)

type Application struct {
    *gogo.AppServer
}

func New(runMode, srcPath string) *Application {
    appServer := gogo.New(runMode, srcPath)

    err := NewAppConfig(appServer.Config())
    if err != nil {
        panic(err.Error())
    }

    return &Application{appServer}
}

// Middlerwares implements gogo.Middlewarer
// NOTE: DO NOT change the method name, its required by gogo!
func (app *Application) Middlewares() {
    // apply your middlewares

    // panic recovery
    app.Use(middlewares.Recovery())
}

// Resources implements gogo.Resourcer
// NOTE: DO NOT change the method name, its required by gogo!
func (app *Application) Resources() {
    // register your resources
    // app.GET("/", handler)

    app.GET("/@getting_start/hello", GettingStart.Hello)
}

// Run runs application after registering middelwares and resources
func (app *Application) Run() {
    // register middlewares
    app.Middlewares()

    // register resources
    app.Resources()

    // run server
    app.AppServer.Run()
}
`, `package controllers

import (
    "net/http/httptest"
    "os"
    "path"
    "testing"

    "github.com/dolab/httptesting"
)

var (
    testServer *httptest.Server
    testClient *httptesting.Client
)

func TestMain(m *testing.M) {
    var (
        runMode = "test"
        srcPath = path.Clean("../../")
    )

    app := New(runMode, srcPath)
    app.Resources()

    testServer = httptest.NewServer(app)
    testClient = httptesting.New(testServer.URL, false)

    code := m.Run()

    testServer.Close()

    os.Exit(code)
}
`}

	configTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"
)

var (
    Config *AppConfig
)

// Application configuration specs
type AppConfig struct {
    Domain       string              ` + "`" + `json:"domain"` + "`" + `
    GettingStart *GettingStartConfig ` + "`" + `json:"getting_start"` + "`" + `
}

// NewAppConfig apply application config from *gogo.AppConfig
func NewAppConfig(config *gogo.AppConfig) error {
    return config.UnmarshalJSON(&Config)
}

// Sample application config for illustration
type GettingStartConfig struct {
    Greeting string ` + "`" + `json:"greeting"` + "`" + `
}
`, `package controllers

import (
    "testing"

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

func Test_AppConfig(t *testing.T) {
    assertion := assert.New(t)

    assertion.NotEmpty(Config.Domain)
    assertion.NotNil(Config.GettingStart)
}
`}

	gettingStartTemplate = []string{`package controllers

import (
    "github.com/dolab/gogo"
)

var (
    GettingStart *_GettingStart
)

type _GettingStart struct{}

// @route GET /@getting_start/hello
func (_ *_GettingStart) Hello(ctx *gogo.Context) {
    ctx.Logger.Warnf("Visiting domain is: %s", Config.Domain)

    ctx.Text(Config.GettingStart.Greeting)
}
`, `package controllers

import (
    "testing"
)

func Test_ExampleHello(t *testing.T) {
    testClient.Get(t, "/@getting_start/hello")

    testClient.AssertOK()
    testClient.AssertContains(Config.GettingStart.Greeting)
}
`}

	middlewareTemplate = []string{`package middlewares

import (
    "runtime"
    "strings"

    "github.com/dolab/gogo"
)

func Recovery() gogo.Middleware {
    return func(ctx *gogo.Context) {
        defer func() {
            if panicErr := recover(); panicErr != nil {
                // where does panic occur? try max 20 depths
                pcs := make([]uintptr, 20)
                max := runtime.Callers(2, pcs)
                for i := 0; i < max; i++ {
                    pcfunc := runtime.FuncForPC(pcs[i])
                    if strings.HasPrefix(pcfunc.Name(), "runtime.") {
                        continue
                    }

                    pcfile, pcline := pcfunc.FileLine(pcs[i])

                    tmp := strings.SplitN(pcfile, "/src/", 2)
                    if len(tmp) == 2 {
                        pcfile = "src/" + tmp[1]
                    }
                    ctx.Logger.Errorf("(%s:%d: %v)", pcfile, pcline, panicErr)

                    break
                }

                ctx.Abort()
            }
        }()

        ctx.Next()
    }
}
`, `package middlewares

import (
    "testing"

    "github.com/dolab/gogo"
)

func Test_Recovery(t *testing.T) {
    testApp.Use(Recovery())
    defer testApp.Clean()

    // register temp resource for testing
    testApp.GET("/middlewares/recovery", func(ctx *gogo.Context) {
        panic("Recover testing")
    })

    testClient.Get(t, "/middlewares/recovery", nil)
    testClient.AssertOK()
}
`, `package middlewares

import (
    "net/http/httptest"
    "os"
    "path"
    "testing"

    "github.com/dolab/gogo"
    "github.com/dolab/httptesting"
)

var (
    testApp    *gogo.AppServer
    testServer *httptest.Server
    testClient *httptesting.Client
)

func TestMain(m *testing.M) {
    var (
        runMode = "test"
        srcPath = path.Clean("../../")
    )

    testApp = gogo.New(runMode, srcPath)
    testServer = httptest.NewServer(testApp)
    testClient = httptesting.New(testServer.URL, false)

    code := m.Run()

    testServer.Close()

    os.Exit(code)
}
`}

	jsonTemplate = `{
    "name": "{{.Application}}",
    "mode": "test",
    "sections": {
        "development": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": false,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "debug",
                "filter_params": ["password", "password_confirmation"]
            },
            "domain": "https://example.com",
            "getting_start": {
                "greeting": "Hello, gogo!"
            }
        },

        "test": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": false,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "info",
                "filter_params": ["password", "password_confirmation"]
            },
            "domain": "https://example.com",
            "getting_start": {
                "greeting": "Hello, gogo!"
            }
        },

        "production": {
            "server": {
                "addr": "localhost",
                "port": 9090,
                "ssl": true,
                "ssl_cert": "/path/to/ssl/cert",
                "ssl_key": "/path/to/ssl/key",
                "request_timeout": 30,
                "response_timeout": 30,
                "request_id": "X-Request-Id"
            },
            "logger": {
                "output": "stdout",
                "level": "warn",
                "filter_params": ["password", "password_confirmation"]
            }
        }
    }
}
`

	mainTemplate = `package main

import (
    "flag"
    "os"
    "path"

    "github.com/dolab/gogo"

    "{{.Namespace}}/{{.Application}}/app/controllers"
)

var (
    runMode string // app run mode, available values are [development|test|production], default to development
    srcPath string // app source path, e.g. /home/deploy/websites/helloapp
)

func main() {
    flag.StringVar(&runMode, "runMode", "development", "{{.Application}} -runMode=[development|test|production]")
    flag.StringVar(&srcPath, "srcPath", "", "{{.Application}} -srcPath=/path/to/source")
    flag.Parse()

    // verify run mode
    if mode := gogo.RunMode(runMode); !mode.IsValid() {
        flag.PrintDefaults()
        return
    }

    // adjust src path
    if srcPath == "" {
        var err error

        srcPath, err = os.Getwd()
        if err != nil {
            panic(err)
        }
    } else {
        srcPath = path.Clean(srcPath)
    }

    controllers.New(runMode, srcPath).Run()
}
`
)

type templateData struct {
	Namespace   string
	Application string
}

func init() {
	var err error

	// setup logger
	stderr, err = logger.New("stderr")
	if err != nil {
		panic(err.Error())
	}

	stderr.SetLevelByName("info")
	stderr.SetFlag(log.Lshortfile)
}
<|endoftext|>


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

package gozzle

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestExec(t *testing.T) {
	// Initialize
	n := 5
	f := "test %d"
	h := "Test"

	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Loop
		for i := 0; i < n; i++ {
			// Get formatted message
			m := fmt.Sprintf(f, i)

			// Valid header
			if r.Header.Get(h) == m {
				// Set header
				w.Header().Set(h, m)

				// Set body
				w.Write([]byte(m))
			}
		}
	}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Loop
	for i := 0; i < n; i++ {
		// Get formatted message
		m := fmt.Sprintf(f, i)

		// Create request
		req := NewRequest(m, MethodGet, server.URL)
		req.AddHeader(h, m)
		reqSet.AddRequest(req)
	}

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Loop
	assert.Len(t, respSet.Names(), n)
	for i := 0; i < n; i++ {
		// Get formatted message
		m := fmt.Sprintf(f, i)

		// Get response
		resp := respSet.GetResponse(m)

		// Assert
		assert.Len(t, resp.Errors(), 0)
		assert.Equal(t, m, resp.Header().Get(h))
		c, e := ioutil.ReadAll(resp.BodyReader())
		assert.NoError(t, e)
		assert.Equal(t, m, string(c))
	}
}

func TestExecRequestBeforeHandler(t *testing.T) {
	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Create request
	req := NewRequest("test", MethodGet, server.URL)
	req.SetBeforeHandler(func(r Request) bool {
		return false
	})
	reqSet.AddRequest(req)

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Assert
	assert.Len(t, respSet.Names(), 0)
}

func TestExecRequestError(t *testing.T) {
	// Initialize
	c := 500

	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(c)
	}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Create requests
	req1 := NewRequest("test1", MethodGet, server.URL)
	reqSet.AddRequest(req1)
	req2 := NewRequest("test2", MethodGet, "test")
	reqSet.AddRequest(req2)

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Assert
	assert.Len(t, respSet.Names(), 2)
	assert.Equal(t, c, respSet.GetResponse("test1").StatusCode())
	assert.Len(t, respSet.GetResponse("test1").Errors(), 1)
	assert.EqualError(t, respSet.GetResponse("test1").Errors()[0], ErrInvalidStatusCode.Error())
	assert.Len(t, respSet.GetResponse("test2").Errors(), 1)
	assert.EqualError(t, respSet.GetResponse("test2").Errors()[0], "Get test: unsupported protocol scheme \"\"")
}

func TestQuery(t *testing.T) {
	// Initialize
	r1 := request{
		query: map[string]string{
			"a":     "b",
			"ké@lù": "ùl@ék",
		},
	}
	r2 := request{}

	// Assert
	assert.Contains(t, "?a=b&k%C3%A9%40l%C3%B9=%C3%B9l%40%C3%A9k?k%C3%A9%40l%C3%B9=%C3%B9l%40%C3%A9k&a=b", query(&r1))
	assert.Empty(t, query(&r2))
}

func TestBody(t *testing.T) {
	// Initialize
	r := request{
		body: map[string]string{
			"test": "message",
		},
		headers: map[string]string{
			"Content-Type": "application/json",
		},
	}

	// Get body reader
	b, e := body(&r)
	assert.NoError(t, e)

	// Read body
	c, e := ioutil.ReadAll(b)
	assert.NoError(t, e)

	// Assert
	assert.Equal(t, "{\"test\":\"message\"}", string(c))
}

func TestBodyEmpty(t *testing.T) {
	r := request{
		body: interface{}(nil),
	}

	// Get body reader
	b, e := body(&r)
	assert.NoError(t, e)

	// Read body
	c, e := ioutil.ReadAll(b)
	assert.NoError(t, e)

	// Assert
	assert.Equal(t, "", string(c))
}

func TestHeaders(t *testing.T) {
	// Initialize
	k := "Key"
	v := "Value"
	r := NewRequest("test", MethodGet, "/test")
	r.AddHeader(k, v)
	hr := http.Request{Header: http.Header{}}

	// Assert
	assert.Empty(t, hr.Header.Get(k))

	// Add headers
	headers(r, &hr)

	// Assert
	assert.Equal(t, v, hr.Header.Get(k))
}
<commit_msg>Added unit test for body reader<commit_after>// Copyright 2015, Quentin RENARD. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gozzle

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestExec(t *testing.T) {
	// Initialize
	n := 5
	f := "test %d"
	h := "Test"

	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Loop
		for i := 0; i < n; i++ {
			// Get formatted message
			m := fmt.Sprintf(f, i)

			// Valid header
			if r.Header.Get(h) == m {
				// Set header
				w.Header().Set(h, m)

				// Set body
				w.Write([]byte(m))
			}
		}
	}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Loop
	for i := 0; i < n; i++ {
		// Get formatted message
		m := fmt.Sprintf(f, i)

		// Create request
		req := NewRequest(m, MethodGet, server.URL)
		req.AddHeader(h, m)
		reqSet.AddRequest(req)
	}

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Loop
	assert.Len(t, respSet.Names(), n)
	for i := 0; i < n; i++ {
		// Get formatted message
		m := fmt.Sprintf(f, i)

		// Get response
		resp := respSet.GetResponse(m)

		// Assert
		assert.Len(t, resp.Errors(), 0)
		assert.Equal(t, m, resp.Header().Get(h))
		c, e := ioutil.ReadAll(resp.BodyReader())
		assert.NoError(t, e)
		assert.Equal(t, m, string(c))
	}
}

func TestExecRequestBeforeHandler(t *testing.T) {
	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Create request
	req := NewRequest("test", MethodGet, server.URL)
	req.SetBeforeHandler(func(r Request) bool {
		return false
	})
	reqSet.AddRequest(req)

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Assert
	assert.Len(t, respSet.Names(), 0)
}

func TestExecRequestError(t *testing.T) {
	// Initialize
	c := 500

	// Create server
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(c)
	}))
	defer server.Close()

	// Create request set
	reqSet := NewRequestSet()

	// Create requests
	req1 := NewRequest("test1", MethodGet, server.URL)
	reqSet.AddRequest(req1)
	req2 := NewRequest("test2", MethodGet, "test")
	reqSet.AddRequest(req2)

	// Create gozzle
	g := NewGozzle(0)

	// Execute requests
	respSet := g.Exec(reqSet)

	// Assert
	assert.Len(t, respSet.Names(), 2)
	assert.Equal(t, c, respSet.GetResponse("test1").StatusCode())
	assert.Len(t, respSet.GetResponse("test1").Errors(), 1)
	assert.EqualError(t, respSet.GetResponse("test1").Errors()[0], ErrInvalidStatusCode.Error())
	assert.Len(t, respSet.GetResponse("test2").Errors(), 1)
	assert.EqualError(t, respSet.GetResponse("test2").Errors()[0], "Get test: unsupported protocol scheme \"\"")
}

func TestQuery(t *testing.T) {
	// Initialize
	r1 := request{
		query: map[string]string{
			"a":     "b",
			"ké@lù": "ùl@ék",
		},
	}
	r2 := request{}

	// Assert
	assert.Contains(t, "?a=b&k%C3%A9%40l%C3%B9=%C3%B9l%40%C3%A9k?k%C3%A9%40l%C3%B9=%C3%B9l%40%C3%A9k&a=b", query(&r1))
	assert.Empty(t, query(&r2))
}

func TestBody(t *testing.T) {
	// Initialize
	r := request{
		body: map[string]string{
			"test": "message",
		},
		headers: map[string]string{
			"Content-Type": "application/json",
		},
	}

	// Get body reader
	b, e := body(&r)
	assert.NoError(t, e)

	// Read body
	c, e := ioutil.ReadAll(b)
	assert.NoError(t, e)

	// Assert
	assert.Equal(t, "{\"test\":\"message\"}", string(c))
}

func TestBodyEmpty(t *testing.T) {
	r := request{
		body: interface{}(nil),
	}

	// Get body reader
	b, e := body(&r)
	assert.NoError(t, e)

	// Read body
	c, e := ioutil.ReadAll(b)
	assert.NoError(t, e)

	// Assert
	assert.Equal(t, "", string(c))
}

func TestBodyReader(t *testing.T) {
	// Initialize
	r := request{
		body: map[string]string{
			"test": "message",
		},
		bodyReader: bytes.NewBuffer([]byte("{\"test\":\"message_reader\"}")),
		headers: map[string]string{
			"Content-Type": "application/json",
		},
	}

	// Get body reader
	b, e := body(&r)
	assert.NoError(t, e)

	// Read body
	c, e := ioutil.ReadAll(b)
	assert.NoError(t, e)

	// Assert
	assert.Equal(t, "{\"test\":\"message_reader\"}", string(c))
}

func TestHeaders(t *testing.T) {
	// Initialize
	k := "Key"
	v := "Value"
	r := NewRequest("test", MethodGet, "/test")
	r.AddHeader(k, v)
	hr := http.Request{Header: http.Header{}}

	// Assert
	assert.Empty(t, hr.Header.Get(k))

	// Add headers
	headers(r, &hr)

	// Assert
	assert.Equal(t, v, hr.Header.Get(k))
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 otelsarama

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
)

func TestNewConfig(t *testing.T) {
	testCases := []struct {
		name     string
		opts     []Option
		expected config
	}{
		{
			name: "with provider",
			opts: []Option{
				WithTracerProvider(otel.GetTracerProvider()),
			},
			expected: config{
				TracerProvider: otel.GetTracerProvider(),
				Tracer:         otel.GetTracerProvider().Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    otel.GetTextMapPropagator(),
			},
		},
		{
			name: "with propagators",
			opts: []Option{
				WithPropagators(nil),
			},
			expected: config{
				TracerProvider: otel.GetTracerProvider(),
				Tracer:         otel.GetTracerProvider().Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    otel.GetTextMapPropagator(),
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result := newConfig(tc.opts...)
			assert.Equal(t, tc.expected, result)
		})
	}
}
<commit_msg>Actually test the passed options in otelsarama (#2270)<commit_after>// Copyright The OpenTelemetry 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 otelsarama

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/trace"
)

// We need a fake tracer provider to ensure the one passed in options is the one used afterwards.
// In order to avoid adding the SDK as a dependency, we use this mock.
type fakeTracerProvider struct{}

func (fakeTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
	return fakeTracer{
		name: name,
	}
}

type fakeTracer struct {
	name string
}

func (fakeTracer) Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
	return ctx, nil
}

func TestNewConfig(t *testing.T) {
	tp := fakeTracerProvider{}
	prop := propagation.NewCompositeTextMapPropagator()

	testCases := []struct {
		name     string
		opts     []Option
		expected config
	}{
		{
			name: "with provider",
			opts: []Option{
				WithTracerProvider(tp),
			},
			expected: config{
				TracerProvider: tp,
				Tracer:         tp.Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    otel.GetTextMapPropagator(),
			},
		},
		{
			name: "with empty provider",
			opts: []Option{
				WithTracerProvider(nil),
			},
			expected: config{
				TracerProvider: otel.GetTracerProvider(),
				Tracer:         otel.GetTracerProvider().Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    otel.GetTextMapPropagator(),
			},
		},
		{
			name: "with propagators",
			opts: []Option{
				WithPropagators(prop),
			},
			expected: config{
				TracerProvider: otel.GetTracerProvider(),
				Tracer:         otel.GetTracerProvider().Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    prop,
			},
		},
		{
			name: "with empty propagators",
			opts: []Option{
				WithPropagators(nil),
			},
			expected: config{
				TracerProvider: otel.GetTracerProvider(),
				Tracer:         otel.GetTracerProvider().Tracer(defaultTracerName, trace.WithInstrumentationVersion(SemVersion())),
				Propagators:    otel.GetTextMapPropagator(),
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			result := newConfig(tc.opts...)
			assert.Equal(t, tc.expected, result)
		})
	}
}
<|endoftext|>


<commit_before>// Windows filesystem monitoring implementation based on
// golang.org/x/exp/winfsnotify
// (specifically
// https://github.com/golang/exp/tree/c84be7c6d1cd7b6a43fd7101daaf2dc35ded445f/winfsnotify),
// but modified to remove import path enforcement, increase
// ReadDirectoryChangesW buffer size, support recursive watching, use more
// idiomatic filesystem path joins, and remove test logging.
//
// The original code license:
//
// Copyright (c) 2009 The Go Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The original license header inside the code itself:
//
// 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 windows

package winfsnotify

import (
	"os"
	"path/filepath"
	"sync/atomic"
	"testing"
	"time"
)

func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
	select {
	case event := <-eventstream:
		if event == nil {
			t.Fatal("nil event received")
		}
		if event.Name != name || event.Mask != mask {
			t.Fatal("did not receive expected event")
		}
	case <-time.After(1 * time.Second):
		t.Fatal("timed out waiting for event")
	}
}

func TestNotifyEvents(t *testing.T) {
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher() failed: %s", err)
	}

	testDir := "TestNotifyEvents.testdirectory"
	testFile := filepath.Join(testDir, "TestNotifyEvents.testfile")
	testFile2 := testFile + ".new"
	const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED

	// Add a watch for testDir
	os.RemoveAll(testDir)
	if err = os.Mkdir(testDir, 0777); err != nil {
		t.Fatalf("Failed to create test directory: %s", err)
	}
	defer os.RemoveAll(testDir)
	err = watcher.AddWatch(testDir, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	// Create a file
	file, err := os.Create(testFile)
	if err != nil {
		t.Fatalf("creating test file failed: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_CREATE)

	err = watcher.AddWatch(testFile, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	if _, err = file.WriteString("hello, world"); err != nil {
		t.Fatalf("failed to write to test file: %s", err)
	}
	if err = file.Close(); err != nil {
		t.Fatalf("failed to close test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MODIFY)
	expect(t, watcher.Event, testFile, FS_MODIFY)

	if err = os.Rename(testFile, testFile2); err != nil {
		t.Fatalf("failed to rename test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MOVED_FROM)
	expect(t, watcher.Event, testFile2, FS_MOVED_TO)
	expect(t, watcher.Event, testFile, FS_MOVE_SELF)

	if err = os.RemoveAll(testDir); err != nil {
		t.Fatalf("failed to remove test directory: %s", err)
	}
	expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
	expect(t, watcher.Event, testFile2, FS_IGNORED)
	expect(t, watcher.Event, testFile2, FS_DELETE)
	expect(t, watcher.Event, testDir, FS_DELETE_SELF)
	expect(t, watcher.Event, testDir, FS_IGNORED)

	if err = watcher.Close(); err != nil {
		t.Fatalf("failed to close watcher: %s", err)
	}

	// Check for errors
	if err := <-watcher.Error; err != nil {
		t.Fatalf("error received: %s", err)
	}
}

func TestNotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	var done int32
	go func() {
		watcher.Close()
		atomic.StoreInt32(&done, 1)
	}()

	time.Sleep(50 * time.Millisecond)
	if atomic.LoadInt32(&done) == 0 {
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	err = watcher.Watch(t.TempDir())
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<commit_msg>Additional fix for f3dde29.<commit_after>// Windows filesystem monitoring implementation based on
// golang.org/x/exp/winfsnotify
// (specifically
// https://github.com/golang/exp/tree/c84be7c6d1cd7b6a43fd7101daaf2dc35ded445f/winfsnotify),
// but modified to remove import path enforcement, increase
// ReadDirectoryChangesW buffer size, support recursive watching, use more
// idiomatic filesystem path joins, and remove test logging.
//
// The original code license:
//
// Copyright (c) 2009 The Go Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The original license header inside the code itself:
//
// 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 windows

package winfsnotify

import (
	"os"
	"path/filepath"
	"sync/atomic"
	"testing"
	"time"
)

func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
	select {
	case event := <-eventstream:
		if event == nil {
			t.Fatal("nil event received")
		}
		if event.Name != name || event.Mask != mask {
			t.Fatal("did not receive expected event")
		}
	case <-time.After(1 * time.Second):
		t.Fatal("timed out waiting for event")
	}
}

func TestNotifyEvents(t *testing.T) {
	watcher, err := NewWatcher()
	if err != nil {
		t.Fatalf("NewWatcher() failed: %s", err)
	}

	testDir := "TestNotifyEvents.testdirectory"
	testFile := filepath.Join(testDir, "TestNotifyEvents.testfile")
	testFile2 := testFile + ".new"
	const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED

	// Add a watch for testDir
	os.RemoveAll(testDir)
	if err = os.Mkdir(testDir, 0777); err != nil {
		t.Fatalf("Failed to create test directory: %s", err)
	}
	defer os.RemoveAll(testDir)
	err = watcher.AddWatch(testDir, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	// Create a file
	file, err := os.Create(testFile)
	if err != nil {
		t.Fatalf("creating test file failed: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_CREATE)

	err = watcher.AddWatch(testFile, mask)
	if err != nil {
		t.Fatalf("Watcher.Watch() failed: %s", err)
	}

	if _, err = file.WriteString("hello, world"); err != nil {
		t.Fatalf("failed to write to test file: %s", err)
	}
	if err = file.Close(); err != nil {
		t.Fatalf("failed to close test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MODIFY)
	expect(t, watcher.Event, testFile, FS_MODIFY)

	if err = os.Rename(testFile, testFile2); err != nil {
		t.Fatalf("failed to rename test file: %s", err)
	}
	expect(t, watcher.Event, testFile, FS_MOVED_FROM)
	expect(t, watcher.Event, testFile2, FS_MOVED_TO)
	expect(t, watcher.Event, testFile, FS_MOVE_SELF)

	if err = os.RemoveAll(testDir); err != nil {
		t.Fatalf("failed to remove test directory: %s", err)
	}
	expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
	expect(t, watcher.Event, testFile2, FS_IGNORED)
	expect(t, watcher.Event, testFile2, FS_DELETE)
	expect(t, watcher.Event, testDir, FS_DELETE_SELF)
	expect(t, watcher.Event, testDir, FS_IGNORED)

	if err = watcher.Close(); err != nil {
		t.Fatalf("failed to close watcher: %s", err)
	}

	// Check for errors
	if err := <-watcher.Error; err != nil {
		t.Fatalf("error received: %s", err)
	}
}

func TestNotifyClose(t *testing.T) {
	watcher, _ := NewWatcher()
	watcher.Close()

	var done int32
	go func() {
		watcher.Close()
		atomic.StoreInt32(&done, 1)
	}()

	time.Sleep(50 * time.Millisecond)
	if atomic.LoadInt32(&done) == 0 {
		t.Fatal("double Close() test failed: second Close() call didn't return")
	}

	err := watcher.Watch(t.TempDir())
	if err == nil {
		t.Fatal("expected error on Watch() after Close(), got nil")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/LiamHaworth/go-tproxy"
	"io"
	"log"
	"net"
	"sync"
)

func main() {
	log.Println("Starting GoLang TProxy example")

	bindAddr := &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 8080}
	log.Printf("Attempting to bind listener on: %s", bindAddr.String())

	listener, err := tproxy.ListenTCP("tcp", bindAddr)
	if err != nil {
		log.Fatalf("Encountered error while binding listener: %s", err)
		return
	}

	log.Println("Listener bound successfully, now accepting connections")
	for {
		conn, err := listener.Accept()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				log.Printf("Temporary error while accepting connection: %s", netErr)
			}

			log.Fatalf("Unrecoverable error while accepting connection: %s", err)
			return
		}

		go handleConn(conn)
	}
}

func handleConn(conn net.Conn) {
	log.Printf("Accepting connection from %s with destination of %s", conn.RemoteAddr().String(), conn.LocalAddr().String())

	remoteConn, err := conn.(*tproxy.Conn).DialOriginalDestination(false)
	if err != nil {
		log.Printf("Failed to connect to original destination [%s]: %s", conn.LocalAddr().String(), err)
	} else {
		defer remoteConn.Close()
		defer conn.Close()
	}

	var streamWait sync.WaitGroup
	streamWait.Add(2)

	streamConn := func(dst io.Writer, src io.Reader) {
		io.Copy(dst, src)
		streamWait.Done()
	}

	go streamConn(remoteConn, conn)
	go streamConn(conn, remoteConn)

	streamWait.Wait()
}
<commit_msg>update(example): Updated example code to use both TCP and UDP<commit_after>package main

import (
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"sync"
	"time"

	"github.com/LiamHaworth/go-tproxy"
)

var (
	// tcpListener represents the TCP
	// listening socket that will receive
	// TCP connections from TProxy
	tcpListener net.Listener

	// udpListener represents tje UDP
	// listening socket that will receive
	// UDP packets from TProxy
	udpListener *net.UDPConn
)

// main will initialize the TProxy
// handling application
func main() {
	log.Println("Starting GoLang TProxy example")
	var err error

	log.Println("Binding TCP TProxy listener to 0.0.0.0:8080")
	tcpListener, err = tproxy.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP("0.0.0.0"), Port: 8080})
	if err != nil {
		log.Fatalf("Encountered error while binding listener: %s", err)
		return
	}

	defer tcpListener.Close()
	go listenTCP()

	log.Println("Binding UDP TProxy listener to 0.0.0.0:8080")
	udpListener, err = tproxy.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 8080})
	if err != nil {
		log.Fatalf("Encountered error while binding UDP listener: %s", err)
		return
	}

	defer udpListener.Close()
	go listenUDP()

	interruptListener := make(chan os.Signal)
	signal.Notify(interruptListener, os.Interrupt)
	<-interruptListener

	log.Println("TProxy listener closing")
}

// listenUDP runs in a routine to
// accept UDP connections and hand them
// off into their own routines for handling
func listenUDP() {
	for {
		buff := make([]byte, 1024)
		n, srcAddr, dstAddr, err := tproxy.ReadFromUDP(udpListener, buff)
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				log.Printf("Temporary error while reading data: %s", netErr)
			}

			log.Fatalf("Unrecoverable error while reading data: %s", err)
			return
		}

		log.Printf("Accepting UDP connection from %s with destination of %s", srcAddr.String(), dstAddr.String())
		go handleUDPConn(buff[:n], srcAddr, dstAddr)
	}
}

// listenTCP runs in a routine to
// accept TCP connections and hand them
// off into their own routines for handling
func listenTCP() {
	for {
		conn, err := tcpListener.Accept()
		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				log.Printf("Temporary error while accepting connection: %s", netErr)
			}

			log.Fatalf("Unrecoverable error while accepting connection: %s", err)
			return
		}

		go handleTCPConn(conn)
	}
}

// handleUDPConn will open a connection
// to the original destination pretending
// to be the client. It will when right
// the received data to the remote host
// and wait a few seconds for any possible
// response data
func handleUDPConn(data []byte, srcAddr, dstAddr *net.UDPAddr) {
	log.Printf("Accepting UDP connection from %s with destination of %s", srcAddr, dstAddr)

	localConn, err := tproxy.DialUDP("udp", dstAddr, srcAddr)
	if err != nil {
		log.Printf("Failed to connect to original UDP source [%s]: %s", srcAddr.String(), err)
		return
	}
	defer localConn.Close()

	remoteConn, err := tproxy.DialUDP("udp", srcAddr, dstAddr)
	if err != nil {
		log.Printf("Failed to connect to original UDP destination [%s]: %s", dstAddr.String(), err)
		return
	}
	defer remoteConn.Close()

	bytesWritten, err := remoteConn.Write(data)
	if err != nil {
		log.Printf("Encountered error while writing to remote [%s]: %s", remoteConn.RemoteAddr(), err)
		return
	} else if bytesWritten < len(data) {
		log.Printf("Not all bytes [%d < %d] in buffer written to remote [%s]", bytesWritten, len(data), remoteConn.RemoteAddr())
		return
	}

	data = make([]byte, 1024)
	remoteConn.SetReadDeadline(time.Now().Add(2 * time.Second)) // Add deadline to ensure it doesn't block forever
	bytesRead, err := remoteConn.Read(data)
	if err != nil {
		if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
			return
		}

		log.Printf("Encountered error while reading from remote [%s]: %s", remoteConn.RemoteAddr(), err)
		return
	}

	bytesWritten, err = localConn.Write(data)
	if err != nil {
		log.Printf("Encountered error while writing to local [%s]: %s", localConn.RemoteAddr(), err)
		return
	} else if bytesWritten < bytesRead {
		log.Printf("Not all bytes [%d < %d] in buffer written to locoal [%s]", bytesWritten, len(data), remoteConn.RemoteAddr())
		return
	}
}

// handleTCPConn will open a connection
// to the original destination pretending
// to be the client. From there it will setup
// two routines to stream data between the
// connections
func handleTCPConn(conn net.Conn) {
	log.Printf("Accepting TCP connection from %s with destination of %s", conn.RemoteAddr().String(), conn.LocalAddr().String())

	remoteConn, err := conn.(*tproxy.Conn).DialOriginalDestination(false)
	if err != nil {
		log.Printf("Failed to connect to original destination [%s]: %s", conn.LocalAddr().String(), err)
	} else {
		defer remoteConn.Close()
		defer conn.Close()
	}

	var streamWait sync.WaitGroup
	streamWait.Add(2)

	streamConn := func(dst io.Writer, src io.Reader) {
		io.Copy(dst, src)
		streamWait.Done()
	}

	go streamConn(remoteConn, conn)
	go streamConn(conn, remoteConn)

	streamWait.Wait()
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium 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 swarming

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/luci/luci-go/client/logdog/annotee"
	"github.com/luci/luci-go/common/clock"
	"github.com/luci/luci-go/common/logdog/types"
	miloProto "github.com/luci/luci-go/common/proto/milo"
	"github.com/luci/luci-go/common/transport"
	"golang.org/x/net/context"

	"github.com/luci/luci-go/appengine/cmd/milo/resp"
)

func resolveServer(server string) string {
	// TODO(hinoka): configure this map in luci-config
	if server == "" || server == "default" || server == "dev" {
		return "chromium-swarm-dev.appspot.com"
	} else if server == "prod" {
		return "chromium-swarm.appspot.com"
	} else {
		return server
	}
}

// swarmingIDs that beging with "debug:" wil redirect to json found in
// /testdata/
func getSwarmingLog(server string, swarmingID string, c context.Context) ([]byte, error) {
	// Fetch the debug file instead.
	if strings.HasPrefix(swarmingID, "debug:") {
		filename := strings.Join(
			[]string{"testdata", swarmingID[6:]}, "/")
		b, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}
		return b, nil
	}

	swarmingURL := fmt.Sprintf(
		"https://%s/swarming/api/v1/client/task/%s/output/0",
		resolveServer(server), swarmingID)
	client := transport.GetClient(c)
	resp, err := client.Get(swarmingURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("Failed to fetch %s, status code %d", swarmingURL, resp.StatusCode)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Decode the JSON and extract the actual log.
	sm := map[string]*string{}
	if err := json.Unmarshal(body, &sm); err != nil {
		return nil, err
	}

	// Decode the data using annotee.
	if output, ok := sm["output"]; ok {
		return []byte(*output), nil
	}
	return nil, fmt.Errorf("Swarming response did not contain output\n%s", body)
}

// TODO(hinoka): This should go in a more generic file, when milo has more
// than one page.
func getNavi(swarmingID string, URL string) *resp.Navigation {
	navi := &resp.Navigation{}
	navi.PageTitle = &resp.Link{
		Label: swarmingID,
		URL:   URL,
	}
	navi.SiteTitle = &resp.Link{
		Label: "Milo",
		URL:   "/",
	}
	return navi
}

// Given a logdog/milo step, translate it to a BuildComponent struct.
func miloBuildStep(
	url string, anno *miloProto.Step, name string) *resp.BuildComponent {
	comp := &resp.BuildComponent{}
	asc := anno.GetStepComponent()
	comp.Label = asc.Name
	switch asc.Status {
	case miloProto.Status_RUNNING:
		comp.Status = resp.Running

	case miloProto.Status_SUCCESS:
		comp.Status = resp.Success

	case miloProto.Status_FAILURE:
		if anno.GetFailureDetails() != nil {
			switch anno.GetFailureDetails().Type {
			case miloProto.FailureDetails_INFRA:
				comp.Status = resp.InfraFailure

			case miloProto.FailureDetails_DM_DEPENDENCY_FAILED:
				comp.Status = resp.DependencyFailure

			default:
				comp.Status = resp.Failure
			}
		} else {
			comp.Status = resp.Failure
		}
		// Missing the case of waiting on unfinished dependency...
	default:
		comp.Status = resp.NotRun
	}
	// Sub link is for one link per log that isn't stdio.
	for _, link := range asc.GetOtherLinks() {
		lds := link.GetLogdogStream()
		shortName := lds.Name[5 : len(lds.Name)-2]
		if strings.HasSuffix(lds.Name, "annotations") || strings.HasSuffix(lds.Name, "stdio") {
			// Skip the special ones.
			continue
		}
		newLink := &resp.Link{
			Label: shortName,
			URL:   strings.Join([]string{url, lds.Name}, "/"),
		}
		comp.SubLink = append(comp.SubLink, newLink)
	}

	// Main link is a link to the stdio.
	comp.MainLink = &resp.Link{
		Label: "stdio",
		URL:   strings.Join([]string{url, name, "logs", "stdio"}, "/"),
	}

	// This should always be a step.
	comp.Type = resp.Step

	// This should always be 0
	comp.LevelsDeep = 0

	// Timeswamapts
	comp.Started = asc.Started.Time().Format(time.RFC3339)

	// This should be the exact same thing.
	comp.Text = asc.Text

	return comp
}

// Takes a butler client and return a fully populated milo build.
func buildFromClient(c context.Context, swarmingID string, url string, s *memoryClient) (*resp.MiloBuild, error) {
	// Build the basic page response.
	build := &resp.MiloBuild{}
	build.Navi = getNavi(swarmingID, url)
	build.CurrentTime = clock.Now(c).String()

	// Now Fetch the main annotation of the build.
	mainAnno := &miloProto.Step{}
	proto.Unmarshal(s.stream["annotations"].dg, mainAnno)

	// Now fill in each of the step components.
	// TODO(hinoka): This is totes cachable.
	for _, name := range mainAnno.SubstepLogdogNameBase {
		anno := &miloProto.Step{}
		fullname := strings.Join([]string{name, "annotations"}, "/")
		proto.Unmarshal(s.stream[fullname].dg, anno)
		build.Components = append(build.Components, miloBuildStep(url, anno, name))
	}

	// Take care of properties
	propGroup := &resp.PropertyGroup{
		GroupName: "Main",
	}
	for _, prop := range mainAnno.GetStepComponent().Property {
		propGroup.Property = append(propGroup.Property, &resp.Property{
			Key:   prop.Name,
			Value: prop.Value,
		})
	}
	build.PropertyGroup = append(build.PropertyGroup, propGroup)

	// And we're done!
	return build, nil
}

// Takes in an annotated log and returns a fully populated memory client.
func clientFromAnnotatedLog(ctx context.Context, log []byte) (*memoryClient, error) {
	c := &memoryClient{}
	p := annotee.Processor{
		Context:                ctx,
		Client:                 c,
		MetadataUpdateInterval: time.Hour * 24, // Neverrrrrr send incr updates.
	}
	is := annotee.Stream{
		Reader:           bytes.NewBuffer(log),
		Name:             types.StreamName("stdio"),
		Annotate:         true,
		StripAnnotations: true,
	}
	// If this ever has more than one stream then memoryClient needs to become
	// goroutine safe
	if err := p.RunStreams([]*annotee.Stream{&is}); err != nil {
		return nil, err
	}
	return c, nil
}

func swarmingBuildImpl(c context.Context, URL string, server string, id string) (*resp.MiloBuild, error) {
	// Fetch the data from Swarming
	body, err := getSwarmingLog(server, id, c)
	if err != nil {
		return nil, err
	}

	// Decode the data using annotee.
	client, err := clientFromAnnotatedLog(c, body)
	if err != nil {
		return nil, err
	}

	return buildFromClient(c, id, URL, client)
}
<commit_msg>Milo: Use the new swarming endpoint<commit_after>// Copyright 2015 The Chromium 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 swarming

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/luci/luci-go/client/logdog/annotee"
	"github.com/luci/luci-go/common/clock"
	"github.com/luci/luci-go/common/logdog/types"
	miloProto "github.com/luci/luci-go/common/proto/milo"
	"github.com/luci/luci-go/common/transport"
	"golang.org/x/net/context"

	"github.com/luci/luci-go/appengine/cmd/milo/resp"
	"github.com/luci/luci-go/appengine/gaeauth/client"
)

func resolveServer(server string) string {
	// TODO(hinoka): configure this map in luci-config
	if server == "" || server == "default" || server == "dev" {
		return "chromium-swarm-dev.appspot.com"
	} else if server == "prod" {
		return "chromium-swarm.appspot.com"
	} else {
		return server
	}
}

// swarmingIDs that beging with "debug:" wil redirect to json found in
// /testdata/
func getSwarmingLog(server string, swarmingID string, c context.Context) ([]byte, error) {
	// Fetch the debug file instead.
	if strings.HasPrefix(swarmingID, "debug:") {
		filename := strings.Join(
			[]string{"testdata", swarmingID[6:]}, "/")
		b, err := ioutil.ReadFile(filename)
		if err != nil {
			return nil, err
		}
		return b, nil
	}

	swarmingURL := fmt.Sprintf(
		"https://%s/_ah/api/swarming/v1/task/%s/stdout",
		resolveServer(server), swarmingID)
	client := transport.GetClient(client.UseServiceAccountTransport(c,
		[]string{"https://www.googleapis.com/auth/userinfo.email"}, nil))
	resp, err := client.Get(swarmingURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("Failed to fetch %s, status code %d", swarmingURL, resp.StatusCode)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Decode the JSON and extract the actual log.
	sm := map[string]*string{}
	if err := json.Unmarshal(body, &sm); err != nil {
		return nil, err
	}

	// Decode the data using annotee.
	if output, ok := sm["output"]; ok {
		return []byte(*output), nil
	}
	return nil, fmt.Errorf("Swarming response did not contain output\n%s", body)
}

// TODO(hinoka): This should go in a more generic file, when milo has more
// than one page.
func getNavi(swarmingID string, URL string) *resp.Navigation {
	navi := &resp.Navigation{}
	navi.PageTitle = &resp.Link{
		Label: swarmingID,
		URL:   URL,
	}
	navi.SiteTitle = &resp.Link{
		Label: "Milo",
		URL:   "/",
	}
	return navi
}

// Given a logdog/milo step, translate it to a BuildComponent struct.
func miloBuildStep(
	url string, anno *miloProto.Step, name string) *resp.BuildComponent {
	comp := &resp.BuildComponent{}
	asc := anno.GetStepComponent()
	comp.Label = asc.Name
	switch asc.Status {
	case miloProto.Status_RUNNING:
		comp.Status = resp.Running

	case miloProto.Status_SUCCESS:
		comp.Status = resp.Success

	case miloProto.Status_FAILURE:
		if anno.GetFailureDetails() != nil {
			switch anno.GetFailureDetails().Type {
			case miloProto.FailureDetails_INFRA:
				comp.Status = resp.InfraFailure

			case miloProto.FailureDetails_DM_DEPENDENCY_FAILED:
				comp.Status = resp.DependencyFailure

			default:
				comp.Status = resp.Failure
			}
		} else {
			comp.Status = resp.Failure
		}
		// Missing the case of waiting on unfinished dependency...
	default:
		comp.Status = resp.NotRun
	}
	// Sub link is for one link per log that isn't stdio.
	for _, link := range asc.GetOtherLinks() {
		lds := link.GetLogdogStream()
		shortName := lds.Name[5 : len(lds.Name)-2]
		if strings.HasSuffix(lds.Name, "annotations") || strings.HasSuffix(lds.Name, "stdio") {
			// Skip the special ones.
			continue
		}
		newLink := &resp.Link{
			Label: shortName,
			URL:   strings.Join([]string{url, lds.Name}, "/"),
		}
		comp.SubLink = append(comp.SubLink, newLink)
	}

	// Main link is a link to the stdio.
	comp.MainLink = &resp.Link{
		Label: "stdio",
		URL:   strings.Join([]string{url, name, "logs", "stdio"}, "/"),
	}

	// This should always be a step.
	comp.Type = resp.Step

	// This should always be 0
	comp.LevelsDeep = 0

	// Timeswamapts
	comp.Started = asc.Started.Time().Format(time.RFC3339)

	// This should be the exact same thing.
	comp.Text = asc.Text

	return comp
}

// Takes a butler client and return a fully populated milo build.
func buildFromClient(c context.Context, swarmingID string, url string, s *memoryClient) (*resp.MiloBuild, error) {
	// Build the basic page response.
	build := &resp.MiloBuild{}
	build.Navi = getNavi(swarmingID, url)
	build.CurrentTime = clock.Now(c).String()

	// Now Fetch the main annotation of the build.
	mainAnno := &miloProto.Step{}
	proto.Unmarshal(s.stream["annotations"].dg, mainAnno)

	// Now fill in each of the step components.
	// TODO(hinoka): This is totes cachable.
	for _, name := range mainAnno.SubstepLogdogNameBase {
		anno := &miloProto.Step{}
		fullname := strings.Join([]string{name, "annotations"}, "/")
		proto.Unmarshal(s.stream[fullname].dg, anno)
		build.Components = append(build.Components, miloBuildStep(url, anno, name))
	}

	// Take care of properties
	propGroup := &resp.PropertyGroup{
		GroupName: "Main",
	}
	for _, prop := range mainAnno.GetStepComponent().Property {
		propGroup.Property = append(propGroup.Property, &resp.Property{
			Key:   prop.Name,
			Value: prop.Value,
		})
	}
	build.PropertyGroup = append(build.PropertyGroup, propGroup)

	// And we're done!
	return build, nil
}

// Takes in an annotated log and returns a fully populated memory client.
func clientFromAnnotatedLog(ctx context.Context, log []byte) (*memoryClient, error) {
	c := &memoryClient{}
	p := annotee.Processor{
		Context:                ctx,
		Client:                 c,
		MetadataUpdateInterval: time.Hour * 24, // Neverrrrrr send incr updates.
	}
	is := annotee.Stream{
		Reader:           bytes.NewBuffer(log),
		Name:             types.StreamName("stdio"),
		Annotate:         true,
		StripAnnotations: true,
	}
	// If this ever has more than one stream then memoryClient needs to become
	// goroutine safe
	if err := p.RunStreams([]*annotee.Stream{&is}); err != nil {
		return nil, err
	}
	return c, nil
}

func swarmingBuildImpl(c context.Context, URL string, server string, id string) (*resp.MiloBuild, error) {
	// Fetch the data from Swarming
	body, err := getSwarmingLog(server, id, c)
	if err != nil {
		return nil, err
	}

	// Decode the data using annotee.
	client, err := clientFromAnnotatedLog(c, body)
	if err != nil {
		return nil, err
	}

	return buildFromClient(c, id, URL, client)
}
<|endoftext|>


<commit_before>package proxy_test

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/tendermint/tendermint/lite"
	"github.com/tendermint/tendermint/lite/proxy"
	"github.com/tendermint/tendermint/types"
)

var (
	deadBeefTxs           = types.Txs{[]byte("DE"), []byte("AD"), []byte("BE"), []byte("EF")}
	deadBeefRipEmd160Hash = deadBeefTxs.Hash()
)

func TestValidateBlock(t *testing.T) {
	tests := []struct {
		block   *types.Block
		commit  lite.Commit
		wantErr string
	}{
		{
			block: nil, wantErr: "non-nil Block",
		},
		{
			block: &types.Block{}, wantErr: "nil Header",
		},
		{
			block: &types.Block{Header: new(types.Header)},
		},

		// Start Header.Height mismatch test
		{
			block:   &types.Block{Header: &types.Header{Height: 10}},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "don't match - 10 vs 11",
		},

		{
			block:  &types.Block{Header: &types.Header{Height: 11}},
			commit: lite.Commit{Header: &types.Header{Height: 11}},
		},
		// End Header.Height mismatch test

		// Start Header.Hash mismatch test
		{
			block: &types.Block{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "Headers don't match",
		},

		{
			block: &types.Block{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
		},
		// End Header.Hash mismatch test

		// Start Header.Data hash mismatch test
		{
			block: &types.Block{
				Header: &types.Header{Height: 11},
				Data:   &types.Data{Txs: []types.Tx{[]byte("0xDE"), []byte("AD")}},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("0xDEADBEEF")}},
			},
			wantErr: "Data hash doesn't match header",
		},
		{
			block: &types.Block{
				Header: &types.Header{Height: 11, DataHash: deadBeefRipEmd160Hash},
				Data:   &types.Data{Txs: deadBeefTxs},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
		},
		// End Header.Data hash mismatch test
	}

	for i, tt := range tests {
		err := proxy.ValidateBlock(tt.block, tt.commit)
		if tt.wantErr != "" {
			if err == nil {
				assert.FailNowf(t, "Unexpectedly passed", "#%d", i)
			} else {
				assert.Contains(t, err.Error(), tt.wantErr, "#%d should contain the substring\n\n", i)
			}
			continue
		}

		assert.Nil(t, err, "#%d: expecting a nil error", i)
	}
}

func TestValidateBlockMeta(t *testing.T) {
	tests := []struct {
		meta    *types.BlockMeta
		commit  lite.Commit
		wantErr string
	}{
		{
			meta: nil, wantErr: "non-nil BlockMeta",
		},
		{
			meta: &types.BlockMeta{}, wantErr: "non-nil Header",
		},
		{
			meta: &types.BlockMeta{Header: new(types.Header)},
		},

		// Start Header.Height mismatch test
		{
			meta:    &types.BlockMeta{Header: &types.Header{Height: 10}},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "don't match - 10 vs 11",
		},

		{
			meta:   &types.BlockMeta{Header: &types.Header{Height: 11}},
			commit: lite.Commit{Header: &types.Header{Height: 11}},
		},
		// End Header.Height mismatch test

		// Start Headers don't match test
		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "Headers don't match",
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height:         11,
					Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
					ValidatorsHash: []byte("Tendermint"),
				},
			},
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11,
					// TODO: (@odeke-em) inquire why ValidatorsHash has to be non-blank
					// for the Header to be hashed. Perhaps this is a security hole because
					// an aggressor could perhaps pass in headers that don't have
					// ValidatorsHash set and we won't be able to validate blocks.
					ValidatorsHash: []byte("lite-test"),
					// TODO: (@odeke-em) file an issue with Tendermint to get them to update
					// to the latest go-wire, then no more need for this value fill to avoid
					// the time zero value of less than 1970.
					Time: time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11, DataHash: deadBeefRipEmd160Hash},
			},
			wantErr: "Headers don't match",
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2017, 1, 2, 2, 1, 1, 1, time.UTC),
				},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
			wantErr: "Headers don't match",
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint-x"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
			wantErr: "Headers don't match",
		},
		// End Headers don't match test
	}

	for i, tt := range tests {
		err := proxy.ValidateBlockMeta(tt.meta, tt.commit)
		if tt.wantErr != "" {
			if err == nil {
				assert.FailNowf(t, "Unexpectedly passed", "#%d: wanted error %q", i, tt.wantErr)
			} else {
				assert.Contains(t, err.Error(), tt.wantErr, "#%d should contain the substring\n\n", i)
			}
			continue
		}

		assert.Nil(t, err, "#%d: expecting a nil error", i)
	}
}
<commit_msg>lite/proxy: consolidate some common test headers into a variable<commit_after>package proxy_test

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/tendermint/tendermint/lite"
	"github.com/tendermint/tendermint/lite/proxy"
	"github.com/tendermint/tendermint/types"
)

var (
	deadBeefTxs = types.Txs{[]byte("DE"), []byte("AD"), []byte("BE"), []byte("EF")}

	deadBeefRipEmd160Hash = deadBeefTxs.Hash()
)

var hdrHeight11Tendermint = &types.Header{
	Height:         11,
	Time:           time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
	ValidatorsHash: []byte("Tendermint"),
}

func TestValidateBlock(t *testing.T) {
	tests := []struct {
		block   *types.Block
		commit  lite.Commit
		wantErr string
	}{
		{
			block: nil, wantErr: "non-nil Block",
		},
		{
			block: &types.Block{}, wantErr: "nil Header",
		},
		{
			block: &types.Block{Header: new(types.Header)},
		},

		// Start Header.Height mismatch test
		{
			block:   &types.Block{Header: &types.Header{Height: 10}},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "don't match - 10 vs 11",
		},

		{
			block:  &types.Block{Header: &types.Header{Height: 11}},
			commit: lite.Commit{Header: &types.Header{Height: 11}},
		},
		// End Header.Height mismatch test

		// Start Header.Hash mismatch test
		{
			block:   &types.Block{Header: hdrHeight11Tendermint},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "Headers don't match",
		},

		{
			block:  &types.Block{Header: hdrHeight11Tendermint},
			commit: lite.Commit{Header: hdrHeight11Tendermint},
		},
		// End Header.Hash mismatch test

		// Start Header.Data hash mismatch test
		{
			block: &types.Block{
				Header: &types.Header{Height: 11},
				Data:   &types.Data{Txs: []types.Tx{[]byte("0xDE"), []byte("AD")}},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("0xDEADBEEF")}},
			},
			wantErr: "Data hash doesn't match header",
		},
		{
			block: &types.Block{
				Header: &types.Header{Height: 11, DataHash: deadBeefRipEmd160Hash},
				Data:   &types.Data{Txs: deadBeefTxs},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
		},
		// End Header.Data hash mismatch test
	}

	for i, tt := range tests {
		err := proxy.ValidateBlock(tt.block, tt.commit)
		if tt.wantErr != "" {
			if err == nil {
				assert.FailNowf(t, "Unexpectedly passed", "#%d", i)
			} else {
				assert.Contains(t, err.Error(), tt.wantErr, "#%d should contain the substring\n\n", i)
			}
			continue
		}

		assert.Nil(t, err, "#%d: expecting a nil error", i)
	}
}

func TestValidateBlockMeta(t *testing.T) {
	tests := []struct {
		meta    *types.BlockMeta
		commit  lite.Commit
		wantErr string
	}{
		{
			meta: nil, wantErr: "non-nil BlockMeta",
		},
		{
			meta: &types.BlockMeta{}, wantErr: "non-nil Header",
		},
		{
			meta: &types.BlockMeta{Header: new(types.Header)},
		},

		// Start Header.Height mismatch test
		{
			meta:    &types.BlockMeta{Header: &types.Header{Height: 10}},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "don't match - 10 vs 11",
		},

		{
			meta:   &types.BlockMeta{Header: &types.Header{Height: 11}},
			commit: lite.Commit{Header: &types.Header{Height: 11}},
		},
		// End Header.Height mismatch test

		// Start Headers don't match test
		{
			meta:    &types.BlockMeta{Header: hdrHeight11Tendermint},
			commit:  lite.Commit{Header: &types.Header{Height: 11}},
			wantErr: "Headers don't match",
		},

		{
			meta:   &types.BlockMeta{Header: hdrHeight11Tendermint},
			commit: lite.Commit{Header: hdrHeight11Tendermint},
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11,
					// TODO: (@odeke-em) inquire why ValidatorsHash has to be non-blank
					// for the Header to be hashed. Perhaps this is a security hole because
					// an aggressor could perhaps pass in headers that don't have
					// ValidatorsHash set and we won't be able to validate blocks.
					ValidatorsHash: []byte("lite-test"),
					// TODO: (@odeke-em) file an issue with Tendermint to get them to update
					// to the latest go-wire, then no more need for this value fill to avoid
					// the time zero value of less than 1970.
					Time: time.Date(2018, 1, 1, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{Height: 11, DataHash: deadBeefRipEmd160Hash},
			},
			wantErr: "Headers don't match",
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2018, 1, 2, 1, 1, 1, 1, time.UTC),
				},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
			wantErr: "Headers don't match",
		},

		{
			meta: &types.BlockMeta{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
			},
			commit: lite.Commit{
				Header: &types.Header{
					Height: 11, DataHash: deadBeefRipEmd160Hash,
					ValidatorsHash: []byte("Tendermint-x"),
					Time:           time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC),
				},
				Commit: &types.Commit{BlockID: types.BlockID{Hash: []byte("DEADBEEF")}},
			},
			wantErr: "Headers don't match",
		},
		// End Headers don't match test
	}

	for i, tt := range tests {
		err := proxy.ValidateBlockMeta(tt.meta, tt.commit)
		if tt.wantErr != "" {
			if err == nil {
				assert.FailNowf(t, "Unexpectedly passed", "#%d: wanted error %q", i, tt.wantErr)
			} else {
				assert.Contains(t, err.Error(), tt.wantErr, "#%d should contain the substring\n\n", i)
			}
			continue
		}

		assert.Nil(t, err, "#%d: expecting a nil error", i)
	}
}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2011 Red Hat, 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"reflect"
	"strings"
	"time"

	"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog"
	"github.com/snowdrop/service-catalog-java-api/generator/pkg/schemagen"
	"os"
)

//A Schema with the core types of the Service Catalog
type Schema struct {
	ClusterServiceBroker     servicecatalog.ClusterServiceBroker
	ClusterServiceBrokerList servicecatalog.ClusterServiceBrokerList
	ClusterServiceClass      servicecatalog.ClusterServiceClass
	ClusterServiceClassList  servicecatalog.ClusterServiceClassList
	ClusterServicePlan       servicecatalog.ClusterServicePlan
	ClusterServicePlanList   servicecatalog.ClusterServicePlanList
	ServiceInstance          servicecatalog.ServiceInstance
	ServiceInstanceList      servicecatalog.ServiceInstanceList
	ServiceBinding           servicecatalog.ServiceBinding
	ServiceBindingList       servicecatalog.ServiceBindingList
	ServiceBroker            servicecatalog.ServiceBroker
	ServiceBrokerList        servicecatalog.ServiceBrokerList
}

func main() {
	packages := []schemagen.PackageDescriptor{
		{"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog", "", "me.snowdrop.servicecatalog.api.model", "servicecatalog_"},
	}

	typeMap := map[reflect.Type]reflect.Type{
		reflect.TypeOf(time.Time{}): reflect.TypeOf(""),
		reflect.TypeOf(struct{}{}):  reflect.TypeOf(""),
	}
	schema, err := schemagen.GenerateSchema(reflect.TypeOf(Schema{}), packages, typeMap)
	if err != nil {
		log.Fatal(err)
	}

	args := os.Args[1:]
	if len(args) < 1 || args[0] != "validation" {
		schema.Resources = nil
	}

	b, err := json.Marshal(&schema)
	if err != nil {
		log.Fatal(err)
	}
	result := string(b)
	result = strings.Replace(result, "\"additionalProperty\":", "\"additionalProperties\":", -1)
	var out bytes.Buffer
	err = json.Indent(&out, []byte(result), "", "  ")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(out.String())
}
<commit_msg>chore: package reoder.<commit_after>/**
 * Copyright (C) 2011 Red Hat, 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog"
	"github.com/snowdrop/service-catalog-java-api/generator/pkg/schemagen"
	"log"
	"os"
	"reflect"
	"strings"
	"time"
)

//A Schema with the core types of the Service Catalog
type Schema struct {
	ClusterServiceBroker     servicecatalog.ClusterServiceBroker
	ClusterServiceBrokerList servicecatalog.ClusterServiceBrokerList
	ClusterServiceClass      servicecatalog.ClusterServiceClass
	ClusterServiceClassList  servicecatalog.ClusterServiceClassList
	ClusterServicePlan       servicecatalog.ClusterServicePlan
	ClusterServicePlanList   servicecatalog.ClusterServicePlanList
	ServiceInstance          servicecatalog.ServiceInstance
	ServiceInstanceList      servicecatalog.ServiceInstanceList
	ServiceBinding           servicecatalog.ServiceBinding
	ServiceBindingList       servicecatalog.ServiceBindingList
	ServiceBroker            servicecatalog.ServiceBroker
	ServiceBrokerList        servicecatalog.ServiceBrokerList
}

func main() {
	packages := []schemagen.PackageDescriptor{
		{"github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog", "", "me.snowdrop.servicecatalog.api.model", "servicecatalog_"},
	}

	typeMap := map[reflect.Type]reflect.Type{
		reflect.TypeOf(time.Time{}): reflect.TypeOf(""),
		reflect.TypeOf(struct{}{}):  reflect.TypeOf(""),
	}
	schema, err := schemagen.GenerateSchema(reflect.TypeOf(Schema{}), packages, typeMap)
	if err != nil {
		log.Fatal(err)
	}

	args := os.Args[1:]
	if len(args) < 1 || args[0] != "validation" {
		schema.Resources = nil
	}

	b, err := json.Marshal(&schema)
	if err != nil {
		log.Fatal(err)
	}
	result := string(b)
	result = strings.Replace(result, "\"additionalProperty\":", "\"additionalProperties\":", -1)
	var out bytes.Buffer
	err = json.Indent(&out, []byte(result), "", "  ")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(out.String())
}
<|endoftext|>