<commit_before>// Code generated by counterfeiter. DO NOT EDIT.
package providerfakes

import (
	"net/http"
	"sync"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/atc/auth/provider"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

type FakeProvider struct {
	PreTokenClientStub        func() (*http.Client, error)
	preTokenClientMutex       sync.RWMutex
	preTokenClientArgsForCall []struct{}
	preTokenClientReturns     struct {
		result1 *http.Client
		result2 error
	}
	preTokenClientReturnsOnCall map[int]struct {
		result1 *http.Client
		result2 error
	}
	AuthCodeURLStub        func(string, ...oauth2.AuthCodeOption) string
	authCodeURLMutex       sync.RWMutex
	authCodeURLArgsForCall []struct {
		arg1 string
		arg2 []oauth2.AuthCodeOption
	}
	authCodeURLReturns struct {
		result1 string
	}
	authCodeURLReturnsOnCall map[int]struct {
		result1 string
	}
	ExchangeStub        func(context.Context, string) (*oauth2.Token, error)
	exchangeMutex       sync.RWMutex
	exchangeArgsForCall []struct {
		arg1 context.Context
		arg2 string
	}
	exchangeReturns struct {
		result1 *oauth2.Token
		result2 error
	}
	exchangeReturnsOnCall map[int]struct {
		result1 *oauth2.Token
		result2 error
	}
	ClientStub        func(context.Context, *oauth2.Token) *http.Client
	clientMutex       sync.RWMutex
	clientArgsForCall []struct {
		arg1 context.Context
		arg2 *oauth2.Token
	}
	clientReturns struct {
		result1 *http.Client
	}
	clientReturnsOnCall map[int]struct {
		result1 *http.Client
	}
	VerifyStub        func(lager.Logger, *http.Client) (bool, error)
	verifyMutex       sync.RWMutex
	verifyArgsForCall []struct {
		arg1 lager.Logger
		arg2 *http.Client
	}
	verifyReturns struct {
		result1 bool
		result2 error
	}
	verifyReturnsOnCall map[int]struct {
		result1 bool
		result2 error
	}
	invocations      map[string][][]interface{}
	invocationsMutex sync.RWMutex
}

func (fake *FakeProvider) PreTokenClient() (*http.Client, error) {
	fake.preTokenClientMutex.Lock()
	ret, specificReturn := fake.preTokenClientReturnsOnCall[len(fake.preTokenClientArgsForCall)]
	fake.preTokenClientArgsForCall = append(fake.preTokenClientArgsForCall, struct{}{})
	fake.recordInvocation("PreTokenClient", []interface{}{})
	fake.preTokenClientMutex.Unlock()
	if fake.PreTokenClientStub != nil {
		return fake.PreTokenClientStub()
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.preTokenClientReturns.result1, fake.preTokenClientReturns.result2
}

func (fake *FakeProvider) PreTokenClientCallCount() int {
	fake.preTokenClientMutex.RLock()
	defer fake.preTokenClientMutex.RUnlock()
	return len(fake.preTokenClientArgsForCall)
}

func (fake *FakeProvider) PreTokenClientReturns(result1 *http.Client, result2 error) {
	fake.PreTokenClientStub = nil
	fake.preTokenClientReturns = struct {
		result1 *http.Client
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) PreTokenClientReturnsOnCall(i int, result1 *http.Client, result2 error) {
	fake.PreTokenClientStub = nil
	if fake.preTokenClientReturnsOnCall == nil {
		fake.preTokenClientReturnsOnCall = make(map[int]struct {
			result1 *http.Client
			result2 error
		})
	}
	fake.preTokenClientReturnsOnCall[i] = struct {
		result1 *http.Client
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) AuthCodeURL(arg1 string, arg2 ...oauth2.AuthCodeOption) string {
	fake.authCodeURLMutex.Lock()
	ret, specificReturn := fake.authCodeURLReturnsOnCall[len(fake.authCodeURLArgsForCall)]
	fake.authCodeURLArgsForCall = append(fake.authCodeURLArgsForCall, struct {
		arg1 string
		arg2 []oauth2.AuthCodeOption
	}{arg1, arg2})
	fake.recordInvocation("AuthCodeURL", []interface{}{arg1, arg2})
	fake.authCodeURLMutex.Unlock()
	if fake.AuthCodeURLStub != nil {
		return fake.AuthCodeURLStub(arg1, arg2...)
	}
	if specificReturn {
		return ret.result1
	}
	return fake.authCodeURLReturns.result1
}

func (fake *FakeProvider) AuthCodeURLCallCount() int {
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	return len(fake.authCodeURLArgsForCall)
}

func (fake *FakeProvider) AuthCodeURLArgsForCall(i int) (string, []oauth2.AuthCodeOption) {
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	return fake.authCodeURLArgsForCall[i].arg1, fake.authCodeURLArgsForCall[i].arg2
}

func (fake *FakeProvider) AuthCodeURLReturns(result1 string) {
	fake.AuthCodeURLStub = nil
	fake.authCodeURLReturns = struct {
		result1 string
	}{result1}
}

func (fake *FakeProvider) AuthCodeURLReturnsOnCall(i int, result1 string) {
	fake.AuthCodeURLStub = nil
	if fake.authCodeURLReturnsOnCall == nil {
		fake.authCodeURLReturnsOnCall = make(map[int]struct {
			result1 string
		})
	}
	fake.authCodeURLReturnsOnCall[i] = struct {
		result1 string
	}{result1}
}

func (fake *FakeProvider) Exchange(arg1 context.Context, arg2 string) (*oauth2.Token, error) {
	fake.exchangeMutex.Lock()
	ret, specificReturn := fake.exchangeReturnsOnCall[len(fake.exchangeArgsForCall)]
	fake.exchangeArgsForCall = append(fake.exchangeArgsForCall, struct {
		arg1 context.Context
		arg2 string
	}{arg1, arg2})
	fake.recordInvocation("Exchange", []interface{}{arg1, arg2})
	fake.exchangeMutex.Unlock()
	if fake.ExchangeStub != nil {
		return fake.ExchangeStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.exchangeReturns.result1, fake.exchangeReturns.result2
}

func (fake *FakeProvider) ExchangeCallCount() int {
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	return len(fake.exchangeArgsForCall)
}

func (fake *FakeProvider) ExchangeArgsForCall(i int) (context.Context, string) {
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	return fake.exchangeArgsForCall[i].arg1, fake.exchangeArgsForCall[i].arg2
}

func (fake *FakeProvider) ExchangeReturns(result1 *oauth2.Token, result2 error) {
	fake.ExchangeStub = nil
	fake.exchangeReturns = struct {
		result1 *oauth2.Token
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) ExchangeReturnsOnCall(i int, result1 *oauth2.Token, result2 error) {
	fake.ExchangeStub = nil
	if fake.exchangeReturnsOnCall == nil {
		fake.exchangeReturnsOnCall = make(map[int]struct {
			result1 *oauth2.Token
			result2 error
		})
	}
	fake.exchangeReturnsOnCall[i] = struct {
		result1 *oauth2.Token
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) Client(arg1 context.Context, arg2 *oauth2.Token) *http.Client {
	fake.clientMutex.Lock()
	ret, specificReturn := fake.clientReturnsOnCall[len(fake.clientArgsForCall)]
	fake.clientArgsForCall = append(fake.clientArgsForCall, struct {
		arg1 context.Context
		arg2 *oauth2.Token
	}{arg1, arg2})
	fake.recordInvocation("Client", []interface{}{arg1, arg2})
	fake.clientMutex.Unlock()
	if fake.ClientStub != nil {
		return fake.ClientStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1
	}
	return fake.clientReturns.result1
}

func (fake *FakeProvider) ClientCallCount() int {
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	return len(fake.clientArgsForCall)
}

func (fake *FakeProvider) ClientArgsForCall(i int) (context.Context, *oauth2.Token) {
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	return fake.clientArgsForCall[i].arg1, fake.clientArgsForCall[i].arg2
}

func (fake *FakeProvider) ClientReturns(result1 *http.Client) {
	fake.ClientStub = nil
	fake.clientReturns = struct {
		result1 *http.Client
	}{result1}
}

func (fake *FakeProvider) ClientReturnsOnCall(i int, result1 *http.Client) {
	fake.ClientStub = nil
	if fake.clientReturnsOnCall == nil {
		fake.clientReturnsOnCall = make(map[int]struct {
			result1 *http.Client
		})
	}
	fake.clientReturnsOnCall[i] = struct {
		result1 *http.Client
	}{result1}
}

func (fake *FakeProvider) Verify(arg1 lager.Logger, arg2 *http.Client) (bool, error) {
	fake.verifyMutex.Lock()
	ret, specificReturn := fake.verifyReturnsOnCall[len(fake.verifyArgsForCall)]
	fake.verifyArgsForCall = append(fake.verifyArgsForCall, struct {
		arg1 lager.Logger
		arg2 *http.Client
	}{arg1, arg2})
	fake.recordInvocation("Verify", []interface{}{arg1, arg2})
	fake.verifyMutex.Unlock()
	if fake.VerifyStub != nil {
		return fake.VerifyStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.verifyReturns.result1, fake.verifyReturns.result2
}

func (fake *FakeProvider) VerifyCallCount() int {
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	return len(fake.verifyArgsForCall)
}

func (fake *FakeProvider) VerifyArgsForCall(i int) (lager.Logger, *http.Client) {
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	return fake.verifyArgsForCall[i].arg1, fake.verifyArgsForCall[i].arg2
}

func (fake *FakeProvider) VerifyReturns(result1 bool, result2 error) {
	fake.VerifyStub = nil
	fake.verifyReturns = struct {
		result1 bool
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) VerifyReturnsOnCall(i int, result1 bool, result2 error) {
	fake.VerifyStub = nil
	if fake.verifyReturnsOnCall == nil {
		fake.verifyReturnsOnCall = make(map[int]struct {
			result1 bool
			result2 error
		})
	}
	fake.verifyReturnsOnCall[i] = struct {
		result1 bool
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) Invocations() map[string][][]interface{} {
	fake.invocationsMutex.RLock()
	defer fake.invocationsMutex.RUnlock()
	fake.preTokenClientMutex.RLock()
	defer fake.preTokenClientMutex.RUnlock()
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	copiedInvocations := map[string][][]interface{}{}
	for key, value := range fake.invocations {
		copiedInvocations[key] = value
	}
	return copiedInvocations
}

func (fake *FakeProvider) recordInvocation(key string, args []interface{}) {
	fake.invocationsMutex.Lock()
	defer fake.invocationsMutex.Unlock()
	if fake.invocations == nil {
		fake.invocations = map[string][][]interface{}{}
	}
	if fake.invocations[key] == nil {
		fake.invocations[key] = [][]interface{}{}
	}
	fake.invocations[key] = append(fake.invocations[key], args)
}

var _ provider.Provider = new(FakeProvider)
<commit_msg>Update Provider fake<commit_after>// Code generated by counterfeiter. DO NOT EDIT.
package providerfakes

import (
	"net/http"
	"sync"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/atc/auth/provider"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

type FakeProvider struct {
	PreTokenClientStub        func() (*http.Client, error)
	preTokenClientMutex       sync.RWMutex
	preTokenClientArgsForCall []struct{}
	preTokenClientReturns     struct {
		result1 *http.Client
		result2 error
	}
	preTokenClientReturnsOnCall map[int]struct {
		result1 *http.Client
		result2 error
	}
	AuthCodeURLStub        func(string, ...oauth2.AuthCodeOption) string
	authCodeURLMutex       sync.RWMutex
	authCodeURLArgsForCall []struct {
		arg1 string
		arg2 []oauth2.AuthCodeOption
	}
	authCodeURLReturns struct {
		result1 string
	}
	authCodeURLReturnsOnCall map[int]struct {
		result1 string
	}
	ExchangeStub        func(context.Context, *http.Request) (*oauth2.Token, error)
	exchangeMutex       sync.RWMutex
	exchangeArgsForCall []struct {
		arg1 context.Context
		arg2 *http.Request
	}
	exchangeReturns struct {
		result1 *oauth2.Token
		result2 error
	}
	exchangeReturnsOnCall map[int]struct {
		result1 *oauth2.Token
		result2 error
	}
	ClientStub        func(context.Context, *oauth2.Token) *http.Client
	clientMutex       sync.RWMutex
	clientArgsForCall []struct {
		arg1 context.Context
		arg2 *oauth2.Token
	}
	clientReturns struct {
		result1 *http.Client
	}
	clientReturnsOnCall map[int]struct {
		result1 *http.Client
	}
	VerifyStub        func(lager.Logger, *http.Client) (bool, error)
	verifyMutex       sync.RWMutex
	verifyArgsForCall []struct {
		arg1 lager.Logger
		arg2 *http.Client
	}
	verifyReturns struct {
		result1 bool
		result2 error
	}
	verifyReturnsOnCall map[int]struct {
		result1 bool
		result2 error
	}
	invocations      map[string][][]interface{}
	invocationsMutex sync.RWMutex
}

func (fake *FakeProvider) PreTokenClient() (*http.Client, error) {
	fake.preTokenClientMutex.Lock()
	ret, specificReturn := fake.preTokenClientReturnsOnCall[len(fake.preTokenClientArgsForCall)]
	fake.preTokenClientArgsForCall = append(fake.preTokenClientArgsForCall, struct{}{})
	fake.recordInvocation("PreTokenClient", []interface{}{})
	fake.preTokenClientMutex.Unlock()
	if fake.PreTokenClientStub != nil {
		return fake.PreTokenClientStub()
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.preTokenClientReturns.result1, fake.preTokenClientReturns.result2
}

func (fake *FakeProvider) PreTokenClientCallCount() int {
	fake.preTokenClientMutex.RLock()
	defer fake.preTokenClientMutex.RUnlock()
	return len(fake.preTokenClientArgsForCall)
}

func (fake *FakeProvider) PreTokenClientReturns(result1 *http.Client, result2 error) {
	fake.PreTokenClientStub = nil
	fake.preTokenClientReturns = struct {
		result1 *http.Client
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) PreTokenClientReturnsOnCall(i int, result1 *http.Client, result2 error) {
	fake.PreTokenClientStub = nil
	if fake.preTokenClientReturnsOnCall == nil {
		fake.preTokenClientReturnsOnCall = make(map[int]struct {
			result1 *http.Client
			result2 error
		})
	}
	fake.preTokenClientReturnsOnCall[i] = struct {
		result1 *http.Client
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) AuthCodeURL(arg1 string, arg2 ...oauth2.AuthCodeOption) string {
	fake.authCodeURLMutex.Lock()
	ret, specificReturn := fake.authCodeURLReturnsOnCall[len(fake.authCodeURLArgsForCall)]
	fake.authCodeURLArgsForCall = append(fake.authCodeURLArgsForCall, struct {
		arg1 string
		arg2 []oauth2.AuthCodeOption
	}{arg1, arg2})
	fake.recordInvocation("AuthCodeURL", []interface{}{arg1, arg2})
	fake.authCodeURLMutex.Unlock()
	if fake.AuthCodeURLStub != nil {
		return fake.AuthCodeURLStub(arg1, arg2...)
	}
	if specificReturn {
		return ret.result1
	}
	return fake.authCodeURLReturns.result1
}

func (fake *FakeProvider) AuthCodeURLCallCount() int {
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	return len(fake.authCodeURLArgsForCall)
}

func (fake *FakeProvider) AuthCodeURLArgsForCall(i int) (string, []oauth2.AuthCodeOption) {
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	return fake.authCodeURLArgsForCall[i].arg1, fake.authCodeURLArgsForCall[i].arg2
}

func (fake *FakeProvider) AuthCodeURLReturns(result1 string) {
	fake.AuthCodeURLStub = nil
	fake.authCodeURLReturns = struct {
		result1 string
	}{result1}
}

func (fake *FakeProvider) AuthCodeURLReturnsOnCall(i int, result1 string) {
	fake.AuthCodeURLStub = nil
	if fake.authCodeURLReturnsOnCall == nil {
		fake.authCodeURLReturnsOnCall = make(map[int]struct {
			result1 string
		})
	}
	fake.authCodeURLReturnsOnCall[i] = struct {
		result1 string
	}{result1}
}

func (fake *FakeProvider) Exchange(arg1 context.Context, arg2 *http.Request) (*oauth2.Token, error) {
	fake.exchangeMutex.Lock()
	ret, specificReturn := fake.exchangeReturnsOnCall[len(fake.exchangeArgsForCall)]
	fake.exchangeArgsForCall = append(fake.exchangeArgsForCall, struct {
		arg1 context.Context
		arg2 *http.Request
	}{arg1, arg2})
	fake.recordInvocation("Exchange", []interface{}{arg1, arg2})
	fake.exchangeMutex.Unlock()
	if fake.ExchangeStub != nil {
		return fake.ExchangeStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.exchangeReturns.result1, fake.exchangeReturns.result2
}

func (fake *FakeProvider) ExchangeCallCount() int {
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	return len(fake.exchangeArgsForCall)
}

func (fake *FakeProvider) ExchangeArgsForCall(i int) (context.Context, *http.Request) {
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	return fake.exchangeArgsForCall[i].arg1, fake.exchangeArgsForCall[i].arg2
}

func (fake *FakeProvider) ExchangeReturns(result1 *oauth2.Token, result2 error) {
	fake.ExchangeStub = nil
	fake.exchangeReturns = struct {
		result1 *oauth2.Token
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) ExchangeReturnsOnCall(i int, result1 *oauth2.Token, result2 error) {
	fake.ExchangeStub = nil
	if fake.exchangeReturnsOnCall == nil {
		fake.exchangeReturnsOnCall = make(map[int]struct {
			result1 *oauth2.Token
			result2 error
		})
	}
	fake.exchangeReturnsOnCall[i] = struct {
		result1 *oauth2.Token
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) Client(arg1 context.Context, arg2 *oauth2.Token) *http.Client {
	fake.clientMutex.Lock()
	ret, specificReturn := fake.clientReturnsOnCall[len(fake.clientArgsForCall)]
	fake.clientArgsForCall = append(fake.clientArgsForCall, struct {
		arg1 context.Context
		arg2 *oauth2.Token
	}{arg1, arg2})
	fake.recordInvocation("Client", []interface{}{arg1, arg2})
	fake.clientMutex.Unlock()
	if fake.ClientStub != nil {
		return fake.ClientStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1
	}
	return fake.clientReturns.result1
}

func (fake *FakeProvider) ClientCallCount() int {
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	return len(fake.clientArgsForCall)
}

func (fake *FakeProvider) ClientArgsForCall(i int) (context.Context, *oauth2.Token) {
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	return fake.clientArgsForCall[i].arg1, fake.clientArgsForCall[i].arg2
}

func (fake *FakeProvider) ClientReturns(result1 *http.Client) {
	fake.ClientStub = nil
	fake.clientReturns = struct {
		result1 *http.Client
	}{result1}
}

func (fake *FakeProvider) ClientReturnsOnCall(i int, result1 *http.Client) {
	fake.ClientStub = nil
	if fake.clientReturnsOnCall == nil {
		fake.clientReturnsOnCall = make(map[int]struct {
			result1 *http.Client
		})
	}
	fake.clientReturnsOnCall[i] = struct {
		result1 *http.Client
	}{result1}
}

func (fake *FakeProvider) Verify(arg1 lager.Logger, arg2 *http.Client) (bool, error) {
	fake.verifyMutex.Lock()
	ret, specificReturn := fake.verifyReturnsOnCall[len(fake.verifyArgsForCall)]
	fake.verifyArgsForCall = append(fake.verifyArgsForCall, struct {
		arg1 lager.Logger
		arg2 *http.Client
	}{arg1, arg2})
	fake.recordInvocation("Verify", []interface{}{arg1, arg2})
	fake.verifyMutex.Unlock()
	if fake.VerifyStub != nil {
		return fake.VerifyStub(arg1, arg2)
	}
	if specificReturn {
		return ret.result1, ret.result2
	}
	return fake.verifyReturns.result1, fake.verifyReturns.result2
}

func (fake *FakeProvider) VerifyCallCount() int {
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	return len(fake.verifyArgsForCall)
}

func (fake *FakeProvider) VerifyArgsForCall(i int) (lager.Logger, *http.Client) {
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	return fake.verifyArgsForCall[i].arg1, fake.verifyArgsForCall[i].arg2
}

func (fake *FakeProvider) VerifyReturns(result1 bool, result2 error) {
	fake.VerifyStub = nil
	fake.verifyReturns = struct {
		result1 bool
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) VerifyReturnsOnCall(i int, result1 bool, result2 error) {
	fake.VerifyStub = nil
	if fake.verifyReturnsOnCall == nil {
		fake.verifyReturnsOnCall = make(map[int]struct {
			result1 bool
			result2 error
		})
	}
	fake.verifyReturnsOnCall[i] = struct {
		result1 bool
		result2 error
	}{result1, result2}
}

func (fake *FakeProvider) Invocations() map[string][][]interface{} {
	fake.invocationsMutex.RLock()
	defer fake.invocationsMutex.RUnlock()
	fake.preTokenClientMutex.RLock()
	defer fake.preTokenClientMutex.RUnlock()
	fake.authCodeURLMutex.RLock()
	defer fake.authCodeURLMutex.RUnlock()
	fake.exchangeMutex.RLock()
	defer fake.exchangeMutex.RUnlock()
	fake.clientMutex.RLock()
	defer fake.clientMutex.RUnlock()
	fake.verifyMutex.RLock()
	defer fake.verifyMutex.RUnlock()
	copiedInvocations := map[string][][]interface{}{}
	for key, value := range fake.invocations {
		copiedInvocations[key] = value
	}
	return copiedInvocations
}

func (fake *FakeProvider) recordInvocation(key string, args []interface{}) {
	fake.invocationsMutex.Lock()
	defer fake.invocationsMutex.Unlock()
	if fake.invocations == nil {
		fake.invocations = map[string][][]interface{}{}
	}
	if fake.invocations[key] == nil {
		fake.invocations[key] = [][]interface{}{}
	}
	fake.invocations[key] = append(fake.invocations[key], args)
}

var _ provider.Provider = new(FakeProvider)
<|endoftext|>


<commit_before>package xc

import (
	"math"
	"strconv"

	"github.com/h8liu/xlang/parser"
)

var voidNode = &enode{isVoid: true, t: typeVoid}

func (ast *AST) prepareBuild() {
	ast.ir = newIrBlock()
	ast.scope = newScope()
	ast.scope.push() // buildin scope

	// TODO: fix this
	t := &xtype{isFunc: true}
	v := &enode{
		name: "print",
		t: t,
		onHeap: true,
		addr: 0x8000,
	}
	s := &symbol {
		name: "print",
		pos: nil,
		typ: t,
		v: v,
	}
	ast.scope.put(s)
}

// builds a function
func (ast *AST) buildFunc() {
	ast.scope.push()

	b := ast.root.(*ASTBlock)
	for _, s := range b.Nodes {
		ast.buildStmt(s)
	}

	ast.scope.pop()

	ast.obj = new(Object)
	ast.obj.ir = ast.ir
}

// builds an expression
func (ast *AST) buildExpr(s ASTNode) *enode {
	switch n := s.(type) {
	case *ASTOpExpr:
		return ast.buildOp(n)
	case *ASTCall:
		return ast.buildCall(n)
	case *parser.Tok:
		if n.Type == parser.TypeIdent {
			return ast.buildVarRef(n)
		} else if n.Type == parser.TypeInt {
			return ast.buildIntConst(n)
		}
	}
	return nil
}

// builds an operation
func (ast *AST) buildOp(n *ASTOpExpr) *enode {
	const arithErr = "arithmetic operation on non-number"
	const typeErr = "type mismatch on operation %q"

	if n.A == nil {
		// unary op
		switch n.Op.Lit {
		case "+":
			ret := ast.buildExpr(n.B)
			if ret == nil {
				return nil
			}
			if !ret.typ().isNum() {
				ast.errs.Log(n.Op.Pos, arithErr)
				return nil
			}
			return ret
		case "-":
			b := ast.buildExpr(n.B)
			if b == nil {
				return nil
			}
			if !b.typ().isNum() {
				ast.errs.Log(n.Op.Pos, arithErr)
				return nil
			}
			ret := ast.newTemp(b.typ())
			ast.ir.addUnaryOp(ret, "-", b)
			return ret
		default:
			panic("unknown op")
		}
	}

	switch n.Op.Lit {
	case "+", "-":
		a := ast.buildExpr(n.A)
		b := ast.buildExpr(n.B)
		if a == nil || b == nil {
			return nil
		}
		if !a.typ().isNum() {
			ast.errs.Log(n.Op.Pos, arithErr)
			return nil
		}
		if !a.typ().numEquals(b.typ()) {
			ast.errs.Log(n.Op.Pos, typeErr, n.Op.Lit)
			return nil
		}

		ret := ast.newTemp(a.typ())
		ast.ir.addBinaryOp(ret, a, n.Op.Lit, b)
		return ret
	default:
		panic("unknown op")
	}
}

// builds a function call
func (ast *AST) buildCall(n *ASTCall) *enode {
	f := ast.buildExpr(n.Func)
	if f == nil {
		return nil
	}

	var args []*enode
	for _, p := range n.Paras {
		r := ast.buildExpr(p)
		if r == nil {
			return nil
		}
		args = append(args, r)
	}

	// TODO: function signature type check
	// we now assume it is always print with one parameter

	if len(n.Paras) != 1 {
		ast.errs.Log(n.Lparen.Pos, "print only accepts one paramter")
		return nil
	}

	ast.ir.addCall(voidNode, f, args...)
	return voidNode
}

// builds a variable reference
func (ast *AST) buildVarRef(t *parser.Tok) *enode {
	found := ast.scope.find(t.Lit)
	if found == nil {
		ast.errs.Log(t.Pos, "%s not defined", t.Lit)
		return nil
	}

	return found.v
}

// builds a integer constant.
// for integer within int32 range, the type is int32
// otherwise, for integer within uint32 range, the type is uint32
// otherwise, it is out of range and invalid
func (ast *AST) buildIntConst(t *parser.Tok) *enode {
	v, e := strconv.ParseInt(t.Lit, 0, 64)
	if e != nil {
		ast.errs.Log(t.Pos, "invalid integer")
		return nil
	}

	if v > math.MaxUint32 || v < math.MinInt32 {
		ast.errs.Log(t.Pos, "integer out of range")
		return nil
	}

	if v > math.MaxInt32 {
		return ast.newConst(typeUint, int32(v))
	}

	return ast.newConst(typeInt, int32(v))
}

// build assignment
func (ast *AST) buildAssign(n *ASTAssign) {
	nleft := len(n.LHS)
	nright := len(n.RHS)
	if nleft != nright {
		ast.errs.Log(n.Pos, "expect %d on left hand side, got %d",
			nright, nleft,
		)
		return
	}

	var temps []*enode
	for _, expr := range n.RHS {
		t := ast.buildExpr(expr)
		if t == nil {
			return
		}
		temps = append(temps, t)
	}

	for i, d := range n.LHS {
		dest := ast.buildExpr(d)
		if dest == nil {
			return
		}

		if !dest.addressable() {
			ast.errs.Log(n.Pos, "assigning to not addressable")
			return
		}

		destType := dest.typ()
		src := temps[i]
		srcType := src.typ()
		if !srcType.canAssignTo(destType) {
			ast.errs.Log(n.Pos, "cannot assign %s to %s", srcType, destType)
			return
		}

		ast.ir.addAssign(dest, src)
	}
}

// build variable declaration
func (ast *AST) buildVarDecl(n *ASTVarDecl) {
	var src *enode
	if n.Expr != nil {
		src = ast.buildExpr(n.Expr)
		if src == nil {
			return
		}
	}

	varName := n.Name.Lit
	pre := ast.scope.findTop(varName)
	if pre != nil {
		ast.errs.Log(n.Name.Pos, "%s already declared", n.Name.Lit)
		ast.errs.Log(pre.pos, "  previously declared here")
		return
	}

	typ := typeInt // TODO: parse the type
	v := ast.newVar(varName, typ)
	sym := &symbol{
		name: varName,
		pos:  n.Name.Pos,
		typ:  typ,
		v:    v,
	}
	ast.scope.put(sym)

	if n.Expr != nil {
		if src == nil {
			return
		}
		srcType := src.typ()
		destType := v.typ()

		if !srcType.canAssignTo(destType) {
			ast.errs.Log(n.Name.Pos, "cannot assign %s to %s", srcType, destType)
			return
		}

		ast.ir.addAssign(v, src)
	} else {
		ast.ir.addAssign(v, ast.newZero(v.typ()))
	}
}

func (ast *AST) buildExprStmt(n *ASTExprStmt) {
	ast.buildExpr(n.Expr)
}

// build a statement
func (ast *AST) buildStmt(s ASTNode) {
	switch n := s.(type) {
	case *ASTAssign:
		ast.buildAssign(n)
	case *ASTVarDecl:
		ast.buildVarDecl(n)
	case *ASTExprStmt:
		ast.buildExprStmt(n)
	default:
		panic("invalid statement")
	}
}
<commit_msg>build<commit_after>package xc

import (
	"math"
	"strconv"

	"github.com/h8liu/xlang/parser"
)

var voidNode = &enode{isVoid: true, t: typeVoid}

func (ast *AST) prepareBuild() {
	ast.ir = newIrBlock()
	ast.scope = newScope()
	ast.scope.push() // buildin scope

	// TODO: fix this
	t := &xtype{isFunc: true}
	v := &enode{
		name:   "print",
		t:      t,
		onHeap: true,
		addr:   0x8000,
	}
	s := &symbol{
		name: "print",
		pos:  nil,
		typ:  t,
		v:    v,
	}
	ast.scope.put(s)
}

// builds a function
func (ast *AST) buildFunc() {
	ast.scope.push()

	b := ast.root.(*ASTBlock)
	for _, s := range b.Nodes {
		ast.buildStmt(s)
	}

	ast.scope.pop()

	ast.obj = new(Object)
	ast.obj.ir = ast.ir
}

// builds an expression
func (ast *AST) buildExpr(s ASTNode) *enode {
	switch n := s.(type) {
	case *ASTOpExpr:
		return ast.buildOp(n)
	case *ASTCall:
		return ast.buildCall(n)
	case *parser.Tok:
		if n.Type == parser.TypeIdent {
			return ast.buildVarRef(n)
		} else if n.Type == parser.TypeInt {
			return ast.buildIntConst(n)
		}
	}
	return nil
}

// builds an operation
func (ast *AST) buildOp(n *ASTOpExpr) *enode {
	const arithErr = "arithmetic operation on non-number"
	const typeErr = "type mismatch on operation %q"

	if n.A == nil {
		// unary op
		switch n.Op.Lit {
		case "+":
			ret := ast.buildExpr(n.B)
			if ret == nil {
				return nil
			}
			if !ret.typ().isNum() {
				ast.errs.Log(n.Op.Pos, arithErr)
				return nil
			}
			return ret
		case "-":
			b := ast.buildExpr(n.B)
			if b == nil {
				return nil
			}
			if !b.typ().isNum() {
				ast.errs.Log(n.Op.Pos, arithErr)
				return nil
			}
			ret := ast.newTemp(b.typ())
			ast.ir.addUnaryOp(ret, "-", b)
			return ret
		default:
			panic("unknown op")
		}
	}

	switch n.Op.Lit {
	case "+", "-":
		a := ast.buildExpr(n.A)
		b := ast.buildExpr(n.B)
		if a == nil || b == nil {
			return nil
		}
		if !a.typ().isNum() {
			ast.errs.Log(n.Op.Pos, arithErr)
			return nil
		}
		if !a.typ().numEquals(b.typ()) {
			ast.errs.Log(n.Op.Pos, typeErr, n.Op.Lit)
			return nil
		}

		ret := ast.newTemp(a.typ())
		ast.ir.addBinaryOp(ret, a, n.Op.Lit, b)
		return ret
	default:
		panic("unknown op")
	}
}

// builds a function call
func (ast *AST) buildCall(n *ASTCall) *enode {
	f := ast.buildExpr(n.Func)
	if f == nil {
		return nil
	}

	var args []*enode
	for _, p := range n.Paras {
		r := ast.buildExpr(p)
		if r == nil {
			return nil
		}
		args = append(args, r)
	}

	// TODO: function signature type check
	// we now assume it is always print with one parameter

	if len(n.Paras) != 1 {
		ast.errs.Log(n.Lparen.Pos, "print only accepts one paramter")
		return nil
	}

	ast.ir.addCall(voidNode, f, args...)
	return voidNode
}

// builds a variable reference
func (ast *AST) buildVarRef(t *parser.Tok) *enode {
	found := ast.scope.find(t.Lit)
	if found == nil {
		ast.errs.Log(t.Pos, "%s not defined", t.Lit)
		return nil
	}

	return found.v
}

// builds a integer constant.
// for integer within int32 range, the type is int32
// otherwise, for integer within uint32 range, the type is uint32
// otherwise, it is out of range and invalid
func (ast *AST) buildIntConst(t *parser.Tok) *enode {
	v, e := strconv.ParseInt(t.Lit, 0, 64)
	if e != nil {
		ast.errs.Log(t.Pos, "invalid integer")
		return nil
	}

	if v > math.MaxUint32 || v < math.MinInt32 {
		ast.errs.Log(t.Pos, "integer out of range")
		return nil
	}

	if v > math.MaxInt32 {
		return ast.newConst(typeUint, int32(v))
	}

	return ast.newConst(typeInt, int32(v))
}

// build assignment
func (ast *AST) buildAssign(n *ASTAssign) {
	nleft := len(n.LHS)
	nright := len(n.RHS)
	if nleft != nright {
		ast.errs.Log(n.Pos, "expect %d on left hand side, got %d",
			nright, nleft,
		)
		return
	}

	var temps []*enode
	for _, expr := range n.RHS {
		t := ast.buildExpr(expr)
		if t == nil {
			return
		}
		temps = append(temps, t)
	}

	for i, d := range n.LHS {
		dest := ast.buildExpr(d)
		if dest == nil {
			return
		}

		if !dest.addressable() {
			ast.errs.Log(n.Pos, "assigning to not addressable")
			return
		}

		destType := dest.typ()
		src := temps[i]
		srcType := src.typ()
		if !srcType.canAssignTo(destType) {
			ast.errs.Log(n.Pos, "cannot assign %s to %s", srcType, destType)
			return
		}

		ast.ir.addAssign(dest, src)
	}
}

// build variable declaration
func (ast *AST) buildVarDecl(n *ASTVarDecl) {
	var src *enode
	if n.Expr != nil {
		src = ast.buildExpr(n.Expr)
		if src == nil {
			return
		}
	}

	varName := n.Name.Lit
	pre := ast.scope.findTop(varName)
	if pre != nil {
		ast.errs.Log(n.Name.Pos, "%s already declared", n.Name.Lit)
		ast.errs.Log(pre.pos, "  previously declared here")
		return
	}

	typ := typeInt // TODO: parse the type
	v := ast.newVar(varName, typ)
	sym := &symbol{
		name: varName,
		pos:  n.Name.Pos,
		typ:  typ,
		v:    v,
	}
	ast.scope.put(sym)

	if n.Expr != nil {
		if src == nil {
			return
		}
		srcType := src.typ()
		destType := v.typ()

		if !srcType.canAssignTo(destType) {
			ast.errs.Log(n.Name.Pos, "cannot assign %s to %s", srcType, destType)
			return
		}

		ast.ir.addAssign(v, src)
	} else {
		ast.ir.addAssign(v, ast.newZero(v.typ()))
	}
}

func (ast *AST) buildExprStmt(n *ASTExprStmt) {
	ast.buildExpr(n.Expr)
}

// build a statement
func (ast *AST) buildStmt(s ASTNode) {
	switch n := s.(type) {
	case *ASTAssign:
		ast.buildAssign(n)
	case *ASTVarDecl:
		ast.buildVarDecl(n)
	case *ASTExprStmt:
		ast.buildExprStmt(n)
	default:
		panic("invalid statement")
	}
}
<|endoftext|>


<commit_before>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 ffjsoninception

import (
	"fmt"
	"reflect"
)

func typeInInception(ic *Inception, typ reflect.Type) bool {
	for _, v := range ic.objs {
		if v.Typ == typ {
			return true
		}
		if typ.Kind() == reflect.Ptr {
			if v.Typ == typ.Elem() {
				return true
			}
		}
	}

	return false
}

func getOmitEmpty(ic *Inception, sf *StructField) string {
	switch sf.Typ.Kind() {

	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return "if len(mj." + sf.Name + ") != 0 {" + "\n"

	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64,
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uintptr,
		reflect.Float32,
		reflect.Float64:
		return "if mj." + sf.Name + " != 0 {" + "\n"

	case reflect.Bool:
		return "if mj." + sf.Name + " != false {" + "\n"

	case reflect.Interface, reflect.Ptr:
		return "if mj." + sf.Name + " != nil {" + "\n"

	default:
		// TODO(pquerna): fix types
		return "if true {" + "\n"
	}
}

func getGetInnerValue(ic *Inception, name string, typ reflect.Type, ptr bool) string {
	var out = ""

	if typ.Implements(marshalerBufType) ||
		typeInInception(ic, typ) ||
		typ.Implements(marshalerType) ||
		reflect.PtrTo(typ).Implements(marshalerType) {

		out += tplStr(encodeTpl["handleMarshaler"], handleMarshaler{
			IC:             ic,
			Name:           name,
			MarshalJSONBuf: typ.Implements(marshalerBufType) || typeInInception(ic, typ),
			Marshaler:      typ.Implements(marshalerType) || reflect.PtrTo(typ).Implements(marshalerType),
		})
		return out
	}

	ptname := name
	if ptr {
		ptname = "*" + name
	}

	switch typ.Kind() {
	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.FormatBits(&scratch, buf, uint64(" + ptname + "), 10, " + ptname + " < 0)" + "\n"
	case reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uintptr:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.FormatBits(&scratch, buf, uint64(" + ptname + "), 10, false)" + "\n"
	case reflect.Float32:
		ic.OutputImports[`"strconv"`] = true
		out += "buf.Write(strconv.AppendFloat([]byte{}, float64(" + ptname + "), 'f', 10, 32))" + "\n"
	case reflect.Float64:
		ic.OutputImports[`"strconv"`] = true
		out += "buf.Write(strconv.AppendFloat([]byte{}, " + ptname + ", 'f', 10, 64))" + "\n"
	case reflect.Array,
		reflect.Slice:
		out += "if " + name + "!= nil {" + "\n"
		out += "buf.WriteString(`[`)" + "\n"
		out += "for i, v := range " + name + "{" + "\n"
		out += "if i != 0 {" + "\n"
		out += "buf.WriteString(`,`)" + "\n"
		out += "}" + "\n"
		out += getGetInnerValue(ic, "v", typ.Elem(), false)
		out += "}" + "\n"
		out += "buf.WriteString(`]`)" + "\n"
		out += "} else {" + "\n"
		out += "buf.WriteString(`null`)" + "\n"
		out += "}" + "\n"
	case reflect.String:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.WriteJsonString(buf, " + ptname + ")" + "\n"
	case reflect.Ptr:
		out += "if " + name + "!= nil {" + "\n"
		switch typ.Elem().Kind() {
		case reflect.Struct:
			out += getGetInnerValue(ic, name, typ.Elem(), false)
		default:
			out += getGetInnerValue(ic, "*"+name, typ.Elem(), false)
		}
		out += "} else {" + "\n"
		out += "buf.WriteString(`null`)" + "\n"
		out += "}" + "\n"
	case reflect.Bool:
		out += "if " + ptname + " {" + "\n"
		out += "buf.WriteString(`true`)" + "\n"
		out += "} else {" + "\n"
		out += "buf.WriteString(`false`)" + "\n"
		out += "}" + "\n"
	case reflect.Interface:
		ic.OutputImports[`"encoding/json"`] = true
		out += fmt.Sprintf("/* Interface types must use runtime reflection. type=%v kind=%v */\n", typ, typ.Kind())
		out += "obj, err = json.Marshal(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
		out += "buf.Write(obj)" + "\n"
	default:
		ic.OutputImports[`"encoding/json"`] = true
		out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
		out += "obj, err = json.Marshal(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
		out += "buf.Write(obj)" + "\n"
	}

	return out
}

func getValue(ic *Inception, sf *StructField) string {
	return getGetInnerValue(ic, "mj."+sf.Name, sf.Typ, sf.Pointer)
}

func p2(v uint32) uint32 {
	v--
	v |= v >> 1
	v |= v >> 2
	v |= v >> 4
	v |= v >> 8
	v |= v >> 16
	v++
	return v
}

func getTotalSize(si *StructInfo) uintptr {
	rv := si.Typ.Size()
	for _, f := range si.Fields {
		rv += f.Typ.Size()
	}
	return rv
}

func getBufGrowSize(si *StructInfo) uint32 {

	// TOOD(pquerna): automatically calc a better grow size based on history
	// of a struct.
	return p2(uint32(float32(getTotalSize(si)) * 3.0))
}

func isInt(t reflect.Type) bool {
	if t.Kind() >= reflect.Int && t.Kind() <= reflect.Uintptr {
		return true
	}
	return false
}

func CreateMarshalJSON(ic *Inception, si *StructInfo) error {
	conditionalWrites := false
	needScratch := false
	out := ""

	ic.OutputImports[`"bytes"`] = true

	out += `func (mj *` + si.Name + `) MarshalJSON() ([]byte, error) {` + "\n"
	out += `var buf fflib.Buffer` + "\n"

	out += fmt.Sprintf("buf.Grow(%d)\n", getBufGrowSize(si))
	out += `err := mj.MarshalJSONBuf(&buf)` + "\n"
	out += `if err != nil {` + "\n"
	out += "  return nil, err" + "\n"
	out += `}` + "\n"
	out += `return buf.Bytes(), nil` + "\n"
	out += `}` + "\n"

	for _, f := range si.Fields {
		if isInt(f.Typ) {
			needScratch = true
		}
	}

	for _, f := range si.Fields {
		if f.OmitEmpty || f.Pointer {
			// if we have >= 1 non-conditional write, we can
			// assume our trailing logic is reaosnable.
			if conditionalWrites {
				conditionalWrites = false
				break
			}
			conditionalWrites = true
		}
	}

	out += `func (mj *` + si.Name + `) MarshalJSONBuf(buf fflib.EncodingBuffer) (error) {` + "\n"
	out += `var err error` + "\n"
	out += `var obj []byte` + "\n"
	if needScratch {
		out += `var scratch fflib.FormatBitsScratch` + "\n"
	}

	if conditionalWrites {
		out += `var wroteAnyFields bool = false` + "\n"
	}

	out += `_ = obj` + "\n"
	out += `_ = err` + "\n"
	out += "buf.WriteString(`{`)" + "\n"

	for _, f := range si.Fields {
		if f.OmitEmpty {
			out += getOmitEmpty(ic, f)
		}

		if f.Pointer {
			out += "if mj." + f.Name + " != nil {" + "\n"
		}

		if conditionalWrites {
			out += `wroteAnyFields = true` + "\n"
		}

		// JsonName is already escaped and quoted.
		out += "buf.WriteString(`" + f.JsonName + ":`)" + "\n"
		out += getValue(ic, f)
		out += "buf.WriteString(`, `)" + "\n"

		if f.Pointer {
			out += "}" + "\n"
		}

		if f.OmitEmpty {
			out += "}" + "\n"
		}
	}

	if conditionalWrites {
		out += `if wroteAnyFields {` + "\n"
		out += "  	buf.Rewind(2)" + "\n"
		out += "	buf.WriteByte('}')" + "\n"
		out += `} else {` + "\n"
		out += "	buf.WriteByte('}')" + "\n"
		out += `}` + "\n"
	} else {
		out += "buf.Rewind(2)" + "\n"
		out += "buf.WriteByte('}')" + "\n"
	}

	out += `return nil` + "\n"
	out += `}` + "\n"
	ic.OutputFuncs = append(ic.OutputFuncs, out)
	return nil
}
<commit_msg>improve size estimation<commit_after>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 ffjsoninception

import (
	"fmt"
	"reflect"
)

func typeInInception(ic *Inception, typ reflect.Type) bool {
	for _, v := range ic.objs {
		if v.Typ == typ {
			return true
		}
		if typ.Kind() == reflect.Ptr {
			if v.Typ == typ.Elem() {
				return true
			}
		}
	}

	return false
}

func getOmitEmpty(ic *Inception, sf *StructField) string {
	switch sf.Typ.Kind() {

	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return "if len(mj." + sf.Name + ") != 0 {" + "\n"

	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64,
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uintptr,
		reflect.Float32,
		reflect.Float64:
		return "if mj." + sf.Name + " != 0 {" + "\n"

	case reflect.Bool:
		return "if mj." + sf.Name + " != false {" + "\n"

	case reflect.Interface, reflect.Ptr:
		return "if mj." + sf.Name + " != nil {" + "\n"

	default:
		// TODO(pquerna): fix types
		return "if true {" + "\n"
	}
}

func getGetInnerValue(ic *Inception, name string, typ reflect.Type, ptr bool) string {
	var out = ""

	if typ.Implements(marshalerBufType) ||
		typeInInception(ic, typ) ||
		typ.Implements(marshalerType) ||
		reflect.PtrTo(typ).Implements(marshalerType) {

		out += tplStr(encodeTpl["handleMarshaler"], handleMarshaler{
			IC:             ic,
			Name:           name,
			MarshalJSONBuf: typ.Implements(marshalerBufType) || typeInInception(ic, typ),
			Marshaler:      typ.Implements(marshalerType) || reflect.PtrTo(typ).Implements(marshalerType),
		})
		return out
	}

	ptname := name
	if ptr {
		ptname = "*" + name
	}

	switch typ.Kind() {
	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.FormatBits(&scratch, buf, uint64(" + ptname + "), 10, " + ptname + " < 0)" + "\n"
	case reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uintptr:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.FormatBits(&scratch, buf, uint64(" + ptname + "), 10, false)" + "\n"
	case reflect.Float32:
		ic.OutputImports[`"strconv"`] = true
		out += "buf.Write(strconv.AppendFloat([]byte{}, float64(" + ptname + "), 'f', 10, 32))" + "\n"
	case reflect.Float64:
		ic.OutputImports[`"strconv"`] = true
		out += "buf.Write(strconv.AppendFloat([]byte{}, " + ptname + ", 'f', 10, 64))" + "\n"
	case reflect.Array,
		reflect.Slice:
		out += "if " + name + "!= nil {" + "\n"
		out += "buf.WriteString(`[`)" + "\n"
		out += "for i, v := range " + name + "{" + "\n"
		out += "if i != 0 {" + "\n"
		out += "buf.WriteString(`,`)" + "\n"
		out += "}" + "\n"
		out += getGetInnerValue(ic, "v", typ.Elem(), false)
		out += "}" + "\n"
		out += "buf.WriteString(`]`)" + "\n"
		out += "} else {" + "\n"
		out += "buf.WriteString(`null`)" + "\n"
		out += "}" + "\n"
	case reflect.String:
		ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
		out += "fflib.WriteJsonString(buf, " + ptname + ")" + "\n"
	case reflect.Ptr:
		out += "if " + name + "!= nil {" + "\n"
		switch typ.Elem().Kind() {
		case reflect.Struct:
			out += getGetInnerValue(ic, name, typ.Elem(), false)
		default:
			out += getGetInnerValue(ic, "*"+name, typ.Elem(), false)
		}
		out += "} else {" + "\n"
		out += "buf.WriteString(`null`)" + "\n"
		out += "}" + "\n"
	case reflect.Bool:
		out += "if " + ptname + " {" + "\n"
		out += "buf.WriteString(`true`)" + "\n"
		out += "} else {" + "\n"
		out += "buf.WriteString(`false`)" + "\n"
		out += "}" + "\n"
	case reflect.Interface:
		ic.OutputImports[`"encoding/json"`] = true
		out += fmt.Sprintf("/* Interface types must use runtime reflection. type=%v kind=%v */\n", typ, typ.Kind())
		out += "obj, err = json.Marshal(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
		out += "buf.Write(obj)" + "\n"
	default:
		ic.OutputImports[`"encoding/json"`] = true
		out += fmt.Sprintf("/* Falling back. type=%v kind=%v */\n", typ, typ.Kind())
		out += "obj, err = json.Marshal(" + name + ")" + "\n"
		out += "if err != nil {" + "\n"
		out += "  return err" + "\n"
		out += "}" + "\n"
		out += "buf.Write(obj)" + "\n"
	}

	return out
}

func getValue(ic *Inception, sf *StructField) string {
	return getGetInnerValue(ic, "mj."+sf.Name, sf.Typ, sf.Pointer)
}

func p2(v uint32) uint32 {
	v--
	v |= v >> 1
	v |= v >> 2
	v |= v >> 4
	v |= v >> 8
	v |= v >> 16
	v++
	return v
}

func getTypeSize(t reflect.Type) uint32 {
	switch t.Kind() {
	case reflect.String:
		// TODO: consider runtime analysis.
		return 32
	case reflect.Array, reflect.Map, reflect.Slice:
		// TODO: consider runtime analysis.
		return 4 * getTypeSize(t.Elem())
	case reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32:
		return 8
	case reflect.Int64,
		reflect.Uint64,
		reflect.Uintptr:
		return 16
	case reflect.Float32,
		reflect.Float64:
		return 16
	case reflect.Bool:
		return 4
	case reflect.Ptr:
		return getTypeSize(t.Elem())
	default:
		return 16
	}
}

func getTotalSize(si *StructInfo) uint32 {
	rv := uint32(si.Typ.Size())
	for _, f := range si.Fields {
		rv += getTypeSize(f.Typ)
	}
	return rv
}

func getBufGrowSize(si *StructInfo) uint32 {

	// TOOD(pquerna): automatically calc a better grow size based on history
	// of a struct.
	return p2(getTotalSize(si))
}

func isInt(t reflect.Type) bool {
	if t.Kind() >= reflect.Int && t.Kind() <= reflect.Uintptr {
		return true
	}
	return false
}

func CreateMarshalJSON(ic *Inception, si *StructInfo) error {
	conditionalWrites := false
	needScratch := false
	out := ""

	ic.OutputImports[`"bytes"`] = true

	out += `func (mj *` + si.Name + `) MarshalJSON() ([]byte, error) {` + "\n"
	out += `var buf fflib.Buffer` + "\n"

	out += fmt.Sprintf("buf.Grow(%d)\n", getBufGrowSize(si))
	out += `err := mj.MarshalJSONBuf(&buf)` + "\n"
	out += `if err != nil {` + "\n"
	out += "  return nil, err" + "\n"
	out += `}` + "\n"
	out += `return buf.Bytes(), nil` + "\n"
	out += `}` + "\n"

	for _, f := range si.Fields {
		if isInt(f.Typ) {
			needScratch = true
		}
	}

	for _, f := range si.Fields {
		if f.OmitEmpty || f.Pointer {
			// if we have >= 1 non-conditional write, we can
			// assume our trailing logic is reaosnable.
			if conditionalWrites {
				conditionalWrites = false
				break
			}
			conditionalWrites = true
		}
	}

	out += `func (mj *` + si.Name + `) MarshalJSONBuf(buf fflib.EncodingBuffer) (error) {` + "\n"
	out += `var err error` + "\n"
	out += `var obj []byte` + "\n"
	if needScratch {
		out += `var scratch fflib.FormatBitsScratch` + "\n"
	}

	if conditionalWrites {
		out += `var wroteAnyFields bool = false` + "\n"
	}

	out += `_ = obj` + "\n"
	out += `_ = err` + "\n"
	out += "buf.WriteString(`{`)" + "\n"

	for _, f := range si.Fields {
		if f.OmitEmpty {
			out += getOmitEmpty(ic, f)
		}

		if f.Pointer {
			out += "if mj." + f.Name + " != nil {" + "\n"
		}

		if conditionalWrites {
			out += `wroteAnyFields = true` + "\n"
		}

		// JsonName is already escaped and quoted.
		out += "buf.WriteString(`" + f.JsonName + ":`)" + "\n"
		out += getValue(ic, f)
		out += "buf.WriteString(`, `)" + "\n"

		if f.Pointer {
			out += "}" + "\n"
		}

		if f.OmitEmpty {
			out += "}" + "\n"
		}
	}

	if conditionalWrites {
		out += `if wroteAnyFields {` + "\n"
		out += "  	buf.Rewind(2)" + "\n"
		out += "	buf.WriteByte('}')" + "\n"
		out += `} else {` + "\n"
		out += "	buf.WriteByte('}')" + "\n"
		out += `}` + "\n"
	} else {
		out += "buf.Rewind(2)" + "\n"
		out += "buf.WriteByte('}')" + "\n"
	}

	out += `return nil` + "\n"
	out += `}` + "\n"
	ic.OutputFuncs = append(ic.OutputFuncs, out)
	return nil
}
<|endoftext|>


<commit_before>package common

// Defalut value
var (
	DefaultCleanSession      = true
	DefaultKeepAlive    uint = 60
)

// OptionsPacketCONNECT is options for creating a CONNECT Packet.
type OptionsPacketCONNECT struct {
	// CleanSession is the Clean Session of the connect flags.
	CleanSession *bool
	// WillTopic is the Will Topic of the payload.
	WillTopic string
	// WillMessage is the Will Message of the payload.
	WillMessage string
	// WillQoS is the Will QoS of the connect flags.
	WillQoS uint
	// WillRetain is the Will Retain of the connect flags.
	WillRetain bool
	// UserName is the user name used by the server for authentication and authorization.
	UserName string
	// Password is the password used by the server for authentication and authorization.
	Password string
	// KeepAlive is the Keep Alive in the variable header.
	KeepAlive *uint
}

// Init initialize the ConnectOpts.
func (opts *OptionsPacketCONNECT) Init() {
	if opts.CleanSession == nil {
		opts.CleanSession = &DefaultCleanSession
	}

	if opts.KeepAlive == nil {
		opts.KeepAlive = &DefaultKeepAlive
	}
}
<commit_msg>Update options_packet_connect.go<commit_after>package common

// Defalut value
var (
	DefaultCleanSession      = true
	DefaultKeepAlive    uint = 60
)

// OptionsPacketCONNECT is options for creating a CONNECT Packet.
type OptionsPacketCONNECT struct {
	// CleanSession is the Clean Session of the connect flags.
	CleanSession *bool
	// WillTopic is the Will Topic of the payload.
	WillTopic string
	// WillMessage is the Will Message of the payload.
	WillMessage string
	// WillQoS is the Will QoS of the connect flags.
	WillQoS uint
	// WillRetain is the Will Retain of the connect flags.
	WillRetain bool
	// UserName is the user name used by the server for authentication and authorization.
	UserName string
	// Password is the password used by the server for authentication and authorization.
	Password string
	// KeepAlive is the Keep Alive in the variable header.
	KeepAlive *uint
}

// Init initializes the OptionsPacketCONNECT.
func (opts *OptionsPacketCONNECT) Init() {
	if opts.CleanSession == nil {
		opts.CleanSession = &DefaultCleanSession
	}

	if opts.KeepAlive == nil {
		opts.KeepAlive = &DefaultKeepAlive
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 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 main

// This server runs along side the karma tests and listens for POST requests
// when any test case reports it has output for Gold. See testReporter.js
// for the browser side part.

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"image"
	"image/png"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strings"
	"sync"

	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/go/jsonio"
	"go.skia.org/infra/golden/go/types"
)

// This allows us to use upload_dm_results.py out of the box
const JSON_FILENAME = "dm.json"

var (
	outDir = flag.String("out_dir", "/OUT/", "location to dump the Gold JSON and pngs")
	port   = flag.String("port", "8081", "Port to listen on.")

	browser          = flag.String("browser", "Chrome", "Browser Key")
	buildBucketID    = flag.String("buildbucket_build_id", "", "Buildbucket build id key")
	builder          = flag.String("builder", "", "Builder, like 'Test-Debian9-EMCC-GCE-CPU-AVX2-wasm-Debug-All-PathKit'")
	compiledLanguage = flag.String("compiled_language", "wasm", "wasm or asm.js")
	config           = flag.String("config", "Release", "Configuration (e.g. Debug/Release) key")
	gitHash          = flag.String("git_hash", "-", "The git commit hash of the version being tested")
	hostOS           = flag.String("host_os", "Debian9", "OS Key")
	issue            = flag.String("issue", "", "ChangelistID (if tryjob)")
	patchset         = flag.Int("patchset", 0, "patchset (if tryjob)")
	sourceType       = flag.String("source_type", "pathkit", "Gold Source type, like pathkit,canvaskit")
)

// Received from the JS side.
type reportBody struct {
	// e.g. "canvas" or "svg"
	OutputType string `json:"output_type"`
	// a base64 encoded PNG image.
	Data string `json:"data"`
	// a name describing the test. Should be unique enough to allow use of grep.
	TestName string `json:"test_name"`
}

// The keys to be used at the top level for all Results.
var defaultKeys map[string]string

// contains all the results reported in through report_gold_data
var results []*jsonio.Result
var resultsMutex sync.Mutex

func main() {
	flag.Parse()

	cpuGPU := "CPU"
	if strings.Index(*builder, "-GPU-") != -1 {
		cpuGPU = "GPU"
	}
	defaultKeys = map[string]string{
		"arch":              "WASM",
		"browser":           *browser,
		"compiled_language": *compiledLanguage,
		"compiler":          "emsdk",
		"configuration":     *config,
		"cpu_or_gpu":        cpuGPU,
		"cpu_or_gpu_value":  "Browser",
		"os":                *hostOS,
		"source_type":       *sourceType,
	}

	results = []*jsonio.Result{}

	http.HandleFunc("/report_gold_data", reporter)
	http.HandleFunc("/dump_json", dumpJSON)

	fmt.Printf("Waiting for gold ingestion on port %s\n", *port)

	log.Fatal(http.ListenAndServe(":"+*port, nil))
}

// reporter handles when the client reports a test has Gold output.
// It writes the corresponding PNG to disk and appends a Result, assuming
// no errors.
func reporter(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Only POST accepted", 400)
		return
	}
	defer util.Close(r.Body)

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Malformed body", 400)
		return
	}

	testOutput := reportBody{}
	if err := json.Unmarshal(body, &testOutput); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not unmarshal JSON", 400)
		return
	}

	hash := ""
	if hash, err = writeBase64EncodedPNG(testOutput.Data); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not write image to disk", 500)
		return
	}

	if _, err := w.Write([]byte("Accepted")); err != nil {
		fmt.Printf("Could not write response: %s\n", err)
		return
	}

	resultsMutex.Lock()
	defer resultsMutex.Unlock()
	results = append(results, &jsonio.Result{
		Digest: types.Digest(hash),
		Key: map[string]string{
			"name":   testOutput.TestName,
			"config": testOutput.OutputType,
		},
		Options: map[string]string{
			"ext": "png",
		},
	})
}

// createOutputFile creates a file and set permissions correctly.
func createOutputFile(p string) (*os.File, error) {
	outputFile, err := os.Create(p)
	if err != nil {
		return nil, fmt.Errorf("Could not open file %s on disk: %s", p, err)
	}
	// Make this accessible (and deletable) by all users
	if err = outputFile.Chmod(0666); err != nil {
		return nil, fmt.Errorf("Could not change permissions of file %s: %s", p, err)
	}
	return outputFile, nil
}

// dumpJSON writes out a JSON file with all the results, typically at the end of
// all the tests.
func dumpJSON(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Only POST accepted", 400)
		return
	}

	p := path.Join(*outDir, JSON_FILENAME)
	outputFile, err := createOutputFile(p)
	if err != nil {
		fmt.Println(err)
		http.Error(w, "Could not open json file on disk", 500)
		return
	}
	defer util.Close(outputFile)

	dmresults := jsonio.GoldResults{
		GitHash: *gitHash,
		Key:     defaultKeys,
		Results: results,
	}

	if *patchset > 0 {
		dmresults.ChangelistID = *issue
		dmresults.PatchsetOrder = *patchset
		dmresults.CodeReviewSystem = "gerrit"
		dmresults.ContinuousIntegrationSystem = "buildbucket"
		dmresults.TryJobID = *buildBucketID
	}

	enc := json.NewEncoder(outputFile)
	enc.SetIndent("", "  ") // Make it human readable.
	if err := enc.Encode(&dmresults); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not write json to disk", 500)
		return
	}
	fmt.Println("JSON Written")
}

// writeBase64EncodedPNG writes a PNG to disk and returns the md5 of the
// decoded PNG bytes and any error. This hash is what will be used as
// the gold digest and the file name.
func writeBase64EncodedPNG(data string) (string, error) {
	// data starts with something like data:image/png;base64,[data]
	// https://en.wikipedia.org/wiki/Data_URI_scheme
	start := strings.Index(data, ",")
	b := bytes.NewBufferString(data[start+1:])
	pngReader := base64.NewDecoder(base64.StdEncoding, b)

	pngBytes, err := ioutil.ReadAll(pngReader)
	if err != nil {
		return "", fmt.Errorf("Could not decode base 64 encoding %s", err)
	}

	// compute the hash of the pixel values, like DM does
	img, err := png.Decode(bytes.NewBuffer(pngBytes))
	if err != nil {
		return "", fmt.Errorf("Not a valid png: %s", err)
	}
	hash := ""
	switch img.(type) {
	case *image.NRGBA:
		i := img.(*image.NRGBA)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	case *image.RGBA:
		i := img.(*image.RGBA)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	case *image.RGBA64:
		i := img.(*image.RGBA64)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	default:
		return "", fmt.Errorf("Unknown type of image")
	}

	p := path.Join(*outDir, hash+".png")
	outputFile, err := createOutputFile(p)
	if err != nil {
		return "", fmt.Errorf("Could not create png file %s: %s", p, err)
	}
	if _, err = outputFile.Write(pngBytes); err != nil {
		util.Close(outputFile)
		return "", fmt.Errorf("Could not write to file %s: %s", p, err)
	}
	return hash, outputFile.Close()
}
<commit_msg>[infra] Update wasm_gold_aggregator<commit_after>// Copyright 2018 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 main

// This server runs along side the karma tests and listens for POST requests
// when any test case reports it has output for Gold. See testReporter.js
// for the browser side part.

import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"image"
	"image/png"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strings"
	"sync"

	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/go/jsonio"
	"go.skia.org/infra/golden/go/types"
)

// This allows us to use upload_dm_results.py out of the box
const JSON_FILENAME = "dm.json"

var (
	outDir = flag.String("out_dir", "/OUT/", "location to dump the Gold JSON and pngs")
	port   = flag.String("port", "8081", "Port to listen on.")

	browser          = flag.String("browser", "Chrome", "Browser Key")
	buildBucketID    = flag.String("buildbucket_build_id", "", "Buildbucket build id key")
	builder          = flag.String("builder", "", "Builder, like 'Test-Debian9-EMCC-GCE-CPU-AVX2-wasm-Debug-All-PathKit'")
	compiledLanguage = flag.String("compiled_language", "wasm", "wasm or asm.js")
	config           = flag.String("config", "Release", "Configuration (e.g. Debug/Release) key")
	gitHash          = flag.String("git_hash", "-", "The git commit hash of the version being tested")
	hostOS           = flag.String("host_os", "Debian9", "OS Key")
	issue            = flag.String("issue", "", "ChangelistID (if tryjob)")
	patchset         = flag.Int("patchset", 0, "patchset (if tryjob)")
	sourceType       = flag.String("source_type", "pathkit", "Gold Source type, like pathkit,canvaskit")
)

// Received from the JS side.
type reportBody struct {
	// e.g. "canvas" or "svg"
	OutputType string `json:"output_type"`
	// a base64 encoded PNG image.
	Data string `json:"data"`
	// a name describing the test. Should be unique enough to allow use of grep.
	TestName string `json:"test_name"`
}

// The keys to be used at the top level for all Results.
var defaultKeys map[string]string

// contains all the results reported in through report_gold_data
var results []jsonio.Result
var resultsMutex sync.Mutex

func main() {
	flag.Parse()

	cpuGPU := "CPU"
	if strings.Index(*builder, "-GPU-") != -1 {
		cpuGPU = "GPU"
	}
	defaultKeys = map[string]string{
		"arch":              "WASM",
		"browser":           *browser,
		"compiled_language": *compiledLanguage,
		"compiler":          "emsdk",
		"configuration":     *config,
		"cpu_or_gpu":        cpuGPU,
		"cpu_or_gpu_value":  "Browser",
		"os":                *hostOS,
		"source_type":       *sourceType,
	}

	results = []jsonio.Result{}

	http.HandleFunc("/report_gold_data", reporter)
	http.HandleFunc("/dump_json", dumpJSON)

	fmt.Printf("Waiting for gold ingestion on port %s\n", *port)

	log.Fatal(http.ListenAndServe(":"+*port, nil))
}

// reporter handles when the client reports a test has Gold output.
// It writes the corresponding PNG to disk and appends a Result, assuming
// no errors.
func reporter(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Only POST accepted", 400)
		return
	}
	defer util.Close(r.Body)

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Malformed body", 400)
		return
	}

	testOutput := reportBody{}
	if err := json.Unmarshal(body, &testOutput); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not unmarshal JSON", 400)
		return
	}

	hash := ""
	if hash, err = writeBase64EncodedPNG(testOutput.Data); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not write image to disk", 500)
		return
	}

	if _, err := w.Write([]byte("Accepted")); err != nil {
		fmt.Printf("Could not write response: %s\n", err)
		return
	}

	resultsMutex.Lock()
	defer resultsMutex.Unlock()
	results = append(results, jsonio.Result{
		Digest: types.Digest(hash),
		Key: map[string]string{
			"name":   testOutput.TestName,
			"config": testOutput.OutputType,
		},
		Options: map[string]string{
			"ext": "png",
		},
	})
}

// createOutputFile creates a file and set permissions correctly.
func createOutputFile(p string) (*os.File, error) {
	outputFile, err := os.Create(p)
	if err != nil {
		return nil, fmt.Errorf("Could not open file %s on disk: %s", p, err)
	}
	// Make this accessible (and deletable) by all users
	if err = outputFile.Chmod(0666); err != nil {
		return nil, fmt.Errorf("Could not change permissions of file %s: %s", p, err)
	}
	return outputFile, nil
}

// dumpJSON writes out a JSON file with all the results, typically at the end of
// all the tests.
func dumpJSON(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Only POST accepted", 400)
		return
	}

	p := path.Join(*outDir, JSON_FILENAME)
	outputFile, err := createOutputFile(p)
	if err != nil {
		fmt.Println(err)
		http.Error(w, "Could not open json file on disk", 500)
		return
	}
	defer util.Close(outputFile)

	dmresults := jsonio.GoldResults{
		GitHash: *gitHash,
		Key:     defaultKeys,
		Results: results,
	}

	if *patchset > 0 {
		dmresults.ChangelistID = *issue
		dmresults.PatchsetOrder = *patchset
		dmresults.CodeReviewSystem = "gerrit"
		dmresults.ContinuousIntegrationSystem = "buildbucket"
		dmresults.TryJobID = *buildBucketID
	}

	enc := json.NewEncoder(outputFile)
	enc.SetIndent("", "  ") // Make it human readable.
	if err := enc.Encode(&dmresults); err != nil {
		fmt.Println(err)
		http.Error(w, "Could not write json to disk", 500)
		return
	}
	fmt.Println("JSON Written")
}

// writeBase64EncodedPNG writes a PNG to disk and returns the md5 of the
// decoded PNG bytes and any error. This hash is what will be used as
// the gold digest and the file name.
func writeBase64EncodedPNG(data string) (string, error) {
	// data starts with something like data:image/png;base64,[data]
	// https://en.wikipedia.org/wiki/Data_URI_scheme
	start := strings.Index(data, ",")
	b := bytes.NewBufferString(data[start+1:])
	pngReader := base64.NewDecoder(base64.StdEncoding, b)

	pngBytes, err := ioutil.ReadAll(pngReader)
	if err != nil {
		return "", fmt.Errorf("Could not decode base 64 encoding %s", err)
	}

	// compute the hash of the pixel values, like DM does
	img, err := png.Decode(bytes.NewBuffer(pngBytes))
	if err != nil {
		return "", fmt.Errorf("Not a valid png: %s", err)
	}
	hash := ""
	switch img.(type) {
	case *image.NRGBA:
		i := img.(*image.NRGBA)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	case *image.RGBA:
		i := img.(*image.RGBA)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	case *image.RGBA64:
		i := img.(*image.RGBA64)
		hash = fmt.Sprintf("%x", md5.Sum(i.Pix))
	default:
		return "", fmt.Errorf("Unknown type of image")
	}

	p := path.Join(*outDir, hash+".png")
	outputFile, err := createOutputFile(p)
	if err != nil {
		return "", fmt.Errorf("Could not create png file %s: %s", p, err)
	}
	if _, err = outputFile.Write(pngBytes); err != nil {
		util.Close(outputFile)
		return "", fmt.Errorf("Could not write to file %s: %s", p, err)
	}
	return hash, outputFile.Close()
}
<|endoftext|>


<commit_before>// This is a client that writes out to a file, and optionally rolls the file

package main

import (
	"compress/gzip"
	"errors"
	"flag"
	"fmt"
	"github.com/bitly/nsq/nsq"
	"github.com/bitly/nsq/util"
	"log"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"
)

var (
	datetimeFormat   = flag.String("datetime-format", "%Y-%m-%d_%H", "strftime compatible format for <DATETIME> in filename format")
	filenameFormat   = flag.String("filename-format", "<TOPIC>.<HOST><GZIPREV>.<DATETIME>.log", "output filename format (<TOPIC>, <HOST>, <DATETIME>, <GZIPREV> are replaced. <GZIPREV> is a suffix when an existing gzip file already exists)")
	showVersion      = flag.Bool("version", false, "print version string")
	hostIdentifier   = flag.String("host-identifier", "", "value to output in log filename in place of hostname. <SHORT_HOST> and <HOSTNAME> are valid replacement tokens")
	outputDir        = flag.String("output-dir", "/tmp", "directory to write output files to")
	topic            = flag.String("topic", "", "nsq topic")
	channel          = flag.String("channel", "nsq_to_file", "nsq channel")
	maxInFlight      = flag.Int("max-in-flight", 1000, "max number of messages to allow in flight")
	gzipCompression  = flag.Int("gzip-compression", 3, "gzip compression level. 1 BestSpeed, 2 BestCompression, 3 DefaultCompression")
	gzipEnabled      = flag.Bool("gzip", false, "gzip output files.")
	verbose          = flag.Bool("verbose", false, "verbose logging")
	nsqdTCPAddrs     = util.StringArray{}
	lookupdHTTPAddrs = util.StringArray{}
)

func init() {
	flag.Var(&nsqdTCPAddrs, "nsqd-tcp-address", "nsqd TCP address (may be given multiple times)")
	flag.Var(&lookupdHTTPAddrs, "lookupd-http-address", "lookupd HTTP address (may be given multiple times)")
}

type FileLogger struct {
	out              *os.File
	gzipWriter       *gzip.Writer
	lastFilename     string
	logChan          chan *Message
	compressionLevel int
	gzipEnabled      bool
	filenameFormat   string
}

type Message struct {
	*nsq.Message
	returnChannel chan *nsq.FinishedMessage
}

type SyncMsg struct {
	m             *nsq.FinishedMessage
	returnChannel chan *nsq.FinishedMessage
}

func (l *FileLogger) HandleMessage(m *nsq.Message, responseChannel chan *nsq.FinishedMessage) {
	l.logChan <- &Message{m, responseChannel}
}

func router(r *nsq.Reader, f *FileLogger, termChan chan os.Signal, hupChan chan os.Signal) {
	pos := 0
	output := make([]*Message, *maxInFlight)
	sync := false
	ticker := time.NewTicker(time.Duration(30) * time.Second)
	closing := false

	for {
		select {
		case <-termChan:
			ticker.Stop()
			r.Stop()
			// ensures that we keep flushing whatever is left in the channels
			closing = true
		case <-hupChan:
			f.Close()
			f.updateFile()
			sync = true
		case <-ticker.C:
			f.updateFile()
			sync = true
		case m := <-f.logChan:
			if f.updateFile() {
				sync = true
			}
			_, err := f.Write(m.Body)
			if err != nil {
				log.Fatalf("ERROR: writing message to disk - %s", err.Error())
			}
			_, err = f.Write([]byte("\n"))
			if err != nil {
				log.Fatalf("ERROR: writing newline to disk - %s", err.Error())
			}
			output[pos] = m
			pos++
			if pos == *maxInFlight {
				sync = true
			}
		}

		if closing || sync || r.IsStarved() {
			if pos > 0 {
				log.Printf("syncing %d records to disk", pos)
				err := f.Sync()
				if err != nil {
					log.Fatalf("ERROR: failed syncing messages - %s", err.Error())
				}
				for pos > 0 {
					pos--
					m := output[pos]
					m.returnChannel <- &nsq.FinishedMessage{m.Id, 0, true}
					output[pos] = nil
				}
			}
			sync = false
		}
	}
}

func (f *FileLogger) Close() {
	if f.out != nil {
		if f.gzipWriter != nil {
			f.gzipWriter.Close()
		}
		f.out.Close()
		f.out = nil
	}
}
func (f *FileLogger) Write(p []byte) (n int, err error) {
	if f.gzipWriter != nil {
		return f.gzipWriter.Write(p)
	}
	return f.out.Write(p)
}
func (f *FileLogger) Sync() error {
	var err error
	if f.gzipWriter != nil {
		f.gzipWriter.Close()
		err = f.out.Sync()
		f.gzipWriter, _ = gzip.NewWriterLevel(f.out, f.compressionLevel)
	} else {
		err = f.out.Sync()
	}
	return err
}

func (f *FileLogger) calculateCurrentFilename() string {
	t := time.Now()

	datetime := strftime(*datetimeFormat, t)
	filename := strings.Replace(f.filenameFormat, "<DATETIME>", datetime, -1)
	if !f.gzipEnabled {
		filename = strings.Replace(filename, "<GZIPREV>", "", -1)
	}
	return filename

}

func (f *FileLogger) updateFile() bool {
	filename := f.calculateCurrentFilename()
	maxGzipRevisions := 1000
	if filename != f.lastFilename || f.out == nil {
		f.Close()
		os.MkdirAll(*outputDir, 777)
		var newFile *os.File
		var err error
		if f.gzipEnabled {
			// for gzip files, we never append to an existing file
			// we try to create different revisions, replacing <GZIPREV> in the filename
			for gzipRevision := 0; gzipRevision < maxGzipRevisions; gzipRevision += 1 {
				var revisionSuffix string
				if gzipRevision > 0 {
					revisionSuffix = fmt.Sprintf("-%d", gzipRevision)
				}
				tempFilename := strings.Replace(filename, "<GZIPREV>", revisionSuffix, -1)
				fullPath := path.Join(*outputDir, tempFilename)
				newFile, err = os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
				if err != nil && os.IsExist(err) {
					log.Printf("INFO: file already exists: %s", fullPath)
					continue
				}
				if err != nil {
					log.Fatalf("ERROR: %s Unable to open %s", err, fullPath)
				}
				log.Printf("opening %s", fullPath)
				break
			}
			if newFile == nil {
				log.Fatalf("ERROR: Unable to open a new gzip file after %d tries", maxGzipRevisions)
			}
		} else {
			log.Printf("opening %s/%s", *outputDir, filename)
			newFile, err = os.OpenFile(path.Join(*outputDir, filename), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				log.Fatal(err)
			}
		}

		f.out = newFile
		f.lastFilename = filename
		if f.gzipEnabled {
			f.gzipWriter, _ = gzip.NewWriterLevel(newFile, f.compressionLevel)
		}
		return true
	}

	return false
}

func NewFileLogger(gzipEnabled bool, compressionLevel int, filenameFormat string) (*FileLogger, error) {
	var speed int
	switch compressionLevel {
	case 1:
		speed = gzip.BestSpeed
	case 2:
		speed = gzip.BestCompression
	case 3:
		speed = gzip.DefaultCompression
	}

	if gzipEnabled && strings.Index(filenameFormat, "<GZIPREV>") == -1 {
		return nil, errors.New("missing <GZIPREV> in filenameFormat")
	}

	hostname, err := os.Hostname()
	if err != nil {
		return nil, err
	}
	shortHostname := strings.Split(hostname, ".")[0]
	identifier := shortHostname
	if len(*hostIdentifier) != 0 {
		identifier = strings.Replace(*hostIdentifier, "<SHORT_HOST>", shortHostname, -1)
		identifier = strings.Replace(identifier, "<HOSTNAME>", hostname, -1)
	}
	filenameFormat = strings.Replace(filenameFormat, "<TOPIC>", *topic, -1)
	filenameFormat = strings.Replace(filenameFormat, "<HOST>", identifier, -1)
	if gzipEnabled && !strings.HasSuffix(filenameFormat, ".gz") {
		filenameFormat = filenameFormat + ".gz"
	}

	f := &FileLogger{
		logChan:          make(chan *Message, 1),
		compressionLevel: speed,
		filenameFormat:   filenameFormat,
		gzipEnabled:      gzipEnabled,
	}
	return f, nil
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("nsq_to_file v%s\n", util.BINARY_VERSION)
		return
	}

	if *topic == "" || *channel == "" {
		log.Fatalf("--topic and --channel are required")
	}

	if *maxInFlight < 0 {
		log.Fatalf("--max-in-flight must be > 0")
	}

	if len(nsqdTCPAddrs) == 0 && len(lookupdHTTPAddrs) == 0 {
		log.Fatalf("--nsqd-tcp-address or --lookupd-http-address required.")
	}
	if len(nsqdTCPAddrs) != 0 && len(lookupdHTTPAddrs) != 0 {
		log.Fatalf("use --nsqd-tcp-address or --lookupd-http-address not both")
	}

	if *gzipCompression < 1 || *gzipCompression > 3 {
		log.Fatalf("invalid --gzip-compresion value (%v). should be 1,2 or 3", *gzipCompression)
	}

	hupChan := make(chan os.Signal, 1)
	termChan := make(chan os.Signal, 1)
	signal.Notify(hupChan, syscall.SIGHUP)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)

	f, err := NewFileLogger(*gzipEnabled, *gzipCompression, *filenameFormat)
	if err != nil {
		log.Fatal(err.Error())
	}

	r, err := nsq.NewReader(*topic, *channel)
	if err != nil {
		log.Fatalf(err.Error())
	}
	r.SetMaxInFlight(*maxInFlight)
	r.VerboseLogging = *verbose

	r.AddAsyncHandler(f)
	go router(r, f, termChan, hupChan)

	for _, addrString := range nsqdTCPAddrs {
		err := r.ConnectToNSQ(addrString)
		if err != nil {
			log.Fatalf(err.Error())
		}
	}

	for _, addrString := range lookupdHTTPAddrs {
		log.Printf("lookupd addr %s", addrString)
		err := r.ConnectToLookupd(addrString)
		if err != nil {
			log.Fatalf(err.Error())
		}
	}

	<-r.ExitChan
}
<commit_msg>fix cases that caused empty files<commit_after>// This is a client that writes out to a file, and optionally rolls the file

package main

import (
	"compress/gzip"
	"errors"
	"flag"
	"fmt"
	"github.com/bitly/nsq/nsq"
	"github.com/bitly/nsq/util"
	"log"
	"os"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"time"
)

var (
	datetimeFormat   = flag.String("datetime-format", "%Y-%m-%d_%H", "strftime compatible format for <DATETIME> in filename format")
	filenameFormat   = flag.String("filename-format", "<TOPIC>.<HOST><GZIPREV>.<DATETIME>.log", "output filename format (<TOPIC>, <HOST>, <DATETIME>, <GZIPREV> are replaced. <GZIPREV> is a suffix when an existing gzip file already exists)")
	showVersion      = flag.Bool("version", false, "print version string")
	hostIdentifier   = flag.String("host-identifier", "", "value to output in log filename in place of hostname. <SHORT_HOST> and <HOSTNAME> are valid replacement tokens")
	outputDir        = flag.String("output-dir", "/tmp", "directory to write output files to")
	topic            = flag.String("topic", "", "nsq topic")
	channel          = flag.String("channel", "nsq_to_file", "nsq channel")
	maxInFlight      = flag.Int("max-in-flight", 1000, "max number of messages to allow in flight")
	gzipCompression  = flag.Int("gzip-compression", 3, "gzip compression level. 1 BestSpeed, 2 BestCompression, 3 DefaultCompression")
	gzipEnabled      = flag.Bool("gzip", false, "gzip output files.")
	verbose          = flag.Bool("verbose", false, "verbose logging")
	skipEmptyFiles   = flag.Bool("skip-empty-files", false, "Skip writting empty files")
	nsqdTCPAddrs     = util.StringArray{}
	lookupdHTTPAddrs = util.StringArray{}
)

func init() {
	flag.Var(&nsqdTCPAddrs, "nsqd-tcp-address", "nsqd TCP address (may be given multiple times)")
	flag.Var(&lookupdHTTPAddrs, "lookupd-http-address", "lookupd HTTP address (may be given multiple times)")
}

type FileLogger struct {
	out              *os.File
	gzipWriter       *gzip.Writer
	lastFilename     string
	logChan          chan *Message
	compressionLevel int
	gzipEnabled      bool
	filenameFormat   string

	ExitChan chan int
}

type Message struct {
	*nsq.Message
	returnChannel chan *nsq.FinishedMessage
}

type SyncMsg struct {
	m             *nsq.FinishedMessage
	returnChannel chan *nsq.FinishedMessage
}

func (l *FileLogger) HandleMessage(m *nsq.Message, responseChannel chan *nsq.FinishedMessage) {
	l.logChan <- &Message{m, responseChannel}
}

func (f *FileLogger) router(r *nsq.Reader, termChan chan os.Signal, hupChan chan os.Signal) {
	pos := 0
	output := make([]*Message, *maxInFlight)
	sync := false
	ticker := time.NewTicker(time.Duration(30) * time.Second)
	closing := false
	closeFile := false
	exit := false

	for {
		select {
		case <-r.ExitChan:
			sync = true
			closeFile = true
			exit = true
		case <-termChan:
			ticker.Stop()
			r.Stop()
			sync = true
			closing = true
		case <-hupChan:
			sync = true
			closeFile = true
		case <-ticker.C:
			if f.needsFileRotate() {
				if *skipEmptyFiles {
					closeFile = true
				} else {
					f.updateFile()
				}
			}
			sync = true
		case m := <-f.logChan:
			if f.updateFile() {
				sync = true
			}
			_, err := f.Write(m.Body)
			if err != nil {
				log.Fatalf("ERROR: writing message to disk - %s", err.Error())
			}
			_, err = f.Write([]byte("\n"))
			if err != nil {
				log.Fatalf("ERROR: writing newline to disk - %s", err.Error())
			}
			output[pos] = m
			pos++
			if pos == *maxInFlight {
				sync = true
			}
		}

		if closing || sync || r.IsStarved() {
			if pos > 0 {
				log.Printf("syncing %d records to disk", pos)
				err := f.Sync()
				if err != nil {
					log.Fatalf("ERROR: failed syncing messages - %s", err.Error())
				}
				for pos > 0 {
					pos--
					m := output[pos]
					m.returnChannel <- &nsq.FinishedMessage{m.Id, 0, true}
					output[pos] = nil
				}
			}
			sync = false
		}

		if closeFile {
			f.Close()
			closeFile = false
		}
		if exit {
			close(f.ExitChan)
			break
		}
	}
}

func (f *FileLogger) Close() {
	if f.out != nil {
		if f.gzipWriter != nil {
			f.gzipWriter.Close()
		}
		f.out.Close()
		f.out = nil
	}
}
func (f *FileLogger) Write(p []byte) (n int, err error) {
	if f.gzipWriter != nil {
		return f.gzipWriter.Write(p)
	}
	return f.out.Write(p)
}
func (f *FileLogger) Sync() error {
	var err error
	if f.gzipWriter != nil {
		f.gzipWriter.Close()
		err = f.out.Sync()
		f.gzipWriter, _ = gzip.NewWriterLevel(f.out, f.compressionLevel)
	} else {
		err = f.out.Sync()
	}
	return err
}

func (f *FileLogger) calculateCurrentFilename() string {
	t := time.Now()

	datetime := strftime(*datetimeFormat, t)
	filename := strings.Replace(f.filenameFormat, "<DATETIME>", datetime, -1)
	if !f.gzipEnabled {
		filename = strings.Replace(filename, "<GZIPREV>", "", -1)
	}
	return filename

}

func (f *FileLogger) needsFileRotate() bool {
	filename := f.calculateCurrentFilename()
	return filename != f.lastFilename
}

func (f *FileLogger) updateFile() bool {
	filename := f.calculateCurrentFilename()
	maxGzipRevisions := 1000
	if filename != f.lastFilename || f.out == nil {
		f.Close()
		os.MkdirAll(*outputDir, 777)
		var newFile *os.File
		var err error
		if f.gzipEnabled {
			// for gzip files, we never append to an existing file
			// we try to create different revisions, replacing <GZIPREV> in the filename
			for gzipRevision := 0; gzipRevision < maxGzipRevisions; gzipRevision += 1 {
				var revisionSuffix string
				if gzipRevision > 0 {
					revisionSuffix = fmt.Sprintf("-%d", gzipRevision)
				}
				tempFilename := strings.Replace(filename, "<GZIPREV>", revisionSuffix, -1)
				fullPath := path.Join(*outputDir, tempFilename)
				newFile, err = os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
				if err != nil && os.IsExist(err) {
					log.Printf("INFO: file already exists: %s", fullPath)
					continue
				}
				if err != nil {
					log.Fatalf("ERROR: %s Unable to open %s", err, fullPath)
				}
				log.Printf("opening %s", fullPath)
				break
			}
			if newFile == nil {
				log.Fatalf("ERROR: Unable to open a new gzip file after %d tries", maxGzipRevisions)
			}
		} else {
			log.Printf("opening %s/%s", *outputDir, filename)
			newFile, err = os.OpenFile(path.Join(*outputDir, filename), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				log.Fatal(err)
			}
		}

		f.out = newFile
		f.lastFilename = filename
		if f.gzipEnabled {
			f.gzipWriter, _ = gzip.NewWriterLevel(newFile, f.compressionLevel)
		}
		return true
	}

	return false
}

func NewFileLogger(gzipEnabled bool, compressionLevel int, filenameFormat string) (*FileLogger, error) {
	var speed int
	switch compressionLevel {
	case 1:
		speed = gzip.BestSpeed
	case 2:
		speed = gzip.BestCompression
	case 3:
		speed = gzip.DefaultCompression
	}

	if gzipEnabled && strings.Index(filenameFormat, "<GZIPREV>") == -1 {
		return nil, errors.New("missing <GZIPREV> in filenameFormat")
	}

	hostname, err := os.Hostname()
	if err != nil {
		return nil, err
	}
	shortHostname := strings.Split(hostname, ".")[0]
	identifier := shortHostname
	if len(*hostIdentifier) != 0 {
		identifier = strings.Replace(*hostIdentifier, "<SHORT_HOST>", shortHostname, -1)
		identifier = strings.Replace(identifier, "<HOSTNAME>", hostname, -1)
	}
	filenameFormat = strings.Replace(filenameFormat, "<TOPIC>", *topic, -1)
	filenameFormat = strings.Replace(filenameFormat, "<HOST>", identifier, -1)
	if gzipEnabled && !strings.HasSuffix(filenameFormat, ".gz") {
		filenameFormat = filenameFormat + ".gz"
	}

	f := &FileLogger{
		logChan:          make(chan *Message, 1),
		compressionLevel: speed,
		filenameFormat:   filenameFormat,
		gzipEnabled:      gzipEnabled,
		ExitChan:         make(chan int),
	}
	return f, nil
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("nsq_to_file v%s\n", util.BINARY_VERSION)
		return
	}

	if *topic == "" || *channel == "" {
		log.Fatalf("--topic and --channel are required")
	}

	if *maxInFlight < 0 {
		log.Fatalf("--max-in-flight must be > 0")
	}

	if len(nsqdTCPAddrs) == 0 && len(lookupdHTTPAddrs) == 0 {
		log.Fatalf("--nsqd-tcp-address or --lookupd-http-address required.")
	}
	if len(nsqdTCPAddrs) != 0 && len(lookupdHTTPAddrs) != 0 {
		log.Fatalf("use --nsqd-tcp-address or --lookupd-http-address not both")
	}

	if *gzipCompression < 1 || *gzipCompression > 3 {
		log.Fatalf("invalid --gzip-compresion value (%v). should be 1,2 or 3", *gzipCompression)
	}

	hupChan := make(chan os.Signal, 1)
	termChan := make(chan os.Signal, 1)
	signal.Notify(hupChan, syscall.SIGHUP)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)

	f, err := NewFileLogger(*gzipEnabled, *gzipCompression, *filenameFormat)
	if err != nil {
		log.Fatal(err.Error())
	}

	r, err := nsq.NewReader(*topic, *channel)
	if err != nil {
		log.Fatalf(err.Error())
	}
	r.SetMaxInFlight(*maxInFlight)
	r.VerboseLogging = *verbose

	r.AddAsyncHandler(f)
	go f.router(r, termChan, hupChan)

	for _, addrString := range nsqdTCPAddrs {
		err := r.ConnectToNSQ(addrString)
		if err != nil {
			log.Fatalf(err.Error())
		}
	}

	for _, addrString := range lookupdHTTPAddrs {
		log.Printf("lookupd addr %s", addrString)
		err := r.ConnectToLookupd(addrString)
		if err != nil {
			log.Fatalf(err.Error())
		}
	}

	<-f.ExitChan
}
<|endoftext|>


<commit_before>package utils

import (
  "strings"
  "net/http"
)

type ipAddress string

// IP address helpers taken
// from https://groups.google.com/forum/#!topic/golang-nuts/lomWKs0kOfE

// Request.RemoteAddress contains port, which we want to remove i.e.:
// "[::1]:58292" => "[::1]"
func ipAddrFromRemoteAddr(s string) string {
  idx := strings.LastIndex(s, ":")
  if idx == -1 {
    return s
  }
  return s[:idx]
}

func GetIpAddress(r *http.Request) string {
  hdr := r.Header
  hdrRealIp := hdr.Get("X-Real-Ip")
  hdrForwardedFor := hdr.Get("X-Forwarded-For")
  if hdrRealIp == "" && hdrForwardedFor == "" {
    return ipAddrFromRemoteAddr(r.RemoteAddr)
  }
  if hdrForwardedFor != "" {
    // X-Forwarded-For is potentially a list of addresses separated with ","
    parts := strings.Split(hdrForwardedFor, ",")
    for i, p := range parts {
      parts[i] = strings.TrimSpace(p)
    }
    // TODO: should return first non-local address
    return parts[0]
  }
  return hdrRealIp
}
<commit_msg>Update utils.go with gofmt<commit_after>package utils

import (
	"net/http"
	"strings"
)

type ipAddress string

// IP address helpers taken
// from https://groups.google.com/forum/#!topic/golang-nuts/lomWKs0kOfE

// Request.RemoteAddress contains port, which we want to remove i.e.:
// "[::1]:58292" => "[::1]"
func ipAddrFromRemoteAddr(s string) string {
	idx := strings.LastIndex(s, ":")
	if idx == -1 {
		return s
	}
	return s[:idx]
}

func GetIpAddress(r *http.Request) string {
	hdr := r.Header
	hdrRealIp := hdr.Get("X-Real-Ip")
	hdrForwardedFor := hdr.Get("X-Forwarded-For")
	if hdrRealIp == "" && hdrForwardedFor == "" {
		return ipAddrFromRemoteAddr(r.RemoteAddr)
	}
	if hdrForwardedFor != "" {
		// X-Forwarded-For is potentially a list of addresses separated with ","
		parts := strings.Split(hdrForwardedFor, ",")
		for i, p := range parts {
			parts[i] = strings.TrimSpace(p)
		}
		// TODO: should return first non-local address
		return parts[0]
	}
	return hdrRealIp
}
<|endoftext|>


<commit_before>package wats

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

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
)

var _ = Describe("Application Lifecycle", func() {
	reportedComputerNames := func(instances int) map[string]bool {
		timer := time.NewTimer(time.Second * 120)
		defer timer.Stop()
		run := true
		go func() {
			<-timer.C
			run = false
		}()

		seenComputerNames := map[string]bool{}
		for len(seenComputerNames) != instances && run == true {
			seenComputerNames[helpers.CurlApp(config, appName, "/ENV/CF_INSTANCE_IP")] = true
		}

		return seenComputerNames
	}

	BeforeEach(func() {
		memLimit := config.GetNumWindowsCells() * 2 * 4
		if memLimit < 10 {
			memLimit = 10
		}
		setTotalMemoryLimit(fmt.Sprintf("%dG", memLimit))
	})

	AfterEach(func() {
		setTotalMemoryLimit("10G")
	})

	Describe("An app staged on Diego and running on Diego", func() {
		It("attempts to forkbomb the environment", func() {
			src, err := os.Open("../../assets/greenhouse-security-fixtures/bin/BreakoutBomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer src.Close()
			dst, err := os.Create("../../assets/nora/NoraPublished/bin/breakoutbomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer dst.Close()
			_, err = io.Copy(dst, src)
			Expect(err).NotTo(HaveOccurred())
			dst.Close()

			By("pushing it", func() {
				Expect(pushNoraWithOptions(appName, config.GetNumWindowsCells()*2, "2G").Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("staging and running it on Diego", func() {
				Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("verifying it's up", func() {
				Eventually(appRunning(appName, config.GetNumWindowsCells()*2, CF_PUSH_TIMEOUT), CF_PUSH_TIMEOUT).Should(Succeed())
				Eventually(helpers.CurlingAppRoot(config, appName)).Should(ContainSubstring("hello i am nora"))
			})

			By("storing the current computer names")
			computerNames := reportedComputerNames(config.GetNumWindowsCells())
			Expect(len(computerNames)).To(Equal(config.GetNumWindowsCells()))

			By("Running fork bomb", func() {
				helpers.CurlApp(config, appName, "/run", "-f", "-X", "POST", "-d", "bin/breakoutbomb.exe")
			})

			time.Sleep(3 * time.Second)

			By("Making sure the bomb did not take down the machine", func() {
				newComputerNames := reportedComputerNames(config.GetNumWindowsCells())
				Expect(newComputerNames).To(Equal(computerNames))
			})
		})
	})
})
<commit_msg>Revert "Don't skip forkbomb test on windows2016"<commit_after>package wats

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

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
)

var _ = Describe("Application Lifecycle", func() {
	reportedComputerNames := func(instances int) map[string]bool {
		timer := time.NewTimer(time.Second * 120)
		defer timer.Stop()
		run := true
		go func() {
			<-timer.C
			run = false
		}()

		seenComputerNames := map[string]bool{}
		for len(seenComputerNames) != instances && run == true {
			seenComputerNames[helpers.CurlApp(config, appName, "/ENV/CF_INSTANCE_IP")] = true
		}

		return seenComputerNames
	}

	BeforeEach(func() {
		if config.GetStack() == "windows2016" {
			Skip("this test may not pass on windows2016")
		}

		memLimit := config.GetNumWindowsCells() * 2 * 4
		if memLimit < 10 {
			memLimit = 10
		}
		setTotalMemoryLimit(fmt.Sprintf("%dG", memLimit))
	})

	AfterEach(func() {
		setTotalMemoryLimit("10G")
	})

	Describe("An app staged on Diego and running on Diego", func() {
		It("attempts to forkbomb the environment", func() {
			src, err := os.Open("../../assets/greenhouse-security-fixtures/bin/BreakoutBomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer src.Close()
			dst, err := os.Create("../../assets/nora/NoraPublished/bin/breakoutbomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer dst.Close()
			_, err = io.Copy(dst, src)
			Expect(err).NotTo(HaveOccurred())
			dst.Close()

			By("pushing it", func() {
				Expect(pushNoraWithOptions(appName, config.GetNumWindowsCells()*2, "2G").Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("staging and running it on Diego", func() {
				Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("verifying it's up", func() {
				Eventually(appRunning(appName, config.GetNumWindowsCells()*2, CF_PUSH_TIMEOUT), CF_PUSH_TIMEOUT).Should(Succeed())
				Eventually(helpers.CurlingAppRoot(config, appName)).Should(ContainSubstring("hello i am nora"))
			})

			By("storing the current computer names")
			computerNames := reportedComputerNames(config.GetNumWindowsCells())
			Expect(len(computerNames)).To(Equal(config.GetNumWindowsCells()))

			By("Running fork bomb", func() {
				helpers.CurlApp(config, appName, "/run", "-f", "-X", "POST", "-d", "bin/breakoutbomb.exe")
			})

			time.Sleep(3 * time.Second)

			By("Making sure the bomb did not take down the machine", func() {
				newComputerNames := reportedComputerNames(config.GetNumWindowsCells())
				Expect(newComputerNames).To(Equal(computerNames))
			})
		})
	})
})
<|endoftext|>