<commit_before>/*
TODO:
 - Camera
 - Triangles
 - Spheres
 - Point lights
 - Reflection
 - Refraction
 - Phong lighting
 - Texture mapping
 - Bump mapping
 - Antialiasing
 - Skybox
 - Caustics
*/
package main

import (
	"flag"
	"fmt"
	"image"
	"image/png"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/Bredgren/raytracer"
)

const (
	sceneDir = "scene"
	renderDir = "renderedscene"
	usageStr = "Usage: raytracer scenefile"
)

var (
	sceneFile = ""
	noImg = false
)

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n", usageStr)
		flag.PrintDefaults()
	}
	flag.BoolVar(&noImg, "NoImg", false, "Don't create an image if present.")
	flag.Parse()

	if flag.NArg() < 1 {
		panic(usageStr)
	}

	sceneFile = flag.Arg(0)
}

func main() {
	scene := raytracer.Parse(sceneDir + "/" + sceneFile)

	bounds := image.Rect(0, 0, scene.Camera.ImageWidth, scene.Camera.ImageHeight)
	img := image.NewNRGBA(bounds)

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			img.SetNRGBA(x, y, scene.TracePixel(x, y))
		}
	}

	if noImg {
		return
	}

	files, err := ioutil.ReadDir(renderDir)
	if err != nil {
		log.Fatal(err)
	}
	count := 0
	for _, file := range files {
		name :=file.Name()
		if strings.HasPrefix(name, "render") && len(name) > 10 {
			number, err := strconv.Atoi(name[6:len(name) - 4])
			if err != nil {
				log.Fatal(err)
			}
			if number > count {
				count = number
			}
		}
	}

	outFile := fmt.Sprintf("%s/render%d.png", renderDir, count + 1)

	file, err := os.Create(outFile)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	png.Encode(file, img)
}
<commit_msg>Add timer.<commit_after>/*
TODO:
 - Phong lighting
 - Reflection
 - Refraction
 - Texture mapping
 - Bump mapping
 - Antialiasing
 - Skybox
 - Caustics
*/
package main

import (
	"flag"
	"fmt"
	"image"
	"image/png"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/Bredgren/raytracer"
)

const (
	sceneDir = "scene"
	renderDir = "renderedscene"
	usageStr = "Usage: raytracer scenefile"
)

var (
	sceneFile = ""
	noImg = false
)

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n", usageStr)
		flag.PrintDefaults()
	}
	flag.BoolVar(&noImg, "NoImg", false, "Don't create an image if present.")
	flag.Parse()

	if flag.NArg() < 1 {
		panic(usageStr)
	}

	sceneFile = flag.Arg(0)
}

func main() {
	scene := raytracer.Parse(sceneDir + "/" + sceneFile)

	bounds := image.Rect(0, 0, scene.Camera.ImageWidth, scene.Camera.ImageHeight)
	img := image.NewNRGBA(bounds)

	log.Println("Begin tracing")
	begin := time.Now()
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			img.SetNRGBA(x, y, scene.TracePixel(x, y))
		}
	}
	end := time.Now()
	log.Printf("Done tracing, took %v", end.Sub(begin))

	if noImg {
		return
	}

	files, err := ioutil.ReadDir(renderDir)
	if err != nil {
		log.Fatal(err)
	}
	count := 0
	for _, file := range files {
		name :=file.Name()
		if strings.HasPrefix(name, "render") && len(name) > 10 {
			number, err := strconv.Atoi(name[6:len(name) - 4])
			if err != nil {
				log.Fatal(err)
			}
			if number > count {
				count = number
			}
		}
	}

	outFile := fmt.Sprintf("%s/render%d.png", renderDir, count + 1)

	file, err := os.Create(outFile)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	png.Encode(file, img)
}
<|endoftext|>


<commit_before>package movieds

import (
	"context"
	"database/sql"

	"github.com/gilcrest/go-api-basic/app"
	"github.com/gilcrest/go-api-basic/datastore"
	"github.com/gilcrest/go-api-basic/domain/errs"
	"github.com/gilcrest/go-api-basic/domain/movie"
	"github.com/google/uuid"
	"github.com/rs/xid"
)

// MovieDS is the interface for the persistence layer for a movie
type MovieDS interface {
	Store(context.Context, *movie.Movie) error
	FindByID(context.Context, xid.ID) (*movie.Movie, error)
}

// ProvideMovieDS sets up either a concrete MovieDB or a MockMovieDB
// depending on the underlying struct of the Datastore passed in
func ProvideMovieDS(app *app.Application) (MovieDS, error) {
	const op errs.Op = "movieds/ProvideMovieDS"

	// Use a type switch to determine if the app datastore is a Mock
	// Datastore, if so, then return MockMovieDB, otherwise use
	// composition to add the Datastore to the MovieDB struct
	switch ds := app.DS.(type) {
	case *datastore.MockDS:
		return &MockMovieDB{}, nil
	case *datastore.DS:
		return &MovieDB{DS: ds}, nil
	default:
		return nil, errs.E(op, "Unknown type for datastore.Datastore")
	}
}

// MovieDB is the database implementation for CRUD operations for a movie
type MovieDB struct {
	*datastore.DS
}

// Store creates a record in the user table using a stored function
func (mdb *MovieDB) Store(ctx context.Context, m *movie.Movie) error {
	const op errs.Op = "movie/Movie.createDB"

	// Prepare the sql statement using bind variables
	stmt, err := mdb.Tx.PrepareContext(ctx, `
	select o_create_timestamp,
		   o_update_timestamp
	  from demo.create_movie (
		p_id => $1,
		p_extl_id => $2,
		p_title => $3,
		p_year => $4,
		p_rated => $5,
		p_released => $6,
		p_run_time => $7,
		p_director => $8,
		p_writer => $9,
		p_create_client_id => $10,
		p_create_user_id => $11)`)

	if err != nil {
		return errs.E(op, err)
	}
	defer stmt.Close()

	// At some point, I will add a whole user flow, but for now
	// faking a user uuid....
	fakeUserID := uuid.New()

	// Execute stored function that returns the create_date timestamp,
	// hence the use of QueryContext instead of Exec
	rows, err := stmt.QueryContext(ctx,
		m.ID,              //$1
		m.ExtlID.String(), //$2
		m.Title,           //$3
		m.Year,            //$4
		m.Rated,           //$5
		m.Released,        //$6
		m.RunTime,         //$7
		m.Director,        //$8
		m.Writer,          //$9
		fakeUserID,        //$10
		fakeUserID)        //$11

	if err != nil {
		return errs.E(op, err)
	}
	defer rows.Close()

	// Iterate through the returned record(s)
	for rows.Next() {
		if err := rows.Scan(&m.CreateTimestamp, &m.UpdateTimestamp); err != nil {
			return errs.E(op, err)
		}
	}

	// If any error was encountered while iterating through rows.Next above
	// it will be returned here
	if err := rows.Err(); err != nil {
		return errs.E(op, err)
	}

	return nil
}

// FindByID returns a Movie struct to populate the response
func (mdb *MovieDB) FindByID(ctx context.Context, extlID xid.ID) (*movie.Movie, error) {
	const op errs.Op = "movieds/MovieDB.FindByID"

	// Prepare the sql statement using bind variables
	row := mdb.DB.QueryRowContext(ctx,
		`select movie_id,
				extl_id,
				title,
				year,
				rated,
				released,
				run_time,
				director,
				writer,
				create_timestamp,
				update_timestamp
		   from demo.movie m
		  where extl_id = $1;`, extlID)

	m := new(movie.Movie)
	err := row.Scan(
		&m.ID,
		&m.ExtlID,
		&m.Title,
		&m.Year,
		&m.Rated,
		&m.Released,
		&m.RunTime,
		&m.Director,
		&m.Writer,
		&m.CreateTimestamp,
		&m.UpdateTimestamp)

	if err == sql.ErrNoRows {
		return nil, errs.E(op, errs.NotExist, err)
	} else if err != nil {
		return nil, errs.E(op, err)
	}

	return m, nil
}
<commit_msg>Add FindAll<commit_after>package movieds

import (
	"context"
	"database/sql"
	"time"

	"github.com/gilcrest/go-api-basic/app"
	"github.com/gilcrest/go-api-basic/datastore"
	"github.com/gilcrest/go-api-basic/domain/errs"
	"github.com/gilcrest/go-api-basic/domain/movie"
	"github.com/google/uuid"
	"github.com/rs/xid"
)

// MovieDS is the interface for the persistence layer for a movie
type MovieDS interface {
	Store(context.Context, *movie.Movie) error
	FindByID(context.Context, xid.ID) (*movie.Movie, error)
	FindAll(context.Context) ([]*movie.Movie, error)
}

// ProvideMovieDS sets up either a concrete MovieDB or a MockMovieDB
// depending on the underlying struct of the Datastore passed in
func ProvideMovieDS(app *app.Application) (MovieDS, error) {
	const op errs.Op = "movieds/ProvideMovieDS"

	// Use a type switch to determine if the app datastore is a Mock
	// Datastore, if so, then return MockMovieDB, otherwise use
	// composition to add the Datastore to the MovieDB struct
	switch ds := app.DS.(type) {
	case *datastore.MockDS:
		return &MockMovieDB{}, nil
	case *datastore.DS:
		return &MovieDB{DS: ds}, nil
	default:
		return nil, errs.E(op, "Unknown type for datastore.Datastore")
	}
}

// MovieDB is the database implementation for CRUD operations for a movie
type MovieDB struct {
	*datastore.DS
}

// Store creates a record in the user table using a stored function
func (mdb *MovieDB) Store(ctx context.Context, m *movie.Movie) error {
	const op errs.Op = "movie/Movie.createDB"

	// Prepare the sql statement using bind variables
	stmt, err := mdb.Tx.PrepareContext(ctx, `
	select o_create_timestamp,
		   o_update_timestamp
	  from demo.create_movie (
		p_id => $1,
		p_extl_id => $2,
		p_title => $3,
		p_year => $4,
		p_rated => $5,
		p_released => $6,
		p_run_time => $7,
		p_director => $8,
		p_writer => $9,
		p_create_client_id => $10,
		p_create_user_id => $11)`)

	if err != nil {
		return errs.E(op, err)
	}
	defer stmt.Close()

	// At some point, I will add a whole user flow, but for now
	// faking a user uuid....
	fakeUserID := uuid.New()

	// Execute stored function that returns the create_date timestamp,
	// hence the use of QueryContext instead of Exec
	rows, err := stmt.QueryContext(ctx,
		m.ID,              //$1
		m.ExtlID.String(), //$2
		m.Title,           //$3
		m.Year,            //$4
		m.Rated,           //$5
		m.Released,        //$6
		m.RunTime,         //$7
		m.Director,        //$8
		m.Writer,          //$9
		fakeUserID,        //$10
		fakeUserID)        //$11

	if err != nil {
		return errs.E(op, err)
	}
	defer rows.Close()

	// Iterate through the returned record(s)
	for rows.Next() {
		if err := rows.Scan(&m.CreateTimestamp, &m.UpdateTimestamp); err != nil {
			return errs.E(op, err)
		}
	}

	// If any error was encountered while iterating through rows.Next above
	// it will be returned here
	if err := rows.Err(); err != nil {
		return errs.E(op, err)
	}

	return nil
}

// FindByID returns a Movie struct to populate the response
func (mdb *MovieDB) FindByID(ctx context.Context, extlID xid.ID) (*movie.Movie, error) {
	const op errs.Op = "movieds/MovieDB.FindByID"

	// Prepare the sql statement using bind variables
	row := mdb.DB.QueryRowContext(ctx,
		`select movie_id,
				extl_id,
				title,
				year,
				rated,
				released,
				run_time,
				director,
				writer,
				create_timestamp,
				update_timestamp
		   from demo.movie m
		  where extl_id = $1;`, extlID)

	m := new(movie.Movie)
	err := row.Scan(
		&m.ID,
		&m.ExtlID,
		&m.Title,
		&m.Year,
		&m.Rated,
		&m.Released,
		&m.RunTime,
		&m.Director,
		&m.Writer,
		&m.CreateTimestamp,
		&m.UpdateTimestamp)

	if err == sql.ErrNoRows {
		return nil, errs.E(op, errs.NotExist, err)
	} else if err != nil {
		return nil, errs.E(op, err)
	}

	return m, nil
}

// FindAll returns a slice of Movie structs to populate the response
func (mdb *MovieDB) FindAll(ctx context.Context) ([]*movie.Movie, error) {
	const op errs.Op = "movieds/MockMovieDB.FindAll"

	m1 := new(movie.Movie)
	m1.ExtlID = xid.New()
	m1.Title = "Clockwork Orange"
	m1.CreateTimestamp = time.Now()

	m2 := new(movie.Movie)
	m2.ExtlID = xid.New()
	m2.Title = "Repo Man"
	m2.CreateTimestamp = time.Now()

	s := []*movie.Movie{m1, m2}

	return s, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/elasticache"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsElasticacheSubnetGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsElasticacheSubnetGroupCreate,
		Read:   resourceAwsElasticacheSubnetGroupRead,
		Update: resourceAwsElasticacheSubnetGroupUpdate,
		Delete: resourceAwsElasticacheSubnetGroupDelete,

		Schema: map[string]*schema.Schema{
			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "Managed by Terraform",
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				StateFunc: func(val interface{}) string {
					// Elasticache normalizes subnet names to lowercase,
					// so we have to do this too or else we can end up
					// with non-converging diffs.
					return strings.ToLower(val.(string))
				},
			},
			"subnet_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
		},
	}
}

func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn

	// Get the group properties
	name := d.Get("name").(string)
	desc := d.Get("description").(string)
	subnetIdsSet := d.Get("subnet_ids").(*schema.Set)

	log.Printf("[DEBUG] Cache subnet group create: name: %s, description: %s", name, desc)

	subnetIds := expandStringList(subnetIdsSet.List())

	req := &elasticache.CreateCacheSubnetGroupInput{
		CacheSubnetGroupDescription: aws.String(desc),
		CacheSubnetGroupName:        aws.String(name),
		SubnetIds:                   subnetIds,
	}

	_, err := conn.CreateCacheSubnetGroup(req)
	if err != nil {
		return fmt.Errorf("Error creating CacheSubnetGroup: %s", err)
	}

	// Assign the group name as the resource ID
	// Elasticache always retains the name in lower case, so we have to
	// mimic that or else we won't be able to refresh a resource whose
	// name contained uppercase characters.
	d.SetId(strings.ToLower(name))

	return nil
}

func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn
	req := &elasticache.DescribeCacheSubnetGroupsInput{
		CacheSubnetGroupName: aws.String(d.Get("name").(string)),
	}

	res, err := conn.DescribeCacheSubnetGroups(req)
	if err != nil {
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "CacheSubnetGroupNotFoundFault" {
			// Update state to indicate the db subnet no longer exists.
			d.SetId("")
			return nil
		}
		return err
	}
	if len(res.CacheSubnetGroups) == 0 {
		return fmt.Errorf("Error missing %v", d.Get("name"))
	}

	var group *elasticache.CacheSubnetGroup
	for _, g := range res.CacheSubnetGroups {
		log.Printf("[DEBUG] %v %v", g.CacheSubnetGroupName, d.Id())
		if *g.CacheSubnetGroupName == d.Id() {
			group = g
		}
	}
	if group == nil {
		return fmt.Errorf("Error retrieving cache subnet group: %v", res)
	}

	ids := make([]string, len(group.Subnets))
	for i, s := range group.Subnets {
		ids[i] = *s.SubnetIdentifier
	}

	d.Set("name", group.CacheSubnetGroupName)
	d.Set("description", group.CacheSubnetGroupDescription)
	d.Set("subnet_ids", ids)

	return nil
}

func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn
	if d.HasChange("subnet_ids") || d.HasChange("description") {
		var subnets []*string
		if v := d.Get("subnet_ids"); v != nil {
			for _, v := range v.(*schema.Set).List() {
				subnets = append(subnets, aws.String(v.(string)))
			}
		}
		log.Printf("[DEBUG] Updating ElastiCache Subnet Group")

		_, err := conn.ModifyCacheSubnetGroup(&elasticache.ModifyCacheSubnetGroupInput{
			CacheSubnetGroupName:        aws.String(d.Get("name").(string)),
			CacheSubnetGroupDescription: aws.String(d.Get("description").(string)),
			SubnetIds:                   subnets,
		})
		if err != nil {
			return err
		}
	}

	return resourceAwsElasticacheSubnetGroupRead(d, meta)
}
func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn

	log.Printf("[DEBUG] Cache subnet group delete: %s", d.Id())

	return resource.Retry(5*time.Minute, func() *resource.RetryError {
		_, err := conn.DeleteCacheSubnetGroup(&elasticache.DeleteCacheSubnetGroupInput{
			CacheSubnetGroupName: aws.String(d.Id()),
		})
		if err != nil {
			apierr, ok := err.(awserr.Error)
			if !ok {
				return resource.RetryableError(err)
			}
			log.Printf("[DEBUG] APIError.Code: %v", apierr.Code())
			switch apierr.Code() {
			case "DependencyViolation":
				// If it is a dependency violation, we want to retry
				return resource.RetryableError(err)
			default:
				return resource.NonRetryableError(err)
			}
		}
		return nil
	})
}
<commit_msg>provider/aws: Log ElasticCache subnet removal<commit_after>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/elasticache"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsElasticacheSubnetGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsElasticacheSubnetGroupCreate,
		Read:   resourceAwsElasticacheSubnetGroupRead,
		Update: resourceAwsElasticacheSubnetGroupUpdate,
		Delete: resourceAwsElasticacheSubnetGroupDelete,

		Schema: map[string]*schema.Schema{
			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Default:  "Managed by Terraform",
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
				StateFunc: func(val interface{}) string {
					// Elasticache normalizes subnet names to lowercase,
					// so we have to do this too or else we can end up
					// with non-converging diffs.
					return strings.ToLower(val.(string))
				},
			},
			"subnet_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},
		},
	}
}

func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn

	// Get the group properties
	name := d.Get("name").(string)
	desc := d.Get("description").(string)
	subnetIdsSet := d.Get("subnet_ids").(*schema.Set)

	log.Printf("[DEBUG] Cache subnet group create: name: %s, description: %s", name, desc)

	subnetIds := expandStringList(subnetIdsSet.List())

	req := &elasticache.CreateCacheSubnetGroupInput{
		CacheSubnetGroupDescription: aws.String(desc),
		CacheSubnetGroupName:        aws.String(name),
		SubnetIds:                   subnetIds,
	}

	_, err := conn.CreateCacheSubnetGroup(req)
	if err != nil {
		return fmt.Errorf("Error creating CacheSubnetGroup: %s", err)
	}

	// Assign the group name as the resource ID
	// Elasticache always retains the name in lower case, so we have to
	// mimic that or else we won't be able to refresh a resource whose
	// name contained uppercase characters.
	d.SetId(strings.ToLower(name))

	return nil
}

func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn
	req := &elasticache.DescribeCacheSubnetGroupsInput{
		CacheSubnetGroupName: aws.String(d.Get("name").(string)),
	}

	res, err := conn.DescribeCacheSubnetGroups(req)
	if err != nil {
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "CacheSubnetGroupNotFoundFault" {
			// Update state to indicate the db subnet no longer exists.
			log.Printf("[WARN] Elasticache Subnet Group (%s) not found, removing from state", d.Id())
			d.SetId("")
			return nil
		}
		return err
	}
	if len(res.CacheSubnetGroups) == 0 {
		return fmt.Errorf("Error missing %v", d.Get("name"))
	}

	var group *elasticache.CacheSubnetGroup
	for _, g := range res.CacheSubnetGroups {
		log.Printf("[DEBUG] %v %v", g.CacheSubnetGroupName, d.Id())
		if *g.CacheSubnetGroupName == d.Id() {
			group = g
		}
	}
	if group == nil {
		return fmt.Errorf("Error retrieving cache subnet group: %v", res)
	}

	ids := make([]string, len(group.Subnets))
	for i, s := range group.Subnets {
		ids[i] = *s.SubnetIdentifier
	}

	d.Set("name", group.CacheSubnetGroupName)
	d.Set("description", group.CacheSubnetGroupDescription)
	d.Set("subnet_ids", ids)

	return nil
}

func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn
	if d.HasChange("subnet_ids") || d.HasChange("description") {
		var subnets []*string
		if v := d.Get("subnet_ids"); v != nil {
			for _, v := range v.(*schema.Set).List() {
				subnets = append(subnets, aws.String(v.(string)))
			}
		}
		log.Printf("[DEBUG] Updating ElastiCache Subnet Group")

		_, err := conn.ModifyCacheSubnetGroup(&elasticache.ModifyCacheSubnetGroupInput{
			CacheSubnetGroupName:        aws.String(d.Get("name").(string)),
			CacheSubnetGroupDescription: aws.String(d.Get("description").(string)),
			SubnetIds:                   subnets,
		})
		if err != nil {
			return err
		}
	}

	return resourceAwsElasticacheSubnetGroupRead(d, meta)
}
func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).elasticacheconn

	log.Printf("[DEBUG] Cache subnet group delete: %s", d.Id())

	return resource.Retry(5*time.Minute, func() *resource.RetryError {
		_, err := conn.DeleteCacheSubnetGroup(&elasticache.DeleteCacheSubnetGroupInput{
			CacheSubnetGroupName: aws.String(d.Id()),
		})
		if err != nil {
			apierr, ok := err.(awserr.Error)
			if !ok {
				return resource.RetryableError(err)
			}
			log.Printf("[DEBUG] APIError.Code: %v", apierr.Code())
			switch apierr.Code() {
			case "DependencyViolation":
				// If it is a dependency violation, we want to retry
				return resource.RetryableError(err)
			default:
				return resource.NonRetryableError(err)
			}
		}
		return nil
	})
}
<|endoftext|>


<commit_before>package vitals_test

import (
	"path"
	"runtime"
	"time"

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

	"github.com/cloudfoundry/bosh-agent/platform/disk/diskfakes"
	boshstats "github.com/cloudfoundry/bosh-agent/platform/stats"
	fakestats "github.com/cloudfoundry/bosh-agent/platform/stats/fakes"
	. "github.com/cloudfoundry/bosh-agent/platform/vitals"
	boshdirs "github.com/cloudfoundry/bosh-agent/settings/directories"
	boshassert "github.com/cloudfoundry/bosh-utils/assert"
)

const Windows = runtime.GOOS == "windows"

var _ = Describe("Vitals service", func() {
	var (
		dirProvider    boshdirs.Provider
		statsCollector *fakestats.FakeCollector
		mounter        *diskfakes.FakeMounter
		service        Service
	)

	BeforeEach(func() {
		dirProvider = boshdirs.NewProvider("/fake/base/dir")
		statsCollector = &fakestats.FakeCollector{
			CPULoad: boshstats.CPULoad{
				One:     0.2,
				Five:    4.55,
				Fifteen: 1.123,
			},
			StartCollectingCPUStats: boshstats.CPUStats{
				User:  56,
				Sys:   10,
				Wait:  1,
				Total: 100,
			},
			MemStats: boshstats.Usage{
				Used:  700 * 1024,
				Total: 1000 * 1024,
			},
			SwapStats: boshstats.Usage{
				Used:  600 * 1024,
				Total: 1000 * 1024,
			},
			UptimeStats: boshstats.UptimeStats{
				Secs: 5,
			},
			DiskStats: map[string]boshstats.DiskStats{
				"/": {
					DiskUsage:  boshstats.Usage{Used: 100, Total: 200},
					InodeUsage: boshstats.Usage{Used: 50, Total: 500},
				},
				dirProvider.DataDir(): {
					DiskUsage:  boshstats.Usage{Used: 15, Total: 20},
					InodeUsage: boshstats.Usage{Used: 10, Total: 50},
				},
				dirProvider.StoreDir(): {
					DiskUsage:  boshstats.Usage{Used: 2, Total: 2},
					InodeUsage: boshstats.Usage{Used: 3, Total: 4},
				},
			},
		}

		mounter = &diskfakes.FakeMounter{}
		mounter.IsMountPointReturns("/dev/fake-partition-device", true, nil)

		service = NewService(statsCollector, dirProvider, mounter)
		statsCollector.StartCollecting(1*time.Millisecond, nil)
	})

	It("constructs vitals properly", func() {
		vitals, err := service.Get()

		expectedVitals := map[string]interface{}{
			"cpu": map[string]string{
				"sys":  "10.0",
				"user": "56.0",
				"wait": "1.0",
			},
			"disk": map[string]interface{}{
				"system": map[string]string{
					"percent":       "50",
					"inode_percent": "10",
				},
				"ephemeral": map[string]string{
					"percent":       "75",
					"inode_percent": "20",
				},
				"persistent": map[string]string{
					"percent":       "100",
					"inode_percent": "75",
				},
			},
			"mem": map[string]string{
				"kb":      "700",
				"percent": "70",
			},
			"swap": map[string]string{
				"kb":      "600",
				"percent": "60",
			},
			"uptime": map[string]uint64{
				"secs": 5,
			},
		}
		if Windows {
			expectedVitals["load"] = []string{""}
		} else {
			expectedVitals["load"] = []string{"0.20", "4.55", "1.12"}
		}

		Expect(err).ToNot(HaveOccurred())

		Expect(mounter.IsMountPointCallCount()).To(Equal(3))

		boshassert.MatchesJSONMap(GinkgoT(), vitals, expectedVitals)
	})

	Context("when missing stats for ephemeral and peristent disk", func() {
		BeforeEach(func() {
			statsCollector.DiskStats = map[string]boshstats.DiskStats{
				"/": {
					DiskUsage:  boshstats.Usage{Used: 100, Total: 200},
					InodeUsage: boshstats.Usage{Used: 50, Total: 500},
				},
			}
		})

		It("returns vitals for root disk only", func() {
			vitals, err := service.Get()
			Expect(err).ToNot(HaveOccurred())

			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "ephemeral")
			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "persistent")
		})
	})

	Context("when missing stats for system disk", func() {
		BeforeEach(func() {
			statsCollector.DiskStats = map[string]boshstats.DiskStats{}
		})

		It("returns an error", func() {
			_, err := service.Get()
			Expect(err).To(HaveOccurred())
		})
	})

	Context("when no persistent disk is mounted", func() {
		BeforeEach(func() {
			mounter.IsMountPointStub = func(folderPath string) (partitionPath string, isMountPoint bool, err error) {
				partitionPath = "/dev/fake-partition-device"
				isMountPoint = path.Base(folderPath) != "store"
				return
			}
		})

		It("does not return vitals for persistent disk", func() {
			vitals, err := service.Get()

			Expect(err).NotTo(HaveOccurred())
			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "persistent")
		})
	})
})
<commit_msg>Change from path.Base to filepath.Base because the latter respects os path separators<commit_after>package vitals_test

import (
	"path/filepath"
	"runtime"
	"time"

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

	"github.com/cloudfoundry/bosh-agent/platform/disk/diskfakes"
	boshstats "github.com/cloudfoundry/bosh-agent/platform/stats"
	fakestats "github.com/cloudfoundry/bosh-agent/platform/stats/fakes"
	. "github.com/cloudfoundry/bosh-agent/platform/vitals"
	boshdirs "github.com/cloudfoundry/bosh-agent/settings/directories"
	boshassert "github.com/cloudfoundry/bosh-utils/assert"
)

const Windows = runtime.GOOS == "windows"

var _ = Describe("Vitals service", func() {
	var (
		dirProvider    boshdirs.Provider
		statsCollector *fakestats.FakeCollector
		mounter        *diskfakes.FakeMounter
		service        Service
	)

	BeforeEach(func() {
		dirProvider = boshdirs.NewProvider("/fake/base/dir")
		statsCollector = &fakestats.FakeCollector{
			CPULoad: boshstats.CPULoad{
				One:     0.2,
				Five:    4.55,
				Fifteen: 1.123,
			},
			StartCollectingCPUStats: boshstats.CPUStats{
				User:  56,
				Sys:   10,
				Wait:  1,
				Total: 100,
			},
			MemStats: boshstats.Usage{
				Used:  700 * 1024,
				Total: 1000 * 1024,
			},
			SwapStats: boshstats.Usage{
				Used:  600 * 1024,
				Total: 1000 * 1024,
			},
			UptimeStats: boshstats.UptimeStats{
				Secs: 5,
			},
			DiskStats: map[string]boshstats.DiskStats{
				"/": {
					DiskUsage:  boshstats.Usage{Used: 100, Total: 200},
					InodeUsage: boshstats.Usage{Used: 50, Total: 500},
				},
				dirProvider.DataDir(): {
					DiskUsage:  boshstats.Usage{Used: 15, Total: 20},
					InodeUsage: boshstats.Usage{Used: 10, Total: 50},
				},
				dirProvider.StoreDir(): {
					DiskUsage:  boshstats.Usage{Used: 2, Total: 2},
					InodeUsage: boshstats.Usage{Used: 3, Total: 4},
				},
			},
		}

		mounter = &diskfakes.FakeMounter{}
		mounter.IsMountPointReturns("/dev/fake-partition-device", true, nil)

		service = NewService(statsCollector, dirProvider, mounter)
		statsCollector.StartCollecting(1*time.Millisecond, nil)
	})

	It("constructs vitals properly", func() {
		vitals, err := service.Get()

		expectedVitals := map[string]interface{}{
			"cpu": map[string]string{
				"sys":  "10.0",
				"user": "56.0",
				"wait": "1.0",
			},
			"disk": map[string]interface{}{
				"system": map[string]string{
					"percent":       "50",
					"inode_percent": "10",
				},
				"ephemeral": map[string]string{
					"percent":       "75",
					"inode_percent": "20",
				},
				"persistent": map[string]string{
					"percent":       "100",
					"inode_percent": "75",
				},
			},
			"mem": map[string]string{
				"kb":      "700",
				"percent": "70",
			},
			"swap": map[string]string{
				"kb":      "600",
				"percent": "60",
			},
			"uptime": map[string]uint64{
				"secs": 5,
			},
		}
		if Windows {
			expectedVitals["load"] = []string{""}
		} else {
			expectedVitals["load"] = []string{"0.20", "4.55", "1.12"}
		}

		Expect(err).ToNot(HaveOccurred())

		Expect(mounter.IsMountPointCallCount()).To(Equal(3))

		boshassert.MatchesJSONMap(GinkgoT(), vitals, expectedVitals)
	})

	Context("when missing stats for ephemeral and peristent disk", func() {
		BeforeEach(func() {
			statsCollector.DiskStats = map[string]boshstats.DiskStats{
				"/": {
					DiskUsage:  boshstats.Usage{Used: 100, Total: 200},
					InodeUsage: boshstats.Usage{Used: 50, Total: 500},
				},
			}
		})

		It("returns vitals for root disk only", func() {
			vitals, err := service.Get()
			Expect(err).ToNot(HaveOccurred())

			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "ephemeral")
			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "persistent")
		})
	})

	Context("when missing stats for system disk", func() {
		BeforeEach(func() {
			statsCollector.DiskStats = map[string]boshstats.DiskStats{}
		})

		It("returns an error", func() {
			_, err := service.Get()
			Expect(err).To(HaveOccurred())
		})
	})

	Context("when no persistent disk is mounted", func() {
		BeforeEach(func() {
			mounter.IsMountPointStub = func(folderPath string) (partitionPath string, isMountPoint bool, err error) {
				partitionPath = "/dev/fake-partition-device"
				isMountPoint = filepath.Base(folderPath) != "store"
				return
			}
		})

		It("does not return vitals for persistent disk", func() {
			vitals, err := service.Get()

			Expect(err).NotTo(HaveOccurred())
			boshassert.LacksJSONKey(GinkgoT(), vitals.Disk, "persistent")
		})
	})
})
<|endoftext|>


<commit_before>package TF2RconWrapper

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/james4k/rcon"
)

// TF2RconConnection represents a rcon connection to a TF2 server
type TF2RconConnection struct {
	rc   *rcon.RemoteConsole
	host string
}

// Query executes a query and returns the server responses
func (c *TF2RconConnection) Query(req string) (string, error) {
	reqID, reqErr := c.rc.Write(req)
	if reqErr != nil {
		fmt.Print(reqErr)
		return "", reqErr
	}

	resp, respID, respErr := c.rc.Read()
	if respErr != nil {
		fmt.Print(respErr)
		return "", respErr
	}

	// retry until you get a response
	for {
		if reqID == respID {
			break
		} else {
			resp, respID, respErr = c.rc.Read()
			if respErr != nil {
				fmt.Print(respErr)
				return "", reqErr
			}
		}
	}

	return resp, nil
}

// GetPlayers returns a list of players in the server. Includes bots.
func (c *TF2RconConnection) GetPlayers() []Player {
	playerString, err := c.Query("status")
	res := strings.Split(playerString, "\n")
	for !strings.HasPrefix(res[0], "#") {
		res = res[1:]
	}
	res = res[1:]
	var list []Player
	for _, elem := range res {
		if elem == "" {
			continue
		}
		if !strings.HasPrefix(elem, "#") {
			break
		}
		elems := strings.Fields(elem)[1:]
		userID := elems[0]
		name := elems[1]
		name = name[1 : len(name)-1]
		uniqueID := elems[2]
		if uniqueID == "BOT" {
			list = append(list, Player{userID, name, uniqueID, 0, "active", ""})
		} else {
			ping, _ := strconv.Atoi(elems[4])
			state := elems[6]
			ip := elems[7]
			list = append(list, Player{userID, name, uniqueID, ping, state, ip})
		}
	}
	return list
}

// KickPlayer kicks a player
func (c *TF2RconConnection) KickPlayer(p Player, message string) error {
	query := "kickid " + p.UserID
	if message != "" {
		query += " \"" + message + "\""
	}
	_, err := c.Query(query)
	return err
}

// BanPlayer bans a player
func (c *TF2RconConnection) BanPlayer(minutes int, p Player, message string) error {
	query := "banid " + fmt.Sprintf("%v", minutes) + " " + p.UserID
	if message != "" {
		query += " \"" + message + "\""
	}
	_, err := c.Query(query)
	return err
}

// UnbanPlayer unbans a player
func (c *TF2RconConnection) UnbanPlayer(p Player) error {
	query := "unbanid " + p.UserID
	_, err := c.Query(query)
	return err
}

// Say sends a message to the TF2 server chat
func (c *TF2RconConnection) Say(message string) error {
	query := "say " + message
	_, err := c.Query(query)
	return err
}

// ChangeRconPassword changes the rcon password and updates the current connection
// to use the new password
func (c *TF2RconConnection) ChangeRconPassword(password string) error {
	query := "rcon_password \"" + password + "\""
	_, err := c.Query(query)

	if err == nil {
		c.rc.Close()
		newConnection, _ := rcon.Dial(c.host, password)
		c.rc = newConnection
	}

	return err
}

// ChangeMap changes the map
func (c *TF2RconConnection) ChangeMap(mapname string) error {
	query := "changelevel \"" + mapname + "\""
	res, err := c.Query(query)
	if res != "" {
		return errors.New(res)
	}
	return err
}

// ChangeServerPassword changes the server password
func (c *TF2RconConnection) ChangeServerPassword(password string) error {
	query := "sv_password \"" + password + "\""
	_, err := c.Query(query)
	return err
}

// RedirectLogs send the logaddress_add command
func (c *TF2RconConnection) RedirectLogs(ip string, port string) error {
	query := "logaddress_add " + ip + ":" + port
	_, err := c.Query(query)
	return err
}

// Close closes the connection
func (c *TF2RconConnection) Close() {
	c.rc.Close()
}

// ExecConfig accepts a string and executes its lines one by one. Assumes
// UNiX line endings
func (c *TF2RconConnection) ExecConfig(config string) error {
	lines := strings.Split(config, "\n")
	for _, line := range lines {
		_, err := c.Query(line)
		if err != nil {
			return err
		}
	}
	return nil
}

// NewTF2RconConnection builds a new TF2RconConnection to a server at address ("ip:port") using
// a rcon_password password
func NewTF2RconConnection(address, password string) (*TF2RconConnection, error) {
	rc, err := rcon.Dial(address, password)
	if err != nil {
		return nil, err
	}
	return &TF2RconConnection{rc, address}, nil
}
<commit_msg>Removed unused variable<commit_after>package TF2RconWrapper

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/james4k/rcon"
)

// TF2RconConnection represents a rcon connection to a TF2 server
type TF2RconConnection struct {
	rc   *rcon.RemoteConsole
	host string
}

// Query executes a query and returns the server responses
func (c *TF2RconConnection) Query(req string) (string, error) {
	reqID, reqErr := c.rc.Write(req)
	if reqErr != nil {
		fmt.Print(reqErr)
		return "", reqErr
	}

	resp, respID, respErr := c.rc.Read()
	if respErr != nil {
		fmt.Print(respErr)
		return "", respErr
	}

	// retry until you get a response
	for {
		if reqID == respID {
			break
		} else {
			resp, respID, respErr = c.rc.Read()
			if respErr != nil {
				fmt.Print(respErr)
				return "", reqErr
			}
		}
	}

	return resp, nil
}

// GetPlayers returns a list of players in the server. Includes bots.
func (c *TF2RconConnection) GetPlayers() []Player {
	playerString, _ := c.Query("status")
	res := strings.Split(playerString, "\n")
	for !strings.HasPrefix(res[0], "#") {
		res = res[1:]
	}
	res = res[1:]
	var list []Player
	for _, elem := range res {
		if elem == "" {
			continue
		}
		if !strings.HasPrefix(elem, "#") {
			break
		}
		elems := strings.Fields(elem)[1:]
		userID := elems[0]
		name := elems[1]
		name = name[1 : len(name)-1]
		uniqueID := elems[2]
		if uniqueID == "BOT" {
			list = append(list, Player{userID, name, uniqueID, 0, "active", ""})
		} else {
			ping, _ := strconv.Atoi(elems[4])
			state := elems[6]
			ip := elems[7]
			list = append(list, Player{userID, name, uniqueID, ping, state, ip})
		}
	}
	return list
}

// KickPlayer kicks a player
func (c *TF2RconConnection) KickPlayer(p Player, message string) error {
	query := "kickid " + p.UserID
	if message != "" {
		query += " \"" + message + "\""
	}
	_, err := c.Query(query)
	return err
}

// BanPlayer bans a player
func (c *TF2RconConnection) BanPlayer(minutes int, p Player, message string) error {
	query := "banid " + fmt.Sprintf("%v", minutes) + " " + p.UserID
	if message != "" {
		query += " \"" + message + "\""
	}
	_, err := c.Query(query)
	return err
}

// UnbanPlayer unbans a player
func (c *TF2RconConnection) UnbanPlayer(p Player) error {
	query := "unbanid " + p.UserID
	_, err := c.Query(query)
	return err
}

// Say sends a message to the TF2 server chat
func (c *TF2RconConnection) Say(message string) error {
	query := "say " + message
	_, err := c.Query(query)
	return err
}

// ChangeRconPassword changes the rcon password and updates the current connection
// to use the new password
func (c *TF2RconConnection) ChangeRconPassword(password string) error {
	query := "rcon_password \"" + password + "\""
	_, err := c.Query(query)

	if err == nil {
		c.rc.Close()
		newConnection, _ := rcon.Dial(c.host, password)
		c.rc = newConnection
	}

	return err
}

// ChangeMap changes the map
func (c *TF2RconConnection) ChangeMap(mapname string) error {
	query := "changelevel \"" + mapname + "\""
	res, err := c.Query(query)
	if res != "" {
		return errors.New(res)
	}
	return err
}

// ChangeServerPassword changes the server password
func (c *TF2RconConnection) ChangeServerPassword(password string) error {
	query := "sv_password \"" + password + "\""
	_, err := c.Query(query)
	return err
}

// RedirectLogs send the logaddress_add command
func (c *TF2RconConnection) RedirectLogs(ip string, port string) error {
	query := "logaddress_add " + ip + ":" + port
	_, err := c.Query(query)
	return err
}

// Close closes the connection
func (c *TF2RconConnection) Close() {
	c.rc.Close()
}

// ExecConfig accepts a string and executes its lines one by one. Assumes
// UNiX line endings
func (c *TF2RconConnection) ExecConfig(config string) error {
	lines := strings.Split(config, "\n")
	for _, line := range lines {
		_, err := c.Query(line)
		if err != nil {
			return err
		}
	}
	return nil
}

// NewTF2RconConnection builds a new TF2RconConnection to a server at address ("ip:port") using
// a rcon_password password
func NewTF2RconConnection(address, password string) (*TF2RconConnection, error) {
	rc, err := rcon.Dial(address, password)
	if err != nil {
		return nil, err
	}
	return &TF2RconConnection{rc, address}, nil
}
<|endoftext|>


<commit_before>package fasthttp

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"math"
	"net"
	"sync"
	"time"
	"unsafe"
)

// AppendIPv4 appends string representation of the given ip v4 to dst
// and returns the extended dst.
func AppendIPv4(dst []byte, ip net.IP) []byte {
	ip = ip.To4()
	if ip == nil {
		return append(dst, "non-v4 ip passed to AppendIPv4"...)
	}

	dst = AppendUint(dst, int(ip[0]))
	for i := 1; i < 4; i++ {
		dst = append(dst, '.')
		dst = AppendUint(dst, int(ip[i]))
	}
	return dst
}

// ParseIPv4 parses ip address from ipStr into dst and returns the extended dst.
func ParseIPv4(dst net.IP, ipStr []byte) (net.IP, error) {
	if len(dst) < net.IPv4len {
		dst = make([]byte, net.IPv4len)
	}
	copy(dst, net.IPv4zero)
	dst = dst.To4()
	if dst == nil {
		panic("BUG: dst must not be nil")
	}

	b := ipStr
	for i := 0; i < 3; i++ {
		n := bytes.IndexByte(b, '.')
		if n < 0 {
			return dst, fmt.Errorf("cannot find dot in ipStr %q", ipStr)
		}
		v, err := ParseUint(b[:n])
		if err != nil {
			return dst, fmt.Errorf("cannot parse ipStr %q: %s", ipStr, err)
		}
		if v > 255 {
			return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v)
		}
		dst[i] = byte(v)
		b = b[n+1:]
	}
	v, err := ParseUint(b)
	if err != nil {
		return dst, fmt.Errorf("cannot parse ipStr %q: %s", ipStr, err)
	}
	if v > 255 {
		return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v)
	}
	dst[3] = byte(v)

	return dst, nil
}

// AppendHTTPDate appends HTTP-compliant (RFC1123) representation of date
// to dst and returns the extended dst.
func AppendHTTPDate(dst []byte, date time.Time) []byte {
	dst = date.In(time.UTC).AppendFormat(dst, time.RFC1123)
	copy(dst[len(dst)-3:], strGMT)
	return dst
}

// ParseHTTPDate parses HTTP-compliant (RFC1123) date.
func ParseHTTPDate(date []byte) (time.Time, error) {
	return time.Parse(time.RFC1123, unsafeBytesToStr(date))
}

// AppendUint appends n to dst and returns the extended dst.
func AppendUint(dst []byte, n int) []byte {
	if n < 0 {
		panic("BUG: int must be positive")
	}

	var b [20]byte
	buf := b[:]
	i := len(buf)
	var q int
	for n >= 10 {
		i--
		q = n / 10
		buf[i] = '0' + byte(n-q*10)
		n = q
	}
	i--
	buf[i] = '0' + byte(n)

	dst = append(dst, buf[i:]...)
	return dst
}

// ParseUint parses uint from buf.
func ParseUint(buf []byte) (int, error) {
	v, n, err := parseUintBuf(buf)
	if n != len(buf) {
		return -1, fmt.Errorf("only %b bytes out of %d bytes exhausted when parsing int %q", n, len(buf), buf)
	}
	return v, err
}

func parseUintBuf(b []byte) (int, int, error) {
	n := len(b)
	if n == 0 {
		return -1, 0, fmt.Errorf("empty integer")
	}
	v := 0
	for i := 0; i < n; i++ {
		c := b[i]
		k := c - '0'
		if k > 9 {
			if i == 0 {
				return -1, i, fmt.Errorf("unexpected first char %c. Expected 0-9", c)
			}
			return v, i, nil
		}
		if i >= maxIntChars {
			return -1, i, fmt.Errorf("too long int %q", b[:i+1])
		}
		v = 10*v + int(k)
	}
	return v, n, nil
}

// ParseUfloat parses unsigned float from buf.
func ParseUfloat(buf []byte) (float64, error) {
	if len(buf) == 0 {
		return -1, fmt.Errorf("empty float number")
	}
	b := buf
	var v uint64
	var offset float64 = 1.0
	var pointFound bool
	for i, c := range b {
		if c < '0' || c > '9' {
			if c == '.' {
				if pointFound {
					return -1, fmt.Errorf("duplicate point found in %q", buf)
				}
				pointFound = true
				continue
			}
			if c == 'e' || c == 'E' {
				if i+1 >= len(b) {
					return -1, fmt.Errorf("unexpected end of float after %c. num=%q", c, buf)
				}
				b = b[i+1:]
				minus := -1
				switch b[0] {
				case '+':
					b = b[1:]
					minus = 1
				case '-':
					b = b[1:]
				default:
					minus = 1
				}
				vv, err := ParseUint(b)
				if err != nil {
					return -1, fmt.Errorf("cannot parse exponent part of %q: %s", buf, err)
				}
				return float64(v) * offset * math.Pow10(minus*int(vv)), nil
			}
			return -1, fmt.Errorf("unexpected char found %c in %q", c, buf)
		}
		v = 10*v + uint64(c-'0')
		if pointFound {
			offset /= 10
		}
	}
	return float64(v) * offset, nil
}

func readHexInt(r *bufio.Reader) (int, error) {
	n := 0
	i := 0
	var k int
	for {
		c, err := r.ReadByte()
		if err != nil {
			if err == io.EOF && i > 0 {
				return n, nil
			}
			return -1, err
		}
		k = hexbyte2int(c)
		if k < 0 {
			if i == 0 {
				return -1, fmt.Errorf("cannot read hex num from empty string")
			}
			r.UnreadByte()
			return n, nil
		}
		if i >= maxHexIntChars {
			return -1, fmt.Errorf("cannot read hex num with more than %d digits", maxHexIntChars)
		}
		n = (n << 4) | k
		i++
	}
}

var hexIntBufPool sync.Pool

func writeHexInt(w *bufio.Writer, n int) error {
	if n < 0 {
		panic("BUG: int must be positive")
	}

	v := hexIntBufPool.Get()
	if v == nil {
		v = make([]byte, maxHexIntChars+1)
	}
	buf := v.([]byte)
	i := len(buf) - 1
	for {
		buf[i] = int2hexbyte(n & 0xf)
		n >>= 4
		if n == 0 {
			break
		}
		i--
	}
	_, err := w.Write(buf[i:])
	hexIntBufPool.Put(v)
	return err
}

func int2hexbyte(n int) byte {
	if n < 10 {
		return '0' + byte(n)
	}
	return 'a' + byte(n) - 10
}

func hexCharUpper(c byte) byte {
	if c < 10 {
		return '0' + c
	}
	return c - 10 + 'A'
}

var hex2intTable = func() []byte {
	b := make([]byte, 255)
	for i := byte(0); i < 255; i++ {
		c := byte(0)
		if i >= '0' && i <= '9' {
			c = 1 + i - '0'
		} else if i >= 'a' && i <= 'f' {
			c = 1 + i - 'a' + 10
		} else if i >= 'A' && i <= 'F' {
			c = 1 + i - 'A' + 10
		}
		b[i] = c
	}
	return b
}()

func hexbyte2int(c byte) int {
	return int(hex2intTable[c]) - 1
}

const toLower = 'a' - 'A'

func uppercaseByte(p *byte) {
	c := *p
	if c >= 'a' && c <= 'z' {
		*p = c - toLower
	}
}

func lowercaseByte(p *byte) {
	c := *p
	if c >= 'A' && c <= 'Z' {
		*p = c + toLower
	}
}

func lowercaseBytes(b []byte) {
	for i, n := 0, len(b); i < n; i++ {
		lowercaseByte(&b[i])
	}
}

// unsafeBytesToStr converts byte slice to a string without memory allocation.
// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
//
// Note it may break if string and/or slice header will change
// in the future go versions.
func unsafeBytesToStr(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

func appendQuotedArg(dst, v []byte) []byte {
	for _, c := range v {
		// See http://www.w3.org/TR/html5/forms.html#form-submission-algorithm
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
			c == '*' || c == '-' || c == '.' || c == '_' {
			dst = append(dst, c)
		} else {
			dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
		}
	}
	return dst
}

func appendQuotedPath(dst, v []byte) []byte {
	for _, c := range v {
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
			c == '/' || c == '.' || c == ',' || c == '=' || c == ':' || c == '&' || c == '~' || c == '-' || c == '_' {
			dst = append(dst, c)
		} else {
			dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
		}
	}
	return dst
}

// EqualBytesStr returns true if string(b) == s.
//
// This function has no performance benefits comparing to string(b) == s.
// It is left here for backwards compatibility only.
//
// This function is deperecated and may be deleted soon.
func EqualBytesStr(b []byte, s string) bool {
	return string(b) == s
}

// AppendBytesStr appends src to dst and returns the extended dst.
//
// This function has no performance benefits comparing to append(dst, src...).
// It is left here for backwards compatibility only.
//
// This function is deprecated and may be deleted soon.
func AppendBytesStr(dst []byte, src string) []byte {
	return append(dst, src...)
}
<commit_msg>typo fix<commit_after>package fasthttp

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"math"
	"net"
	"sync"
	"time"
	"unsafe"
)

// AppendIPv4 appends string representation of the given ip v4 to dst
// and returns the extended dst.
func AppendIPv4(dst []byte, ip net.IP) []byte {
	ip = ip.To4()
	if ip == nil {
		return append(dst, "non-v4 ip passed to AppendIPv4"...)
	}

	dst = AppendUint(dst, int(ip[0]))
	for i := 1; i < 4; i++ {
		dst = append(dst, '.')
		dst = AppendUint(dst, int(ip[i]))
	}
	return dst
}

// ParseIPv4 parses ip address from ipStr into dst and returns the extended dst.
func ParseIPv4(dst net.IP, ipStr []byte) (net.IP, error) {
	if len(dst) < net.IPv4len {
		dst = make([]byte, net.IPv4len)
	}
	copy(dst, net.IPv4zero)
	dst = dst.To4()
	if dst == nil {
		panic("BUG: dst must not be nil")
	}

	b := ipStr
	for i := 0; i < 3; i++ {
		n := bytes.IndexByte(b, '.')
		if n < 0 {
			return dst, fmt.Errorf("cannot find dot in ipStr %q", ipStr)
		}
		v, err := ParseUint(b[:n])
		if err != nil {
			return dst, fmt.Errorf("cannot parse ipStr %q: %s", ipStr, err)
		}
		if v > 255 {
			return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v)
		}
		dst[i] = byte(v)
		b = b[n+1:]
	}
	v, err := ParseUint(b)
	if err != nil {
		return dst, fmt.Errorf("cannot parse ipStr %q: %s", ipStr, err)
	}
	if v > 255 {
		return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v)
	}
	dst[3] = byte(v)

	return dst, nil
}

// AppendHTTPDate appends HTTP-compliant (RFC1123) representation of date
// to dst and returns the extended dst.
func AppendHTTPDate(dst []byte, date time.Time) []byte {
	dst = date.In(time.UTC).AppendFormat(dst, time.RFC1123)
	copy(dst[len(dst)-3:], strGMT)
	return dst
}

// ParseHTTPDate parses HTTP-compliant (RFC1123) date.
func ParseHTTPDate(date []byte) (time.Time, error) {
	return time.Parse(time.RFC1123, unsafeBytesToStr(date))
}

// AppendUint appends n to dst and returns the extended dst.
func AppendUint(dst []byte, n int) []byte {
	if n < 0 {
		panic("BUG: int must be positive")
	}

	var b [20]byte
	buf := b[:]
	i := len(buf)
	var q int
	for n >= 10 {
		i--
		q = n / 10
		buf[i] = '0' + byte(n-q*10)
		n = q
	}
	i--
	buf[i] = '0' + byte(n)

	dst = append(dst, buf[i:]...)
	return dst
}

// ParseUint parses uint from buf.
func ParseUint(buf []byte) (int, error) {
	v, n, err := parseUintBuf(buf)
	if n != len(buf) {
		return -1, fmt.Errorf("only %d bytes out of %d bytes exhausted when parsing int %q", n, len(buf), buf)
	}
	return v, err
}

func parseUintBuf(b []byte) (int, int, error) {
	n := len(b)
	if n == 0 {
		return -1, 0, fmt.Errorf("empty integer")
	}
	v := 0
	for i := 0; i < n; i++ {
		c := b[i]
		k := c - '0'
		if k > 9 {
			if i == 0 {
				return -1, i, fmt.Errorf("unexpected first char %c. Expected 0-9", c)
			}
			return v, i, nil
		}
		if i >= maxIntChars {
			return -1, i, fmt.Errorf("too long int %q", b[:i+1])
		}
		v = 10*v + int(k)
	}
	return v, n, nil
}

// ParseUfloat parses unsigned float from buf.
func ParseUfloat(buf []byte) (float64, error) {
	if len(buf) == 0 {
		return -1, fmt.Errorf("empty float number")
	}
	b := buf
	var v uint64
	var offset float64 = 1.0
	var pointFound bool
	for i, c := range b {
		if c < '0' || c > '9' {
			if c == '.' {
				if pointFound {
					return -1, fmt.Errorf("duplicate point found in %q", buf)
				}
				pointFound = true
				continue
			}
			if c == 'e' || c == 'E' {
				if i+1 >= len(b) {
					return -1, fmt.Errorf("unexpected end of float after %c. num=%q", c, buf)
				}
				b = b[i+1:]
				minus := -1
				switch b[0] {
				case '+':
					b = b[1:]
					minus = 1
				case '-':
					b = b[1:]
				default:
					minus = 1
				}
				vv, err := ParseUint(b)
				if err != nil {
					return -1, fmt.Errorf("cannot parse exponent part of %q: %s", buf, err)
				}
				return float64(v) * offset * math.Pow10(minus*int(vv)), nil
			}
			return -1, fmt.Errorf("unexpected char found %c in %q", c, buf)
		}
		v = 10*v + uint64(c-'0')
		if pointFound {
			offset /= 10
		}
	}
	return float64(v) * offset, nil
}

func readHexInt(r *bufio.Reader) (int, error) {
	n := 0
	i := 0
	var k int
	for {
		c, err := r.ReadByte()
		if err != nil {
			if err == io.EOF && i > 0 {
				return n, nil
			}
			return -1, err
		}
		k = hexbyte2int(c)
		if k < 0 {
			if i == 0 {
				return -1, fmt.Errorf("cannot read hex num from empty string")
			}
			r.UnreadByte()
			return n, nil
		}
		if i >= maxHexIntChars {
			return -1, fmt.Errorf("cannot read hex num with more than %d digits", maxHexIntChars)
		}
		n = (n << 4) | k
		i++
	}
}

var hexIntBufPool sync.Pool

func writeHexInt(w *bufio.Writer, n int) error {
	if n < 0 {
		panic("BUG: int must be positive")
	}

	v := hexIntBufPool.Get()
	if v == nil {
		v = make([]byte, maxHexIntChars+1)
	}
	buf := v.([]byte)
	i := len(buf) - 1
	for {
		buf[i] = int2hexbyte(n & 0xf)
		n >>= 4
		if n == 0 {
			break
		}
		i--
	}
	_, err := w.Write(buf[i:])
	hexIntBufPool.Put(v)
	return err
}

func int2hexbyte(n int) byte {
	if n < 10 {
		return '0' + byte(n)
	}
	return 'a' + byte(n) - 10
}

func hexCharUpper(c byte) byte {
	if c < 10 {
		return '0' + c
	}
	return c - 10 + 'A'
}

var hex2intTable = func() []byte {
	b := make([]byte, 255)
	for i := byte(0); i < 255; i++ {
		c := byte(0)
		if i >= '0' && i <= '9' {
			c = 1 + i - '0'
		} else if i >= 'a' && i <= 'f' {
			c = 1 + i - 'a' + 10
		} else if i >= 'A' && i <= 'F' {
			c = 1 + i - 'A' + 10
		}
		b[i] = c
	}
	return b
}()

func hexbyte2int(c byte) int {
	return int(hex2intTable[c]) - 1
}

const toLower = 'a' - 'A'

func uppercaseByte(p *byte) {
	c := *p
	if c >= 'a' && c <= 'z' {
		*p = c - toLower
	}
}

func lowercaseByte(p *byte) {
	c := *p
	if c >= 'A' && c <= 'Z' {
		*p = c + toLower
	}
}

func lowercaseBytes(b []byte) {
	for i, n := 0, len(b); i < n; i++ {
		lowercaseByte(&b[i])
	}
}

// unsafeBytesToStr converts byte slice to a string without memory allocation.
// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
//
// Note it may break if string and/or slice header will change
// in the future go versions.
func unsafeBytesToStr(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

func appendQuotedArg(dst, v []byte) []byte {
	for _, c := range v {
		// See http://www.w3.org/TR/html5/forms.html#form-submission-algorithm
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
			c == '*' || c == '-' || c == '.' || c == '_' {
			dst = append(dst, c)
		} else {
			dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
		}
	}
	return dst
}

func appendQuotedPath(dst, v []byte) []byte {
	for _, c := range v {
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
			c == '/' || c == '.' || c == ',' || c == '=' || c == ':' || c == '&' || c == '~' || c == '-' || c == '_' {
			dst = append(dst, c)
		} else {
			dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
		}
	}
	return dst
}

// EqualBytesStr returns true if string(b) == s.
//
// This function has no performance benefits comparing to string(b) == s.
// It is left here for backwards compatibility only.
//
// This function is deperecated and may be deleted soon.
func EqualBytesStr(b []byte, s string) bool {
	return string(b) == s
}

// AppendBytesStr appends src to dst and returns the extended dst.
//
// This function has no performance benefits comparing to append(dst, src...).
// It is left here for backwards compatibility only.
//
// This function is deprecated and may be deleted soon.
func AppendBytesStr(dst []byte, src string) []byte {
	return append(dst, src...)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os/exec"
	"strings"

	"github.com/go-check/check"
)

func (s *DockerSuite) TestClientSetsTLSServerName(c *check.C) {
	// there may be more than one hit to the server for each registry request
	serverNameReceived := []string{}
	var serverName string

	virtualHostServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		serverNameReceived = append(serverNameReceived, r.TLS.ServerName)
	}))
	defer virtualHostServer.Close()
	// discard TLS handshake errors written by default to os.Stderr
	virtualHostServer.Config.ErrorLog = log.New(ioutil.Discard, "", 0)

	u, err := url.Parse(virtualHostServer.URL)
	c.Assert(err, check.IsNil)
	hostPort := u.Host
	serverName = strings.Split(hostPort, ":")[0]

	repoName := fmt.Sprintf("%v/dockercli/image:latest", hostPort)
	cmd := exec.Command(dockerBinary, "pull", repoName)
	cmd.Run()

	// check that the fake server was hit at least once
	c.Assert(len(serverNameReceived) > 0, check.Equals, true)
	// check that for each hit the right server name was received
	for _, item := range serverNameReceived {
		c.Check(item, check.Equals, serverName)
	}
}
<commit_msg>Disable flakey TestClientSetsTLSServerName<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os/exec"
	"strings"

	"github.com/go-check/check"
)

func (s *DockerSuite) TestClientSetsTLSServerName(c *check.C) {
	c.Skip("Flakey test")
	// there may be more than one hit to the server for each registry request
	serverNameReceived := []string{}
	var serverName string

	virtualHostServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		serverNameReceived = append(serverNameReceived, r.TLS.ServerName)
	}))
	defer virtualHostServer.Close()
	// discard TLS handshake errors written by default to os.Stderr
	virtualHostServer.Config.ErrorLog = log.New(ioutil.Discard, "", 0)

	u, err := url.Parse(virtualHostServer.URL)
	c.Assert(err, check.IsNil)
	hostPort := u.Host
	serverName = strings.Split(hostPort, ":")[0]

	repoName := fmt.Sprintf("%v/dockercli/image:latest", hostPort)
	cmd := exec.Command(dockerBinary, "pull", repoName)
	cmd.Run()

	// check that the fake server was hit at least once
	c.Assert(len(serverNameReceived) > 0, check.Equals, true)
	// check that for each hit the right server name was received
	for _, item := range serverNameReceived {
		c.Check(item, check.Equals, serverName)
	}
}
<|endoftext|>


<commit_before>package redisence

import (
	"errors"
	"fmt"
	"testing"
	"time"
)

func initRedisence(t *testing.T) *Session {
	ses, err := New("localhost:6379", 10, time.Second*1)
	if err != nil {
		t.Fatal(err)
	}
	conn := ses.redis.Pool().Get()
	conn.Do("CONFIG", "SET", "notify-keyspace-events Ex$")
	if err := conn.Close(); err != nil {
		t.Fatal(err)
	}

	return ses
}

func TestInitialization(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()
}

func TestSinglePing(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiPing(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id", "id2"); err != nil {
		t.Fatal(err)
	}
}

func TestOnlineStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "id3"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}

	status, err := s.Status(id)
	if err != nil {
		t.Fatal(err)
	}

	if status.Status != Online {
		t.Fatal(errors.New("User should be active"))
	}
}

func TestOfflineStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "id4"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}

	status, err := s.Status("id5")
	if err != nil {
		t.Fatal(err)
	}

	if status.Status != Offline {
		t.Fatal(errors.New("User should be offline"))
	}
}

func TestMultiStatusAllOnline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id6", "id7"); err != nil {
		t.Fatal(err)
	}

	status, err := s.MultipleStatus([]string{"id6", "id7"})
	if err != nil {
		t.Fatal(err)
	}
	for _, st := range status {
		if st.Status != Online {
			t.Fatal(errors.New("User should be active"))
		}
	}
}

func TestMultiStatusAllOffline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id8", "id9"); err != nil {
		t.Fatal(err)
	}

	status, err := s.MultipleStatus([]string{"id10", "id11"})
	if err != nil {
		t.Fatal(err)
	}

	for _, st := range status {
		if st.Status != Offline {
			t.Fatal(errors.New("User should be offline"))
		}
	}
}

func TestStatusWithTimeout(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "12"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}
	time.Sleep(time.Second * 1)
	status, err := s.Status(id)
	if err != nil {
		t.Fatal(err)
	}
	if status.Status == Online {
		t.Fatal(errors.New("User should not be active"))
	}
}

func TestSubscriptions(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	// wait for all keys to expire
	time.Sleep(time.Second * 1)

	events := make(chan Event)

	id1 := "13"
	id2 := "14"
	id3 := "15"

	go s.ListenStatusChanges(events)

	time.AfterFunc(time.Second*5, func() {
		err := s.Close()
		if err != nil {
			t.Fatal(err)
		}
	})

	time.AfterFunc(time.Second*1, func() {
		err := s.Online(id1, id2, id3)
		if err != nil {
			t.Fatal(err)
		}
		// err = s.Offline(id1, id2, id3)
		// if err != nil {
		// 	t.Fatal(err)
		// }
	})

	onlineCount := 0
	offlineCount := 0
	closedCount := 0
	for event := range events {
		switch event.Status {
		case Online:
			onlineCount++
		case Offline:
			offlineCount++
		case Closed:
			closedCount++
			close(events)
			// return
		default:
		}
	}

	if onlineCount != 3 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("online count should be 3 it is %d", onlineCount),
			),
		)
	}

	if offlineCount != 3 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("offline count should be 3 it is %d", offlineCount),
			),
		)
	}

	if closedCount != 1 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("closedCount count should be 3 it is %d", closedCount),
			),
		)
	}

}

func TestJustMultiOffline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Offline("id16", "id17"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiOnlineAndOfflineTogether(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id18", "id19"); err != nil {
		t.Fatal(err)
	}
	if err := s.Offline("id18", "id19"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiOfflineWithMultiStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id20", "id21"); err != nil {
		t.Fatal(err)
	}
	if err := s.Offline("id20", "id21"); err != nil {
		t.Fatal(err)
	}
	status, err := s.MultipleStatus([]string{"id20", "id21"})
	if err != nil {
		t.Fatal(err)
	}

	for _, st := range status {
		if st.Status != Offline {
			t.Fatal(errors.New("User should be offline"))
		}
	}
}
<commit_msg>Redisence: skip test because travis' redis servers doesn't send notification information they are using 2.6x http://docs.travis-ci.com/user/ci-environment/, this feature needs alt least 2.8<commit_after>package redisence

import (
	"errors"
	"fmt"
	"testing"
	"time"
)

func initRedisence(t *testing.T) *Session {
	ses, err := New("localhost:6379", 10, time.Second*1)
	if err != nil {
		t.Fatal(err)
	}
	conn := ses.redis.Pool().Get()
	conn.Do("CONFIG", "SET", "notify-keyspace-events Ex$")
	if err := conn.Close(); err != nil {
		t.Fatal(err)
	}

	return ses
}

func TestInitialization(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()
}

func TestSinglePing(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiPing(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id", "id2"); err != nil {
		t.Fatal(err)
	}
}

func TestOnlineStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "id3"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}

	status, err := s.Status(id)
	if err != nil {
		t.Fatal(err)
	}

	if status.Status != Online {
		t.Fatal(errors.New("User should be active"))
	}
}

func TestOfflineStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "id4"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}

	status, err := s.Status("id5")
	if err != nil {
		t.Fatal(err)
	}

	if status.Status != Offline {
		t.Fatal(errors.New("User should be offline"))
	}
}

func TestMultiStatusAllOnline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id6", "id7"); err != nil {
		t.Fatal(err)
	}

	status, err := s.MultipleStatus([]string{"id6", "id7"})
	if err != nil {
		t.Fatal(err)
	}
	for _, st := range status {
		if st.Status != Online {
			t.Fatal(errors.New("User should be active"))
		}
	}
}

func TestMultiStatusAllOffline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id8", "id9"); err != nil {
		t.Fatal(err)
	}

	status, err := s.MultipleStatus([]string{"id10", "id11"})
	if err != nil {
		t.Fatal(err)
	}

	for _, st := range status {
		if st.Status != Offline {
			t.Fatal(errors.New("User should be offline"))
		}
	}
}

func TestStatusWithTimeout(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	id := "12"
	if err := s.Online(id); err != nil {
		t.Fatal(err)
	}
	time.Sleep(time.Second * 2)
	status, err := s.Status(id)
	if err != nil {
		t.Fatal(err)
	}
	if status.Status == Online {
		t.Fatal(errors.New("User should not be active"))
	}
}

func TestSubscriptions(t *testing.T) {
	t.Skip("Skipped to travis")
	s := initRedisence(t)
	defer s.Close()

	// wait for all keys to expire
	time.Sleep(time.Second * 1)

	events := make(chan Event)

	id1 := "13"
	id2 := "14"
	id3 := "15"

	go s.ListenStatusChanges(events)

	time.AfterFunc(time.Second*5, func() {
		err := s.Close()
		if err != nil {
			t.Fatal(err)
		}
	})

	time.AfterFunc(time.Second*1, func() {
		err := s.Online(id1, id2, id3)
		if err != nil {
			t.Fatal(err)
		}
		// err = s.Offline(id1, id2, id3)
		// if err != nil {
		// 	t.Fatal(err)
		// }
	})

	onlineCount := 0
	offlineCount := 0
	closedCount := 0
	for event := range events {
		switch event.Status {
		case Online:
			onlineCount++
		case Offline:
			offlineCount++
		case Closed:
			closedCount++
			close(events)
			// return
		default:
		}
	}

	if onlineCount != 3 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("online count should be 3 it is %d", onlineCount),
			),
		)
	}

	if offlineCount != 3 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("offline count should be 3 it is %d", offlineCount),
			),
		)
	}

	if closedCount != 1 {
		t.Fatal(
			errors.New(
				fmt.Sprintf("closedCount count should be 3 it is %d", closedCount),
			),
		)
	}

}

func TestJustMultiOffline(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Offline("id16", "id17"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiOnlineAndOfflineTogether(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id18", "id19"); err != nil {
		t.Fatal(err)
	}
	if err := s.Offline("id18", "id19"); err != nil {
		t.Fatal(err)
	}
}

func TestMultiOfflineWithMultiStatus(t *testing.T) {
	s := initRedisence(t)
	defer s.Close()

	if err := s.Online("id20", "id21"); err != nil {
		t.Fatal(err)
	}
	if err := s.Offline("id20", "id21"); err != nil {
		t.Fatal(err)
	}
	status, err := s.MultipleStatus([]string{"id20", "id21"})
	if err != nil {
		t.Fatal(err)
	}

	for _, st := range status {
		if st.Status != Offline {
			t.Fatal(errors.New("User should be offline"))
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program 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.
//
// This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

package tls

import (
	"strconv"
	"time"

	"github.com/minio/minio/internal/auth"
	"github.com/minio/minio/internal/config"
	"github.com/minio/pkg/env"
)

const (
	// EnvIdentityTLSEnabled is an environment variable that controls whether the X.509
	// TLS STS API is enabled. By default, if not set, it is enabled.
	EnvIdentityTLSEnabled = "MINIO_IDENTITY_TLS_ENABLE"

	// EnvIdentityTLSSkipVerify is an environment variable that controls whether
	// MinIO verifies the client certificate present by the client
	// when requesting temp. credentials.
	// By default, MinIO always verify the client certificate.
	//
	// The client certificate verification should only be skipped
	// when debugging or testing a setup since it allows arbitrary
	// clients to obtain temp. credentials with arbitrary policy
	// permissions - including admin permissions.
	EnvIdentityTLSSkipVerify = "MINIO_IDENTITY_TLS_SKIP_VERIFY"
)

// Config contains the STS TLS configuration for generating temp.
// credentials and mapping client certificates to S3 policies.
type Config struct {
	Enabled bool `json:"enabled"`

	// InsecureSkipVerify, if set to true, disables the client
	// certificate verification. It should only be set for
	// debugging or testing purposes.
	InsecureSkipVerify bool `json:"skip_verify"`
}

const (
	defaultExpiry time.Duration = 1 * time.Hour
	minExpiry     time.Duration = 15 * time.Minute
	maxExpiry     time.Duration = 365 * 24 * time.Hour
)

// GetExpiryDuration - return parsed expiry duration.
func (l Config) GetExpiryDuration(dsecs string) (time.Duration, error) {
	if dsecs == "" {
		return defaultExpiry, nil
	}

	d, err := strconv.Atoi(dsecs)
	if err != nil {
		return 0, auth.ErrInvalidDuration
	}

	dur := time.Duration(d) * time.Second

	if dur < minExpiry || dur > maxExpiry {
		return 0, auth.ErrInvalidDuration
	}
	return dur, nil
}

// Lookup returns a new Config by merging the given K/V config
// system with environment variables.
func Lookup(kvs config.KVS) (Config, error) {
	if err := config.CheckValidKeys(config.IdentityTLSSubSys, kvs, DefaultKVS); err != nil {
		return Config{}, err
	}
	insecureSkipVerify, err := config.ParseBool(env.Get(EnvIdentityTLSSkipVerify, kvs.Get(skipVerify)))
	if err != nil {
		return Config{}, err
	}
	enabled, err := config.ParseBool(env.Get(EnvIdentityTLSEnabled, ""))
	if err != nil {
		return Config{}, err
	}
	return Config{
		Enabled:            enabled,
		InsecureSkipVerify: insecureSkipVerify,
	}, nil
}

const (
	skipVerify = "skip_verify"
)

// DefaultKVS is the the default K/V config system for
// the STS TLS API.
var DefaultKVS = config.KVS{
	config.KV{
		Key:   skipVerify,
		Value: "off",
	},
}

// Help is the help and description for the STS API K/V configuration.
var Help = config.HelpKVS{
	config.HelpKV{
		Key:         skipVerify,
		Description: `trust client certificates without verification. Defaults to "off" (verify)`,
		Optional:    true,
		Type:        "on|off",
	},
}
<commit_msg>fix: ignore empty values while parsing tlsEnabled value<commit_after>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program 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.
//
// This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

package tls

import (
	"strconv"
	"time"

	"github.com/minio/minio/internal/auth"
	"github.com/minio/minio/internal/config"
	"github.com/minio/pkg/env"
)

const (
	// EnvIdentityTLSEnabled is an environment variable that controls whether the X.509
	// TLS STS API is enabled. By default, if not set, it is enabled.
	EnvIdentityTLSEnabled = "MINIO_IDENTITY_TLS_ENABLE"

	// EnvIdentityTLSSkipVerify is an environment variable that controls whether
	// MinIO verifies the client certificate present by the client
	// when requesting temp. credentials.
	// By default, MinIO always verify the client certificate.
	//
	// The client certificate verification should only be skipped
	// when debugging or testing a setup since it allows arbitrary
	// clients to obtain temp. credentials with arbitrary policy
	// permissions - including admin permissions.
	EnvIdentityTLSSkipVerify = "MINIO_IDENTITY_TLS_SKIP_VERIFY"
)

// Config contains the STS TLS configuration for generating temp.
// credentials and mapping client certificates to S3 policies.
type Config struct {
	Enabled bool `json:"enabled"`

	// InsecureSkipVerify, if set to true, disables the client
	// certificate verification. It should only be set for
	// debugging or testing purposes.
	InsecureSkipVerify bool `json:"skip_verify"`
}

const (
	defaultExpiry time.Duration = 1 * time.Hour
	minExpiry     time.Duration = 15 * time.Minute
	maxExpiry     time.Duration = 365 * 24 * time.Hour
)

// GetExpiryDuration - return parsed expiry duration.
func (l Config) GetExpiryDuration(dsecs string) (time.Duration, error) {
	if dsecs == "" {
		return defaultExpiry, nil
	}

	d, err := strconv.Atoi(dsecs)
	if err != nil {
		return 0, auth.ErrInvalidDuration
	}

	dur := time.Duration(d) * time.Second

	if dur < minExpiry || dur > maxExpiry {
		return 0, auth.ErrInvalidDuration
	}
	return dur, nil
}

// Lookup returns a new Config by merging the given K/V config
// system with environment variables.
func Lookup(kvs config.KVS) (Config, error) {
	if err := config.CheckValidKeys(config.IdentityTLSSubSys, kvs, DefaultKVS); err != nil {
		return Config{}, err
	}
	cfg := Config{}
	var err error
	v := env.Get(EnvIdentityTLSEnabled, "")
	if v == "" {
		return cfg, nil
	}
	cfg.Enabled, err = config.ParseBool(v)
	if err != nil {
		return Config{}, err
	}
	cfg.InsecureSkipVerify, err = config.ParseBool(env.Get(EnvIdentityTLSSkipVerify, kvs.Get(skipVerify)))
	if err != nil {
		return Config{}, err
	}
	return cfg, nil
}

const (
	skipVerify = "skip_verify"
)

// DefaultKVS is the the default K/V config system for
// the STS TLS API.
var DefaultKVS = config.KVS{
	config.KV{
		Key:   skipVerify,
		Value: "off",
	},
}

// Help is the help and description for the STS API K/V configuration.
var Help = config.HelpKVS{
	config.HelpKV{
		Key:         skipVerify,
		Description: `trust client certificates without verification. Defaults to "off" (verify)`,
		Optional:    true,
		Type:        "on|off",
	},
}
<|endoftext|>


<commit_before>package restorer

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

	"github.com/restic/restic/internal/crypto"
	"github.com/restic/restic/internal/restic"
	rtest "github.com/restic/restic/internal/test"
)

type TestBlob struct {
	data string
	pack string
}

type TestFile struct {
	name  string
	blobs []TestBlob
}

type TestRepo struct {
	key *crypto.Key

	// pack names and ids
	packsNameToID map[string]restic.ID
	packsIDToName map[restic.ID]string
	packsIDToData map[restic.ID][]byte

	// blobs and files
	blobs              map[restic.ID][]restic.PackedBlob
	files              []*fileInfo
	filesPathToContent map[string]string

	//
	loader func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error
}

func (i *TestRepo) Lookup(blobID restic.ID, _ restic.BlobType) []restic.PackedBlob {
	packs := i.blobs[blobID]
	return packs
}

func (i *TestRepo) packName(pack *packInfo) string {
	return i.packsIDToName[pack.id]
}

func (i *TestRepo) packID(name string) restic.ID {
	return i.packsNameToID[name]
}

func (i *TestRepo) fileContent(file *fileInfo) string {
	return i.filesPathToContent[file.location]
}

func newTestRepo(content []TestFile) *TestRepo {
	type Pack struct {
		name  string
		data  []byte
		blobs map[restic.ID]restic.Blob
	}
	packs := make(map[string]Pack)

	key := crypto.NewRandomKey()
	seal := func(data []byte) []byte {
		ciphertext := restic.NewBlobBuffer(len(data))
		ciphertext = ciphertext[:0] // truncate the slice
		nonce := crypto.NewRandomNonce()
		ciphertext = append(ciphertext, nonce...)
		return key.Seal(ciphertext, nonce, data, nil)
	}

	filesPathToContent := make(map[string]string)

	for _, file := range content {
		var content string
		for _, blob := range file.blobs {
			content += blob.data

			// get the pack, create as necessary
			var pack Pack
			var found bool
			if pack, found = packs[blob.pack]; !found {
				pack = Pack{name: blob.pack, blobs: make(map[restic.ID]restic.Blob)}
			}

			// calculate blob id and add to the pack as necessary
			blobID := restic.Hash([]byte(blob.data))
			if _, found := pack.blobs[blobID]; !found {
				blobData := seal([]byte(blob.data))
				pack.blobs[blobID] = restic.Blob{
					Type:   restic.DataBlob,
					ID:     blobID,
					Length: uint(len(blobData)),
					Offset: uint(len(pack.data)),
				}
				pack.data = append(pack.data, blobData...)
			}

			packs[blob.pack] = pack
		}
		filesPathToContent[file.name] = content
	}

	blobs := make(map[restic.ID][]restic.PackedBlob)
	packsIDToName := make(map[restic.ID]string)
	packsIDToData := make(map[restic.ID][]byte)
	packsNameToID := make(map[string]restic.ID)

	for _, pack := range packs {
		packID := restic.Hash(pack.data)
		packsIDToName[packID] = pack.name
		packsIDToData[packID] = pack.data
		packsNameToID[pack.name] = packID
		for blobID, blob := range pack.blobs {
			blobs[blobID] = append(blobs[blobID], restic.PackedBlob{Blob: blob, PackID: packID})
		}
	}

	var files []*fileInfo
	for _, file := range content {
		content := restic.IDs{}
		for _, blob := range file.blobs {
			content = append(content, restic.Hash([]byte(blob.data)))
		}
		files = append(files, &fileInfo{location: file.name, blobs: content})
	}

	repo := &TestRepo{
		key:                key,
		packsIDToName:      packsIDToName,
		packsIDToData:      packsIDToData,
		packsNameToID:      packsNameToID,
		blobs:              blobs,
		files:              files,
		filesPathToContent: filesPathToContent,
	}
	repo.loader = func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error {
		packID, err := restic.ParseID(h.Name)
		if err != nil {
			return err
		}
		rd := bytes.NewReader(repo.packsIDToData[packID][int(offset) : int(offset)+length])
		return fn(rd)
	}

	return repo
}

func restoreAndVerify(t *testing.T, tempdir string, content []TestFile) {
	repo := newTestRepo(content)

	r := newFileRestorer(tempdir, repo.loader, repo.key, repo.Lookup)
	r.files = repo.files

	err := r.restoreFiles(context.TODO())
	rtest.OK(t, err)

	for _, file := range repo.files {
		target := r.targetPath(file.location)
		data, err := ioutil.ReadFile(target)
		if err != nil {
			t.Errorf("unable to read file %v: %v", file.location, err)
			continue
		}

		content := repo.fileContent(file)
		if !bytes.Equal(data, []byte(content)) {
			t.Errorf("file %v has wrong content: want %q, got %q", file.location, content, data)
		}
	}
}

func TestFileRestorerBasic(t *testing.T) {
	tempdir, cleanup := rtest.TempDir(t)
	defer cleanup()

	restoreAndVerify(t, tempdir, []TestFile{
		TestFile{
			name: "file1",
			blobs: []TestBlob{
				TestBlob{"data1-1", "pack1-1"},
				TestBlob{"data1-2", "pack1-2"},
			},
		},
		TestFile{
			name: "file2",
			blobs: []TestBlob{
				TestBlob{"data2-1", "pack2-1"},
				TestBlob{"data2-2", "pack2-2"},
			},
		},
		TestFile{
			name: "file3",
			blobs: []TestBlob{
				// same blob multiple times
				TestBlob{"data3-1", "pack3-1"},
				TestBlob{"data3-1", "pack3-1"},
			},
		},
	})
}
<commit_msg>restorer: remove redundant type specification<commit_after>package restorer

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

	"github.com/restic/restic/internal/crypto"
	"github.com/restic/restic/internal/restic"
	rtest "github.com/restic/restic/internal/test"
)

type TestBlob struct {
	data string
	pack string
}

type TestFile struct {
	name  string
	blobs []TestBlob
}

type TestRepo struct {
	key *crypto.Key

	// pack names and ids
	packsNameToID map[string]restic.ID
	packsIDToName map[restic.ID]string
	packsIDToData map[restic.ID][]byte

	// blobs and files
	blobs              map[restic.ID][]restic.PackedBlob
	files              []*fileInfo
	filesPathToContent map[string]string

	//
	loader func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error
}

func (i *TestRepo) Lookup(blobID restic.ID, _ restic.BlobType) []restic.PackedBlob {
	packs := i.blobs[blobID]
	return packs
}

func (i *TestRepo) packName(pack *packInfo) string {
	return i.packsIDToName[pack.id]
}

func (i *TestRepo) packID(name string) restic.ID {
	return i.packsNameToID[name]
}

func (i *TestRepo) fileContent(file *fileInfo) string {
	return i.filesPathToContent[file.location]
}

func newTestRepo(content []TestFile) *TestRepo {
	type Pack struct {
		name  string
		data  []byte
		blobs map[restic.ID]restic.Blob
	}
	packs := make(map[string]Pack)

	key := crypto.NewRandomKey()
	seal := func(data []byte) []byte {
		ciphertext := restic.NewBlobBuffer(len(data))
		ciphertext = ciphertext[:0] // truncate the slice
		nonce := crypto.NewRandomNonce()
		ciphertext = append(ciphertext, nonce...)
		return key.Seal(ciphertext, nonce, data, nil)
	}

	filesPathToContent := make(map[string]string)

	for _, file := range content {
		var content string
		for _, blob := range file.blobs {
			content += blob.data

			// get the pack, create as necessary
			var pack Pack
			var found bool
			if pack, found = packs[blob.pack]; !found {
				pack = Pack{name: blob.pack, blobs: make(map[restic.ID]restic.Blob)}
			}

			// calculate blob id and add to the pack as necessary
			blobID := restic.Hash([]byte(blob.data))
			if _, found := pack.blobs[blobID]; !found {
				blobData := seal([]byte(blob.data))
				pack.blobs[blobID] = restic.Blob{
					Type:   restic.DataBlob,
					ID:     blobID,
					Length: uint(len(blobData)),
					Offset: uint(len(pack.data)),
				}
				pack.data = append(pack.data, blobData...)
			}

			packs[blob.pack] = pack
		}
		filesPathToContent[file.name] = content
	}

	blobs := make(map[restic.ID][]restic.PackedBlob)
	packsIDToName := make(map[restic.ID]string)
	packsIDToData := make(map[restic.ID][]byte)
	packsNameToID := make(map[string]restic.ID)

	for _, pack := range packs {
		packID := restic.Hash(pack.data)
		packsIDToName[packID] = pack.name
		packsIDToData[packID] = pack.data
		packsNameToID[pack.name] = packID
		for blobID, blob := range pack.blobs {
			blobs[blobID] = append(blobs[blobID], restic.PackedBlob{Blob: blob, PackID: packID})
		}
	}

	var files []*fileInfo
	for _, file := range content {
		content := restic.IDs{}
		for _, blob := range file.blobs {
			content = append(content, restic.Hash([]byte(blob.data)))
		}
		files = append(files, &fileInfo{location: file.name, blobs: content})
	}

	repo := &TestRepo{
		key:                key,
		packsIDToName:      packsIDToName,
		packsIDToData:      packsIDToData,
		packsNameToID:      packsNameToID,
		blobs:              blobs,
		files:              files,
		filesPathToContent: filesPathToContent,
	}
	repo.loader = func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error {
		packID, err := restic.ParseID(h.Name)
		if err != nil {
			return err
		}
		rd := bytes.NewReader(repo.packsIDToData[packID][int(offset) : int(offset)+length])
		return fn(rd)
	}

	return repo
}

func restoreAndVerify(t *testing.T, tempdir string, content []TestFile) {
	repo := newTestRepo(content)

	r := newFileRestorer(tempdir, repo.loader, repo.key, repo.Lookup)
	r.files = repo.files

	err := r.restoreFiles(context.TODO())
	rtest.OK(t, err)

	for _, file := range repo.files {
		target := r.targetPath(file.location)
		data, err := ioutil.ReadFile(target)
		if err != nil {
			t.Errorf("unable to read file %v: %v", file.location, err)
			continue
		}

		content := repo.fileContent(file)
		if !bytes.Equal(data, []byte(content)) {
			t.Errorf("file %v has wrong content: want %q, got %q", file.location, content, data)
		}
	}
}

func TestFileRestorerBasic(t *testing.T) {
	tempdir, cleanup := rtest.TempDir(t)
	defer cleanup()

	restoreAndVerify(t, tempdir, []TestFile{
		{
			name: "file1",
			blobs: []TestBlob{
				{"data1-1", "pack1-1"},
				{"data1-2", "pack1-2"},
			},
		},
		{
			name: "file2",
			blobs: []TestBlob{
				{"data2-1", "pack2-1"},
				{"data2-2", "pack2-2"},
			},
		},
		{
			name: "file3",
			blobs: []TestBlob{
				// same blob multiple times
				{"data3-1", "pack3-1"},
				{"data3-1", "pack3-1"},
			},
		},
	})
}
<|endoftext|>


<commit_before>package polynomial

import (
	"math"

	"github.com/ready-steady/adapt/grid/equidistant"
)

// Open is a basis in (0, 1)^n.
type Open struct {
	nd   uint
	grid equidistant.Open
}

// NewOpen creates a basis.
func NewOpen(dimensions, power uint) *Open {
	if power != 1 {
		panic("not implemented")
	}
	return &Open{
		nd:   dimensions,
		grid: *equidistant.NewOpen(1),
	}
}

// Compute evaluates a basis function.
func (self *Open) Compute(index []uint64, point []float64) float64 {
	return compute(index, point, self.nd, self.compute)
}

// Integrate computes the integral of a basis function.
func (self *Open) Integrate(index []uint64) float64 {
	return integrate(index, self.nd, self.integrate)
}

func (self *Open) compute(level, order uint64, x float64) float64 {
	if level == 0 {
		return 1.0
	}
	xi, h, count := self.grid.Node(level, order)
	switch order {
	case 0:
		if x >= 2.0*h {
			return 0.0
		}
		return 2.0 - x/h
	case count - 1:
		left := float64(count - 1)
		if x <= left*h {
			return 0.0
		}
		return x/h - left
	default:
		Δ := math.Abs(x - xi)
		if Δ >= h {
			return 0.0
		}
		return 1.0 - Δ/h
	}
}

func (self *Open) integrate(level, order uint64) float64 {
	if level == 0 {
		return 1.0
	}
	_, _, count := self.grid.Node(level, order)
	switch order {
	case 0, count - 1:
		return 2.0 / float64(count+1)
	default:
		return 1.0 / float64(count+1)
	}
}
<commit_msg>b/polynomial: make a cosmetic adjustment<commit_after>package polynomial

import (
	"math"

	"github.com/ready-steady/adapt/grid/equidistant"
)

// Open is a basis in (0, 1)^n.
type Open struct {
	nd   uint
	grid equidistant.Open
}

// NewOpen creates a basis.
func NewOpen(dimensions, power uint) *Open {
	if power != 1 {
		panic("not implemented")
	}
	return &Open{
		nd:   dimensions,
		grid: *equidistant.NewOpen(1),
	}
}

// Compute evaluates a basis function.
func (self *Open) Compute(index []uint64, point []float64) float64 {
	return compute(index, point, self.nd, self.compute)
}

// Integrate computes the integral of a basis function.
func (self *Open) Integrate(index []uint64) float64 {
	return integrate(index, self.nd, self.integrate)
}

func (self *Open) compute(level, order uint64, x float64) float64 {
	if level == 0 {
		return 1.0
	}
	xi, h, count := self.grid.Node(level, order)
	switch order {
	case 0:
		if x >= 2.0*h {
			return 0.0
		}
		return 2.0 - x/h
	case count - 1:
		left := float64(count - 1)
		if x <= left*h {
			return 0.0
		}
		return x/h - left
	default:
		Δ := math.Abs(x - xi)
		if Δ >= h {
			return 0.0
		}
		return 1.0 - Δ/h
	}
}

func (self *Open) integrate(level, order uint64) float64 {
	if level == 0 {
		return 1.0
	}
	_, h, count := self.grid.Node(level, order)
	switch order {
	case 0, count - 1:
		return 2.0 * h
	default:
		return 1.0 * h
	}
}
<|endoftext|>