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

package lease

import (
	"container/list"
	"fmt"
	"log"
	"os"

	"github.com/jacobsa/fuse/fsutil"
	"github.com/jacobsa/gcloud/syncutil"
)

// A type that manages read and read/write leases for anonymous temporary files.
//
// Safe for concurrent access.
type FileLeaser interface {
	// Create a new anonymous file, and return a read/write lease for it. The
	// read/write lease will pin resources until rwl.Downgrade is called. It need
	// not be called if the process is exiting.
	NewFile() (rwl ReadWriteLease, err error)

	// Revoke all read leases that have been issued. For testing use only.
	RevokeReadLeases()
}

// Create a new file leaser that uses the supplied directory for temporary
// files (before unlinking them) and attempts to keep usage in number of files
// and bytes below the given limits. If dir is empty, the system default will be
// used.
//
// Usage may exceed the given limits if there are read/write leases whose total
// size exceeds the limits, since such leases cannot be revoked.
func NewFileLeaser(
	dir string,
	limitNumFiles int,
	limitBytes int64) (fl FileLeaser) {
	typed := &fileLeaser{
		dir:             dir,
		limitNumFiles:   limitNumFiles,
		limitBytes:      limitBytes,
		readLeasesIndex: make(map[*readLease]*list.Element),
	}

	typed.mu = syncutil.NewInvariantMutex(typed.checkInvariants)

	fl = typed
	return
}

type fileLeaser struct {
	/////////////////////////
	// Constant data
	/////////////////////////

	dir           string
	limitNumFiles int
	limitBytes    int64

	/////////////////////////
	// Mutable state
	/////////////////////////

	// A lock that guards the mutable state in this struct. Usually this is used
	// only for light weight operations, but while evicting it may require
	// waiting on a goroutine that is holding a read lease lock while reading
	// from a file.
	//
	// Lock ordering
	// -------------
	//
	// Define < to be the minimum strict partial order satisfying:
	//
	//  1. For any read/write lease W, W < leaser.
	//  2. For any read lease R, leaser < R.
	//
	// In other words: read/write before leaser before read, and never hold two
	// locks from the same category together.
	mu syncutil.InvariantMutex

	// The number of outstanding read/write leases.
	readWriteCount int

	// The current estimated total size of outstanding read/write leases. This is
	// only an estimate because we can't synchronize its update with a call to
	// the wrapped file to e.g. write or truncate.
	readWriteBytes int64

	// All outstanding read leases, ordered by recency of use.
	//
	// INVARIANT: Each element is of type *readLease
	// INVARIANT: No element has been revoked.
	// INVARIANT: 0 <= readLeases.Len() <= max(0, limitNumFiles - readWriteCount)
	readLeases list.List

	// The sum of all outstanding read lease sizes.
	//
	// INVARIANT: Equal to the sum over readLeases sizes.
	// INVARIANT: 0 <= readOutstanding
	// INVARIANT: readOutstanding <= max(0, limitBytes - readWriteBytes)
	readOutstanding int64

	// Index of read leases by pointer.
	//
	// INVARIANT: Is an index of exactly the elements of readLeases
	readLeasesIndex map[*readLease]*list.Element
}

func (fl *fileLeaser) NewFile() (rwl ReadWriteLease, err error) {
	// Create an anonymous file.
	f, err := fsutil.AnonymousFile(fl.dir)
	if err != nil {
		err = fmt.Errorf("AnonymousFile: %v", err)
		return
	}

	// Wrap a lease around it.
	rwl = newReadWriteLease(fl, 0, f)

	return
}

// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) RevokeReadLeases() {
	fl.mu.Lock()
	defer fl.mu.Unlock()

	fl.evict(0)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func maxInt(a int, b int) int {
	if a > b {
		return a
	}

	return b
}

func maxInt64(a int64, b int64) int64 {
	if a > b {
		return a
	}

	return b
}

// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) checkInvariants() {
	// INVARIANT: Each element is of type *readLease
	// INVARIANT: No element has been revoked.
	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		rl := e.Value.(*readLease)
		func() {
			rl.Mu.Lock()
			defer rl.Mu.Unlock()

			if rl.revoked() {
				panic("Found revoked read lease")
			}
		}()
	}

	// INVARIANT: 0 <= readLeases.Len() <= max(0, limitNumFiles - readWriteCount)
	if !(0 <= fl.readLeases.Len() &&
		fl.readLeases.Len() <= maxInt(0, fl.limitNumFiles-fl.readWriteCount)) {
		panic(fmt.Sprintf(
			"Out of range read lease count: %d, limitNumFiles: %d, readWriteCount: %d",
			fl.readLeases.Len(),
			fl.limitNumFiles,
			fl.readWriteCount))
	}

	// INVARIANT: Equal to the sum over readLeases sizes.
	var sum int64
	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		rl := e.Value.(*readLease)
		sum += rl.Size()
	}

	if fl.readOutstanding != sum {
		panic(fmt.Sprintf(
			"readOutstanding mismatch: %v vs. %v",
			fl.readOutstanding,
			sum))
	}

	// INVARIANT: 0 <= readOutstanding
	if !(0 <= fl.readOutstanding) {
		panic(fmt.Sprintf("Unexpected readOutstanding: %v", fl.readOutstanding))
	}

	// INVARIANT: readOutstanding <= max(0, limitBytes - readWriteBytes)
	if !(fl.readOutstanding <= maxInt64(0, fl.limitBytes-fl.readWriteBytes)) {
		panic(fmt.Sprintf(
			"Unexpected readOutstanding: %v. limitBytes: %v, readWriteBytes: %v",
			fl.readOutstanding,
			fl.limitBytes,
			fl.readWriteBytes))
	}

	// INVARIANT: Is an index of exactly the elements of readLeases
	if len(fl.readLeasesIndex) != fl.readLeases.Len() {
		panic(fmt.Sprintf(
			"readLeasesIndex length mismatch: %v vs. %v",
			len(fl.readLeasesIndex),
			fl.readLeases.Len()))
	}

	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		if fl.readLeasesIndex[e.Value.(*readLease)] != e {
			panic("Mismatch in readLeasesIndex")
		}
	}
}

// Add the supplied delta to the leaser's view of outstanding read/write lease
// bytes, then revoke read leases until we're under limitBytes or we run out of
// leases to revoke.
//
// Called by readWriteLease while holding its lock.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) addReadWriteByteDelta(delta int64) {
	fl.readWriteBytes += delta
	fl.evict(fl.limitBytes)
}

// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) overLimit(limitBytes int64) bool {
	return fl.readOutstanding+fl.readWriteBytes > limitBytes
}

// Revoke read leases until we're within the given limitBytes or we run out of
// things to revoke.
//
// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) evict(limitBytes int64) {
	for fl.overLimit(limitBytes) {
		// Do we have anything to revoke?
		lru := fl.readLeases.Back()
		if lru == nil {
			return
		}

		// Revoke it.
		rl := lru.Value.(*readLease)
		func() {
			rl.Mu.Lock()
			defer rl.Mu.Unlock()

			fl.revoke(rl)
		}()
	}
}

// Note that a read/write lease of the given size is destroying itself, and
// turn it into a read lease of the supplied size wrapped around the given
// file.
//
// Called by readWriteLease with its lock held.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) downgrade(
	size int64,
	file *os.File) (rl ReadLease) {
	// Create the read lease.
	rlTyped := newReadLease(size, fl, file)
	rl = rlTyped

	// Update the leaser's state, noting the new read lease and that the
	// read/write lease has gone away.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	fl.readWriteBytes -= size
	fl.readOutstanding += size

	e := fl.readLeases.PushFront(rl)
	fl.readLeasesIndex[rlTyped] = e

	// Ensure that we're not now over capacity.
	fl.evict(fl.limitBytes)

	return
}

// Upgrade the supplied read lease.
//
// Called by readLease with no lock held.
//
// LOCKS_EXCLUDED(fl.mu, rl.Mu)
func (fl *fileLeaser) upgrade(rl *readLease) (rwl ReadWriteLease, err error) {
	// Grab each lock in turn.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	rl.Mu.Lock()
	defer rl.Mu.Unlock()

	// Has the lease already been revoked?
	if rl.revoked() {
		err = &RevokedError{}
		return
	}

	size := rl.Size()

	// Update leaser state.
	fl.readWriteBytes += size
	fl.readOutstanding -= size

	e := fl.readLeasesIndex[rl]
	delete(fl.readLeasesIndex, rl)
	fl.readLeases.Remove(e)

	// Extract the interesting information from the read lease, leaving it an
	// empty husk.
	file := rl.release()

	// Create the read/write lease, telling it that we already know its initial
	// size.
	rwl = newReadWriteLease(fl, size, file)

	return
}

// Promote the given read lease to most recently used, if we still know it.
// Because our lock order forbids us from acquiring the leaser lock while
// holding a read lease lock, this of course races with other promotions.
//
// Called by readLease without holding a lock.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) promoteToMostRecent(rl *readLease) {
	fl.mu.Lock()
	defer fl.mu.Unlock()

	e := fl.readLeasesIndex[rl]
	if e != nil {
		fl.readLeases.MoveToFront(e)
	}
}

// Forcibly revoke the supplied read lease.
//
// REQUIRES: !rl.revoked()
//
// LOCKS_REQUIRED(fl.mu)
// LOCKS_REQUIRED(rl.Mu)
func (fl *fileLeaser) revoke(rl *readLease) {
	if rl.revoked() {
		panic("Already revoked")
	}

	size := rl.Size()

	// Update leaser state.
	fl.readOutstanding -= size

	e := fl.readLeasesIndex[rl]
	delete(fl.readLeasesIndex, rl)
	fl.readLeases.Remove(e)

	// Kill the lease and close its file.
	file := rl.release()
	if err := file.Close(); err != nil {
		log.Println("Error closing file for revoked lease:", err)
	}
}

// Called by the read lease when the user wants to manually revoke it.
//
// LOCKS_EXCLUDED(fl.mu)
// LOCKS_EXCLUDED(rl.Mu)
func (fl *fileLeaser) revokeVoluntarily(rl *readLease) {
	// Grab each lock in turn.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	rl.Mu.Lock()
	defer rl.Mu.Unlock()

	// Has the lease already been revoked?
	if rl.revoked() {
		return
	}

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

package lease

import (
	"container/list"
	"fmt"
	"log"
	"os"

	"github.com/jacobsa/fuse/fsutil"
	"github.com/jacobsa/gcloud/syncutil"
)

// A type that manages read and read/write leases for anonymous temporary files.
//
// Safe for concurrent access.
type FileLeaser interface {
	// Create a new anonymous file, and return a read/write lease for it. The
	// read/write lease will pin resources until rwl.Downgrade is called. It need
	// not be called if the process is exiting.
	NewFile() (rwl ReadWriteLease, err error)

	// Revoke all read leases that have been issued. For testing use only.
	RevokeReadLeases()
}

// Create a new file leaser that uses the supplied directory for temporary
// files (before unlinking them) and attempts to keep usage in number of files
// and bytes below the given limits. If dir is empty, the system default will be
// used.
//
// Usage may exceed the given limits if there are read/write leases whose total
// size exceeds the limits, since such leases cannot be revoked.
func NewFileLeaser(
	dir string,
	limitNumFiles int,
	limitBytes int64) (fl FileLeaser) {
	typed := &fileLeaser{
		dir:             dir,
		limitNumFiles:   limitNumFiles,
		limitBytes:      limitBytes,
		readLeasesIndex: make(map[*readLease]*list.Element),
	}

	typed.mu = syncutil.NewInvariantMutex(typed.checkInvariants)

	fl = typed
	return
}

type fileLeaser struct {
	/////////////////////////
	// Constant data
	/////////////////////////

	dir           string
	limitNumFiles int
	limitBytes    int64

	/////////////////////////
	// Mutable state
	/////////////////////////

	// A lock that guards the mutable state in this struct. Usually this is used
	// only for light weight operations, but while evicting it may require
	// waiting on a goroutine that is holding a read lease lock while reading
	// from a file.
	//
	// Lock ordering
	// -------------
	//
	// Define < to be the minimum strict partial order satisfying:
	//
	//  1. For any read/write lease W, W < leaser.
	//  2. For any read lease R, leaser < R.
	//
	// In other words: read/write before leaser before read, and never hold two
	// locks from the same category together.
	mu syncutil.InvariantMutex

	// The number of outstanding read/write leases.
	//
	// INVARIANT: readWriteCount >= 0
	readWriteCount int

	// The current estimated total size of outstanding read/write leases. This is
	// only an estimate because we can't synchronize its update with a call to
	// the wrapped file to e.g. write or truncate.
	readWriteBytes int64

	// All outstanding read leases, ordered by recency of use.
	//
	// INVARIANT: Each element is of type *readLease
	// INVARIANT: No element has been revoked.
	// INVARIANT: 0 <= readLeases.Len() <= max(0, limitNumFiles - readWriteCount)
	readLeases list.List

	// The sum of all outstanding read lease sizes.
	//
	// INVARIANT: Equal to the sum over readLeases sizes.
	// INVARIANT: 0 <= readOutstanding
	// INVARIANT: readOutstanding <= max(0, limitBytes - readWriteBytes)
	readOutstanding int64

	// Index of read leases by pointer.
	//
	// INVARIANT: Is an index of exactly the elements of readLeases
	readLeasesIndex map[*readLease]*list.Element
}

func (fl *fileLeaser) NewFile() (rwl ReadWriteLease, err error) {
	// Create an anonymous file.
	f, err := fsutil.AnonymousFile(fl.dir)
	if err != nil {
		err = fmt.Errorf("AnonymousFile: %v", err)
		return
	}

	// Wrap a lease around it.
	rwl = newReadWriteLease(fl, 0, f)

	return
}

// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) RevokeReadLeases() {
	fl.mu.Lock()
	defer fl.mu.Unlock()

	fl.evict(0)
}

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func maxInt(a int, b int) int {
	if a > b {
		return a
	}

	return b
}

func maxInt64(a int64, b int64) int64 {
	if a > b {
		return a
	}

	return b
}

// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) checkInvariants() {
	// INVARIANT: readWriteCount >= 0
	if fl.readWriteCount < 0 {
		panic(fmt.Sprintf("Unexpected read/write count: %d", fl.readWriteCount))
	}

	// INVARIANT: Each element is of type *readLease
	// INVARIANT: No element has been revoked.
	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		rl := e.Value.(*readLease)
		func() {
			rl.Mu.Lock()
			defer rl.Mu.Unlock()

			if rl.revoked() {
				panic("Found revoked read lease")
			}
		}()
	}

	// INVARIANT: 0 <= readLeases.Len() <= max(0, limitNumFiles - readWriteCount)
	if !(0 <= fl.readLeases.Len() &&
		fl.readLeases.Len() <= maxInt(0, fl.limitNumFiles-fl.readWriteCount)) {
		panic(fmt.Sprintf(
			"Out of range read lease count: %d, limitNumFiles: %d, readWriteCount: %d",
			fl.readLeases.Len(),
			fl.limitNumFiles,
			fl.readWriteCount))
	}

	// INVARIANT: Equal to the sum over readLeases sizes.
	var sum int64
	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		rl := e.Value.(*readLease)
		sum += rl.Size()
	}

	if fl.readOutstanding != sum {
		panic(fmt.Sprintf(
			"readOutstanding mismatch: %v vs. %v",
			fl.readOutstanding,
			sum))
	}

	// INVARIANT: 0 <= readOutstanding
	if !(0 <= fl.readOutstanding) {
		panic(fmt.Sprintf("Unexpected readOutstanding: %v", fl.readOutstanding))
	}

	// INVARIANT: readOutstanding <= max(0, limitBytes - readWriteBytes)
	if !(fl.readOutstanding <= maxInt64(0, fl.limitBytes-fl.readWriteBytes)) {
		panic(fmt.Sprintf(
			"Unexpected readOutstanding: %v. limitBytes: %v, readWriteBytes: %v",
			fl.readOutstanding,
			fl.limitBytes,
			fl.readWriteBytes))
	}

	// INVARIANT: Is an index of exactly the elements of readLeases
	if len(fl.readLeasesIndex) != fl.readLeases.Len() {
		panic(fmt.Sprintf(
			"readLeasesIndex length mismatch: %v vs. %v",
			len(fl.readLeasesIndex),
			fl.readLeases.Len()))
	}

	for e := fl.readLeases.Front(); e != nil; e = e.Next() {
		if fl.readLeasesIndex[e.Value.(*readLease)] != e {
			panic("Mismatch in readLeasesIndex")
		}
	}
}

// Add the supplied delta to the leaser's view of outstanding read/write lease
// bytes, then revoke read leases until we're under limitBytes or we run out of
// leases to revoke.
//
// Called by readWriteLease while holding its lock.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) addReadWriteByteDelta(delta int64) {
	fl.readWriteCount++
	fl.readWriteBytes += delta
	fl.evict(fl.limitBytes)
}

// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) overLimit(limitBytes int64) bool {
	return fl.readOutstanding+fl.readWriteBytes > limitBytes
}

// Revoke read leases until we're within the given limitBytes or we run out of
// things to revoke.
//
// LOCKS_REQUIRED(fl.mu)
func (fl *fileLeaser) evict(limitBytes int64) {
	for fl.overLimit(limitBytes) {
		// Do we have anything to revoke?
		lru := fl.readLeases.Back()
		if lru == nil {
			return
		}

		// Revoke it.
		rl := lru.Value.(*readLease)
		func() {
			rl.Mu.Lock()
			defer rl.Mu.Unlock()

			fl.revoke(rl)
		}()
	}
}

// Note that a read/write lease of the given size is destroying itself, and
// turn it into a read lease of the supplied size wrapped around the given
// file.
//
// Called by readWriteLease with its lock held.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) downgrade(
	size int64,
	file *os.File) (rl ReadLease) {
	// Create the read lease.
	rlTyped := newReadLease(size, fl, file)
	rl = rlTyped

	// Update the leaser's state, noting the new read lease and that the
	// read/write lease has gone away.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	fl.readWriteCount--
	fl.readWriteBytes -= size
	fl.readOutstanding += size

	e := fl.readLeases.PushFront(rl)
	fl.readLeasesIndex[rlTyped] = e

	// Ensure that we're not now over capacity.
	fl.evict(fl.limitBytes)

	return
}

// Upgrade the supplied read lease.
//
// Called by readLease with no lock held.
//
// LOCKS_EXCLUDED(fl.mu, rl.Mu)
func (fl *fileLeaser) upgrade(rl *readLease) (rwl ReadWriteLease, err error) {
	// Grab each lock in turn.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	rl.Mu.Lock()
	defer rl.Mu.Unlock()

	// Has the lease already been revoked?
	if rl.revoked() {
		err = &RevokedError{}
		return
	}

	size := rl.Size()

	// Update leaser state.
	fl.readWriteBytes += size
	fl.readOutstanding -= size

	e := fl.readLeasesIndex[rl]
	delete(fl.readLeasesIndex, rl)
	fl.readLeases.Remove(e)

	// Extract the interesting information from the read lease, leaving it an
	// empty husk.
	file := rl.release()

	// Create the read/write lease, telling it that we already know its initial
	// size.
	rwl = newReadWriteLease(fl, size, file)

	return
}

// Promote the given read lease to most recently used, if we still know it.
// Because our lock order forbids us from acquiring the leaser lock while
// holding a read lease lock, this of course races with other promotions.
//
// Called by readLease without holding a lock.
//
// LOCKS_EXCLUDED(fl.mu)
func (fl *fileLeaser) promoteToMostRecent(rl *readLease) {
	fl.mu.Lock()
	defer fl.mu.Unlock()

	e := fl.readLeasesIndex[rl]
	if e != nil {
		fl.readLeases.MoveToFront(e)
	}
}

// Forcibly revoke the supplied read lease.
//
// REQUIRES: !rl.revoked()
//
// LOCKS_REQUIRED(fl.mu)
// LOCKS_REQUIRED(rl.Mu)
func (fl *fileLeaser) revoke(rl *readLease) {
	if rl.revoked() {
		panic("Already revoked")
	}

	size := rl.Size()

	// Update leaser state.
	fl.readOutstanding -= size

	e := fl.readLeasesIndex[rl]
	delete(fl.readLeasesIndex, rl)
	fl.readLeases.Remove(e)

	// Kill the lease and close its file.
	file := rl.release()
	if err := file.Close(); err != nil {
		log.Println("Error closing file for revoked lease:", err)
	}
}

// Called by the read lease when the user wants to manually revoke it.
//
// LOCKS_EXCLUDED(fl.mu)
// LOCKS_EXCLUDED(rl.Mu)
func (fl *fileLeaser) revokeVoluntarily(rl *readLease) {
	// Grab each lock in turn.
	fl.mu.Lock()
	defer fl.mu.Unlock()

	rl.Mu.Lock()
	defer rl.Mu.Unlock()

	// Has the lease already been revoked?
	if rl.revoked() {
		return
	}

	// Revoke it.
	fl.revoke(rl)
}
<|endoftext|>


<commit_before>package boil

import (
	"database/sql/driver"
	"testing"
	"time"

	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"gopkg.in/nullbio/null.v4"
)

type mockRowMaker struct {
	int
	rows []driver.Value
}

func TestBind(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		ID   int
		Name string `boil:"test"`
	}{}

	query := &Query{
		from: []string{"fun"},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id", "test"})
	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
	ret.AddRow(driver.Value(int64(12)), driver.Value("cat"))
	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].ID; id != 35 {
		t.Error("wrong ID:", id)
	}
	if name := testResults[0].Name; name != "pat" {
		t.Error("wrong name:", name)
	}

	if id := testResults[1].ID; id != 12 {
		t.Error("wrong ID:", id)
	}
	if name := testResults[1].Name; name != "cat" {
		t.Error("wrong name:", name)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBindSingular(t *testing.T) {
	t.Parallel()

	testResults := struct {
		ID   int
		Name string `boil:"test"`
	}{}

	query := &Query{
		from: []string{"fun"},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id", "test"})
	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if id := testResults.ID; id != 35 {
		t.Error("wrong ID:", id)
	}
	if name := testResults.Name; name != "pat" {
		t.Error("wrong name:", name)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBind_InnerJoin(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		Happy struct {
			ID int `boil:"identifier"`
		} `boil:",bind"`
		Fun struct {
			ID int `boil:"id"`
		} `boil:",bind"`
	}{}

	query := &Query{
		from:  []string{"fun"},
		joins: []join{{kind: JoinInner, clause: "happy as h on fun.id = h.fun_id"}},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id"})
	ret.AddRow(driver.Value(int64(10)))
	ret.AddRow(driver.Value(int64(11)))
	mock.ExpectQuery(`SELECT "fun"\.\* FROM "fun" INNER JOIN happy as h on fun.id = h.fun_id;`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].Happy.ID; id != 0 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[0].Fun.ID; id != 10 {
		t.Error("wrong ID:", id)
	}

	if id := testResults[1].Happy.ID; id != 0 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[1].Fun.ID; id != 11 {
		t.Error("wrong ID:", id)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBind_InnerJoinSelect(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		Happy struct {
			ID int
		} `boil:",bind"`
		Fun struct {
			ID int
		} `boil:",bind"`
	}{}

	query := &Query{
		selectCols: []string{"fun.id", "h.id"},
		from:       []string{"fun"},
		joins:      []join{{kind: JoinInner, clause: "happy as h on fun.happy_id = h.id"}},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"fun.id", "h.id"})
	ret.AddRow(driver.Value(int64(10)), driver.Value(int64(11)))
	ret.AddRow(driver.Value(int64(12)), driver.Value(int64(13)))
	mock.ExpectQuery(`SELECT "fun"."id" as "fun.id","h"."id" as "h.id" FROM "fun" INNER JOIN happy as h on fun.happy_id = h.id;`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].Happy.ID; id != 11 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[0].Fun.ID; id != 10 {
		t.Error("wrong ID:", id)
	}

	if id := testResults[1].Happy.ID; id != 13 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[1].Fun.ID; id != 12 {
		t.Error("wrong ID:", id)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBindPtrs_Easy(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		ID   int `boil:"identifier"`
		Date time.Time
	}{}

	cols := []string{"identifier", "date"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*time.Time) != &testStruct.Date {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_Recursive(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		Happy struct {
			ID int `boil:"identifier"`
		}
		Fun struct {
			ID int
		} `boil:",bind"`
	}{}

	cols := []string{"id", "fun.id"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_RecursiveTags(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		Happy struct {
			ID int `boil:"identifier"`
		} `boil:",bind"`
		Fun struct {
			ID int `boil:"identification"`
		} `boil:",bind"`
	}{}

	cols := []string{"happy.identifier", "fun.identification"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Happy.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_Ignore(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		ID    int `boil:"-"`
		Happy struct {
			ID int
		} `boil:",bind"`
	}{}

	cols := []string{"id"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Happy.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestGetStructValues(t *testing.T) {
	t.Parallel()
	timeThing := time.Now()
	o := struct {
		TitleThing string
		Name       string
		ID         int
		Stuff      int
		Things     int
		Time       time.Time
		NullBool   null.Bool
	}{
		TitleThing: "patrick",
		Stuff:      10,
		Things:     0,
		Time:       timeThing,
		NullBool:   null.NewBool(true, false),
	}

	vals := GetStructValues(&o, "title_thing", "name", "id", "stuff", "things", "time", "null_bool")
	if vals[0].(string) != "patrick" {
		t.Errorf("Want test, got %s", vals[0])
	}
	if vals[1].(string) != "" {
		t.Errorf("Want empty string, got %s", vals[1])
	}
	if vals[2].(int) != 0 {
		t.Errorf("Want 0, got %d", vals[2])
	}
	if vals[3].(int) != 10 {
		t.Errorf("Want 10, got %d", vals[3])
	}
	if vals[4].(int) != 0 {
		t.Errorf("Want 0, got %d", vals[4])
	}
	if !vals[5].(time.Time).Equal(timeThing) {
		t.Errorf("Want %s, got %s", o.Time, vals[5])
	}
	if !vals[6].(null.Bool).IsZero() {
		t.Errorf("Want %v, got %v", o.NullBool, vals[6])
	}
}

func TestGetStructPointers(t *testing.T) {
	t.Parallel()

	o := struct {
		Title string
		ID    *int
	}{
		Title: "patrick",
	}

	ptrs := GetStructPointers(&o, "title", "id")
	*ptrs[0].(*string) = "test"
	if o.Title != "test" {
		t.Errorf("Expected test, got %s", o.Title)
	}
	x := 5
	*ptrs[1].(**int) = &x
	if *o.ID != 5 {
		t.Errorf("Expected 5, got %d", *o.ID)
	}
}
<commit_msg>Fix failing test.<commit_after>package boil

import (
	"database/sql/driver"
	"testing"
	"time"

	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"gopkg.in/nullbio/null.v4"
)

type mockRowMaker struct {
	int
	rows []driver.Value
}

func TestBind(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		ID   int
		Name string `boil:"test"`
	}{}

	query := &Query{
		from: []string{"fun"},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id", "test"})
	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
	ret.AddRow(driver.Value(int64(12)), driver.Value("cat"))
	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].ID; id != 35 {
		t.Error("wrong ID:", id)
	}
	if name := testResults[0].Name; name != "pat" {
		t.Error("wrong name:", name)
	}

	if id := testResults[1].ID; id != 12 {
		t.Error("wrong ID:", id)
	}
	if name := testResults[1].Name; name != "cat" {
		t.Error("wrong name:", name)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBindSingular(t *testing.T) {
	t.Parallel()

	testResults := struct {
		ID   int
		Name string `boil:"test"`
	}{}

	query := &Query{
		from: []string{"fun"},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id", "test"})
	ret.AddRow(driver.Value(int64(35)), driver.Value("pat"))
	mock.ExpectQuery(`SELECT \* FROM "fun";`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if id := testResults.ID; id != 35 {
		t.Error("wrong ID:", id)
	}
	if name := testResults.Name; name != "pat" {
		t.Error("wrong name:", name)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBind_InnerJoin(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		Happy struct {
			ID int `boil:"identifier"`
		} `boil:",bind"`
		Fun struct {
			ID int `boil:"id"`
		} `boil:",bind"`
	}{}

	query := &Query{
		from:  []string{"fun"},
		joins: []join{{kind: JoinInner, clause: "happy as h on fun.id = h.fun_id"}},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"id"})
	ret.AddRow(driver.Value(int64(10)))
	ret.AddRow(driver.Value(int64(11)))
	mock.ExpectQuery(`SELECT "fun"\.\* FROM "fun" INNER JOIN happy as h on fun.id = h.fun_id;`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].Happy.ID; id != 0 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[0].Fun.ID; id != 10 {
		t.Error("wrong ID:", id)
	}

	if id := testResults[1].Happy.ID; id != 0 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[1].Fun.ID; id != 11 {
		t.Error("wrong ID:", id)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBind_InnerJoinSelect(t *testing.T) {
	t.Parallel()

	testResults := []*struct {
		Happy struct {
			ID int
		} `boil:"h,bind"`
		Fun struct {
			ID int
		} `boil:",bind"`
	}{}

	query := &Query{
		selectCols: []string{"fun.id", "h.id"},
		from:       []string{"fun"},
		joins:      []join{{kind: JoinInner, clause: "happy as h on fun.happy_id = h.id"}},
	}

	db, mock, err := sqlmock.New()
	if err != nil {
		t.Error(err)
	}

	ret := sqlmock.NewRows([]string{"fun.id", "h.id"})
	ret.AddRow(driver.Value(int64(10)), driver.Value(int64(11)))
	ret.AddRow(driver.Value(int64(12)), driver.Value(int64(13)))
	mock.ExpectQuery(`SELECT "fun"."id" as "fun.id","h"."id" as "h.id" FROM "fun" INNER JOIN happy as h on fun.happy_id = h.id;`).WillReturnRows(ret)

	SetExecutor(query, db)
	err = query.Bind(&testResults)
	if err != nil {
		t.Error(err)
	}

	if len(testResults) != 2 {
		t.Fatal("wrong number of results:", len(testResults))
	}
	if id := testResults[0].Happy.ID; id != 11 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[0].Fun.ID; id != 10 {
		t.Error("wrong ID:", id)
	}

	if id := testResults[1].Happy.ID; id != 13 {
		t.Error("wrong ID:", id)
	}
	if id := testResults[1].Fun.ID; id != 12 {
		t.Error("wrong ID:", id)
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Error(err)
	}
}

func TestBindPtrs_Easy(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		ID   int `boil:"identifier"`
		Date time.Time
	}{}

	cols := []string{"identifier", "date"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*time.Time) != &testStruct.Date {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_Recursive(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		Happy struct {
			ID int `boil:"identifier"`
		}
		Fun struct {
			ID int
		} `boil:",bind"`
	}{}

	cols := []string{"id", "fun.id"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_RecursiveTags(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		Happy struct {
			ID int `boil:"identifier"`
		} `boil:",bind"`
		Fun struct {
			ID int `boil:"identification"`
		} `boil:",bind"`
	}{}

	cols := []string{"happy.identifier", "fun.identification"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Happy.ID {
		t.Error("id is the wrong pointer")
	}
	if ptrs[1].(*int) != &testStruct.Fun.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestBindPtrs_Ignore(t *testing.T) {
	t.Parallel()

	testStruct := struct {
		ID    int `boil:"-"`
		Happy struct {
			ID int
		} `boil:",bind"`
	}{}

	cols := []string{"id"}
	ptrs, err := bindPtrs(&testStruct, cols...)
	if err != nil {
		t.Error(err)
	}

	if ptrs[0].(*int) != &testStruct.Happy.ID {
		t.Error("id is the wrong pointer")
	}
}

func TestGetStructValues(t *testing.T) {
	t.Parallel()
	timeThing := time.Now()
	o := struct {
		TitleThing string
		Name       string
		ID         int
		Stuff      int
		Things     int
		Time       time.Time
		NullBool   null.Bool
	}{
		TitleThing: "patrick",
		Stuff:      10,
		Things:     0,
		Time:       timeThing,
		NullBool:   null.NewBool(true, false),
	}

	vals := GetStructValues(&o, "title_thing", "name", "id", "stuff", "things", "time", "null_bool")
	if vals[0].(string) != "patrick" {
		t.Errorf("Want test, got %s", vals[0])
	}
	if vals[1].(string) != "" {
		t.Errorf("Want empty string, got %s", vals[1])
	}
	if vals[2].(int) != 0 {
		t.Errorf("Want 0, got %d", vals[2])
	}
	if vals[3].(int) != 10 {
		t.Errorf("Want 10, got %d", vals[3])
	}
	if vals[4].(int) != 0 {
		t.Errorf("Want 0, got %d", vals[4])
	}
	if !vals[5].(time.Time).Equal(timeThing) {
		t.Errorf("Want %s, got %s", o.Time, vals[5])
	}
	if !vals[6].(null.Bool).IsZero() {
		t.Errorf("Want %v, got %v", o.NullBool, vals[6])
	}
}

func TestGetStructPointers(t *testing.T) {
	t.Parallel()

	o := struct {
		Title string
		ID    *int
	}{
		Title: "patrick",
	}

	ptrs := GetStructPointers(&o, "title", "id")
	*ptrs[0].(*string) = "test"
	if o.Title != "test" {
		t.Errorf("Expected test, got %s", o.Title)
	}
	x := 5
	*ptrs[1].(**int) = &x
	if *o.ID != 5 {
		t.Errorf("Expected 5, got %d", *o.ID)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"os"
	"strings"

	maddr "github.com/multiformats/go-multiaddr"
)

var (
	flagHelp bool
)

func main() {
	flag.Usage = func() {
		usage := `usage: %s [options] ADDR

Print details about the given multiaddr.

Options:
`
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	flag.BoolVar(&flagHelp, "h", false, "display help message")
	flag.Parse()

	if flagHelp || len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(0)
	}

	addrStr := flag.Args()[0]
	var addr maddr.Multiaddr
	var err error
	if strings.HasPrefix(addrStr, "0x") {
		addrBytes, err := hex.DecodeString(addrStr[2:])
		if err != nil {
			fmt.Fprintf(os.Stderr, "parse error: %s\n", err)
			os.Exit(1)
		}
		addr, err = maddr.NewMultiaddrBytes(addrBytes)
	} else {
		addr, err = maddr.NewMultiaddr(addrStr)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "parse error: %s\n", err)
		os.Exit(1)
	}

	infoCommand(addr)
}

func infoCommand(addr maddr.Multiaddr) {
	var compsJson []string
	maddr.ForEach(addr, func(comp maddr.Component) bool {
		lengthPrefix := ""
		if comp.Protocol().Size == maddr.LengthPrefixedVarSize {
			lengthPrefix = "0x" + hex.EncodeToString(maddr.CodeToVarint(len(comp.RawValue())))
		}

		compsJson = append(compsJson, `{`+
			fmt.Sprintf(`"string": "%s", `, comp.String())+
			fmt.Sprintf(`"stringSize": "%d", `, len(comp.String()))+
			fmt.Sprintf(`"packed": "0x%x", `, comp.Bytes())+
			fmt.Sprintf(`"packedSize": "%d", `, len(comp.Bytes()))+
			fmt.Sprintf(`"value": %#v, `, comp.Value())+
			fmt.Sprintf(`"rawValue": "0x%x", `, comp.RawValue())+
			fmt.Sprintf(`"valueSize": "%d", `, len(comp.RawValue()))+
			fmt.Sprintf(`"protocol": "%s", `, comp.Protocol().Name)+
			fmt.Sprintf(`"codec": "%d", `, comp.Protocol().Code)+
			fmt.Sprintf(`"uvarint": "0x%x", `, comp.Protocol().VCode)+
			fmt.Sprintf(`"lengthPrefix": "%s"`, lengthPrefix)+
			`}`)
		return true
	})

	addrJson := `{
  "string": "%[1]s",
  "stringSize": "%[2]d",
  "packed": "0x%[3]x",
  "packedSize": "%[4]d",
  "components": [
    %[5]s
  ]
}`
	fmt.Fprintf(os.Stdout, addrJson+"\n",
		addr.String(), len(addr.String()), addr.Bytes(), len(addr.Bytes()), strings.Join(compsJson, ",\n    "))
}
<commit_msg>fix ineffectual assignment of error<commit_after>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"os"
	"strings"

	maddr "github.com/multiformats/go-multiaddr"
)

var (
	flagHelp bool
)

func main() {
	flag.Usage = func() {
		usage := `usage: %s [options] ADDR

Print details about the given multiaddr.

Options:
`
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	flag.BoolVar(&flagHelp, "h", false, "display help message")
	flag.Parse()

	if flagHelp || len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(0)
	}

	addrStr := flag.Args()[0]
	var addr maddr.Multiaddr
	var merr error
	if strings.HasPrefix(addrStr, "0x") {
		addrBytes, err := hex.DecodeString(addrStr[2:])
		if err != nil {
			fmt.Fprintf(os.Stderr, "parse error: %s\n", err)
			os.Exit(1)
		}
		addr, merr = maddr.NewMultiaddrBytes(addrBytes)
	} else {
		addr, merr = maddr.NewMultiaddr(addrStr)
	}
	if merr != nil {
		fmt.Fprintf(os.Stderr, "parse error: %s\n", merr)
		os.Exit(1)
	}

	infoCommand(addr)
}

func infoCommand(addr maddr.Multiaddr) {
	var compsJson []string
	maddr.ForEach(addr, func(comp maddr.Component) bool {
		lengthPrefix := ""
		if comp.Protocol().Size == maddr.LengthPrefixedVarSize {
			lengthPrefix = "0x" + hex.EncodeToString(maddr.CodeToVarint(len(comp.RawValue())))
		}

		compsJson = append(compsJson, `{`+
			fmt.Sprintf(`"string": "%s", `, comp.String())+
			fmt.Sprintf(`"stringSize": "%d", `, len(comp.String()))+
			fmt.Sprintf(`"packed": "0x%x", `, comp.Bytes())+
			fmt.Sprintf(`"packedSize": "%d", `, len(comp.Bytes()))+
			fmt.Sprintf(`"value": %#v, `, comp.Value())+
			fmt.Sprintf(`"rawValue": "0x%x", `, comp.RawValue())+
			fmt.Sprintf(`"valueSize": "%d", `, len(comp.RawValue()))+
			fmt.Sprintf(`"protocol": "%s", `, comp.Protocol().Name)+
			fmt.Sprintf(`"codec": "%d", `, comp.Protocol().Code)+
			fmt.Sprintf(`"uvarint": "0x%x", `, comp.Protocol().VCode)+
			fmt.Sprintf(`"lengthPrefix": "%s"`, lengthPrefix)+
			`}`)
		return true
	})

	addrJson := `{
  "string": "%[1]s",
  "stringSize": "%[2]d",
  "packed": "0x%[3]x",
  "packedSize": "%[4]d",
  "components": [
    %[5]s
  ]
}`
	fmt.Fprintf(os.Stdout, addrJson+"\n",
		addr.String(), len(addr.String()), addr.Bytes(), len(addr.Bytes()), strings.Join(compsJson, ",\n    "))
}
<|endoftext|>


<commit_before>package caspercloud

import (
	"bufio"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"time"
)

type CasperCmd struct {
	proxyServer   string
	id            string
	tmpl          string
	userName      string
	passWord      string
	message       chan *Output
	input         chan map[string]string
	isKill        bool
	isFinish      bool
	args          map[string]string
	privateKey    *rsa.PrivateKey
	mailProcessor *MailProcessor
}

type CasperCmdFactory struct{}

func (s *CasperCmdFactory) CreateCommand(params url.Values) Command {
	tmpl := params.Get("tmpl")
	ret := &CasperCmd{
		proxyServer:   "",
		id:            fmt.Sprintf("%s_%d", tmpl, time.Now().UnixNano()),
		tmpl:          tmpl,
		userName:      "",
		passWord:      "",
		message:       make(chan *Output, 5),
		input:         make(chan map[string]string, 5),
		args:          make(map[string]string),
		isKill:        false,
		isFinish:      false,
		mailProcessor: NewMailProcessor("server_list.json"),
	}
	var err error
	ret.privateKey, err = GenerateRSAKey()
	if err != nil {
		log.Fatalln("fail to generate rsa key", err)
	}
	go ret.run()
	return ret
}

func (s *CasperCmdFactory) CreateCommandWithPrivateKey(params url.Values, pk *rsa.PrivateKey) Command {
	tmpl := params.Get("tmpl")
	ret := &CasperCmd{
		proxyServer:   "",
		id:            fmt.Sprintf("%s_%d", tmpl, time.Now().UnixNano()),
		tmpl:          tmpl,
		userName:      "",
		passWord:      "",
		message:       make(chan *Output, 5),
		input:         make(chan map[string]string, 5),
		args:          make(map[string]string),
		isKill:        false,
		isFinish:      false,
		mailProcessor: NewMailProcessor("server_list.json"),
		privateKey:    pk,
	}
	go ret.run()
	return ret
}

func (self *CasperCmd) GetId() string {
	return self.id
}

func (self *CasperCmd) SetInputArgs(input map[string]string) {
	if self.Finished() {
		log.Println("start another casperjs")
		go self.run()
	}
	log.Println("insert input:", input)
	self.input <- input
}

func (self *CasperCmd) GetMessage() *Output {
	return <-self.message
}

func (self *CasperCmd) readInputArgs(key string) string {
	args := <-self.input
	for k, v := range args {
		if k == "username" {
			self.userName = v
		}

		if k == "password" {
			self.passWord = v
		}

		self.args[k] = v
	}
	if val, ok := self.args[key]; ok {
		log.Println("find param", key, val)
		return val
	}

	message := &Output{
		Id:        self.GetArgsValue("id"),
		NeedParam: key,
		Status:    NEED_PARAM,
	}
	log.Println("need param", key)
	self.message <- message
	return ""
}

func (self *CasperCmd) GetArgsValue(key string) string {
	if val, ok := self.args[key]; ok {
		log.Println("successfully get args value", val)
		return val
	}
	for {
		val := self.readInputArgs(key)
		if len(val) != 0 {
			log.Println("successfully get args value", val)
			return val
		}
	}

}

func (self *CasperCmd) getArgsList(args string) []string {
	segs := strings.Split(args, "/")
	if len(segs) < 2 {
		return nil
	}
	return segs[1:]
}

func (self *CasperCmd) getMetaInfo() *ParseRequest {
	ret := &ParseRequest{}
	ret.PrivateKey = string(PrivateKeyString(self.privateKey))
	ret.PublicKey = string(PublicKeyString(&self.privateKey.PublicKey))
	ret.Tmpl = self.tmpl
	ret.UserName = self.userName
	ret.Secret = self.passWord
	ret.RowKey = self.tmpl + "|" + self.userName
	return ret
}

func (self *CasperCmd) Successed() bool {
	return true
}

func (self *CasperCmd) Finished() bool {
	return self.isKill || self.isFinish
}

func DecodePassword(p string, privateKey *rsa.PrivateKey) string {
	bp, err := hex.DecodeString(p)
	if err != nil {
		log.Println("decode password hex error:", err)
		return ""
	}
	out, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey,
		bp, []byte(""))
	if err != nil {
		log.Println("decode password error:", err)
		return ""
	}
	log.Println("decode password:", string(out))
	return string(out)
}

func (self *CasperCmd) run() {
	log.Println("begin run cmd", self.tmpl)
	self.isFinish = false
	self.isKill = false

	path := "./" + self.tmpl + "/" + self.id
	os.RemoveAll(path)
	if err := os.MkdirAll(path, 0755); err != nil {
		log.Fatalln("can not create", path, err)
	}

	cookieFile, err := os.Create(path + "/cookie.txt")
	defer cookieFile.Close()
	var cmd *exec.Cmd
	if len(self.proxyServer) == 0 {
		cmd = exec.Command("casperjs", self.tmpl+".js",
			"--web-security=no",
			"--cookies-file="+path+"/cookie.txt",
			"--context="+path)
	} else {
		cmd = exec.Command("casperjs", self.tmpl+".js",
			"--web-security=no",
			"--cookies-file="+path+"/cookie.txt",
			"--proxy="+self.proxyServer, "--proxy-type=http",
			"--context="+path)
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Panicln("can not get stdout pipe:", err)
	}
	bufout := bufio.NewReader(stdout)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Panicln("can not get stdin pipe:", err)
	}
	bufin := bufio.NewWriter(stdin)

	if err := cmd.Start(); err != nil {
		log.Panicln("can not start cmd:", err)
	}

	go func() {
		timer := time.NewTimer(5 * time.Minute)
		<-timer.C
		cmd.Process.Kill()
		self.isKill = true
	}()

	log.Println("begin read line from capser")
	for {
		line, err := bufout.ReadString('\n')
		line = strings.Trim(line, "\n")
		if err != nil {
			log.Println(err)
			cmd.Process.Wait()
			cmd.Process.Kill()
			break
		}
		log.Println(line)

		if strings.HasPrefix(line, "CMD INFO STARTED") {
			message := &Output{
				Id:     self.GetArgsValue("id"),
				Status: OUTPUT_PUBLICKEY,
				Data:   string(PublicKeyString(&self.privateKey.PublicKey)),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD GET ARGS") {
			for _, v := range self.getArgsList(line) {
				key := strings.TrimRight(v, "\n")
				val := self.GetArgsValue(key)
				if key == "password" {
					val = DecodePassword(val, self.privateKey)
				}
				bufin.WriteString(val)
				delete(self.args, key)
				bufin.WriteRune('\n')
				bufin.Flush()
			}
			continue
		}

		if strings.HasPrefix(line, "CMD INFO LOGIN SUCCESS") {
			message := &Output{
				Id:     self.GetArgsValue("id"),
				Status: LOGIN_SUCCESS,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD NEED") {
			result := strings.TrimPrefix(line, "CMD NEED")
			result = strings.TrimSpace(result)
			message := &Output{
				Id:        self.GetArgsValue("id"),
				Status:    NEED_PARAM,
				NeedParam: result,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO RANDCODE") {
			result := strings.TrimPrefix(line, "CMD INFO RANDCODE")
			result = strings.Trim(result, " \n")
			result = UploadImage("./site/" + result)
			log.Println("success upload captcha image to", result)
			message := &Output{
				Id:        self.GetArgsValue("id"),
				Status:    OUTPUT_VERIFYCODE,
				Data:      result,
				NeedParam: PARAM_VERIFY_CODE,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO CONTENT") {
			message := &Output{
				Status: strings.TrimSpace(strings.TrimPrefix(line,
					"CMD INFO CONTENT")),
				Id: self.GetArgsValue("id"),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO FETCHED MAIL") {
			result := strings.TrimSpace(strings.TrimPrefix(line,
				"CMD INFO FETCHED MAIL"))
			var out CasperOutput
			json.Unmarshal([]byte(result), &out)
			if self.mailProcessor != nil {
				go self.mailProcessor.Process(self.getMetaInfo(), out.Downloads)
			}
			message := &Output{
				Status: FINISH_FETCH_DATA,
				Id:     self.GetArgsValue("id"),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD FAIL") {
			message := &Output{
				Status: FAIL,
				Id:     self.GetArgsValue("id"),
			}
			self.message <- message
			cmd.Process.Wait()
			cmd.Process.Kill()
			break
		}
	}
	self.isFinish = true
}
<commit_msg>ignore for ssl errors<commit_after>package caspercloud

import (
	"bufio"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"time"
)

type CasperCmd struct {
	proxyServer   string
	id            string
	tmpl          string
	userName      string
	passWord      string
	message       chan *Output
	input         chan map[string]string
	isKill        bool
	isFinish      bool
	args          map[string]string
	privateKey    *rsa.PrivateKey
	mailProcessor *MailProcessor
}

type CasperCmdFactory struct{}

func (s *CasperCmdFactory) CreateCommand(params url.Values) Command {
	tmpl := params.Get("tmpl")
	ret := &CasperCmd{
		proxyServer:   "",
		id:            fmt.Sprintf("%s_%d", tmpl, time.Now().UnixNano()),
		tmpl:          tmpl,
		userName:      "",
		passWord:      "",
		message:       make(chan *Output, 5),
		input:         make(chan map[string]string, 5),
		args:          make(map[string]string),
		isKill:        false,
		isFinish:      false,
		mailProcessor: NewMailProcessor("server_list.json"),
	}
	var err error
	ret.privateKey, err = GenerateRSAKey()
	if err != nil {
		log.Fatalln("fail to generate rsa key", err)
	}
	go ret.run()
	return ret
}

func (s *CasperCmdFactory) CreateCommandWithPrivateKey(params url.Values, pk *rsa.PrivateKey) Command {
	tmpl := params.Get("tmpl")
	ret := &CasperCmd{
		proxyServer:   "",
		id:            fmt.Sprintf("%s_%d", tmpl, time.Now().UnixNano()),
		tmpl:          tmpl,
		userName:      "",
		passWord:      "",
		message:       make(chan *Output, 5),
		input:         make(chan map[string]string, 5),
		args:          make(map[string]string),
		isKill:        false,
		isFinish:      false,
		mailProcessor: NewMailProcessor("server_list.json"),
		privateKey:    pk,
	}
	go ret.run()
	return ret
}

func (self *CasperCmd) GetId() string {
	return self.id
}

func (self *CasperCmd) SetInputArgs(input map[string]string) {
	if self.Finished() {
		log.Println("start another casperjs")
		go self.run()
	}
	log.Println("insert input:", input)
	self.input <- input
}

func (self *CasperCmd) GetMessage() *Output {
	return <-self.message
}

func (self *CasperCmd) readInputArgs(key string) string {
	args := <-self.input
	for k, v := range args {
		if k == "username" {
			self.userName = v
		}

		if k == "password" {
			self.passWord = v
		}

		self.args[k] = v
	}
	if val, ok := self.args[key]; ok {
		log.Println("find param", key, val)
		return val
	}

	message := &Output{
		Id:        self.GetArgsValue("id"),
		NeedParam: key,
		Status:    NEED_PARAM,
	}
	log.Println("need param", key)
	self.message <- message
	return ""
}

func (self *CasperCmd) GetArgsValue(key string) string {
	if val, ok := self.args[key]; ok {
		log.Println("successfully get args value", val)
		return val
	}
	for {
		val := self.readInputArgs(key)
		if len(val) != 0 {
			log.Println("successfully get args value", val)
			return val
		}
	}

}

func (self *CasperCmd) getArgsList(args string) []string {
	segs := strings.Split(args, "/")
	if len(segs) < 2 {
		return nil
	}
	return segs[1:]
}

func (self *CasperCmd) getMetaInfo() *ParseRequest {
	ret := &ParseRequest{}
	ret.PrivateKey = string(PrivateKeyString(self.privateKey))
	ret.PublicKey = string(PublicKeyString(&self.privateKey.PublicKey))
	ret.Tmpl = self.tmpl
	ret.UserName = self.userName
	ret.Secret = self.passWord
	ret.RowKey = self.tmpl + "|" + self.userName
	return ret
}

func (self *CasperCmd) Successed() bool {
	return true
}

func (self *CasperCmd) Finished() bool {
	return self.isKill || self.isFinish
}

func DecodePassword(p string, privateKey *rsa.PrivateKey) string {
	bp, err := hex.DecodeString(p)
	if err != nil {
		log.Println("decode password hex error:", err)
		return ""
	}
	out, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey,
		bp, []byte(""))
	if err != nil {
		log.Println("decode password error:", err)
		return ""
	}
	log.Println("decode password:", string(out))
	return string(out)
}

func (self *CasperCmd) run() {
	log.Println("begin run cmd", self.tmpl)
	self.isFinish = false
	self.isKill = false

	path := "./" + self.tmpl + "/" + self.id
	os.RemoveAll(path)
	if err := os.MkdirAll(path, 0755); err != nil {
		log.Fatalln("can not create", path, err)
	}

	cookieFile, err := os.Create(path + "/cookie.txt")
	defer cookieFile.Close()
	var cmd *exec.Cmd
	if len(self.proxyServer) == 0 {
		cmd = exec.Command("casperjs", self.tmpl+".js",
			"--ignore-ssl-errors=true",
			"--web-security=no",
			"--cookies-file="+path+"/cookie.txt",
			"--context="+path)
	} else {
		cmd = exec.Command("casperjs", self.tmpl+".js",
			"--ignore-ssl-errors=true",
			"--web-security=no",
			"--cookies-file="+path+"/cookie.txt",
			"--proxy="+self.proxyServer, "--proxy-type=http",
			"--context="+path)
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Panicln("can not get stdout pipe:", err)
	}
	bufout := bufio.NewReader(stdout)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Panicln("can not get stdin pipe:", err)
	}
	bufin := bufio.NewWriter(stdin)

	if err := cmd.Start(); err != nil {
		log.Panicln("can not start cmd:", err)
	}

	go func() {
		timer := time.NewTimer(5 * time.Minute)
		<-timer.C
		cmd.Process.Kill()
		self.isKill = true
	}()

	log.Println("begin read line from capser")
	for {
		line, err := bufout.ReadString('\n')
		line = strings.Trim(line, "\n")
		if err != nil {
			log.Println(err)
			cmd.Process.Wait()
			cmd.Process.Kill()
			break
		}
		log.Println(line)

		if strings.HasPrefix(line, "CMD INFO STARTED") {
			message := &Output{
				Id:     self.GetArgsValue("id"),
				Status: OUTPUT_PUBLICKEY,
				Data:   string(PublicKeyString(&self.privateKey.PublicKey)),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD GET ARGS") {
			for _, v := range self.getArgsList(line) {
				key := strings.TrimRight(v, "\n")
				val := self.GetArgsValue(key)
				if key == "password" {
					val = DecodePassword(val, self.privateKey)
				}
				bufin.WriteString(val)
				delete(self.args, key)
				bufin.WriteRune('\n')
				bufin.Flush()
			}
			continue
		}

		if strings.HasPrefix(line, "CMD INFO LOGIN SUCCESS") {
			message := &Output{
				Id:     self.GetArgsValue("id"),
				Status: LOGIN_SUCCESS,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD NEED") {
			result := strings.TrimPrefix(line, "CMD NEED")
			result = strings.TrimSpace(result)
			message := &Output{
				Id:        self.GetArgsValue("id"),
				Status:    NEED_PARAM,
				NeedParam: result,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO RANDCODE") {
			result := strings.TrimPrefix(line, "CMD INFO RANDCODE")
			result = strings.Trim(result, " \n")
			result = UploadImage("./site/" + result)
			log.Println("success upload captcha image to", result)
			message := &Output{
				Id:        self.GetArgsValue("id"),
				Status:    OUTPUT_VERIFYCODE,
				Data:      result,
				NeedParam: PARAM_VERIFY_CODE,
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO CONTENT") {
			message := &Output{
				Status: strings.TrimSpace(strings.TrimPrefix(line,
					"CMD INFO CONTENT")),
				Id: self.GetArgsValue("id"),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD INFO FETCHED MAIL") {
			result := strings.TrimSpace(strings.TrimPrefix(line,
				"CMD INFO FETCHED MAIL"))
			var out CasperOutput
			json.Unmarshal([]byte(result), &out)
			if self.mailProcessor != nil {
				go self.mailProcessor.Process(self.getMetaInfo(), out.Downloads)
			}
			message := &Output{
				Status: FINISH_FETCH_DATA,
				Id:     self.GetArgsValue("id"),
			}
			self.message <- message
			continue
		}

		if strings.HasPrefix(line, "CMD FAIL") {
			message := &Output{
				Status: FAIL,
				Id:     self.GetArgsValue("id"),
			}
			self.message <- message
			cmd.Process.Wait()
			cmd.Process.Kill()
			break
		}
	}
	self.isFinish = true
}
<|endoftext|>


<commit_before>package dht

import (
	"net"
	"testing"
)

func TestReceive(t *testing.T) {
	id1, err := GenerateIdentity()
	if err != nil {
		t.Fatal(err)
		return
	}
	transport1, err := NewLocalTransport(id1)
	if err != nil {
		t.Fatal(err)
		return
	}
	id2, err := GenerateIdentity()
	if err != nil {
		t.Fatal(err)
		return
	}
	transport2, err := NewLocalTransport(id2)
	if err != nil {
		t.Fatal(err)
		return
	}

	// used to wait for the test to finish
	ch := make(chan struct{})

	// register the receiver before we send
	transport1.RegisterReceiver(func(pp *PlainPacket, addr *net.UDPAddr) bool {
		switch payload := pp.Payload.(type) {
		case *PingPong:
			if payload.IsPing != true {
				t.Fatalf("Was not ping: %b", payload.IsPing)
			}
			if payload.RequestID != 3 {
				t.Fatalf("Wrong pingID: %d", payload.RequestID)
			}
		default:
			t.Fatalf("Internal error. Failed to handle payload of parsed packet. %d\n", pp.Payload.Kind())
		}
		close(ch)
		return true
	})

	// pipe the output of transport2 into the input of transport1
	transport2.ChOut = transport1.ChIn
	transport2.Send(&PingPong{IsPing: true, RequestID: 3}, &DHTPeer{PublicKey: id1.PublicKey})

	// process the message
	transport1.Listen()

	<-ch
}
<commit_msg>fix tests<commit_after>package dht

import (
	"net"
	"testing"
)

func TestReceive(t *testing.T) {
	id1, err := GenerateIdentity()
	if err != nil {
		t.Fatal(err)
		return
	}
	transport1, err := NewLocalTransport(id1)
	if err != nil {
		t.Fatal(err)
		return
	}
	id2, err := GenerateIdentity()
	if err != nil {
		t.Fatal(err)
		return
	}
	transport2, err := NewLocalTransport(id2)
	if err != nil {
		t.Fatal(err)
		return
	}

	// used to wait for the test to finish
	ch := make(chan struct{})

	// register the receiver before we send
	transport1.RegisterReceiver(func(pp *PlainPacket, addr *net.UDPAddr) bool {
		switch payload := pp.Payload.(type) {
		case *PingPong:
			if payload.IsPing != true {
				t.Fatalf("Was not ping: %b", payload.IsPing)
			}
			if payload.RequestID != 3 {
				t.Fatalf("Wrong pingID: %d", payload.RequestID)
			}
		default:
			t.Fatalf("Internal error. Failed to handle payload of parsed packet. %d\n", pp.Payload.Kind())
		}
		close(ch)
		return true
	})

	// pipe the output of transport2 into the input of transport1
	transport2.ChOut = transport1.ChIn
	transport2.Send(&PingPong{IsPing: true, RequestID: 3}, &DHTPeer{PublicKey: id1.PublicKey})

	// process the message
	transport1.Listen(nil)

	<-ch
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
)

func jump_forward(source []uint8, start int, source_length int) int {
	var count = 1
	for tip := start; tip < source_length; tip++ {
		if source[tip] == '[' {
			count += 1
		} else if source[tip] == ']' {
			count -= 1
		}
		if count == 0 {
			return tip + 1
		}
	}
	return -1
}

func jump_backward(source []uint8, start int) int {
	var count = 1
	for tip := start; tip > 0; tip-- {
		if source[tip] == ']' {
			count += 1
		} else if source[tip] == '[' {
			count -= 1
		}
		if count == 0 {
			return tip + 1
		}
	}
	return -1
}

func main() {
	pathPtr := flag.String("path", "", "path to Brainfuck source")
	sizePtr := flag.Int("size", 30000, "size of the data array")

	flag.Parse()

	path := *pathPtr
	if path == "" {
		fmt.Println("You must specify a path to Brainfuck source: -path=...")
		os.Exit(1)
	}

	source, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}

	var data = make([]int, *sizePtr)
	var source_length = len(source)
	var dp = 0
	for ip := 0; ip < source_length; {
		var c = source[ip]
		switch {
		case c == '>':
			dp += 1
			ip += 1
		case c == '<':
			dp -= 1
			ip += 1
		case c == '+':
			data[dp] += 1
			ip += 1
		case c == '-':
			data[dp] -= 1
			ip += 1
		case c == '.':
			fmt.Printf("%c", data[dp])
			ip += 1
		case c == ',':
			fmt.Scanf("%c", &data[dp])
			ip += 1
		case c == '[':
			if data[dp] == 0 {
				ip = jump_forward(source, ip+1, source_length)
			} else {
				ip += 1
			}
		case c == ']':
			if data[dp] != 0 {
				ip = jump_backward(source, ip-1)
			} else {
				ip += 1
			}
		default:
			ip += 1
		}
		// execution ends as expected when ip == source_length
		if ip < 0 || ip > source_length {
			panic(fmt.Sprintf("Aborting execution as instruction pointer is invalid: %d.", ip))
		}
		if dp < 0 || dp >= *sizePtr {
			panic(fmt.Sprintf("Aborting execution as data pointer is invalid: %d.", dp))
		}
	}
}
<commit_msg>Fixed issue in case we need to jump back to first instruction after '[' at first position in source<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
)

func jump_forward(source []uint8, start int, source_length int) int {
	var count = 1
	for tip := start; tip < source_length; tip++ {
		if source[tip] == '[' {
			count += 1
		} else if source[tip] == ']' {
			count -= 1
		}
		if count == 0 {
			return tip + 1
		}
	}
	return -1
}

func jump_backward(source []uint8, start int) int {
	var count = 1
	for tip := start; tip >= 0; tip-- {
		if source[tip] == ']' {
			count += 1
		} else if source[tip] == '[' {
			count -= 1
		}
		if count == 0 {
			return tip + 1
		}
	}
	return -1
}

func main() {
	pathPtr := flag.String("path", "", "path to Brainfuck source")
	sizePtr := flag.Int("size", 30000, "size of the data array")

	flag.Parse()

	path := *pathPtr
	if path == "" {
		fmt.Println("You must specify a path to Brainfuck source: -path=...")
		os.Exit(1)
	}

	source, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}

	var data = make([]int, *sizePtr)
	var source_length = len(source)
	var dp = 0
	for ip := 0; ip < source_length; {
		var c = source[ip]
		switch {
		case c == '>':
			dp += 1
			ip += 1
		case c == '<':
			dp -= 1
			ip += 1
		case c == '+':
			data[dp] += 1
			ip += 1
		case c == '-':
			data[dp] -= 1
			ip += 1
		case c == '.':
			fmt.Printf("%c", data[dp])
			ip += 1
		case c == ',':
			fmt.Scanf("%c", &data[dp])
			ip += 1
		case c == '[':
			if data[dp] == 0 {
				ip = jump_forward(source, ip+1, source_length)
			} else {
				ip += 1
			}
		case c == ']':
			if data[dp] != 0 {
				ip = jump_backward(source, ip-1)
			} else {
				ip += 1
			}
		default:
			ip += 1
		}
		// execution ends as expected when ip == source_length
		if ip < 0 || ip > source_length {
			panic(fmt.Sprintf("Aborting execution as instruction pointer is invalid: %d.", ip))
		}
		if dp < 0 || dp >= *sizePtr {
			panic(fmt.Sprintf("Aborting execution as data pointer is invalid: %d.", dp))
		}
	}
}
<|endoftext|>


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

/*
 * Cephes Math Library Release 2.4:  March,1996
 * Copyright 1984, 1996 by Stephen L. Moshier
 */

package cephes

import "math"

// Incbi computes the inverse of the regularized incomplete beta integral.
func Incbi(aa, bb, yy0 float64) float64 {
	var a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh, xt float64
	var i, rflg, dir, nflg int

	i = 0
	if yy0 <= 0 {
		return (0.0)
	}
	if yy0 >= 1.0 {
		return (1.0)
	}
	x0 = 0.0
	yl = 0.0
	x1 = 1.0
	yh = 1.0
	nflg = 0

	if aa <= 1.0 || bb <= 1.0 {
		dithresh = 1.0e-6
		rflg = 0
		a = aa
		b = bb
		y0 = yy0
		x = a / (a + b)
		y = Incbet(a, b, x)
		goto ihalve
	} else {
		dithresh = 1.0e-4
	}
	// Approximation to inverse function
	yp = -Ndtri(yy0)

	if yy0 > 0.5 {
		rflg = 1
		a = bb
		b = aa
		y0 = 1.0 - yy0
		yp = -yp
	} else {
		rflg = 0
		a = aa
		b = bb
		y0 = yy0
	}

	lgm = (yp*yp - 3.0) / 6.0
	x = 2.0 / (1.0/(2.0*a-1.0) + 1.0/(2.0*b-1.0))
	d = yp*math.Sqrt(x+lgm)/x - (1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(lgm+5.0/6.0-2.0/(3.0*x))
	d = 2.0 * d
	if d < minLog {
		// mtherr("incbi", UNDERFLOW)
		x = 0
		goto done
	}
	x = a / (a + b*math.Exp(d))
	y = Incbet(a, b, x)
	yp = (y - y0) / y0
	if math.Abs(yp) < 0.2 {
		goto newt
	}

	/* Resort to interval halving if not close enough. */
ihalve:

	dir = 0
	di = 0.5
	for i = 0; i < 100; i++ {
		if i != 0 {
			x = x0 + di*(x1-x0)
			if x == 1.0 {
				x = 1.0 - machEp
			}
			if x == 0.0 {
				di = 0.5
				x = x0 + di*(x1-x0)
				if x == 0.0 {
					// mtherr("incbi", UNDERFLOW)
					goto done
				}
			}
			y = Incbet(a, b, x)
			yp = (x1 - x0) / (x1 + x0)
			if math.Abs(yp) < dithresh {
				goto newt
			}
			yp = (y - y0) / y0
			if math.Abs(yp) < dithresh {
				goto newt
			}
		}
		if y < y0 {
			x0 = x
			yl = y
			if dir < 0 {
				dir = 0
				di = 0.5
			} else if dir > 3 {
				di = 1.0 - (1.0-di)*(1.0-di)
			} else if dir > 1 {
				di = 0.5*di + 0.5
			} else {
				di = (y0 - y) / (yh - yl)
			}
			dir += 1
			if x0 > 0.75 {
				if rflg == 1 {
					rflg = 0
					a = aa
					b = bb
					y0 = yy0
				} else {
					rflg = 1
					a = bb
					b = aa
					y0 = 1.0 - yy0
				}
				x = 1.0 - x
				y = Incbet(a, b, x)
				x0 = 0.0
				yl = 0.0
				x1 = 1.0
				yh = 1.0
				goto ihalve
			}
		} else {
			x1 = x
			if rflg == 1 && x1 < machEp {
				x = 0.0
				goto done
			}
			yh = y
			if dir > 0 {
				dir = 0
				di = 0.5
			} else if dir < -3 {
				di = di * di
			} else if dir < -1 {
				di = 0.5 * di
			} else {
				di = (y - y0) / (yh - yl)
			}
			dir -= 1
		}
	}
	// mtherr("incbi", PLOSS)
	if x0 >= 1.0 {
		x = 1.0 - machEp
		goto done
	}
	if x <= 0.0 {
		// mtherr("incbi", UNDERFLOW)
		x = 0.0
		goto done
	}

newt:
	if nflg > 0 {
		goto done
	}
	nflg = 1
	lgm = lgam(a+b) - lgam(a) - lgam(b)

	for i = 0; i < 8; i++ {
		/* Compute the function at this point. */
		if i != 0 {
			y = Incbet(a, b, x)
		}
		if y < yl {
			x = x0
			y = yl
		} else if y > yh {
			x = x1
			y = yh
		} else if y < y0 {
			x0 = x
			yl = y
		} else {
			x1 = x
			yh = y
		}
		if x == 1.0 || x == 0.0 {
			break
		}
		/* Compute the derivative of the function at this point. */
		d = (a-1.0)*math.Log(x) + (b-1.0)*math.Log(1.0-x) + lgm
		if d < minLog {
			goto done
		}
		if d > maxLog {
			break
		}
		d = math.Exp(d)
		/* Compute the step to the next approximation of x. */
		d = (y - y0) / d
		xt = x - d
		if xt <= x0 {
			y = (x - x0) / (x1 - x0)
			xt = x0 + 0.5*y*(x-x0)
			if xt <= 0.0 {
				break
			}
		}
		if xt >= x1 {
			y = (x1 - x) / (x1 - x0)
			xt = x1 - 0.5*y*(x1-x)
			if xt >= 1.0 {
				break
			}
		}
		x = xt
		if math.Abs(d/x) < 128.0*machEp {
			goto done
		}
	}
	/* Did not converge.  */
	dithresh = 256.0 * machEp
	goto ihalve

done:

	if rflg > 0 {
		if x <= machEp {
			x = 1.0 - machEp
		} else {
			x = 1.0 - x
		}
	}
	return (x)
}

func lgam(a float64) float64 {
	lg, _ := math.Lgamma(a)
	return lg
}
<commit_msg>mathext/internal/cephes: remove redundant zero assignment<commit_after>// Copyright ©2016 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
 * Cephes Math Library Release 2.4:  March,1996
 * Copyright 1984, 1996 by Stephen L. Moshier
 */

package cephes

import "math"

// Incbi computes the inverse of the regularized incomplete beta integral.
func Incbi(aa, bb, yy0 float64) float64 {
	var a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh, xt float64
	var i, rflg, dir, nflg int

	if yy0 <= 0 {
		return (0.0)
	}
	if yy0 >= 1.0 {
		return (1.0)
	}
	x0 = 0.0
	yl = 0.0
	x1 = 1.0
	yh = 1.0
	nflg = 0

	if aa <= 1.0 || bb <= 1.0 {
		dithresh = 1.0e-6
		rflg = 0
		a = aa
		b = bb
		y0 = yy0
		x = a / (a + b)
		y = Incbet(a, b, x)
		goto ihalve
	} else {
		dithresh = 1.0e-4
	}
	// Approximation to inverse function
	yp = -Ndtri(yy0)

	if yy0 > 0.5 {
		rflg = 1
		a = bb
		b = aa
		y0 = 1.0 - yy0
		yp = -yp
	} else {
		rflg = 0
		a = aa
		b = bb
		y0 = yy0
	}

	lgm = (yp*yp - 3.0) / 6.0
	x = 2.0 / (1.0/(2.0*a-1.0) + 1.0/(2.0*b-1.0))
	d = yp*math.Sqrt(x+lgm)/x - (1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(lgm+5.0/6.0-2.0/(3.0*x))
	d = 2.0 * d
	if d < minLog {
		// mtherr("incbi", UNDERFLOW)
		x = 0
		goto done
	}
	x = a / (a + b*math.Exp(d))
	y = Incbet(a, b, x)
	yp = (y - y0) / y0
	if math.Abs(yp) < 0.2 {
		goto newt
	}

	/* Resort to interval halving if not close enough. */
ihalve:

	dir = 0
	di = 0.5
	for i = 0; i < 100; i++ {
		if i != 0 {
			x = x0 + di*(x1-x0)
			if x == 1.0 {
				x = 1.0 - machEp
			}
			if x == 0.0 {
				di = 0.5
				x = x0 + di*(x1-x0)
				if x == 0.0 {
					// mtherr("incbi", UNDERFLOW)
					goto done
				}
			}
			y = Incbet(a, b, x)
			yp = (x1 - x0) / (x1 + x0)
			if math.Abs(yp) < dithresh {
				goto newt
			}
			yp = (y - y0) / y0
			if math.Abs(yp) < dithresh {
				goto newt
			}
		}
		if y < y0 {
			x0 = x
			yl = y
			if dir < 0 {
				dir = 0
				di = 0.5
			} else if dir > 3 {
				di = 1.0 - (1.0-di)*(1.0-di)
			} else if dir > 1 {
				di = 0.5*di + 0.5
			} else {
				di = (y0 - y) / (yh - yl)
			}
			dir += 1
			if x0 > 0.75 {
				if rflg == 1 {
					rflg = 0
					a = aa
					b = bb
					y0 = yy0
				} else {
					rflg = 1
					a = bb
					b = aa
					y0 = 1.0 - yy0
				}
				x = 1.0 - x
				y = Incbet(a, b, x)
				x0 = 0.0
				yl = 0.0
				x1 = 1.0
				yh = 1.0
				goto ihalve
			}
		} else {
			x1 = x
			if rflg == 1 && x1 < machEp {
				x = 0.0
				goto done
			}
			yh = y
			if dir > 0 {
				dir = 0
				di = 0.5
			} else if dir < -3 {
				di = di * di
			} else if dir < -1 {
				di = 0.5 * di
			} else {
				di = (y - y0) / (yh - yl)
			}
			dir -= 1
		}
	}
	// mtherr("incbi", PLOSS)
	if x0 >= 1.0 {
		x = 1.0 - machEp
		goto done
	}
	if x <= 0.0 {
		// mtherr("incbi", UNDERFLOW)
		x = 0.0
		goto done
	}

newt:
	if nflg > 0 {
		goto done
	}
	nflg = 1
	lgm = lgam(a+b) - lgam(a) - lgam(b)

	for i = 0; i < 8; i++ {
		/* Compute the function at this point. */
		if i != 0 {
			y = Incbet(a, b, x)
		}
		if y < yl {
			x = x0
			y = yl
		} else if y > yh {
			x = x1
			y = yh
		} else if y < y0 {
			x0 = x
			yl = y
		} else {
			x1 = x
			yh = y
		}
		if x == 1.0 || x == 0.0 {
			break
		}
		/* Compute the derivative of the function at this point. */
		d = (a-1.0)*math.Log(x) + (b-1.0)*math.Log(1.0-x) + lgm
		if d < minLog {
			goto done
		}
		if d > maxLog {
			break
		}
		d = math.Exp(d)
		/* Compute the step to the next approximation of x. */
		d = (y - y0) / d
		xt = x - d
		if xt <= x0 {
			y = (x - x0) / (x1 - x0)
			xt = x0 + 0.5*y*(x-x0)
			if xt <= 0.0 {
				break
			}
		}
		if xt >= x1 {
			y = (x1 - x) / (x1 - x0)
			xt = x1 - 0.5*y*(x1-x)
			if xt >= 1.0 {
				break
			}
		}
		x = xt
		if math.Abs(d/x) < 128.0*machEp {
			goto done
		}
	}
	/* Did not converge.  */
	dithresh = 256.0 * machEp
	goto ihalve

done:

	if rflg > 0 {
		if x <= machEp {
			x = 1.0 - machEp
		} else {
			x = 1.0 - x
		}
	}
	return (x)
}

func lgam(a float64) float64 {
	lg, _ := math.Lgamma(a)
	return lg
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, Shinya Yagyu
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */

package cgi

import (
	"bytes"
	"fmt"
	"html/template"
	htmlTemplate "html/template"
	"io"
	"log"
	"path"
	"path/filepath"
	textTemplate "text/template"
	"time"

	"github.com/shingetsu-gou/shingetsu-gou/cfg"
	"github.com/shingetsu-gou/shingetsu-gou/util"
)

//TmpH is template for html.
var TmpH = newHtemplate(cfg.TemplateDir)

//TmpT is template for text(rss).
var TmpT = newTtemplate(cfg.TemplateDir)

var funcMap = map[string]interface{}{
	"add":          func(a, b int) int { return a + b },
	"sub":          func(a, b int) int { return a - b },
	"mul":          func(a, b int) int { return a * b },
	"div":          func(a, b int) int { return a / b },
	"toMB":         func(a int) float64 { return float64(a) / (1024 * 1024) },
	"toKB":         func(a int) float64 { return float64(a) / (1024) },
	"toInt":        func(a int64) int { return int(a) },
	"stopEscaping": func(a string) template.HTML { return template.HTML(a) },
	"strEncode":    util.StrEncode,
	"escape":       util.Escape,
	"escapeSpace":  util.EscapeSpace,
	"localtime":    func(stamp int64) string { return time.Unix(stamp, 0).Format("2006-01-02 15:04") },
	"unescapedPrintf": func(format string, a ...interface{}) htmlTemplate.HTML {
		return htmlTemplate.HTML(fmt.Sprintf(format, a))
	},
}

//Ttemplate is for rendering text rss template.
type Ttemplate struct {
	*textTemplate.Template
}

//newTtemplate adds funcmap to template var and parse files.
func newTtemplate(templateDir string) *Ttemplate {
	t := &Ttemplate{textTemplate.New("")}
	t.Funcs(textTemplate.FuncMap(funcMap))
	templateFiles := filepath.Join(templateDir, "rss1.txt")
	if util.IsFile(templateFiles) {
		_, err := t.ParseFiles(templateFiles)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		cont, err := util.Asset(path.Join("gou_template", "rss1.txt"))
		if err != nil {
			log.Fatal(err)
		}
		_, err = t.Parse(string(cont))
		if err != nil {
			log.Fatal(err)
		}
	}
	return t
}

//Htemplate is for rendering html stuff.
type Htemplate struct {
	*htmlTemplate.Template
}

//newHtemplate adds funcmap to template var and parse files.
func newHtemplate(templateDir string) *Htemplate {
	t := &Htemplate{htmlTemplate.New("")}
	t.Funcs(htmlTemplate.FuncMap(funcMap))
	templateFiles := filepath.Join(templateDir, "*.txt")

	if util.IsDir(templateDir) {
		_, err := t.ParseGlob(templateFiles)
		if err != nil {
			log.Fatal(err)
		}
	}
	mat, err := filepath.Glob(templateFiles)
	if err != nil {
		log.Fatal(err)
	}
	e := make(map[string]struct{})
	for _, m := range mat {
		e[filepath.Base(m)] = struct{}{}
	}
	dir, err := util.AssetDir("gou_template")
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range dir {
		if _, exist := e[path.Base(a)]; exist {
			continue
		}
		c, err := util.Asset(path.Join("gou_template", a))
		if err != nil {
			log.Fatal(err)
		}

		if _, err := t.Parse(string(c)); err != nil {
			log.Fatal(err)
		}
	}

	return t
}

//RenderTemplate executes template and write to wr.
func (t *Htemplate) RenderTemplate(file string, st interface{}, wr io.Writer) {
	if err := t.Template.ExecuteTemplate(wr, file, st); err != nil {
		log.Println(err)
	}
}

//ExecuteTemplate executes template and returns it as string.
func (t *Htemplate) ExecuteTemplate(file string, st interface{}) string {
	var doc bytes.Buffer
	t.RenderTemplate(file, st, &doc)
	return doc.String()
}

//RenderTemplate executes rss template and write to wr.
func (t *Ttemplate) RenderTemplate(file string, st interface{}, wr io.Writer) {
	if err := t.ExecuteTemplate(wr, file, st); err != nil {
		log.Println(err)
	}
}
<commit_msg>trivials<commit_after>/*
 * Copyright (c) 2015, Shinya Yagyu
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 */

package cgi

import (
	"bytes"
	"html/template"
	htmlTemplate "html/template"
	"io"
	"log"
	"path"
	"path/filepath"
	textTemplate "text/template"
	"time"

	"github.com/shingetsu-gou/shingetsu-gou/cfg"
	"github.com/shingetsu-gou/shingetsu-gou/util"
)

//TmpH is template for html.
var TmpH = newHtemplate(cfg.TemplateDir)

//TmpT is template for text(rss).
var TmpT = newTtemplate(cfg.TemplateDir)

var funcMap = map[string]interface{}{
	"add":          func(a, b int) int { return a + b },
	"sub":          func(a, b int) int { return a - b },
	"mul":          func(a, b int) int { return a * b },
	"div":          func(a, b int) int { return a / b },
	"toMB":         func(a int) float64 { return float64(a) / (1024 * 1024) },
	"toKB":         func(a int) float64 { return float64(a) / (1024) },
	"toInt":        func(a int64) int { return int(a) },
	"stopEscaping": func(a string) template.HTML { return template.HTML(a) },
	"strEncode":    util.StrEncode,
	"escape":       util.Escape,
	"escapeSpace":  util.EscapeSpace,
	"localtime":    func(stamp int64) string { return time.Unix(stamp, 0).Format("2006-01-02 15:04") },
}

//Ttemplate is for rendering text rss template.
type Ttemplate struct {
	*textTemplate.Template
}

//newTtemplate adds funcmap to template var and parse files.
func newTtemplate(templateDir string) *Ttemplate {
	t := &Ttemplate{textTemplate.New("")}
	t.Funcs(textTemplate.FuncMap(funcMap))
	templateFiles := filepath.Join(templateDir, "rss1.txt")
	if util.IsFile(templateFiles) {
		_, err := t.ParseFiles(templateFiles)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		cont, err := util.Asset(path.Join("gou_template", "rss1.txt"))
		if err != nil {
			log.Fatal(err)
		}
		_, err = t.Parse(string(cont))
		if err != nil {
			log.Fatal(err)
		}
	}
	return t
}

//Htemplate is for rendering html stuff.
type Htemplate struct {
	*htmlTemplate.Template
}

//newHtemplate adds funcmap to template var and parse files.
func newHtemplate(templateDir string) *Htemplate {
	t := &Htemplate{htmlTemplate.New("")}
	t.Funcs(htmlTemplate.FuncMap(funcMap))
	templateFiles := filepath.Join(templateDir, "*.txt")

	if util.IsDir(templateDir) {
		_, err := t.ParseGlob(templateFiles)
		if err != nil {
			log.Fatal(err)
		}
	}
	mat, err := filepath.Glob(templateFiles)
	if err != nil {
		log.Fatal(err)
	}
	e := make(map[string]struct{})
	for _, m := range mat {
		e[filepath.Base(m)] = struct{}{}
	}
	dir, err := util.AssetDir("gou_template")
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range dir {
		if _, exist := e[path.Base(a)]; exist {
			continue
		}
		c, err := util.Asset(path.Join("gou_template", a))
		if err != nil {
			log.Fatal(err)
		}

		if _, err := t.Parse(string(c)); err != nil {
			log.Fatal(err)
		}
	}

	return t
}

//RenderTemplate executes template and write to wr.
func (t *Htemplate) RenderTemplate(file string, st interface{}, wr io.Writer) {
	if err := t.Template.ExecuteTemplate(wr, file, st); err != nil {
		log.Println(err)
	}
}

//ExecuteTemplate executes template and returns it as string.
func (t *Htemplate) ExecuteTemplate(file string, st interface{}) string {
	var doc bytes.Buffer
	t.RenderTemplate(file, st, &doc)
	return doc.String()
}

//RenderTemplate executes rss template and write to wr.
func (t *Ttemplate) RenderTemplate(file string, st interface{}, wr io.Writer) {
	if err := t.ExecuteTemplate(wr, file, st); err != nil {
		log.Println(err)
	}
}
<|endoftext|>


<commit_before>package helix

import (
	"fmt"
	"net/http"
	"strings"

	helixClient "github.com/nicklaw5/helix"
	log "github.com/sirupsen/logrus"
)

// Client wrapper for helix
type Client struct {
	clientID   string
	client     *helixClient.Client
	httpClient *http.Client
}

var (
	userCacheByID       map[string]*UserData
	userCacheByUsername map[string]*UserData
)

func init() {
	userCacheByID = map[string]*UserData{}
	userCacheByUsername = map[string]*UserData{}
}

// NewClient Create helix client
func NewClient(clientID string) Client {
	client, err := helixClient.NewClient(&helixClient.Options{
		ClientID: clientID,
	})
	if err != nil {
		panic(err)
	}

	return Client{
		clientID:   clientID,
		client:     client,
		httpClient: &http.Client{},
	}
}

type userResponse struct {
	Data []UserData `json:"data"`
}

// UserData exported data from twitch
type UserData struct {
	ID              string `json:"id"`
	Login           string `json:"login"`
	DisplayName     string `json:"display_name"`
	Type            string `json:"type"`
	BroadcasterType string `json:"broadcaster_type"`
	Description     string `json:"description"`
	ProfileImageURL string `json:"profile_image_url"`
	OfflineImageURL string `json:"offline_image_url"`
	ViewCount       int    `json:"view_count"`
	Email           string `json:"email"`
}

// GetUsersByUserIds receive userData for given ids
func (c *Client) GetUsersByUserIds(userIDs []string) (map[string]UserData, error) {
	var filteredUserIDs []string

	for _, id := range userIDs {
		if _, ok := userCacheByID[id]; !ok {
			filteredUserIDs = append(filteredUserIDs, id)
		}
	}

	if len(filteredUserIDs) > 0 {
		var chunks [][]string
		for i := 0; i < len(filteredUserIDs); i += 99 {
			end := i + 99

			if end > len(filteredUserIDs) {
				end = len(filteredUserIDs)
			}

			chunks = append(chunks, filteredUserIDs[i:end])
		}

		for _, chunk := range chunks {
			resp, err := c.client.GetUsers(&helixClient.UsersParams{
				IDs: chunk,
			})
			if err != nil {
				return make(map[string]UserData), err
			}
			log.Infof("[helix] %d GetUsersByUserIds %v", resp.StatusCode, chunk)
			if resp.StatusCode > http.StatusMultipleChoices {
				return make(map[string]UserData), fmt.Errorf("bad helix response: %v", resp.ErrorMessage)
			}

			for _, user := range resp.Data.Users {
				data := &UserData{
					ID:              user.ID,
					Login:           user.Login,
					DisplayName:     user.Login,
					Type:            user.Type,
					BroadcasterType: user.BroadcasterType,
					Description:     user.Description,
					ProfileImageURL: user.ProfileImageURL,
					OfflineImageURL: user.OfflineImageURL,
					ViewCount:       user.ViewCount,
					Email:           user.Email,
				}
				userCacheByID[user.ID] = data
				userCacheByUsername[user.Login] = data
			}
		}
	}

	result := make(map[string]UserData)

	for _, id := range userIDs {
		result[id] = *userCacheByID[id]
	}

	return result, nil
}

// GetUsersByUsernames fetches userdata from helix
func (c *Client) GetUsersByUsernames(usernames []string) (map[string]UserData, error) {
	var filteredUsernames []string

	for _, username := range usernames {
		if _, ok := userCacheByUsername[strings.ToLower(username)]; !ok {
			filteredUsernames = append(filteredUsernames, strings.ToLower(username))
		}
	}

	if len(filteredUsernames) > 0 {
		resp, err := c.client.GetUsers(&helixClient.UsersParams{
			Logins: filteredUsernames,
		})
		if err != nil {
			return map[string]UserData{}, err
		}

		log.Infof("[helix] %d GetUsersByUsernames %v", resp.StatusCode, filteredUsernames)

		for _, user := range resp.Data.Users {
			data := &UserData{
				ID:              user.ID,
				Login:           user.Login,
				DisplayName:     user.Login,
				Type:            user.Type,
				BroadcasterType: user.BroadcasterType,
				Description:     user.Description,
				ProfileImageURL: user.ProfileImageURL,
				OfflineImageURL: user.OfflineImageURL,
				ViewCount:       user.ViewCount,
				Email:           user.Email,
			}
			userCacheByID[user.ID] = data
			userCacheByUsername[user.Login] = data
		}
	}

	result := make(map[string]UserData)

	for _, username := range usernames {
		result[strings.ToLower(username)] = *userCacheByUsername[strings.ToLower(username)]
	}

	return result, nil
}
<commit_msg>handle banned users<commit_after>package helix

import (
	"fmt"
	"net/http"
	"strings"

	helixClient "github.com/nicklaw5/helix"
	log "github.com/sirupsen/logrus"
)

// Client wrapper for helix
type Client struct {
	clientID   string
	client     *helixClient.Client
	httpClient *http.Client
}

var (
	userCacheByID       map[string]*UserData
	userCacheByUsername map[string]*UserData
)

func init() {
	userCacheByID = map[string]*UserData{}
	userCacheByUsername = map[string]*UserData{}
}

// NewClient Create helix client
func NewClient(clientID string) Client {
	client, err := helixClient.NewClient(&helixClient.Options{
		ClientID: clientID,
	})
	if err != nil {
		panic(err)
	}

	return Client{
		clientID:   clientID,
		client:     client,
		httpClient: &http.Client{},
	}
}

type userResponse struct {
	Data []UserData `json:"data"`
}

// UserData exported data from twitch
type UserData struct {
	ID              string `json:"id"`
	Login           string `json:"login"`
	DisplayName     string `json:"display_name"`
	Type            string `json:"type"`
	BroadcasterType string `json:"broadcaster_type"`
	Description     string `json:"description"`
	ProfileImageURL string `json:"profile_image_url"`
	OfflineImageURL string `json:"offline_image_url"`
	ViewCount       int    `json:"view_count"`
	Email           string `json:"email"`
}

// GetUsersByUserIds receive userData for given ids
func (c *Client) GetUsersByUserIds(userIDs []string) (map[string]UserData, error) {
	var filteredUserIDs []string

	for _, id := range userIDs {
		if _, ok := userCacheByID[id]; !ok {
			filteredUserIDs = append(filteredUserIDs, id)
		}
	}

	if len(filteredUserIDs) > 0 {
		var chunks [][]string
		for i := 0; i < len(filteredUserIDs); i += 100 {
			end := i + 100

			if end > len(filteredUserIDs) {
				end = len(filteredUserIDs)
			}

			chunks = append(chunks, filteredUserIDs[i:end])
		}

		for _, chunk := range chunks {
			resp, err := c.client.GetUsers(&helixClient.UsersParams{
				IDs: chunk,
			})
			if err != nil {
				return make(map[string]UserData), err
			}
			log.Infof("[helix] %d GetUsersByUserIds %v", resp.StatusCode, chunk)
			if resp.StatusCode > http.StatusMultipleChoices {
				return make(map[string]UserData), fmt.Errorf("bad helix response: %v", resp.ErrorMessage)
			}

			for _, user := range resp.Data.Users {
				data := &UserData{
					ID:              user.ID,
					Login:           user.Login,
					DisplayName:     user.Login,
					Type:            user.Type,
					BroadcasterType: user.BroadcasterType,
					Description:     user.Description,
					ProfileImageURL: user.ProfileImageURL,
					OfflineImageURL: user.OfflineImageURL,
					ViewCount:       user.ViewCount,
					Email:           user.Email,
				}
				userCacheByID[user.ID] = data
				userCacheByUsername[user.Login] = data
			}
		}
	}

	result := make(map[string]UserData)

	for _, id := range userIDs {
		if _, ok := userCacheByID[id]; !ok {
			log.Errorf("Could not find userId, channel might be banned: %s", id)
			continue
		}
		result[id] = *userCacheByID[id]
	}

	return result, nil
}

// GetUsersByUsernames fetches userdata from helix
func (c *Client) GetUsersByUsernames(usernames []string) (map[string]UserData, error) {
	var filteredUsernames []string

	for _, username := range usernames {
		if _, ok := userCacheByUsername[strings.ToLower(username)]; !ok {
			filteredUsernames = append(filteredUsernames, strings.ToLower(username))
		}
	}

	if len(filteredUsernames) > 0 {
		resp, err := c.client.GetUsers(&helixClient.UsersParams{
			Logins: filteredUsernames,
		})
		if err != nil {
			return map[string]UserData{}, err
		}

		log.Infof("[helix] %d GetUsersByUsernames %v", resp.StatusCode, filteredUsernames)

		for _, user := range resp.Data.Users {
			data := &UserData{
				ID:              user.ID,
				Login:           user.Login,
				DisplayName:     user.Login,
				Type:            user.Type,
				BroadcasterType: user.BroadcasterType,
				Description:     user.Description,
				ProfileImageURL: user.ProfileImageURL,
				OfflineImageURL: user.OfflineImageURL,
				ViewCount:       user.ViewCount,
				Email:           user.Email,
			}
			userCacheByID[user.ID] = data
			userCacheByUsername[user.Login] = data
		}
	}

	result := make(map[string]UserData)

	for _, username := range usernames {
		result[strings.ToLower(username)] = *userCacheByUsername[strings.ToLower(username)]
	}

	return result, nil
}
<|endoftext|>


<commit_before>package check

// GoLint is the check for the go lint command
type GoLint struct {
	Dir       string
	Filenames []string
}

// Name returns the name of the display name of the command
func (g GoLint) Name() string {
	return "golint"
}

// Weight returns the weight this check has in the overall average
func (g GoLint) Weight() float64 {
	return .10
}

// Percentage returns the percentage of .go files that pass golint
func (g GoLint) Percentage() (float64, []FileSummary, error) {
	return GoTool(g.Dir, g.Filenames, []string{"gometalinter", "--deadline=180s", "--disable-all", "--enable=golint", "--min-confidence=0.85"})
}

// Description returns the description of go lint
func (g GoLint) Description() string {
	return `Golint is a linter for Go source code.`
}
<commit_msg>#158 add --vendor flag for golint check (not sure yet if others need it too)<commit_after>package check

// GoLint is the check for the go lint command
type GoLint struct {
	Dir       string
	Filenames []string
}

// Name returns the name of the display name of the command
func (g GoLint) Name() string {
	return "golint"
}

// Weight returns the weight this check has in the overall average
func (g GoLint) Weight() float64 {
	return .10
}

// Percentage returns the percentage of .go files that pass golint
func (g GoLint) Percentage() (float64, []FileSummary, error) {
	return GoTool(g.Dir, g.Filenames, []string{"gometalinter", "--deadline=180s", "--disable-all", "--enable=golint", "--min-confidence=0.85", "--vendor"})
}

// Description returns the description of go lint
func (g GoLint) Description() string {
	return `Golint is a linter for Go source code.`
}
<|endoftext|>


<commit_before>/**
 * (C) Copyright 2014, Deft Labs
 *
 * 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 dlshared

import (
	"sync"
	"time"
	"testing"
)

type testCronTestComponent struct {
	waitGroup *sync.WaitGroup

	runCalledCount int
	testCalledCount int
}

func (self *testCronTestComponent) Run() {
	self.waitGroup.Add(1)
	self.runCalledCount++
	self.waitGroup.Done()
}

func (self *testCronTestComponent) Test() {
	self.waitGroup.Add(1)
	self.testCalledCount++
	self.waitGroup.Done()
}

// Test the cron services.
func TestCron(t *testing.T) {

	waitGroup := new(sync.WaitGroup)

	testComponent := &testCronTestComponent{ waitGroup: waitGroup }

	kernel, err := baseTestStartKernel("cronTest", func(kernel *Kernel) {

		kernel.AddComponent("testCronTestComponent", testComponent)

		kernel.AddComponentWithStartStopMethods("CronSvc", NewCronSvc("cron.scheduled"), "Start", "Stop")
	})

	if err != nil { t.Errorf("TestCron start kernel is broken:", err); return }

	waitGroup.Wait()

	time.Sleep(2*time.Second)

	if testComponent.runCalledCount == 0 { t.Errorf("TestCron Run() not called") }

	if testComponent.testCalledCount == 0 { t.Errorf("TestCron Test() not called") }

	if err := kernel.Stop(); err != nil { t.Errorf("TestCron stop kernel is broken:", err) }
}

<commit_msg>added tests for timeout<commit_after>/**
 * (C) Copyright 2014, Deft Labs
 *
 * 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 dlshared

import (
	"sync"
	"time"
	"testing"
)

type testCronTestComponent struct {
	waitGroup *sync.WaitGroup
	runCalledCount int
	interruptCalledCount int
	interruptReceived bool
	lock *sync.Mutex
}

func (self *testCronTestComponent) Run(interruptChannel chan bool) {
	self.waitGroup.Add(1)
	defer self.waitGroup.Done()

	self.lock.Lock()
	self.runCalledCount++
	self.lock.Unlock()

	time.Sleep(1* time.Millisecond)
}

func (self *testCronTestComponent) Interrupt(interruptChannel chan bool) {
	self.waitGroup.Add(1)
	defer self.waitGroup.Done()

	self.lock.Lock()
	self.interruptCalledCount++
	self.lock.Unlock()

	<- interruptChannel // wait for the signal

	self.lock.Lock()
	self.interruptReceived = true
	self.lock.Unlock()

}

// Test the cron services.
func TestCron(t *testing.T) {

	waitGroup := new(sync.WaitGroup)

	testComponent := &testCronTestComponent{ waitGroup: waitGroup, lock: new(sync.Mutex) }

	kernel, err := baseTestStartKernel("cronTest", func(kernel *Kernel) {
		kernel.AddComponent("testCronTestComponent", testComponent)
		kernel.AddComponentWithStartStopMethods("CronSvc", NewCronSvc("cron.scheduled"), "Start", "Stop")
	})

	if err != nil { t.Errorf("TestCron start kernel is broken:", err); return }

	waitGroup.Wait()

	time.Sleep(4*time.Second)

	// We have multiple goroutines modifying the
	testComponent.lock.Lock()
	if testComponent.runCalledCount == 0 { t.Errorf("TestCron Run(chan) not called") }
	if testComponent.interruptCalledCount == 0 { t.Errorf("TestCron Interrupt(chan) not called") }
	if !testComponent.interruptReceived { t.Errorf("TestCron Interrupt(chan) was not interrupted") }
	testComponent.lock.Unlock()

	if err := kernel.Stop(); err != nil { t.Errorf("TestCron stop kernel is broken:", err) }
}

<|endoftext|>