<commit_before>package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {

	num := 16.0
	upperBound := 10.0

	// A case body breaks automatically, unless it ends with a fallthrough statement.
	// Switch cases evaluate cases from top to bottom, stopping when a case succeeds.

	// switch with no condition
	switch {
	case num < upperBound:
		fmt.Printf("%.2f < %.2f\n", num, upperBound)
	case num == upperBound:
		fmt.Printf("%.2f == %.2f\n", num, upperBound)
	default:
		fmt.Printf("%.2f > %.2f\n", num, upperBound)
	}

	// switch with condition and a statement
	// NOTE the scope of variable oe is limited to the switch block

	// seed the random number generator
	rand.Seed(int64(time.Now().Nanosecond()))
	// generate a random number between 1 and 100
	rnum := rand.Intn(100)

	switch oe := rnum % 2; oe {
	case 0:
		fmt.Printf("Number %d is even\n", rnum)
	case 1:
		fmt.Printf("Number %d is odd\n", rnum)
	}

	// cases can be composed of compound statements
	switch {
	case rnum%2 == 0 && rnum%4 == 0:
		fmt.Printf("The number %d is divisible by 2 and 4\n", rnum)
	case rnum%2 == 0 || rnum%4 == 0:
		fmt.Printf("The number is %d is not divisible by both 2 and 4\n", rnum)
	default:
		fmt.Printf("I do know what to do with %d\n", rnum)
	}

	// if want switch to continue evalution after the first match you
	// do so with fallthrough statement.
	// NOTE: you can not fallthrough the final case in switch
	switch {
	case rnum%2 == 0 && rnum%4 == 0:
		fmt.Printf("The number %d is divisible by 2 and 4\n", rnum)
		fallthrough
	case rnum%3 == 0:
		fmt.Printf("The number is %d is divisible by both 3\n", rnum)
		fallthrough
	default:
		fmt.Printf("I do know what to do with %d\n", rnum)
	}

	// A break statement can be used to terminate the switch early
	// Sometimes, though, it's necessary to break out of a surrounding loop,
	// not the switch, and in Go that can be accomplished by putting a label
	// on the loop and "breaking" to that label. This example shows both uses.
	// addtionally this example also shows that cases can evaluate multiple
	// values at once
LOOP:
	for i := 0; i < 10; i++ {
		switch i {
		case 0, 2, 4, 6, 8:
			fmt.Printf("Even number %d\n", i)
		case 3, 5, 7, 9:
			break LOOP
		default:
			fmt.Printf("What shall we do with %d\n", i)
		}
	}

}
<commit_msg>fix typo<commit_after>package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {

	num := 16.0
	upperBound := 10.0

	// A case body breaks automatically, unless it ends with a fallthrough statement.
	// Switch cases evaluate cases from top to bottom, stopping when a case succeeds.

	// switch with no condition
	switch {
	case num < upperBound:
		fmt.Printf("%.2f < %.2f\n", num, upperBound)
	case num == upperBound:
		fmt.Printf("%.2f == %.2f\n", num, upperBound)
	default:
		fmt.Printf("%.2f > %.2f\n", num, upperBound)
	}

	// switch with condition and a statement
	// NOTE the scope of variable oe is limited to the switch block

	// seed the random number generator
	rand.Seed(int64(time.Now().Nanosecond()))
	// generate a random number between 1 and 100
	rnum := rand.Intn(100)

	switch oe := rnum % 2; oe {
	case 0:
		fmt.Printf("Number %d is even\n", rnum)
	case 1:
		fmt.Printf("Number %d is odd\n", rnum)
	}

	// cases can be composed of compound statements
	switch {
	case rnum%2 == 0 && rnum%4 == 0:
		fmt.Printf("The number %d is divisible by 2 and 4\n", rnum)
	case rnum%2 == 0 || rnum%4 == 0:
		fmt.Printf("The number is %d is not divisible by both 2 and 4\n", rnum)
	default:
		fmt.Printf("I do know what to do with %d\n", rnum)
	}

	// if want switch to continue evalution after the first match you
	// do so with fallthrough statement.
	// NOTE: you can not fallthrough the final case in switch
	switch {
	case rnum%2 == 0 && rnum%4 == 0:
		fmt.Printf("The number %d is divisible by 2 and 4\n", rnum)
		fallthrough
	case rnum%3 == 0:
		fmt.Printf("The number is %d is divisible by 3\n", rnum)
		fallthrough
	default:
		fmt.Printf("I do know what to do with %d\n", rnum)
	}

	// A break statement can be used to terminate the switch early
	// Sometimes, though, it's necessary to break out of a surrounding loop,
	// not the switch, and in Go that can be accomplished by putting a label
	// on the loop and "breaking" to that label. This example shows both uses.
	// addtionally this example also shows that cases can evaluate multiple
	// values at once
LOOP:
	for i := 0; i < 10; i++ {
		switch i {
		case 0, 2, 4, 6, 8:
			fmt.Printf("Even number %d\n", i)
		case 3, 5, 7, 9:
			break LOOP
		default:
			fmt.Printf("What shall we do with %d\n", i)
		}
	}

}
<|endoftext|>


<commit_before>package elm

import (
	"github.com/prasmussen/glot-code-runner/cmd"
	"path/filepath"
)

func Run(files []string, stdin string) (string, string, error) {
	workDir := filepath.Dir(files[0])

	// Move bootstrap files into work dir
	stdout, stderr, err := cmd.RunBash(workDir, "mv -f /bootstrap/* .")
	if err != nil {
		return stdout, stderr, err
	}

	// Compile elm to javascript
	stdout, stderr, err = cmd.Run(workDir, "elm-make", files[0], "--output", "elm.js")
	if err != nil {
		return stdout, stderr, err
	}

	// Run javascript with node via app.js from bootstrap
	return cmd.RunStdin(workDir, stdin, "node", "app.js")
}
<commit_msg>Elm: cp files to workaround hardlink issue<commit_after>package elm

import (
	"github.com/prasmussen/glot-code-runner/cmd"
	"path/filepath"
)

func Run(files []string, stdin string) (string, string, error) {
	workDir := filepath.Dir(files[0])

	// Move bootstrap files into work dir
	stdout, stderr, err := cmd.RunBash(workDir, "cp -rf /bootstrap/* .")
	if err != nil {
		return stdout, stderr, err
	}

	// Compile elm to javascript
	stdout, stderr, err = cmd.Run(workDir, "elm-make", files[0], "--output", "elm.js")
	if err != nil {
		return stdout, stderr, err
	}

	// Run javascript with node via app.js from bootstrap
	return cmd.RunStdin(workDir, stdin, "node", "app.js")
}
<|endoftext|>


<commit_before>package password

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"net/http"
	"time"

	"github.com/boltdb/bolt"
	jwt "github.com/dgrijalva/jwt-go"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

var (
	// ErrInvalidSigningMethod is the error returned when a token's signature
	// does match the signature used to sign the token header.
	ErrInvalidSigningMethod = errors.New("Invalid signing method")
	// ErrTokenInvalid means the signature didn't match.
	ErrTokenInvalid = errors.New("Token isn't valid")

	signingKey = genRandBytes()

	//
	cost         = bcrypt.DefaultCost
	defaultStore = newDB()
)

// Authenticator is the interface that implements the methods for storing and
// retrieving passwords.
type Authenticator interface {
	Store(id string, secret string) string
	Retrieve(id string, secret string) string
}

// DefaultSore contains a reference to the default store for Password, and
// satiesfies the Authenticator interface.
type DefaultStore struct {
	DB         *bolt.DB
	BucketName string
	Bucket     *bolt.Bucket
}

func (s *DefaultStore) Store(id string, secret string) string {
	err := s.DB.Update(func(tx *bolt.Tx) error {

		return nil
	})
	if err != nil {
		// handle error
	}
	return ""
}

func (s *DefaultStore) Retrieve(id string, secret string) string {
	err := s.DB.View(func(tx *bolt.Tx) error {
		//
		return nil
	})
	if err != nil {
		// handle error
	}
	return "" // I should implement these
}

func newDB() *DefaultStore {
	db, err := bolt.Open("password.db", 0600, &bolt.Options{
		Timeout: 1 * time.Second,
	})
	if err != nil {
		panic(err)
	}

	var bucket *bolt.Bucket
	bucketName := "Users"
	db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte(bucketName))
		if err != nil {
			return err
		}
		bucket = b
		return nil
	})

	return &DefaultStore{
		DB:         db,
		Bucket:     bucket,
		BucketName: bucketName,
	}
}

// Hash hashes and salts a plaintext secret using bcrypt.
func Hash(id string, secret string) (string, error) {
	hashedSecret, err := bcrypt.GenerateFromPassword([]byte(secret), cost)
	if err != nil {
		return "", err // couldn't run bcrypt
	}
	return string(hashedSecret), nil
}

// Compare compares a hashed secret with a plaintext secret to see if they
// match. If they do, a JSON web token is generated with the given id.
func Compare(id string, secret string, hashedSecret string) (string, error) {
	err := bcrypt.CompareHashAndPassword([]byte(hashedSecret), []byte(secret))
	if err != nil {
		return "", err // passwords didn't match
	}
	return genToken(id)
}

// Authenticate runs `Compare`, and writes the generated JSON web token to the
// response writer.
func Authenticate(w http.ResponseWriter, id string, secret string, hashedSecret string) {
	tokStr, err := Compare(id, secret, hashedSecret)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(map[string]string{"token": tokStr})
}

// Protect is middleware that checks to see if the incoming request has a
// valid JSON web token. If it does, it executes the next `http.HandlerFunc`,
// and passes it a `context.Context` with the field "id" assigned to the
// current user id.
type Protect func(ctx context.Context, w http.ResponseWriter, r *http.Request)

func (fn Protect) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tok, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
		_, ok := token.Method.(*jwt.SigningMethodHMAC)
		if ok == false {
			return nil, ErrInvalidSigningMethod
		}
		return signingKey, nil
	})
	if err != nil {
		// might wanna use switch statement
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if tok.Valid != true {
		http.Error(w, ErrTokenInvalid.Error(), http.StatusUnauthorized)
	}

	id := tok.Claims["sub"]
	ctx := context.WithValue(context.Background(), "id", id)

	fn(ctx, w, r)
}

// SetSigningKey allows you to override the default HMAC signing key with one
// of your own. Every time this package is imported, a signing key is set
// randomly. That means that in between restarts, a new key is set, so you'd
// no longer be able to verify JSON web tokens created with that key. In order
// to reuse the signing key, you must set it yourself. Just call this function
// before creating any tokens, and you'll be good to go.
func SetSigningKey(key []byte) {
	signingKey = key
}

func genToken(id string) (string, error) {
	jwt := jwt.New(jwt.SigningMethodHS256)
	expTime := time.Now().Add(time.Hour * 72).Unix()

	jwt.Claims["sub"] = id
	jwt.Claims["exp"] = expTime
	jwt.Claims["iat"] = time.Now().Unix()

	tokStr, err := jwt.SignedString(signingKey)
	if err != nil {
		return "", err // failed to sign token
	}

	return tokStr, nil
}

func genRandBytes() []byte {
	// Use 32 bytes (256 bits) to satisfy the requirement for the HMAC key
	// length.
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		// If this errors, it means that something is wrong the system's
		// CSPRNG, which indicates a critical operating system failure. Panic
		// and crash here
		panic(err)
	}
	return []byte(base64.URLEncoding.EncodeToString(b))
}
<commit_msg>Fix warnings from lack of docs and spelling mistakes<commit_after>package password

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"net/http"
	"time"

	"github.com/boltdb/bolt"
	jwt "github.com/dgrijalva/jwt-go"
	"golang.org/x/crypto/bcrypt"
	"golang.org/x/net/context"
)

var (
	// ErrInvalidSigningMethod is the error returned when a token's signature
	// does match the signature used to sign the token header.
	ErrInvalidSigningMethod = errors.New("Invalid signing method")
	// ErrTokenInvalid means the signature didn't match.
	ErrTokenInvalid = errors.New("Token isn't valid")

	signingKey = genRandBytes()

	//
	cost         = bcrypt.DefaultCost
	defaultStore = newDB()
)

// Authenticator is the interface that implements the methods for storing and
// retrieving passwords.
type Authenticator interface {
	Store(id string, secret string) string
	Retrieve(id string, secret string) string
}

// DefaultStore contains a reference to the default store for Password, and
// satiesfies the Authenticator interface.
type DefaultStore struct {
	DB         *bolt.DB
	BucketName string
	Bucket     *bolt.Bucket
}

// Store stores the given id and secret in Bolt. It will hash the secret using
// bcrypt before storing it.
func (s *DefaultStore) Store(id string, secret string) string {
	err := s.DB.Update(func(tx *bolt.Tx) error {

		return nil
	})
	if err != nil {
		// handle error
	}
	return ""
}

// Retrieve retrieves the given id and secret from Bolt. It will compare the
// plaintext password with the hashed password.
func (s *DefaultStore) Retrieve(id string, secret string) string {
	err := s.DB.View(func(tx *bolt.Tx) error {
		//
		return nil
	})
	if err != nil {
		// handle error
	}
	return "" // I should implement these
}

func newDB() *DefaultStore {
	db, err := bolt.Open("password.db", 0600, &bolt.Options{
		Timeout: 1 * time.Second,
	})
	if err != nil {
		panic(err)
	}

	var bucket *bolt.Bucket
	bucketName := "Users"
	db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte(bucketName))
		if err != nil {
			return err
		}
		bucket = b
		return nil
	})

	return &DefaultStore{
		DB:         db,
		Bucket:     bucket,
		BucketName: bucketName,
	}
}

// Hash hashes and salts a plaintext secret using bcrypt.
func Hash(id string, secret string) (string, error) {
	hashedSecret, err := bcrypt.GenerateFromPassword([]byte(secret), cost)
	if err != nil {
		return "", err // couldn't run bcrypt
	}
	return string(hashedSecret), nil
}

// Compare compares a hashed secret with a plaintext secret to see if they
// match. If they do, a JSON web token is generated with the given id.
func Compare(id string, secret string, hashedSecret string) (string, error) {
	err := bcrypt.CompareHashAndPassword([]byte(hashedSecret), []byte(secret))
	if err != nil {
		return "", err // passwords didn't match
	}
	return genToken(id)
}

// Authenticate runs `Compare`, and writes the generated JSON web token to the
// response writer.
func Authenticate(w http.ResponseWriter, id string, secret string, hashedSecret string) {
	tokStr, err := Compare(id, secret, hashedSecret)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(map[string]string{"token": tokStr})
}

// Protect is middleware that checks to see if the incoming request has a
// valid JSON web token. If it does, it executes the next `http.HandlerFunc`,
// and passes it a `context.Context` with the field "id" assigned to the
// current user id.
type Protect func(ctx context.Context, w http.ResponseWriter, r *http.Request)

func (fn Protect) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tok, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
		_, ok := token.Method.(*jwt.SigningMethodHMAC)
		if ok == false {
			return nil, ErrInvalidSigningMethod
		}
		return signingKey, nil
	})
	if err != nil {
		// might wanna use switch statement
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if tok.Valid != true {
		http.Error(w, ErrTokenInvalid.Error(), http.StatusUnauthorized)
	}

	id := tok.Claims["sub"]
	ctx := context.WithValue(context.Background(), "id", id)

	fn(ctx, w, r)
}

// SetSigningKey allows you to override the default HMAC signing key with one
// of your own. Every time this package is imported, a signing key is set
// randomly. That means that in between restarts, a new key is set, so you'd
// no longer be able to verify JSON web tokens created with that key. In order
// to reuse the signing key, you must set it yourself. Just call this function
// before creating any tokens, and you'll be good to go.
func SetSigningKey(key []byte) {
	signingKey = key
}

func genToken(id string) (string, error) {
	jwt := jwt.New(jwt.SigningMethodHS256)
	expTime := time.Now().Add(time.Hour * 72).Unix()

	jwt.Claims["sub"] = id
	jwt.Claims["exp"] = expTime
	jwt.Claims["iat"] = time.Now().Unix()

	tokStr, err := jwt.SignedString(signingKey)
	if err != nil {
		return "", err // failed to sign token
	}

	return tokStr, nil
}

func genRandBytes() []byte {
	// Use 32 bytes (256 bits) to satisfy the requirement for the HMAC key
	// length.
	b := make([]byte, 32)
	_, err := rand.Read(b)
	if err != nil {
		// If this errors, it means that something is wrong the system's
		// CSPRNG, which indicates a critical operating system failure. Panic
		// and crash here
		panic(err)
	}
	return []byte(base64.URLEncoding.EncodeToString(b))
}
<|endoftext|>


<commit_before>package analyze

import (
	"math"
	"math/rand"

	"github.com/phil-mansfield/shellfish/math/sort"
)

type Shell func(phi, theta float64) float64

func randomAngle() (phi, theta float64) {
	u, v := rand.Float64(), rand.Float64()
	return 2 * math.Pi * u, math.Acos(2*v - 1)
}

func cartesian(phi, theta, r float64) (x, y, z float64) {
	sinP, cosP := math.Sincos(phi)
	sinT, cosT := math.Sincos(theta)
	return r * sinT * cosP, r * sinT * sinP, r * cosT
}

func (s Shell) CartesianSampledVolume(samples int, rMax float64) float64 {
	inside := 0
	for i := 0; i < samples; i++ {
		x := rand.Float64()*(2*rMax) - rMax
		y := rand.Float64()*(2*rMax) - rMax
		z := rand.Float64()*(2*rMax) - rMax

		r := math.Sqrt(x*x + y*y + z*z)
		phi := math.Atan2(y, x)
		th := math.Acos(z / r)

		rs := s(phi, th)
		if r < rs {
			inside++
		}
	}

	return float64(inside) / float64(samples) * (rMax * rMax * rMax * 8)
}

func (s Shell) Volume(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		sum += r * r * r
	}
	r3 := sum / float64(samples)
	return r3 * 4 * (math.Pi / 3)
}

func (s Shell) MeanRadius(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, th := randomAngle()
		r := s(phi, th)
		sum += r
	}
	return sum / float64(samples)
}

func (s Shell) MedianRadius(samples int) float64 {
	rs := make([]float64, samples)
	for i := range rs {
		phi, th := randomAngle()
		rs[i] = s(phi, th)
	}
	return sort.Median(rs, rs)
}

func (s Shell) Moments(samples int) (Ix, Iy, Iz float64) {
	xSum, ySum, zSum, rSum := 0.0, 0.0, 0.0, 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		x, y, z := cartesian(phi, theta, r)
		xSum += (y*y + z*z) * r * r
		ySum += (x*x + z*z) * r * r
		zSum += (x*x + y*y) * r * r
		rSum += r * r
	}
	return xSum / rSum, ySum / rSum, zSum / rSum
}

func (s Shell) SurfaceArea(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		sum += r * r
	}
	return sum / float64(samples) * 4 * math.Pi
}

func (s1 Shell) DiffVolume(s2 Shell, samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r1, r2 := s1(phi, theta), s2(phi, theta)
		r := (r1 + r2) / 2
		dr := math.Abs(r1 - r2)
		sum += dr * r * r
	}
	return sum / float64(samples) * (4 * math.Pi) / 3
}

func (s1 Shell) MaxDiff(s2 Shell, samples int) float64 {
	max := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r1, r2 := s1(phi, theta), s2(phi, theta)
		dr := math.Abs(r1 - r2)
		if dr > max {
			max = dr
		}
	}
	return max
}

func (s Shell) RadialRange(samples int) (low, high float64) {
	phi, theta := randomAngle()
	low = s(phi, theta)
	high = low
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		if r > high {
			high = r
		}
		if r < low {
			low = r
		}
	}
	return low, high
}

func  (s Shell) RadiusHistogram(
	samples, bins int, rMin, rMax float64,
) (rs, ns []float64) {
	rs, ns = make([]float64, bins), make([]float64, bins)
	dr := (rMax - rMin) / float64(bins)
	for i := range rs {
		rs[i] = rMin + dr*(float64(i) + 0.5)
	}

	count := 0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		ri := (r - rMin) / dr
		if ri < 0 { continue }
		idx := int(ri)
		if idx >= bins { continue }
		ns[idx]++
		count++
	}

	for i := range ns {
		ns[i] /= float64(count) * dr
	}

	return rs, ns
}

func (s Shell) Contains(x, y, z float64) bool {
	r := math.Sqrt(x*x + y*y + z*z)
	phi := math.Atan2(y, x)
	theta := math.Acos(z / r)
	return s(phi, theta) > r
}
<commit_msg>Wrote axis calculator for Shells.<commit_after>package analyze

import (
	"math"
	"math/rand"

	"github.com/phil-mansfield/shellfish/math/sort"
	"github.com/gonum/matrix/mat64"
)

type Shell func(phi, theta float64) float64

func randomAngle() (phi, theta float64) {
	u, v := rand.Float64(), rand.Float64()
	return 2 * math.Pi * u, math.Acos(2*v - 1)
}

func cartesian(phi, theta, r float64) (x, y, z float64) {
	sinP, cosP := math.Sincos(phi)
	sinT, cosT := math.Sincos(theta)
	return r * sinT * cosP, r * sinT * sinP, r * cosT
}

func (s Shell) CartesianSampledVolume(samples int, rMax float64) float64 {
	inside := 0
	for i := 0; i < samples; i++ {
		x := rand.Float64()*(2*rMax) - rMax
		y := rand.Float64()*(2*rMax) - rMax
		z := rand.Float64()*(2*rMax) - rMax

		r := math.Sqrt(x*x + y*y + z*z)
		phi := math.Atan2(y, x)
		th := math.Acos(z / r)

		rs := s(phi, th)
		if r < rs {
			inside++
		}
	}

	return float64(inside) / float64(samples) * (rMax * rMax * rMax * 8)
}

func (s Shell) Volume(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		sum += r * r * r
	}
	r3 := sum / float64(samples)
	return r3 * 4 * (math.Pi / 3)
}

func (s Shell) MeanRadius(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, th := randomAngle()
		r := s(phi, th)
		sum += r
	}
	return sum / float64(samples)
}

func (s Shell) MedianRadius(samples int) float64 {
	rs := make([]float64, samples)
	for i := range rs {
		phi, th := randomAngle()
		rs[i] = s(phi, th)
	}
	return sort.Median(rs, rs)
}

func trisort(x, y, z float64) (a, b, c float64) {
	var p, q float64
	switch {
	case x > y && x > z: a, p, q = x, y, z
	case y > x && y > z: a, p, q = y, z, x
	default: a, p, q = z, x, y
	}

	if p > q {
		return a, p, q
	} else {
		return a, q, p
	}
}

func (s Shell) Axes(samples int) (a, b, c float64) {
	nxx, nyy, nzz := 0.0, 0.0, 0.0
	nxy, nyz, nzx := 0.0, 0.0, 0.0
	norm := 0.0

	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		area := r*r
		x, y, z := cartesian(phi, theta, r)

		nxx, nyy, nzz = nxx + area*x*x, nyy + area*y*y, nzz + area*z*z
		nxy, nyz, nzx = nxy + area*x*y, nyz + area*y*z, nzx + area*z*x
		norm += area
	}

	nxx, nyy, nzz = nxx/norm, nyy/norm, nzz/norm
	nxy, nyz, nzx = nxy/norm, nyz/norm, nzx/norm

	mat := mat64.NewDense(3, 3, []float64{
		nxx, nxy, nzx,
		nxy, nyy, nyz,
		nzx, nyz, nzz,
	})
	out := &mat64.EigenSym{}
	mat.EigenvectorsSym(out)
	vals := out.Values(nil)
	Ixx, Iyy, Izz := vals[0], vals[1], vals[2]

	ax := math.Sqrt((Izz + Iyy - Ixx) * 2.5)
	az := math.Sqrt((Iyy - ax*ax) * 5)
	ay := math.Sqrt((Izz - ax*ax) * 5)
	return trisort(ax, ay, az)
}

func (s Shell) SurfaceArea(samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		sum += r*r
	}
	return sum / float64(samples) * 4 * math.Pi
}

func (s1 Shell) DiffVolume(s2 Shell, samples int) float64 {
	sum := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r1, r2 := s1(phi, theta), s2(phi, theta)
		r := (r1 + r2) / 2
		dr := math.Abs(r1 - r2)
		sum += dr * r * r
	}
	return sum / float64(samples) * (4 * math.Pi) / 3
}

func (s1 Shell) MaxDiff(s2 Shell, samples int) float64 {
	max := 0.0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r1, r2 := s1(phi, theta), s2(phi, theta)
		dr := math.Abs(r1 - r2)
		if dr > max {
			max = dr
		}
	}
	return max
}

func (s Shell) RadialRange(samples int) (low, high float64) {
	phi, theta := randomAngle()
	low = s(phi, theta)
	high = low
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		if r > high {
			high = r
		}
		if r < low {
			low = r
		}
	}
	return low, high
}

func  (s Shell) RadiusHistogram(
	samples, bins int, rMin, rMax float64,
) (rs, ns []float64) {
	rs, ns = make([]float64, bins), make([]float64, bins)
	dr := (rMax - rMin) / float64(bins)
	for i := range rs {
		rs[i] = rMin + dr*(float64(i) + 0.5)
	}

	count := 0
	for i := 0; i < samples; i++ {
		phi, theta := randomAngle()
		r := s(phi, theta)
		ri := (r - rMin) / dr
		if ri < 0 { continue }
		idx := int(ri)
		if idx >= bins { continue }
		ns[idx]++
		count++
	}

	for i := range ns {
		ns[i] /= float64(count) * dr
	}

	return rs, ns
}

func (s Shell) Contains(x, y, z float64) bool {
	r := math.Sqrt(x*x + y*y + z*z)
	phi := math.Atan2(y, x)
	theta := math.Acos(z / r)
	return s(phi, theta) > r
}
<|endoftext|>


<commit_before>// Copyright 2018 The Go Cloud Development Kit 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
//
//     https://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 cloudsql contains Wire providers that are common across Google Cloud
// SQL.
package cloudsql // import "gocloud.dev/gcp/cloudsql"

import (
	"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/certs"
	"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
	"github.com/google/wire"
	"gocloud.dev/gcp"
)

// CertSourceSet is a Wire provider set that binds a Cloud SQL proxy
// certificate source from an GCP-authenticated HTTP client.
var CertSourceSet = wire.NewSet(
	NewCertSource,
	wire.Bind(new(proxy.CertSource), new(*certs.RemoteCertSource)))

// NewCertSource creates a local certificate source that uses the given
// HTTP client. The client is assumed to make authenticated requests.
func NewCertSource(c *gcp.HTTPClient) *certs.RemoteCertSource {
	return certs.NewCertSourceOpts(&c.Client, certs.RemoteOpts{})
}
<commit_msg>gcp/cloudsql: enable IAM login (#3122)<commit_after>// Copyright 2018 The Go Cloud Development Kit 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
//
//     https://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 cloudsql contains Wire providers that are common across Google Cloud
// SQL.
package cloudsql // import "gocloud.dev/gcp/cloudsql"

import (
	"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/certs"
	"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/proxy"
	"github.com/google/wire"
	"gocloud.dev/gcp"
)

// CertSourceSet is a Wire provider set that binds a Cloud SQL proxy
// certificate source from an GCP-authenticated HTTP client.
var CertSourceSet = wire.NewSet(
	NewCertSource,
	wire.Bind(new(proxy.CertSource), new(*certs.RemoteCertSource)))

// NewCertSource creates a local certificate source that uses the given
// HTTP client. The client is assumed to make authenticated requests.
func NewCertSource(c *gcp.HTTPClient) *certs.RemoteCertSource {
	return certs.NewCertSourceOpts(&c.Client, certs.RemoteOpts{EnableIAMLogin: true})
}
<|endoftext|>


<commit_before>package ntp

import (
	"strings"
	"testing"
	"time"

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

const (
	host = "0.beevik-ntp.pool.ntp.org"
)

func isNil(t *testing.T, err error) bool {
	switch {
	case err == nil:
		return true
	case strings.Contains(err.Error(), "timeout"):
		t.Logf("[%s] Query timeout: %s", host, err)
		return false
	default:
		t.Errorf("[%s] Query failed: %s", host, err)
		return false
	}
}

func assertValid(t *testing.T, r *Response) {
	err := r.Validate()
	if err != nil {
		t.Errorf("[%s] Query invalid: %s\n", host, err)
	}
}

func assertInvalid(t *testing.T, r *Response) {
	err := r.Validate()
	assert.NotNil(t, err)
}

func TestTime(t *testing.T) {
	tm, err := Time(host)
	now := time.Now()
	if isNil(t, err) {
		t.Logf("Local Time %v\n", now)
		t.Logf("~True Time %v\n", tm)
		t.Logf("Offset %v\n", tm.Sub(now))
	}
}

func TestTimeFailure(t *testing.T) {
	// First use a link-local IP address that won't have an NTP
	// server listening on it. This should return the local system's time.
	local, err := Time("169.254.122.229")
	assert.NotNil(t, err)

	// Now use a valid NTP server IP address.
	remote, err := Time(host)
	assert.Nil(t, err)

	// The remote and local times should be approximately equal.
	diffMinutes := remote.Sub(local).Minutes()
	assert.True(t, diffMinutes > -15 && diffMinutes < 15)
}

func TestQuery(t *testing.T) {
	t.Logf("[%s] ----------------------", host)
	t.Logf("[%s] NTP protocol version %d", host, 4)

	r, err := QueryWithOptions(host, QueryOptions{Version: 4})
	if !isNil(t, err) {
		return
	}

	if r.Stratum >= 17 {
		t.Errorf("[%s] Invalid stratum: %d", host, r.Stratum)
	}

	if r.RTT < time.Duration(0) {
		t.Errorf("[%s] Negative round trip time: %v", host, r.RTT)
	}

	t.Logf("[%s]  LocalTime: %v", host, time.Now())
	t.Logf("[%s]   XmitTime: %v", host, r.Time)
	t.Logf("[%s]    RefTime: %v", host, r.ReferenceTime)
	t.Logf("[%s]        RTT: %v", host, r.RTT)
	t.Logf("[%s]     Offset: %v", host, r.ClockOffset)
	t.Logf("[%s] !Causality: %v", host, r.CausalityViolation)
	t.Logf("[%s]       Poll: %v", host, r.Poll)
	t.Logf("[%s]  Precision: %v", host, r.Precision)
	t.Logf("[%s]    Stratum: %v", host, r.Stratum)
	t.Logf("[%s]      RefID: 0x%08x", host, r.ReferenceID)
	t.Logf("[%s]  RootDelay: %v", host, r.RootDelay)
	t.Logf("[%s]   RootDisp: %v", host, r.RootDispersion)
	t.Logf("[%s]   RootDist: %v", host, r.RootDistance)
	t.Logf("[%s]       Leap: %v", host, r.Leap)

	assertValid(t, r)
}

func TestValidate(t *testing.T) {
	var m msg
	var r *Response
	m.Stratum = 1
	m.ReferenceID = 0x58585858 // `XXXX`
	m.ReferenceTime = 1 << 32

	m.OriginTime = 1 << 32
	m.ReceiveTime = 1 << 32
	m.TransmitTime = 1 << 32
	r = parseTime(&m, 1<<32)
	assertValid(t, r)

	m.ReferenceTime = 2 << 32 // negative freshness
	r = parseTime(&m, 1<<32)
	assertInvalid(t, r)

	m.OriginTime = 2 * 86400 << 32
	m.ReceiveTime = 2 * 86400 << 32
	m.TransmitTime = 2 * 86400 << 32
	r = parseTime(&m, 2*86400<<32) // 48h freshness
	assertInvalid(t, r)

	m.ReferenceTime = 1 * 86400 << 32 // 24h freshness
	r = parseTime(&m, 2*86400<<32)
	assertValid(t, r)

	m.RootDelay = 16 << 16
	m.ReferenceTime = 1 << 32
	m.OriginTime = 20 << 32
	m.ReceiveTime = 10 << 32
	m.TransmitTime = 15 << 32
	r = parseTime(&m, 22<<32)
	assert.NotNil(t, r)
	assertValid(t, r)
	assert.Equal(t, r.RTT, -3*time.Second)
	assert.Equal(t, r.RootDistance, 8*time.Second)
	assert.Equal(t, r.CausalityViolation, 10*time.Second)
}

func TestCausality(t *testing.T) {
	var m msg
	var r *Response

	m.Stratum = 1
	m.ReferenceID = 0x58585858 // `XXXX`
	m.ReferenceTime = 1 << 32

	m.OriginTime = 1 << 32
	m.ReceiveTime = 2 << 32
	m.TransmitTime = 3 << 32
	r = parseTime(&m, 4<<32)
	assertValid(t, r)
	assert.Equal(t, r.CausalityViolation, time.Duration(0))

	var t1, t2, t3, t4 int64
	for t1 = 1; t1 <= 10; t1++ {
		for t2 = 1; t2 <= 10; t2++ {
			for t3 = 1; t3 <= 10; t3++ {
				for t4 = 1; t4 <= 10; t4++ {
					m.OriginTime = ntpTime(t1 << 32)
					m.ReceiveTime = ntpTime(t2 << 32)
					m.TransmitTime = ntpTime(t3 << 32)
					r = parseTime(&m, ntpTime(t4<<32))
					if t1 <= t4 && t2 <= t3 { // anything else is invalid getTime() response
						assertValid(t, r) // negative RTT is still possible
						var d12, d34 int64
						if t1 >= t2 {
							d12 = t1 - t2
						}
						if t3 >= t4 {
							d34 = t3 - t4
						}
						var caserr int64
						if d12 > d34 {
							caserr = d12
						} else {
							caserr = d34
						}
						assert.Equal(t, r.CausalityViolation, time.Duration(caserr)*time.Second)
					}
				}
			}
		}
	}
}

func TestServerPort(t *testing.T) {
	tm, _, err := getTime(host, QueryOptions{Port: 9}) // `discard` service
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestTTL(t *testing.T) {
	// TTL should cause a timeout here:
	tm, _, err := getTime(host, QueryOptions{TTL: 1})
	assert.Nil(t, tm)
	assert.NotNil(t, err)

	// TTL should be large enough not to fail:
	tm, _, err = getTime(host, QueryOptions{TTL: 255})
	if isNil(t, err) {
		assert.NotNil(t, tm)
	}
}

func TestQueryTimeout(t *testing.T) {
	tm, err := QueryWithOptions(host, QueryOptions{Version: 4, Timeout: time.Nanosecond})
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestGetTimeTimeout(t *testing.T) {
	tm, _, err := getTime(host, QueryOptions{Version: 4, Timeout: time.Nanosecond})
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestTimeOrdering(t *testing.T) {
	tm, DestinationTime, err := getTime(host, QueryOptions{})
	if isNil(t, err) {
		assert.True(t, tm.OriginTime <= DestinationTime)  // local clock tick forward
		assert.True(t, tm.ReceiveTime <= tm.TransmitTime) // server clock tick forward
	}
}

func TestShortConversion(t *testing.T) {
	var ts ntpTimeShort

	ts = 0x00000000
	assert.Equal(t, 0*time.Nanosecond, ts.Duration())

	ts = 0x00000001
	assert.Equal(t, 15258*time.Nanosecond, ts.Duration()) // well, it's actually 15258.789, but it's good enough

	ts = 0x00008000
	assert.Equal(t, 500*time.Millisecond, ts.Duration()) // precise

	ts = 0x0000c000
	assert.Equal(t, 750*time.Millisecond, ts.Duration()) // precise

	ts = 0x0000ff80
	assert.Equal(t, time.Second-(1000000000/512)*time.Nanosecond, ts.Duration()) // last precise sub-second value

	ts = 0x00010000
	assert.Equal(t, 1000*time.Millisecond, ts.Duration()) // precise

	ts = 0x00018000
	assert.Equal(t, 1500*time.Millisecond, ts.Duration()) // precise

	ts = 0xffff0000
	assert.Equal(t, 65535*time.Second, ts.Duration()) // precise

	ts = 0xffffff80
	assert.Equal(t, 65536*time.Second-(1000000000/512)*time.Nanosecond, ts.Duration()) // last precise value
}

func TestLongConversion(t *testing.T) {
	ts := []ntpTime{0x0, 0xff800000, 0x1ff800000, 0x80000000ff800000, 0xffffffffff800000}

	for _, v := range ts {
		assert.Equal(t, v, toNtpTime(v.Time()))
	}
}

func abs(d time.Duration) time.Duration {
	switch {
	case int64(d) < 0:
		return -d
	default:
		return d
	}
}

func TestOffsetCalculation(t *testing.T) {
	now := time.Now()
	t1 := toNtpTime(now)
	t2 := toNtpTime(now.Add(20 * time.Second))
	t3 := toNtpTime(now.Add(21 * time.Second))
	t4 := toNtpTime(now.Add(5 * time.Second))

	// expectedOffset := ((T2 - T1) + (T3 - T4)) / 2
	// ((119 - 99) + (121 - 104)) / 2
	// (20 +  17) / 2
	// 37 / 2 = 18
	expectedOffset := 18 * time.Second
	offset := offset(t1, t2, t3, t4)
	assert.Equal(t, expectedOffset, offset)
}

func TestOffsetCalculationNegative(t *testing.T) {
	now := time.Now()
	t1 := toNtpTime(now.Add(101 * time.Second))
	t2 := toNtpTime(now.Add(102 * time.Second))
	t3 := toNtpTime(now.Add(103 * time.Second))
	t4 := toNtpTime(now.Add(105 * time.Second))

	// expectedOffset := ((T2 - T1) + (T3 - T4)) / 2
	// ((102 - 101) + (103 - 105)) / 2
	// (1 + -2) / 2 = -1 / 2
	expectedOffset := -time.Second / 2
	offset := offset(t1, t2, t3, t4)
	assert.Equal(t, expectedOffset, offset)
}
<commit_msg>Unit tests make fewer requests on the NTP server.<commit_after>package ntp

import (
	"strings"
	"testing"
	"time"

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

const (
	host = "0.beevik-ntp.pool.ntp.org"
)

func isNil(t *testing.T, err error) bool {
	switch {
	case err == nil:
		return true
	case strings.Contains(err.Error(), "timeout"):
		t.Logf("[%s] Query timeout: %s", host, err)
		return false
	default:
		t.Errorf("[%s] Query failed: %s", host, err)
		return false
	}
}

func assertValid(t *testing.T, r *Response) {
	err := r.Validate()
	if err != nil {
		t.Errorf("[%s] Query invalid: %s\n", host, err)
	}
}

func assertInvalid(t *testing.T, r *Response) {
	err := r.Validate()
	assert.NotNil(t, err)
}

func TestTime(t *testing.T) {
	tm, err := Time(host)
	now := time.Now()
	if isNil(t, err) {
		t.Logf("Local Time %v\n", now)
		t.Logf("~True Time %v\n", tm)
		t.Logf("Offset %v\n", tm.Sub(now))
	}
}

func TestTimeFailure(t *testing.T) {
	// Use a link-local IP address that won't have an NTP server listening
	// on it. This should return the local system's time.
	local, err := Time("169.254.122.229")
	assert.NotNil(t, err)

	now := time.Now()

	// When the NTP time query fails, it should return the system time.
	// Compare the "now" system time with the returned time. It should be
	// about the same.
	diffMinutes := now.Sub(local).Minutes()
	assert.True(t, diffMinutes > -1 && diffMinutes < 1)
}

func TestQuery(t *testing.T) {
	t.Logf("[%s] ----------------------", host)
	t.Logf("[%s] NTP protocol version %d", host, 4)

	r, err := QueryWithOptions(host, QueryOptions{Version: 4})
	if !isNil(t, err) {
		return
	}

	if r.Stratum > 16 {
		t.Errorf("[%s] Invalid stratum: %d", host, r.Stratum)
	}

	if r.RTT < time.Duration(0) {
		t.Errorf("[%s] Negative round trip time: %v", host, r.RTT)
	}

	t.Logf("[%s]  LocalTime: %v", host, time.Now())
	t.Logf("[%s]   XmitTime: %v", host, r.Time)
	t.Logf("[%s]    RefTime: %v", host, r.ReferenceTime)
	t.Logf("[%s]        RTT: %v", host, r.RTT)
	t.Logf("[%s]     Offset: %v", host, r.ClockOffset)
	t.Logf("[%s] !Causality: %v", host, r.CausalityViolation)
	t.Logf("[%s]       Poll: %v", host, r.Poll)
	t.Logf("[%s]  Precision: %v", host, r.Precision)
	t.Logf("[%s]    Stratum: %v", host, r.Stratum)
	t.Logf("[%s]      RefID: 0x%08x", host, r.ReferenceID)
	t.Logf("[%s]  RootDelay: %v", host, r.RootDelay)
	t.Logf("[%s]   RootDisp: %v", host, r.RootDispersion)
	t.Logf("[%s]   RootDist: %v", host, r.RootDistance)
	t.Logf("[%s]       Leap: %v", host, r.Leap)

	assertValid(t, r)
}

func TestValidate(t *testing.T) {
	var m msg
	var r *Response
	m.Stratum = 1
	m.ReferenceID = 0x58585858 // `XXXX`
	m.ReferenceTime = 1 << 32

	m.OriginTime = 1 << 32
	m.ReceiveTime = 1 << 32
	m.TransmitTime = 1 << 32
	r = parseTime(&m, 1<<32)
	assertValid(t, r)

	m.ReferenceTime = 2 << 32 // negative freshness
	r = parseTime(&m, 1<<32)
	assertInvalid(t, r)

	m.OriginTime = 2 * 86400 << 32
	m.ReceiveTime = 2 * 86400 << 32
	m.TransmitTime = 2 * 86400 << 32
	r = parseTime(&m, 2*86400<<32) // 48h freshness
	assertInvalid(t, r)

	m.ReferenceTime = 1 * 86400 << 32 // 24h freshness
	r = parseTime(&m, 2*86400<<32)
	assertValid(t, r)

	m.RootDelay = 16 << 16
	m.ReferenceTime = 1 << 32
	m.OriginTime = 20 << 32
	m.ReceiveTime = 10 << 32
	m.TransmitTime = 15 << 32
	r = parseTime(&m, 22<<32)
	assert.NotNil(t, r)
	assertValid(t, r)
	assert.Equal(t, r.RTT, -3*time.Second)
	assert.Equal(t, r.RootDistance, 8*time.Second)
	assert.Equal(t, r.CausalityViolation, 10*time.Second)
}

func TestCausality(t *testing.T) {
	var m msg
	var r *Response

	m.Stratum = 1
	m.ReferenceID = 0x58585858 // `XXXX`
	m.ReferenceTime = 1 << 32

	m.OriginTime = 1 << 32
	m.ReceiveTime = 2 << 32
	m.TransmitTime = 3 << 32
	r = parseTime(&m, 4<<32)
	assertValid(t, r)
	assert.Equal(t, r.CausalityViolation, time.Duration(0))

	var t1, t2, t3, t4 int64
	for t1 = 1; t1 <= 10; t1++ {
		for t2 = 1; t2 <= 10; t2++ {
			for t3 = 1; t3 <= 10; t3++ {
				for t4 = 1; t4 <= 10; t4++ {
					m.OriginTime = ntpTime(t1 << 32)
					m.ReceiveTime = ntpTime(t2 << 32)
					m.TransmitTime = ntpTime(t3 << 32)
					r = parseTime(&m, ntpTime(t4<<32))
					if t1 <= t4 && t2 <= t3 { // anything else is invalid getTime() response
						assertValid(t, r) // negative RTT is still possible
						var d12, d34 int64
						if t1 >= t2 {
							d12 = t1 - t2
						}
						if t3 >= t4 {
							d34 = t3 - t4
						}
						var caserr int64
						if d12 > d34 {
							caserr = d12
						} else {
							caserr = d34
						}
						assert.Equal(t, r.CausalityViolation, time.Duration(caserr)*time.Second)
					}
				}
			}
		}
	}
}

func TestBadServerPort(t *testing.T) {
	// Not NTP port.
	tm, _, err := getTime(host, QueryOptions{Port: 9})
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestTTL(t *testing.T) {
	// TTL of 1 should cause a timeout.
	tm, _, err := getTime(host, QueryOptions{TTL: 1})
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestQueryTimeout(t *testing.T) {
	// Force an immediate timeout.
	tm, err := QueryWithOptions(host, QueryOptions{Version: 4, Timeout: time.Nanosecond})
	assert.Nil(t, tm)
	assert.NotNil(t, err)
}

func TestShortConversion(t *testing.T) {
	var ts ntpTimeShort

	ts = 0x00000000
	assert.Equal(t, 0*time.Nanosecond, ts.Duration())

	ts = 0x00000001
	assert.Equal(t, 15258*time.Nanosecond, ts.Duration()) // well, it's actually 15258.789, but it's good enough

	ts = 0x00008000
	assert.Equal(t, 500*time.Millisecond, ts.Duration()) // precise

	ts = 0x0000c000
	assert.Equal(t, 750*time.Millisecond, ts.Duration()) // precise

	ts = 0x0000ff80
	assert.Equal(t, time.Second-(1000000000/512)*time.Nanosecond, ts.Duration()) // last precise sub-second value

	ts = 0x00010000
	assert.Equal(t, 1000*time.Millisecond, ts.Duration()) // precise

	ts = 0x00018000
	assert.Equal(t, 1500*time.Millisecond, ts.Duration()) // precise

	ts = 0xffff0000
	assert.Equal(t, 65535*time.Second, ts.Duration()) // precise

	ts = 0xffffff80
	assert.Equal(t, 65536*time.Second-(1000000000/512)*time.Nanosecond, ts.Duration()) // last precise value
}

func TestLongConversion(t *testing.T) {
	ts := []ntpTime{0x0, 0xff800000, 0x1ff800000, 0x80000000ff800000, 0xffffffffff800000}

	for _, v := range ts {
		assert.Equal(t, v, toNtpTime(v.Time()))
	}
}

func abs(d time.Duration) time.Duration {
	switch {
	case int64(d) < 0:
		return -d
	default:
		return d
	}
}

func TestOffsetCalculation(t *testing.T) {
	now := time.Now()
	t1 := toNtpTime(now)
	t2 := toNtpTime(now.Add(20 * time.Second))
	t3 := toNtpTime(now.Add(21 * time.Second))
	t4 := toNtpTime(now.Add(5 * time.Second))

	// expectedOffset := ((T2 - T1) + (T3 - T4)) / 2
	// ((119 - 99) + (121 - 104)) / 2
	// (20 +  17) / 2
	// 37 / 2 = 18
	expectedOffset := 18 * time.Second
	offset := offset(t1, t2, t3, t4)
	assert.Equal(t, expectedOffset, offset)
}

func TestOffsetCalculationNegative(t *testing.T) {
	now := time.Now()
	t1 := toNtpTime(now.Add(101 * time.Second))
	t2 := toNtpTime(now.Add(102 * time.Second))
	t3 := toNtpTime(now.Add(103 * time.Second))
	t4 := toNtpTime(now.Add(105 * time.Second))

	// expectedOffset := ((T2 - T1) + (T3 - T4)) / 2
	// ((102 - 101) + (103 - 105)) / 2
	// (1 + -2) / 2 = -1 / 2
	expectedOffset := -time.Second / 2
	offset := offset(t1, t2, t3, t4)
	assert.Equal(t, expectedOffset, offset)
}
<|endoftext|>


<commit_before>package stubs

// Copyright 2019 Google LLC
//
// 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
//
// 	https://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.

import (
	"context"

	container "google.golang.org/api/container/v1"
)

// ContainerStub provides a stub for the container client.
type ContainerStub struct {
}

// DisableKubernetesDashboard disables the kubernetes dashboard for a given cluster.
func (c *ContainerStub) DisableKubernetesDashboard(ctx context.Context, _, _, _ string) (*container.Operation, error) {
	return nil, nil
}
<commit_msg>Renames the method to simplify its signature<commit_after>package stubs

// Copyright 2019 Google LLC
//
// 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
//
// 	https://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.

import (
	"context"

	container "google.golang.org/api/container/v1"
)

// ContainerStub provides a stub for the container client.
type ContainerStub struct {
}

// DisableDashboard disables the Kubernetes Dashboard for a given cluster.
func (c *ContainerStub) DisableDashboard(context.Context, string, string, string) (*container.Operation, error) {
	return nil, nil
}
<|endoftext|>


<commit_before>package util

import (
	"bytes"
	"image"
	"image/color"
	"image/gif"
	"strings"

	"golang.org/x/image/font"
	"golang.org/x/image/font/basicfont"
	"golang.org/x/image/math/fixed"
)

const lineSpace int = 16
const xBorder int = 30
const yBorder int = 14
const maxWidth int = 500

func MakeGif(text string) []byte {
	const defaultText string = "Hover to view"
	var frames []*image.Paletted

	text, imageSize := formatTextSize(text, defaultText)

	frames = addImageFrame(frames, imageSize, defaultText, color.RGBA{0xff, 0xff, 0xff, 0xff}, color.RGBA{0x00, 0x00, 0x00, 0xff})

	frames = addImageFrame(frames, imageSize, text, color.RGBA{0x00, 0x00, 0x00, 0xff}, color.RGBA{0xff, 0xff, 0xff, 0xff})

	buf := new(bytes.Buffer)
	gif.EncodeAll(buf, &gif.GIF{
		Image:     frames,
		LoopCount: 1,
		Delay:     []int{300, 100000},
	})
	return buf.Bytes()
}

func addImageFrame(frames []*image.Paletted, size image.Rectangle, text string, imageColor color.RGBA, textColor color.RGBA) []*image.Paletted {
	lines := strings.Split(text, "\n")
	img, d := uniformColorImage(size,
		imageColor, textColor, fixed.Point26_6{fixed.Int26_6(xBorder / 2 * 64), fixed.Int26_6(lineSpace * 64)})
	for i, s := range lines {
		d.Dot.X = fixed.Int26_6(xBorder / 2 * 64)
		d.Dot.Y = fixed.Int26_6((i + 1) * lineSpace * 64)

		d.DrawString(s)
	}
	return append(frames, img)
}

func uniformColorImage(size image.Rectangle, imageColor color.RGBA, textColor color.RGBA, startPoint fixed.Point26_6) (result *image.Paletted, drawer *font.Drawer) {
	var palette = []color.Color{
		color.RGBA{0x00, 0x00, 0x00, 0xff},
		color.RGBA{0xff, 0xff, 0xff, 0xff},
	}
	img := image.NewPaletted(size, palette)
	setBackground(img, imageColor)
	d := &font.Drawer{
		Dst:  img,
		Src:  image.NewUniform(textColor),
		Face: basicfont.Face7x13,
		Dot:  startPoint,
	}
	return img, d
}

func setBackground(img *image.Paletted, imgColor color.RGBA) {
	bounds := img.Bounds()
	for x := 0; x < bounds.Size().X; x++ {
		for y := 0; y < bounds.Size().Y; y++ {
			img.Set(x, y, imgColor)
		}
	}
}

func formatTextSize(text string, def string) (string, image.Rectangle) {
	var r image.Rectangle
	if font.MeasureString(basicfont.Face7x13, def).Ceil() >= font.MeasureString(basicfont.Face7x13, text).Ceil() {
		r = image.Rect(0, 0,
			font.MeasureString(basicfont.Face7x13, def).Ceil()+xBorder,
			yBorder+lineSpace,
		)
		return text, r
	}

	lines := strings.Split(text, "\n")
	result := []string{}
	for _, line := range lines {
		result = append(result, formatLine(line)...)
	}

	size := image.Point{X: 0, Y: 0}
	if len(result) > 1 {
		size.X = maxWidth
	} else {
		size.X = font.MeasureString(basicfont.Face7x13, text).Ceil()
	}
	size.Y = lineSpace*len(result) + yBorder
	r = image.Rect(0, 0, size.X, size.Y)
	return strings.Join(result, "\n"), r
}

func formatLine(text string) []string {
	result := []string{text}
	currentLine := text

	for font.MeasureString(basicfont.Face7x13, currentLine).Ceil() > maxWidth-xBorder {
		lineFragments := strings.Split(currentLine, " ")
		result = append(result, "")
		for i := len(lineFragments) - 2; i >= 0 && font.MeasureString(basicfont.Face7x13, currentLine).Ceil() > maxWidth-xBorder; i-- {
			currentLine = strings.Join(lineFragments[:i], " ")
			result[len(result)-2] = currentLine
			result[len(result)-1] = strings.Join(lineFragments[i:], " ")
		}
		currentLine = result[len(result)-1]
	}
	return result
}
<commit_msg>Fixed formatting issues<commit_after>package util

import (
	"bytes"
	"image"
	"image/color"
	"image/gif"
	"strings"

	"golang.org/x/image/font"
	"golang.org/x/image/font/basicfont"
	"golang.org/x/image/math/fixed"
)

const (
	lineSpace = 16
	xBorder   = 30
	yBorder   = 14
	maxWidth  = 500
)

func MakeGif(text string) []byte {
	const defaultText = "Hover to view"
	var frames []*image.Paletted

	text, imageSize := formatTextSize(text, defaultText)

	frames = addImageFrame(frames, imageSize, defaultText, color.RGBA{0xff, 0xff, 0xff, 0xff}, color.RGBA{0x00, 0x00, 0x00, 0xff})

	frames = addImageFrame(frames, imageSize, text, color.RGBA{0x00, 0x00, 0x00, 0xff}, color.RGBA{0xff, 0xff, 0xff, 0xff})

	buf := new(bytes.Buffer)
	gif.EncodeAll(buf, &gif.GIF{
		Image:     frames,
		LoopCount: 1,
		Delay:     []int{300, 100000},
	})
	return buf.Bytes()
}

func addImageFrame(frames []*image.Paletted, size image.Rectangle, text string, imageColor color.RGBA, textColor color.RGBA) []*image.Paletted {
	lines := strings.Split(text, "\n")
	img, d := uniformColorImage(size,
		imageColor, textColor, fixed.Point26_6{fixed.Int26_6(xBorder / 2 * 64), fixed.Int26_6(lineSpace * 64)})
	for i, s := range lines {
		d.Dot.X = fixed.Int26_6(xBorder / 2 * 64)
		d.Dot.Y = fixed.Int26_6((i + 1) * lineSpace * 64)

		d.DrawString(s)
	}
	return append(frames, img)
}

func uniformColorImage(size image.Rectangle, imageColor color.RGBA, textColor color.RGBA, startPoint fixed.Point26_6) (result *image.Paletted, drawer *font.Drawer) {
	var palette = []color.Color{
		color.RGBA{0x00, 0x00, 0x00, 0xff},
		color.RGBA{0xff, 0xff, 0xff, 0xff},
	}
	img := image.NewPaletted(size, palette)
	setBackground(img, imageColor)
	d := &font.Drawer{
		Dst:  img,
		Src:  image.NewUniform(textColor),
		Face: basicfont.Face7x13,
		Dot:  startPoint,
	}
	return img, d
}

func setBackground(img *image.Paletted, imgColor color.RGBA) {
	bounds := img.Bounds()
	for x := 0; x < bounds.Size().X; x++ {
		for y := 0; y < bounds.Size().Y; y++ {
			img.Set(x, y, imgColor)
		}
	}
}

func formatTextSize(text string, def string) (string, image.Rectangle) {
	var r image.Rectangle
	if font.MeasureString(basicfont.Face7x13, def).Ceil() >= font.MeasureString(basicfont.Face7x13, text).Ceil() {
		r = image.Rect(0, 0,
			font.MeasureString(basicfont.Face7x13, def).Ceil()+xBorder,
			yBorder+lineSpace,
		)
		return text, r
	}

	lines := strings.Split(text, "\n")
	result := []string{}
	for _, line := range lines {
		result = append(result, formatLine(line)...)
	}

	size := image.Point{X: 0, Y: 0}
	if len(result) > 1 {
		size.X = maxWidth
	} else {
		size.X = font.MeasureString(basicfont.Face7x13, text).Ceil()
	}
	size.Y = lineSpace*len(result) + yBorder
	r = image.Rect(0, 0, size.X, size.Y)
	return strings.Join(result, "\n"), r
}

func formatLine(text string) []string {
	result := []string{text}
	currentLine := text

	for font.MeasureString(basicfont.Face7x13, currentLine).Ceil() > maxWidth-xBorder {
		lineFragments := strings.Split(currentLine, " ")
		result = append(result, "")
		for i := len(lineFragments) - 2; i >= 0 && font.MeasureString(basicfont.Face7x13, currentLine).Ceil() > maxWidth-xBorder; i-- {
			currentLine = strings.Join(lineFragments[:i], " ")
			result[len(result)-2] = currentLine
			result[len(result)-1] = strings.Join(lineFragments[i:], " ")
		}
		currentLine = result[len(result)-1]
	}
	return result
}
<|endoftext|>


<commit_before>package driver

import (
	"fmt"

	"github.com/estesp/dockerbench/utils"
)

// DockerDriver is an implementation of the driver interface for the Docker engine
type DockerDriver struct {
	dockerBinary string
}

// DockerContainer is an implementation of the container metadata needed for docker
type DockerContainer struct {
	name      string
	imageName string
	detached  bool
}

// NewDockerDriver creates an instance of the docker driver, providing a path to the docker client binary
func NewDockerDriver(binaryPath string) (Driver, error) {
	resolvedBinPath, err := utils.ResolveBinary(binaryPath)
	if err != nil {
		return &DockerDriver{}, err
	}
	driver := &DockerDriver{
		dockerBinary: resolvedBinPath,
	}
	driver.Info()
	return driver, nil
}

// newDockerContainer creates the metadata object of a docker-specific container with
// image name, container runtime name, and any required additional information
func newDockerContainer(name, image string, detached bool) Container {
	return &DockerContainer{
		name:      name,
		imageName: image,
		detached:  detached,
	}
}

// Name returns the name of the container
func (c *DockerContainer) Name() string {
	return c.name
}

// Detached returns whether the container should be started in detached mode
func (c *DockerContainer) Detached() bool {
	return c.detached
}

// Image returns the image name that Docker will use
func (c *DockerContainer) Image() string {
	return c.imageName
}

// Type returns a driver.Type to indentify the driver implementation
func (d *DockerDriver) Type() Type {
	return Docker
}

// Info returns
func (d *DockerDriver) Info() (string, error) {
	info := "docker driver (binary: " + d.dockerBinary + ")\n"
	versionInfo, err := utils.ExecCmd(d.dockerBinary, "version")
	if err != nil {
		return "", fmt.Errorf("Error trying to retrieve docker version info: %v", err)
	}
	return info + versionInfo, nil
}

// Create will create a container instance matching the specific needs
// of a driver
func (d *DockerDriver) Create(name, image string, detached bool) (Container, error) {
	return newDockerContainer(name, image, detached), nil
}

// Clean will clean the environment; removing any remaining containers in the runc metadata
func (d *DockerDriver) Clean() error {
	return nil
}

// Run will execute a container using the driver
func (d *DockerDriver) Run(ctr Container) (string, int, error) {
	var detached string
	if ctr.Detached() {
		detached = "-d"
	}
	args := fmt.Sprintf("run %s --name %s %s", detached, ctr.Name(), ctr.Image())
	return utils.ExecTimedCmd(d.dockerBinary, args)
}

// Stop will stop/kill a container
func (d *DockerDriver) Stop(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "stop "+ctr.Name())
}

// Remove will remove a container
func (d *DockerDriver) Remove(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "rm "+ctr.Name())
}

// Pause will pause a container
func (d *DockerDriver) Pause(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "pause "+ctr.Name())
}

// Unpause will unpause/resume a container
func (d *DockerDriver) Unpause(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "unpause "+ctr.Name())
}
<commit_msg>better docker version/info parsing<commit_after>package driver

import (
	"bufio"
	"fmt"
	"strings"
	"sync"

	"github.com/estesp/dockerbench/utils"
)

// DockerDriver is an implementation of the driver interface for the Docker engine
type DockerDriver struct {
	once         sync.Once
	dockerBinary string
	dockerInfo   string
}

// DockerContainer is an implementation of the container metadata needed for docker
type DockerContainer struct {
	name      string
	imageName string
	detached  bool
}

// NewDockerDriver creates an instance of the docker driver, providing a path to the docker client binary
func NewDockerDriver(binaryPath string) (Driver, error) {
	resolvedBinPath, err := utils.ResolveBinary(binaryPath)
	if err != nil {
		return &DockerDriver{}, err
	}
	driver := &DockerDriver{
		dockerBinary: resolvedBinPath,
	}
	driver.Info()
	return driver, nil
}

// newDockerContainer creates the metadata object of a docker-specific container with
// image name, container runtime name, and any required additional information
func newDockerContainer(name, image string, detached bool) Container {
	return &DockerContainer{
		name:      name,
		imageName: image,
		detached:  detached,
	}
}

// Name returns the name of the container
func (c *DockerContainer) Name() string {
	return c.name
}

// Detached returns whether the container should be started in detached mode
func (c *DockerContainer) Detached() bool {
	return c.detached
}

// Image returns the image name that Docker will use
func (c *DockerContainer) Image() string {
	return c.imageName
}

// Type returns a driver.Type to indentify the driver implementation
func (d *DockerDriver) Type() Type {
	return Docker
}

// Info returns
func (d *DockerDriver) Info() (string, error) {
	if d.dockerInfo != "" {
		return d.dockerInfo, nil
	}

	infoStart := "docker driver (binary: " + d.dockerBinary + ")\n"
	version, err := utils.ExecCmd(d.dockerBinary, "version")
	info, err := utils.ExecCmd(d.dockerBinary, "info")
	if err != nil {
		return "", fmt.Errorf("Error trying to retrieve docker daemon info: %v", err)
	}
	d.dockerInfo = infoStart + parseDaemonInfo(version, info)
	return d.dockerInfo, nil
}

// Create will create a container instance matching the specific needs
// of a driver
func (d *DockerDriver) Create(name, image string, detached bool) (Container, error) {
	return newDockerContainer(name, image, detached), nil
}

// Clean will clean the environment; removing any remaining containers in the runc metadata
func (d *DockerDriver) Clean() error {
	return nil
}

// Run will execute a container using the driver
func (d *DockerDriver) Run(ctr Container) (string, int, error) {
	var detached string
	if ctr.Detached() {
		detached = "-d"
	}
	args := fmt.Sprintf("run %s --name %s %s", detached, ctr.Name(), ctr.Image())
	return utils.ExecTimedCmd(d.dockerBinary, args)
}

// Stop will stop/kill a container
func (d *DockerDriver) Stop(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "stop "+ctr.Name())
}

// Remove will remove a container
func (d *DockerDriver) Remove(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "rm "+ctr.Name())
}

// Pause will pause a container
func (d *DockerDriver) Pause(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "pause "+ctr.Name())
}

// Unpause will unpause/resume a container
func (d *DockerDriver) Unpause(ctr Container) (string, int, error) {
	return utils.ExecTimedCmd(d.dockerBinary, "unpause "+ctr.Name())
}

// return a condensed string of version and daemon information
func parseDaemonInfo(version, info string) string {
	var (
		clientVer string
		clientAPI string
		serverVer string
	)
	vReader := strings.NewReader(version)
	vScan := bufio.NewScanner(vReader)

	for vScan.Scan() {
		line := vScan.Text()
		parts := strings.Split(line, ":")
		switch strings.TrimSpace(parts[0]) {
		case "Version":
			if clientVer == "" {
				// first time is client
				clientVer = strings.TrimSpace(parts[1])
			} else {
				serverVer = strings.TrimSpace(parts[1])
			}
		case "API version":
			if clientAPI == "" {
				// first instance is client
				clientAPI = parts[1]
				clientVer = clientVer + "|API:" + strings.TrimSpace(parts[1])
			} else {
				serverVer = serverVer + "|API:" + strings.TrimSpace(parts[1])
			}
		default:
		}

	}
	iReader := strings.NewReader(info)
	iScan := bufio.NewScanner(iReader)

	for iScan.Scan() {
		line := iScan.Text()
		parts := strings.Split(line, ":")
		switch strings.TrimSpace(parts[0]) {
		case "Kernel Version":
			serverVer = serverVer + "|Kernel:" + strings.TrimSpace(parts[1])
		case "Storage Driver":
			serverVer = serverVer + "|Storage:" + strings.TrimSpace(parts[1])
		case "Backing Filesystem":
			serverVer = serverVer + "|BackingFS:" + strings.TrimSpace(parts[1])
		default:
		}

	}
	return fmt.Sprintf("[CLIENT:%s][SERVER:%s]", clientVer, serverVer)
}
<|endoftext|>


<commit_before>package profile

import (
	"bytes"
	"flag"
	"hash/fnv"
	"io"
	"io/ioutil"
	"path/filepath"
	"testing"
)

const (
	testdata      = "testdata"
	fileExt       = ".xlsx"
	goldenSuffix  = ".golden"
	currentSuffix = ".current"
)

var update = flag.Bool("update", false, "update .golden output files")

func init() { flag.Parse() }

var currentSDK = sdks[0]

var defGenOpts = []GeneratorOption{
	WithGenerationTimestamp(false),
}

func relPath(sdkVersion string) string {
	return filepath.Join(testdata, sdkVersion+fileExt)
}

func (p *Profile) WriteTo(w io.Writer) (int64, error) {
	var err error
	var n int
	write := func(buf []byte) {
		if err != nil {
			return
		}
		n, err = w.Write(buf)
	}
	write([]byte("// TYPES\n"))
	write(p.TypesSource)
	write([]byte("// MESSAGES\n"))
	write(p.MessagesSource)
	write([]byte("// PROFILE\n"))
	write(p.ProfileSource)
	write([]byte("// STRINGER TYPE INPUT\n"))
	write([]byte(p.StringerInput))
	write([]byte("\n// MESSAGE NUMS WITHOUT MESSAGE\n"))
	for _, mn := range p.MesgNumsWithoutMessage {
		write([]byte(mn))
		write([]byte{'\n'})
	}
	return int64(n), err
}

func (p *Profile) WriteToFile(path string) error {
	buf := new(bytes.Buffer)
	_, err := p.WriteTo(buf)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(path, buf.Bytes(), 0644)
}

func (p *Profile) FnvHash() uint32 {
	h := fnv.New32a()
	_, _ = p.WriteTo(h)
	return h.Sum32()
}

type sdk struct {
	version    string
	goldenHash uint32
}

var sdks = []sdk{
	{"16.20", 341779287},
}

func TestGenerator(t *testing.T) {
	for _, sdk := range sdks {
		t.Run(sdk.version, func(t *testing.T) {
			if sdk == currentSDK && testing.Short() {
				t.Skip("skipping test in short mode")
			}
			path := relPath(sdk.version)
			data, err := ioutil.ReadFile(path)
			if err != nil {
				t.Fatal(err)
			}
			g, err := NewGenerator(path, data, defGenOpts...)
			if err != nil {
				t.Fatal(err)
			}
			profile, err := g.GenerateProfile()
			if err != nil {
				t.Fatal(err)
			}
			gotHash := profile.FnvHash()
			if gotHash == sdk.goldenHash {
				return
			}
			t.Errorf("profile fingerprint differs: got: %d, want %d", gotHash, sdk.goldenHash)
			if !*update {
				path = path + currentSuffix
			} else {
				path = path + goldenSuffix
			}
			err = profile.WriteToFile(path)
			if err != nil {
				t.Fatalf("error writing output: %v", err)
			}
			if !*update {
				t.Logf("current output written to: %s", path)
			} else {
				t.Logf("%q has been updated", path)
				t.Logf("new fingerprint is: %d", gotHash)
			}
		})
	}
}

var profileSink *Profile

func BenchmarkGenerator(b *testing.B) {
	for _, sdk := range sdks {
		b.Run(sdk.version, func(b *testing.B) {
			path := relPath(sdk.version)
			data, err := ioutil.ReadFile(path)
			if err != nil {
				b.Fatalf("error reading profile workbook: %v", err)
			}
			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				g, err := NewGenerator(path, data, defGenOpts...)
				if err != nil {
					b.Fatal(err)
				}
				profileSink, err = g.GenerateProfile()
				if err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}
<commit_msg>cmd/fitgen/internal/profile: ensure black box testing of generator<commit_after>package profile_test

import (
	"bytes"
	"flag"
	"hash/fnv"
	"io"
	"io/ioutil"
	"path/filepath"
	"testing"

	"github.com/tormoder/fit/cmd/fitgen/internal/profile"
)

const (
	testdata      = "testdata"
	fileExt       = ".xlsx"
	goldenSuffix  = ".golden"
	currentSuffix = ".current"
)

var update = flag.Bool("update", false, "update .golden output files")

func init() { flag.Parse() }

var currentSDK = sdks[0]

var defGenOpts = []profile.GeneratorOption{
	profile.WithGenerationTimestamp(false),
}

func relPath(sdkVersion string) string {
	return filepath.Join(testdata, sdkVersion+fileExt)
}

func writeProfile(p *profile.Profile, w io.Writer) error {
	var err error
	write := func(buf []byte) {
		if err != nil {
			return
		}
		_, err = w.Write(buf)
	}
	write([]byte("// TYPES\n"))
	write(p.TypesSource)
	write([]byte("// MESSAGES\n"))
	write(p.MessagesSource)
	write([]byte("// PROFILE\n"))
	write(p.ProfileSource)
	write([]byte("// STRINGER TYPE INPUT\n"))
	write([]byte(p.StringerInput))
	write([]byte("\n// MESSAGE NUMS WITHOUT MESSAGE\n"))
	for _, mn := range p.MesgNumsWithoutMessage {
		write([]byte(mn))
		write([]byte{'\n'})
	}
	return err
}

func writeProfileToFile(p *profile.Profile, path string) error {
	buf := new(bytes.Buffer)
	err := writeProfile(p, buf)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(path, buf.Bytes(), 0644)
}

func profileFingerprint(p *profile.Profile) uint32 {
	h := fnv.New32a()
	_ = writeProfile(p, h)
	return h.Sum32()
}

type sdk struct {
	version    string
	goldenHash uint32
}

var sdks = []sdk{
	{"16.20", 341779287},
}

func TestGenerator(t *testing.T) {
	for _, sdk := range sdks {
		t.Run(sdk.version, func(t *testing.T) {
			if sdk == currentSDK && testing.Short() {
				t.Skip("skipping test in short mode")
			}
			path := relPath(sdk.version)
			data, err := ioutil.ReadFile(path)
			if err != nil {
				t.Fatal(err)
			}
			g, err := profile.NewGenerator(path, data, defGenOpts...)
			if err != nil {
				t.Fatal(err)
			}
			p, err := g.GenerateProfile()
			if err != nil {
				t.Fatal(err)
			}
			gotHash := profileFingerprint(p)
			if gotHash == sdk.goldenHash {
				return
			}
			t.Errorf("profile fingerprint differs: got: %d, want %d", gotHash, sdk.goldenHash)
			if !*update {
				path = path + currentSuffix
			} else {
				path = path + goldenSuffix
			}
			err = writeProfileToFile(p, path)
			if err != nil {
				t.Fatalf("error writing output: %v", err)
			}
			if !*update {
				t.Logf("current output written to: %s", path)
			} else {
				t.Logf("%q has been updated", path)
				t.Logf("new fingerprint is: %d", gotHash)
			}
		})
	}
}

var profileSink *profile.Profile

func BenchmarkGenerator(b *testing.B) {
	for _, sdk := range sdks {
		b.Run(sdk.version, func(b *testing.B) {
			path := relPath(sdk.version)
			data, err := ioutil.ReadFile(path)
			if err != nil {
				b.Fatalf("error reading profile workbook: %v", err)
			}
			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				g, err := profile.NewGenerator(path, data, defGenOpts...)
				if err != nil {
					b.Fatal(err)
				}
				profileSink, err = g.GenerateProfile()
				if err != nil {
					b.Fatal(err)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>package slackapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"strings"
)

// SlackAPI defines the base object. It holds the API token, the information of
// the user account associated to such API token, the information for the robot
// session (if the user decides has activated it), a list of all the available
// public channels, a list of all the accessible private groups, and a list of
// the users registered into the Slack team.
type SlackAPI struct {
	owner        Owner
	token        string
	params       map[string]string
	teamUsers    ResponseUsersList
	teamGroups   ResponseGroupsList
	teamChannels ResponseChannelsList
}

// New instantiates a new object.
func New() *SlackAPI {
	var s SlackAPI

	s.params = make(map[string]string, 0)

	return &s
}

// SetToken sets the API token for the session.
func (s *SlackAPI) SetToken(token string) {
	s.token = token
}

// URL builds and returns the URL to send the HTTP requests.
func (s *SlackAPI) URL(action string, params map[string]string) string {
	data := url.Values{}
	url := "https://slack.com/api/" + action

	for name, value := range params {
		data.Add(name, value)
	}

	if encoded := data.Encode(); encoded != "" {
		url += "?" + encoded
	}

	return url
}

// HTTPRequest builds an HTTP request object and attaches the action parameters.
func (s *SlackAPI) HTTPRequest(method string, body io.Reader, action string, params map[string]string) (*http.Request, error) {
	if len(s.params) > 0 {
		for name, value := range s.params {
			params[name] = value
		}
		s.params = map[string]string{}
	}

	url := s.URL(action, params)
	req, err := http.NewRequest(method, url, body)

	if err != nil {
		return nil, err
	}

	req.Header.Add("Connection", "keep-alive")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Accept-Language", "en-US,en")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("User-Agent", "Mozilla/5.0 (KHTML, like Gecko) Safari/537.36")

	return req, nil
}

// DataToParams converts a template into a HTTP request parameter map.
func (s *SlackAPI) DataToParams(data interface{}) map[string]string {
	if data == nil {
		/* no params except for the API token */
		return map[string]string{"token": s.token}
	}

	var name string
	var value interface{}

	t := reflect.TypeOf(data)
	v := reflect.ValueOf(data)

	length := t.NumField() /* struct size */
	params := make(map[string]string, length+1)
	params["token"] = s.token /* API token */

	for i := 0; i < length; i++ {
		name = t.Field(i).Tag.Get("json")
		value = v.Field(i).Interface()

		switch v.Field(i).Interface().(type) {
		case int:
			params[name] = fmt.Sprintf("%d", value)

		case bool:
			if value.(bool) {
				params[name] = "true"
			} else {
				params[name] = "false"
			}

		case string:
			params[name] = value.(string)

		case []string:
			params[name] = strings.Join(value.([]string), ",")

		case []Attachment:
			if out, err := json.Marshal(value); err == nil {
				params[name] = string(out)
			}
		}
	}

	return params
}

// AddRequestParam adds an additional parameter to the HTTP request.
func (s *SlackAPI) AddRequestParam(name string, value string) {
	s.params[name] = value
}

// ExecuteRequest sends the HTTP request and decodes the JSON response.
func (s *SlackAPI) ExecuteRequest(req *http.Request, data interface{}) {
	client := &http.Client{}
	resp, err := client.Do(req)

	if err != nil {
		log.Println("http;", err)
		return
	}

	defer func() {
		if err := resp.Body.Close(); err != nil {
			log.Println("http exec; body close;", err)
		}
	}()

	var buf bytes.Buffer
	tee := io.TeeReader(resp.Body, &buf)

	if err := json.NewDecoder(tee).Decode(&data); err != nil {
		out, _ := ioutil.ReadAll(&buf) /* bad idea; change */

		if strings.Contains(string(out), "too many requests") {
			fake := "{\"ok\":false, \"error\":\"RATELIMIT\"}"
			read := bytes.NewReader([]byte(fake))

			if err2 := json.NewDecoder(read).Decode(&data); err2 != nil {
				log.Println("http exec; json decode;", err)
			}

			return
		}

		log.Println("ratelimit;", err)
	}
}

// PrintCurlCommand prints the HTTP request object into the console.
func (s *SlackAPI) PrintCurlCommand(req *http.Request, params map[string]string) {
	if os.Getenv("SLACK_VERBOSE") != "true" {
		return
	}

	fmt.Printf("curl -X %s \"%s\"", req.Method, req.URL)

	for header, values := range req.Header {
		fmt.Printf(" \x5c\n-H \"%s: %s\"", header, values[0])
	}

	fmt.Printf(" \x5c\n-H \"Host: %s\"", req.Host)

	if req.Method == "POST" {
		for name, value := range params {
			fmt.Printf(" \x5c\n-d \"%s=%s\"", name, value)
		}
	}

	fmt.Println()
}

// GetRequest sends a HTTP GET request to the API and returns the response.
func (s *SlackAPI) GetRequest(v interface{}, action string, data interface{}) {
	params := s.DataToParams(data)
	req, err := s.HTTPRequest("GET", nil, action, params)

	if err != nil {
		log.Println("http get;", err)
		return
	}

	s.PrintCurlCommand(req, params)
	s.ExecuteRequest(req, &v)
}

// PostRequest sends a HTTP POST request to the API and returns the response. If
// one of the request parameters is prefixed with an AT symbol the method will
// assume that the user is trying to load a local file, it will proceed to check
// this by locating such file in the disk, then will attach the data into the
// HTTP request object and upload it to the API. Alternatively, if the file does
// not exists, the method will send the parameter with the apparent filename as
// a string value.
func (s *SlackAPI) PostRequest(v interface{}, action string, data interface{}) {
	var buffer bytes.Buffer
	params := s.DataToParams(data)
	writer := multipart.NewWriter(&buffer)

	// Append more HTTP request params.
	for name, value := range params {
		/* Check if the parameter is referencing a file */
		isfile, fpath, fname := s.CheckFileReference(value)

		if !isfile {
			fwriter, _ := writer.CreateFormField(name)
			if _, err := fwriter.Write([]byte(value)); err != nil {
				log.Println("http post; create field;", err)
			}
			continue
		}

		/* Read referenced file and attach to the request */
		resource, err := os.Open(fpath)
		if err != nil {
			log.Println("file open;", err)
			return
		}

		defer func() {
			if err := resource.Close(); err != nil {
				log.Println("http post; file close;", err)
			}
		}()

		fwriter, _ := writer.CreateFormFile(name, fpath)
		if _, err := io.Copy(fwriter, resource); err != nil {
			log.Println("http post; copy param;", err)
			continue
		}

		fwriter, _ = writer.CreateFormField("filename")
		if _, err := fwriter.Write([]byte(fname)); err != nil {
			log.Println("http post; write param;", err)
			continue
		}
	}

	if err := writer.Close(); err != nil {
		log.Println("http post; write close;", err)
		return
	}

	// Now that you have a form, you can submit it to your handler.
	req, err := s.HTTPRequest("POST", &buffer, action, nil)

	if err != nil {
		log.Println("http post;", err)
		return
	}

	req.Header.Set("Content-Type", writer.FormDataContentType())

	s.PrintCurlCommand(req, params)
	s.ExecuteRequest(req, &v)
}

// CheckFileReference checks if a HTTP request parameter is a file reference.
func (s *SlackAPI) CheckFileReference(text string) (bool, string, string) {
	if len(text) < 2 || text[0] != '@' {
		return false, "", ""
	}

	fpath := text[1:]

	/* Check if the file actually exists */
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		return false, "", ""
	}

	parts := strings.Split(fpath, "/")
	fname := parts[len(parts)-1]

	return true, fpath, fname
}
<commit_msg>Modify initialization of the HTTP request parameter map<commit_after>package slackapi

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"strings"
)

// SlackAPI defines the base object. It holds the API token, the information of
// the user account associated to such API token, the information for the robot
// session (if the user decides has activated it), a list of all the available
// public channels, a list of all the accessible private groups, and a list of
// the users registered into the Slack team.
type SlackAPI struct {
	owner        Owner
	token        string
	params       map[string]string
	teamUsers    ResponseUsersList
	teamGroups   ResponseGroupsList
	teamChannels ResponseChannelsList
}

// New instantiates a new object.
func New() *SlackAPI {
	var s SlackAPI

	s.params = make(map[string]string)

	return &s
}

// SetToken sets the API token for the session.
func (s *SlackAPI) SetToken(token string) {
	s.token = token
}

// URL builds and returns the URL to send the HTTP requests.
func (s *SlackAPI) URL(action string, params map[string]string) string {
	data := url.Values{}
	url := "https://slack.com/api/" + action

	for name, value := range params {
		data.Add(name, value)
	}

	if encoded := data.Encode(); encoded != "" {
		url += "?" + encoded
	}

	return url
}

// HTTPRequest builds an HTTP request object and attaches the action parameters.
func (s *SlackAPI) HTTPRequest(method string, body io.Reader, action string, params map[string]string) (*http.Request, error) {
	if len(s.params) > 0 {
		for name, value := range s.params {
			params[name] = value
		}
		s.params = map[string]string{}
	}

	url := s.URL(action, params)
	req, err := http.NewRequest(method, url, body)

	if err != nil {
		return nil, err
	}

	req.Header.Add("Connection", "keep-alive")
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Accept-Language", "en-US,en")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("User-Agent", "Mozilla/5.0 (KHTML, like Gecko) Safari/537.36")

	return req, nil
}

// DataToParams converts a template into a HTTP request parameter map.
func (s *SlackAPI) DataToParams(data interface{}) map[string]string {
	if data == nil {
		/* no params except for the API token */
		return map[string]string{"token": s.token}
	}

	var name string
	var value interface{}

	t := reflect.TypeOf(data)
	v := reflect.ValueOf(data)

	length := t.NumField() /* struct size */
	params := make(map[string]string, length+1)
	params["token"] = s.token /* API token */

	for i := 0; i < length; i++ {
		name = t.Field(i).Tag.Get("json")
		value = v.Field(i).Interface()

		switch v.Field(i).Interface().(type) {
		case int:
			params[name] = fmt.Sprintf("%d", value)

		case bool:
			if value.(bool) {
				params[name] = "true"
			} else {
				params[name] = "false"
			}

		case string:
			params[name] = value.(string)

		case []string:
			params[name] = strings.Join(value.([]string), ",")

		case []Attachment:
			if out, err := json.Marshal(value); err == nil {
				params[name] = string(out)
			}
		}
	}

	return params
}

// AddRequestParam adds an additional parameter to the HTTP request.
func (s *SlackAPI) AddRequestParam(name string, value string) {
	s.params[name] = value
}

// ExecuteRequest sends the HTTP request and decodes the JSON response.
func (s *SlackAPI) ExecuteRequest(req *http.Request, data interface{}) {
	client := &http.Client{}
	resp, err := client.Do(req)

	if err != nil {
		log.Println("http;", err)
		return
	}

	defer func() {
		if err := resp.Body.Close(); err != nil {
			log.Println("http exec; body close;", err)
		}
	}()

	var buf bytes.Buffer
	tee := io.TeeReader(resp.Body, &buf)

	if err := json.NewDecoder(tee).Decode(&data); err != nil {
		out, _ := ioutil.ReadAll(&buf) /* bad idea; change */

		if strings.Contains(string(out), "too many requests") {
			fake := "{\"ok\":false, \"error\":\"RATELIMIT\"}"
			read := bytes.NewReader([]byte(fake))

			if err2 := json.NewDecoder(read).Decode(&data); err2 != nil {
				log.Println("http exec; json decode;", err)
			}

			return
		}

		log.Println("ratelimit;", err)
	}
}

// PrintCurlCommand prints the HTTP request object into the console.
func (s *SlackAPI) PrintCurlCommand(req *http.Request, params map[string]string) {
	if os.Getenv("SLACK_VERBOSE") != "true" {
		return
	}

	fmt.Printf("curl -X %s \"%s\"", req.Method, req.URL)

	for header, values := range req.Header {
		fmt.Printf(" \x5c\n-H \"%s: %s\"", header, values[0])
	}

	fmt.Printf(" \x5c\n-H \"Host: %s\"", req.Host)

	if req.Method == "POST" {
		for name, value := range params {
			fmt.Printf(" \x5c\n-d \"%s=%s\"", name, value)
		}
	}

	fmt.Println()
}

// GetRequest sends a HTTP GET request to the API and returns the response.
func (s *SlackAPI) GetRequest(v interface{}, action string, data interface{}) {
	params := s.DataToParams(data)
	req, err := s.HTTPRequest("GET", nil, action, params)

	if err != nil {
		log.Println("http get;", err)
		return
	}

	s.PrintCurlCommand(req, params)
	s.ExecuteRequest(req, &v)
}

// PostRequest sends a HTTP POST request to the API and returns the response. If
// one of the request parameters is prefixed with an AT symbol the method will
// assume that the user is trying to load a local file, it will proceed to check
// this by locating such file in the disk, then will attach the data into the
// HTTP request object and upload it to the API. Alternatively, if the file does
// not exists, the method will send the parameter with the apparent filename as
// a string value.
func (s *SlackAPI) PostRequest(v interface{}, action string, data interface{}) {
	var buffer bytes.Buffer
	params := s.DataToParams(data)
	writer := multipart.NewWriter(&buffer)

	// Append more HTTP request params.
	for name, value := range params {
		/* Check if the parameter is referencing a file */
		isfile, fpath, fname := s.CheckFileReference(value)

		if !isfile {
			fwriter, _ := writer.CreateFormField(name)
			if _, err := fwriter.Write([]byte(value)); err != nil {
				log.Println("http post; create field;", err)
			}
			continue
		}

		/* Read referenced file and attach to the request */
		resource, err := os.Open(fpath)
		if err != nil {
			log.Println("file open;", err)
			return
		}

		defer func() {
			if err := resource.Close(); err != nil {
				log.Println("http post; file close;", err)
			}
		}()

		fwriter, _ := writer.CreateFormFile(name, fpath)
		if _, err := io.Copy(fwriter, resource); err != nil {
			log.Println("http post; copy param;", err)
			continue
		}

		fwriter, _ = writer.CreateFormField("filename")
		if _, err := fwriter.Write([]byte(fname)); err != nil {
			log.Println("http post; write param;", err)
			continue
		}
	}

	if err := writer.Close(); err != nil {
		log.Println("http post; write close;", err)
		return
	}

	// Now that you have a form, you can submit it to your handler.
	req, err := s.HTTPRequest("POST", &buffer, action, nil)

	if err != nil {
		log.Println("http post;", err)
		return
	}

	req.Header.Set("Content-Type", writer.FormDataContentType())

	s.PrintCurlCommand(req, params)
	s.ExecuteRequest(req, &v)
}

// CheckFileReference checks if a HTTP request parameter is a file reference.
func (s *SlackAPI) CheckFileReference(text string) (bool, string, string) {
	if len(text) < 2 || text[0] != '@' {
		return false, "", ""
	}

	fpath := text[1:]

	/* Check if the file actually exists */
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		return false, "", ""
	}

	parts := strings.Split(fpath, "/")
	fname := parts[len(parts)-1]

	return true, fpath, fname
}
<|endoftext|>


<commit_before>package openstack_test

import (
	"crypto/rand"
	"fmt"
	"io"
	. "launchpad.net/gocheck"
	"launchpad.net/goose/client"
	"launchpad.net/goose/identity"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/jujutest"
	"launchpad.net/juju-core/environs/openstack"
	coretesting "launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/version"
	"strings"
)

// uniqueName is generated afresh for every test run, so that
// we are not polluted by previous test state.
var uniqueName = randomName()

func randomName() string {
	buf := make([]byte, 8)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		panic(fmt.Sprintf("error from crypto rand: %v", err))
	}
	return fmt.Sprintf("%x", buf)
}

func makeTestConfig() map[string]interface{} {
	// The following attributes hold the environment configuration
	// for running the OpenStack integration tests.
	//
	// This is missing keys for security reasons; set the following
	// environment variables to make the OpenStack testing work:
	//  access-key: $OS_USERNAME
	//  secret-key: $OS_PASSWORD
	//
	attrs := map[string]interface{}{
		"name":           "sample-" + uniqueName,
		"type":           "openstack",
		"auth-method":    "userpass",
		"control-bucket": "juju-test-" + uniqueName,
		"ca-cert":        coretesting.CACert,
		"ca-private-key": coretesting.CAKey,
	}
	return attrs
}

// Register tests to run against a real Openstack instance.
func registerOpenStackTests(cred *identity.Credentials) {
	Suite(&LiveTests{
		cred: cred,
	})
}

// LiveTests contains tests that can be run against OpenStack deployments.
// The deployment can be a real live instance or service doubles.
// Each test runs using the same connection.
type LiveTests struct {
	coretesting.LoggingSuite
	jujutest.LiveTests
	cred                   *identity.Credentials
	writeablePublicStorage environs.Storage
}

const (
	// TODO (wallyworld) - ideally, something like http://cloud-images.ubuntu.com would have images we could use
	// but until it does, we allow a default image id to be specified.
	// This is an existing image on Canonistack - smoser-cloud-images/ubuntu-quantal-12.10-i386-server-20121017
	testImageId = "0f602ea9-c09e-440c-9e29-cfae5635afa3"
)

func (t *LiveTests) SetUpSuite(c *C) {
	t.LoggingSuite.SetUpSuite(c)
	// Get an authenticated Goose client to extract some configuration parameters for the test environment.
	client := client.NewClient(t.cred, identity.AuthUserPass, nil)
	err := client.Authenticate()
	c.Assert(err, IsNil)
	publicBucketURL, err := client.MakeServiceURL("object-store", nil)
	c.Assert(err, IsNil)
	attrs := makeTestConfig()
	attrs["admin-secret"] = "secret"
	attrs["username"] = t.cred.User
	attrs["password"] = t.cred.Secrets
	attrs["region"] = t.cred.Region
	attrs["auth-url"] = t.cred.URL
	attrs["tenant-name"] = t.cred.TenantName
	attrs["public-bucket-url"] = publicBucketURL
	attrs["default-image-id"] = testImageId
	t.Config = attrs
	t.LiveTests = jujutest.LiveTests{
		Config:         attrs,
		Attempt:        *openstack.ShortAttempt,
		CanOpenState:   false, // no state; local tests (unless -live is passed)
		HasProvisioner: false, // don't deploy anything
	}
	e, err := environs.NewFromAttrs(t.Config)
	c.Assert(err, IsNil)

	// Environ.PublicStorage() is read only.
	// For testing, we create a specific storage instance which is authorised to write to
	// the public storage bucket so that we can upload files for testing.
	t.writeablePublicStorage = openstack.WritablePublicStorage(e)
	// Put some fake tools in place so that tests that are simply
	// starting instances without any need to check if those instances
	// are running will find them in the public bucket.
	putFakeTools(c, t.writeablePublicStorage)
	t.LiveTests.SetUpSuite(c)
}

func (t *LiveTests) TearDownSuite(c *C) {
	if t.Env == nil {
		// This can happen if SetUpSuite fails.
		return
	}
	if t.writeablePublicStorage != nil {
		err := openstack.DeleteStorageContent(t.writeablePublicStorage)
		c.Check(err, IsNil)
	}
	t.LiveTests.TearDownSuite(c)
	t.LoggingSuite.TearDownSuite(c)
}

func (t *LiveTests) SetUpTest(c *C) {
	t.LoggingSuite.SetUpTest(c)
	t.LiveTests.SetUpTest(c)
}

func (t *LiveTests) TearDownTest(c *C) {
	t.LiveTests.TearDownTest(c)
	t.LoggingSuite.TearDownTest(c)
}

// putFakeTools sets up a bucket containing something
// that looks like a tools archive so test methods
// that start an instance can succeed even though they
// do not upload tools.
func putFakeTools(c *C, s environs.StorageWriter) {
	path := environs.ToolsStoragePath(version.Current)
	c.Logf("putting fake tools at %v", path)
	toolsContents := "tools archive, honest guv"
	err := s.Put(path, strings.NewReader(toolsContents), int64(len(toolsContents)))
	c.Assert(err, IsNil)
}

func (t *LiveTests) TestFindImageSpec(c *C) {
	imageId, flavorId, err := openstack.FindInstanceSpec(t.Env, "precise", "amd64", "m1.small")
	c.Assert(err, IsNil)
	// For now, the imageId always comes from the environment config.
	c.Assert(imageId, Equals, testImageId)
	c.Assert(flavorId, Not(Equals), "")
}

// The following tests need to be enabled once the coding is complete.

func (s *LiveTests) TestGlobalPorts(c *C) {
	c.Skip("Work in progress")
}

func (s *LiveTests) TestPorts(c *C) {
	c.Skip("Work in progress")
}

func (s *LiveTests) TestStartStop(c *C) {
	c.Skip("Work in progress")
}
<commit_msg>Add another test<commit_after>package openstack_test

import (
	"crypto/rand"
	"fmt"
	"io"
	. "launchpad.net/gocheck"
	"launchpad.net/goose/client"
	"launchpad.net/goose/identity"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/jujutest"
	"launchpad.net/juju-core/environs/openstack"
	coretesting "launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/version"
	"strings"
)

// uniqueName is generated afresh for every test run, so that
// we are not polluted by previous test state.
var uniqueName = randomName()

func randomName() string {
	buf := make([]byte, 8)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		panic(fmt.Sprintf("error from crypto rand: %v", err))
	}
	return fmt.Sprintf("%x", buf)
}

func makeTestConfig() map[string]interface{} {
	// The following attributes hold the environment configuration
	// for running the OpenStack integration tests.
	//
	// This is missing keys for security reasons; set the following
	// environment variables to make the OpenStack testing work:
	//  access-key: $OS_USERNAME
	//  secret-key: $OS_PASSWORD
	//
	attrs := map[string]interface{}{
		"name":           "sample-" + uniqueName,
		"type":           "openstack",
		"auth-method":    "userpass",
		"control-bucket": "juju-test-" + uniqueName,
		"ca-cert":        coretesting.CACert,
		"ca-private-key": coretesting.CAKey,
	}
	return attrs
}

// Register tests to run against a real Openstack instance.
func registerOpenStackTests(cred *identity.Credentials) {
	Suite(&LiveTests{
		cred: cred,
	})
}

// LiveTests contains tests that can be run against OpenStack deployments.
// The deployment can be a real live instance or service doubles.
// Each test runs using the same connection.
type LiveTests struct {
	coretesting.LoggingSuite
	jujutest.LiveTests
	cred                   *identity.Credentials
	writeablePublicStorage environs.Storage
}

const (
	// TODO (wallyworld) - ideally, something like http://cloud-images.ubuntu.com would have images we could use
	// but until it does, we allow a default image id to be specified.
	// This is an existing image on Canonistack - smoser-cloud-images/ubuntu-quantal-12.10-i386-server-20121017
	testImageId = "0f602ea9-c09e-440c-9e29-cfae5635afa3"
)

func (t *LiveTests) SetUpSuite(c *C) {
	t.LoggingSuite.SetUpSuite(c)
	// Get an authenticated Goose client to extract some configuration parameters for the test environment.
	client := client.NewClient(t.cred, identity.AuthUserPass, nil)
	err := client.Authenticate()
	c.Assert(err, IsNil)
	publicBucketURL, err := client.MakeServiceURL("object-store", nil)
	c.Assert(err, IsNil)
	attrs := makeTestConfig()
	attrs["admin-secret"] = "secret"
	attrs["username"] = t.cred.User
	attrs["password"] = t.cred.Secrets
	attrs["region"] = t.cred.Region
	attrs["auth-url"] = t.cred.URL
	attrs["tenant-name"] = t.cred.TenantName
	attrs["public-bucket-url"] = publicBucketURL
	attrs["default-image-id"] = testImageId
	t.Config = attrs
	t.LiveTests = jujutest.LiveTests{
		Config:         attrs,
		Attempt:        *openstack.ShortAttempt,
		CanOpenState:   false, // no state; local tests (unless -live is passed)
		HasProvisioner: false, // don't deploy anything
	}
	e, err := environs.NewFromAttrs(t.Config)
	c.Assert(err, IsNil)

	// Environ.PublicStorage() is read only.
	// For testing, we create a specific storage instance which is authorised to write to
	// the public storage bucket so that we can upload files for testing.
	t.writeablePublicStorage = openstack.WritablePublicStorage(e)
	// Put some fake tools in place so that tests that are simply
	// starting instances without any need to check if those instances
	// are running will find them in the public bucket.
	putFakeTools(c, t.writeablePublicStorage)
	t.LiveTests.SetUpSuite(c)
}

func (t *LiveTests) TearDownSuite(c *C) {
	if t.Env == nil {
		// This can happen if SetUpSuite fails.
		return
	}
	if t.writeablePublicStorage != nil {
		err := openstack.DeleteStorageContent(t.writeablePublicStorage)
		c.Check(err, IsNil)
	}
	t.LiveTests.TearDownSuite(c)
	t.LoggingSuite.TearDownSuite(c)
}

func (t *LiveTests) SetUpTest(c *C) {
	t.LoggingSuite.SetUpTest(c)
	t.LiveTests.SetUpTest(c)
}

func (t *LiveTests) TearDownTest(c *C) {
	t.LiveTests.TearDownTest(c)
	t.LoggingSuite.TearDownTest(c)
}

// putFakeTools sets up a bucket containing something
// that looks like a tools archive so test methods
// that start an instance can succeed even though they
// do not upload tools.
func putFakeTools(c *C, s environs.StorageWriter) {
	path := environs.ToolsStoragePath(version.Current)
	c.Logf("putting fake tools at %v", path)
	toolsContents := "tools archive, honest guv"
	err := s.Put(path, strings.NewReader(toolsContents), int64(len(toolsContents)))
	c.Assert(err, IsNil)
}

func (t *LiveTests) TestFindImageSpec(c *C) {
	imageId, flavorId, err := openstack.FindInstanceSpec(t.Env, "precise", "amd64", "m1.small")
	c.Assert(err, IsNil)
	// For now, the imageId always comes from the environment config.
	c.Assert(imageId, Equals, testImageId)
	c.Assert(flavorId, Not(Equals), "")
}

func (t *LiveTests) TestFindImageBadFlavor(c *C) {
	imageId, flavorId, err := openstack.FindInstanceSpec(t.Env, "precise", "amd64", "bad.flavor")
	_, ok := err.(environs.NotFoundError)
	c.Assert(ok, Equals, true)
	c.Assert(imageId, Equals, "")
	c.Assert(flavorId, Equals, "")
}

// The following tests need to be enabled once the coding is complete.

func (s *LiveTests) TestGlobalPorts(c *C) {
	c.Skip("Work in progress")
}

func (s *LiveTests) TestPorts(c *C) {
	c.Skip("Work in progress")
}

func (s *LiveTests) TestStartStop(c *C) {
	c.Skip("Work in progress")
}
<|endoftext|>