<commit_before>package leakybucket

import (
	"math"
	"reflect"
	"sync"
	"testing"
	"time"
)

// CreateTest returns a test of bucket creation for a given storage backend.
// It is meant to be used by leakybucket implementers who wish to test this.
func CreateTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		now := time.Now()
		bucket, err := s.Create("testbucket", 100, time.Minute)
		if err != nil {
			t.Fatal(err)
		}
		if capacity := bucket.Capacity(); capacity != 100 {
			t.Fatalf("expected capacity of %d, got %d", 100, capacity)
		}
		e := float64(1 * time.Second) // margin of error
		if error := float64(bucket.Reset().Sub(now.Add(time.Minute))); math.Abs(error) > e {
			t.Fatalf("expected reset time close to %s, got %s", now.Add(time.Minute),
				bucket.Reset())
		}
	}
}

// AddTest returns a test that adding to a single bucket works.
// It is meant to be used by leakybucket implementers who wish to test this.
func AddTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		bucket, err := s.Create("testbucket", 10, time.Minute)
		if err != nil {
			t.Fatal(err)
		}

		addAndTestRemaining := func(add, remaining uint) {
			if state, err := bucket.Add(add); err != nil {
				t.Fatal(err)
			} else if bucket.Remaining() != state.Remaining {
				t.Fatalf("expected bucket and state remaining to match, bucket is %d, state is %d",
					bucket.Remaining(), state.Remaining)
			} else if state.Remaining != remaining {
				t.Fatalf("expected %d remaining, got %d", remaining, state.Remaining)
			}
		}

		addAndTestRemaining(1, 9)
		addAndTestRemaining(3, 6)
		addAndTestRemaining(6, 0)

		if _, err := bucket.Add(1); err == nil {
			t.Fatalf("expected ErrorFull, received no error")
		} else if err != ErrorFull {
			t.Fatalf("expected ErrorFull, received %v", err)
		}
	}
}

// ThreadSafeAddTest returns a test that adding to a single bucket is thread-safe.
// It is meant to be used by leakybucket implementers who wish to test this.
func ThreadSafeAddTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		// Make a bucket of size `n`. Spawn `n+1` goroutines that each try to take one token.
		// We should see the bucket transition through having `n-1`, `n-2`, ... 0 remaining capacity.
		// We should also witness one error when the bucket has reached capacity.
		n := 100
		bucket, err := s.Create("testbucket", uint(n), time.Minute)
		if err != nil {
			t.Fatal(err)
		}
		remaining := map[uint]bool{}     // record observed "remaining" counts. (ab)using map as set here
		remainingMutex := sync.RWMutex{} // maps are not threadsafe
		errors := []error{}              // record observed errors
		var wg sync.WaitGroup
		for i := 0; i < n+1; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				state, err := bucket.Add(1)
				if err != nil {
					errors = append(errors, err)
				} else {
					remainingMutex.Lock()
					defer remainingMutex.Unlock()
					remaining[state.Remaining] = true
				}
			}()
		}
		wg.Wait()
		keys := reflect.ValueOf(remaining).MapKeys()
		if len(remaining) != n {
			string_keys := []int{}
			for key := range keys {
				string_keys = append(string_keys, key)
			}
			t.Fatalf("Did not observe correct bucket states. Saw %d distinct remaining values instead of %d: %#v",
				len(remaining), n, string_keys)
		}
		if len(errors) != 1 && errors[0] != ErrorFull {
			t.Fatalf("Did not observe one full error: %#v", errors)
		}
	}
}
<commit_msg>test: ThreadSafeAdd: fix wrong remaining vals<commit_after>package leakybucket

import (
	"log"
	"math"
	"sync"
	"testing"
	"time"
)

// CreateTest returns a test of bucket creation for a given storage backend.
// It is meant to be used by leakybucket implementers who wish to test this.
func CreateTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		now := time.Now()
		bucket, err := s.Create("testbucket", 100, time.Minute)
		if err != nil {
			t.Fatal(err)
		}
		if capacity := bucket.Capacity(); capacity != 100 {
			t.Fatalf("expected capacity of %d, got %d", 100, capacity)
		}
		e := float64(1 * time.Second) // margin of error
		if error := float64(bucket.Reset().Sub(now.Add(time.Minute))); math.Abs(error) > e {
			t.Fatalf("expected reset time close to %s, got %s", now.Add(time.Minute),
				bucket.Reset())
		}
	}
}

// AddTest returns a test that adding to a single bucket works.
// It is meant to be used by leakybucket implementers who wish to test this.
func AddTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		bucket, err := s.Create("testbucket", 10, time.Minute)
		if err != nil {
			t.Fatal(err)
		}

		addAndTestRemaining := func(add, remaining uint) {
			if state, err := bucket.Add(add); err != nil {
				t.Fatal(err)
			} else if bucket.Remaining() != state.Remaining {
				t.Fatalf("expected bucket and state remaining to match, bucket is %d, state is %d",
					bucket.Remaining(), state.Remaining)
			} else if state.Remaining != remaining {
				t.Fatalf("expected %d remaining, got %d", remaining, state.Remaining)
			}
		}

		addAndTestRemaining(1, 9)
		addAndTestRemaining(3, 6)
		addAndTestRemaining(6, 0)

		if _, err := bucket.Add(1); err == nil {
			t.Fatalf("expected ErrorFull, received no error")
		} else if err != ErrorFull {
			t.Fatalf("expected ErrorFull, received %v", err)
		}
	}
}

// ThreadSafeAddTest returns a test that adding to a single bucket is thread-safe.
// It is meant to be used by leakybucket implementers who wish to test this.
func ThreadSafeAddTest(s Storage) func(*testing.T) {
	return func(t *testing.T) {
		// Make a bucket of size `n`. Spawn `n+1` goroutines that each try to take one token.
		// We should see the bucket transition through having `n-1`, `n-2`, ... 0 remaining capacity.
		// We should also witness one error when the bucket has reached capacity.
		n := 100
		bucket, err := s.Create("testbucket", uint(n), time.Minute)
		if err != nil {
			t.Fatal(err)
		}
		remaining := map[uint]bool{}     // record observed "remaining" counts. (ab)using map as set here
		remainingMutex := sync.RWMutex{} // maps are not threadsafe
		errors := []error{}              // record observed errors
		var wg sync.WaitGroup
		for i := 0; i < n+1; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				state, err := bucket.Add(1)
				if err != nil {
					errors = append(errors, err)
				} else {
					remainingMutex.Lock()
					defer remainingMutex.Unlock()
					remaining[state.Remaining] = true
				}
			}()
		}
		wg.Wait()
		if len(remaining) != n {
			keys := []uint{}
			for key, _ := range remaining {
				keys = append(keys, key)
			}
			t.Fatalf("Did not observe correct bucket states. Saw %d distinct remaining values instead of %d: %v",
				len(remaining), n, keys)
		}
		if len(errors) != 1 && errors[0] != ErrorFull {
			t.Fatalf("Did not observe one full error: %#v", errors)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sync"

	"github.com/cheggaaa/pb"
	_ "github.com/mattn/go-sqlite3"
)

const (
	thumbsDir      = "public/thumbs"
	bigThumbSize   = "1000"
	smallThumbSize = "200"
	workers        = 4 // min: 1
)

func generateSmallThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_small.jpg", identifier))

	absThumbPath, err := filepath.Abs(thumbPath)
	if err != nil {
		return
	}

	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"vipsthumbnail", photoPath,
			"--rotate",
			"--size", smallThumbSize,
			"--crop",
			"--interpolator", "bicubic",
			"--output", absThumbPath+"[Q=97,no_subsample,strip]").Run()
	}

	return
}

func generateBigThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_big.jpg", identifier))

	absThumbPath, err := filepath.Abs(thumbPath)
	if err != nil {
		return
	}

	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"vipsthumbnail", photoPath,
			"--rotate",
			"--size", bigThumbSize,
			"--interpolator", "bicubic",
			"--output", absThumbPath+"[Q=97,no_subsample,strip]").Run()
	}

	return
}

func generateThumbsImpl(photoPath string) (err error) {
	identifier := fmt.Sprintf("%x", md5.Sum([]byte(photoPath)))

	bigThumbPath, err := generateBigThumb(photoPath, identifier)
	if err == nil { // success
		_, err = generateSmallThumb(bigThumbPath, identifier)
	} else { // create from original photo since big thumb failed
		_, err = generateSmallThumb(photoPath, identifier)
	}

	return
}

func generateThumbs(ch chan string, wg *sync.WaitGroup, bar *pb.ProgressBar) {
	defer wg.Done()

	for photoPath := range ch {
		generateThumbsImpl(photoPath)
		bar.Increment()
	}
}

func main() {
	var photosCount int

	if workers < 1 {
		log.Fatal("number of workers must be at least 1")
	}

	db, err := sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	rows, err := db.Query(`
	SELECT path FROM photos
	JOIN sets ON photos.set_id = sets.id
	ORDER BY sets.taken_at DESC, photos.taken_at ASC
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	err = db.QueryRow("SELECT COUNT(*) FROM photos").Scan(&photosCount)
	if err != nil {
		log.Fatal(err)
	}

	if err := os.MkdirAll(thumbsDir, os.ModeDir|0755); err != nil {
		log.Fatal(err)
	}

	ch := make(chan string)
	wg := sync.WaitGroup{}
	bar := pb.StartNew(photosCount)

	for i := 0; i < workers; i++ {
		wg.Add(1)
		go generateThumbs(ch, &wg, bar)
	}

	for rows.Next() {
		var photoPath string
		rows.Scan(&photoPath)
		ch <- photoPath
	}

	close(ch)
	wg.Wait()

	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>DRY small thumb generation function call<commit_after>package main

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sync"

	"github.com/cheggaaa/pb"
	_ "github.com/mattn/go-sqlite3"
)

const (
	thumbsDir      = "public/thumbs"
	bigThumbSize   = "1000"
	smallThumbSize = "200"
	workers        = 4 // min: 1
)

func generateSmallThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_small.jpg", identifier))

	absThumbPath, err := filepath.Abs(thumbPath)
	if err != nil {
		return
	}

	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"vipsthumbnail", photoPath,
			"--rotate",
			"--size", smallThumbSize,
			"--crop",
			"--interpolator", "bicubic",
			"--output", absThumbPath+"[Q=97,no_subsample,strip]").Run()
	}

	return
}

func generateBigThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_big.jpg", identifier))

	absThumbPath, err := filepath.Abs(thumbPath)
	if err != nil {
		return
	}

	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"vipsthumbnail", photoPath,
			"--rotate",
			"--size", bigThumbSize,
			"--interpolator", "bicubic",
			"--output", absThumbPath+"[Q=97,no_subsample,strip]").Run()
	}

	return
}

func generateThumbsImpl(photoPath string) (err error) {
	smallThumbPhotoPath := photoPath
	identifier := fmt.Sprintf("%x", md5.Sum([]byte(photoPath)))

	bigThumbPath, err := generateBigThumb(photoPath, identifier)
	if err == nil {
		smallThumbPhotoPath = bigThumbPath // create small thumb from big for speed
	}

	_, err = generateSmallThumb(smallThumbPhotoPath, identifier)

	return
}

func generateThumbs(ch chan string, wg *sync.WaitGroup, bar *pb.ProgressBar) {
	defer wg.Done()

	for photoPath := range ch {
		generateThumbsImpl(photoPath)
		bar.Increment()
	}
}

func main() {
	var photosCount int

	if workers < 1 {
		log.Fatal("number of workers must be at least 1")
	}

	db, err := sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	rows, err := db.Query(`
	SELECT path FROM photos
	JOIN sets ON photos.set_id = sets.id
	ORDER BY sets.taken_at DESC, photos.taken_at ASC
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	err = db.QueryRow("SELECT COUNT(*) FROM photos").Scan(&photosCount)
	if err != nil {
		log.Fatal(err)
	}

	if err := os.MkdirAll(thumbsDir, os.ModeDir|0755); err != nil {
		log.Fatal(err)
	}

	ch := make(chan string)
	wg := sync.WaitGroup{}
	bar := pb.StartNew(photosCount)

	for i := 0; i < workers; i++ {
		wg.Add(1)
		go generateThumbs(ch, &wg, bar)
	}

	for rows.Next() {
		var photoPath string
		rows.Scan(&photoPath)
		ch <- photoPath
	}

	close(ch)
	wg.Wait()

	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"sync"

	_ "github.com/mattn/go-sqlite3"
)

const (
	thumbsDir      = "public/thumbs"
	bigThumbSize   = "1000x1000"
	smallThumbSize = "200x200"
	workers        = 4 // min: 1
)

func generateSmallThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_small.jpg", identifier))
	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"convert", photoPath,
			"-auto-orient",
			"-strip",
			"-resize", smallThumbSize+"^",
			"-gravity", "center",
			"-extent", smallThumbSize,
			thumbPath).Run()
	}
	return
}

func generateBigThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_big.jpg", identifier))
	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"convert", photoPath,
			"-auto-orient",
			"-strip",
			"-resize", bigThumbSize,
			thumbPath).Run()
	}
	return
}

func generateThumb(ch chan string, wg *sync.WaitGroup) {
	defer wg.Done()

	for photoPath := range ch {
		identifier := fmt.Sprintf("%x", md5.Sum([]byte(photoPath)))

		bigThumbPath, err := generateBigThumb(photoPath, identifier)
		if err != nil { // error
			return
		}

		fmt.Println(bigThumbPath)

		smallThumbPath, err := generateSmallThumb(bigThumbPath, identifier)
		if err == nil { // success
			fmt.Println(smallThumbPath)
		}
	}
}

func main() {
	var wg sync.WaitGroup

	if workers < 1 {
		log.Fatal("number of workers must be at least 1")
	}

	ch := make(chan string)

	db, err := sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	rows, err := db.Query(`
	SELECT path FROM photos
	JOIN sets ON photos.set_id = sets.id
	ORDER BY sets.taken_at DESC, photos.taken_at ASC
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	if err := os.MkdirAll(thumbsDir, os.ModeDir|0755); err != nil {
		log.Fatal(err)
	}

	for i := 0; i < workers; i++ {
		wg.Add(1)
		go generateThumb(ch, &wg)
	}

	for rows.Next() {
		var photoPath string
		rows.Scan(&photoPath)
		ch <- photoPath
	}

	close(ch)
	wg.Wait()

	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Assign channel and wait group before using<commit_after>package main

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"sync"

	_ "github.com/mattn/go-sqlite3"
)

const (
	thumbsDir      = "public/thumbs"
	bigThumbSize   = "1000x1000"
	smallThumbSize = "200x200"
	workers        = 4 // min: 1
)

func generateSmallThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_small.jpg", identifier))
	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"convert", photoPath,
			"-auto-orient",
			"-strip",
			"-resize", smallThumbSize+"^",
			"-gravity", "center",
			"-extent", smallThumbSize,
			thumbPath).Run()
	}
	return
}

func generateBigThumb(photoPath, identifier string) (thumbPath string, err error) {
	thumbPath = path.Join(thumbsDir, fmt.Sprintf("%s_big.jpg", identifier))
	if _, err = os.Stat(thumbPath); os.IsNotExist(err) { // file does not exist
		err = exec.Command(
			"convert", photoPath,
			"-auto-orient",
			"-strip",
			"-resize", bigThumbSize,
			thumbPath).Run()
	}
	return
}

func generateThumb(ch chan string, wg *sync.WaitGroup) {
	defer wg.Done()

	for photoPath := range ch {
		identifier := fmt.Sprintf("%x", md5.Sum([]byte(photoPath)))

		bigThumbPath, err := generateBigThumb(photoPath, identifier)
		if err != nil { // error
			return
		}

		fmt.Println(bigThumbPath)

		smallThumbPath, err := generateSmallThumb(bigThumbPath, identifier)
		if err == nil { // success
			fmt.Println(smallThumbPath)
		}
	}
}

func main() {
	if workers < 1 {
		log.Fatal("number of workers must be at least 1")
	}

	db, err := sql.Open("sqlite3", "thyme.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	rows, err := db.Query(`
	SELECT path FROM photos
	JOIN sets ON photos.set_id = sets.id
	ORDER BY sets.taken_at DESC, photos.taken_at ASC
	`)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	if err := os.MkdirAll(thumbsDir, os.ModeDir|0755); err != nil {
		log.Fatal(err)
	}

	ch := make(chan string)
	wg := sync.WaitGroup{}

	for i := 0; i < workers; i++ {
		wg.Add(1)
		go generateThumb(ch, &wg)
	}

	for rows.Next() {
		var photoPath string
		rows.Scan(&photoPath)
		ch <- photoPath
	}

	close(ch)
	wg.Wait()

	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package inject_test

import (
	"testing"

	"github.com/daaku/go.inject"
)

type TypeAnswerStruct struct {
	Answer  int
	private int
}

type Answerable interface {
	Answer() int
}

type TypeNestedStruct struct {
	A *TypeAnswerStruct `inject:""`
}

func (b *TypeNestedStruct) Answer() int {
	return b.A.Answer
}

type C struct {
	A *TypeAnswerStruct `inject:""`
	B *TypeNestedStruct `inject:""`
}

func (c *C) Answer() int {
	return c.A.Answer + c.B.Answer()
}

func TestRequireTag(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A is not nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
}

type TypeWithNonPointerInject struct {
	A int `inject:""`
}

func TestErrorOnNonPointerInject(t *testing.T) {
	var a TypeWithNonPointerInject
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "found inject tag on non-pointer field A in type *inject_test.TypeWithNonPointerInject"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithNonPointerStructInject struct {
	A *int `inject:""`
}

func TestErrorOnNonPointerStructInject(t *testing.T) {
	var a TypeWithNonPointerStructInject
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "found inject tag on non-pointer field A in type *inject_test.TypeWithNonPointerStructInject"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestInjectSimple(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct `inject:""`
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A == nil {
		t.Fatal("v.A is nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
	if v.B.A == nil {
		t.Fatal("v.B.A is nil")
	}
	if v.A != v.B.A {
		t.Fatal("got different instances of A")
	}
}

func TestDoesNotOverwrite(t *testing.T) {
	a := &TypeAnswerStruct{}
	v := &C{A: a}
	if err := inject.Populate(v); err != nil {
		t.Fatal(err)
	}
	if v.A != a {
		t.Fatal("original A was lost")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
}

func TestPrivate(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct `inject:"private"`
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A == nil {
		t.Fatal("v.A is nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
	if v.B.A == nil {
		t.Fatal("v.B.A is nil")
	}
	if v.A == v.B.A {
		t.Fatal("got the same A")
	}
}

type TypeWithJustColon struct {
	A *TypeAnswerStruct `inject:`
}

func TestTagWithJustColon(t *testing.T) {
	var a TypeWithJustColon
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "unexpected tag format `inject:` for field A in type *inject_test.TypeWithJustColon"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithOpenQuote struct {
	A *TypeAnswerStruct `inject:"`
}

func TestTagWithOpenQuote(t *testing.T) {
	var a TypeWithOpenQuote
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "unexpected tag format `inject:\"` for field A in type *inject_test.TypeWithOpenQuote"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideNonPointer(t *testing.T) {
	var g inject.Graph
	var i int
	err := g.Provide(inject.Object{Value: i})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "expected object value to be a pointer to a struct but got type int with value 0"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideNonPointerStruct(t *testing.T) {
	var g inject.Graph
	var i *int
	err := g.Provide(inject.Object{Value: i})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "expected object value to be a pointer to a struct but got type *int with value <nil>"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoOfTheSame(t *testing.T) {
	var g inject.Graph
	a := TypeAnswerStruct{}
	err := g.Provide(inject.Object{Value: &a})
	if err != nil {
		t.Fatal(err)
	}

	err = g.Provide(inject.Object{Value: &a})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two unnamed instances of type *inject_test.TypeAnswerStruct"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoOfTheSameWithPopulate(t *testing.T) {
	a := TypeAnswerStruct{}
	err := inject.Populate(&a, &a)
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two unnamed instances of type *inject_test.TypeAnswerStruct"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoWithTheSameName(t *testing.T) {
	var g inject.Graph
	const name = "foo"
	a := TypeAnswerStruct{}
	err := g.Provide(inject.Object{Value: &a, Name: name})
	if err != nil {
		t.Fatal(err)
	}

	err = g.Provide(inject.Object{Value: &a, Name: name})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two instances named foo"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestNamedInstanceWithDependencies(t *testing.T) {
	var g inject.Graph
	a := &TypeNestedStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	var c struct {
		A *TypeNestedStruct `inject:"foo"`
	}
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}

	if c.A.A == nil {
		t.Fatal("c.A.A was not injected")
	}
}

func TestTwoNamedInstances(t *testing.T) {
	var g inject.Graph
	a := &TypeAnswerStruct{}
	b := &TypeAnswerStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	if err := g.Provide(inject.Object{Value: b, Name: "bar"}); err != nil {
		t.Fatal(err)
	}

	var c struct {
		A *TypeAnswerStruct `inject:"foo"`
		B *TypeAnswerStruct `inject:"bar"`
	}
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}

	if c.A != a {
		t.Fatal("did not find expected c.A")
	}
	if c.B != b {
		t.Fatal("did not find expected c.B")
	}
}

type TypeWithMissingNamed struct {
	A *TypeAnswerStruct `inject:"foo"`
}

func TestTagWithMissingNamed(t *testing.T) {
	var a TypeWithMissingNamed
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "did not find object named foo required by field A in type *inject_test.TypeWithMissingNamed"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestCompleteProvides(t *testing.T) {
	var g inject.Graph
	var v struct {
		A *TypeAnswerStruct `inject:""`
	}
	if err := g.Provide(inject.Object{Value: &v, Complete: true}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A was not nil")
	}
}

func TestCompleteNamedProvides(t *testing.T) {
	var g inject.Graph
	var v struct {
		A *TypeAnswerStruct `inject:""`
	}
	if err := g.Provide(inject.Object{Value: &v, Complete: true, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A was not nil")
	}
}

type TypeInjectInterface struct {
	Answerable Answerable        `inject:""`
	B          *TypeNestedStruct `inject:""`
}

func TestInjectInterface(t *testing.T) {
	var v TypeInjectInterface
	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.Answerable == nil || v.Answerable != v.B {
		t.Fatalf(
			"expected the same but got Answerable = %T %+v / B = %T %+v",
			v.Answerable,
			v.Answerable,
			v.B,
			v.B,
		)
	}
}

type TypeWithInvalidNamedType struct {
	A *TypeNestedStruct `inject:"foo"`
}

func TestInvalidNamedInstanceType(t *testing.T) {
	var g inject.Graph
	a := &TypeAnswerStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	var c TypeWithInvalidNamedType
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	err := g.Populate()
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "object named foo of type *inject_test.TypeNestedStruct is not assignable to field A in type *inject_test.TypeWithInvalidNamedType"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithInjectOnPrivateField struct {
	a *TypeAnswerStruct `inject:""`
}

func TestInjectOnPrivateField(t *testing.T) {
	var a TypeWithInjectOnPrivateField
	err := inject.Populate(&a)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "inject requested on unexported field a in type *inject_test.TypeWithInjectOnPrivateField"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithInjectOnPrivateInterfaceField struct {
	a Answerable `inject:""`
}

func TestInjectOnPrivateInterfaceField(t *testing.T) {
	var a TypeWithInjectOnPrivateField
	err := inject.Populate(&a)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "inject requested on unexported field a in type *inject_test.TypeWithInjectOnPrivateField"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeInjectPrivateInterface struct {
	Answerable Answerable        `inject:"private"`
	B          *TypeNestedStruct `inject:""`
}

func TestInjectPrivateInterface(t *testing.T) {
	var v TypeInjectPrivateInterface
	err := inject.Populate(&v)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "found private inject tag on interface field Answerable in type *inject_test.TypeInjectPrivateInterface"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}
<commit_msg>remove badly named type C from test<commit_after>package inject_test

import (
	"testing"

	"github.com/daaku/go.inject"
)

type TypeAnswerStruct struct {
	Answer  int
	private int
}

type Answerable interface {
	Answer() int
}

type TypeNestedStruct struct {
	A *TypeAnswerStruct `inject:""`
}

func (b *TypeNestedStruct) Answer() int {
	return b.A.Answer
}

func TestRequireTag(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A is not nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
}

type TypeWithNonPointerInject struct {
	A int `inject:""`
}

func TestErrorOnNonPointerInject(t *testing.T) {
	var a TypeWithNonPointerInject
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "found inject tag on non-pointer field A in type *inject_test.TypeWithNonPointerInject"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithNonPointerStructInject struct {
	A *int `inject:""`
}

func TestErrorOnNonPointerStructInject(t *testing.T) {
	var a TypeWithNonPointerStructInject
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "found inject tag on non-pointer field A in type *inject_test.TypeWithNonPointerStructInject"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestInjectSimple(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct `inject:""`
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A == nil {
		t.Fatal("v.A is nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
	if v.B.A == nil {
		t.Fatal("v.B.A is nil")
	}
	if v.A != v.B.A {
		t.Fatal("got different instances of A")
	}
}

func TestDoesNotOverwrite(t *testing.T) {
	a := &TypeAnswerStruct{}
	var v struct {
		A *TypeAnswerStruct `inject:""`
		B *TypeNestedStruct `inject:""`
	}
	v.A = a
	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A != a {
		t.Fatal("original A was lost")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
}

func TestPrivate(t *testing.T) {
	var v struct {
		A *TypeAnswerStruct `inject:"private"`
		B *TypeNestedStruct `inject:""`
	}

	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.A == nil {
		t.Fatal("v.A is nil")
	}
	if v.B == nil {
		t.Fatal("v.B is nil")
	}
	if v.B.A == nil {
		t.Fatal("v.B.A is nil")
	}
	if v.A == v.B.A {
		t.Fatal("got the same A")
	}
}

type TypeWithJustColon struct {
	A *TypeAnswerStruct `inject:`
}

func TestTagWithJustColon(t *testing.T) {
	var a TypeWithJustColon
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "unexpected tag format `inject:` for field A in type *inject_test.TypeWithJustColon"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithOpenQuote struct {
	A *TypeAnswerStruct `inject:"`
}

func TestTagWithOpenQuote(t *testing.T) {
	var a TypeWithOpenQuote
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "unexpected tag format `inject:\"` for field A in type *inject_test.TypeWithOpenQuote"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideNonPointer(t *testing.T) {
	var g inject.Graph
	var i int
	err := g.Provide(inject.Object{Value: i})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "expected object value to be a pointer to a struct but got type int with value 0"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideNonPointerStruct(t *testing.T) {
	var g inject.Graph
	var i *int
	err := g.Provide(inject.Object{Value: i})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "expected object value to be a pointer to a struct but got type *int with value <nil>"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoOfTheSame(t *testing.T) {
	var g inject.Graph
	a := TypeAnswerStruct{}
	err := g.Provide(inject.Object{Value: &a})
	if err != nil {
		t.Fatal(err)
	}

	err = g.Provide(inject.Object{Value: &a})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two unnamed instances of type *inject_test.TypeAnswerStruct"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoOfTheSameWithPopulate(t *testing.T) {
	a := TypeAnswerStruct{}
	err := inject.Populate(&a, &a)
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two unnamed instances of type *inject_test.TypeAnswerStruct"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestProvideTwoWithTheSameName(t *testing.T) {
	var g inject.Graph
	const name = "foo"
	a := TypeAnswerStruct{}
	err := g.Provide(inject.Object{Value: &a, Name: name})
	if err != nil {
		t.Fatal(err)
	}

	err = g.Provide(inject.Object{Value: &a, Name: name})
	if err == nil {
		t.Fatal("expected error")
	}

	const msg = "provided two instances named foo"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestNamedInstanceWithDependencies(t *testing.T) {
	var g inject.Graph
	a := &TypeNestedStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	var c struct {
		A *TypeNestedStruct `inject:"foo"`
	}
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}

	if c.A.A == nil {
		t.Fatal("c.A.A was not injected")
	}
}

func TestTwoNamedInstances(t *testing.T) {
	var g inject.Graph
	a := &TypeAnswerStruct{}
	b := &TypeAnswerStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	if err := g.Provide(inject.Object{Value: b, Name: "bar"}); err != nil {
		t.Fatal(err)
	}

	var c struct {
		A *TypeAnswerStruct `inject:"foo"`
		B *TypeAnswerStruct `inject:"bar"`
	}
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}

	if c.A != a {
		t.Fatal("did not find expected c.A")
	}
	if c.B != b {
		t.Fatal("did not find expected c.B")
	}
}

type TypeWithMissingNamed struct {
	A *TypeAnswerStruct `inject:"foo"`
}

func TestTagWithMissingNamed(t *testing.T) {
	var a TypeWithMissingNamed
	err := inject.Populate(&a)
	if err == nil {
		t.Fatalf("expected error for %+v", a)
	}

	const msg = "did not find object named foo required by field A in type *inject_test.TypeWithMissingNamed"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

func TestCompleteProvides(t *testing.T) {
	var g inject.Graph
	var v struct {
		A *TypeAnswerStruct `inject:""`
	}
	if err := g.Provide(inject.Object{Value: &v, Complete: true}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A was not nil")
	}
}

func TestCompleteNamedProvides(t *testing.T) {
	var g inject.Graph
	var v struct {
		A *TypeAnswerStruct `inject:""`
	}
	if err := g.Provide(inject.Object{Value: &v, Complete: true, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	if err := g.Populate(); err != nil {
		t.Fatal(err)
	}
	if v.A != nil {
		t.Fatal("v.A was not nil")
	}
}

type TypeInjectInterface struct {
	Answerable Answerable        `inject:""`
	B          *TypeNestedStruct `inject:""`
}

func TestInjectInterface(t *testing.T) {
	var v TypeInjectInterface
	if err := inject.Populate(&v); err != nil {
		t.Fatal(err)
	}
	if v.Answerable == nil || v.Answerable != v.B {
		t.Fatalf(
			"expected the same but got Answerable = %T %+v / B = %T %+v",
			v.Answerable,
			v.Answerable,
			v.B,
			v.B,
		)
	}
}

type TypeWithInvalidNamedType struct {
	A *TypeNestedStruct `inject:"foo"`
}

func TestInvalidNamedInstanceType(t *testing.T) {
	var g inject.Graph
	a := &TypeAnswerStruct{}
	if err := g.Provide(inject.Object{Value: a, Name: "foo"}); err != nil {
		t.Fatal(err)
	}

	var c TypeWithInvalidNamedType
	if err := g.Provide(inject.Object{Value: &c}); err != nil {
		t.Fatal(err)
	}

	err := g.Populate()
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "object named foo of type *inject_test.TypeNestedStruct is not assignable to field A in type *inject_test.TypeWithInvalidNamedType"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithInjectOnPrivateField struct {
	a *TypeAnswerStruct `inject:""`
}

func TestInjectOnPrivateField(t *testing.T) {
	var a TypeWithInjectOnPrivateField
	err := inject.Populate(&a)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "inject requested on unexported field a in type *inject_test.TypeWithInjectOnPrivateField"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeWithInjectOnPrivateInterfaceField struct {
	a Answerable `inject:""`
}

func TestInjectOnPrivateInterfaceField(t *testing.T) {
	var a TypeWithInjectOnPrivateField
	err := inject.Populate(&a)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "inject requested on unexported field a in type *inject_test.TypeWithInjectOnPrivateField"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}

type TypeInjectPrivateInterface struct {
	Answerable Answerable        `inject:"private"`
	B          *TypeNestedStruct `inject:""`
}

func TestInjectPrivateInterface(t *testing.T) {
	var v TypeInjectPrivateInterface
	err := inject.Populate(&v)
	if err == nil {
		t.Fatal("did not find expected error")
	}

	const msg = "found private inject tag on interface field Answerable in type *inject_test.TypeInjectPrivateInterface"
	if err.Error() != msg {
		t.Fatalf("expected:\n%s\nactual:\n%s", msg, err.Error())
	}
}
<|endoftext|>


<commit_before>package cli

import "os"
import "fmt"
import "bytes"
import "strings"

// CLI represents a set of defined flags.  The zero value of a FlagSet
// has no name and has ContinueOnError error handling.
type CLI struct {
	flagable
	paramable
	subCommandable
	*writer

	fn           commandFn
	name         string
	description  string
	parsed       bool
	unparsedArgs []string
}

// NewCLI returns a new cli with the specified name and
// error handling property.
func NewCLI(version, desc string, fn commandFn, paramNames ...string) *CLI {
	nameParts := strings.Split(os.Args[0], "/")
	cli := new(CLI)
	cli.init(nameParts[len(nameParts)-1], desc, fn, paramNames...)
	cli.version = version
	cli.description = desc
	return cli
}

// Args returns any remaining args that were not parsed as params
func (cmd *CLI) Args() []string {
	return cmd.unparsedArgs
}

// Arg takes a position of a remaining arg that was not parsed as a param
func (cmd *CLI) Arg(index int) string {
	return cmd.Args()[index]
}

// DefineSubCommand return a SubCommand and adds the current CLI as the parent
func (cmd *CLI) DefineSubCommand(name string, desc string, fn commandFn, paramNames ...string) *SubCommand {
	subcmd := cmd.subCommandable.DefineSubCommand(name, desc, fn, paramNames...)
	subcmd.parent = cmd
	return subcmd
}

// Description returns the command description
func (cmd *CLI) Description() string {
	return cmd.description
}

// Name returns the command name
func (cmd *CLI) Name() string {
	var name string
	if cmd.parent != nil {
		name = strings.Join([]string{cmd.parent.Name(), cmd.name}, " ")
	} else {
		name = cmd.name
	}
	return name
}

// Parsed reports whether f.Parse has been called.
func (cmd *CLI) Parsed() bool {
	cmd.parsed = cmd.flagable.Parsed() && cmd.paramable.Parsed() && cmd.subCommandable.Parsed()
	return cmd.parsed
}

// Start starts the command with args, arg[0] is ignored
func (cmd *CLI) Start(args ...string) {
	if args == nil {
		args = os.Args
	}

	if len(args) > 1 {
		args = args[1:]
	} else {
		args = []string{}
	}

	// parse flags and args
	args = cmd.flagable.parse(args)

	// Show a version
	if len(cmd.Version()) > 0 && cmd.Flag("version").Get() == true {
		fmt.Println(cmd.Name(), cmd.Version())
		return
	}

	// Show Help
	if cmd.Flag("help").Get() == true {
		cmd.Usage()
		return
	}

	// Parse Params
	args = cmd.paramable.parse(args)

	var subCommandsParsed bool
	if cmd.unparsedArgs, subCommandsParsed = cmd.subCommandable.parse(args); subCommandsParsed {
		return
	}

	// Run the function
	cmd.fn(cmd)
}

// UsageString returns the command usage as a string
func (cmd *CLI) UsageString() string {
	hasSubCommands := len(cmd.subCommands) > 0
	hasParams := len(cmd.params) > 0
	hasDescription := len(cmd.description) > 0

	// Start the Buffer
	var buff bytes.Buffer

	buff.WriteString("Usage:\n")
	buff.WriteString(fmt.Sprintf("  %s [options...]", cmd.Name()))

	// Write Param Syntax
	if hasParams {
		buff.WriteString(fmt.Sprintf(" %s", cmd.paramable.UsageString()))
	}

	// Write Sub Command Syntax
	if hasSubCommands {
		buff.WriteString(" <command> [arg...]")
	}

	if hasDescription {
		buff.WriteString(fmt.Sprintf("\n\n%s", cmd.Description()))
	}

	// Write Flags Syntax
	buff.WriteString("\n\nOptions:\n")
	buff.WriteString(cmd.flagable.UsageString())

	// Write Sub Command List
	if hasSubCommands {
		buff.WriteString("\n\nCommands:\n")
		buff.WriteString(cmd.subCommandable.UsageString())
	}

	// Return buffer as string
	return buff.String()
}

func (cmd *CLI) init(name, desc string, fn commandFn, paramNames ...string) {
	writer := &writer{ErrorHandling: ExitOnError}
	cmd.writer = writer
	cmd.flagable = flagable{writer: writer}
	cmd.paramable = paramable{writer: writer}
	cmd.subCommandable = subCommandable{writer: writer}
	cmd.name = name
	cmd.fn = fn
	cmd.description = desc
	cmd.DefineParams(paramNames...)
	cmd.usage = func() { fmt.Fprintln(cmd.StdOutput(), cmd.UsageString()) }
}
<commit_msg>fix output<commit_after>package cli

import "os"
import "fmt"
import "bytes"
import "strings"

// CLI represents a set of defined flags.  The zero value of a FlagSet
// has no name and has ContinueOnError error handling.
type CLI struct {
	flagable
	paramable
	subCommandable
	*writer

	fn           commandFn
	name         string
	description  string
	parsed       bool
	unparsedArgs []string
}

// NewCLI returns a new cli with the specified name and
// error handling property.
func NewCLI(version, desc string, fn commandFn, paramNames ...string) *CLI {
	nameParts := strings.Split(os.Args[0], "/")
	cli := new(CLI)
	cli.init(nameParts[len(nameParts)-1], desc, fn, paramNames...)
	cli.version = version
	cli.description = desc
	return cli
}

// Args returns any remaining args that were not parsed as params
func (cmd *CLI) Args() []string {
	return cmd.unparsedArgs
}

// Arg takes a position of a remaining arg that was not parsed as a param
func (cmd *CLI) Arg(index int) string {
	return cmd.Args()[index]
}

// DefineSubCommand return a SubCommand and adds the current CLI as the parent
func (cmd *CLI) DefineSubCommand(name string, desc string, fn commandFn, paramNames ...string) *SubCommand {
	subcmd := cmd.subCommandable.DefineSubCommand(name, desc, fn, paramNames...)
	subcmd.parent = cmd
	return subcmd
}

// Description returns the command description
func (cmd *CLI) Description() string {
	return cmd.description
}

// Name returns the command name
func (cmd *CLI) Name() string {
	var name string
	if cmd.parent != nil {
		name = strings.Join([]string{cmd.parent.Name(), cmd.name}, " ")
	} else {
		name = cmd.name
	}
	return name
}

// Parsed reports whether f.Parse has been called.
func (cmd *CLI) Parsed() bool {
	cmd.parsed = cmd.flagable.Parsed() && cmd.paramable.Parsed() && cmd.subCommandable.Parsed()
	return cmd.parsed
}

// Start starts the command with args, arg[0] is ignored
func (cmd *CLI) Start(args ...string) {
	if args == nil {
		args = os.Args
	}

	if len(args) > 1 {
		args = args[1:]
	} else {
		args = []string{}
	}

	// parse flags and args
	args = cmd.flagable.parse(args)

	// Show a version
	if len(cmd.Version()) > 0 && cmd.Flag("version").Get() == true {
		fmt.Fprintln(cmd.StdOutput(), cmd.Name(), cmd.Version())
		return
	}

	// Show Help
	if cmd.Flag("help").Get() == true {
		cmd.Usage()
		return
	}

	// Parse Params
	args = cmd.paramable.parse(args)

	var subCommandsParsed bool
	if cmd.unparsedArgs, subCommandsParsed = cmd.subCommandable.parse(args); subCommandsParsed {
		return
	}

	// Run the function
	cmd.fn(cmd)
}

// UsageString returns the command usage as a string
func (cmd *CLI) UsageString() string {
	hasSubCommands := len(cmd.subCommands) > 0
	hasParams := len(cmd.params) > 0
	hasDescription := len(cmd.description) > 0

	// Start the Buffer
	var buff bytes.Buffer

	buff.WriteString("Usage:\n")
	buff.WriteString(fmt.Sprintf("  %s [options...]", cmd.Name()))

	// Write Param Syntax
	if hasParams {
		buff.WriteString(fmt.Sprintf(" %s", cmd.paramable.UsageString()))
	}

	// Write Sub Command Syntax
	if hasSubCommands {
		buff.WriteString(" <command> [arg...]")
	}

	if hasDescription {
		buff.WriteString(fmt.Sprintf("\n\n%s", cmd.Description()))
	}

	// Write Flags Syntax
	buff.WriteString("\n\nOptions:\n")
	buff.WriteString(cmd.flagable.UsageString())

	// Write Sub Command List
	if hasSubCommands {
		buff.WriteString("\n\nCommands:\n")
		buff.WriteString(cmd.subCommandable.UsageString())
	}

	// Return buffer as string
	return buff.String()
}

func (cmd *CLI) init(name, desc string, fn commandFn, paramNames ...string) {
	writer := &writer{ErrorHandling: ExitOnError}
	cmd.writer = writer
	cmd.flagable = flagable{writer: writer}
	cmd.paramable = paramable{writer: writer}
	cmd.subCommandable = subCommandable{writer: writer}
	cmd.name = name
	cmd.fn = fn
	cmd.description = desc
	cmd.DefineParams(paramNames...)
	cmd.usage = func() { fmt.Fprintln(cmd.StdOutput(), cmd.UsageString()) }
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"
	"github.com/ProductHealth/gose4"
	"github.com/golang/glog"
	"io"
	"net/http"
	"net/url"
	"strings"
	"github.com/ProductHealth/gommons/time"
)

type check struct {
	url             *url.URL
	method          string
	statusCode      int
	requestBody     *string
	requestHeaders  *map[string]string
	expectedHeaders *map[string]string
	expectedBody    *string
	config          gose4.Configuration
	requestFunc     func(*http.Request) (*http.Response, error)
}

func New(address, method string, statusCode int, config gose4.Configuration) (*check, error) {
	url, err := url.Parse(address)
	if err != nil {
		return nil, err
	}

	requestFunc := func(req *http.Request) (*http.Response, error) {
		return http.DefaultClient.Do(req)
	}

	return &check{url: url, method: method, statusCode: statusCode, config: config, requestFunc: requestFunc}, nil
}

func (hc *check) RequestBody(content string) {
	hc.requestBody = &content
}

func (hc *check) RequestHeaders(rh map[string]string) {
	hc.requestHeaders = &rh
}

func (hc *check) ExpectedHeaders(eh map[string]string) {
	hc.expectedHeaders = &eh
}

func (hc *check) ExpectedBody(content string) {
	hc.requestBody = &content
}

func (hc *check) Run() gose4.HealthCheckResult {
	sw := time.NewStopWatch()
	var bodyReader io.Reader = nil
	if hc.requestBody != nil {
		bodyReader = strings.NewReader(*(hc.requestBody))
	}
	request, err := http.NewRequest(hc.method, hc.url.String(), bodyReader)
	if err != nil {
		return gose4.Failed(sw.GetDuration(), err.Error())
	}
	response, err := hc.requestFunc(request)
	glog.V(5).Infof("RESPONSE %#v ERR: %s", response, err)
	if err != nil {
		return gose4.Failed(sw.GetDuration(), fmt.Sprintf("Error while requesting %#v: %s", hc.url, err))
	}
	if hc.statusCode != response.StatusCode {
		return gose4.Failed(sw.GetDuration(), fmt.Sprintf("Returned response code %#v does not match required %#v ", response.StatusCode, hc.statusCode))
	}
	return gose4.Ok(sw.GetDuration())
}

func (hc *check) Configuration() gose4.Configuration {
	return hc.config
}
<commit_msg>Added body.Close() on http check<commit_after>package http

import (
	"fmt"
	"github.com/ProductHealth/gose4"
	"github.com/golang/glog"
	"io"
	"net/http"
	"net/url"
	"strings"
	"github.com/ProductHealth/gommons/time"
)

type check struct {
	url             *url.URL
	method          string
	statusCode      int
	requestBody     *string
	requestHeaders  *map[string]string
	expectedHeaders *map[string]string
	expectedBody    *string
	config          gose4.Configuration
	requestFunc     func(*http.Request) (*http.Response, error)
}

func New(address, method string, statusCode int, config gose4.Configuration) (*check, error) {
	url, err := url.Parse(address)
	if err != nil {
		return nil, err
	}

	requestFunc := func(req *http.Request) (*http.Response, error) {
		return http.DefaultClient.Do(req)
	}

	return &check{url: url, method: method, statusCode: statusCode, config: config, requestFunc: requestFunc}, nil
}

func (hc *check) RequestBody(content string) {
	hc.requestBody = &content
}

func (hc *check) RequestHeaders(rh map[string]string) {
	hc.requestHeaders = &rh
}

func (hc *check) ExpectedHeaders(eh map[string]string) {
	hc.expectedHeaders = &eh
}

func (hc *check) ExpectedBody(content string) {
	hc.requestBody = &content
}

func (hc *check) Run() gose4.HealthCheckResult {
	sw := time.NewStopWatch()
	var bodyReader io.Reader = nil
	if hc.requestBody != nil {
		bodyReader = strings.NewReader(*(hc.requestBody))
	}
	request, err := http.NewRequest(hc.method, hc.url.String(), bodyReader)
	if err != nil {
		return gose4.Failed(sw.GetDuration(), err.Error())
	}
	response, err := hc.requestFunc(request)
	defer response.Body.Close()
	glog.V(5).Infof("RESPONSE %#v ERR: %s", response, err)
	if err != nil {
		return gose4.Failed(sw.GetDuration(), fmt.Sprintf("Error while requesting %#v: %s", hc.url, err))
	}
	if hc.statusCode != response.StatusCode {
		return gose4.Failed(sw.GetDuration(), fmt.Sprintf("Returned response code %#v does not match required %#v ", response.StatusCode, hc.statusCode))
	}
	return gose4.Ok(sw.GetDuration())
}

func (hc *check) Configuration() gose4.Configuration {
	return hc.config
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

package rand_test

import (
	"fmt"
	"math/rand"
	"os"
	"strings"
	"text/tabwriter"
)

// These tests serve as an example but also make sure we don't change
// the output of the random number generator when given a fixed seed.

func Example() {
	rand.Seed(42) // Try changing this number!
	answers := []string{
		"It is certain",
		"It is decidedly so",
		"Without a doubt",
		"Yes definitely",
		"You may rely on it",
		"As I see it yes",
		"Most likely",
		"Outlook good",
		"Yes",
		"Signs point to yes",
		"Reply hazy try again",
		"Ask again later",
		"Better not tell you now",
		"Cannot predict now",
		"Concentrate and ask again",
		"Don't count on it",
		"My reply is no",
		"My sources say no",
		"Outlook not so good",
		"Very doubtful",
	}
	fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))])
	// Output: Magic 8-Ball says: As I see it yes
}

// This example shows the use of each of the methods on a *Rand.
// The use of the global functions is the same, without the receiver.
func Example_rand() {
	// Create and seed the generator.
	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
	// Using a fixed seed will produce the same output on every run.
	r := rand.New(rand.NewSource(99))

	// The tabwriter here helps us generate aligned output.
	w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
	defer w.Flush()
	show := func(name string, v1, v2, v3 interface{}) {
		fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
	}

	// Float32 and Float64 values are in [0, 1).
	show("Float32", r.Float32(), r.Float32(), r.Float32())
	show("Float64", r.Float64(), r.Float64(), r.Float64())

	// ExpFloat64 values have an average of 1 but decay exponentially.
	show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())

	// NormFloat64 values have an average of 0 and a standard deviation of 1.
	show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())

	// Int31, Int63, and Uint32 generate values of the given width.
	// The Int method (not shown) is like either Int31 or Int63
	// depending on the size of 'int'.
	show("Int31", r.Int31(), r.Int31(), r.Int31())
	show("Int63", r.Int63(), r.Int63(), r.Int63())
	show("Uint32", r.Uint32(), r.Uint32(), r.Uint32())

	// Intn, Int31n, and Int63n limit their output to be < n.
	// They do so more carefully than using r.Int()%n.
	show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
	show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
	show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))

	// Perm generates a random permutation of the numbers [0, n).
	show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
	// Output:
	// Float32     0.2635776           0.6358173           0.6718283
	// Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
	// ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
	// NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
	// Int31       1501292890          1486668269          182840835
	// Int63       3546343826724305832 5724354148158589552 5239846799706671610
	// Uint32      2760229429          296659907           1922395059
	// Intn(10)    1                   2                   5
	// Int31n(10)  4                   7                   8
	// Int63n(10)  7                   6                   3
	// Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
}

func ExamplePerm() {
	for _, value := range rand.Perm(3) {
		fmt.Println(value)
	}

	// Unordered output: 1
	// 2
	// 0
}

func ExampleShuffle() {
	words := strings.Fields("ink runs from the corners of my mouth")
	rand.Shuffle(len(words), func(i, j int) {
		words[i], words[j] = words[j], words[i]
	})
	fmt.Println(words)

	// Output:
	// [mouth my the of runs corners from ink]
}

func ExampleShuffle_slicesInUnison() {
	numbers := []byte("12345")
	letters := []byte("ABCDE")
	// Shuffle numbers, swapping corresponding entries in letters at the same time.
	rand.Shuffle(len(numbers), func(i, j int) {
		numbers[i], numbers[j] = numbers[j], numbers[i]
		letters[i], letters[j] = letters[j], letters[i]
	})
	for i := range numbers {
		fmt.Printf("%c: %c\n", letters[i], numbers[i])
	}

	// Output:
	// C: 3
	// D: 4
	// A: 1
	// E: 5
	// B: 2
}
<commit_msg>math/rand: clarify documentation for Seed example<commit_after>// Copyright 2012 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.

package rand_test

import (
	"fmt"
	"math/rand"
	"os"
	"strings"
	"text/tabwriter"
)

// These tests serve as an example but also make sure we don't change
// the output of the random number generator when given a fixed seed.

func Example() {
	// Seeding with the same value results in the same random sequence each run.
	// For different numbers, seed with a different value, such as
	// time.Now().UnixNano(), which yields a constantly-changing number.
	rand.Seed(42)
	answers := []string{
		"It is certain",
		"It is decidedly so",
		"Without a doubt",
		"Yes definitely",
		"You may rely on it",
		"As I see it yes",
		"Most likely",
		"Outlook good",
		"Yes",
		"Signs point to yes",
		"Reply hazy try again",
		"Ask again later",
		"Better not tell you now",
		"Cannot predict now",
		"Concentrate and ask again",
		"Don't count on it",
		"My reply is no",
		"My sources say no",
		"Outlook not so good",
		"Very doubtful",
	}
	fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))])
	// Output: Magic 8-Ball says: As I see it yes
}

// This example shows the use of each of the methods on a *Rand.
// The use of the global functions is the same, without the receiver.
func Example_rand() {
	// Create and seed the generator.
	// Typically a non-fixed seed should be used, such as time.Now().UnixNano().
	// Using a fixed seed will produce the same output on every run.
	r := rand.New(rand.NewSource(99))

	// The tabwriter here helps us generate aligned output.
	w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
	defer w.Flush()
	show := func(name string, v1, v2, v3 interface{}) {
		fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
	}

	// Float32 and Float64 values are in [0, 1).
	show("Float32", r.Float32(), r.Float32(), r.Float32())
	show("Float64", r.Float64(), r.Float64(), r.Float64())

	// ExpFloat64 values have an average of 1 but decay exponentially.
	show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())

	// NormFloat64 values have an average of 0 and a standard deviation of 1.
	show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())

	// Int31, Int63, and Uint32 generate values of the given width.
	// The Int method (not shown) is like either Int31 or Int63
	// depending on the size of 'int'.
	show("Int31", r.Int31(), r.Int31(), r.Int31())
	show("Int63", r.Int63(), r.Int63(), r.Int63())
	show("Uint32", r.Uint32(), r.Uint32(), r.Uint32())

	// Intn, Int31n, and Int63n limit their output to be < n.
	// They do so more carefully than using r.Int()%n.
	show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
	show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
	show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))

	// Perm generates a random permutation of the numbers [0, n).
	show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
	// Output:
	// Float32     0.2635776           0.6358173           0.6718283
	// Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
	// ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
	// NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
	// Int31       1501292890          1486668269          182840835
	// Int63       3546343826724305832 5724354148158589552 5239846799706671610
	// Uint32      2760229429          296659907           1922395059
	// Intn(10)    1                   2                   5
	// Int31n(10)  4                   7                   8
	// Int63n(10)  7                   6                   3
	// Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
}

func ExamplePerm() {
	for _, value := range rand.Perm(3) {
		fmt.Println(value)
	}

	// Unordered output: 1
	// 2
	// 0
}

func ExampleShuffle() {
	words := strings.Fields("ink runs from the corners of my mouth")
	rand.Shuffle(len(words), func(i, j int) {
		words[i], words[j] = words[j], words[i]
	})
	fmt.Println(words)

	// Output:
	// [mouth my the of runs corners from ink]
}

func ExampleShuffle_slicesInUnison() {
	numbers := []byte("12345")
	letters := []byte("ABCDE")
	// Shuffle numbers, swapping corresponding entries in letters at the same time.
	rand.Shuffle(len(numbers), func(i, j int) {
		numbers[i], numbers[j] = numbers[j], numbers[i]
		letters[i], letters[j] = letters[j], letters[i]
	})
	for i := range numbers {
		fmt.Printf("%c: %c\n", letters[i], numbers[i])
	}

	// Output:
	// C: 3
	// D: 4
	// A: 1
	// E: 5
	// B: 2
}
<|endoftext|>


<commit_before>package version

// IPCVersion represents a version of the IPC protocol.
type IPCVersion uint32

const (
	// UnknownIPCVersion is used for Min/MaxIPCVersion in an Endpoint when
	// we don't know the relevant version numbers.  In this case the IPC
	// implementation will have to guess the correct values.
	UnknownIPCVersion IPCVersion = iota
	// Deprecated versions
	ipcVersion2
	ipcVersion3
	ipcDummyVersion3 // So that the numeric value of IPCVersion4 is 4
	IPCVersion4

	// IPCVersion5 uses the new security model (Principal and Blessings objects),
	// and sends discharges for third-party caveats on the server's blessings
	// during authentication.
	IPCVersion5

	// IPCVersion6 adds control channel encryption to IPCVersion5.
	IPCVersion6
)

// IPCVersionRange allows you to optionally specify a range of versions to
// use when calling FormatEndpoint
type IPCVersionRange struct {
	Min, Max IPCVersion
}

// EndpointOpt implents the EndpointOpt interface so an IPCVersionRange
// can be used as an option to FormatEndpoint.
func (IPCVersionRange) EndpointOpt() {}
<commit_msg>runtimes/google/ipc/stream: Marshal discharges safely.<commit_after>package version

// IPCVersion represents a version of the IPC protocol.
type IPCVersion uint32

const (
	// UnknownIPCVersion is used for Min/MaxIPCVersion in an Endpoint when
	// we don't know the relevant version numbers.  In this case the IPC
	// implementation will have to guess the correct values.
	UnknownIPCVersion IPCVersion = iota
	// Deprecated versions
	ipcVersion2
	ipcVersion3
	ipcDummyVersion3 // So that the numeric value of IPCVersion4 is 4
	ipcVersion4
	// TODO(ashankar): Unexport all versions except the last before release
	// IPCVersion5 uses the new security model (Principal and Blessings objects),
	// and sends discharges for third-party caveats on the server's blessings
	// during authentication.
	IPCVersion5

	// IPCVersion6 adds control channel encryption to IPCVersion5.
	IPCVersion6

	// IPCVersion7 uses concrete types for security.Discharge during VC
	// authentication.
	IPCVersion7
)

// IPCVersionRange allows you to optionally specify a range of versions to
// use when calling FormatEndpoint
type IPCVersionRange struct {
	Min, Max IPCVersion
}

// EndpointOpt implents the EndpointOpt interface so an IPCVersionRange
// can be used as an option to FormatEndpoint.
func (IPCVersionRange) EndpointOpt() {}
<|endoftext|>


<commit_before>package check

import (
	"testing"

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

var (
	referenceServer = "8.8.8.8"
	testChecker     = &Checker{ReferenceServer: referenceServer}
)

func resolve(server, query string) (records stringSet, authenticated bool, err error) {
	return testChecker.resolve(server, query)
}

func TestExistent(t *testing.T) {
	assert := assert.New(t)
	result, _, err := resolve(referenceServer, "example.com")

	assert.Nil(err)
	assert.Len(result, 1)
}

func TestNotExistent(t *testing.T) {
	assert := assert.New(t)
	result, authenticated, err := resolve(referenceServer, "xxx.example.com")

	assert.Nil(err)
	assert.False(authenticated)
	assert.Len(result, 0)
}

func TestAuthenticated(t *testing.T) {
	assert := assert.New(t)
	result, authenticated, err := resolve(referenceServer, "verisignlabs.com")

	assert.Nil(err)
	assert.True(authenticated)
	assert.Len(result, 2)
}

func TestUnreachable(t *testing.T) {
	assert := assert.New(t)
	_, _, err := resolve("127.1.2.3", "example.com")

	assert.EqualError(err, "connection refused")
}

func TestPtrName(t *testing.T) {
	assert := assert.New(t)
	result := testChecker.ptrName("8.8.8.8")

	assert.Equal("dns.google.", result)
}

func TestVersion(t *testing.T) {
	assert := assert.New(t)
	result := testChecker.version("82.96.65.2")

	assert.Equal("Make my day", result)
}
<commit_msg>Fix tests<commit_after>package check

import (
	"testing"

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

var (
	referenceServer = "8.8.8.8"
	testChecker     = &Checker{ReferenceServer: referenceServer}
)

func resolve(server, query string) (records stringSet, authenticated bool, err error) {
	return testChecker.resolve(server, query)
}

func TestExistent(t *testing.T) {
	assert := assert.New(t)
	result, _, err := resolve(referenceServer, "example.com")

	assert.Nil(err)
	assert.Len(result, 1)
}

func TestNotExistent(t *testing.T) {
	assert := assert.New(t)
	result, authenticated, err := resolve(referenceServer, "xxx.example.com")

	assert.Nil(err)
	assert.False(authenticated)
	assert.Len(result, 0)
}

func TestAuthenticated(t *testing.T) {
	assert := assert.New(t)
	result, authenticated, err := resolve(referenceServer, "verisignlabs.com")

	assert.Nil(err)
	assert.True(authenticated)
	assert.Len(result, 1)
}

func TestUnreachable(t *testing.T) {
	assert := assert.New(t)
	_, _, err := resolve("127.1.2.3", "example.com")

	assert.EqualError(err, "connection refused")
}

func TestPtrName(t *testing.T) {
	assert := assert.New(t)
	result := testChecker.ptrName("8.8.8.8")

	assert.Equal("dns.google.", result)
}

func TestVersion(t *testing.T) {
	assert := assert.New(t)
	result := testChecker.version("82.96.65.2")

	assert.Equal("Make my day", result)
}
<|endoftext|>


<commit_before>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"log"
	"sync"
)

// ActionHandler processes incoming requests for some node action.
type ActionHandler func(req Request, res *Response, s *Session)

// NodeTypeHandler handles requests for some node type.
type NodeTypeHandler struct {
	Name                                string
	EditAction, ViewAction, EmbedAction ActionHandler
}

// NodeProvider provides Node services for one ore more content types.
type NodeProvider struct {
	// Logger to be used
	Logger *log.Logger
	pool   *SessionPool
	types  map[string]*NodeTypeHandler
}

func NewNodeProvider(logger *log.Logger, infoPath string) *NodeProvider {
	p := NodeProvider{
		logger, NewSessionPool(1, infoPath),
		make(map[string]*NodeTypeHandler),
	}
	return &p
}

// AddNodeType adds a handler for a node type to be served.
func (p *NodeProvider) AddNodeType(h *NodeTypeHandler) {
	p.types[h.Name] = h
}

// Serve registers and serves the node types at the given Node service path.
func (p *NodeProvider) Serve(path string) error {
	// Start own NODE service
	var waitGroup sync.WaitGroup
	p.Logger.Println("Starting Node service")
	waitGroup.Add(1)
	go func() {
		defer waitGroup.Done()
		var provider Provider
		var node_ nodeService
		node_.Provider = p
		node_.Pool = p.pool
		provider.Logger = p.Logger
		if err := provider.Serve(path, "Node", &node_); err != nil {
			p.Logger.Printf("service: Could not start Node service: %v", err)
		}
	}()
	s, err := p.pool.New()
	if err != nil {
		return fmt.Errorf("service: Could not get session: %v", err)
	}
	defer p.pool.Free(s)
	if err := s.Info().PublishService("Node", path); err != nil {
		return fmt.Errorf("service: Could not publish node service: %v", err)
	}
	waitGroup.Wait()
	return nil
}

type nodeService struct {
	Provider *NodeProvider
	Pool     *SessionPool
}

func (i nodeService) Request(req Request,
	reply *Response) error {
	nodeType := req.Node.Type
	var f ActionHandler
	session, err := i.Pool.New()
	if err != nil {
		return fmt.Errorf("service: Could not get session: %v", err)
	}
	defer i.Pool.Free(session)
	switch req.Action {
	case EditAction:
		f = i.Provider.types[nodeType].EditAction
	}
	if f == nil {
		f = i.Provider.types[nodeType].ViewAction
	}
	f(req, reply, session)
	return nil
}

func (i *nodeService) GetNodeTypes(req int,
	reply *[]string) error {
	*reply = make([]string, 0)
	for key, _ := range i.Provider.types {
		*reply = append(*reply, key)
	}
	return nil
}
<commit_msg>Refactor error handling for node requests.<commit_after>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"log"
	"sync"
)

// ActionHandler processes incoming requests for some node action.
type ActionHandler func(req Request, res *Response, s *Session) error

// NodeTypeHandler handles requests for some node type.
type NodeTypeHandler struct {
	Name                                string
	EditAction, ViewAction, EmbedAction ActionHandler
}

// NodeProvider provides Node services for one ore more content types.
type NodeProvider struct {
	// Logger to be used
	Logger *log.Logger
	pool   *SessionPool
	types  map[string]*NodeTypeHandler
}

func NewNodeProvider(logger *log.Logger, infoPath string) *NodeProvider {
	p := NodeProvider{
		logger, NewSessionPool(1, infoPath),
		make(map[string]*NodeTypeHandler),
	}
	return &p
}

// AddNodeType adds a handler for a node type to be served.
func (p *NodeProvider) AddNodeType(h *NodeTypeHandler) {
	p.types[h.Name] = h
}

// Serve registers and serves the node types at the given Node service path.
func (p *NodeProvider) Serve(path string) error {
	// Start own NODE service
	var waitGroup sync.WaitGroup
	p.Logger.Println("Starting Node service")
	waitGroup.Add(1)
	go func() {
		defer waitGroup.Done()
		var provider Provider
		var node_ nodeService
		node_.Provider = p
		node_.Pool = p.pool
		provider.Logger = p.Logger
		if err := provider.Serve(path, "Node", &node_); err != nil {
			p.Logger.Printf("service: Could not start Node service: %v", err)
		}
	}()
	s, err := p.pool.New()
	if err != nil {
		return fmt.Errorf("service: Could not get session: %v", err)
	}
	defer p.pool.Free(s)
	if err := s.Info().PublishService("Node", path); err != nil {
		return fmt.Errorf("service: Could not publish node service: %v", err)
	}
	waitGroup.Wait()
	return nil
}

type nodeService struct {
	Provider *NodeProvider
	Pool     *SessionPool
}

func (i nodeService) Request(req Request, reply *Response) error {
	nodeType := req.Node.Type
	var f ActionHandler
	session, err := i.Pool.New()
	if err != nil {
		return fmt.Errorf("service: Could not get session: %v", err)
	}
	defer i.Pool.Free(session)
	switch req.Action {
	case EditAction:
		f = i.Provider.types[nodeType].EditAction
	}
	if f == nil {
		f = i.Provider.types[nodeType].ViewAction
	}
	return f(req, reply, session)
}

func (i *nodeService) GetNodeTypes(req int,
	reply *[]string) error {
	*reply = make([]string, 0)
	for key, _ := range i.Provider.types {
		*reply = append(*reply, key)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/goadesign/goa"
	"github.com/tri125/gwentapi/app"
	"github.com/tri125/gwentapi/controllers"
	"log"
)

// CardController implements the card resource.
type CardController struct {
	*goa.Controller
}

// NewCardController creates a card controller.
func NewCardController(service *goa.Service) *CardController {
	return &CardController{Controller: service.NewController("CardController")}
}

// CardFaction runs the cardFaction action.
func (c *CardController) CardFaction(ctx *app.CardFactionCardContext) error {
	// CardController_CardFaction: start_implement

	// Put your logic here

	// CardController_CardFaction: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// CardLeader runs the cardLeader action.
func (c *CardController) CardLeader(ctx *app.CardLeaderCardContext) error {
	// CardController_CardLeader: start_implement

	// Put your logic here

	// CardController_CardLeader: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// CardRarity runs the cardRarity action.
func (c *CardController) CardRarity(ctx *app.CardRarityCardContext) error {
	// CardController_CardRarity: start_implement

	return ctx.NotFound()

	//res := make(app.GwentapiCardCollection, len(cards))

	// CardController_CardRarity: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// List runs the list action.
func (c *CardController) List(ctx *app.ListCardContext) error {
	// CardController_List: start_implement

	cards, err := controllers.FetchAllCards()
	if err != nil {
		log.Println(err)
		return ctx.InternalServerError()
	}

	res := make(app.GwentapiCardCollection, len(cards))
	for i, card := range cards {

		res[i] = createCard(card)
	}

	// CardController_List: end_implement
	return ctx.OK(res)
}

// Show runs the show action.
func (c *CardController) Show(ctx *app.ShowCardContext) error {
	// CardController_Show: start_implement

	// Put your logic here
	card, err := controllers.FetchCard(ctx.CardID)
	if err != nil {
		log.Println(err)
		return ctx.InternalServerError()
	}
	// CardController_Show: end_implement
	res := createCard(&card)

	return ctx.OK(res)
}

func createCard(card *controllers.CardModel) *app.GwentapiCard {
	c := &app.GwentapiCard{
		ID:     card.ID,
		Href:   app.CardHref(card.ID),
		Name:   card.Name,
		Text:   card.Text,
		Flavor: card.Flavor,
	}

	f := &app.GwentapiFaction{
		ID:   card.Faction.ID,
		Href: app.FactionHref(card.Faction.ID),
		Name: card.Faction.Name,
	}
	c.Faction = f

	t := &app.GwentapiType{
		ID:   card.TypeCard.ID,
		Href: app.TypeHref(card.TypeCard.ID),
		Name: card.TypeCard.Name,
	}
	c.Type = t

	rar := &app.GwentapiRarity{
		ID:   card.Rarity.ID,
		Href: app.RarityHref(card.Rarity.ID),
		Name: card.Rarity.Name,
	}
	c.Rarity = rar

	typeCollection := make(app.GwentapiTypeCollection, len(card.Subtypes))
	for i, cardType := range card.Subtypes {
		subt := &app.GwentapiType{
			ID:   cardType.ID,
			Href: app.TypeHref(cardType.ID),
			Name: cardType.Name,
		}
		typeCollection[i] = subt
	}
	c.Subtypes = typeCollection

	rowCollection := make(app.GwentapiRowCollection, len(card.Rows))
	for i, row := range card.Rows {
		r := &app.GwentapiRow{
			ID:   row.ID,
			Href: app.RowHref(row.ID),
			Name: row.Name,
		}
		rowCollection[i] = r
	}
	c.Rows = rowCollection

	return c
}
<commit_msg>createCard will no longer create a rowCollection if there are no rows to create.<commit_after>package main

import (
	"github.com/goadesign/goa"
	"github.com/tri125/gwentapi/app"
	"github.com/tri125/gwentapi/controllers"
	"log"
)

// CardController implements the card resource.
type CardController struct {
	*goa.Controller
}

// NewCardController creates a card controller.
func NewCardController(service *goa.Service) *CardController {
	return &CardController{Controller: service.NewController("CardController")}
}

// CardFaction runs the cardFaction action.
func (c *CardController) CardFaction(ctx *app.CardFactionCardContext) error {
	// CardController_CardFaction: start_implement

	// Put your logic here

	// CardController_CardFaction: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// CardLeader runs the cardLeader action.
func (c *CardController) CardLeader(ctx *app.CardLeaderCardContext) error {
	// CardController_CardLeader: start_implement

	// Put your logic here

	// CardController_CardLeader: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// CardRarity runs the cardRarity action.
func (c *CardController) CardRarity(ctx *app.CardRarityCardContext) error {
	// CardController_CardRarity: start_implement

	return ctx.NotFound()

	//res := make(app.GwentapiCardCollection, len(cards))

	// CardController_CardRarity: end_implement
	res := app.GwentapiCardCollection{}
	return ctx.OK(res)
}

// List runs the list action.
func (c *CardController) List(ctx *app.ListCardContext) error {
	// CardController_List: start_implement

	cards, err := controllers.FetchAllCards()
	if err != nil {
		log.Println(err)
		return ctx.InternalServerError()
	}

	res := make(app.GwentapiCardCollection, len(cards))
	for i, card := range cards {

		res[i] = createCard(card)
	}

	// CardController_List: end_implement
	return ctx.OK(res)
}

// Show runs the show action.
func (c *CardController) Show(ctx *app.ShowCardContext) error {
	// CardController_Show: start_implement

	// Put your logic here
	card, err := controllers.FetchCard(ctx.CardID)
	if err != nil {
		log.Println(err)
		return ctx.InternalServerError()
	}
	// CardController_Show: end_implement
	res := createCard(&card)

	return ctx.OK(res)
}

func createCard(card *controllers.CardModel) *app.GwentapiCard {
	c := &app.GwentapiCard{
		ID:     card.ID,
		Href:   app.CardHref(card.ID),
		Name:   card.Name,
		Text:   card.Text,
		Flavor: card.Flavor,
	}

	f := &app.GwentapiFaction{
		ID:   card.Faction.ID,
		Href: app.FactionHref(card.Faction.ID),
		Name: card.Faction.Name,
	}
	c.Faction = f

	t := &app.GwentapiType{
		ID:   card.TypeCard.ID,
		Href: app.TypeHref(card.TypeCard.ID),
		Name: card.TypeCard.Name,
	}
	c.Type = t

	rar := &app.GwentapiRarity{
		ID:   card.Rarity.ID,
		Href: app.RarityHref(card.Rarity.ID),
		Name: card.Rarity.Name,
	}
	c.Rarity = rar

	typeCollection := make(app.GwentapiTypeCollection, len(card.Subtypes))
	for i, cardType := range card.Subtypes {
		subt := &app.GwentapiType{
			ID:   cardType.ID,
			Href: app.TypeHref(cardType.ID),
			Name: cardType.Name,
		}
		typeCollection[i] = subt
	}
	c.Subtypes = typeCollection

	if len(card.Rows) != 0 {
		rowCollection := make(app.GwentapiRowCollection, len(card.Rows))
		for i, row := range card.Rows {
			r := &app.GwentapiRow{
				ID:   row.ID,
				Href: app.RowHref(row.ID),
				Name: row.Name,
			}
			rowCollection[i] = r
		}
		c.Rows = rowCollection
	}

	return c
}
<|endoftext|>


<commit_before>// Copyright 2021 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 instantiation of generic types
// through substitution of type parameters by type arguments.

package types2

import (
	"cmd/compile/internal/syntax"
	"fmt"
)

// Instantiate instantiates the type typ with the given type arguments
// targs. To check type constraint satisfaction, verify must be set.
// pos and posList correspond to the instantiation and type argument
// positions respectively; posList may be nil or shorter than the number
// of type arguments provided.
// typ must be a *Named or a *Signature type, and its number of type
// parameters must match the number of provided type arguments.
// The receiver (check) may be nil if and only if verify is not set.
// The result is a new, instantiated (not generic) type of the same kind
// (either a *Named or a *Signature).
// Any methods attached to a *Named are simply copied; they are not
// instantiated.
func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) {
	// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
	var inst Type
	switch t := typ.(type) {
	case *Named:
		inst = check.instantiateLazy(pos, t, targs)
	case *Signature:
		tparams := t.TParams().list()
		defer func() {
			// If we had an unexpected failure somewhere don't panic below when
			// asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
			// is returned.
			if _, ok := res.(*Signature); !ok {
				return
			}
			// If the signature doesn't use its type parameters, subst
			// will not make a copy. In that case, make a copy now (so
			// we can set tparams to nil w/o causing side-effects).
			if t == res {
				copy := *t
				res = &copy
			}
			// After instantiating a generic signature, it is not generic
			// anymore; we need to set tparams to nil.
			res.(*Signature).tparams = nil
		}()
		inst = check.instantiate(pos, typ, tparams, targs, nil)
	default:
		// only types and functions can be generic
		panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
	}

	if verify {
		if check == nil {
			panic("cannot have nil Checker if verifying constraints")
		}
		assert(len(posList) <= len(targs))
		check.later(func() {
			// Collect tparams again because lazily loaded *Named types may not have
			// had tparams set up above.
			var tparams []*TypeName
			switch t := typ.(type) {
			case *Named:
				tparams = t.TParams().list()
			case *Signature:
				tparams = t.TParams().list()
			}
			// Avoid duplicate errors; instantiate will have complained if tparams
			// and targs do not have the same length.
			if len(tparams) == len(targs) {
				check.verify(pos, tparams, targs, posList)
			}
		})
	}

	return inst
}

func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) {
	// the number of supplied types must match the number of type parameters
	if len(targs) != len(tparams) {
		// TODO(gri) provide better error message
		if check != nil {
			check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams))
			return Typ[Invalid]
		}
		panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams)))
	}

	if check != nil && check.conf.Trace {
		check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs))
		check.indent++
		defer func() {
			check.indent--
			var under Type
			if res != nil {
				// Calling under() here may lead to endless instantiations.
				// Test case: type T[P any] T[P]
				// TODO(gri) investigate if that's a bug or to be expected.
				under = safeUnderlying(res)
			}
			check.trace(pos, "=> %s (under = %s)", res, under)
		}()
	}

	if len(tparams) == 0 {
		return typ // nothing to do (minor optimization)
	}

	return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap)
}

// instantiateLazy avoids actually instantiating the type until needed. typ
// must be a *Named type.
func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type) Type {
	h := instantiatedHash(orig, targs)
	if check != nil {
		// typ may already have been instantiated with identical type arguments. In
		// that case, re-use the existing instance.
		if named := check.typMap[h]; named != nil {
			return named
		}
	}

	tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
	named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded
	named.targs = targs
	named.instance = &instance{pos}
	if check != nil {
		check.typMap[h] = named
	}

	return named
}

func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type, posList []syntax.Pos) {
	smap := makeSubstMap(tparams, targs)
	for i, tname := range tparams {
		// best position for error reporting
		pos := pos
		if i < len(posList) {
			pos = posList[i]
		}

		// stop checking bounds after the first failure
		if !check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap) {
			break
		}
	}
}

// satisfies reports whether the type argument targ satisfies the constraint of type parameter
// parameter tpar (after any of its type parameters have been substituted through smap).
// A suitable error is reported if the result is false.
// TODO(gri) This should be a method of interfaces or type sets.
func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) bool {
	iface := tpar.iface()
	if iface.Empty() {
		return true // no type bound
	}

	// The type parameter bound is parameterized with the same type parameters
	// as the instantiated type; before we can use it for bounds checking we
	// need to instantiate it with the type arguments with which we instantiate
	// the parameterized type.
	iface = check.subst(pos, iface, smap, nil).(*Interface)

	// if iface is comparable, targ must be comparable
	// TODO(gri) the error messages needs to be better, here
	if iface.IsComparable() && !Comparable(targ) {
		if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() {
			check.softErrorf(pos, "%s has no constraints", targ)
			return false
		}
		check.softErrorf(pos, "%s does not satisfy comparable", targ)
		return false
	}

	// targ must implement iface (methods)
	// - check only if we have methods
	if iface.NumMethods() > 0 {
		// If the type argument is a pointer to a type parameter, the type argument's
		// method set is empty.
		// TODO(gri) is this what we want? (spec question)
		if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
			check.errorf(pos, "%s has no methods", targ)
			return false
		}
		if m, wrong := check.missingMethod(targ, iface, true); m != nil {
			// TODO(gri) needs to print updated name to avoid major confusion in error message!
			//           (print warning for now)
			// Old warning:
			// check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m)
			if wrong != nil {
				// TODO(gri) This can still report uninstantiated types which makes the error message
				//           more difficult to read then necessary.
				check.softErrorf(pos,
					"%s does not satisfy %s: wrong method signature\n\tgot  %s\n\twant %s",
					targ, tpar.bound, wrong, m,
				)
			} else {
				check.softErrorf(pos, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name)
			}
			return false
		}
	}

	// targ's underlying type must also be one of the interface types listed, if any
	if !iface.typeSet().hasTerms() {
		return true // nothing to do
	}

	// If targ is itself a type parameter, each of its possible types, but at least one, must be in the
	// list of iface types (i.e., the targ type list must be a non-empty subset of the iface types).
	if targ := asTypeParam(targ); targ != nil {
		targBound := targ.iface()
		if !targBound.typeSet().hasTerms() {
			check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
			return false
		}
		if !targBound.typeSet().subsetOf(iface.typeSet()) {
			// TODO(gri) need better error message
			check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound)
			return false
		}
		return true
	}

	// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
	if !iface.typeSet().includes(targ) {
		// TODO(gri) better error message
		check.softErrorf(pos, "%s does not satisfy %s", targ, tpar.bound)
		return false
	}

	return true
}
<commit_msg>cmd/compile/internal/types2: change Checker.verify to return an error<commit_after>// Copyright 2021 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 instantiation of generic types
// through substitution of type parameters by type arguments.

package types2

import (
	"cmd/compile/internal/syntax"
	"errors"
	"fmt"
)

// Instantiate instantiates the type typ with the given type arguments
// targs. To check type constraint satisfaction, verify must be set.
// pos and posList correspond to the instantiation and type argument
// positions respectively; posList may be nil or shorter than the number
// of type arguments provided.
// typ must be a *Named or a *Signature type, and its number of type
// parameters must match the number of provided type arguments.
// The receiver (check) may be nil if and only if verify is not set.
// The result is a new, instantiated (not generic) type of the same kind
// (either a *Named or a *Signature).
// Any methods attached to a *Named are simply copied; they are not
// instantiated.
func (check *Checker) Instantiate(pos syntax.Pos, typ Type, targs []Type, posList []syntax.Pos, verify bool) (res Type) {
	// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
	var inst Type
	switch t := typ.(type) {
	case *Named:
		inst = check.instantiateLazy(pos, t, targs)
	case *Signature:
		tparams := t.TParams().list()
		defer func() {
			// If we had an unexpected failure somewhere don't panic below when
			// asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
			// is returned.
			if _, ok := res.(*Signature); !ok {
				return
			}
			// If the signature doesn't use its type parameters, subst
			// will not make a copy. In that case, make a copy now (so
			// we can set tparams to nil w/o causing side-effects).
			if t == res {
				copy := *t
				res = &copy
			}
			// After instantiating a generic signature, it is not generic
			// anymore; we need to set tparams to nil.
			res.(*Signature).tparams = nil
		}()
		inst = check.instantiate(pos, typ, tparams, targs, nil)
	default:
		// only types and functions can be generic
		panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
	}

	if verify {
		if check == nil {
			panic("cannot have nil Checker if verifying constraints")
		}
		assert(len(posList) <= len(targs))
		check.later(func() {
			// Collect tparams again because lazily loaded *Named types may not have
			// had tparams set up above.
			var tparams []*TypeName
			switch t := typ.(type) {
			case *Named:
				tparams = t.TParams().list()
			case *Signature:
				tparams = t.TParams().list()
			}
			// Avoid duplicate errors; instantiate will have complained if tparams
			// and targs do not have the same length.
			if len(tparams) == len(targs) {
				if i, err := check.verify(pos, tparams, targs); err != nil {
					// best position for error reporting
					pos := pos
					if i < len(posList) {
						pos = posList[i]
					}
					check.softErrorf(pos, err.Error())
				}
			}
		})
	}

	return inst
}

func (check *Checker) instantiate(pos syntax.Pos, typ Type, tparams []*TypeName, targs []Type, typMap map[string]*Named) (res Type) {
	// the number of supplied types must match the number of type parameters
	if len(targs) != len(tparams) {
		// TODO(gri) provide better error message
		if check != nil {
			check.errorf(pos, "got %d arguments but %d type parameters", len(targs), len(tparams))
			return Typ[Invalid]
		}
		panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), len(tparams)))
	}

	if check != nil && check.conf.Trace {
		check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs))
		check.indent++
		defer func() {
			check.indent--
			var under Type
			if res != nil {
				// Calling under() here may lead to endless instantiations.
				// Test case: type T[P any] T[P]
				// TODO(gri) investigate if that's a bug or to be expected.
				under = safeUnderlying(res)
			}
			check.trace(pos, "=> %s (under = %s)", res, under)
		}()
	}

	if len(tparams) == 0 {
		return typ // nothing to do (minor optimization)
	}

	return check.subst(pos, typ, makeSubstMap(tparams, targs), typMap)
}

// instantiateLazy avoids actually instantiating the type until needed. typ
// must be a *Named type.
func (check *Checker) instantiateLazy(pos syntax.Pos, orig *Named, targs []Type) Type {
	h := instantiatedHash(orig, targs)
	if check != nil {
		// typ may already have been instantiated with identical type arguments. In
		// that case, re-use the existing instance.
		if named := check.typMap[h]; named != nil {
			return named
		}
	}

	tname := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
	named := check.newNamed(tname, orig, nil, nil, nil) // methods and tparams are set when named is loaded
	named.targs = targs
	named.instance = &instance{pos}
	if check != nil {
		check.typMap[h] = named
	}

	return named
}

func (check *Checker) verify(pos syntax.Pos, tparams []*TypeName, targs []Type) (int, error) {
	smap := makeSubstMap(tparams, targs)
	for i, tname := range tparams {
		// stop checking bounds after the first failure
		if err := check.satisfies(pos, targs[i], tname.typ.(*TypeParam), smap); err != nil {
			return i, err
		}
	}
	return -1, nil
}

// satisfies reports whether the type argument targ satisfies the constraint of type parameter
// parameter tpar (after any of its type parameters have been substituted through smap).
// A suitable error is reported if the result is false.
// TODO(gri) This should be a method of interfaces or type sets.
func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap substMap) error {
	iface := tpar.iface()
	if iface.Empty() {
		return nil // no type bound
	}

	// TODO(rfindley): it would be great if users could pass in a qualifier here,
	// rather than falling back to verbose qualification. Maybe this can be part
	// of a the shared environment.
	var qf Qualifier
	if check != nil {
		qf = check.qualifier
	}
	errorf := func(format string, args ...interface{}) error {
		return errors.New(sprintf(qf, format, args...))
	}

	// The type parameter bound is parameterized with the same type parameters
	// as the instantiated type; before we can use it for bounds checking we
	// need to instantiate it with the type arguments with which we instantiate
	// the parameterized type.
	iface = check.subst(pos, iface, smap, nil).(*Interface)

	// if iface is comparable, targ must be comparable
	// TODO(gri) the error messages needs to be better, here
	if iface.IsComparable() && !Comparable(targ) {
		if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() {
			return errorf("%s has no constraints", targ)
		}
		return errorf("%s does not satisfy comparable", targ)
	}

	// targ must implement iface (methods)
	// - check only if we have methods
	if iface.NumMethods() > 0 {
		// If the type argument is a pointer to a type parameter, the type argument's
		// method set is empty.
		// TODO(gri) is this what we want? (spec question)
		if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
			return errorf("%s has no methods", targ)
		}
		if m, wrong := check.missingMethod(targ, iface, true); m != nil {
			// TODO(gri) needs to print updated name to avoid major confusion in error message!
			//           (print warning for now)
			// Old warning:
			// check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m)
			if wrong != nil {
				// TODO(gri) This can still report uninstantiated types which makes the error message
				//           more difficult to read then necessary.
				return errorf("%s does not satisfy %s: wrong method signature\n\tgot  %s\n\twant %s",
					targ, tpar.bound, wrong, m,
				)
			}
			return errorf("%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name)
		}
	}

	// targ's underlying type must also be one of the interface types listed, if any
	if !iface.typeSet().hasTerms() {
		return nil // nothing to do
	}

	// If targ is itself a type parameter, each of its possible types, but at least one, must be in the
	// list of iface types (i.e., the targ type list must be a non-empty subset of the iface types).
	if targ := asTypeParam(targ); targ != nil {
		targBound := targ.iface()
		if !targBound.typeSet().hasTerms() {
			return errorf("%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
		}
		if !targBound.typeSet().subsetOf(iface.typeSet()) {
			// TODO(gri) need better error message
			return errorf("%s does not satisfy %s", targ, tpar.bound)
		}
		return nil
	}

	// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
	if !iface.typeSet().includes(targ) {
		// TODO(gri) better error message
		return errorf("%s does not satisfy %s", targ, tpar.bound)
	}

	return nil
}
<|endoftext|>


<commit_before>package connections

type OutputMessageType uint8

const (
	OutputMessageTypeGameEvent OutputMessageType = iota
	OutputMessageGroupNotice
)

type OutputMessage struct {
	Type    OutputMessageType
	Payload interface{}
}
<commit_msg>Create stringer method for OutputMessage struct<commit_after>package connections

type OutputMessageType uint8

const (
	OutputMessageTypeGameEvent OutputMessageType = iota
	OutputMessageTypeGroupNotice
	OutputMessageTypeConnectionNotice
)

var outputMessageTypeLabels = map[OutputMessageType]string{
	OutputMessageTypeGameEvent:        "game_event",
	OutputMessageTypeGroupNotice:      "group_notice",
	OutputMessageTypeConnectionNotice: "connection_notice",
}

func (t OutputMessageType) String() string {
	if label, ok := outputMessageTypeLabels[t]; ok {
		return label
	}
	return "unknown"
}

type OutputMessage struct {
	Type    OutputMessageType
	Payload interface{}
}
<|endoftext|>