<commit_before>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016-2018
	All Rights Reserved
	Documentation http://djthorpe.github.io/gopi/
	For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"time"
)

/////////////////////////////////////////////////////////////////////
// TYPES

type Metric struct {
	Rate  MetricRate
	Type  MetricType
	Name  string
	Value uint    // Last value
	Mean  float64 // Mean value per hour (or whatever rate)
	Total uint    // Total over the past hour (or whatever rate)
}

type (
	MetricRate uint
	MetricType uint
)

/////////////////////////////////////////////////////////////////////
// INTERFACE

// Metrics returns various metrics for host and
// custom metrics
type Metrics interface {
	Driver

	// Uptimes for host and for application
	UptimeHost() time.Duration
	UptimeApp() time.Duration

	// Load Average (1, 5 and 15 minutes)
	LoadAverage() (float64, float64, float64)

	// Return metric channel, which when you send a value on
	// it will store the metric
	NewMetricUint(MetricType, MetricRate, string) (chan<- uint, error)

	// Return all metrics of a particular type, or METRIC_TYPE_NONE
	// for all metrics
	Metrics(MetricType) []*Metric
}

/////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	METRIC_RATE_NONE MetricRate = iota
	METRIC_RATE_SECOND
	METRIC_RATE_MINUTE
	METRIC_RATE_HOUR
)

const (
	METRIC_TYPE_NONE    MetricType = iota
	METRIC_TYPE_PURE               // Pure number
	METRIC_TYPE_CELCIUS            // Temperature
)

/////////////////////////////////////////////////////////////////////
// STRINGIFY

func (v MetricRate) String() string {
	switch v {
	case METRIC_RATE_SECOND:
		return "METRIC_RATE_SECOND"
	case METRIC_RATE_MINUTE:
		return "METRIC_RATE_MINUTE"
	case METRIC_RATE_HOUR:
		return "METRIC_RATE_HOUR"
	default:
		return "[?? Invalid MetricRate value]"
	}
}
<commit_msg>Updated metrics<commit_after>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016-2018
	All Rights Reserved
	Documentation http://djthorpe.github.io/gopi/
	For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"time"
)

/////////////////////////////////////////////////////////////////////
// TYPES

type Metric interface {
	// Return the metric rate (store values over a period)
	Rate() MetricRate

	// Return the metric type (the units used for the metric)
	Type() MetricType

	// Return the name of the metric
	Name() string

	// Return the last metric value as a uint
	UintValue() uint

	// Return the last metric value as a float64
	FloatValue() float64
}

type (
	MetricRate uint
	MetricType uint
)

/////////////////////////////////////////////////////////////////////
// INTERFACE

// Metrics returns various metrics for host and
// custom metrics
type Metrics interface {
	Driver

	// Uptimes for host and for application
	UptimeHost() time.Duration
	UptimeApp() time.Duration

	// Load Average (1, 5 and 15 minutes)
	LoadAverage() (float64, float64, float64)

	// Return metric channel which records uint values
	NewMetricUint(MetricType, MetricRate, string) (chan<- uint, error)

	// Return metric channel which records float64 values
	NewMetricFloat64(MetricType, MetricRate, string) (chan<- float64, error)

	// Return all metrics of a particular type, or METRIC_TYPE_NONE
	// for all metrics
	Metrics(MetricType) []*Metric
}

/////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	METRIC_RATE_NONE MetricRate = iota
	METRIC_RATE_SECOND
	METRIC_RATE_MINUTE
	METRIC_RATE_HOUR
	METRIC_RATE_DAY
)

const (
	METRIC_TYPE_NONE    MetricType = iota
	METRIC_TYPE_PURE               // Pure number
	METRIC_TYPE_CELCIUS            // Temperature
)

/////////////////////////////////////////////////////////////////////
// STRINGIFY

func (v MetricRate) String() string {
	switch v {
	case METRIC_RATE_SECOND:
		return "METRIC_RATE_SECOND"
	case METRIC_RATE_MINUTE:
		return "METRIC_RATE_MINUTE"
	case METRIC_RATE_HOUR:
		return "METRIC_RATE_HOUR"
	case METRIC_RATE_DAY:
		return "METRIC_RATE_DAY"
	default:
		return "[?? Invalid MetricRate value]"
	}
}

func (t MetricType) String() string {
	switch t {
	case METRIC_TYPE_PURE:
		return "METRIC_TYPE_PURE"
	case METRIC_TYPE_CELCIUS:
		return "METRIC_TYPE_CELCIUS"
	default:
		return "[?? Invalid MetricType value]"
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"errors"
	"fmt"
	_ "github.com/bmizerany/pq"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"
)

type MigrationRecord struct {
	VersionId int64
	TStamp    time.Time
	IsApplied bool // was this a result of up() or down()
}

type Migration struct {
	Version  int64
	Next     int64  // next version, or -1 if none
	Previous int64  // previous version, -1 if none
	Source   string // .go or .sql script
}

type MigrationSlice []Migration

// helpers so we can use pkg sort
func (s MigrationSlice) Len() int           { return len(s) }
func (s MigrationSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s MigrationSlice) Less(i, j int) bool { return s[i].Version < s[j].Version }

type MigrationMap struct {
	Migrations MigrationSlice // migrations, sorted according to Direction
	Direction  bool           // sort direction: true -> Up, false -> Down
}

func runMigrations(conf *DBConf, migrationsDir string, target int64) {

	db, err := sql.Open(conf.Driver, conf.OpenStr)
	if err != nil {
		log.Fatal("couldn't open DB:", err)
	}
	defer db.Close()

	current, e := ensureDBVersion(db)
	if e != nil {
		log.Fatalf("couldn't get DB version: %v", e)
	}

	mm, err := collectMigrations(migrationsDir, current, target)
	if err != nil {
		log.Fatal(err)
	}

	if len(mm.Migrations) == 0 {
		fmt.Printf("goose: no migrations to run. current version: %d\n", current)
		return
	}

	mm.Sort(current < target)

	fmt.Printf("goose: migrating db environment '%v', current version: %d, target: %d\n",
		conf.Env, current, target)

	for _, m := range mm.Migrations {

		var e error

		switch path.Ext(m.Source) {
		case ".go":
			e = runGoMigration(conf, m.Source, m.Version, mm.Direction)
		case ".sql":
			e = runSQLMigration(db, m.Source, m.Version, mm.Direction)
		}

		if e != nil {
			log.Fatalf("FAIL %v, quitting migration", e)
		}

		fmt.Println("OK   ", path.Base(m.Source))
	}
}

// collect all the valid looking migration scripts in the
// migrations folder, and key them by version
func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap, err error) {

	mm = &MigrationMap{}

	// extract the numeric component of each migration,
	// filter out any uninteresting files,
	// and ensure we only have one file per migration version.
	filepath.Walk(dirpath, func(name string, info os.FileInfo, err error) error {

		if v, e := numericComponent(name); e == nil {

			for _, m := range mm.Migrations {
				if v == m.Version {
					log.Fatalf("more than one file specifies the migration for version %d (%s and %s)",
						v, m.Source, path.Join(dirpath, name))
				}
			}

			if versionFilter(v, current, target) {
				mm.Append(v, name)
			}
		}

		return nil
	})

	return mm, nil
}

func versionFilter(v, current, target int64) bool {

	if target > current {
		return v > current && v <= target
	}

	if target < current {
		return v <= current && v > target
	}

	return false
}

func (mm *MigrationMap) Append(v int64, source string) {
	mm.Migrations = append(mm.Migrations, Migration{
		Version:  v,
		Next:     -1,
		Previous: -1,
		Source:   source,
	})
}

func (mm *MigrationMap) Sort(direction bool) {
	sort.Sort(mm.Migrations)

	// set direction, and reverse order if need be
	mm.Direction = direction
	if mm.Direction == false {
		for i, j := 0, len(mm.Migrations)-1; i < j; i, j = i+1, j-1 {
			mm.Migrations[i], mm.Migrations[j] = mm.Migrations[j], mm.Migrations[i]
		}
	}

	// now that we're sorted in the appropriate direction,
	// populate next and previous for each migration
	for i, m := range mm.Migrations {
		prev := int64(-1)
		if i > 0 {
			prev = mm.Migrations[i-1].Version
			mm.Migrations[i-1].Next = m.Version
		}
		m.Previous = prev
	}
}

// look for migration scripts with names in the form:
//  XXX_descriptivename.ext
// where XXX specifies the version number
// and ext specifies the type of migration
func numericComponent(name string) (int64, error) {

	base := path.Base(name)

	if ext := path.Ext(base); ext != ".go" && ext != ".sql" {
		return 0, errors.New("not a recognized migration file type")
	}

	idx := strings.Index(base, "_")
	if idx < 0 {
		return 0, errors.New("no separator found")
	}

	n, e := strconv.ParseInt(base[:idx], 10, 64)
	if e == nil && n <= 0 {
		return 0, errors.New("migration IDs must be greater than zero")
	}

	return n, e
}

// retrieve the current version for this DB.
// Create and initialize the DB version table if it doesn't exist.
func ensureDBVersion(db *sql.DB) (int64, error) {

	rows, err := db.Query("SELECT version_id, is_applied from goose_db_version ORDER BY tstamp DESC;")
	if err != nil {
		// XXX: cross platform method to detect failure reason
		// for now, assume it was because the table didn't exist, and try to create it
		return 0, createVersionTable(db)
	}

	// The most recent record for each migration specifies
	// whether it has been applied or rolled back.
	// The first version we find that has been applied is the current version.

	toSkip := make([]int64, 0)

	for rows.Next() {
		var row MigrationRecord
		if err = rows.Scan(&row.VersionId, &row.IsApplied); err != nil {
			log.Fatal("error scanning rows:", err)
		}

		// have we already marked this version to be skipped?
		skip := false
		for _, v := range toSkip {
			if v == row.VersionId {
				skip = true
				break
			}
		}

		// if version has been applied and not marked to be skipped, we're done
		if row.IsApplied && !skip {
			return row.VersionId, nil
		}

		// version is either not applied, or we've already seen a more
		// recent version of it that was not applied.
		if !skip {
			toSkip = append(toSkip, row.VersionId)
		}
	}

	panic("failure in ensureDBVersion()")
}

func createVersionTable(db *sql.DB) error {
	txn, err := db.Begin()
	if err != nil {
		return err
	}

	// create the table and insert an initial value of 0
	create := `CREATE TABLE goose_db_version (
                version_id bigint NOT NULL,
                is_applied boolean NOT NULL,
                tstamp timestamp NULL default now(),
                PRIMARY KEY(tstamp)
              );`
	insert := "INSERT INTO goose_db_version (version_id, is_applied) VALUES (0, true);"

	for _, str := range []string{create, insert} {
		if _, err := txn.Exec(str); err != nil {
			txn.Rollback()
			return err
		}
	}

	return txn.Commit()
}

// wrapper for ensureDBVersion for callers that don't already have
// their own DB instance
func getDBVersion(conf *DBConf) int64 {

	db, err := sql.Open(conf.Driver, conf.OpenStr)
	if err != nil {
		log.Fatal("couldn't open DB:", err)
	}
	defer db.Close()

	version, err := ensureDBVersion(db)
	if err != nil {
		log.Fatalf("couldn't get DB version: %v", err)
	}

	return version
}
<commit_msg>Load the mymysql database driver<commit_after>package main

import (
	"database/sql"
	"errors"
	"fmt"
	_ "github.com/bmizerany/pq"
	_ "github.com/ziutek/mymysql/godrv"
	"log"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"
)

type MigrationRecord struct {
	VersionId int64
	TStamp    time.Time
	IsApplied bool // was this a result of up() or down()
}

type Migration struct {
	Version  int64
	Next     int64  // next version, or -1 if none
	Previous int64  // previous version, -1 if none
	Source   string // .go or .sql script
}

type MigrationSlice []Migration

// helpers so we can use pkg sort
func (s MigrationSlice) Len() int           { return len(s) }
func (s MigrationSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s MigrationSlice) Less(i, j int) bool { return s[i].Version < s[j].Version }

type MigrationMap struct {
	Migrations MigrationSlice // migrations, sorted according to Direction
	Direction  bool           // sort direction: true -> Up, false -> Down
}

func runMigrations(conf *DBConf, migrationsDir string, target int64) {

	db, err := sql.Open(conf.Driver, conf.OpenStr)
	if err != nil {
		log.Fatal("couldn't open DB:", err)
	}
	defer db.Close()

	current, e := ensureDBVersion(db)
	if e != nil {
		log.Fatalf("couldn't get DB version: %v", e)
	}

	mm, err := collectMigrations(migrationsDir, current, target)
	if err != nil {
		log.Fatal(err)
	}

	if len(mm.Migrations) == 0 {
		fmt.Printf("goose: no migrations to run. current version: %d\n", current)
		return
	}

	mm.Sort(current < target)

	fmt.Printf("goose: migrating db environment '%v', current version: %d, target: %d\n",
		conf.Env, current, target)

	for _, m := range mm.Migrations {

		var e error

		switch path.Ext(m.Source) {
		case ".go":
			e = runGoMigration(conf, m.Source, m.Version, mm.Direction)
		case ".sql":
			e = runSQLMigration(db, m.Source, m.Version, mm.Direction)
		}

		if e != nil {
			log.Fatalf("FAIL %v, quitting migration", e)
		}

		fmt.Println("OK   ", path.Base(m.Source))
	}
}

// collect all the valid looking migration scripts in the
// migrations folder, and key them by version
func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap, err error) {

	mm = &MigrationMap{}

	// extract the numeric component of each migration,
	// filter out any uninteresting files,
	// and ensure we only have one file per migration version.
	filepath.Walk(dirpath, func(name string, info os.FileInfo, err error) error {

		if v, e := numericComponent(name); e == nil {

			for _, m := range mm.Migrations {
				if v == m.Version {
					log.Fatalf("more than one file specifies the migration for version %d (%s and %s)",
						v, m.Source, path.Join(dirpath, name))
				}
			}

			if versionFilter(v, current, target) {
				mm.Append(v, name)
			}
		}

		return nil
	})

	return mm, nil
}

func versionFilter(v, current, target int64) bool {

	if target > current {
		return v > current && v <= target
	}

	if target < current {
		return v <= current && v > target
	}

	return false
}

func (mm *MigrationMap) Append(v int64, source string) {
	mm.Migrations = append(mm.Migrations, Migration{
		Version:  v,
		Next:     -1,
		Previous: -1,
		Source:   source,
	})
}

func (mm *MigrationMap) Sort(direction bool) {
	sort.Sort(mm.Migrations)

	// set direction, and reverse order if need be
	mm.Direction = direction
	if mm.Direction == false {
		for i, j := 0, len(mm.Migrations)-1; i < j; i, j = i+1, j-1 {
			mm.Migrations[i], mm.Migrations[j] = mm.Migrations[j], mm.Migrations[i]
		}
	}

	// now that we're sorted in the appropriate direction,
	// populate next and previous for each migration
	for i, m := range mm.Migrations {
		prev := int64(-1)
		if i > 0 {
			prev = mm.Migrations[i-1].Version
			mm.Migrations[i-1].Next = m.Version
		}
		m.Previous = prev
	}
}

// look for migration scripts with names in the form:
//  XXX_descriptivename.ext
// where XXX specifies the version number
// and ext specifies the type of migration
func numericComponent(name string) (int64, error) {

	base := path.Base(name)

	if ext := path.Ext(base); ext != ".go" && ext != ".sql" {
		return 0, errors.New("not a recognized migration file type")
	}

	idx := strings.Index(base, "_")
	if idx < 0 {
		return 0, errors.New("no separator found")
	}

	n, e := strconv.ParseInt(base[:idx], 10, 64)
	if e == nil && n <= 0 {
		return 0, errors.New("migration IDs must be greater than zero")
	}

	return n, e
}

// retrieve the current version for this DB.
// Create and initialize the DB version table if it doesn't exist.
func ensureDBVersion(db *sql.DB) (int64, error) {

	rows, err := db.Query("SELECT version_id, is_applied from goose_db_version ORDER BY tstamp DESC;")
	if err != nil {
		// XXX: cross platform method to detect failure reason
		// for now, assume it was because the table didn't exist, and try to create it
		return 0, createVersionTable(db)
	}

	// The most recent record for each migration specifies
	// whether it has been applied or rolled back.
	// The first version we find that has been applied is the current version.

	toSkip := make([]int64, 0)

	for rows.Next() {
		var row MigrationRecord
		if err = rows.Scan(&row.VersionId, &row.IsApplied); err != nil {
			log.Fatal("error scanning rows:", err)
		}

		// have we already marked this version to be skipped?
		skip := false
		for _, v := range toSkip {
			if v == row.VersionId {
				skip = true
				break
			}
		}

		// if version has been applied and not marked to be skipped, we're done
		if row.IsApplied && !skip {
			return row.VersionId, nil
		}

		// version is either not applied, or we've already seen a more
		// recent version of it that was not applied.
		if !skip {
			toSkip = append(toSkip, row.VersionId)
		}
	}

	panic("failure in ensureDBVersion()")
}

func createVersionTable(db *sql.DB) error {
	txn, err := db.Begin()
	if err != nil {
		return err
	}

	// create the table and insert an initial value of 0
	create := `CREATE TABLE goose_db_version (
                version_id bigint NOT NULL,
                is_applied boolean NOT NULL,
                tstamp timestamp NULL default now(),
                PRIMARY KEY(tstamp)
              );`
	insert := "INSERT INTO goose_db_version (version_id, is_applied) VALUES (0, true);"

	for _, str := range []string{create, insert} {
		if _, err := txn.Exec(str); err != nil {
			txn.Rollback()
			return err
		}
	}

	return txn.Commit()
}

// wrapper for ensureDBVersion for callers that don't already have
// their own DB instance
func getDBVersion(conf *DBConf) int64 {

	db, err := sql.Open(conf.Driver, conf.OpenStr)
	if err != nil {
		log.Fatal("couldn't open DB:", err)
	}
	defer db.Close()

	version, err := ensureDBVersion(db)
	if err != nil {
		log.Fatalf("couldn't get DB version: %v", err)
	}

	return version
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"runtime/pprof"
	"time"
)

const (
	KB          = 1024
	MB          = KB * 1024
	BLOCK_SIZE  = 4 * KB
	BUFFER_SIZE = 1024
)

type Reading struct {
	Data   []byte
	Offset int64
	Error  error
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profiling data")
	flag.Parse()

	if *cpuprofile != "" {
		cpu, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			os.Exit(1)
		}
		pprof.StartCPUProfile(cpu)
		defer pprof.StopCPUProfile()
	}

	if flag.NArg() != 2 {
		fmt.Fprintf(os.Stderr, "%s source destination", os.Args[0])
		os.Exit(1)
	}
	src := flag.Arg(0)
	dst := flag.Arg(1)

	start := time.Now()
	reads, writes, err := Sync(src, dst)
	duration := time.Since(start)

	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err.Error())
		os.Exit(2)
	}

	ratio := 0.0
	if reads > 0 {
		ratio = float64(writes) / float64(reads) * 100
	}
	fmt.Printf("reads\t%d\nwrites\t%d\nratio\t%3.2f%%\ntime\t%v\n", reads, writes, ratio, duration)
}

func Sync(src, dst string) (reads, writes int, err error) {

	readings := make(chan Reading, BUFFER_SIZE)
	stop, clean := Reader(src, readings)
	defer func() { <-clean }()
	defer close(stop)

	fd, err := os.OpenFile(dst, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer fd.Close()
	defer fd.Sync()

	bd := make([]byte, BLOCK_SIZE)

	for {
		reading := <-readings
		nd, errd := fd.Read(bd)
		reads++

		if !Compare(reading.Data, bd[:nd]) {
			_, err = fd.WriteAt(reading.Data, reading.Offset)
			writes++
			if err != nil {
				return
			}
		}

		switch {
		case reading.Error == io.EOF:
			err = fd.Truncate(reading.Offset)
			if err != nil {
				return
			}
			return
		case errd == io.EOF:
			continue
		case reading.Error != nil:
			err = reading.Error
			return
		case errd != nil:
			err = errd
			return
		}
	}
}

func Reader(name string, readings chan Reading) (stop, clean chan struct{}) {

	stop = make(chan struct{})
	clean = make(chan struct{})

	go func() {
		defer close(clean)
		defer close(readings)

		file, err := os.Open(name)
		if err != nil {
			readings <- Reading{nil, 0, err}
			return
		}
		defer file.Close()

		offset := int64(0)
		for {
			select {
			case <-stop:
				return
			default:
				data := make([]byte, BLOCK_SIZE)
				n, err := file.Read(data)
				readings <- Reading{data[:n], offset, err}
				offset += int64(n)
				if err == io.EOF {
					return
				}
			}
		}

	}()

	return
}

func Compare(b1, b2 []byte) bool {
	if len(b1) != len(b2) {
		return false
	}
	for i := 0; i < len(b1); i++ {
		if b1[i] != b2[i] {
			return false
		}
	}
	return true
}
<commit_msg>readings both files through channels<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"runtime/pprof"
	"time"
)

const (
	KB          = 1024
	MB          = KB * 1024
	BLOCK_SIZE  = 4 * KB
	BUFFER_SIZE = 1024
)

type Reading struct {
	Data   []byte
	Offset int64
	Error  error
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profiling data")
	flag.Parse()

	if *cpuprofile != "" {
		cpu, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			os.Exit(1)
		}
		pprof.StartCPUProfile(cpu)
		defer pprof.StopCPUProfile()
	}

	if flag.NArg() != 2 {
		fmt.Fprintf(os.Stderr, "%s source destination", os.Args[0])
		os.Exit(1)
	}
	src := flag.Arg(0)
	dst := flag.Arg(1)

	start := time.Now()
	reads, writes, err := Sync(src, dst)
	duration := time.Since(start)

	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err.Error())
		os.Exit(2)
	}

	ratio := 0.0
	if reads > 0 {
		ratio = float64(writes) / float64(reads) * 100
	}
	fmt.Printf("reads\t%d\nwrites\t%d\nratio\t%3.2f%%\ntime\t%v\n", reads, writes, ratio, duration)
}

func Sync(src, dst string) (reads, writes int, err error) {

	srs := make(chan Reading, BUFFER_SIZE)
	ss, sc := Reader(src, srs)
	defer func() { <-sc }()
	defer close(ss)

	drs := make(chan Reading, BUFFER_SIZE)
	ds, dc := Reader(dst, drs)
	defer func() { <-dc }()
	defer close(ds)

	fd, err := os.OpenFile(dst, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer fd.Close()
	defer fd.Sync()

	for {
		sr := <-srs
		dr := <-drs
		reads++

		if !Compare(sr.Data, dr.Data) {
			_, err = fd.WriteAt(sr.Data, sr.Offset)
			writes++
			if err != nil {
				return
			}
		}

		switch {
		case sr.Error == io.EOF:
			err = fd.Truncate(sr.Offset)
			return
		case dr.Error == io.EOF:
			continue
		case sr.Error != nil:
			err = sr.Error
			return
		case dr.Error != nil:
			err = dr.Error
			return
		}
	}
}

func Reader(name string, readings chan Reading) (stop, clean chan struct{}) {

	stop = make(chan struct{})
	clean = make(chan struct{})

	go func() {
		defer close(clean)
		defer close(readings)

		file, err := os.Open(name)
		if err != nil {
			readings <- Reading{nil, 0, err}
			return
		}
		defer file.Close()

		offset := int64(0)
		for {
			select {
			case <-stop:
				return
			default:
				data := make([]byte, BLOCK_SIZE)
				n, err := file.Read(data)
				readings <- Reading{data[:n], offset, err}
				offset += int64(n)
				if err == io.EOF {
					return
				}
			}
		}

	}()

	return
}

func Compare(b1, b2 []byte) bool {
	if len(b1) != len(b2) {
		return false
	}
	for i := 0; i < len(b1); i++ {
		if b1[i] != b2[i] {
			return false
		}
	}
	return true
}
<|endoftext|>


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

// Waiting for FDs via epoll(7).

package net

import (
	"net";
	"os";
	"syscall";
)

const (
	Read = syscall.EPOLLIN | syscall.EPOLLRDHUP;
	Write = syscall.EPOLLOUT
)

export type Pollster struct {
	epfd int64;

	// Events we're already waiting for
	events *map[int64] uint;
}

export func NewPollster() (p *Pollster, err *os.Error) {
	p = new(Pollster);
	var e int64;

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know.
	if p.epfd, e = syscall.epoll_create(16); e != 0 {
		return nil, os.ErrnoToError(e)
	}
	p.events = new(map[int64] uint);
	return p, nil
}

func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
	var ev syscall.EpollEvent
	var already bool;
	ev.fd = int32(fd);
	ev.events, already = p.events[fd];
	if !repeat {
		ev.events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		ev.events |= Read
	} else {
		ev.events |= Write
	}

	var op int64;
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.epoll_ctl(p.epfd, op, fd, &ev); e != 0 {
		return os.ErrnoToError(e)
	}
	p.events[fd] = ev.events;
	return nil
}

func (p *Pollster) StopWaiting(fd int64, bits uint) {
	events, already := p.events[fd];
	if !already {
		print("Epoll unexpected fd=", fd, "\n");
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events & syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^bits;
	if int32(events) & ^syscall.EPOLLONESHOT != 0 {
		var ev syscall.EpollEvent;
		ev.fd = int32(fd);
		ev.events = events;
		if e := syscall.epoll_ctl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.ErrnoToError(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.epoll_ctl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.ErrnoToError(e).String(), "\n")
		}
		p.events[fd] = 0, false
	}
}

func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) {
	// Get an event.
	var evarray [1]syscall.EpollEvent;
	ev := &evarray[0];
	n, e := syscall.epoll_wait(p.epfd, &evarray, -1);
	for e == syscall.EAGAIN || e == syscall.EINTR {
		n, e = syscall.epoll_wait(p.epfd, &evarray, -1)
	}
	if e != 0 {
		return -1, 0, os.ErrnoToError(e)
	}
	fd = int64(ev.fd);

	if ev.events & Write != 0 {
		p.StopWaiting(fd, Write);
		return fd, 'w', nil
	}
	if ev.events & Read != 0 {
		p.StopWaiting(fd, Read);
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, already := p.events[fd];
	if events & Write != 0 {
		p.StopWaiting(fd, Write);
		return fd, 'w', nil
	}
	p.StopWaiting(fd, Read);
	return fd, 'r', nil
}

func (p *Pollster) Close() *os.Error {
	r, e := syscall.close(p.epfd);
	return os.ErrnoToError(e)
}
<commit_msg>Unterminated declaration breaks build.<commit_after>// Copyright 2009 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.

// Waiting for FDs via epoll(7).

package net

import (
	"net";
	"os";
	"syscall";
)

const (
	Read = syscall.EPOLLIN | syscall.EPOLLRDHUP;
	Write = syscall.EPOLLOUT
)

export type Pollster struct {
	epfd int64;

	// Events we're already waiting for
	events *map[int64] uint;
}

export func NewPollster() (p *Pollster, err *os.Error) {
	p = new(Pollster);
	var e int64;

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know.
	if p.epfd, e = syscall.epoll_create(16); e != 0 {
		return nil, os.ErrnoToError(e)
	}
	p.events = new(map[int64] uint);
	return p, nil
}

func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
	var ev syscall.EpollEvent;
	var already bool;
	ev.fd = int32(fd);
	ev.events, already = p.events[fd];
	if !repeat {
		ev.events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		ev.events |= Read
	} else {
		ev.events |= Write
	}

	var op int64;
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.epoll_ctl(p.epfd, op, fd, &ev); e != 0 {
		return os.ErrnoToError(e)
	}
	p.events[fd] = ev.events;
	return nil
}

func (p *Pollster) StopWaiting(fd int64, bits uint) {
	events, already := p.events[fd];
	if !already {
		print("Epoll unexpected fd=", fd, "\n");
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events & syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^bits;
	if int32(events) & ^syscall.EPOLLONESHOT != 0 {
		var ev syscall.EpollEvent;
		ev.fd = int32(fd);
		ev.events = events;
		if e := syscall.epoll_ctl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.ErrnoToError(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.epoll_ctl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.ErrnoToError(e).String(), "\n")
		}
		p.events[fd] = 0, false
	}
}

func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) {
	// Get an event.
	var evarray [1]syscall.EpollEvent;
	ev := &evarray[0];
	n, e := syscall.epoll_wait(p.epfd, &evarray, -1);
	for e == syscall.EAGAIN || e == syscall.EINTR {
		n, e = syscall.epoll_wait(p.epfd, &evarray, -1)
	}
	if e != 0 {
		return -1, 0, os.ErrnoToError(e)
	}
	fd = int64(ev.fd);

	if ev.events & Write != 0 {
		p.StopWaiting(fd, Write);
		return fd, 'w', nil
	}
	if ev.events & Read != 0 {
		p.StopWaiting(fd, Read);
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, already := p.events[fd];
	if events & Write != 0 {
		p.StopWaiting(fd, Write);
		return fd, 'w', nil
	}
	p.StopWaiting(fd, Read);
	return fd, 'r', nil
}

func (p *Pollster) Close() *os.Error {
	r, e := syscall.close(p.epfd);
	return os.ErrnoToError(e)
}
<|endoftext|>


<commit_before>package models

import (
	"context"
	"net"
	"time"
)

// TCP_BUFFER_SIZE is the maximum packet size
const TCP_BUFFER_SIZE = 1024 * 64

// DEFAULT_RELAY is the default relay used (can be set using --relay)
var (
	DEFAULT_RELAY      = "croc.schollz.com"
	DEFAULT_RELAY6     = "croc6.schollz.com"
	DEFAULT_PORT       = "9009"
	DEFAULT_PASSPHRASE = "pass123"
)

func init() {
	var err error
	DEFAULT_RELAY, err = lookupIP(DEFAULT_RELAY)
	if err == nil {
		DEFAULT_RELAY += ":" + DEFAULT_PORT
	} else {
		DEFAULT_RELAY = ""
	}
	DEFAULT_RELAY6, err = lookupIP(DEFAULT_RELAY6)
	if err == nil {
		DEFAULT_RELAY6 = "[" + DEFAULT_RELAY6 + "]:" + DEFAULT_PORT
	} else {
		DEFAULT_RELAY6 = ""
	}
}

func lookupIP(address string) (ipaddress string, err error) {
	r := &net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			d := net.Dialer{
				Timeout: time.Millisecond * time.Duration(10000),
			}
			return d.DialContext(ctx, "udp", "1.1.1.1:53")
		},
	}
	ip, err := r.LookupHost(context.Background(), address)
	if err != nil {
		return
	}
	ipaddress = ip[0]
	return
}
<commit_msg>find dns from any number of providers<commit_after>package models

import (
	"context"
	"net"
	"time"
)

// TCP_BUFFER_SIZE is the maximum packet size
const TCP_BUFFER_SIZE = 1024 * 64

// DEFAULT_RELAY is the default relay used (can be set using --relay)
var (
	DEFAULT_RELAY      = "croc.schollz.com"
	DEFAULT_RELAY6     = "croc6.schollz.com"
	DEFAULT_PORT       = "9009"
	DEFAULT_PASSPHRASE = "pass123"
)

func init() {
	var err error
	DEFAULT_RELAY, err = lookupIPs(DEFAULT_RELAY)
	if err == nil {
		DEFAULT_RELAY += ":" + DEFAULT_PORT
	} else {
		DEFAULT_RELAY = ""
	}
	DEFAULT_RELAY6, err = lookupIPs(DEFAULT_RELAY6)
	if err == nil {
		DEFAULT_RELAY6 = "[" + DEFAULT_RELAY6 + "]:" + DEFAULT_PORT
	} else {
		DEFAULT_RELAY6 = ""
	}
}

func lookupIPs(address string) (ipaddress string, err error) {
	var publicDns = []string{"1.1.1.1", "8.8.8.8", "8.8.4.4", "1.0.0.1", "8.26.56.26", "208.67.222.222", "208.67.220.220"}
	result := make(chan string, len(publicDns))
	for _, dns := range publicDns {
		go func(dns string) {
			s, _ := lookupIP(address, dns)
			result <- s
		}(dns)
	}
	for i := 0; i < len(publicDns); i++ {
		ipaddress = <-result
		if ipaddress != "" {
			return
		}
	}
	return
}

func lookupIP(address, dns string) (ipaddress string, err error) {
	r := &net.Resolver{
		PreferGo: true,
		Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
			d := net.Dialer{
				Timeout: time.Millisecond * time.Duration(10000),
			}
			return d.DialContext(ctx, "udp", dns+":53")
		},
	}
	ip, err := r.LookupHost(context.Background(), address)
	if err != nil {
		return
	}
	ipaddress = ip[0]
	return
}
<|endoftext|>


<commit_before>package action

import (
	"fmt"

	bosherr "github.com/cloudfoundry/bosh-agent/errors"

	bslcvm "github.com/maximilien/bosh-softlayer-cpi/softlayer/vm"
)

type HasVM struct {
	vmFinder bslcvm.Finder
}

func NewHasVM(vmFinder bslcvm.Finder) HasVM {
	return HasVM{vmFinder: vmFinder}
}

func (a HasVM) Run(vmCID VMCID) (bool, error) {
	//DEBUG
	fmt.Println("HasVM.Run")
	fmt.Printf("----> vmCID: %#v\n", vmCID)
	fmt.Println()
	//DEBUG

	_, found, err := a.vmFinder.Find(int(vmCID))
	if err != nil {
		return false, bosherr.WrapError(err, "Finding VM '%s'", vmCID)
	}

	return found, nil
}
<commit_msg>removed debug statements<commit_after>package action

import (
	bosherr "github.com/cloudfoundry/bosh-agent/errors"

	bslcvm "github.com/maximilien/bosh-softlayer-cpi/softlayer/vm"
)

type HasVM struct {
	vmFinder bslcvm.Finder
}

func NewHasVM(vmFinder bslcvm.Finder) HasVM {
	return HasVM{vmFinder: vmFinder}
}

func (a HasVM) Run(vmCID VMCID) (bool, error) {
	_, found, err := a.vmFinder.Find(int(vmCID))
	if err != nil {
		return false, bosherr.WrapError(err, "Finding VM '%s'", vmCID)
	}

	return found, nil
}
<|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 net

import (
	"fmt"
	"io"
	"reflect"
	"runtime"
	"sync"
	"testing"
	"time"
)

func BenchmarkTCP4OneShot(b *testing.B) {
	benchmarkTCP(b, false, false, "127.0.0.1:0")
}

func BenchmarkTCP4OneShotTimeout(b *testing.B) {
	benchmarkTCP(b, false, true, "127.0.0.1:0")
}

func BenchmarkTCP4Persistent(b *testing.B) {
	benchmarkTCP(b, true, false, "127.0.0.1:0")
}

func BenchmarkTCP4PersistentTimeout(b *testing.B) {
	benchmarkTCP(b, true, true, "127.0.0.1:0")
}

func BenchmarkTCP6OneShot(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, false, false, "[::1]:0")
}

func BenchmarkTCP6OneShotTimeout(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, false, true, "[::1]:0")
}

func BenchmarkTCP6Persistent(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, true, false, "[::1]:0")
}

func BenchmarkTCP6PersistentTimeout(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, true, true, "[::1]:0")
}

func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
	const msgLen = 512
	conns := b.N
	numConcurrent := runtime.GOMAXPROCS(-1) * 16
	msgs := 1
	if persistent {
		conns = numConcurrent
		msgs = b.N / conns
		if msgs == 0 {
			msgs = 1
		}
		if conns > b.N {
			conns = b.N
		}
	}
	sendMsg := func(c Conn, buf []byte) bool {
		n, err := c.Write(buf)
		if n != len(buf) || err != nil {
			b.Logf("Write failed: %v", err)
			return false
		}
		return true
	}
	recvMsg := func(c Conn, buf []byte) bool {
		for read := 0; read != len(buf); {
			n, err := c.Read(buf)
			read += n
			if err != nil {
				b.Logf("Read failed: %v", err)
				return false
			}
		}
		return true
	}
	ln, err := Listen("tcp", laddr)
	if err != nil {
		b.Fatalf("Listen failed: %v", err)
	}
	defer ln.Close()
	// Acceptor.
	go func() {
		for {
			c, err := ln.Accept()
			if err != nil {
				break
			}
			// Server connection.
			go func(c Conn) {
				defer c.Close()
				if timeout {
					c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
				}
				var buf [msgLen]byte
				for m := 0; m < msgs; m++ {
					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
						break
					}
				}
			}(c)
		}
	}()
	sem := make(chan bool, numConcurrent)
	for i := 0; i < conns; i++ {
		sem <- true
		// Client connection.
		go func() {
			defer func() {
				<-sem
			}()
			c, err := Dial("tcp", ln.Addr().String())
			if err != nil {
				b.Logf("Dial failed: %v", err)
				return
			}
			defer c.Close()
			if timeout {
				c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
			}
			var buf [msgLen]byte
			for m := 0; m < msgs; m++ {
				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
					break
				}
			}
		}()
	}
	for i := 0; i < cap(sem); i++ {
		sem <- true
	}
}

type resolveTCPAddrTest struct {
	net     string
	litAddr string
	addr    *TCPAddr
	err     error
}

var resolveTCPAddrTests = []resolveTCPAddrTest{
	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},

	{"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
	{"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},

	{"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
	{"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},

	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior

	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
}

func init() {
	if ifi := loopbackInterface(); ifi != nil {
		index := fmt.Sprintf("%v", ifi.Index)
		resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
			{"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
			{"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
		}...)
	}
}

func TestResolveTCPAddr(t *testing.T) {
	for _, tt := range resolveTCPAddrTests {
		addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
		if err != tt.err {
			t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
		}
		if !reflect.DeepEqual(addr, tt.addr) {
			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
		}
	}
}

var tcpListenerNameTests = []struct {
	net   string
	laddr *TCPAddr
}{
	{"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
	{"tcp4", &TCPAddr{}},
	{"tcp4", nil},
}

func TestTCPListenerName(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}

	for _, tt := range tcpListenerNameTests {
		ln, err := ListenTCP(tt.net, tt.laddr)
		if err != nil {
			t.Fatalf("ListenTCP failed: %v", err)
		}
		defer ln.Close()
		la := ln.Addr()
		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
		}
	}
}

func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}
	ifi := loopbackInterface()
	if ifi == nil {
		t.Skip("loopback interface not found")
	}
	laddr := ipv6LinkLocalUnicastAddr(ifi)
	if laddr == "" {
		t.Skip("ipv6 unicast address on loopback not found")
	}

	type test struct {
		net, addr  string
		nameLookup bool
	}
	var tests = []test{
		{"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false},
		{"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
	}
	switch runtime.GOOS {
	case "darwin", "freebsd", "opensbd", "netbsd":
		tests = append(tests, []test{
			{"tcp", "[localhost%" + ifi.Name + "]:0", true},
			{"tcp6", "[localhost%" + ifi.Name + "]:0", true},
		}...)
	case "linux":
		tests = append(tests, []test{
			{"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
			{"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
		}...)
	}
	for _, tt := range tests {
		ln, err := Listen(tt.net, tt.addr)
		if err != nil {
			// It might return "LookupHost returned no
			// suitable address" error on some platforms.
			t.Logf("Listen failed: %v", err)
			continue
		}
		defer ln.Close()
		if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", la)
		}

		done := make(chan int)
		go transponder(t, ln, done)

		c, err := Dial(tt.net, ln.Addr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		defer c.Close()
		if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", la)
		}
		if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
		}

		if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
			t.Fatalf("Conn.Write failed: %v", err)
		}
		b := make([]byte, 32)
		if _, err := c.Read(b); err != nil {
			t.Fatalf("Conn.Read failed: %v", err)
		}

		<-done
	}
}

func TestTCPConcurrentAccept(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}
	const N = 10
	var wg sync.WaitGroup
	wg.Add(N)
	for i := 0; i < N; i++ {
		go func() {
			for {
				c, err := ln.Accept()
				if err != nil {
					break
				}
				c.Close()
			}
			wg.Done()
		}()
	}
	for i := 0; i < 10*N; i++ {
		c, err := Dial("tcp", ln.Addr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		c.Close()
	}
	ln.Close()
	wg.Wait()
}

func TestTCPReadWriteMallocs(t *testing.T) {
	maxMallocs := 0
	switch runtime.GOOS {
	// Add other OSes if you know how many mallocs they do.
	case "windows":
		maxMallocs = 0
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}
	defer ln.Close()
	var server Conn
	errc := make(chan error)
	go func() {
		var err error
		server, err = ln.Accept()
		errc <- err
	}()
	client, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial failed: %v", err)
	}
	if err := <-errc; err != nil {
		t.Fatalf("Accept failed: %v", err)
	}
	defer server.Close()
	var buf [128]byte
	mallocs := testing.AllocsPerRun(1000, func() {
		_, err := server.Write(buf[:])
		if err != nil {
			t.Fatalf("Write failed: %v", err)
		}
		_, err = io.ReadFull(client, buf[:])
		if err != nil {
			t.Fatalf("Read failed: %v", err)
		}
	})
	if int(mallocs) > maxMallocs {
		t.Fatalf("Got %v allocs, want %v", mallocs, maxMallocs)
	}
}
<commit_msg>net: fix intentional build breakage introduced in 12413043<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 net

import (
	"fmt"
	"io"
	"reflect"
	"runtime"
	"sync"
	"testing"
	"time"
)

func BenchmarkTCP4OneShot(b *testing.B) {
	benchmarkTCP(b, false, false, "127.0.0.1:0")
}

func BenchmarkTCP4OneShotTimeout(b *testing.B) {
	benchmarkTCP(b, false, true, "127.0.0.1:0")
}

func BenchmarkTCP4Persistent(b *testing.B) {
	benchmarkTCP(b, true, false, "127.0.0.1:0")
}

func BenchmarkTCP4PersistentTimeout(b *testing.B) {
	benchmarkTCP(b, true, true, "127.0.0.1:0")
}

func BenchmarkTCP6OneShot(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, false, false, "[::1]:0")
}

func BenchmarkTCP6OneShotTimeout(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, false, true, "[::1]:0")
}

func BenchmarkTCP6Persistent(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, true, false, "[::1]:0")
}

func BenchmarkTCP6PersistentTimeout(b *testing.B) {
	if !supportsIPv6 {
		b.Skip("ipv6 is not supported")
	}
	benchmarkTCP(b, true, true, "[::1]:0")
}

func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
	const msgLen = 512
	conns := b.N
	numConcurrent := runtime.GOMAXPROCS(-1) * 16
	msgs := 1
	if persistent {
		conns = numConcurrent
		msgs = b.N / conns
		if msgs == 0 {
			msgs = 1
		}
		if conns > b.N {
			conns = b.N
		}
	}
	sendMsg := func(c Conn, buf []byte) bool {
		n, err := c.Write(buf)
		if n != len(buf) || err != nil {
			b.Logf("Write failed: %v", err)
			return false
		}
		return true
	}
	recvMsg := func(c Conn, buf []byte) bool {
		for read := 0; read != len(buf); {
			n, err := c.Read(buf)
			read += n
			if err != nil {
				b.Logf("Read failed: %v", err)
				return false
			}
		}
		return true
	}
	ln, err := Listen("tcp", laddr)
	if err != nil {
		b.Fatalf("Listen failed: %v", err)
	}
	defer ln.Close()
	// Acceptor.
	go func() {
		for {
			c, err := ln.Accept()
			if err != nil {
				break
			}
			// Server connection.
			go func(c Conn) {
				defer c.Close()
				if timeout {
					c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
				}
				var buf [msgLen]byte
				for m := 0; m < msgs; m++ {
					if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
						break
					}
				}
			}(c)
		}
	}()
	sem := make(chan bool, numConcurrent)
	for i := 0; i < conns; i++ {
		sem <- true
		// Client connection.
		go func() {
			defer func() {
				<-sem
			}()
			c, err := Dial("tcp", ln.Addr().String())
			if err != nil {
				b.Logf("Dial failed: %v", err)
				return
			}
			defer c.Close()
			if timeout {
				c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
			}
			var buf [msgLen]byte
			for m := 0; m < msgs; m++ {
				if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
					break
				}
			}
		}()
	}
	for i := 0; i < cap(sem); i++ {
		sem <- true
	}
}

type resolveTCPAddrTest struct {
	net     string
	litAddr string
	addr    *TCPAddr
	err     error
}

var resolveTCPAddrTests = []resolveTCPAddrTest{
	{"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
	{"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},

	{"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
	{"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},

	{"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
	{"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},

	{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
	{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior

	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
}

func init() {
	if ifi := loopbackInterface(); ifi != nil {
		index := fmt.Sprintf("%v", ifi.Index)
		resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
			{"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
			{"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
		}...)
	}
}

func TestResolveTCPAddr(t *testing.T) {
	for _, tt := range resolveTCPAddrTests {
		addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
		if err != tt.err {
			t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
		}
		if !reflect.DeepEqual(addr, tt.addr) {
			t.Fatalf("got %#v; expected %#v", addr, tt.addr)
		}
	}
}

var tcpListenerNameTests = []struct {
	net   string
	laddr *TCPAddr
}{
	{"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
	{"tcp4", &TCPAddr{}},
	{"tcp4", nil},
}

func TestTCPListenerName(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}

	for _, tt := range tcpListenerNameTests {
		ln, err := ListenTCP(tt.net, tt.laddr)
		if err != nil {
			t.Fatalf("ListenTCP failed: %v", err)
		}
		defer ln.Close()
		la := ln.Addr()
		if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
			t.Fatalf("got %v; expected a proper address with non-zero port number", la)
		}
	}
}

func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}
	if !supportsIPv6 {
		t.Skip("ipv6 is not supported")
	}
	ifi := loopbackInterface()
	if ifi == nil {
		t.Skip("loopback interface not found")
	}
	laddr := ipv6LinkLocalUnicastAddr(ifi)
	if laddr == "" {
		t.Skip("ipv6 unicast address on loopback not found")
	}

	type test struct {
		net, addr  string
		nameLookup bool
	}
	var tests = []test{
		{"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false},
		{"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
	}
	switch runtime.GOOS {
	case "darwin", "freebsd", "opensbd", "netbsd":
		tests = append(tests, []test{
			{"tcp", "[localhost%" + ifi.Name + "]:0", true},
			{"tcp6", "[localhost%" + ifi.Name + "]:0", true},
		}...)
	case "linux":
		tests = append(tests, []test{
			{"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
			{"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
		}...)
	}
	for _, tt := range tests {
		ln, err := Listen(tt.net, tt.addr)
		if err != nil {
			// It might return "LookupHost returned no
			// suitable address" error on some platforms.
			t.Logf("Listen failed: %v", err)
			continue
		}
		defer ln.Close()
		if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", la)
		}

		done := make(chan int)
		go transponder(t, ln, done)

		c, err := Dial(tt.net, ln.Addr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		defer c.Close()
		if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", la)
		}
		if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
			t.Fatalf("got %v; expected a proper address with zone identifier", ra)
		}

		if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
			t.Fatalf("Conn.Write failed: %v", err)
		}
		b := make([]byte, 32)
		if _, err := c.Read(b); err != nil {
			t.Fatalf("Conn.Read failed: %v", err)
		}

		<-done
	}
}

func TestTCPConcurrentAccept(t *testing.T) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}
	const N = 10
	var wg sync.WaitGroup
	wg.Add(N)
	for i := 0; i < N; i++ {
		go func() {
			for {
				c, err := ln.Accept()
				if err != nil {
					break
				}
				c.Close()
			}
			wg.Done()
		}()
	}
	for i := 0; i < 10*N; i++ {
		c, err := Dial("tcp", ln.Addr().String())
		if err != nil {
			t.Fatalf("Dial failed: %v", err)
		}
		c.Close()
	}
	ln.Close()
	wg.Wait()
}

func TestTCPReadWriteMallocs(t *testing.T) {
	maxMallocs := 10000
	switch runtime.GOOS {
	// Add other OSes if you know how many mallocs they do.
	case "windows":
		maxMallocs = 0
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}
	defer ln.Close()
	var server Conn
	errc := make(chan error)
	go func() {
		var err error
		server, err = ln.Accept()
		errc <- err
	}()
	client, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial failed: %v", err)
	}
	if err := <-errc; err != nil {
		t.Fatalf("Accept failed: %v", err)
	}
	defer server.Close()
	var buf [128]byte
	mallocs := testing.AllocsPerRun(1000, func() {
		_, err := server.Write(buf[:])
		if err != nil {
			t.Fatalf("Write failed: %v", err)
		}
		_, err = io.ReadFull(client, buf[:])
		if err != nil {
			t.Fatalf("Read failed: %v", err)
		}
	})
	if int(mallocs) > maxMallocs {
		t.Fatalf("Got %v allocs, want %v", mallocs, maxMallocs)
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2021 PaperCut Software International Pty. Ltd.
 */

package osutils

import (
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// FileExists check if a file denoted by path exists, returning true or false.
func FileExists(path string) bool {
	_, err := os.Stat(path)
	return !os.IsNotExist(err)
}

// CopyFile copies a file from src to dst
func CopyFile(src, dest string) error {
	s, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func() { _ = s.Close() }()
	d, err := os.Create(dest)
	if err != nil {
		return err
	}
	if _, err := io.Copy(d, s); err != nil {
		_ = d.Close()
		return err
	}
	return d.Close()
}

// WriteFileString writes a string to file denoted by filename with specified permissions.
func WriteFileString(filename string, data string, perm os.FileMode) error {
	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	_, err = f.WriteString(data)
	if err := f.Close(); err != nil {
		return err
	}
	return err
}

// ReadStringFromFile reads a text file and returns contents as string or fall back to default as per def on error
func ReadStringFromFile(file string, def string) string {
	if dat, err := ioutil.ReadFile(file); err == nil {
		def = strings.TrimSpace(string(dat))
	}
	return def
}
<commit_msg>fix: missing if<commit_after>/*
 * Copyright © 2021 PaperCut Software International Pty. Ltd.
 */

package osutils

import (
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// FileExists check if a file denoted by path exists, returning true or false.
func FileExists(path string) bool {
	_, err := os.Stat(path)
	return !os.IsNotExist(err)
}

// CopyFile copies a file from src to dst
func CopyFile(src, dest string) error {
	s, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func() { _ = s.Close() }()
	d, err := os.Create(dest)
	if err != nil {
		return err
	}
	if _, err := io.Copy(d, s); err != nil {
		_ = d.Close()
		return err
	}
	return d.Close()
}

// WriteFileString writes a string to file denoted by filename with specified permissions.
func WriteFileString(filename string, data string, perm os.FileMode) error {
	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	_, err = f.WriteString(data)
	if err != nil {
		return err
	}
	if err := f.Close(); err != nil {
		return err
	}
	return err
}

// ReadStringFromFile reads a text file and returns contents as string or fall back to default as per def on error
func ReadStringFromFile(file string, def string) string {
	if dat, err := ioutil.ReadFile(file); err == nil {
		def = strings.TrimSpace(string(dat))
	}
	return def
}
<|endoftext|>


<commit_before>// Copyright 2020 The Knative Authors

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
	"context"
	"encoding/json"
	"strings"

	"gotest.tools/v3/assert"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientv1alpha1 "knative.dev/client/pkg/apis/client/v1alpha1"
	"knative.dev/pkg/kmeta"
	"knative.dev/pkg/ptr"
	pkgtest "knative.dev/pkg/test"
	"knative.dev/serving/pkg/apis/config"
	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
	servingtest "knative.dev/serving/pkg/testing/v1"

	"knative.dev/client/pkg/util"
)

// ExpectedServiceListOption enables further configuration of a ServiceList.
type ExpectedServiceListOption func(*servingv1.ServiceList)

// ExpectedRevisionListOption enables further configuration of a RevisionList.
type ExpectedRevisionListOption func(*servingv1.RevisionList)

// ExpectedKNExportOption enables further configuration of a Export.
type ExpectedKNExportOption func(*clientv1alpha1.Export)

// ServiceCreate verifies given service creation in sync mode and also verifies output
func ServiceCreate(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "create", serviceName, "--image", pkgtest.ImagePath("helloworld"))
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", r.KnTest().Kn().Namespace(), "ready"))
}

// ServiceListEmpty verifies that there are no services present
func ServiceListEmpty(r *KnRunResultCollector) {
	out := r.KnTest().Kn().Run("service", "list")
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, "No services found."))
}

// ServiceList verifies if given service exists
func ServiceList(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "list", serviceName)
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, serviceName))
}

// ServiceDescribe describes given service and verifies the keys in the output
func ServiceDescribe(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "describe", serviceName)
	r.AssertNoError(out)
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, serviceName, r.KnTest().Kn().Namespace(), pkgtest.ImagePath("helloworld")))
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Conditions", "ConfigurationsReady", "Ready", "RoutesReady"))
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Name", "Namespace", "URL", "Age", "Revisions"))
}

// ServiceListOutput verifies listing given service using '--output name' flag
func ServiceListOutput(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "list", serviceName, "--output", "name")
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, serviceName, "service.serving.knative.dev"))
}

// ServiceUpdate verifies service update operation with given arguments in sync mode
func ServiceUpdate(r *KnRunResultCollector, serviceName string, args ...string) {
	fullArgs := append([]string{}, "service", "update", serviceName)
	fullArgs = append(fullArgs, args...)
	out := r.KnTest().Kn().Run(fullArgs...)
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stdout, "updating", "service", serviceName, "ready"))
}

// ServiceUpdateWithError verifies service update operation with given arguments in sync mode
// when expecting an error
func ServiceUpdateWithError(r *KnRunResultCollector, serviceName string, args ...string) {
	fullArgs := append([]string{}, "service", "update", serviceName)
	fullArgs = append(fullArgs, args...)
	out := r.KnTest().Kn().Run(fullArgs...)
	r.AssertError(out)
}

// ServiceDelete verifies service deletion in sync mode
func ServiceDelete(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "delete", "--wait", serviceName)
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, "Service", serviceName, "successfully deleted in namespace", r.KnTest().Kn().Namespace()))
}

// ServiceDescribeWithJSONPath returns output of given JSON path by describing the service
func ServiceDescribeWithJSONPath(r *KnRunResultCollector, serviceName, jsonpath string) string {
	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-o", jsonpath)
	r.AssertNoError(out)
	return out.Stdout
}

// ValidateServiceResources validates cpu and mem resources
func ValidateServiceResources(r *KnRunResultCollector, serviceName string, requestsMemory, requestsCPU, limitsMemory, limitsCPU string) {
	var err error
	rlist := corev1.ResourceList{}
	rlist[corev1.ResourceCPU], err = resource.ParseQuantity(requestsCPU)
	assert.NilError(r.T(), err)
	rlist[corev1.ResourceMemory], err = resource.ParseQuantity(requestsMemory)
	assert.NilError(r.T(), err)

	llist := corev1.ResourceList{}
	llist[corev1.ResourceCPU], err = resource.ParseQuantity(limitsCPU)
	assert.NilError(r.T(), err)
	llist[corev1.ResourceMemory], err = resource.ParseQuantity(limitsMemory)
	assert.NilError(r.T(), err)

	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-ojson")
	data := json.NewDecoder(strings.NewReader(out.Stdout))
	var service servingv1.Service
	err = data.Decode(&service)
	assert.NilError(r.T(), err)

	serviceRequestResourceList := service.Spec.Template.Spec.Containers[0].Resources.Requests
	assert.DeepEqual(r.T(), serviceRequestResourceList, rlist)

	serviceLimitsResourceList := service.Spec.Template.Spec.Containers[0].Resources.Limits
	assert.DeepEqual(r.T(), serviceLimitsResourceList, llist)
}

// GetServiceFromKNServiceDescribe runs the kn service describe command
// decodes it into a ksvc and returns it.
func GetServiceFromKNServiceDescribe(r *KnRunResultCollector, serviceName string) servingv1.Service {
	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-ojson")
	data := json.NewDecoder(strings.NewReader(out.Stdout))
	data.UseNumber()
	var service servingv1.Service
	err := data.Decode(&service)
	assert.NilError(r.T(), err)
	return service
}

// BuildServiceListWithOptions returns ServiceList with options provided
func BuildServiceListWithOptions(options ...ExpectedServiceListOption) *servingv1.ServiceList {
	list := &servingv1.ServiceList{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "List",
		},
	}

	for _, fn := range options {
		fn(list)
	}

	return list
}

// WithService appends the given service to ServiceList
func WithService(svc *servingv1.Service) ExpectedServiceListOption {
	return func(list *servingv1.ServiceList) {
		list.Items = append(list.Items, *svc)
	}
}

// BuildRevisionListWithOptions returns RevisionList with options provided
func BuildRevisionListWithOptions(options ...ExpectedRevisionListOption) *servingv1.RevisionList {
	list := &servingv1.RevisionList{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "List",
		},
	}

	for _, fn := range options {
		fn(list)
	}

	return list
}

// BuildKNExportWithOptions returns Export object with the options provided
func BuildKNExportWithOptions(options ...ExpectedKNExportOption) *clientv1alpha1.Export {
	knExport := &clientv1alpha1.Export{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "client.knative.dev/v1alpha1",
			Kind:       "Export",
		},
	}

	for _, fn := range options {
		fn(knExport)
	}

	return knExport
}

// BuildConfigurationSpec builds servingv1.ConfigurationSpec with the options provided
func BuildConfigurationSpec(co ...servingtest.ConfigOption) *servingv1.ConfigurationSpec {
	c := &servingv1.Configuration{
		Spec: servingv1.ConfigurationSpec{
			Template: servingv1.RevisionTemplateSpec{
				Spec: *BuildRevisionSpec(pkgtest.ImagePath("helloworld")),
			},
		},
	}
	for _, opt := range co {
		opt(c)
	}
	c.SetDefaults(context.Background())
	return &c.Spec
}

// BuildRevisionSpec for provided image
func BuildRevisionSpec(image string) *servingv1.RevisionSpec {
	return &servingv1.RevisionSpec{
		PodSpec: corev1.PodSpec{
			Containers: []corev1.Container{{
				Image: image,
			}},
			EnableServiceLinks: ptr.Bool(false),
		},
		TimeoutSeconds: ptr.Int64(config.DefaultRevisionTimeoutSeconds),
	}
}

// BuildServiceWithOptions returns ksvc with options provided
func BuildServiceWithOptions(name string, so ...servingtest.ServiceOption) *servingv1.Service {
	svc := servingtest.ServiceWithoutNamespace(name, so...)
	svc.TypeMeta = metav1.TypeMeta{
		Kind:       "Service",
		APIVersion: "serving.knative.dev/v1",
	}
	svc.Spec.Template.Spec.Containers[0].Resources = corev1.ResourceRequirements{}
	return svc
}

// WithTrafficSpec adds route to ksvc
func WithTrafficSpec(revisions []string, percentages []int, tags []string) servingtest.ServiceOption {
	return func(svc *servingv1.Service) {
		var trafficTargets []servingv1.TrafficTarget
		for i, rev := range revisions {
			trafficTargets = append(trafficTargets, servingv1.TrafficTarget{
				Percent: ptr.Int64(int64(percentages[i])),
			})
			if tags[i] != "" {
				trafficTargets[i].Tag = tags[i]
			}
			if rev == "latest" {
				trafficTargets[i].LatestRevision = ptr.Bool(true)
			} else {
				trafficTargets[i].RevisionName = rev
				trafficTargets[i].LatestRevision = ptr.Bool(false)
			}
		}
		svc.Spec.RouteSpec = servingv1.RouteSpec{
			Traffic: trafficTargets,
		}
	}
}

// BuildRevision returns Revision object with the options provided
func BuildRevision(name string, options ...servingtest.RevisionOption) *servingv1.Revision {
	rev := servingtest.Revision("", name, options...)
	rev.TypeMeta = metav1.TypeMeta{
		Kind:       "Revision",
		APIVersion: "serving.knative.dev/v1",
	}
	rev.Spec.PodSpec.Containers[0].Name = config.DefaultUserContainerName
	rev.Spec.PodSpec.EnableServiceLinks = ptr.Bool(false)
	rev.ObjectMeta.SelfLink = ""
	rev.ObjectMeta.Namespace = ""
	rev.ObjectMeta.UID = ""
	rev.ObjectMeta.Generation = int64(0)
	rev.Spec.PodSpec.Containers[0].Resources = corev1.ResourceRequirements{}
	return rev
}

// WithRevision appends Revision object to RevisionList
func WithRevision(rev servingv1.Revision) ExpectedRevisionListOption {
	return func(list *servingv1.RevisionList) {
		list.Items = append(list.Items, rev)
	}
}

// WithKNRevision appends Revision object RevisionList to Kn Export
func WithKNRevision(rev servingv1.Revision) ExpectedKNExportOption {
	return func(export *clientv1alpha1.Export) {
		export.Spec.Revisions = append(export.Spec.Revisions, rev)
	}
}

// WithRevisionEnv adds env variable to Revision object
func WithRevisionEnv(evs ...corev1.EnvVar) servingtest.RevisionOption {
	return func(s *servingv1.Revision) {
		s.Spec.PodSpec.Containers[0].Env = evs
	}
}

// WithRevisionImage adds revision image to Revision object
func WithRevisionImage(image string) servingtest.RevisionOption {
	return func(s *servingv1.Revision) {
		s.Spec.PodSpec.Containers[0].Image = image
	}
}

// WithRevisionAnnotations adds annotation to revision spec in ksvc
func WithRevisionAnnotations(annotations map[string]string) servingtest.ServiceOption {
	return func(service *servingv1.Service) {
		service.Spec.Template.ObjectMeta.Annotations = kmeta.UnionMaps(
			service.Spec.Template.ObjectMeta.Annotations, annotations)
	}
}
<commit_msg>Fix sync serviceDelete in test utils (#1467)<commit_after>// Copyright 2020 The Knative Authors

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
	"context"
	"encoding/json"
	"strings"

	"gotest.tools/v3/assert"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	clientv1alpha1 "knative.dev/client/pkg/apis/client/v1alpha1"
	"knative.dev/pkg/kmeta"
	"knative.dev/pkg/ptr"
	pkgtest "knative.dev/pkg/test"
	"knative.dev/serving/pkg/apis/config"
	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
	servingtest "knative.dev/serving/pkg/testing/v1"

	"knative.dev/client/pkg/util"
)

// ExpectedServiceListOption enables further configuration of a ServiceList.
type ExpectedServiceListOption func(*servingv1.ServiceList)

// ExpectedRevisionListOption enables further configuration of a RevisionList.
type ExpectedRevisionListOption func(*servingv1.RevisionList)

// ExpectedKNExportOption enables further configuration of a Export.
type ExpectedKNExportOption func(*clientv1alpha1.Export)

// ServiceCreate verifies given service creation in sync mode and also verifies output
func ServiceCreate(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "create", serviceName, "--image", pkgtest.ImagePath("helloworld"))
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stdout, "service", serviceName, "creating", "namespace", r.KnTest().Kn().Namespace(), "ready"))
}

// ServiceListEmpty verifies that there are no services present
func ServiceListEmpty(r *KnRunResultCollector) {
	out := r.KnTest().Kn().Run("service", "list")
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, "No services found."))
}

// ServiceList verifies if given service exists
func ServiceList(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "list", serviceName)
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, serviceName))
}

// ServiceDescribe describes given service and verifies the keys in the output
func ServiceDescribe(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "describe", serviceName)
	r.AssertNoError(out)
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, serviceName, r.KnTest().Kn().Namespace(), pkgtest.ImagePath("helloworld")))
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Conditions", "ConfigurationsReady", "Ready", "RoutesReady"))
	assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Name", "Namespace", "URL", "Age", "Revisions"))
}

// ServiceListOutput verifies listing given service using '--output name' flag
func ServiceListOutput(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "list", serviceName, "--output", "name")
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, serviceName, "service.serving.knative.dev"))
}

// ServiceUpdate verifies service update operation with given arguments in sync mode
func ServiceUpdate(r *KnRunResultCollector, serviceName string, args ...string) {
	fullArgs := append([]string{}, "service", "update", serviceName)
	fullArgs = append(fullArgs, args...)
	out := r.KnTest().Kn().Run(fullArgs...)
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAllIgnoreCase(out.Stdout, "updating", "service", serviceName, "ready"))
}

// ServiceUpdateWithError verifies service update operation with given arguments in sync mode
// when expecting an error
func ServiceUpdateWithError(r *KnRunResultCollector, serviceName string, args ...string) {
	fullArgs := append([]string{}, "service", "update", serviceName)
	fullArgs = append(fullArgs, args...)
	out := r.KnTest().Kn().Run(fullArgs...)
	r.AssertError(out)
}

// ServiceDelete verifies service deletion in sync mode
func ServiceDelete(r *KnRunResultCollector, serviceName string) {
	out := r.KnTest().Kn().Run("service", "delete", serviceName, "--wait")
	r.AssertNoError(out)
	assert.Check(r.T(), util.ContainsAll(out.Stdout, "Service", serviceName, "successfully deleted in namespace", r.KnTest().Kn().Namespace()))
}

// ServiceDescribeWithJSONPath returns output of given JSON path by describing the service
func ServiceDescribeWithJSONPath(r *KnRunResultCollector, serviceName, jsonpath string) string {
	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-o", jsonpath)
	r.AssertNoError(out)
	return out.Stdout
}

// ValidateServiceResources validates cpu and mem resources
func ValidateServiceResources(r *KnRunResultCollector, serviceName string, requestsMemory, requestsCPU, limitsMemory, limitsCPU string) {
	var err error
	rlist := corev1.ResourceList{}
	rlist[corev1.ResourceCPU], err = resource.ParseQuantity(requestsCPU)
	assert.NilError(r.T(), err)
	rlist[corev1.ResourceMemory], err = resource.ParseQuantity(requestsMemory)
	assert.NilError(r.T(), err)

	llist := corev1.ResourceList{}
	llist[corev1.ResourceCPU], err = resource.ParseQuantity(limitsCPU)
	assert.NilError(r.T(), err)
	llist[corev1.ResourceMemory], err = resource.ParseQuantity(limitsMemory)
	assert.NilError(r.T(), err)

	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-ojson")
	data := json.NewDecoder(strings.NewReader(out.Stdout))
	var service servingv1.Service
	err = data.Decode(&service)
	assert.NilError(r.T(), err)

	serviceRequestResourceList := service.Spec.Template.Spec.Containers[0].Resources.Requests
	assert.DeepEqual(r.T(), serviceRequestResourceList, rlist)

	serviceLimitsResourceList := service.Spec.Template.Spec.Containers[0].Resources.Limits
	assert.DeepEqual(r.T(), serviceLimitsResourceList, llist)
}

// GetServiceFromKNServiceDescribe runs the kn service describe command
// decodes it into a ksvc and returns it.
func GetServiceFromKNServiceDescribe(r *KnRunResultCollector, serviceName string) servingv1.Service {
	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-ojson")
	data := json.NewDecoder(strings.NewReader(out.Stdout))
	data.UseNumber()
	var service servingv1.Service
	err := data.Decode(&service)
	assert.NilError(r.T(), err)
	return service
}

// BuildServiceListWithOptions returns ServiceList with options provided
func BuildServiceListWithOptions(options ...ExpectedServiceListOption) *servingv1.ServiceList {
	list := &servingv1.ServiceList{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "List",
		},
	}

	for _, fn := range options {
		fn(list)
	}

	return list
}

// WithService appends the given service to ServiceList
func WithService(svc *servingv1.Service) ExpectedServiceListOption {
	return func(list *servingv1.ServiceList) {
		list.Items = append(list.Items, *svc)
	}
}

// BuildRevisionListWithOptions returns RevisionList with options provided
func BuildRevisionListWithOptions(options ...ExpectedRevisionListOption) *servingv1.RevisionList {
	list := &servingv1.RevisionList{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "List",
		},
	}

	for _, fn := range options {
		fn(list)
	}

	return list
}

// BuildKNExportWithOptions returns Export object with the options provided
func BuildKNExportWithOptions(options ...ExpectedKNExportOption) *clientv1alpha1.Export {
	knExport := &clientv1alpha1.Export{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "client.knative.dev/v1alpha1",
			Kind:       "Export",
		},
	}

	for _, fn := range options {
		fn(knExport)
	}

	return knExport
}

// BuildConfigurationSpec builds servingv1.ConfigurationSpec with the options provided
func BuildConfigurationSpec(co ...servingtest.ConfigOption) *servingv1.ConfigurationSpec {
	c := &servingv1.Configuration{
		Spec: servingv1.ConfigurationSpec{
			Template: servingv1.RevisionTemplateSpec{
				Spec: *BuildRevisionSpec(pkgtest.ImagePath("helloworld")),
			},
		},
	}
	for _, opt := range co {
		opt(c)
	}
	c.SetDefaults(context.Background())
	return &c.Spec
}

// BuildRevisionSpec for provided image
func BuildRevisionSpec(image string) *servingv1.RevisionSpec {
	return &servingv1.RevisionSpec{
		PodSpec: corev1.PodSpec{
			Containers: []corev1.Container{{
				Image: image,
			}},
			EnableServiceLinks: ptr.Bool(false),
		},
		TimeoutSeconds: ptr.Int64(config.DefaultRevisionTimeoutSeconds),
	}
}

// BuildServiceWithOptions returns ksvc with options provided
func BuildServiceWithOptions(name string, so ...servingtest.ServiceOption) *servingv1.Service {
	svc := servingtest.ServiceWithoutNamespace(name, so...)
	svc.TypeMeta = metav1.TypeMeta{
		Kind:       "Service",
		APIVersion: "serving.knative.dev/v1",
	}
	svc.Spec.Template.Spec.Containers[0].Resources = corev1.ResourceRequirements{}
	return svc
}

// WithTrafficSpec adds route to ksvc
func WithTrafficSpec(revisions []string, percentages []int, tags []string) servingtest.ServiceOption {
	return func(svc *servingv1.Service) {
		var trafficTargets []servingv1.TrafficTarget
		for i, rev := range revisions {
			trafficTargets = append(trafficTargets, servingv1.TrafficTarget{
				Percent: ptr.Int64(int64(percentages[i])),
			})
			if tags[i] != "" {
				trafficTargets[i].Tag = tags[i]
			}
			if rev == "latest" {
				trafficTargets[i].LatestRevision = ptr.Bool(true)
			} else {
				trafficTargets[i].RevisionName = rev
				trafficTargets[i].LatestRevision = ptr.Bool(false)
			}
		}
		svc.Spec.RouteSpec = servingv1.RouteSpec{
			Traffic: trafficTargets,
		}
	}
}

// BuildRevision returns Revision object with the options provided
func BuildRevision(name string, options ...servingtest.RevisionOption) *servingv1.Revision {
	rev := servingtest.Revision("", name, options...)
	rev.TypeMeta = metav1.TypeMeta{
		Kind:       "Revision",
		APIVersion: "serving.knative.dev/v1",
	}
	rev.Spec.PodSpec.Containers[0].Name = config.DefaultUserContainerName
	rev.Spec.PodSpec.EnableServiceLinks = ptr.Bool(false)
	rev.ObjectMeta.SelfLink = ""
	rev.ObjectMeta.Namespace = ""
	rev.ObjectMeta.UID = ""
	rev.ObjectMeta.Generation = int64(0)
	rev.Spec.PodSpec.Containers[0].Resources = corev1.ResourceRequirements{}
	return rev
}

// WithRevision appends Revision object to RevisionList
func WithRevision(rev servingv1.Revision) ExpectedRevisionListOption {
	return func(list *servingv1.RevisionList) {
		list.Items = append(list.Items, rev)
	}
}

// WithKNRevision appends Revision object RevisionList to Kn Export
func WithKNRevision(rev servingv1.Revision) ExpectedKNExportOption {
	return func(export *clientv1alpha1.Export) {
		export.Spec.Revisions = append(export.Spec.Revisions, rev)
	}
}

// WithRevisionEnv adds env variable to Revision object
func WithRevisionEnv(evs ...corev1.EnvVar) servingtest.RevisionOption {
	return func(s *servingv1.Revision) {
		s.Spec.PodSpec.Containers[0].Env = evs
	}
}

// WithRevisionImage adds revision image to Revision object
func WithRevisionImage(image string) servingtest.RevisionOption {
	return func(s *servingv1.Revision) {
		s.Spec.PodSpec.Containers[0].Image = image
	}
}

// WithRevisionAnnotations adds annotation to revision spec in ksvc
func WithRevisionAnnotations(annotations map[string]string) servingtest.ServiceOption {
	return func(service *servingv1.Service) {
		service.Spec.Template.ObjectMeta.Annotations = kmeta.UnionMaps(
			service.Spec.Template.ObjectMeta.Annotations, annotations)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package negotiation

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

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// errNotAcceptable indicates Accept negotiation has failed
type errNotAcceptable struct {
	accepted []string
}

func NewNotAcceptableError(accepted []string) error {
	return errNotAcceptable{accepted}
}

func (e errNotAcceptable) Error() string {
	return fmt.Sprintf("only the following media types are accepted: %v", strings.Join(e.accepted, ", "))
}

func (e errNotAcceptable) Status() metav1.Status {
	return metav1.Status{
		Status:  metav1.StatusFailure,
		Code:    http.StatusNotAcceptable,
		Reason:  metav1.StatusReason("NotAcceptable"),
		Message: e.Error(),
	}
}

// errUnsupportedMediaType indicates Content-Type is not recognized
type errUnsupportedMediaType struct {
	accepted []string
}

func NewUnsupportedMediaTypeError(accepted []string) error {
	return errUnsupportedMediaType{accepted}
}

func (e errUnsupportedMediaType) Error() string {
	return fmt.Sprintf("the body of the request was in an unknown format - accepted media types include: %v", strings.Join(e.accepted, ", "))
}

func (e errUnsupportedMediaType) Status() metav1.Status {
	return metav1.Status{
		Status:  metav1.StatusFailure,
		Code:    http.StatusUnsupportedMediaType,
		Reason:  metav1.StatusReason("UnsupportedMediaType"),
		Message: e.Error(),
	}
}
<commit_msg>Add error helpers and constants for NotAcceptable and UnsupportedMediaType<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package negotiation

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

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// errNotAcceptable indicates Accept negotiation has failed
type errNotAcceptable struct {
	accepted []string
}

func NewNotAcceptableError(accepted []string) error {
	return errNotAcceptable{accepted}
}

func (e errNotAcceptable) Error() string {
	return fmt.Sprintf("only the following media types are accepted: %v", strings.Join(e.accepted, ", "))
}

func (e errNotAcceptable) Status() metav1.Status {
	return metav1.Status{
		Status:  metav1.StatusFailure,
		Code:    http.StatusNotAcceptable,
		Reason:  metav1.StatusReasonNotAcceptable,
		Message: e.Error(),
	}
}

// errUnsupportedMediaType indicates Content-Type is not recognized
type errUnsupportedMediaType struct {
	accepted []string
}

func NewUnsupportedMediaTypeError(accepted []string) error {
	return errUnsupportedMediaType{accepted}
}

func (e errUnsupportedMediaType) Error() string {
	return fmt.Sprintf("the body of the request was in an unknown format - accepted media types include: %v", strings.Join(e.accepted, ", "))
}

func (e errUnsupportedMediaType) Status() metav1.Status {
	return metav1.Status{
		Status:  metav1.StatusFailure,
		Code:    http.StatusUnsupportedMediaType,
		Reason:  metav1.StatusReasonUnsupportedMediaType,
		Message: e.Error(),
	}
}
<|endoftext|>