<commit_before>package gomega

import (
	"github.com/onsi/gomega/matchers"
)

//Equal uses reflect.DeepEqual to compare actual with expected
//It is an error for both actual and expected to be nil.  Use BeNil() instead.
func Equal(expected interface{}) OmegaMatcher {
	return &matchers.EqualMatcher{
		Expected: expected,
	}
}

//BeNil succeeds if actual is nil
func BeNil() OmegaMatcher {
	return &matchers.BeNilMatcher{}
}

//BeTrue succeeds if actual is true
func BeTrue() OmegaMatcher {
	return &matchers.BeTrueMatcher{}
}

//BeFalse succeeds if actual is false
func BeFalse() OmegaMatcher {
	return &matchers.BeFalseMatcher{}
}

//HaveOccured succeeds if actual is a non-nil error
//The typical Go error checking pattern looks like:
//
//  err := SomethingThatMightFail()
//  Ω(err).ShouldNot(HaveOccured())
func HaveOccured() OmegaMatcher {
	return &matchers.HaveOccuredMatcher{}
}

//MatchRegexp succeeds if actual is a string or stringer that matches the
//passed-in regexp.  Optional arguments can be provided to construct a regexp
//via fmt.Sprintf().
func MatchRegexp(regexp string, args ...interface{}) OmegaMatcher {
	return &matchers.MatchRegexpMatcher{
		Regexp: regexp,
		Args:   args,
	}
}

//ContainSubstring succeeds if actual is a string or stringer that contains the
//passed-in regexp.  Optional arguments can be provided to construct the substring
//via fmt.Sprintf().
func ContainSubstring(substr string, args ...interface{}) OmegaMatcher {
	return &matchers.ContainSubstringMatcher{
		Substr: substr,
		Args:   args,
	}
}

//BeEmpty succeeds if actual is empty.  Actual must be of type string, array, map, chan, or slice.
func BeEmpty() OmegaMatcher {
	return &matchers.BeEmptyMatcher{}
}

//HaveLen succeeds if actual has the passed-in length.  Actual must be of type string, array, map, chan, or slice.
func HaveLen(count int) OmegaMatcher {
	return &matchers.HaveLenMatcher{
		Count: count,
	}
}

//BeZero succeeds if actual is the zero value for its type or if actual is nil.
func BeZero() OmegaMatcher {
	return &matchers.BeZeroMatcher{}
}

//ContainElement succeeds if actual contains the passed in element.
//By default ContainElement() uses Equal() to perform the match, however a
//matcher can be passed in instead:
//
//  Ω([]string{"Foo", "FooBar"}).Should(ContainElement(ContainSubstring("Bar")))
//
//Actual must be an array, slice or map.
//For maps, containElement searches through the map's values.
func ContainElement(element interface{}) OmegaMatcher {
	return &matchers.ContainElementMatcher{
		Element: element,
	}
}

//HaveKey succeeds if actual is a map with the passed in key.
//By default HaveKey uses Equal() to perform the match, however a
//matcher can be passed in instead:
//
//  Ω(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKey(MatchRegexp(`.+Foo$`)))
func HaveKey(key interface{}) OmegaMatcher {
	return &matchers.HaveKeyMatcher{
		Key: key,
	}
}

//BeNumerically performs numerical assertions in a type-agnostic way.
//Actual and expected should be numbers, though the specific type of
//number is irrelevant (floa32, float64, uint8, etc...).
//
//There are six, self-explanatory, supported comparators:
//
//  Ω(1.0).Should(BeNumerically("==", 1))
//  Ω(1.0).Should(BeNumerically("~", 0.999, 0.01))
//  Ω(1.0).Should(BeNumerically(">", 0.9))
//  Ω(1.0).Should(BeNumerically(">=", 1.0))
//  Ω(1.0).Should(BeNumerically("<", 3))
//  Ω(1.0).Should(BeNumerically("<=", 1.0))
func BeNumerically(comparator string, compareTo ...interface{}) OmegaMatcher {
	return &matchers.BeNumericallyMatcher{
		Comparator: comparator,
		CompareTo:  compareTo,
	}
}

func BeAssignableTo(expected interface{}) OmegaMatcher {
	return &matchers.AssignableToMatcher{
		Expected: expected,
	}
}

//Panic succeeds if actual is a function that, when invoked, panics.
//Actual must be a function that takes no arguments and returns no results.
func Panic() OmegaMatcher {
	return &matchers.PanicMatcher{}
}
<commit_msg>Adds godoc documentation to BeAssignableTo<commit_after>package gomega

import (
	"github.com/onsi/gomega/matchers"
)

//Equal uses reflect.DeepEqual to compare actual with expected
//It is an error for both actual and expected to be nil.  Use BeNil() instead.
func Equal(expected interface{}) OmegaMatcher {
	return &matchers.EqualMatcher{
		Expected: expected,
	}
}

//BeNil succeeds if actual is nil
func BeNil() OmegaMatcher {
	return &matchers.BeNilMatcher{}
}

//BeTrue succeeds if actual is true
func BeTrue() OmegaMatcher {
	return &matchers.BeTrueMatcher{}
}

//BeFalse succeeds if actual is false
func BeFalse() OmegaMatcher {
	return &matchers.BeFalseMatcher{}
}

//HaveOccured succeeds if actual is a non-nil error
//The typical Go error checking pattern looks like:
//
//  err := SomethingThatMightFail()
//  Ω(err).ShouldNot(HaveOccured())
func HaveOccured() OmegaMatcher {
	return &matchers.HaveOccuredMatcher{}
}

//MatchRegexp succeeds if actual is a string or stringer that matches the
//passed-in regexp.  Optional arguments can be provided to construct a regexp
//via fmt.Sprintf().
func MatchRegexp(regexp string, args ...interface{}) OmegaMatcher {
	return &matchers.MatchRegexpMatcher{
		Regexp: regexp,
		Args:   args,
	}
}

//ContainSubstring succeeds if actual is a string or stringer that contains the
//passed-in regexp.  Optional arguments can be provided to construct the substring
//via fmt.Sprintf().
func ContainSubstring(substr string, args ...interface{}) OmegaMatcher {
	return &matchers.ContainSubstringMatcher{
		Substr: substr,
		Args:   args,
	}
}

//BeEmpty succeeds if actual is empty.  Actual must be of type string, array, map, chan, or slice.
func BeEmpty() OmegaMatcher {
	return &matchers.BeEmptyMatcher{}
}

//HaveLen succeeds if actual has the passed-in length.  Actual must be of type string, array, map, chan, or slice.
func HaveLen(count int) OmegaMatcher {
	return &matchers.HaveLenMatcher{
		Count: count,
	}
}

//BeZero succeeds if actual is the zero value for its type or if actual is nil.
func BeZero() OmegaMatcher {
	return &matchers.BeZeroMatcher{}
}

//ContainElement succeeds if actual contains the passed in element.
//By default ContainElement() uses Equal() to perform the match, however a
//matcher can be passed in instead:
//
//  Ω([]string{"Foo", "FooBar"}).Should(ContainElement(ContainSubstring("Bar")))
//
//Actual must be an array, slice or map.
//For maps, containElement searches through the map's values.
func ContainElement(element interface{}) OmegaMatcher {
	return &matchers.ContainElementMatcher{
		Element: element,
	}
}

//HaveKey succeeds if actual is a map with the passed in key.
//By default HaveKey uses Equal() to perform the match, however a
//matcher can be passed in instead:
//
//  Ω(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKey(MatchRegexp(`.+Foo$`)))
func HaveKey(key interface{}) OmegaMatcher {
	return &matchers.HaveKeyMatcher{
		Key: key,
	}
}

//BeNumerically performs numerical assertions in a type-agnostic way.
//Actual and expected should be numbers, though the specific type of
//number is irrelevant (floa32, float64, uint8, etc...).
//
//There are six, self-explanatory, supported comparators:
//
//  Ω(1.0).Should(BeNumerically("==", 1))
//  Ω(1.0).Should(BeNumerically("~", 0.999, 0.01))
//  Ω(1.0).Should(BeNumerically(">", 0.9))
//  Ω(1.0).Should(BeNumerically(">=", 1.0))
//  Ω(1.0).Should(BeNumerically("<", 3))
//  Ω(1.0).Should(BeNumerically("<=", 1.0))
func BeNumerically(comparator string, compareTo ...interface{}) OmegaMatcher {
	return &matchers.BeNumericallyMatcher{
		Comparator: comparator,
		CompareTo:  compareTo,
	}
}

//BeAssignableTo succeeds if actual is assignable to the type of actual.
//It will return an error when one of the values is nil.
//
//	Ω(0).Should(BeAssignableTo(0))         // Same values
//	Ω(5).Should(BeAssignableTo(-1))        // different values same type
//	Ω("foo").Should(BeAssignableTo("bar")) // different values same type
func BeAssignableTo(expected interface{}) OmegaMatcher {
	return &matchers.AssignableToMatcher{
		Expected: expected,
	}
}

//Panic succeeds if actual is a function that, when invoked, panics.
//Actual must be a function that takes no arguments and returns no results.
func Panic() OmegaMatcher {
	return &matchers.PanicMatcher{}
}
<|endoftext|>


<commit_before>// Package config for config files.
package client

// LibraryVersion specifies the current version of twilio-go.
const LibraryVersion = "0.21.0"
<commit_msg>Release v0.22.0<commit_after>// Package config for config files.
package client

// LibraryVersion specifies the current version of twilio-go.
const LibraryVersion = "0.22.0"
<|endoftext|>


<commit_before>package sync

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

// RWMutex provides locking functions, and an ability to detect and remove
// deadlocks.
type RWMutex struct {
	openLocks        map[int]lockInfo
	openLocksCounter int
	openLocksMutex   sync.Mutex

	callDepth   int
	maxLockTime time.Duration

	mu sync.RWMutex
}

// lockInfo contains information about when and how a lock call was made.
type lockInfo struct {
	// When the lock was called.
	lockTime time.Time

	// Call stack of the caller.
	callingFiles []string
	callingLines []int
}

// New takes a maxLockTime and returns a lock. The lock will never stay locked
// for more than maxLockTime, instead printing an error and unlocking after
// maxLockTime has passed.
func New(maxLockTime time.Duration, callDepth int) *RWMutex {
	rwm := &RWMutex{
		openLocks:   make(map[int]lockInfo),
		maxLockTime: maxLockTime,
		callDepth:   callDepth,
	}

	go rwm.threadedDeadlockFinder()

	return rwm
}

// threadedDeadlockFinder occasionally freezes the mutexes and scans all open mutexes,
// reporting any that have exceeded their time limit.
func (rwm *RWMutex) threadedDeadlockFinder() {
	for {
		rwm.openLocksMutex.Lock()
		for id, info := range rwm.openLocks {
			// Check if the lock has been held for longer than 'maxLockTime'.
			if time.Now().Sub(info.lockTime) > rwm.maxLockTime {
				fmt.Printf("A lock was held for too long, id '%v'. Call stack:\n", id)
				for i := 0; i <= rwm.callDepth; i++ {
					fmt.Printf("\tFile '%v', Line '%v'\n", info.callingFiles[i], info.callingLines[i])
				}
			}
		}
		rwm.openLocksMutex.Unlock()

		time.Sleep(rwm.maxLockTime)
	}
}

// safeLock is the generic function for doing safe locking. If the read flag is
// set, then a readlock will be used, otherwise a lock will be used.
func (rwm *RWMutex) safeLock(read bool) int {
	// Get the call stack.
	var li lockInfo
	li.lockTime = time.Now()
	li.callingFiles = make([]string, rwm.callDepth+1)
	li.callingLines = make([]int, rwm.callDepth+1)
	for i := 0; i <= rwm.callDepth; i++ {
		_, li.callingFiles[i], li.callingLines[i], _ = runtime.Caller(2 + i)
	}

	// Safely register that a lock has been triggered.
	rwm.openLocksMutex.Lock()
	counter := rwm.openLocksCounter
	rwm.openLocks[counter] = li
	rwm.openLocksCounter++
	rwm.openLocksMutex.Unlock()

	// Lock the mutex.
	if read {
		rwm.mu.RLock()
	} else {
		rwm.mu.Lock()
	}

	return counter
}

// safeUnlock is the generic function for doing safe unlocking. If the lock had
// to be removed because a deadlock was detected, an error is printed.
func (rwm *RWMutex) safeUnlock(read bool, counter int) {
	// Get the call stack.
	callingFiles := make([]string, rwm.callDepth+1)
	callingLines := make([]int, rwm.callDepth+1)
	for i := 0; i <= rwm.callDepth; i++ {
		_, callingFiles[i], callingLines[i], _ = runtime.Caller(2 + i)
	}

	rwm.openLocksMutex.Lock()
	defer rwm.openLocksMutex.Unlock()

	// Check if a deadlock has been detected and fixed manually.
	_, exists := rwm.openLocks[counter]
	if !exists {
		var lockType string
		if read {
			lockType = "read "
		} else {
			lockType = ""
		}
		fmt.Printf("A%v lock was held until deadlock, subsequent call to%v unlock failed. id '%v'. Call stack:\n", lockType, lockType, counter)
		for i := 0; i <= rwm.callDepth; i++ {
			fmt.Printf("\tFile '%v', Line '%v'\n", callingFiles[i], callingLines[i])
		}
		return
	}

	// Remove the lock.
	delete(rwm.openLocks, counter)
	if read {
		rwm.mu.RUnlock()
	} else {
		rwm.mu.Unlock()
	}
}

// RLock will read lock the RWMutex. The return value must be used as input
// when calling RUnlock.
func (rwm *RWMutex) RLock() int {
	return rwm.safeLock(true)
}

// RUnlock will read unlock the RWMutex. The return value of calling RLock must
// be used as input.
func (rwm *RWMutex) RUnlock(counter int) {
	rwm.safeUnlock(true, counter)
}

// Lock will lock the RWMutex. The return value must be used as input when
// calling RUnlock.
func (rwm *RWMutex) Lock() int {
	return rwm.safeLock(false)
}

// Unlock will unlock the RWMutex. The return value of calling Lock must be
// used as input.
func (rwm *RWMutex) Unlock(counter int) {
	rwm.safeUnlock(false, counter)
}
<commit_msg>lock trace formatting<commit_after>package sync

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

// RWMutex provides locking functions, and an ability to detect and remove
// deadlocks.
type RWMutex struct {
	openLocks        map[int]lockInfo
	openLocksCounter int
	openLocksMutex   sync.Mutex

	callDepth   int
	maxLockTime time.Duration

	mu sync.RWMutex
}

// lockInfo contains information about when and how a lock call was made.
type lockInfo struct {
	// When the lock was called.
	lockTime time.Time

	// Call stack of the caller.
	callingFiles []string
	callingLines []int
}

// New takes a maxLockTime and returns a lock. The lock will never stay locked
// for more than maxLockTime, instead printing an error and unlocking after
// maxLockTime has passed.
func New(maxLockTime time.Duration, callDepth int) *RWMutex {
	rwm := &RWMutex{
		openLocks:   make(map[int]lockInfo),
		maxLockTime: maxLockTime,
		callDepth:   callDepth,
	}

	go rwm.threadedDeadlockFinder()

	return rwm
}

// threadedDeadlockFinder occasionally freezes the mutexes and scans all open mutexes,
// reporting any that have exceeded their time limit.
func (rwm *RWMutex) threadedDeadlockFinder() {
	for {
		rwm.openLocksMutex.Lock()
		for id, info := range rwm.openLocks {
			// Check if the lock has been held for longer than 'maxLockTime'.
			if time.Now().Sub(info.lockTime) > rwm.maxLockTime {
				fmt.Printf("A lock was held for too long, id '%v'. Call stack:\n", id)
				for i := 0; i <= rwm.callDepth; i++ {
					fmt.Printf("\tFile: '%v:%v'\n", info.callingFiles[i], info.callingLines[i])
				}
			}
		}
		rwm.openLocksMutex.Unlock()

		time.Sleep(rwm.maxLockTime)
	}
}

// safeLock is the generic function for doing safe locking. If the read flag is
// set, then a readlock will be used, otherwise a lock will be used.
func (rwm *RWMutex) safeLock(read bool) int {
	// Get the call stack.
	var li lockInfo
	li.lockTime = time.Now()
	li.callingFiles = make([]string, rwm.callDepth+1)
	li.callingLines = make([]int, rwm.callDepth+1)
	for i := 0; i <= rwm.callDepth; i++ {
		_, li.callingFiles[i], li.callingLines[i], _ = runtime.Caller(2 + i)
	}

	// Safely register that a lock has been triggered.
	rwm.openLocksMutex.Lock()
	counter := rwm.openLocksCounter
	rwm.openLocks[counter] = li
	rwm.openLocksCounter++
	rwm.openLocksMutex.Unlock()

	// Lock the mutex.
	if read {
		rwm.mu.RLock()
	} else {
		rwm.mu.Lock()
	}

	return counter
}

// safeUnlock is the generic function for doing safe unlocking. If the lock had
// to be removed because a deadlock was detected, an error is printed.
func (rwm *RWMutex) safeUnlock(read bool, counter int) {
	// Get the call stack.
	callingFiles := make([]string, rwm.callDepth+1)
	callingLines := make([]int, rwm.callDepth+1)
	for i := 0; i <= rwm.callDepth; i++ {
		_, callingFiles[i], callingLines[i], _ = runtime.Caller(2 + i)
	}

	rwm.openLocksMutex.Lock()
	defer rwm.openLocksMutex.Unlock()

	// Check if a deadlock has been detected and fixed manually.
	_, exists := rwm.openLocks[counter]
	if !exists {
		fmt.Printf("A lock was held until deadlock, subsequent call to unlock failed. id '%v'. Call stack:\n", counter)
		for i := 0; i <= rwm.callDepth; i++ {
			fmt.Printf("\tFile: '%v:%v'\n", callingFiles[i], callingLines[i])
		}
		return
	}

	// Remove the lock.
	delete(rwm.openLocks, counter)
	if read {
		rwm.mu.RUnlock()
	} else {
		rwm.mu.Unlock()
	}
}

// RLock will read lock the RWMutex. The return value must be used as input
// when calling RUnlock.
func (rwm *RWMutex) RLock() int {
	return rwm.safeLock(true)
}

// RUnlock will read unlock the RWMutex. The return value of calling RLock must
// be used as input.
func (rwm *RWMutex) RUnlock(counter int) {
	rwm.safeUnlock(true, counter)
}

// Lock will lock the RWMutex. The return value must be used as input when
// calling RUnlock.
func (rwm *RWMutex) Lock() int {
	return rwm.safeLock(false)
}

// Unlock will unlock the RWMutex. The return value of calling Lock must be
// used as input.
func (rwm *RWMutex) Unlock(counter int) {
	rwm.safeUnlock(false, counter)
}
<|endoftext|>


<commit_before>package cas

import (
	"bytes"
	"io/ioutil"
	"testing"
)

var testBlobs = []struct {
	name string
	data []byte
}{
	{"s6bi7Tmf1itJ5o3vuASiMPDpY69tDkpUjDfe5srJHEX9v", []byte("Test")},
	{"sAKjyeXcDkdbTp7BWZruxDqthaCHb4kmdQxE28j2HSNva", []byte("Test1")},
	{"sGKot5hBsd81kMupNCXHaqbhv3huEbxAFMLnpcX2hniwn", []byte("")},
}

func allCAS(f func(c CAS)) {
	f(InMemory())
}

func TestOpenNonExisting(t *testing.T) {
	allCAS(func(c CAS) {

		s, e := c.Open("non-existing")
		if s != nil {
			t.Fatalf("CAS %s: Opened non-existing blob", c.Kind())
		}
		if e != ErrNotFound {
			t.Fatalf("CAS %s: Invalid error returned for non-existing blob: %s", c.Kind(), e)
		}
	})
}

func TestSaveInvalidName(t *testing.T) {
	allCAS(func(c CAS) {

		w, e := c.Save("invalid-name")
		if e != nil {
			t.Fatalf("CAS %s: Couldn't create CAS writer: %s", c.Kind(), e)
		}
		if w == nil {
			t.Fatalf("CAS %s: Didn't get blob writer", c.Kind())
		}

		n, e := w.Write([]byte("Test"))
		if e != nil {
			t.Fatalf("CAS %s: Couldn't write CAS data: %s", c.Kind(), e)
		}
		if n != 4 {
			t.Fatalf("CAS %s: Invalid number of bytes written: %d", c.Kind(), n)
		}

		e = w.Close()
		if e == nil || e != ErrNameMismatch {
			t.Fatalf("CAS %s: Didn't detect name mismatch: %s", c.Kind(), e)
		}
	})
}

func TestSaveSuccessful(t *testing.T) {
	allCAS(func(c CAS) {
		for _, b := range testBlobs {

			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist", c.Kind())
			}

			// Saving blob
			w, e := c.Save(b.name)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't create CAS writer: %s", c.Kind(), e)
			}
			if w == nil {
				t.Fatalf("CAS %s: Didn't get blob writer", c.Kind())
			}
			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist before saving data", c.Kind())
			}
			n, e := w.Write(b.data)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't write CAS data: %s", c.Kind(), e)
			}
			if n != len(b.data) {
				t.Fatalf("CAS %s: Invalid number of bytes written: %d", c.Kind(), n)
			}
			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist before stream close", c.Kind())
			}
			e = w.Close()
			if e != nil {
				t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
			}
			if !c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should exist after stream close", c.Kind())
			}
			w = nil

			// Reading blob
			r, e := c.Open(b.name)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't open blob for reading: %s", c.Kind(), e)
			}
			d, e := ioutil.ReadAll(r)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't read blob data: %s", c.Kind(), e)
			}
			if !bytes.Equal(b.data, d) {
				t.Fatalf("CAS %s: Did read invalid data", c.Kind())
			}
		}
	})
}

func errPanic(e error) {
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
}

func putBlob(n string, b []byte, c CAS) {
	w, e := c.Save(n)
	errPanic(e)
	cnt, e := w.Write(b)
	errPanic(e)
	if cnt != len(b) {
		panic("Invalid data size written")
	}
	e = w.Close()
	errPanic(e)
	if !c.Exists(n) {
		panic("Blob does not exist: " + n)
	}
}

func getBlob(n string, c CAS) []byte {
	r, e := c.Open(n)
	errPanic(e)
	d, e := ioutil.ReadAll(r)
	errPanic(e)
	e = r.Close()
	errPanic(e)
	return d
}

func TestOverwriteValidContents(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		e := w.Close()
		if e != nil {
			t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestOverwriteInvalidContents(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write([]byte("Extra"))
		e := w.Close()
		if e != ErrNameMismatch {
			t.Fatalf("CAS %s: Invalid blob save error: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestOverwriteWhileDeleting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}
		e := c.Delete(b.name)
		if e != nil {
			t.Fatalf("CAS %s: Can't remove blob", c.Kind())
		}
		if c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should not exist", c.Kind())
		}

		e = w.Close()
		if e != nil {
			t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestDeleteNonExisting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		err := c.Delete("non-existing")
		if err != ErrNotFound {
			t.Fatalf("CAS %s: Did not get ErrNotFound while deleting non-existing blob: %v", c.Kind(), err)
		}

	})
}

func TestDeleteExisting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}

		err := c.Delete(b.name)
		if err != nil {
			t.Fatalf("CAS %s: Couldn't delete blob: %v", c.Kind(), err)
		}

		if c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should not exist", c.Kind())
		}

		r, err := c.Open(b.name)
		if err != ErrNotFound {
			t.Fatalf("CAS %s: Did not get ErrNotFound error after blob deletion", c.Kind())
		}
		if r != nil {
			t.Fatalf("CAS %s: Got reader for deleted blob", c.Kind())
		}

	})
}

func TestGetKind(t *testing.T) {
	allCAS(func(c CAS) {
		k := c.Kind()
		if len(k) == 0 {
			t.Fatalf("Invalid kind - empty string")
		}
	})
}
<commit_msg>Add basic multithreading test<commit_after>package cas

import (
	"bytes"
	"io/ioutil"
	"sync"
	"testing"
)

var testBlobs = []struct {
	name string
	data []byte
}{
	{"s6bi7Tmf1itJ5o3vuASiMPDpY69tDkpUjDfe5srJHEX9v", []byte("Test")},
	{"sAKjyeXcDkdbTp7BWZruxDqthaCHb4kmdQxE28j2HSNva", []byte("Test1")},
	{"sGKot5hBsd81kMupNCXHaqbhv3huEbxAFMLnpcX2hniwn", []byte("")},
}

func allCAS(f func(c CAS)) {
	f(InMemory())
}

func TestOpenNonExisting(t *testing.T) {
	allCAS(func(c CAS) {

		s, e := c.Open("non-existing")
		if s != nil {
			t.Fatalf("CAS %s: Opened non-existing blob", c.Kind())
		}
		if e != ErrNotFound {
			t.Fatalf("CAS %s: Invalid error returned for non-existing blob: %s", c.Kind(), e)
		}
	})
}

func TestSaveInvalidName(t *testing.T) {
	allCAS(func(c CAS) {

		w, e := c.Save("invalid-name")
		if e != nil {
			t.Fatalf("CAS %s: Couldn't create CAS writer: %s", c.Kind(), e)
		}
		if w == nil {
			t.Fatalf("CAS %s: Didn't get blob writer", c.Kind())
		}

		n, e := w.Write([]byte("Test"))
		if e != nil {
			t.Fatalf("CAS %s: Couldn't write CAS data: %s", c.Kind(), e)
		}
		if n != 4 {
			t.Fatalf("CAS %s: Invalid number of bytes written: %d", c.Kind(), n)
		}

		e = w.Close()
		if e == nil || e != ErrNameMismatch {
			t.Fatalf("CAS %s: Didn't detect name mismatch: %s", c.Kind(), e)
		}
	})
}

func TestSaveSuccessful(t *testing.T) {
	allCAS(func(c CAS) {
		for _, b := range testBlobs {

			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist", c.Kind())
			}

			// Saving blob
			w, e := c.Save(b.name)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't create CAS writer: %s", c.Kind(), e)
			}
			if w == nil {
				t.Fatalf("CAS %s: Didn't get blob writer", c.Kind())
			}
			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist before saving data", c.Kind())
			}
			n, e := w.Write(b.data)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't write CAS data: %s", c.Kind(), e)
			}
			if n != len(b.data) {
				t.Fatalf("CAS %s: Invalid number of bytes written: %d", c.Kind(), n)
			}
			if c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should not exist before stream close", c.Kind())
			}
			e = w.Close()
			if e != nil {
				t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
			}
			if !c.Exists(b.name) {
				t.Fatalf("CAS %s: Blob should exist after stream close", c.Kind())
			}
			w = nil

			// Reading blob
			r, e := c.Open(b.name)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't open blob for reading: %s", c.Kind(), e)
			}
			d, e := ioutil.ReadAll(r)
			if e != nil {
				t.Fatalf("CAS %s: Couldn't read blob data: %s", c.Kind(), e)
			}
			if !bytes.Equal(b.data, d) {
				t.Fatalf("CAS %s: Did read invalid data", c.Kind())
			}
		}
	})
}

func errPanic(e error) {
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
}

func putBlob(n string, b []byte, c CAS) {
	w, e := c.Save(n)
	errPanic(e)
	cnt, e := w.Write(b)
	errPanic(e)
	if cnt != len(b) {
		panic("Invalid data size written")
	}
	e = w.Close()
	errPanic(e)
	if !c.Exists(n) {
		panic("Blob does not exist: " + n)
	}
}

func getBlob(n string, c CAS) []byte {
	r, e := c.Open(n)
	errPanic(e)
	d, e := ioutil.ReadAll(r)
	errPanic(e)
	e = r.Close()
	errPanic(e)
	return d
}

func TestOverwriteValidContents(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		e := w.Close()
		if e != nil {
			t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestOverwriteInvalidContents(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write([]byte("Extra"))
		e := w.Close()
		if e != ErrNameMismatch {
			t.Fatalf("CAS %s: Invalid blob save error: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestOverwriteWhileDeleting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		w, _ := c.Save(b.name)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		w.Write(b.data)
		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}
		e := c.Delete(b.name)
		if e != nil {
			t.Fatalf("CAS %s: Can't remove blob", c.Kind())
		}
		if c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should not exist", c.Kind())
		}

		e = w.Close()
		if e != nil {
			t.Fatalf("CAS %s: Couldn't save correct blob: %s", c.Kind(), e)
		}

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}
	})
}

func TestDeleteNonExisting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		err := c.Delete("non-existing")
		if err != ErrNotFound {
			t.Fatalf("CAS %s: Did not get ErrNotFound while deleting non-existing blob: %v", c.Kind(), err)
		}

	})
}

func TestDeleteExisting(t *testing.T) {
	allCAS(func(c CAS) {

		b := testBlobs[0]
		putBlob(b.name, b.data, c)

		if !c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should exist", c.Kind())
		}

		if !bytes.Equal(b.data, getBlob(b.name, c)) {
			t.Fatalf("CAS %s: Did read invalid data", c.Kind())
		}

		err := c.Delete(b.name)
		if err != nil {
			t.Fatalf("CAS %s: Couldn't delete blob: %v", c.Kind(), err)
		}

		if c.Exists(b.name) {
			t.Fatalf("CAS %s: Blob should not exist", c.Kind())
		}

		r, err := c.Open(b.name)
		if err != ErrNotFound {
			t.Fatalf("CAS %s: Did not get ErrNotFound error after blob deletion", c.Kind())
		}
		if r != nil {
			t.Fatalf("CAS %s: Got reader for deleted blob", c.Kind())
		}

	})
}

func TestGetKind(t *testing.T) {
	allCAS(func(c CAS) {
		k := c.Kind()
		if len(k) == 0 {
			t.Fatalf("Invalid kind - empty string")
		}
	})
}

func TestSimultaneousReads(t *testing.T) {
	threadCnt := 100
	readCnt := 1000

	allCAS(func(c CAS) {

		// Prepare data
		for _, b := range testBlobs {
			putBlob(b.name, b.data, c)
		}

		wg := sync.WaitGroup{}
		wg.Add(threadCnt)

		for i := 0; i < threadCnt; i++ {
			go func(i int) {
				defer wg.Done()
				for n := 0; n < readCnt; n++ {
					b := testBlobs[(i+n)%len(testBlobs)]
					if !bytes.Equal(b.data, getBlob(b.name, c)) {
						t.Fatalf("CAS %s: Did read invalid data", c.Kind())
					}
				}
			}(i)
		}

		wg.Wait()
	})
}
<|endoftext|>


<commit_before>package render

import (
	"image/color"
	"testing"

	"github.com/oakmound/oak/physics"
	"github.com/stretchr/testify/assert"
)

func TestCompoundFuncs(t *testing.T) {
	cmp := NewSwitch("red", map[string]Modifiable{
		"red":   NewColorBox(5, 5, color.RGBA{255, 0, 0, 255}),
		"blue":  NewColorBox(5, 5, color.RGBA{0, 0, 255, 255}),
		"green": NewColorBox(5, 5, color.RGBA{0, 255, 0, 255}),
		"empty": NewColorBox(5, 5, color.RGBA{0, 0, 0, 0}),
	})
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{255, 0, 0, 255})
	assert.Equal(t, cmp.Get(), "red")
	assert.Nil(t, cmp.Set("blue"))
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{0, 0, 255, 255})
	assert.Equal(t, cmp.Get(), "blue")
	cmp.Add("blue", NewColorBox(5, 5, color.RGBA{255, 255, 255, 255}))
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{255, 255, 255, 255})
	assert.NotNil(t, cmp.Set("color5"))
	assert.Equal(t, cmp.GetSub("empty"), NewColorBox(5, 5, color.RGBA{0, 0, 0, 0}))
	cmp.SetOffsets("Green", physics.NewVector(5, 5))
	cmp2 := cmp.Copy().(*Switch)
	w, h := cmp2.GetDims()
	assert.Equal(t, w, 5)
	assert.Equal(t, h, 5)
	assert.True(t, cmp2.IsStatic())
	assert.True(t, cmp2.IsInterruptable())
}
<commit_msg>Tests for Render switch expanded<commit_after>package render

import (
	"image"
	"image/color"
	"testing"

	"github.com/oakmound/oak/physics"
	"github.com/oakmound/oak/render/mod"
	"github.com/stretchr/testify/assert"
)

func TestCompoundFuncs(t *testing.T) {
	cmp := NewSwitch("red", map[string]Modifiable{
		"red":   NewColorBox(5, 5, color.RGBA{255, 0, 0, 255}),
		"blue":  NewColorBox(5, 5, color.RGBA{0, 0, 255, 255}),
		"green": NewColorBox(5, 5, color.RGBA{0, 255, 0, 255}),
		"empty": NewColorBox(5, 5, color.RGBA{0, 0, 0, 0}),
	})
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{255, 0, 0, 255})
	assert.Equal(t, cmp.Get(), "red")
	assert.Nil(t, cmp.Set("blue"))
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{0, 0, 255, 255})
	assert.Equal(t, cmp.Get(), "blue")
	cmp.Add("blue", NewColorBox(5, 5, color.RGBA{255, 255, 255, 255}))
	assert.Equal(t, cmp.GetRGBA().At(0, 0), color.RGBA{255, 255, 255, 255})
	assert.NotNil(t, cmp.Set("color5"))
	assert.Equal(t, cmp.GetSub("empty"), NewColorBox(5, 5, color.RGBA{0, 0, 0, 0}))

	cmp2 := cmp.Copy().(*Switch)
	w, h := cmp2.GetDims()
	assert.Equal(t, w, 5)
	assert.Equal(t, h, 5)
	assert.True(t, cmp2.IsStatic())
	assert.True(t, cmp2.IsInterruptable())
}

func TestSwitchPositioning(t *testing.T) {
	red := color.RGBA{255, 0, 0, 255}
	blue := color.RGBA{0, 0, 255, 255}
	cmp := NewSwitch("red", map[string]Modifiable{
		"red":  NewColorBox(5, 5, red),
		"blue": NewColorBox(5, 5, blue),
	})
	rgba := image.NewRGBA(image.Rect(0, 0, 10, 10))

	cmp.Draw(rgba)
	assert.Equal(t, red, rgba.At(0, 0))
	assert.NotEqual(t, red, rgba.At(10, 0))

	rgba = image.NewRGBA(image.Rect(0, 0, 10, 10))
	cmp.Set("blue")
	cmp.ShiftPos(1, 1)
	cmp.DrawOffset(rgba, 0, 0)
	assert.Equal(t, blue, rgba.At(1, 1))
	assert.NotEqual(t, blue, rgba.At(0, 0))
	rgba = image.NewRGBA(image.Rect(0, 0, 10, 10))
	cmp.SetOffsets("red", physics.NewVector(5, 5))
	cmp.Set("red")
	cmp.Draw(rgba)
	assert.Equal(t, red, rgba.At(8, 8))
	assert.NotEqual(t, red, rgba.At(1, 1))

}

func TestSwitchModifiability(t *testing.T) {
	cb := NewColorBox(5, 5, color.RGBA{255, 0, 0, 255})
	cmp := NewSwitch("red", map[string]Modifiable{
		"red":  NewReverting(NewColorBox(5, 5, color.RGBA{255, 0, 0, 255})),
		"blue": NewReverting(NewColorBox(5, 5, color.RGBA{0, 0, 255, 255})),
	})

	assert.Equal(t, cb.GetRGBA(), cmp.GetRGBA())
	for _, mod := range neqmods {
		cmp.Modify(mod)
		assert.NotEqual(t, cb.GetRGBA(), cmp.GetRGBA())
		cmp.Revert(1)
		assert.Equal(t, cb.GetRGBA(), cmp.GetRGBA())
	}
	for _, mod := range eqmods {
		cmp.Modify(mod)
		assert.Equal(t, cb.GetRGBA(), cmp.GetRGBA())
	}
	cmp.RevertAll()
	assert.Equal(t, cb.GetRGBA(), cmp.GetRGBA())

	cmp.Filter(mod.Brighten(-100))
	cmp.RevertAll()
	assert.Equal(t, cb.GetRGBA(), cmp.GetRGBA())

}
<|endoftext|>


<commit_before>package ik

import (
	"testing"
)

func TestBuildRegexpFromGlobPattern_0(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.b.c")
	if err != nil {
		t.Fail()
	}
	if a != "a\\.b\\.c" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_1(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.*.c")
	if err != nil {
		t.Fail()
	}
	if a != "a\\.[^.]*\\.c" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_2(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("**c")
	if err != nil {
		t.Fail()
	}
	if a != ".*c" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_3(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("**.c")
	if err != nil {
		t.Fail()
	}
	if a != "(?:.*\\.|^)c" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_4(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.{b,c}.d")
	println(a)
	if err != nil {
		t.Fail()
	}
	if a != "a\\.(?:(?:b)|(?:c))\\.d" {
		t.Fail()
	}
}
<commit_msg>Fix test.<commit_after>package ik

import (
	"testing"
)

func TestBuildRegexpFromGlobPattern_0(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.b.c")
	if err != nil {
		t.Fail()
	}
	if a != "^a\\.b\\.c$" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_1(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.*.c")
	if err != nil {
		t.Fail()
	}
	if a != "^a\\.[^.]*\\.c$" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_2(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("**c")
	if err != nil {
		t.Fail()
	}
	if a != "^.*c$" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_3(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("**.c")
	if err != nil {
		t.Fail()
	}
	if a != "^(?:.*\\.|^)c$" {
		t.Fail()
	}
}

func TestBuildRegexpFromGlobPattern_4(t *testing.T) {
	a, err := BuildRegexpFromGlobPattern("a.{b,c}.d")
	println(a)
	if err != nil {
		t.Fail()
	}
	if a != "^a\\.(?:(?:b)|(?:c))\\.d$" {
		t.Fail()
	}
}
<|endoftext|>


<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 forgetfs_test

import (
	"io"
	"os"
	"path"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/forgetfs"
	. "github.com/jacobsa/ogletest"
)

func TestForgetFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ForgetFSTest struct {
	samples.SampleTest
	fs *forgetfs.ForgetFS
}

func init() { RegisterTestSuite(&ForgetFSTest{}) }

func (t *ForgetFSTest) SetUp(ti *TestInfo) {
	t.fs = forgetfs.NewFileSystem()
	t.Server = t.fs
	t.SampleTest.SetUp(ti)
}

func (t *ForgetFSTest) TearDown() {
	// Unmount.
	t.SampleTest.TearDown()

	// Crash if anything is left.
	t.fs.Check()
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ForgetFSTest) Open_Foo() {
	var err error

	f, err := os.Open(path.Join(t.Dir, "foo"))
	AssertEq(nil, err)

	err = f.Close()
	AssertEq(nil, err)
}

func (t *ForgetFSTest) Open_Bar() {
	var err error

	f, err := os.Open(path.Join(t.Dir, "bar"))
	AssertEq(nil, err)

	err = f.Close()
	AssertEq(nil, err)
}

func (t *ForgetFSTest) Open_ManyTimes() {
	// Set up a slice of files that will be closed when we're done.
	var toClose []io.Closer
	defer func() {
		for _, c := range toClose {
			ExpectEq(nil, c.Close())
		}
	}()

	// Open foo many times.
	for i := 0; i < 100; i++ {
		f, err := os.Open(path.Join(t.Dir, "foo"))
		AssertEq(nil, err)
		toClose = append(toClose, f)
	}

	// Open bar many times.
	for i := 0; i < 100; i++ {
		f, err := os.Open(path.Join(t.Dir, "bar"))
		AssertEq(nil, err)
		toClose = append(toClose, f)
	}
}

func (t *ForgetFSTest) Stat_Foo() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) Stat_Bar() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) Stat_ManyTimes() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) CreateFile() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) MkDir() {
	AssertTrue(false, "TODO")
}
<commit_msg>ForgetFSTest.Stat_Foo<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 forgetfs_test

import (
	"io"
	"os"
	"path"
	"testing"

	"github.com/jacobsa/fuse/samples"
	"github.com/jacobsa/fuse/samples/forgetfs"
	. "github.com/jacobsa/ogletest"
)

func TestForgetFS(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ForgetFSTest struct {
	samples.SampleTest
	fs *forgetfs.ForgetFS
}

func init() { RegisterTestSuite(&ForgetFSTest{}) }

func (t *ForgetFSTest) SetUp(ti *TestInfo) {
	t.fs = forgetfs.NewFileSystem()
	t.Server = t.fs
	t.SampleTest.SetUp(ti)
}

func (t *ForgetFSTest) TearDown() {
	// Unmount.
	t.SampleTest.TearDown()

	// Crash if anything is left.
	t.fs.Check()
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ForgetFSTest) Open_Foo() {
	var err error

	f, err := os.Open(path.Join(t.Dir, "foo"))
	AssertEq(nil, err)

	err = f.Close()
	AssertEq(nil, err)
}

func (t *ForgetFSTest) Open_Bar() {
	var err error

	f, err := os.Open(path.Join(t.Dir, "bar"))
	AssertEq(nil, err)

	err = f.Close()
	AssertEq(nil, err)
}

func (t *ForgetFSTest) Open_ManyTimes() {
	// Set up a slice of files that will be closed when we're done.
	var toClose []io.Closer
	defer func() {
		for _, c := range toClose {
			ExpectEq(nil, c.Close())
		}
	}()

	// Open foo many times.
	for i := 0; i < 100; i++ {
		f, err := os.Open(path.Join(t.Dir, "foo"))
		AssertEq(nil, err)
		toClose = append(toClose, f)
	}

	// Open bar many times.
	for i := 0; i < 100; i++ {
		f, err := os.Open(path.Join(t.Dir, "bar"))
		AssertEq(nil, err)
		toClose = append(toClose, f)
	}
}

func (t *ForgetFSTest) Stat_Foo() {
	var fi os.FileInfo
	var err error

	fi, err = os.Stat(path.Join(t.Dir, "foo"))
	AssertEq(nil, err)
	AssertEq("foo", fi.Name())
	AssertEq(os.FileMode(0777), fi.Mode())
}

func (t *ForgetFSTest) Stat_Bar() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) Stat_ManyTimes() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) CreateFile() {
	AssertTrue(false, "TODO")
}

func (t *ForgetFSTest) MkDir() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>package format

import (
	"reflect"
	"testing"
)

type test_ParseFormat struct {
	formatString string
	format       Format
}

var tests_ParseFormat []test_ParseFormat = []test_ParseFormat{
	{`a`, Format{rawPart{`a`}}},
	{`abc`, Format{rawPart{`abc`}}},
	{`a$$b`, Format{rawPart{`a$b`}}},
	{`${a}`, Format{fieldPart{`a`}}},
	{`b${a}c`, Format{rawPart{`b`}, fieldPart{`a`}, rawPart{`c`}}},
}

func TestParseFormat(t *testing.T) {
	for _, test := range tests_ParseFormat {
		fmt, err := ParseFormat(test.formatString)
		if err != nil {
			t.Errorf("Unexpected error: %s", err.Error())
		}
		if !reflect.DeepEqual(fmt, test.format) {
			t.Errorf("`%s`: expected %v - got %v",
				test.formatString, test.format, fmt)
		}
	}
}

type test_Write struct {
	formatString string
}

var tests_Write []test_Write = []test_Write{}

func TestWrite(t *testing.T) {
	for _, test := range tests_Write {
		println(test.formatString)
	}
}

func TestRead(t *testing.T) {

}
<commit_msg>Stub BenchParseFormat<commit_after>package format

import (
	"reflect"
	"testing"
)

type test_ParseFormat struct {
	formatString string
	format       Format
}

var tests_ParseFormat []test_ParseFormat = []test_ParseFormat{
	{`a`, Format{rawPart{`a`}}},
	{`abc`, Format{rawPart{`abc`}}},
	{`a$$b`, Format{rawPart{`a$b`}}},
	{`${a}`, Format{fieldPart{`a`}}},
	{`b${a}c`, Format{rawPart{`b`}, fieldPart{`a`}, rawPart{`c`}}},
}

func TestParseFormat(t *testing.T) {
	for _, test := range tests_ParseFormat {
		fmt, err := ParseFormat(test.formatString)
		if err != nil {
			t.Errorf("Unexpected error: %s", err.Error())
		}
		if !reflect.DeepEqual(fmt, test.format) {
			t.Errorf("`%s`: expected %v - got %v",
				test.formatString, test.format, fmt)
		}
	}
}

func BenchParseFormat(b *testing.B) {

}

type test_Write struct {
	formatString string
}

var tests_Write []test_Write = []test_Write{}

func TestWrite(t *testing.T) {
	for _, test := range tests_Write {
		println(test.formatString)
	}
}

func TestRead(t *testing.T) {

}
<|endoftext|>


<commit_before>package mdr

import (
	"crypto/md5"
	"crypto/sha256"
	"errors"
	"fmt"
	"hash"
	"hash/crc64"
	"io"
	"os"
	"strconv"
	"strings"
)

var (
	G_crcTable *crc64.Table
)

func init() {
	G_crcTable = crc64.MakeTable(crc64.ECMA)
}

func DigestToString(digest []byte) string {
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	return string(rv)
}

// syntax sugar
func BufCRC64(bufr []byte) uint64 {
	return crc64.Checksum(bufr[:], G_crcTable)
}

func BufMD5(buf []byte) string {
	var h hash.Hash = md5.New()
	h.Write(buf[:])
	digest := h.Sum(nil)
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return DigestToString(digest)
}

func BufSHA256(buf []byte) string {
	var h hash.Hash = sha256.New()
	h.Write(buf[:])
	digest := h.Sum(nil)
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return DigestToString(digest)
}

// reads file in 512KB chunks
func FileCRC64(fname string) (uint64, error) {
	var checksum uint64
	var bufSize = 1024 * 512
	fp, err := os.Open(fname)
	if err != nil {
		return 0, err
		//fmt.Printf("!Err-> can't read %s\n", fname)
		//log.Panicf("!Err-> can't read %s %s\n", fname, err)
	}
	defer fp.Close()
	bufr := make([]byte, bufSize)
	checksum = 0
	for {
		n, err := io.ReadFull(fp, bufr)
		if err != nil {
			if n > 0 {
				// fmt.Printf("not full block but read %d bytes\n",n)
			}
		}
		if err == io.EOF {
			if n != 0 {
				return 0, err
			} else {
				break // normal end of file reached
			}
		}
		// fmt.Printf(" read %d bytes\n",n)
		checksum = crc64.Update(checksum, G_crcTable, bufr[0:n])
		// checksum = crc64.Checksum(bufr[0:n],crcTable)  if entire string in bufr
	}
	return checksum, nil
}

// Compute md5 for given file
// Test is Test_005
func FileMD5(fname string) (string, error) {
	//fmt.Printf("Computing digest for %s\n",fname)
	const NBUF = 1 << 20 // 20 -> 1 MB
	file, err := os.OpenFile(fname, os.O_RDONLY, 0666)
	if file == nil {
		fmt.Printf("!Err--> mdr.FileMD5() can't open file %s as readonly; err=%v\n", fname, err)
		return "", err
	}
	defer file.Close()
	buf := make([]byte, NBUF)
	var h hash.Hash = md5.New()
	for {
		numRead, err := file.Read(buf)
		if (err == io.EOF) && (numRead == 0) {
			break
		} // end of file reached
		if (err != nil) || (numRead < 0) {
			fmt.Fprintf(os.Stderr, "!Err--> mdr.FileMD5: error reading from %s: %v\n", fname, err)
			return "", err
		}
		//		fmt.Printf("read(%d) bytes\n",numRead)
		h.Write(buf[0:numRead])
	}
	digest := h.Sum(nil)
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return string(rv), nil
}

// Compute sha256 for given file
// Test is Test_005
func FileSHA256(fname string) (string, error) {
	//fmt.Printf("Computing digest for %s\n",fname)
	const NBUF = 1 << 20 // 20 -> 1 MB
	file, err := os.OpenFile(fname, os.O_RDONLY, 0666)
	if file == nil {
		fmt.Printf("mdr: FileSHA256() can't open file %s as readonly; err=%v\n", fname, err)
		return "", err
	}
	defer file.Close()
	buf := make([]byte, NBUF)
	var h hash.Hash = sha256.New()
	for {
		numRead, err := file.Read(buf)
		if (err == io.EOF) && (numRead == 0) {
			break
		} // end of file reached
		if (err != nil) || (numRead < 0) {
			fmt.Fprintf(os.Stderr, "error reading from %s: %v\n", fname, err)
			return "", err
		}
		//		fmt.Printf("read(%d) bytes\n",numRead)
		h.Write(buf[0:numRead])
	}
	digest := h.Sum(nil)
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return string(rv), nil
}

var 	CantCreateRec = errors.New("mdr: cant create Rec256 ")

type Rec256 struct {
	Size             int64
	SHA, Date, Name string
}

func Split256(line string) (Rec256, error) {
	var rec Rec256
	var err error
	x := strings.Split(line, "|")
	if len(x) != 4 {
		fmt.Printf("!ERR--->  found other than 4 parts during split of %q\n", line)
		return rec, CantCreateRec
	}
	rec.Size, err = strconv.ParseInt(strings.Trim(x[0], " \n\t\r"), 10, 64)
	if err != nil {
		fmt.Printf("!ERR--->  Cant parse to int64: %s\n", x[0])
		return rec, CantCreateRec
	}
	rec.SHA = strings.Trim(x[1], " \n\t\r")
	if !ValidHexString(rec.SHA) {
		fmt.Printf("!ERR--->  %q is not valid hex \n", rec.SHA)
		return rec, CantCreateRec
	}
	rec.Date = strings.Trim(x[2], " \n\t\r")
	rec.Name = strings.Trim(x[3], " \n\t\r")

	return rec, nil
}
<commit_msg>added dump method<commit_after>package mdr

import (
	"crypto/md5"
	"crypto/sha256"
	"errors"
	"fmt"
	"hash"
	"hash/crc64"
	"io"
	"os"
	"strconv"
	"strings"
)

var (
	G_crcTable *crc64.Table
)

func init() {
	G_crcTable = crc64.MakeTable(crc64.ECMA)
}

func DigestToString(digest []byte) string {
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	return string(rv)
}

// syntax sugar
func BufCRC64(bufr []byte) uint64 {
	return crc64.Checksum(bufr[:], G_crcTable)
}

func BufMD5(buf []byte) string {
	var h hash.Hash = md5.New()
	h.Write(buf[:])
	digest := h.Sum(nil)
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return DigestToString(digest)
}

func BufSHA256(buf []byte) string {
	var h hash.Hash = sha256.New()
	h.Write(buf[:])
	digest := h.Sum(nil)
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return DigestToString(digest)
}

// reads file in 512KB chunks
func FileCRC64(fname string) (uint64, error) {
	var checksum uint64
	var bufSize = 1024 * 512
	fp, err := os.Open(fname)
	if err != nil {
		return 0, err
		//fmt.Printf("!Err-> can't read %s\n", fname)
		//log.Panicf("!Err-> can't read %s %s\n", fname, err)
	}
	defer fp.Close()
	bufr := make([]byte, bufSize)
	checksum = 0
	for {
		n, err := io.ReadFull(fp, bufr)
		if err != nil {
			if n > 0 {
				// fmt.Printf("not full block but read %d bytes\n",n)
			}
		}
		if err == io.EOF {
			if n != 0 {
				return 0, err
			} else {
				break // normal end of file reached
			}
		}
		// fmt.Printf(" read %d bytes\n",n)
		checksum = crc64.Update(checksum, G_crcTable, bufr[0:n])
		// checksum = crc64.Checksum(bufr[0:n],crcTable)  if entire string in bufr
	}
	return checksum, nil
}

// Compute md5 for given file
// Test is Test_005
func FileMD5(fname string) (string, error) {
	//fmt.Printf("Computing digest for %s\n",fname)
	const NBUF = 1 << 20 // 20 -> 1 MB
	file, err := os.OpenFile(fname, os.O_RDONLY, 0666)
	if file == nil {
		fmt.Printf("!Err--> mdr.FileMD5() can't open file %s as readonly; err=%v\n", fname, err)
		return "", err
	}
	defer file.Close()
	buf := make([]byte, NBUF)
	var h hash.Hash = md5.New()
	for {
		numRead, err := file.Read(buf)
		if (err == io.EOF) && (numRead == 0) {
			break
		} // end of file reached
		if (err != nil) || (numRead < 0) {
			fmt.Fprintf(os.Stderr, "!Err--> mdr.FileMD5: error reading from %s: %v\n", fname, err)
			return "", err
		}
		//		fmt.Printf("read(%d) bytes\n",numRead)
		h.Write(buf[0:numRead])
	}
	digest := h.Sum(nil)
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return string(rv), nil
}

// Compute sha256 for given file
// Test is Test_005
func FileSHA256(fname string) (string, error) {
	//fmt.Printf("Computing digest for %s\n",fname)
	const NBUF = 1 << 20 // 20 -> 1 MB
	file, err := os.OpenFile(fname, os.O_RDONLY, 0666)
	if file == nil {
		fmt.Printf("mdr: FileSHA256() can't open file %s as readonly; err=%v\n", fname, err)
		return "", err
	}
	defer file.Close()
	buf := make([]byte, NBUF)
	var h hash.Hash = sha256.New()
	for {
		numRead, err := file.Read(buf)
		if (err == io.EOF) && (numRead == 0) {
			break
		} // end of file reached
		if (err != nil) || (numRead < 0) {
			fmt.Fprintf(os.Stderr, "error reading from %s: %v\n", fname, err)
			return "", err
		}
		//		fmt.Printf("read(%d) bytes\n",numRead)
		h.Write(buf[0:numRead])
	}
	digest := h.Sum(nil)
	rv := ""
	for _, hex := range digest {
		rv = rv + fmt.Sprintf("%02x", hex)
	}
	//fmt.Printf("%s digest ->%s\n",fname,rv)
	return string(rv), nil
}

var 	CantCreateRec = errors.New("mdr: cant create Rec256 ")

type Rec256 struct {
	Size             int64
	SHA, Date, Name string
}

func (r Rec256) Dump() {
	fmt.Printf("%12d | %64s | %s | %s \n",
		r.Size,
		r.SHA,
		r.Date,
		r.Name)
}

func Split256(line string) (Rec256, error) {
	var rec Rec256
	var err error
	x := strings.Split(line, "|")
	if len(x) != 4 {
		fmt.Printf("!ERR--->  found other than 4 parts during split of %q\n", line)
		return rec, CantCreateRec
	}
	rec.Size, err = strconv.ParseInt(strings.Trim(x[0], " \n\t\r"), 10, 64)
	if err != nil {
		fmt.Printf("!ERR--->  Cant parse to int64: %s\n", x[0])
		return rec, CantCreateRec
	}
	rec.SHA = strings.Trim(x[1], " \n\t\r")
	if !ValidHexString(rec.SHA) {
		fmt.Printf("!ERR--->  %q is not valid hex \n", rec.SHA)
		return rec, CantCreateRec
	}
	rec.Date = strings.Trim(x[2], " \n\t\r")
	rec.Name = strings.Trim(x[3], " \n\t\r")

	return rec, nil
}
<|endoftext|>


<commit_before>//go:generate goagen bootstrap -d github.com/ihcsim/bluelens/design

package main

import (
	"os"

	"github.com/goadesign/goa"
	"github.com/goadesign/goa/middleware"
	"github.com/goadesign/goa/middleware/security/basicauth"
	"github.com/ihcsim/bluelens/cmd/blued/app"
	"github.com/ihcsim/bluelens/cmd/blued/middleware/security/apikey"
	log "github.com/sirupsen/logrus"
)

func main() {
	config, err := parseFlags(os.Args[1:])
	if err != nil {
		log.WithFields(log.Fields{
			"Cause": err},
		).Fatal("Error while parsing runtime configuration flags")
	}

	if err := initStore(config); err != nil {
		log.WithFields(log.Fields{
			"Cause": err},
		).Fatal("Error while initializing data store")
	}

	// Create service
	service := goa.New("bluelens")

	// mount security middleware
	app.UseBasicAuthMiddleware(service, basicauth.New(config.user, config.password))
	app.UseAPIKeyMiddleware(service, apikey.New(config.apiKey))

	// Mount middleware
	service.Use(middleware.RequestID())
	service.Use(middleware.LogRequest(true))
	service.Use(middleware.ErrorHandler(service, true))
	service.Use(middleware.Recover())

	// Mount "music" controller
	c := NewMusicController(service)
	app.MountMusicController(service, c)
	// Mount "recommendations" controller
	c2 := NewRecommendationsController(service)
	app.MountRecommendationsController(service, c2)
	// Mount "swagger" controller
	c3 := NewSwaggerController(service)
	app.MountSwaggerController(service, c3)
	// Mount "user" controller
	c4 := NewUserController(service)
	app.MountUserController(service, c4)

	// Start service
	if err := service.ListenAndServe(":8080"); err != nil {
		service.LogError("startup", "err", err)
	}
}
<commit_msg>Do not error out if 'help' flag is provided.<commit_after>//go:generate goagen bootstrap -d github.com/ihcsim/bluelens/design

package main

import (
	"flag"
	"os"

	"github.com/goadesign/goa"
	"github.com/goadesign/goa/middleware"
	"github.com/goadesign/goa/middleware/security/basicauth"
	"github.com/ihcsim/bluelens/cmd/blued/app"
	"github.com/ihcsim/bluelens/cmd/blued/middleware/security/apikey"
	log "github.com/sirupsen/logrus"
)

func main() {
	config, err := parseFlags(os.Args[1:])
	if err != nil {
		if err == flag.ErrHelp {
			os.Exit(0)
		}

		log.WithFields(log.Fields{
			"Cause": err},
		).Fatal("Error while parsing runtime configuration flags")
	}

	if err := initStore(config); err != nil {
		log.WithFields(log.Fields{
			"Cause": err},
		).Fatal("Error while initializing data store")
	}

	// Create service
	service := goa.New("bluelens")

	// mount security middleware
	app.UseBasicAuthMiddleware(service, basicauth.New(config.user, config.password))
	app.UseAPIKeyMiddleware(service, apikey.New(config.apiKey))

	// Mount middleware
	service.Use(middleware.RequestID())
	service.Use(middleware.LogRequest(true))
	service.Use(middleware.ErrorHandler(service, true))
	service.Use(middleware.Recover())

	// Mount "music" controller
	c := NewMusicController(service)
	app.MountMusicController(service, c)
	// Mount "recommendations" controller
	c2 := NewRecommendationsController(service)
	app.MountRecommendationsController(service, c2)
	// Mount "swagger" controller
	c3 := NewSwaggerController(service)
	app.MountSwaggerController(service, c3)
	// Mount "user" controller
	c4 := NewUserController(service)
	app.MountUserController(service, c4)

	// Start service
	if err := service.ListenAndServe(":8080"); err != nil {
		service.LogError("startup", "err", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"os"
	"path/filepath"

	"github.com/bongo-contrib/loaders"
	"github.com/bongo-contrib/models"

	"github.com/gernest/bongo"

	"gopkg.in/fsnotify.v1"

	"github.com/codegangsta/cli"
)

var (
	authors = []cli.Author{
		{"Geofrey Ernest", "geofreyernest@live.com"},
	}
	sourceFlagName = "source"
	appName        = "bongo"
	version        = "0.1.0"
)

func buildFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:   sourceFlagName,
			Usage:  "sets the path to the project soucce files",
			EnvVar: "PROJECT_SOURCE",
		},
	}
}

func build(ctx *cli.Context) {
	wd, _ := os.Getwd()
	src := wd
	if f := ctx.String(sourceFlagName); f != "" {
		src = f
	}
	app := bongo.New()
	err := app.Run(src)
	if err != nil {
		log.Println(err)
	}

}

func serve(ctx *cli.Context) {
	wd, _ := os.Getwd()
	src := wd
	if f := ctx.String(sourceFlagName); f != "" {
		src = f
	}
	app := bongo.New()
	err := app.Run(src)
	if err != nil {
		log.Println(err)
	}
	files, err := loaders.New().Load(src)
	if err != nil {
		log.Fatal(err)
	}
	watch, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watch.Close()
	for _, file := range files {
		watch.Add(file)
	}
	go func() {
		dir := filepath.Join(src, models.OutputDir)
		log.Println("serving website", dir, "  at  http://localhost:8000")
		log.Fatal(http.ListenAndServe(":8000", http.FileServer(http.Dir(dir))))
	}()
	for {
		select {
		case event := <-watch.Events:
			if event.Op&(fsnotify.Rename|fsnotify.Create|fsnotify.Write) > 0 {
				log.Printf("detected change %s  Rebuilding...\n", event.Name)
				app.Run(src)
			}
		case err := <-watch.Errors:
			if err != nil {
				log.Println(err)
			}
		default:
			continue
		}
	}

}

func main() {
	app := cli.NewApp()
	app.Name = appName
	app.Usage = "Eleant static website generator"
	app.Authors = authors
	app.Version = version
	app.Commands = []cli.Command{
		cli.Command{
			Name:        "build",
			ShortName:   "b",
			Usage:       "build site",
			Description: "build site",
			Action:      build,
			Flags:       buildFlags(),
		},
		cli.Command{
			Name:        "serve",
			ShortName:   "s",
			Usage:       "builds and serves the project",
			Description: "serves site",
			Action:      serve,
			Flags:       buildFlags(),
		},
	}
	app.RunAndExitOnError()
}
<commit_msg>refactoring<commit_after>package main

import (
	"log"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gernest/bongo"

	"gopkg.in/fsnotify.v1"

	"github.com/codegangsta/cli"
)

var (
	authors = []cli.Author{
		{"Geofrey Ernest", "geofreyernest@live.com"},
	}
	sourceFlagName = "source"
	appName        = "bongo"
	version        = "0.1.0"
)

func buildFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{
			Name:   sourceFlagName,
			Usage:  "sets the path to the project soucce files",
			EnvVar: "PROJECT_SOURCE",
		},
	}
}

func build(ctx *cli.Context) {
	wd, _ := os.Getwd()
	src := wd
	if f := ctx.String(sourceFlagName); f != "" {
		src = f
	}
	app := bongo.New()
	err := app.Run(src)
	if err != nil {
		log.Println(err)
	}

}

func serve(ctx *cli.Context) {
	wd, _ := os.Getwd()
	src := wd
	if f := ctx.String(sourceFlagName); f != "" {
		src = f
	}
	app := bongo.New()
	err := app.Run(src)
	if err != nil {
		log.Println(err)
	}
	files, err := bongo.NewLoader().Load(src)
	if err != nil {
		log.Fatal(err)
	}
	watch, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watch.Close()
	for _, file := range files {
		watch.Add(file)
	}
	go func() {
		dir := filepath.Join(src, bongo.OutputDir)
		log.Println("serving website", dir, "  at  http://localhost:8000")
		log.Fatal(http.ListenAndServe(":8000", http.FileServer(http.Dir(dir))))
	}()
	for {
		select {
		case event := <-watch.Events:
			if event.Op&(fsnotify.Rename|fsnotify.Create|fsnotify.Write) > 0 {
				log.Printf("detected change %s  Rebuilding...\n", event.Name)
				app.Run(src)
			}
		case err := <-watch.Errors:
			if err != nil {
				log.Println(err)
			}
		default:
			continue
		}
	}

}

func main() {
	app := cli.NewApp()
	app.Name = appName
	app.Usage = "Eleant static website generator"
	app.Authors = authors
	app.Version = version
	app.Commands = []cli.Command{
		cli.Command{
			Name:        "build",
			ShortName:   "b",
			Usage:       "build site",
			Description: "build site",
			Action:      build,
			Flags:       buildFlags(),
		},
		cli.Command{
			Name:        "serve",
			ShortName:   "s",
			Usage:       "builds and serves the project",
			Description: "serves site",
			Action:      serve,
			Flags:       buildFlags(),
		},
	}
	app.RunAndExitOnError()
}
<|endoftext|>


<commit_before>package cmd

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/antham/gommit/gommit"
)

func TestBuildOptionsWithDefaultValues(t *testing.T) {
	opts := buildOptions()

	assert.Equal(t, gommit.Options{SummaryLength: 50, CheckSummaryLength: false, ExcludeMergeCommits: false}, opts)
}

func TestParseDirectoryWithErrors(t *testing.T) {
	_, err := parseDirectory("/test")

	assert.EqualError(t, err, `Ensure "/test" directory exists`)

	_, err = os.Create("/tmp/file")

	assert.NoError(t, err)

	_, err = parseDirectory("/tmp/file")

	assert.EqualError(t, err, `"/tmp/file" must be a directory`)
}

func TestParseDirectorydWithErrors(t *testing.T) {
	path, err := parseDirectory("")

	assert.NoError(t, err)
	assert.Contains(t, path, "antham/gommit")
}
<commit_msg>cmd : remove useless test<commit_after>package cmd

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/antham/gommit/gommit"
)

func TestBuildOptionsWithDefaultValues(t *testing.T) {
	opts := buildOptions()

	assert.Equal(t, gommit.Options{SummaryLength: 50, CheckSummaryLength: false, ExcludeMergeCommits: false}, opts)
}

func TestParseDirectoryWithErrors(t *testing.T) {
	_, err := parseDirectory("/test")

	assert.EqualError(t, err, `Ensure "/test" directory exists`)

	_, err = os.Create("/tmp/file")

	assert.NoError(t, err)

	_, err = parseDirectory("/tmp/file")

	assert.EqualError(t, err, `"/tmp/file" must be a directory`)
}
<|endoftext|>


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

// This file implements the visitor that computes the (line, column)-(line-column) range for each function.

package main

import (
	"bufio"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"text/tabwriter"

	"code.google.com/p/go.tools/cover"
)

// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
// file to write ("" means to write to standard output). The function reads the profile and produces
// as output the coverage data broken down by function, like this:
//
//	fmt/format.go:	init			100.0%
//	fmt/format.go:	computePadding		84.6%
//	...
//	fmt/scan.go:	doScan			100.0%
//	fmt/scan.go:	advance			96.2%
//	fmt/scan.go:	doScanf			96.8%
//	total:		(statements)		91.4%

func funcOutput(profile, outputFile string) error {
	profiles, err := cover.ParseProfiles(profile)
	if err != nil {
		return err
	}

	var out *bufio.Writer
	if outputFile == "" {
		out = bufio.NewWriter(os.Stdout)
	} else {
		fd, err := os.Create(outputFile)
		if err != nil {
			return err
		}
		defer fd.Close()
		out = bufio.NewWriter(fd)
	}
	defer out.Flush()

	tabber := tabwriter.NewWriter(out, 1, 8, 1, '\t', 0)
	defer tabber.Flush()

	var total, covered int64
	for _, profile := range profiles {
		fn := profile.FileName
		file, err := findFile(fn)
		if err != nil {
			return err
		}
		funcs, err := findFuncs(file)
		if err != nil {
			return err
		}
		// Now match up functions and profile blocks.
		for _, f := range funcs {
			c, t := f.coverage(profile)
			fmt.Fprintf(tabber, "%s:\t%s\t%.1f%%\n", fn, f.name, 100.0*float64(c)/float64(t))
			total += t
			covered += c
		}
	}
	fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", 100.0*float64(covered)/float64(total))

	return nil
}

// findFuncs parses the file and returns a slice of FuncExtent descriptors.
func findFuncs(name string) ([]*FuncExtent, error) {
	fset := token.NewFileSet()
	parsedFile, err := parser.ParseFile(fset, name, nil, 0)
	if err != nil {
		return nil, err
	}
	visitor := &FuncVisitor{
		fset:    fset,
		name:    name,
		astFile: parsedFile,
	}
	ast.Walk(visitor, visitor.astFile)
	return visitor.funcs, nil
}

// FuncExtent describes a function's extent in the source by file and position.
type FuncExtent struct {
	name      string
	startLine int
	startCol  int
	endLine   int
	endCol    int
}

// FuncVisitor implements the visitor that builds the function position list for a file.
type FuncVisitor struct {
	fset    *token.FileSet
	name    string // Name of file.
	astFile *ast.File
	funcs   []*FuncExtent
}

// Visit implements the ast.Visitor interface.
func (v *FuncVisitor) Visit(node ast.Node) ast.Visitor {
	switch n := node.(type) {
	case *ast.FuncDecl:
		start := v.fset.Position(n.Pos())
		end := v.fset.Position(n.End())
		fe := &FuncExtent{
			name:      n.Name.Name,
			startLine: start.Line,
			startCol:  start.Column,
			endLine:   end.Line,
			endCol:    end.Column,
		}
		v.funcs = append(v.funcs, fe)
	}
	return v
}

// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
func (f *FuncExtent) coverage(profile *cover.Profile) (num, den int64) {
	// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
	// but the sizes of the data structures is never very large and the scan is almost instantaneous.
	var covered, total int64
	// The blocks are sorted, so we can stop counting as soon as we reach the end of the relevant block.
	for _, b := range profile.Blocks {
		if b.StartLine > f.endLine || (b.StartLine == f.endLine && b.StartCol >= f.endCol) {
			// Past the end of the function.
			break
		}
		if b.EndLine < f.startLine || (b.EndLine == f.startLine && b.EndCol <= f.startCol) {
			// Before the beginning of the function
			continue
		}
		total += int64(b.NumStmt)
		if b.Count > 0 {
			covered += int64(b.NumStmt)
		}
	}
	if total == 0 {
		total = 1 // Avoid zero denominator.
	}
	return covered, total
}

// findFile finds the location of the named file in GOROOT, GOPATH etc.
func findFile(file string) (string, error) {
	dir, file := filepath.Split(file)
	pkg, err := build.Import(dir, ".", build.FindOnly)
	if err != nil {
		return "", fmt.Errorf("can't find %q: %v", file, err)
	}
	return filepath.Join(pkg.Dir, file), nil
}
<commit_msg>cmd/cover: add start lines numbers to each function in -func mode<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements the visitor that computes the (line, column)-(line-column) range for each function.

package main

import (
	"bufio"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"text/tabwriter"

	"code.google.com/p/go.tools/cover"
)

// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
// file to write ("" means to write to standard output). The function reads the profile and produces
// as output the coverage data broken down by function, like this:
//
//	fmt/format.go:30:	init			100.0%
//	fmt/format.go:57:	clearflags		100.0%
//	...
//	fmt/scan.go:1046:	doScan			100.0%
//	fmt/scan.go:1075:	advance			96.2%
//	fmt/scan.go:1119:	doScanf			96.8%
//	total:		(statements)			91.9%

func funcOutput(profile, outputFile string) error {
	profiles, err := cover.ParseProfiles(profile)
	if err != nil {
		return err
	}

	var out *bufio.Writer
	if outputFile == "" {
		out = bufio.NewWriter(os.Stdout)
	} else {
		fd, err := os.Create(outputFile)
		if err != nil {
			return err
		}
		defer fd.Close()
		out = bufio.NewWriter(fd)
	}
	defer out.Flush()

	tabber := tabwriter.NewWriter(out, 1, 8, 1, '\t', 0)
	defer tabber.Flush()

	var total, covered int64
	for _, profile := range profiles {
		fn := profile.FileName
		file, err := findFile(fn)
		if err != nil {
			return err
		}
		funcs, err := findFuncs(file)
		if err != nil {
			return err
		}
		// Now match up functions and profile blocks.
		for _, f := range funcs {
			c, t := f.coverage(profile)
			fmt.Fprintf(tabber, "%s:%d:\t%s\t%.1f%%\n", fn, f.startLine, f.name, 100.0*float64(c)/float64(t))
			total += t
			covered += c
		}
	}
	fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", 100.0*float64(covered)/float64(total))

	return nil
}

// findFuncs parses the file and returns a slice of FuncExtent descriptors.
func findFuncs(name string) ([]*FuncExtent, error) {
	fset := token.NewFileSet()
	parsedFile, err := parser.ParseFile(fset, name, nil, 0)
	if err != nil {
		return nil, err
	}
	visitor := &FuncVisitor{
		fset:    fset,
		name:    name,
		astFile: parsedFile,
	}
	ast.Walk(visitor, visitor.astFile)
	return visitor.funcs, nil
}

// FuncExtent describes a function's extent in the source by file and position.
type FuncExtent struct {
	name      string
	startLine int
	startCol  int
	endLine   int
	endCol    int
}

// FuncVisitor implements the visitor that builds the function position list for a file.
type FuncVisitor struct {
	fset    *token.FileSet
	name    string // Name of file.
	astFile *ast.File
	funcs   []*FuncExtent
}

// Visit implements the ast.Visitor interface.
func (v *FuncVisitor) Visit(node ast.Node) ast.Visitor {
	switch n := node.(type) {
	case *ast.FuncDecl:
		start := v.fset.Position(n.Pos())
		end := v.fset.Position(n.End())
		fe := &FuncExtent{
			name:      n.Name.Name,
			startLine: start.Line,
			startCol:  start.Column,
			endLine:   end.Line,
			endCol:    end.Column,
		}
		v.funcs = append(v.funcs, fe)
	}
	return v
}

// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
func (f *FuncExtent) coverage(profile *cover.Profile) (num, den int64) {
	// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
	// but the sizes of the data structures is never very large and the scan is almost instantaneous.
	var covered, total int64
	// The blocks are sorted, so we can stop counting as soon as we reach the end of the relevant block.
	for _, b := range profile.Blocks {
		if b.StartLine > f.endLine || (b.StartLine == f.endLine && b.StartCol >= f.endCol) {
			// Past the end of the function.
			break
		}
		if b.EndLine < f.startLine || (b.EndLine == f.startLine && b.EndCol <= f.startCol) {
			// Before the beginning of the function
			continue
		}
		total += int64(b.NumStmt)
		if b.Count > 0 {
			covered += int64(b.NumStmt)
		}
	}
	if total == 0 {
		total = 1 // Avoid zero denominator.
	}
	return covered, total
}

// findFile finds the location of the named file in GOROOT, GOPATH etc.
func findFile(file string) (string, error) {
	dir, file := filepath.Split(file)
	pkg, err := build.Import(dir, ".", build.FindOnly)
	if err != nil {
		return "", fmt.Errorf("can't find %q: %v", file, err)
	}
	return filepath.Join(pkg.Dir, file), nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"io"
	"os"

	cmds "github.com/jbenet/go-ipfs/commands"
	config "github.com/jbenet/go-ipfs/config"
	internal "github.com/jbenet/go-ipfs/core/commands2/internal"
	tour "github.com/jbenet/go-ipfs/tour"
	"github.com/jbenet/go-ipfs/util"
)

// TODO the parent function now uses tourOutput. Migrate the children to also
// use the tourOutput struct

var tourCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "An introduction to IPFS",
		ShortDescription: `
This is a tour that takes you through various IPFS concepts,
features, and tools to make sure you get up to speed with
IPFS very quickly. To start, run:

    ipfs tour
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("number", false, false, "The number of the topic you would like to tour"),
	},
	Subcommands: map[string]*cmds.Command{
		"list":    cmdIpfsTourList,
		"next":    cmdIpfsTourNext,
		"restart": cmdIpfsTourRestart,
	},
	Run: tourRunFunc,
	Marshalers: cmds.MarshalerMap{
		cmds.Text: tourTextMarshaler,
	},
	Type: &tourOutput{},
}

// tourOutput is a union type. It either contains a Topic or it contains the
// list of Topics and an Error.
type tourOutput struct {
	Topic *tour.Topic

	Topics []tour.Topic
	Error  error
}

func tourTextMarshaler(r cmds.Response) ([]byte, error) {
	output, ok := r.Output().(*tourOutput)
	if !ok {
		return nil, util.ErrCast()
	}
	// can be listing when error
	var buf bytes.Buffer
	err := printTourOutput(&buf, output)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func printTourOutput(w io.Writer, output *tourOutput) error {
	tmpl := `{{ if .Error }}
ERROR
	{{ .Error }}
TOPICS
	{{ range $topic := .Topics }}
	{{ $topic.ID }} - {{ $topic.Title }} {{ end }}
{{ else if .Topic }}
Tour {{ .Topic.ID }} - {{ .Topic.Title }}

{{ .Topic.Text }}
{{ end }}
`
	tourTmpl, err := template.New("tour").Parse(tmpl)
	if err != nil {
		return err
	}
	return tourTmpl.Execute(w, output)
}

func tourRunFunc(req cmds.Request) (interface{}, error) {

	cfg, err := req.Context().GetConfig()
	if err != nil {
		return nil, err
	}

	strs, err := internal.CastToStrings(req.Arguments())
	if err != nil {
		return nil, err
	}

	id := tour.TopicID(cfg.Tour.Last)
	if len(strs) > 0 {
		id = tour.TopicID(strs[0])
	}

	t, err := tourGet(id)
	if err != nil {

		// If no topic exists for this id, we handle this error right here.
		// To help the user achieve the task, we construct a response
		// comprised of...
		// 1) a simple error message
		// 2) the full list of topics

		output := &tourOutput{
			Error: err,
		}
		for _, id := range tour.IDs {
			t, ok := tour.Topics[id]
			if !ok {
				return nil, err
			}
			output.Topics = append(output.Topics, t)
		}

		return output, nil
		// return nil, cmds.ClientError(err.Error())
	}

	return &tourOutput{Topic: t}, nil
}

// TODO use tourOutput like parent command
var cmdIpfsTourNext = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show the next IPFS Tour topic",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		var w bytes.Buffer
		path := req.Context().ConfigRoot
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		id := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
		topic, err := tourGet(id)
		if err != nil {
			return nil, err
		}
		if err := tourShow(&w, topic); err != nil {
			return nil, err
		}

		// topic changed, not last. write it out.
		if string(id) != cfg.Tour.Last {
			cfg.Tour.Last = string(id)
			err := writeConfig(path, cfg)
			if err != nil {
				return nil, err
			}
		}

		w.WriteTo(os.Stdout) // TODO write to res.SetValue
		return w, nil
	},
}

var cmdIpfsTourRestart = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Restart the IPFS Tour",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		path := req.Context().ConfigRoot
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		cfg.Tour.Last = ""
		err = writeConfig(path, cfg)
		if err != nil {
			return nil, err
		}
		return nil, nil
	},
}

// TODO use tourOutput like parent command
var cmdIpfsTourList = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show a list of IPFS Tour topics",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		var w bytes.Buffer
		tourListCmd(&w, cfg)
		w.WriteTo(os.Stdout) // TODO use res.SetOutput(output)
		return nil, nil
	},
}

func tourListCmd(w io.Writer, cfg *config.Config) {

	lastid := tour.TopicID(cfg.Tour.Last)
	for _, id := range tour.IDs {
		c := ' '
		switch {
		case id == lastid:
			c = '*'
		case id.LessThan(lastid):
			c = '✓'
		}

		t := tour.Topics[id]
		fmt.Fprintf(w, "- %c %-5.5s %s\n", c, id, t.Title)
	}
}

func tourShow(w io.Writer, t *tour.Topic) error {
	tmpl := `
Tour {{ .ID }} - {{ .Title }}

{{ .Text }}

`
	ttempl, err := template.New("tour").Parse(tmpl)
	if err != nil {
		return err
	}
	return ttempl.Execute(w, t)
}

// tourGet returns an error if topic does not exist
func tourGet(id tour.ID) (*tour.Topic, error) {
	t, found := tour.Topics[id]
	if !found {
		return nil, fmt.Errorf("no topic with id: %s", id)
	}
	return &t, nil
}

// TODO share func
func writeConfig(path string, cfg *config.Config) error {
	filename, err := config.Filename(path)
	if err != nil {
		return err
	}
	return config.WriteConfigFile(filename, cfg)
}
<commit_msg>fix(tour) patch up and verify tour output<commit_after>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"io"
	"os"

	cmds "github.com/jbenet/go-ipfs/commands"
	config "github.com/jbenet/go-ipfs/config"
	internal "github.com/jbenet/go-ipfs/core/commands2/internal"
	tour "github.com/jbenet/go-ipfs/tour"
	"github.com/jbenet/go-ipfs/util"
)

// TODO the parent function now uses tourOutput. Migrate the children to also
// use the tourOutput struct

var tourCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "An introduction to IPFS",
		ShortDescription: `
This is a tour that takes you through various IPFS concepts,
features, and tools to make sure you get up to speed with
IPFS very quickly. To start, run:

    ipfs tour
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("number", false, false, "The number of the topic you would like to tour"),
	},
	Subcommands: map[string]*cmds.Command{
		"list":    cmdIpfsTourList,
		"next":    cmdIpfsTourNext,
		"restart": cmdIpfsTourRestart,
	},
	Run: tourRunFunc,
	Marshalers: cmds.MarshalerMap{
		cmds.Text: tourTextMarshaler,
	},
	Type: &tourOutput{},
}

// tourOutput is a union type. It either contains a Topic or it contains the
// list of Topics and an Error.
type tourOutput struct {
	Last tour.ID

	Topic *tour.Topic

	Topics []tour.Topic
	Error  error
}

func tourTextMarshaler(r cmds.Response) ([]byte, error) {
	output, ok := r.Output().(*tourOutput)
	if !ok {
		return nil, util.ErrCast()
	}
	// can be listing when error
	var buf bytes.Buffer
	err := printTourOutput(&buf, output)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func printTourOutput(w io.Writer, output *tourOutput) error {
	if output.Error != nil {
		fmt.Fprintln(w, "ERROR")
		fmt.Fprintln(w, output.Error.Error())
		fmt.Fprintln(w, "")
		fprintTourList(w, output.Last)
		return nil // TODO err
	}
	return fprintTourShow(w, output.Topic)
}

func tourRunFunc(req cmds.Request) (interface{}, error) {

	cfg, err := req.Context().GetConfig()
	if err != nil {
		return nil, err
	}

	strs, err := internal.CastToStrings(req.Arguments())
	if err != nil {
		return nil, err
	}

	id := tour.TopicID(cfg.Tour.Last)
	if len(strs) > 0 {
		id = tour.TopicID(strs[0])
	}

	t, err := tourGet(id)
	if err != nil {

		// If no topic exists for this id, we handle this error right here.
		// To help the user achieve the task, we construct a response
		// comprised of...
		// 1) a simple error message
		// 2) the full list of topics

		output := &tourOutput{
			Error: err,
			Last:  tour.TopicID(cfg.Tour.Last),
		}

		return output, nil
	}

	return &tourOutput{Topic: t}, nil
}

var cmdIpfsTourNext = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show the next IPFS Tour topic",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		var w bytes.Buffer
		path := req.Context().ConfigRoot
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		id := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
		topic, err := tourGet(id)
		if err != nil {
			return nil, err
		}
		if err := fprintTourShow(&w, topic); err != nil {
			return nil, err
		}

		// topic changed, not last. write it out.
		if string(id) != cfg.Tour.Last {
			cfg.Tour.Last = string(id)
			err := writeConfig(path, cfg)
			if err != nil {
				return nil, err
			}
		}

		w.WriteTo(os.Stdout)
		return nil, nil
	},
}

var cmdIpfsTourRestart = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Restart the IPFS Tour",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		path := req.Context().ConfigRoot
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		cfg.Tour.Last = ""
		err = writeConfig(path, cfg)
		if err != nil {
			return nil, err
		}
		return nil, nil
	},
}

var cmdIpfsTourList = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show a list of IPFS Tour topics",
	},

	Run: func(req cmds.Request) (interface{}, error) {
		cfg, err := req.Context().GetConfig()
		if err != nil {
			return nil, err
		}

		var w bytes.Buffer
		fprintTourList(&w, tour.TopicID(cfg.Tour.Last))
		w.WriteTo(os.Stdout) // TODO use res.SetOutput(output)
		return nil, nil
	},
}

func fprintTourList(w io.Writer, lastid tour.ID) {
	for _, id := range tour.IDs {
		c := ' '
		switch {
		case id == lastid:
			c = '*'
		case id.LessThan(lastid):
			c = '✓'
		}

		t := tour.Topics[id]
		fmt.Fprintf(w, "- %c %-5.5s %s\n", c, id, t.Title)
	}
}

// fprintTourShow writes a text-formatted topic to the writer
func fprintTourShow(w io.Writer, t *tour.Topic) error {
	tmpl := `
Tour {{ .ID }} - {{ .Title }}

{{ .Text }}

`
	ttempl, err := template.New("tour").Parse(tmpl)
	if err != nil {
		return err
	}
	return ttempl.Execute(w, t)
}

// tourGet returns the topic given its ID. Returns an error if topic does not
// exist.
func tourGet(id tour.ID) (*tour.Topic, error) {
	t, found := tour.Topics[id]
	if !found {
		return nil, fmt.Errorf("no topic with id: %s", id)
	}
	return &t, nil
}

// TODO share func
func writeConfig(path string, cfg *config.Config) error {
	filename, err := config.Filename(path)
	if err != nil {
		return err
	}
	return config.WriteConfigFile(filename, cfg)
}
<|endoftext|>


<commit_before>// 7 july 2014

package ui

// Button is a clickable button that performs some task.
type Button interface {
	Control

	// OnClicked sets the event handler for when the Button is clicked.
	OnClicked(func())

	// Text and SetText get and set the Button's label text.
	Text() string
	SetText(text string)
}

// NewButton creates a new Button with the given label text.
func NewButton(text string) Button {
	return newButton(text)
}

// Checkbox is a clickable box that indicates some Boolean value.
type Checkbox interface {
	Control

	// OnToggled sets the event handler for when the Checkbox is toggled.
	OnToggled(func())

	// Text and SetText get and set the Checkbox's label text.
	Text() string
	SetText(text string)

	// Checked and SetChecked get and set the Checkbox's check state.
	Checked() bool
	SetChecked(checked bool)
}

// NewCheckbox creates a new Checkbox with the given label text.
// The Checkbox will be initially unchecked.
func NewCheckbox(text string) Checkbox {
	return newCheckbox(text)
}

// TextField is a Control in which the user can enter a single line of text.
type TextField interface {
	Control

	// Text and SetText are Requests that get and set the TextField's text.
	Text() string
	SetText(text string)

	// OnChanged is triggered when the text in a TextField is changed somehow.
	// Do not bother trying to figure out how the text was changed; instead, perform your validation and use Invalid to inform the user that the entered text is invalid instead.
	OnChanged(func())

	// Invalid throws a non-modal alert (whose nature is system-defined) on or near the TextField that alerts the user that input is invalid.
	// The string passed to Invalid will be displayed to the user to inform them of what specifically is wrong with the input.
	// Pass an empty string to remove the warning.
	Invalid(reason string)

	// ReadOnly and SetReadOnly get and set whether the TextField is read-only.
	// A read-only TextField cannot be changed by the user, but its text can still be manipulated in other ways (selecting, copying, etc.).
	ReadOnly() bool
	SetReadOnly(readonly bool)
}

// NewTextField creates a new TextField.
func NewTextField() TextField {
	return newTextField()
}

// NewPasswordField creates a new TextField for entering passwords; that is, it hides the text being entered.
func NewPasswordField() TextField {
	return newPasswordField()
}

// Tab is a Control that contains multiple pages of tabs, each containing a single Control.
// You can add and remove tabs from the Tab at any time.
// The appearance of a Tab with no tabs is implementation-defined.
type Tab interface {
	Control

	// Append adds a new tab to Tab.
	// The tab is added to the end of the current list of tabs.
	Append(name string, control Control)
}

// NewTab creates a new Tab with no tabs.
func NewTab() Tab {
	return newTab()
}

// Label is a Control that shows a static line of text.
// Label shows one line of text; any text that does not fit is truncated.
// Labels are left-aligned. [FUTURE PLANS: For platform-specific horizontal alignment rules, use a Form.]
type Label interface {
	Control

	// Text and SetText get and set the Label's text.
	Text() string
	SetText(text string)
}

// NewLabel creates a new Label with the given text.
func NewLabel(text string) Label {
	return newLabel(text)
}

// Group is a Control that holds a single Control; if that Control also contains other Controls, then the Controls will appear visually grouped together.
// The appearance of a Group varies from system to system; for the most part a Group consists of a thin frame.
// All Groups have a text label indicating what the Group is for.
type Group interface {
	Control

	// Text and SetText get and set the Group's label text.
	Text() string
	SetText(text string)

	// Margined and SetMargined get and set whether the contents of the Group have a margin around them.
	// The size of the margin is platform-dependent.
	Margined() bool
	SetMargined(margined bool)
}

// NewGroup creates a new Group with the given text label and child Control.
func NewGroup(text string, control Control) Group {
	return newGroup(text, control)
}

// Textbox represents a multi-line text entry box.
// Text in a Textbox is unformatted, and scrollbars are applied automatically.
// TODO rename to TextBox? merge with TextField (but cannot use Invalid())? enable/disable line wrapping?
// TODO events
// TODO Tab key - insert horizontal tab or tab stop?
// TODO ReadOnly
type Textbox interface {
	Control

	// Text and SetText get and set the Textbox's text.
	Text() string
	SetText(text string)
}

// NewTextbox creates a new Textbox.
func NewTextbox() Textbox {
	return newTextbox()
}

// Spinbox is a Control that provides a text entry field that accepts integers and up and down buttons to increment and decrement those values.
// This control is in its preliminary state.
// TODO everything:
// - TODO set increment? (work on windows)
// - TODO set page step?
// - TODO wrapping
// - TODO negative values
type Spinbox interface {
	Control

	// Value and SetValue get and set the current value of the Spinbox, respectively.
	// For SetValue, if the new value is outside the current range of the Spinbox, it is set to the nearest extremity.
	Value() int
	SetValue(value int)

	// OnChanged sets the event handler for when the Spinbox's value is changed.
	// Under what conditions this event is raised when the user types into the Spinbox's edit field is platform-defined.
	OnChanged(func())
}

// NewSpinbox creates a new Spinbox with the given minimum and maximum.
// The initial value will be the minimum value.
// NewSpinbox() panics if min > max.
func NewSpinbox(min int, max int) Spinbox {
	if min > max {
		panic("min > max in NewSpinbox()")
	}
	return newSpinbox(min, max)
}

// ProgressBar is a Control that displays a horizontal bar which shows the level of completion of an operation.
// TODO indetermiante
type ProgressBar interface {
	Control

	// Percent and SetPrecent get and set the current percentage indicated by the ProgressBar, respectively.
	// This value must be between 0 and 100; all other values cause SetPercent to panic.
	// TODO rename to Progress/SetProgress?
	Percent() int
	SetPercent(percent int)
}

// NewProgressBar creates a new ProgressBar.
// It will initially show a progress of 0%.
func NewProgressBar() ProgressBar {
	return newProgressBar()
}
<commit_msg>More TODOs.<commit_after>// 7 july 2014

package ui

// Button is a clickable button that performs some task.
type Button interface {
	Control

	// OnClicked sets the event handler for when the Button is clicked.
	OnClicked(func())

	// Text and SetText get and set the Button's label text.
	Text() string
	SetText(text string)
}

// NewButton creates a new Button with the given label text.
func NewButton(text string) Button {
	return newButton(text)
}

// Checkbox is a clickable box that indicates some Boolean value.
type Checkbox interface {
	Control

	// OnToggled sets the event handler for when the Checkbox is toggled.
	OnToggled(func())

	// Text and SetText get and set the Checkbox's label text.
	Text() string
	SetText(text string)

	// Checked and SetChecked get and set the Checkbox's check state.
	Checked() bool
	SetChecked(checked bool)
}

// NewCheckbox creates a new Checkbox with the given label text.
// The Checkbox will be initially unchecked.
func NewCheckbox(text string) Checkbox {
	return newCheckbox(text)
}

// TextField is a Control in which the user can enter a single line of text.
type TextField interface {
	Control

	// Text and SetText are Requests that get and set the TextField's text.
	Text() string
	SetText(text string)

	// OnChanged is triggered when the text in a TextField is changed somehow.
	// Do not bother trying to figure out how the text was changed; instead, perform your validation and use Invalid to inform the user that the entered text is invalid instead.
	OnChanged(func())

	// Invalid throws a non-modal alert (whose nature is system-defined) on or near the TextField that alerts the user that input is invalid.
	// The string passed to Invalid will be displayed to the user to inform them of what specifically is wrong with the input.
	// Pass an empty string to remove the warning.
	Invalid(reason string)

	// ReadOnly and SetReadOnly get and set whether the TextField is read-only.
	// A read-only TextField cannot be changed by the user, but its text can still be manipulated in other ways (selecting, copying, etc.).
	ReadOnly() bool
	SetReadOnly(readonly bool)
}

// NewTextField creates a new TextField.
func NewTextField() TextField {
	return newTextField()
}

// NewPasswordField creates a new TextField for entering passwords; that is, it hides the text being entered.
func NewPasswordField() TextField {
	return newPasswordField()
}

// Tab is a Control that contains multiple pages of tabs, each containing a single Control.
// You can add and remove tabs from the Tab at any time.
// The appearance of a Tab with no tabs is implementation-defined.
type Tab interface {
	Control

	// Append adds a new tab to Tab.
	// The tab is added to the end of the current list of tabs.
	Append(name string, control Control)
}

// NewTab creates a new Tab with no tabs.
func NewTab() Tab {
	return newTab()
}

// Label is a Control that shows a static line of text.
// Label shows one line of text; any text that does not fit is truncated.
// Labels are left-aligned. [FUTURE PLANS: For platform-specific horizontal alignment rules, use a Form.]
type Label interface {
	Control

	// Text and SetText get and set the Label's text.
	Text() string
	SetText(text string)
}

// NewLabel creates a new Label with the given text.
func NewLabel(text string) Label {
	return newLabel(text)
}

// Group is a Control that holds a single Control; if that Control also contains other Controls, then the Controls will appear visually grouped together.
// The appearance of a Group varies from system to system; for the most part a Group consists of a thin frame.
// All Groups have a text label indicating what the Group is for.
type Group interface {
	Control

	// Text and SetText get and set the Group's label text.
	Text() string
	SetText(text string)

	// Margined and SetMargined get and set whether the contents of the Group have a margin around them.
	// The size of the margin is platform-dependent.
	Margined() bool
	SetMargined(margined bool)
}

// NewGroup creates a new Group with the given text label and child Control.
func NewGroup(text string, control Control) Group {
	return newGroup(text, control)
}

// Textbox represents a multi-line text entry box.
// Text in a Textbox is unformatted, and scrollbars are applied automatically.
// TODO rename to TextBox? merge with TextField (but cannot use Invalid())? enable/disable line wrapping?
// TODO events
// TODO Tab key - insert horizontal tab or tab stop?
// TODO ReadOnly
// TODO line endings
type Textbox interface {
	Control

	// Text and SetText get and set the Textbox's text.
	Text() string
	SetText(text string)
}

// NewTextbox creates a new Textbox.
func NewTextbox() Textbox {
	return newTextbox()
}

// Spinbox is a Control that provides a text entry field that accepts integers and up and down buttons to increment and decrement those values.
// This control is in its preliminary state.
// TODO everything:
// - TODO set increment? (work on windows)
// - TODO set page step?
// - TODO wrapping
// - TODO negative values
type Spinbox interface {
	Control

	// Value and SetValue get and set the current value of the Spinbox, respectively.
	// For SetValue, if the new value is outside the current range of the Spinbox, it is set to the nearest extremity.
	Value() int
	SetValue(value int)

	// OnChanged sets the event handler for when the Spinbox's value is changed.
	// Under what conditions this event is raised when the user types into the Spinbox's edit field is platform-defined.
	OnChanged(func())
}

// NewSpinbox creates a new Spinbox with the given minimum and maximum.
// The initial value will be the minimum value.
// NewSpinbox() panics if min > max.
func NewSpinbox(min int, max int) Spinbox {
	if min > max {
		panic("min > max in NewSpinbox()")
	}
	return newSpinbox(min, max)
}

// ProgressBar is a Control that displays a horizontal bar which shows the level of completion of an operation.
// TODO indetermiante
type ProgressBar interface {
	Control

	// Percent and SetPrecent get and set the current percentage indicated by the ProgressBar, respectively.
	// This value must be between 0 and 100; all other values cause SetPercent to panic.
	// TODO rename to Progress/SetProgress?
	Percent() int
	SetPercent(percent int)
}

// NewProgressBar creates a new ProgressBar.
// It will initially show a progress of 0%.
func NewProgressBar() ProgressBar {
	return newProgressBar()
}
<|endoftext|>