<commit_before>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package test

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/arangodb-helper/arangodb/client"
	shell "github.com/kballard/go-shellquote"
	"github.com/pkg/errors"
)

const (
	ctrlC           = "\u0003"
	whatCluster     = "cluster"
	whatSingle      = "single server"
	testModeProcess = "localprocess"
	testModeDocker  = "docker"
)

var (
	isVerbose bool
	testModes []string
)

func init() {
	isVerbose = os.Getenv("VERBOSE") != ""
	testModes = strings.Split(os.Getenv("TEST_MODES"), " ")
	if len(testModes) == 1 && testModes[0] == "" {
		testModes = nil
	}
}

func needTestMode(t *testing.T, testMode string) {
	for _, x := range testModes {
		if x == testMode {
			return
		}
	}
	if len(testModes) == 0 {
		return
	}
	t.Skipf("Test mode '%s' not set", testMode)
}

// Spawn a command an return its process.
func Spawn(t *testing.T, command string) *SubProcess {
	command = strings.TrimSpace(command)
	args, err := shell.Split(os.ExpandEnv(command))
	if err != nil {
		t.Fatal(describe(err))
	}
	if isVerbose {
		t.Log(args, len(args))
	}
	p, err := NewSubProcess(args[0], args[1:]...)
	if err != nil {
		t.Fatal(describe(err))
	}
	if err := p.Start(); err != nil {
		p.Close()
		t.Fatal(describe(err))
	}
	return p
}

// SetUniqueDataDir creates a temp dir and sets the DATA_DIR environment variable to it.
func SetUniqueDataDir(t *testing.T) string {
	dataDir, err := ioutil.TempDir("", "")
	if err != nil {
		t.Fatal(describe(err))
	}
	os.Setenv("DATA_DIR", dataDir)
	return dataDir
}

// WaitUntilStarterReady waits until all given starter processes have reached the "Your cluster is ready state"
func WaitUntilStarterReady(t *testing.T, what string, starters ...*SubProcess) bool {
	g := sync.WaitGroup{}
	result := true
	for _, starter := range starters {
		starter := starter // Used in nested function
		g.Add(1)
		go func() {
			defer g.Done()
			if err := starter.ExpectTimeout(time.Minute, regexp.MustCompile(fmt.Sprintf("Your %s can now be accessed with a browser at", what))); err != nil {
				result = false
				t.Errorf("Starter is not ready in time: %s", describe(err))
			}
		}()
	}
	g.Wait()
	if !result && os.Getenv("DEBUG_CLUSTER") == "interactive" {
		// Halt forever
		fmt.Println("Cluster not ready in time, halting forever for debugging")
		for {
			time.Sleep(time.Hour)
		}
	}
	return result
}

// SendIntrAndWait stops all all given starter processes by sending a Ctrl-C into it.
// It then waits until the process has terminated.
func SendIntrAndWait(t *testing.T, starters ...*SubProcess) bool {
	g := sync.WaitGroup{}
	result := true
	for _, starter := range starters {
		starter := starter // Used in nested function
		g.Add(1)
		go func() {
			defer g.Done()
			if err := starter.WaitTimeout(time.Second * 30); err != nil {
				result = false
				t.Errorf("Starter is not stopped in time: %s", describe(err))
			}
		}()
	}
	time.Sleep(time.Second)
	for _, starter := range starters {
		starter.SendIntr()
		//starter.Send(ctrlC)
	}
	g.Wait()
	return result
}

// describe returns a string description of the given error.
func describe(err error) string {
	if err == nil {
		return "nil"
	}
	cause := errors.Cause(err)
	c, _ := json.Marshal(cause)
	cStr := fmt.Sprintf("%#v (%s)", cause, string(c))
	if cause.Error() != err.Error() {
		return fmt.Sprintf("%v caused by %v", err, cStr)
	} else {
		return cStr
	}
}

// NewStarterClient creates a new starter API instance for the given endpoint, failing the test on errors.
func NewStarterClient(t *testing.T, endpoint string) client.API {
	ep, err := url.Parse(endpoint)
	if err != nil {
		t.Fatalf("Failed to parse starter endpoint: %s", describe(err))
	}
	c, err := client.NewArangoStarterClient(*ep)
	if err != nil {
		t.Fatalf("Failed to create starter client: %s", describe(err))
	}
	return c
}

// ShutdownStarter calls the starter the shutdown via the HTTP API.
func ShutdownStarter(t *testing.T, endpoint string) {
	c := NewStarterClient(t, endpoint)
	if err := c.Shutdown(context.Background(), false); err != nil {
		t.Errorf("Shutdown failed: %s", describe(err))
	}
	WaitUntilStarterGone(t, endpoint)
}

// WaitUntilStarterGone waits until the starter at given endpoint no longer responds to queries.
func WaitUntilStarterGone(t *testing.T, endpoint string) {
	c := NewStarterClient(t, endpoint)
	failures := 0
	for {
		if _, err := c.Version(context.Background()); err != nil {
			// Version request failed
			failures++
		} else {
			failures = 0
		}
		if failures > 2 {
			// Several failures, we assume the starter is really gone now
			break
		}
		time.Sleep(time.Millisecond * 200)
	}
}

func createEnvironmentStarterOptions() string {
	result := []string{"--starter.debug-cluster"}
	if image := os.Getenv("ARANGODB"); image != "" {
		result = append(result, fmt.Sprintf("--docker.image=%s", image))
	}
	return strings.Join(result, " ")
}
<commit_msg>Extended cluster-ready-timeout to 2min<commit_after>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package test

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/arangodb-helper/arangodb/client"
	shell "github.com/kballard/go-shellquote"
	"github.com/pkg/errors"
)

const (
	ctrlC           = "\u0003"
	whatCluster     = "cluster"
	whatSingle      = "single server"
	testModeProcess = "localprocess"
	testModeDocker  = "docker"
)

var (
	isVerbose bool
	testModes []string
)

func init() {
	isVerbose = os.Getenv("VERBOSE") != ""
	testModes = strings.Split(os.Getenv("TEST_MODES"), " ")
	if len(testModes) == 1 && testModes[0] == "" {
		testModes = nil
	}
}

func needTestMode(t *testing.T, testMode string) {
	for _, x := range testModes {
		if x == testMode {
			return
		}
	}
	if len(testModes) == 0 {
		return
	}
	t.Skipf("Test mode '%s' not set", testMode)
}

// Spawn a command an return its process.
func Spawn(t *testing.T, command string) *SubProcess {
	command = strings.TrimSpace(command)
	args, err := shell.Split(os.ExpandEnv(command))
	if err != nil {
		t.Fatal(describe(err))
	}
	if isVerbose {
		t.Log(args, len(args))
	}
	p, err := NewSubProcess(args[0], args[1:]...)
	if err != nil {
		t.Fatal(describe(err))
	}
	if err := p.Start(); err != nil {
		p.Close()
		t.Fatal(describe(err))
	}
	return p
}

// SetUniqueDataDir creates a temp dir and sets the DATA_DIR environment variable to it.
func SetUniqueDataDir(t *testing.T) string {
	dataDir, err := ioutil.TempDir("", "")
	if err != nil {
		t.Fatal(describe(err))
	}
	os.Setenv("DATA_DIR", dataDir)
	return dataDir
}

// WaitUntilStarterReady waits until all given starter processes have reached the "Your cluster is ready state"
func WaitUntilStarterReady(t *testing.T, what string, starters ...*SubProcess) bool {
	g := sync.WaitGroup{}
	result := true
	for _, starter := range starters {
		starter := starter // Used in nested function
		g.Add(1)
		go func() {
			defer g.Done()
			if err := starter.ExpectTimeout(time.Minute*2, regexp.MustCompile(fmt.Sprintf("Your %s can now be accessed with a browser at", what))); err != nil {
				result = false
				t.Errorf("Starter is not ready in time: %s", describe(err))
			}
		}()
	}
	g.Wait()
	if !result && os.Getenv("DEBUG_CLUSTER") == "interactive" {
		// Halt forever
		fmt.Println("Cluster not ready in time, halting forever for debugging")
		for {
			time.Sleep(time.Hour)
		}
	}
	return result
}

// SendIntrAndWait stops all all given starter processes by sending a Ctrl-C into it.
// It then waits until the process has terminated.
func SendIntrAndWait(t *testing.T, starters ...*SubProcess) bool {
	g := sync.WaitGroup{}
	result := true
	for _, starter := range starters {
		starter := starter // Used in nested function
		g.Add(1)
		go func() {
			defer g.Done()
			if err := starter.WaitTimeout(time.Second * 30); err != nil {
				result = false
				t.Errorf("Starter is not stopped in time: %s", describe(err))
			}
		}()
	}
	time.Sleep(time.Second)
	for _, starter := range starters {
		starter.SendIntr()
		//starter.Send(ctrlC)
	}
	g.Wait()
	return result
}

// describe returns a string description of the given error.
func describe(err error) string {
	if err == nil {
		return "nil"
	}
	cause := errors.Cause(err)
	c, _ := json.Marshal(cause)
	cStr := fmt.Sprintf("%#v (%s)", cause, string(c))
	if cause.Error() != err.Error() {
		return fmt.Sprintf("%v caused by %v", err, cStr)
	} else {
		return cStr
	}
}

// NewStarterClient creates a new starter API instance for the given endpoint, failing the test on errors.
func NewStarterClient(t *testing.T, endpoint string) client.API {
	ep, err := url.Parse(endpoint)
	if err != nil {
		t.Fatalf("Failed to parse starter endpoint: %s", describe(err))
	}
	c, err := client.NewArangoStarterClient(*ep)
	if err != nil {
		t.Fatalf("Failed to create starter client: %s", describe(err))
	}
	return c
}

// ShutdownStarter calls the starter the shutdown via the HTTP API.
func ShutdownStarter(t *testing.T, endpoint string) {
	c := NewStarterClient(t, endpoint)
	if err := c.Shutdown(context.Background(), false); err != nil {
		t.Errorf("Shutdown failed: %s", describe(err))
	}
	WaitUntilStarterGone(t, endpoint)
}

// WaitUntilStarterGone waits until the starter at given endpoint no longer responds to queries.
func WaitUntilStarterGone(t *testing.T, endpoint string) {
	c := NewStarterClient(t, endpoint)
	failures := 0
	for {
		if _, err := c.Version(context.Background()); err != nil {
			// Version request failed
			failures++
		} else {
			failures = 0
		}
		if failures > 2 {
			// Several failures, we assume the starter is really gone now
			break
		}
		time.Sleep(time.Millisecond * 200)
	}
}

func createEnvironmentStarterOptions() string {
	result := []string{"--starter.debug-cluster"}
	if image := os.Getenv("ARANGODB"); image != "" {
		result = append(result, fmt.Sprintf("--docker.image=%s", image))
	}
	return strings.Join(result, " ")
}
<|endoftext|>


<commit_before>package common

import (
	crand "crypto/rand"
	"encoding/hex"
	"math/rand"
	"time"
)

const (
	strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
)

func init() {
	// Seed math/rand with "secure" int64
	b := CRandBytes(8)
	var seed uint64
	for i := 0; i < 8; i++ {
		seed |= uint64(b[i])
		seed <<= 8
	}
	rand.Seed(int64(seed))
}

// Constructs an alphanumeric string of given length.
func RandStr(length int) string {
	chars := []byte{}
MAIN_LOOP:
	for {
		val := rand.Int63()
		for i := 0; i < 10; i++ {
			v := int(val & 0x3f) // rightmost 6 bits
			if v >= 62 {         // only 62 characters in strChars
				val >>= 6
				continue
			} else {
				chars = append(chars, strChars[v])
				if len(chars) == length {
					break MAIN_LOOP
				}
				val >>= 6
			}
		}
	}

	return string(chars)
}

func RandUint16() uint16 {
	return uint16(rand.Uint32() & (1<<16 - 1))
}

func RandUint32() uint32 {
	return rand.Uint32()
}

func RandUint64() uint64 {
	return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
}

func RandUint() uint {
	return uint(rand.Int())
}

func RandInt16() int16 {
	return int16(rand.Uint32() & (1<<16 - 1))
}

func RandInt32() int32 {
	return int32(rand.Uint32())
}

func RandInt64() int64 {
	return int64(rand.Uint32())<<32 + int64(rand.Uint32())
}

func RandInt() int {
	return rand.Int()
}

// Distributed pseudo-exponentially to test for various cases
func RandUint16Exp() uint16 {
	bits := rand.Uint32() % 16
	if bits == 0 {
		return 0
	}
	n := uint16(1 << (bits - 1))
	n += uint16(rand.Int31()) & ((1 << (bits - 1)) - 1)
	return n
}

// Distributed pseudo-exponentially to test for various cases
func RandUint32Exp() uint32 {
	bits := rand.Uint32() % 32
	if bits == 0 {
		return 0
	}
	n := uint32(1 << (bits - 1))
	n += uint32(rand.Int31()) & ((1 << (bits - 1)) - 1)
	return n
}

// Distributed pseudo-exponentially to test for various cases
func RandUint64Exp() uint64 {
	bits := rand.Uint32() % 64
	if bits == 0 {
		return 0
	}
	n := uint64(1 << (bits - 1))
	n += uint64(rand.Int63()) & ((1 << (bits - 1)) - 1)
	return n
}

func RandFloat32() float32 {
	return rand.Float32()
}

func RandTime() time.Time {
	return time.Unix(int64(RandUint64Exp()), 0)
}

func RandBytes(n int) []byte {
	bs := make([]byte, n)
	for i := 0; i < n; i++ {
		bs[i] = byte(rand.Intn(256))
	}
	return bs
}

//-----------------------------------------------------------------------------
// CRand* methods are crypto safe.

func CRandBytes(numBytes int) []byte {
	b := make([]byte, numBytes)
	_, err := crand.Read(b)
	if err != nil {
		PanicCrisis(err)
	}
	return b
}

// RandHex(24) gives 96 bits of randomness, strong enough for most purposes.
func CRandHex(numDigits int) string {
	return hex.EncodeToString(CRandBytes(numDigits / 2))
}
<commit_msg>Remove CRand* from go-common<commit_after>package common

import (
	crand "crypto/rand"
	"math/rand"
	"time"
)

const (
	strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
)

func init() {
	b := cRandBytes(8)
	var seed uint64
	for i := 0; i < 8; i++ {
		seed |= uint64(b[i])
		seed <<= 8
	}
	rand.Seed(int64(seed))
}

// Constructs an alphanumeric string of given length.
func RandStr(length int) string {
	chars := []byte{}
MAIN_LOOP:
	for {
		val := rand.Int63()
		for i := 0; i < 10; i++ {
			v := int(val & 0x3f) // rightmost 6 bits
			if v >= 62 {         // only 62 characters in strChars
				val >>= 6
				continue
			} else {
				chars = append(chars, strChars[v])
				if len(chars) == length {
					break MAIN_LOOP
				}
				val >>= 6
			}
		}
	}

	return string(chars)
}

func RandUint16() uint16 {
	return uint16(rand.Uint32() & (1<<16 - 1))
}

func RandUint32() uint32 {
	return rand.Uint32()
}

func RandUint64() uint64 {
	return uint64(rand.Uint32())<<32 + uint64(rand.Uint32())
}

func RandUint() uint {
	return uint(rand.Int())
}

func RandInt16() int16 {
	return int16(rand.Uint32() & (1<<16 - 1))
}

func RandInt32() int32 {
	return int32(rand.Uint32())
}

func RandInt64() int64 {
	return int64(rand.Uint32())<<32 + int64(rand.Uint32())
}

func RandInt() int {
	return rand.Int()
}

// Distributed pseudo-exponentially to test for various cases
func RandUint16Exp() uint16 {
	bits := rand.Uint32() % 16
	if bits == 0 {
		return 0
	}
	n := uint16(1 << (bits - 1))
	n += uint16(rand.Int31()) & ((1 << (bits - 1)) - 1)
	return n
}

// Distributed pseudo-exponentially to test for various cases
func RandUint32Exp() uint32 {
	bits := rand.Uint32() % 32
	if bits == 0 {
		return 0
	}
	n := uint32(1 << (bits - 1))
	n += uint32(rand.Int31()) & ((1 << (bits - 1)) - 1)
	return n
}

// Distributed pseudo-exponentially to test for various cases
func RandUint64Exp() uint64 {
	bits := rand.Uint32() % 64
	if bits == 0 {
		return 0
	}
	n := uint64(1 << (bits - 1))
	n += uint64(rand.Int63()) & ((1 << (bits - 1)) - 1)
	return n
}

func RandFloat32() float32 {
	return rand.Float32()
}

func RandTime() time.Time {
	return time.Unix(int64(RandUint64Exp()), 0)
}

func RandBytes(n int) []byte {
	bs := make([]byte, n)
	for i := 0; i < n; i++ {
		bs[i] = byte(rand.Intn(256))
	}
	return bs
}

// NOTE: This relies on the os's random number generator.
// For real security, we should salt that with some seed.
// See github.com/tendermint/go-crypto for a more secure reader.
func cRandBytes(numBytes int) []byte {
	b := make([]byte, numBytes)
	_, err := crand.Read(b)
	if err != nil {
		PanicCrisis(err)
	}
	return b
}
<|endoftext|>


<commit_before>package fixity

import (
	"io"
	"os"
)

const (
	// DefaultAverageChunkSize that the chunker will attempt to produce.
	//
	// See WriteRequest.AverageChunkSize documentation for further explanation
	// of chunk sizes.
	//
	// This value is 1024^2*4 bytes, 4MiB, chosen as a compromise for the
	// small and large files.
	//
	// Ideally it should strike a balance between too many chunks written while
	// still mitigating data duplication caused by frequent changes to files
	// and written data.
	//
	// If written data is commonly editing the first X bytes, this value should
	// be overridden in the WriteRequest itself.
	DefaultAverageChunkSize uint64 = 4194304

	// autoChunkCount is the number of chunks SetRollFromBytes/etc will set to.
	//
	// Eg, if SetRollFromBytes is given a byte array that is 1,048,576 bytes,
	// then it will divide 1,048,576 by eg, 10 to set the rollSize to
	// 104,857, effectively rolling the bytes into 10 parts when it's written.
	autoChunkCount = 6

	minAutoChunkSize = 12288
	maxAutoChunkSize = 1073741824
)

// WriteRequest represents a blob to be written alone with metadata.
type WriteRequest struct {
	Id       string
	RollSize uint64
	Fields   Fields
	Blob     io.ReadCloser
}

// NewWrite creates a new WriteRequest to be used with Fixity.WriteRequest.
func NewWrite(id string, rc io.ReadCloser, f ...Field) *WriteRequest {
	return &WriteRequest{
		Id:       id,
		RollSize: DefaultAverageChunkSize,
		Fields:   f,
		Blob:     rc,
	}
}

func (req *WriteRequest) setRollSizeWithMin(roll uint64) {
	if roll < minAutoChunkSize {
		roll = minAutoChunkSize
	}
	if roll > maxAutoChunkSize {
		roll = maxAutoChunkSize
	}
	req.RollSize = roll
}

func (req *WriteRequest) SetRollFromBytes(b []byte) {
	req.setRollSizeWithMin(uint64(len(b)) / autoChunkCount)
}

func (req *WriteRequest) SetRollFromFileInfo(fi os.FileInfo) {
	req.setRollSizeWithMin(uint64(fi.Size()) / autoChunkCount)
}
<commit_msg>refactor: renamed setRollSize method<commit_after>package fixity

import (
	"io"
	"os"
)

const (
	// DefaultAverageChunkSize that the chunker will attempt to produce.
	//
	// See WriteRequest.AverageChunkSize documentation for further explanation
	// of chunk sizes.
	//
	// This value is 1024^2*4 bytes, 4MiB, chosen as a compromise for the
	// small and large files.
	//
	// Ideally it should strike a balance between too many chunks written while
	// still mitigating data duplication caused by frequent changes to files
	// and written data.
	//
	// If written data is commonly editing the first X bytes, this value should
	// be overridden in the WriteRequest itself.
	DefaultAverageChunkSize uint64 = 4194304

	// autoChunkCount is the number of chunks SetRollFromBytes/etc will set to.
	//
	// Eg, if SetRollFromBytes is given a byte array that is 1,048,576 bytes,
	// then it will divide 1,048,576 by eg, 10 to set the rollSize to
	// 104,857, effectively rolling the bytes into 10 parts when it's written.
	autoChunkCount = 6

	minAutoChunkSize = 12288
	maxAutoChunkSize = 1073741824
)

// WriteRequest represents a blob to be written alone with metadata.
type WriteRequest struct {
	Id       string
	RollSize uint64
	Fields   Fields
	Blob     io.ReadCloser
}

// NewWrite creates a new WriteRequest to be used with Fixity.WriteRequest.
func NewWrite(id string, rc io.ReadCloser, f ...Field) *WriteRequest {
	return &WriteRequest{
		Id:       id,
		RollSize: DefaultAverageChunkSize,
		Fields:   f,
		Blob:     rc,
	}
}

func (req *WriteRequest) setRollSize(roll uint64) {
	if roll < minAutoChunkSize {
		roll = minAutoChunkSize
	}
	if roll > maxAutoChunkSize {
		roll = maxAutoChunkSize
	}
	req.RollSize = roll
}

func (req *WriteRequest) SetRollFromBytes(b []byte) {
	req.setRollSize(uint64(len(b)) / autoChunkCount)
}

func (req *WriteRequest) SetRollFromFileInfo(fi os.FileInfo) {
	req.setRollSize(uint64(fi.Size()) / autoChunkCount)
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package siv_test

import (
	"github.com/jacobsa/aes/siv"
	aes_testing "github.com/jacobsa/aes/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

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

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DecryptTest struct{}

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

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

func (t *DecryptTest) NilKey() {
	key := []byte(nil)
	ciphertext := []byte{}

	_, err := siv.Decrypt(key, ciphertext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *DecryptTest) ShortKey() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) LongKey() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) NilCiphertext() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) ShortCiphertext() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) TooMuchAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) JustLittleEnoughAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) DoesntClobberAssociatedSlice() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) WrongKey() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) Rfc5297TestCaseA1() {
	key := aes_testing.FromRfcHex(
		"fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0" +
		"f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff")

	ciphertext := aes_testing.FromRfcHex(
		"85632d07 c6e8f37f 950acd32 0a2ecc93" +
		"40c02b96 90c4dc04 daef7f6a fe5c")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"10111213 14151617 18191a1b 1c1d1e1f" +
			"20212223 24252627"),
	}

	expected := aes_testing.FromRfcHex(
		"11223344 55667788 99aabbcc ddee")

	output, err := siv.Decrypt(key, ciphertext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *DecryptTest) Rfc5297TestCaseA2() {
	key := aes_testing.FromRfcHex(
		"7f7e7d7c 7b7a7978 77767574 73727170" +
		"40414243 44454647 48494a4b 4c4d4e4f")

	ciphertext := aes_testing.FromRfcHex(
		"7bdb6e3b 432667eb 06f4d14b ff2fbd0f" +
		"cb900f2f ddbe4043 26601965 c889bf17" +
		"dba77ceb 094fa663 b7a3f748 ba8af829" +
		"ea64ad54 4a272e9c 485b62a3 fd5c0d")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"00112233 44556677 8899aabb ccddeeff" +
			"deaddada deaddada ffeeddcc bbaa9988" +
			"77665544 33221100"),
		aes_testing.FromRfcHex(
			"10203040 50607080 90a0"),
		aes_testing.FromRfcHex(
			"09f91102 9d74e35b d84156c5 635688c0"),
	}

	expected := aes_testing.FromRfcHex(
		"74686973 20697320 736f6d65 20706c61" +
		"696e7465 78742074 6f20656e 63727970" +
		"74207573 696e6720 5349562d 414553")

	output, err := siv.Decrypt(key, ciphertext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *DecryptTest) GeneratedTestCases() {
	ExpectEq("TODO", "")
}
<commit_msg>DecryptTest.LongKey<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package siv_test

import (
	"github.com/jacobsa/aes/siv"
	aes_testing "github.com/jacobsa/aes/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

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

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DecryptTest struct{}

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

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

func (t *DecryptTest) NilKey() {
	key := []byte(nil)
	ciphertext := []byte{}

	_, err := siv.Decrypt(key, ciphertext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *DecryptTest) ShortKey() {
	key := make([]byte, 31)
	ciphertext := []byte{}

	_, err := siv.Decrypt(key, ciphertext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *DecryptTest) LongKey() {
	key := make([]byte, 65)
	ciphertext := []byte{}

	_, err := siv.Decrypt(key, ciphertext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *DecryptTest) NilCiphertext() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) ShortCiphertext() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) TooMuchAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) JustLittleEnoughAssociatedData() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) DoesntClobberAssociatedSlice() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) WrongKey() {
	ExpectEq("TODO", "")
}

func (t *DecryptTest) Rfc5297TestCaseA1() {
	key := aes_testing.FromRfcHex(
		"fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0" +
		"f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff")

	ciphertext := aes_testing.FromRfcHex(
		"85632d07 c6e8f37f 950acd32 0a2ecc93" +
		"40c02b96 90c4dc04 daef7f6a fe5c")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"10111213 14151617 18191a1b 1c1d1e1f" +
			"20212223 24252627"),
	}

	expected := aes_testing.FromRfcHex(
		"11223344 55667788 99aabbcc ddee")

	output, err := siv.Decrypt(key, ciphertext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *DecryptTest) Rfc5297TestCaseA2() {
	key := aes_testing.FromRfcHex(
		"7f7e7d7c 7b7a7978 77767574 73727170" +
		"40414243 44454647 48494a4b 4c4d4e4f")

	ciphertext := aes_testing.FromRfcHex(
		"7bdb6e3b 432667eb 06f4d14b ff2fbd0f" +
		"cb900f2f ddbe4043 26601965 c889bf17" +
		"dba77ceb 094fa663 b7a3f748 ba8af829" +
		"ea64ad54 4a272e9c 485b62a3 fd5c0d")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"00112233 44556677 8899aabb ccddeeff" +
			"deaddada deaddada ffeeddcc bbaa9988" +
			"77665544 33221100"),
		aes_testing.FromRfcHex(
			"10203040 50607080 90a0"),
		aes_testing.FromRfcHex(
			"09f91102 9d74e35b d84156c5 635688c0"),
	}

	expected := aes_testing.FromRfcHex(
		"74686973 20697320 736f6d65 20706c61" +
		"696e7465 78742074 6f20656e 63727970" +
		"74207573 696e6720 5349562d 414553")

	output, err := siv.Decrypt(key, ciphertext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *DecryptTest) GeneratedTestCases() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package siv_test

import (
	"github.com/jacobsa/crypto/siv"
	aes_testing "github.com/jacobsa/crypto/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

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

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type EncryptTest struct{}

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

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

func (t *EncryptTest) NilKey() {
	key := []byte(nil)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) ShortKey() {
	key := make([]byte, 31)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) LongKey() {
	key := make([]byte, 65)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) TooMuchAssociatedData() {
	key := make([]byte, 64)
	plaintext := []byte{}
	associated := make([][]byte, 127)

	_, err := siv.Encrypt(key, plaintext, associated)
	ExpectThat(err, Error(HasSubstr("associated")))
	ExpectThat(err, Error(HasSubstr("126")))
}

func (t *EncryptTest) JustLittleEnoughAssociatedData() {
	key := make([]byte, 64)
	plaintext := []byte{}
	associated := make([][]byte, 126)

	_, err := siv.Encrypt(key, plaintext, associated)
	ExpectEq(nil, err)
}

func (t *EncryptTest) DoesntClobberAssociatedSlice() {
	key := make([]byte, 32)
	plaintext := []byte{}

	associated0 := aes_testing.FromRfcHex("deadbeef")
	associated1 := aes_testing.FromRfcHex("feedface")
	associated2 := aes_testing.FromRfcHex("ba5eba11")
	associated := [][]byte{associated0, associated1, associated2}

	// Call with a slice of associated missing the last element. The last element
	// shouldn't be clobbered.
	_, err := siv.Encrypt(key, plaintext, associated[:2])
	AssertEq(nil, err)

	ExpectThat(
		associated,
		ElementsAre(
			DeepEquals(associated0),
			DeepEquals(associated1),
			DeepEquals(associated2),
		))
}

func (t *EncryptTest) OutputIsDeterministic() {
	cases := aes_testing.EncryptCases()
	AssertGt(len(cases), 37)
	c := cases[37]

	output0, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	output1, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	output2, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	AssertGt(len(output0), 0)
	ExpectThat(output0, DeepEquals(output1))
	ExpectThat(output0, DeepEquals(output2))
}

func (t *EncryptTest) Rfc5297TestCaseA1() {
	key := aes_testing.FromRfcHex(
		"fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0" +
			"f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff")

	plaintext := aes_testing.FromRfcHex(
		"11223344 55667788 99aabbcc ddee")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"10111213 14151617 18191a1b 1c1d1e1f" +
				"20212223 24252627"),
	}

	expected := aes_testing.FromRfcHex(
		"85632d07 c6e8f37f 950acd32 0a2ecc93" +
			"40c02b96 90c4dc04 daef7f6a fe5c")

	output, err := siv.Encrypt(key, plaintext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *EncryptTest) Rfc5297TestCaseA2() {
	key := aes_testing.FromRfcHex(
		"7f7e7d7c 7b7a7978 77767574 73727170" +
			"40414243 44454647 48494a4b 4c4d4e4f")

	plaintext := aes_testing.FromRfcHex(
		"74686973 20697320 736f6d65 20706c61" +
			"696e7465 78742074 6f20656e 63727970" +
			"74207573 696e6720 5349562d 414553")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"00112233 44556677 8899aabb ccddeeff" +
				"deaddada deaddada ffeeddcc bbaa9988" +
				"77665544 33221100"),
		aes_testing.FromRfcHex(
			"10203040 50607080 90a0"),
		aes_testing.FromRfcHex(
			"09f91102 9d74e35b d84156c5 635688c0"),
	}

	expected := aes_testing.FromRfcHex(
		"7bdb6e3b 432667eb 06f4d14b ff2fbd0f" +
			"cb900f2f ddbe4043 26601965 c889bf17" +
			"dba77ceb 094fa663 b7a3f748 ba8af829" +
			"ea64ad54 4a272e9c 485b62a3 fd5c0d")

	output, err := siv.Encrypt(key, plaintext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *EncryptTest) GeneratedTestCases() {
	cases := aes_testing.EncryptCases()
	AssertGe(len(cases), 100)

	for i, c := range cases {
		output, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
		AssertEq(nil, err, "Case %d: %v", i, c)
		ExpectThat(output, DeepEquals(c.Output), "Case %d: %v", i, c)
	}
}
<commit_msg>Encryption, too.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package siv_test

import (
	"crypto/rand"
	"testing"

	"github.com/jacobsa/crypto/siv"
	aes_testing "github.com/jacobsa/crypto/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

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

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type EncryptTest struct{}

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

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

func (t *EncryptTest) NilKey() {
	key := []byte(nil)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) ShortKey() {
	key := make([]byte, 31)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) LongKey() {
	key := make([]byte, 65)
	plaintext := []byte{}

	_, err := siv.Encrypt(key, plaintext, nil)
	ExpectThat(err, Error(HasSubstr("-byte")))
}

func (t *EncryptTest) TooMuchAssociatedData() {
	key := make([]byte, 64)
	plaintext := []byte{}
	associated := make([][]byte, 127)

	_, err := siv.Encrypt(key, plaintext, associated)
	ExpectThat(err, Error(HasSubstr("associated")))
	ExpectThat(err, Error(HasSubstr("126")))
}

func (t *EncryptTest) JustLittleEnoughAssociatedData() {
	key := make([]byte, 64)
	plaintext := []byte{}
	associated := make([][]byte, 126)

	_, err := siv.Encrypt(key, plaintext, associated)
	ExpectEq(nil, err)
}

func (t *EncryptTest) DoesntClobberAssociatedSlice() {
	key := make([]byte, 32)
	plaintext := []byte{}

	associated0 := aes_testing.FromRfcHex("deadbeef")
	associated1 := aes_testing.FromRfcHex("feedface")
	associated2 := aes_testing.FromRfcHex("ba5eba11")
	associated := [][]byte{associated0, associated1, associated2}

	// Call with a slice of associated missing the last element. The last element
	// shouldn't be clobbered.
	_, err := siv.Encrypt(key, plaintext, associated[:2])
	AssertEq(nil, err)

	ExpectThat(
		associated,
		ElementsAre(
			DeepEquals(associated0),
			DeepEquals(associated1),
			DeepEquals(associated2),
		))
}

func (t *EncryptTest) OutputIsDeterministic() {
	cases := aes_testing.EncryptCases()
	AssertGt(len(cases), 37)
	c := cases[37]

	output0, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	output1, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	output2, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
	AssertEq(nil, err)

	AssertGt(len(output0), 0)
	ExpectThat(output0, DeepEquals(output1))
	ExpectThat(output0, DeepEquals(output2))
}

func (t *EncryptTest) Rfc5297TestCaseA1() {
	key := aes_testing.FromRfcHex(
		"fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0" +
			"f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff")

	plaintext := aes_testing.FromRfcHex(
		"11223344 55667788 99aabbcc ddee")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"10111213 14151617 18191a1b 1c1d1e1f" +
				"20212223 24252627"),
	}

	expected := aes_testing.FromRfcHex(
		"85632d07 c6e8f37f 950acd32 0a2ecc93" +
			"40c02b96 90c4dc04 daef7f6a fe5c")

	output, err := siv.Encrypt(key, plaintext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *EncryptTest) Rfc5297TestCaseA2() {
	key := aes_testing.FromRfcHex(
		"7f7e7d7c 7b7a7978 77767574 73727170" +
			"40414243 44454647 48494a4b 4c4d4e4f")

	plaintext := aes_testing.FromRfcHex(
		"74686973 20697320 736f6d65 20706c61" +
			"696e7465 78742074 6f20656e 63727970" +
			"74207573 696e6720 5349562d 414553")

	associated := [][]byte{
		aes_testing.FromRfcHex(
			"00112233 44556677 8899aabb ccddeeff" +
				"deaddada deaddada ffeeddcc bbaa9988" +
				"77665544 33221100"),
		aes_testing.FromRfcHex(
			"10203040 50607080 90a0"),
		aes_testing.FromRfcHex(
			"09f91102 9d74e35b d84156c5 635688c0"),
	}

	expected := aes_testing.FromRfcHex(
		"7bdb6e3b 432667eb 06f4d14b ff2fbd0f" +
			"cb900f2f ddbe4043 26601965 c889bf17" +
			"dba77ceb 094fa663 b7a3f748 ba8af829" +
			"ea64ad54 4a272e9c 485b62a3 fd5c0d")

	output, err := siv.Encrypt(key, plaintext, associated)
	AssertEq(nil, err)
	ExpectThat(output, DeepEquals(expected))
}

func (t *EncryptTest) GeneratedTestCases() {
	cases := aes_testing.EncryptCases()
	AssertGe(len(cases), 100)

	for i, c := range cases {
		output, err := siv.Encrypt(c.Key, c.Plaintext, c.Associated)
		AssertEq(nil, err, "Case %d: %v", i, c)
		ExpectThat(output, DeepEquals(c.Output), "Case %d: %v", i, c)
	}
}

////////////////////////////////////////////////////////////////////////
// Benchmarks
////////////////////////////////////////////////////////////////////////

func benchmarkEncrypt(
	b *testing.B,
	size int) {
	var err error

	// Generate the appropriate amount of random data.
	plaintext := make([]byte, size)
	_, err = rand.Read(plaintext)
	if err != nil {
		b.Fatalf("rand.Read: %v", err)
	}

	// Create a random key.
	const keyLen = 32
	key := make([]byte, keyLen)

	_, err = rand.Read(key)
	if err != nil {
		b.Fatalf("rand.Read: %v", err)
	}

	// Repeatedly encrypt.
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, err = siv.Encrypt(key, plaintext, nil)
		if err != nil {
			b.Fatalf("Encrypt: %v", err)
		}
	}

	b.SetBytes(int64(size))
}

func BenchmarkEncrypt1KiB(b *testing.B) {
	const size = 1 << 10
	benchmarkEncrypt(b, size)
}

func BenchmarkEncrypt1MiB(b *testing.B) {
	const size = 1 << 20
	benchmarkEncrypt(b, size)
}

func BenchmarkEncrypt16MiB(b *testing.B) {
	const size = 1 << 24
	benchmarkEncrypt(b, size)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package openstack

import (
	"errors"
	"fmt"
	"net/url"

	"github.com/golang/glog"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/kubernetes/pkg/cloudprovider"
)

type Instances struct {
	compute *gophercloud.ServiceClient
}

// Instances returns an implementation of Instances for OpenStack.
func (os *OpenStack) Instances() (cloudprovider.Instances, bool) {
	glog.V(4).Info("openstack.Instances() called")

	compute, err := os.NewComputeV2()
	if err != nil {
		return nil, false
	}

	glog.V(1).Info("Claiming to support Instances")

	return &Instances{compute}, true
}

// Implementation of Instances.CurrentNodeName
// Note this is *not* necessarily the same as hostname.
func (i *Instances) CurrentNodeName(hostname string) (types.NodeName, error) {
	md, err := getMetadata()
	if err != nil {
		return "", err
	}
	return types.NodeName(md.Name), nil
}

func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error {
	return errors.New("unimplemented")
}

func (i *Instances) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) {
	glog.V(4).Infof("NodeAddresses(%v) called", name)

	addrs, err := getAddressesByName(i.compute, name)
	if err != nil {
		return nil, err
	}

	glog.V(4).Infof("NodeAddresses(%v) => %v", name, addrs)
	return addrs, nil
}

// NodeAddressesByProviderID returns the node addresses of an instances with the specified unique providerID
// This method will not be called from the node that is requesting this ID. i.e. metadata service
// and other local methods cannot be used here
func (i *Instances) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) {
	instanceID, err := instanceIDFromProviderID(providerID)

	if err != nil {
		return []v1.NodeAddress{}, err
	}

	server, err := servers.Get(i.compute, instanceID).Extract()

	if err != nil {
		return []v1.NodeAddress{}, err
	}

	addresses, err := nodeAddresses(server)
	if err != nil {
		return []v1.NodeAddress{}, err
	}

	return addresses, nil
}

// ExternalID returns the cloud provider ID of the specified instance (deprecated).
func (i *Instances) ExternalID(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)
	if err != nil {
		if err == ErrNotFound {
			return "", cloudprovider.InstanceNotFound
		}
		return "", err
	}
	return srv.ID, nil
}

// InstanceID returns the kubelet's cloud provider ID.
func (os *OpenStack) InstanceID() (string, error) {
	if len(os.localInstanceID) == 0 {
		id, err := readInstanceID()
		if err != nil {
			return "", err
		}
		os.localInstanceID = id
	}
	return os.localInstanceID, nil
}

// InstanceID returns the cloud provider ID of the specified instance.
func (i *Instances) InstanceID(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)
	if err != nil {
		if err == ErrNotFound {
			return "", cloudprovider.InstanceNotFound
		}
		return "", err
	}
	// In the future it is possible to also return an endpoint as:
	// <endpoint>/<instanceid>
	return "/" + srv.ID, nil
}

// InstanceTypeByProviderID returns the cloudprovider instance type of the node with the specified unique providerID
// This method will not be called from the node that is requesting this ID. i.e. metadata service
// and other local methods cannot be used here
func (i *Instances) InstanceTypeByProviderID(providerID string) (string, error) {
	instanceID, err := instanceIDFromProviderID(providerID)

	if err != nil {
		return "", err
	}

	server, err := servers.Get(i.compute, instanceID).Extract()

	if err != nil {
		return "", err
	}

	return srvInstanceType(server)
}

// InstanceType returns the type of the specified instance.
func (i *Instances) InstanceType(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)

	if err != nil {
		return "", err
	}

	return srvInstanceType(srv)
}

func srvInstanceType(srv *servers.Server) (string, error) {
	keys := []string{"name", "id", "original_name"}
	for _, key := range keys {
		val, found := srv.Flavor[key]
		if found {
			flavor, ok := val.(string)
			if ok {
				return flavor, nil
			}
		}
	}
	return "", fmt.Errorf("flavor name/id not found")
}

func instanceIDFromProviderID(providerID string) (instanceID string, err error) {
	parsedID, err := url.Parse(providerID)
	if err != nil {
		return "", err
	}
	if parsedID.Scheme != ProviderName {
		return "", fmt.Errorf("unrecognized provider %q", parsedID.Scheme)
	}

	return parsedID.Host, nil
}
<commit_msg>Add InstanceExists* methods to cloud provider interface for CCM<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package openstack

import (
	"errors"
	"fmt"
	"net/url"

	"github.com/golang/glog"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"

	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/kubernetes/pkg/cloudprovider"
)

type Instances struct {
	compute *gophercloud.ServiceClient
}

// Instances returns an implementation of Instances for OpenStack.
func (os *OpenStack) Instances() (cloudprovider.Instances, bool) {
	glog.V(4).Info("openstack.Instances() called")

	compute, err := os.NewComputeV2()
	if err != nil {
		return nil, false
	}

	glog.V(1).Info("Claiming to support Instances")

	return &Instances{compute}, true
}

// Implementation of Instances.CurrentNodeName
// Note this is *not* necessarily the same as hostname.
func (i *Instances) CurrentNodeName(hostname string) (types.NodeName, error) {
	md, err := getMetadata()
	if err != nil {
		return "", err
	}
	return types.NodeName(md.Name), nil
}

func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error {
	return errors.New("unimplemented")
}

func (i *Instances) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) {
	glog.V(4).Infof("NodeAddresses(%v) called", name)

	addrs, err := getAddressesByName(i.compute, name)
	if err != nil {
		return nil, err
	}

	glog.V(4).Infof("NodeAddresses(%v) => %v", name, addrs)
	return addrs, nil
}

// NodeAddressesByProviderID returns the node addresses of an instances with the specified unique providerID
// This method will not be called from the node that is requesting this ID. i.e. metadata service
// and other local methods cannot be used here
func (i *Instances) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) {
	instanceID, err := instanceIDFromProviderID(providerID)

	if err != nil {
		return []v1.NodeAddress{}, err
	}

	server, err := servers.Get(i.compute, instanceID).Extract()

	if err != nil {
		return []v1.NodeAddress{}, err
	}

	addresses, err := nodeAddresses(server)
	if err != nil {
		return []v1.NodeAddress{}, err
	}

	return addresses, nil
}

// ExternalID returns the cloud provider ID of the specified instance (deprecated).
func (i *Instances) ExternalID(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)
	if err != nil {
		if err == ErrNotFound {
			return "", cloudprovider.InstanceNotFound
		}
		return "", err
	}
	return srv.ID, nil
}

// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
func (i *Instances) InstanceExistsByProviderID(providerID string) (bool, error) {
	return false, errors.New("unimplemented")
}

// InstanceID returns the kubelet's cloud provider ID.
func (os *OpenStack) InstanceID() (string, error) {
	if len(os.localInstanceID) == 0 {
		id, err := readInstanceID()
		if err != nil {
			return "", err
		}
		os.localInstanceID = id
	}
	return os.localInstanceID, nil
}

// InstanceID returns the cloud provider ID of the specified instance.
func (i *Instances) InstanceID(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)
	if err != nil {
		if err == ErrNotFound {
			return "", cloudprovider.InstanceNotFound
		}
		return "", err
	}
	// In the future it is possible to also return an endpoint as:
	// <endpoint>/<instanceid>
	return "/" + srv.ID, nil
}

// InstanceTypeByProviderID returns the cloudprovider instance type of the node with the specified unique providerID
// This method will not be called from the node that is requesting this ID. i.e. metadata service
// and other local methods cannot be used here
func (i *Instances) InstanceTypeByProviderID(providerID string) (string, error) {
	instanceID, err := instanceIDFromProviderID(providerID)

	if err != nil {
		return "", err
	}

	server, err := servers.Get(i.compute, instanceID).Extract()

	if err != nil {
		return "", err
	}

	return srvInstanceType(server)
}

// InstanceType returns the type of the specified instance.
func (i *Instances) InstanceType(name types.NodeName) (string, error) {
	srv, err := getServerByName(i.compute, name)

	if err != nil {
		return "", err
	}

	return srvInstanceType(srv)
}

func srvInstanceType(srv *servers.Server) (string, error) {
	keys := []string{"name", "id", "original_name"}
	for _, key := range keys {
		val, found := srv.Flavor[key]
		if found {
			flavor, ok := val.(string)
			if ok {
				return flavor, nil
			}
		}
	}
	return "", fmt.Errorf("flavor name/id not found")
}

func instanceIDFromProviderID(providerID string) (instanceID string, err error) {
	parsedID, err := url.Parse(providerID)
	if err != nil {
		return "", err
	}
	if parsedID.Scheme != ProviderName {
		return "", fmt.Errorf("unrecognized provider %q", parsedID.Scheme)
	}

	return parsedID.Host, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base"

	"vitess.io/vitess/go/test/endtoend/cluster"

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

var (
	clusterInstance *cluster.LocalProcessCluster
	masterTablet    cluster.Vttablet
	replicaTablet   cluster.Vttablet
	hostname        = "localhost"
	keyspaceName    = "ks"
	cell            = "zone1"
	sqlSchema       = `
	create table t1(
		id bigint,
		value varchar(16),
		primary key(id)
	) Engine=InnoDB;
`

	vSchema = `
	{
    "sharded": true,
    "vindexes": {
      "hash": {
        "type": "hash"
      }
    },
    "tables": {
      "t1": {
        "column_vindexes": [
          {
            "column": "id",
            "name": "hash"
          }
        ]
      }
    }
	}`

	httpClient   = base.SetupHTTPClient(time.Second)
	checkAPIPath = "throttler/check"
)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		err := clusterInstance.StartTopo()
		if err != nil {
			return 1
		}

		// Set extra tablet args for lock timeout
		clusterInstance.VtTabletExtraArgs = []string{
			"-lock_tables_timeout", "5s",
			"-watch_replication_stream",
			"-enable_replication_reporter",
		}
		// We do not need semiSync for this test case.
		clusterInstance.EnableSemiSync = false

		// Start keyspace
		keyspace := &cluster.Keyspace{
			Name:      keyspaceName,
			SchemaSQL: sqlSchema,
			VSchema:   vSchema,
		}

		if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil {
			return 1
		}

		// Collect table paths and ports
		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
		for _, tablet := range tablets {
			if tablet.Type == "master" {
				masterTablet = *tablet
			} else if tablet.Type != "rdonly" {
				replicaTablet = *tablet
			}
		}

		return m.Run()
	}()
	os.Exit(exitCode)
}

func TestThrottlerBeforeMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	// Immediately after startup, we expect this response:
	// {"StatusCode":404,"Value":0,"Threshold":0,"Message":"No such metric"}
	resp, err := httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", masterTablet.HTTPPort, checkAPIPath))
	assert.NoError(t, err)
	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

func TestThrottlerAfterMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	time.Sleep(10 * time.Second)
	// By this time metrics will have been collected. We expect no lag, and something like:
	// {"StatusCode":200,"Value":0.282278,"Threshold":1,"Message":""}
	resp, err := httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", masterTablet.HTTPPort, checkAPIPath))
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
}
<commit_msg>test no hosts, test restoring hosts<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"testing"
	"time"

	"vitess.io/vitess/go/vt/vttablet/tabletserver/throttle/base"

	"vitess.io/vitess/go/test/endtoend/cluster"

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

var (
	clusterInstance *cluster.LocalProcessCluster
	masterTablet    cluster.Vttablet
	replicaTablet   cluster.Vttablet
	hostname        = "localhost"
	keyspaceName    = "ks"
	cell            = "zone1"
	sqlSchema       = `
	create table t1(
		id bigint,
		value varchar(16),
		primary key(id)
	) Engine=InnoDB;
`

	vSchema = `
	{
    "sharded": true,
    "vindexes": {
      "hash": {
        "type": "hash"
      }
    },
    "tables": {
      "t1": {
        "column_vindexes": [
          {
            "column": "id",
            "name": "hash"
          }
        ]
      }
    }
	}`

	httpClient   = base.SetupHTTPClient(time.Second)
	checkAPIPath = "throttler/check"
)

func TestMain(m *testing.M) {
	defer cluster.PanicHandler(nil)
	flag.Parse()

	exitCode := func() int {
		clusterInstance = cluster.NewCluster(cell, hostname)
		defer clusterInstance.Teardown()

		// Start topo server
		err := clusterInstance.StartTopo()
		if err != nil {
			return 1
		}

		// Set extra tablet args for lock timeout
		clusterInstance.VtTabletExtraArgs = []string{
			"-lock_tables_timeout", "5s",
			"-watch_replication_stream",
			"-enable_replication_reporter",
		}
		// We do not need semiSync for this test case.
		clusterInstance.EnableSemiSync = false

		// Start keyspace
		keyspace := &cluster.Keyspace{
			Name:      keyspaceName,
			SchemaSQL: sqlSchema,
			VSchema:   vSchema,
		}

		if err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false); err != nil {
			return 1
		}

		// Collect table paths and ports
		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
		for _, tablet := range tablets {
			if tablet.Type == "master" {
				masterTablet = *tablet
			} else if tablet.Type != "rdonly" {
				replicaTablet = *tablet
			}
		}

		return m.Run()
	}()
	os.Exit(exitCode)
}

func throttleCheck() (*http.Response, error) {
	return httpClient.Head(fmt.Sprintf("http://localhost:%d/%s", masterTablet.HTTPPort, checkAPIPath))
}

func TestThrottlerBeforeMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	// Immediately after startup, we expect this response:
	// {"StatusCode":404,"Value":0,"Threshold":0,"Message":"No such metric"}
	resp, err := throttleCheck()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

func TestThrottlerAfterMetricsCollected(t *testing.T) {
	defer cluster.PanicHandler(t)

	time.Sleep(10 * time.Second)
	// By this time metrics will have been collected. We expect no lag, and something like:
	// {"StatusCode":200,"Value":0.282278,"Threshold":1,"Message":""}
	resp, err := throttleCheck()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
}

func TestNoReplicas(t *testing.T) {
	defer cluster.PanicHandler(t)

	err := clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "RDONLY")
	assert.NoError(t, err)

	time.Sleep(10 * time.Second)
	// This makes no REPLICA servers available. We expect something like:
	// {"StatusCode":500,"Value":0,"Threshold":1,"Message":"No hosts found"}
	resp, err := throttleCheck()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)

	err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "REPLICA")
	assert.NoError(t, err)

	time.Sleep(10 * time.Second)
	// Restore valid replica
	resp, err = throttleCheck()
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

type bot interface {
	getGreeting() string
}

type englishBot struct {
}

type spanishBot struct {
}

type gujaratiBot struct {
}

func main() {
	eb := englishBot{}
	sb := spanishBot{}
	gb := gujaratiBot{}

	printGreeting(eb)
	printGreeting(sb)
	printGreeting(gb)
}

func (englishBot) getGreeting() string {
	return "Hello, There"
}

func (spanishBot) getGreeting() string {
	return "Hola!"
}

func (gujaratiBot) getGreeting() string {
	return "જય ગાંધી"
}

// func printGreeting(eb englishBot) {
// 	fmt.Println(eb.getGreeting())
// }

// func printGreeting(sb spanishBot) {
// 	fmt.Println(sb.getGreeting())
// }

func printGreeting(b bot) {
	fmt.Println(b.getGreeting())
}
<commit_msg>Added Comments<commit_after>package main

import (
	"fmt"
)

type bot interface {
	getGreeting() string
}

type englishBot struct {
}

type spanishBot struct {
}

type gujaratiBot struct {
}

func main() {
	eb := englishBot{}
	sb := spanishBot{}
	gb := gujaratiBot{}

	printGreeting(eb)
	printGreeting(sb)
	printGreeting(gb)
}

func (englishBot) getGreeting() string {
	return "Hello, There"
}

func (spanishBot) getGreeting() string {
	return "Hola!"
}

func (gujaratiBot) getGreeting() string {
	return "જય ગાંધી"
}

// func printGreeting(eb englishBot) {
// 	fmt.Println(eb.getGreeting())
// }

// func printGreeting(sb spanishBot) {
// 	fmt.Println(sb.getGreeting())
// }

func printGreeting(b bot) {
	fmt.Println(b.getGreeting())
}

// Concrete Type
// map
// struct
// int
// string
// englishBot

// Interface Type
// bot
<|endoftext|>


<commit_before>package textmagic

import (
	"encoding/json"
	"io"
	"net/http"
	"net/url"

	"github.com/MJKWoolnough/memio"
)

var apiURLPrefix = "https://www.textmagic.com/app/api?"

const (
	cmdAccount       = "account"
	cmdCheckNumber   = "check_number"
	cmdDeleteReply   = "delete_reply"
	cmdMessageStatus = "message_status"
	cmdReceive       = "receive"
	cmdSend          = "send"
)

type TextMagic struct {
	username, password string
}

func New(username, password string) TextMagic {
	return TextMagic{username, password}
}

func (t TextMagic) sendAPI(cmd string, params url.Values, data interface{}) error {
	params.Set("username", t.username)
	params.Set("password", t.password)
	params.Set("cmd", cmd)
	r, err := http.Get(apiURLPrefix + params.Encode())
	if err != nil {
		return RequestError{cmd, err}
	}
	defer r.Body.Close()
	if r.StatusCode != http.StatusOK {
		return StatusError{cmd, r.StatusCode}
	}
	jsonData := make([]byte, r.ContentLength) // avoid allocation using io.Pipe?
	var apiError APIError
	err = json.NewDecoder(io.TeeReader(r.Body, memio.Create(&jsonData))).Decode(&apiError)
	if err != nil {
		return JSONError{cmd, err}
	}
	if apiError.Code != 0 {
		apiError.Cmd = cmd
		return apiError
	}
	json.Unmarshal(jsonData, data)
	return nil
}

type balance struct {
	Balance float32 `json:"balance"`
}

func (t TextMagic) Account() (float32, error) {
	var b balance
	if err := t.sendAPI(cmdAccount, url.Values{}, &b); err != nil {
		return 0, err
	}
	return b.Balance, nil
}

type DeliveryNotificationCode string

func (d DeliveryNotificationCode) Status() string {
	switch d {
	case "q", "r", "a", "b", "s":
		return "intermediate"
	case "d", "f", "e", "j", "u":
		return "final"
	}
	return "unknown"
}

func (d DeliveryNotificationCode) String() string {
	switch d {
	case "q":
		return "The message is queued on the TextMagic server."
	case "r":
		return "The message has been sent to the mobile operator."
	case "a":
		return "The mobile operator has acknowledged the message."
	case "b":
		return "The mobile operator has queued the message."
	case "d":
		return "The message has been successfully delivered to the handset."
	case "f":
		return "An error occurred while delivering message."
	case "e":
		return "An error occurred while sending message."
	case "j":
		return "The mobile operator has rejected the message."
	case "s":
		return "This message is scheduled to be sent later."
	default:
		return "The status is unknown."

	}
}

type Status struct {
	Text      string                   `json:"text"`
	Status    DeliveryNotificationCode `json:"status"`
	Created   int64                    `json:"created_time"`
	Reply     string                   `json:"reply_number"`
	Cost      float32                  `json:"credits_cost"`
	Completed int64                    `json:"completed_time"`
}

func (t TextMagic) MessageStatus(ids []uint64) (map[uint64]Status, error) {
	statuses := make(map[uint64]Status)
	for _, tIds := range splitSlice(ids) {
		messageIds := joinUints(tIds)
		strStatuses := make(map[string]Status)
		err := t.sendAPI(cmdMessageStatus, url.Values{"ids": {messageIds}}, strStatuses)
		if err != nil {
			return statuses, err
		}
		for messageID, status := range strStatuses {
			id, isNum := stou(messageID)
			if !isNum {
				continue
			}
			statuses[id] = status
		}
	}
	return statuses, nil
}

type Number struct {
	Price   float32 `json:"price"`
	Country string  `json:"country"`
}

func (t TextMagic) CheckNumber(numbers []uint64) (map[uint64]Number, error) {
	ns := make(map[string]Number)
	if err := t.sendAPI(cmdCheckNumber, url.Values{"phone": {joinUints(numbers)}}, ns); err != nil {
		return nil, err
	}
	toRet := make(map[uint64]Number)
	for n, data := range ns {
		number, isNum := stou(n)
		if !isNum {
			continue
		}
		toRet[number] = data
	}
	return toRet, nil
}

type deleted struct {
	Deleted []uint64 `json:"deleted"`
}

func (t TextMagic) DeleteReply(ids []uint64) ([]uint64, error) {
	toRet := make([]uint64, 0, len(ids))
	for _, tIds := range splitSlice(ids) {
		var d deleted
		if err := t.sendAPI(cmdDeleteReply, url.Values{"deleted": {joinUints(tIds)}}, &d); err != nil {
			return toRet, err
		}
		toRet = append(toRet, d.Deleted...)
	}
	return toRet, nil
}

type Message struct {
	ID        uint64 `json:"message_id"`
	From      uint64 `json:"from"`
	Timestamp int64  `json:"timestamp"`
	Text      string `json:"text"`
}

type received struct {
	Messages []Message `json:"messages"`
	Unread   uint64    `json:"unread"`
}

func (t TextMagic) Receive(lastRetrieved uint64) (uint64, []Message, error) {
	var r received
	err := t.sendAPI(cmdReceive, url.Values{"last_retrieved_id": {utos(lastRetrieved)}}, &r)
	return r.Unread, r.Messages, err
}

func (t TextMagic) Send() {

}

const joinSep = ','

func joinUints(u []uint64) string {
	toStr := make([]byte, 0, 10*len(u))
	var digits [21]byte
	for n, num := range u {
		if n > 0 {
			toStr = append(toStr, joinSep)
		}
		if num == 0 {
			toStr = append(toStr, '0')
			continue
		}
		pos := 21
		for ; num > 0; num /= 10 {
			pos--
			digits[pos] = '0' + byte(num%10)
		}
		toStr = append(toStr, digits[pos:]...)
	}
	return string(toStr)
}

const maxInSlice = 100

func splitSlice(slice []uint64) [][]uint64 {
	toRet := make([][]uint64, 0, len(slice)/maxInSlice+1)
	for len(slice) > 100 {
		toRet = append(toRet, slice[:100])
		slice = slice[100:]
	}
	if len(slice) > 0 {
		toRet = append(toRet, slice)
	}
	return toRet
}

func utos(num uint64) string {
	if num == 0 {
		return "0"
	}
	var digits [21]byte
	pos := 21
	for ; num > 0; num /= 10 {
		pos--
		digits[pos] = '0' + byte(num%10)
	}
	return string(digits[pos:])
}

func stou(str string) (uint64, bool) {
	var num uint64
	for _, c := range str {
		if c > '9' || c < '0' {
			return 0, false
		}
		num *= 10
		num += uint64(c - '0')
	}
	return num, true
}

// Errors

type APIError struct {
	Cmd     string
	Code    int    `json:"error_code"`
	Message string `json:"error_message"`
}

func (a APIError) Error() string {
	return "command " + a.Cmd + " returned the following API error: " + a.Message
}

type RequestError struct {
	Cmd string
	Err error
}

func (r RequestError) Error() string {
	return "command " + r.Cmd + " returned the following error while makeing the API call: " + r.Err.Error()
}

type StatusError struct {
	Cmd        string
	StatusCode int
}

func (s StatusError) Error() string {
	return "command " + s.Cmd + " returned a non-200 OK response: " + http.StatusText(s.StatusCode)
}

type JSONError struct {
	Cmd string
	Err error
}

func (j JSONError) Error() string {
	return "command " + j.Cmd + " returned malformed JSON: " + j.Err.Error()
}
<commit_msg>Added initial Send func<commit_after>package textmagic

import (
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"time"

	"github.com/MJKWoolnough/memio"
)

var apiURLPrefix = "https://www.textmagic.com/app/api?"

const (
	cmdAccount       = "account"
	cmdCheckNumber   = "check_number"
	cmdDeleteReply   = "delete_reply"
	cmdMessageStatus = "message_status"
	cmdReceive       = "receive"
	cmdSend          = "send"
)

type TextMagic struct {
	username, password string
}

func New(username, password string) TextMagic {
	return TextMagic{username, password}
}

func (t TextMagic) sendAPI(cmd string, params url.Values, data interface{}) error {
	params.Set("username", t.username)
	params.Set("password", t.password)
	params.Set("cmd", cmd)
	r, err := http.Get(apiURLPrefix + params.Encode())
	if err != nil {
		return RequestError{cmd, err}
	}
	defer r.Body.Close()
	if r.StatusCode != http.StatusOK {
		return StatusError{cmd, r.StatusCode}
	}
	jsonData := make([]byte, r.ContentLength) // avoid allocation using io.Pipe?
	var apiError APIError
	err = json.NewDecoder(io.TeeReader(r.Body, memio.Create(&jsonData))).Decode(&apiError)
	if err != nil {
		return JSONError{cmd, err}
	}
	if apiError.Code != 0 {
		apiError.Cmd = cmd
		return apiError
	}
	json.Unmarshal(jsonData, data)
	return nil
}

type balance struct {
	Balance float32 `json:"balance"`
}

func (t TextMagic) Account() (float32, error) {
	var b balance
	if err := t.sendAPI(cmdAccount, url.Values{}, &b); err != nil {
		return 0, err
	}
	return b.Balance, nil
}

type DeliveryNotificationCode string

func (d DeliveryNotificationCode) Status() string {
	switch d {
	case "q", "r", "a", "b", "s":
		return "intermediate"
	case "d", "f", "e", "j", "u":
		return "final"
	}
	return "unknown"
}

func (d DeliveryNotificationCode) String() string {
	switch d {
	case "q":
		return "The message is queued on the TextMagic server."
	case "r":
		return "The message has been sent to the mobile operator."
	case "a":
		return "The mobile operator has acknowledged the message."
	case "b":
		return "The mobile operator has queued the message."
	case "d":
		return "The message has been successfully delivered to the handset."
	case "f":
		return "An error occurred while delivering message."
	case "e":
		return "An error occurred while sending message."
	case "j":
		return "The mobile operator has rejected the message."
	case "s":
		return "This message is scheduled to be sent later."
	default:
		return "The status is unknown."

	}
}

type Status struct {
	Text      string                   `json:"text"`
	Status    DeliveryNotificationCode `json:"status"`
	Created   int64                    `json:"created_time"`
	Reply     string                   `json:"reply_number"`
	Cost      float32                  `json:"credits_cost"`
	Completed int64                    `json:"completed_time"`
}

func (t TextMagic) MessageStatus(ids []uint64) (map[uint64]Status, error) {
	statuses := make(map[uint64]Status)
	for _, tIds := range splitSlice(ids) {
		messageIds := joinUints(tIds)
		strStatuses := make(map[string]Status)
		err := t.sendAPI(cmdMessageStatus, url.Values{"ids": {messageIds}}, strStatuses)
		if err != nil {
			return statuses, err
		}
		for messageID, status := range strStatuses {
			id, isNum := stou(messageID)
			if !isNum {
				continue
			}
			statuses[id] = status
		}
	}
	return statuses, nil
}

type Number struct {
	Price   float32 `json:"price"`
	Country string  `json:"country"`
}

func (t TextMagic) CheckNumber(numbers []uint64) (map[uint64]Number, error) {
	ns := make(map[string]Number)
	if err := t.sendAPI(cmdCheckNumber, url.Values{"phone": {joinUints(numbers)}}, ns); err != nil {
		return nil, err
	}
	toRet := make(map[uint64]Number)
	for n, data := range ns {
		number, isNum := stou(n)
		if !isNum {
			continue
		}
		toRet[number] = data
	}
	return toRet, nil
}

type deleted struct {
	Deleted []uint64 `json:"deleted"`
}

func (t TextMagic) DeleteReply(ids []uint64) ([]uint64, error) {
	toRet := make([]uint64, 0, len(ids))
	for _, tIds := range splitSlice(ids) {
		var d deleted
		if err := t.sendAPI(cmdDeleteReply, url.Values{"deleted": {joinUints(tIds)}}, &d); err != nil {
			return toRet, err
		}
		toRet = append(toRet, d.Deleted...)
	}
	return toRet, nil
}

type Message struct {
	ID        uint64 `json:"message_id"`
	From      uint64 `json:"from"`
	Timestamp int64  `json:"timestamp"`
	Text      string `json:"text"`
}

type received struct {
	Messages []Message `json:"messages"`
	Unread   uint64    `json:"unread"`
}

func (t TextMagic) Receive(lastRetrieved uint64) (uint64, []Message, error) {
	var r received
	err := t.sendAPI(cmdReceive, url.Values{"last_retrieved_id": {utos(lastRetrieved)}}, &r)
	return r.Unread, r.Messages, err
}

type option func(u url.Values)

func From(from uint64) option {
	return func(u url.Values) {
		u.Set("from", utos(from))
	}
}

func MaxLength(length uint64) option {
	if length > 3 {
		length = 3
	}
	return func(u url.Values) {
		u.Set("max_length", utos(length))
	}
}

func CutExtra() option {
	return func(u url.Values) {
		u.Set("cut_extra", "1")
	}
}

func SendTime(t time.Time) option {
	return func(u url.Values) {
		u.Set("send_time", t.Format(time.RFC3339))
	}
}

type messageResponse struct {
	IDs   map[string]string `json:"message_id"`
	Text  string            `json:"sent_text"`
	Parts uint              `json:"parts_count"`
}

func (t TextMagic) Send(message string, to []uint64, options ...option) (map[string]uint64, string, uint, error) {
	var (
		params url.Values
		text   string
		parts  uint
		ids    = make(map[string]uint64)
	)
	for _, o := range options {
		o(params)
	}
	// check message for unicode/invalid chars
	params.Set("text", message)
	for _, numbers := range splitSlice(to) {
		params.Set("phone", joinUints(numbers))
		var m messageResponse
		if err := t.sendAPI(cmdSend, params, &m); err != nil {
			return ids, text, parts, err
		}
		if parts == 0 {
			parts = m.Parts
			text = m.Text
		}
		for id, number := range m.IDs {
			if n, isNum := stou(number); isNum {
				ids[id] = n
			}
		}
	}
	return ids, text, parts, nil
}

const joinSep = ','

func joinUints(u []uint64) string {
	toStr := make([]byte, 0, 10*len(u))
	var digits [21]byte
	for n, num := range u {
		if n > 0 {
			toStr = append(toStr, joinSep)
		}
		if num == 0 {
			toStr = append(toStr, '0')
			continue
		}
		pos := 21
		for ; num > 0; num /= 10 {
			pos--
			digits[pos] = '0' + byte(num%10)
		}
		toStr = append(toStr, digits[pos:]...)
	}
	return string(toStr)
}

const maxInSlice = 100

func splitSlice(slice []uint64) [][]uint64 {
	toRet := make([][]uint64, 0, len(slice)/maxInSlice+1)
	for len(slice) > 100 {
		toRet = append(toRet, slice[:100])
		slice = slice[100:]
	}
	if len(slice) > 0 {
		toRet = append(toRet, slice)
	}
	return toRet
}

func utos(num uint64) string {
	if num == 0 {
		return "0"
	}
	var digits [21]byte
	pos := 21
	for ; num > 0; num /= 10 {
		pos--
		digits[pos] = '0' + byte(num%10)
	}
	return string(digits[pos:])
}

func stou(str string) (uint64, bool) {
	var num uint64
	for _, c := range str {
		if c > '9' || c < '0' {
			return 0, false
		}
		num *= 10
		num += uint64(c - '0')
	}
	return num, true
}

// Errors

type APIError struct {
	Cmd     string
	Code    int    `json:"error_code"`
	Message string `json:"error_message"`
}

func (a APIError) Error() string {
	return "command " + a.Cmd + " returned the following API error: " + a.Message
}

type RequestError struct {
	Cmd string
	Err error
}

func (r RequestError) Error() string {
	return "command " + r.Cmd + " returned the following error while makeing the API call: " + r.Err.Error()
}

type StatusError struct {
	Cmd        string
	StatusCode int
}

func (s StatusError) Error() string {
	return "command " + s.Cmd + " returned a non-200 OK response: " + http.StatusText(s.StatusCode)
}

type JSONError struct {
	Cmd string
	Err error
}

func (j JSONError) Error() string {
	return "command " + j.Cmd + " returned malformed JSON: " + j.Err.Error()
}
<|endoftext|>


<commit_before>package jolokia

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	// "net/url"
	"strings"
	// "sync"

	"github.com/influxdb/telegraf/plugins"
)

type Server struct {
  Name string
  Host string
  Port string
}

type Metric struct {
  Name string
  Jmx string
  Pass []string
  Drop []string
}

type Jolokia struct {

  Context   string
  Servers   []Server
  Metrics   []Metric

}

func (j *Jolokia) SampleConfig() string {
	return `[jolokia]
  context = "/jolokia/read"

  [[jolokia.servers]]
        name = "stable"
        host = "192.168.103.2"
        port = "8180"

  [[jolokia.metrics]]
        name = "heap_memory_usage"
        jmx  = "/java.lang:type=Memory/HeapMemoryUsage"
        pass = ["used"]

  [[jolokia.metrics]]
        name = "memory_eden"
        jmx  = "/java.lang:type=MemoryPool,name=PS Eden Space/Usage"
        pass = ["used"]

  [[jolokia.metrics]]
        name = "heap_threads"
        jmx  = "/java.lang:type=Threading"
 #      drop = ["AllThread"]
        pass = ["CurrentThreadCpuTime","CurrentThreadUserTime","DaemonThreadCount","ThreadCount","TotalStartedThreadCount"]
`
}

func (j *Jolokia) Description() string {
	return "Read JMX metrics through Jolokia"
}

func getAttr(url string) (map[string]interface{}, error) {
  //make request
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

  // Process response
  if resp.StatusCode != http.StatusOK {
    err = fmt.Errorf("Response from url \"%s\" has status code %d (%s), expected %d (%s)",
      url,
      resp.StatusCode,
      http.StatusText(resp.StatusCode),
      http.StatusOK,
      http.StatusText(http.StatusOK))
    return nil, err
  }

  // read body
  body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

  // Unmarshal json
  var jsonOut map[string]interface{}
  if err = json.Unmarshal([]byte(body), &jsonOut); err != nil {
    return nil, errors.New("Error decoding JSON response")
  }

  return jsonOut, nil
}

func (m *Metric) shouldPass(field string) bool {

  if m.Pass != nil {

    for _, pass := range m.Pass{
      if strings.HasPrefix(field, pass) {
				return true
			}
    }

    return false
  }

  if m.Drop != nil {

    for _, drop := range m.Drop{
      if strings.HasPrefix(field, drop) {
				return false
			}
    }

    return true
  }

  return true
}

func (m *Metric) filterFields(fields map[string]interface{}) map[string]interface{} {

  for field, _ := range fields{
    if !m.shouldPass(field) {
			delete(fields, field)
		}
  }

  return fields
}

func (j *Jolokia) Gather(acc plugins.Accumulator) error {

  context := j.Context //"/jolokia/read"
  servers := j.Servers
  metrics := j.Metrics

  var tags = map[string]string{
    "group": "application_server",
  }

  for _, server := range servers {
    for _, metric := range metrics {

      measurement := metric.Name
      jmxPath := metric.Jmx

      tags["server"] = server.Name
			tags["port"] = server.Port
			tags["host"] = server.Host

      url := "http://" + server.Host + ":" + server.Port + context + jmxPath
      //fmt.Println(url)
      out, _ := getAttr(url)

      if values, ok := out["value"]; ok {
        switch values.(type) {
          case map[string]interface{}:
            acc.AddFields(measurement, metric.filterFields(values.(map[string]interface{})), tags)
          case interface{}:
            acc.Add(measurement, values.(interface{}), tags)
        }
      }else{
        fmt.Println("Missing key value")
      }
    }
  }

  return nil
}

func init() {
	plugins.Add("jolokia", func() plugins.Plugin {
		return &Jolokia{}
	})
}
<commit_msg>Added Tags as toml field<commit_after>package jolokia

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	// "net/url"
	"strings"
	// "sync"

	"github.com/influxdb/telegraf/plugins"
)

type Server struct {
  Name string
  Host string
  Port string
}

type Metric struct {
  Name string
  Jmx string
  Pass []string
  Drop []string
}

type Jolokia struct {

  Context   string
  Servers   []Server
  Metrics   []Metric
	Tags			map[string]string
}

func (j *Jolokia) SampleConfig() string {
	return `[jolokia]
  context = "/jolokia/read"

	[[jolokia.tags]]
		group = "as"

  [[jolokia.servers]]
        name = "stable"
        host = "192.168.103.2"
        port = "8180"

  [[jolokia.metrics]]
        name = "heap_memory_usage"
        jmx  = "/java.lang:type=Memory/HeapMemoryUsage"
        pass = ["used"]

  [[jolokia.metrics]]
        name = "memory_eden"
        jmx  = "/java.lang:type=MemoryPool,name=PS Eden Space/Usage"
        pass = ["used"]

  [[jolokia.metrics]]
        name = "heap_threads"
        jmx  = "/java.lang:type=Threading"
 #      drop = ["AllThread"]
        pass = ["CurrentThreadCpuTime","CurrentThreadUserTime","DaemonThreadCount","ThreadCount","TotalStartedThreadCount"]
`
}

func (j *Jolokia) Description() string {
	return "Read JMX metrics through Jolokia"
}

func getAttr(url string) (map[string]interface{}, error) {
  //make request
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

  // Process response
  if resp.StatusCode != http.StatusOK {
    err = fmt.Errorf("Response from url \"%s\" has status code %d (%s), expected %d (%s)",
      url,
      resp.StatusCode,
      http.StatusText(resp.StatusCode),
      http.StatusOK,
      http.StatusText(http.StatusOK))
    return nil, err
  }

  // read body
  body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

  // Unmarshal json
  var jsonOut map[string]interface{}
  if err = json.Unmarshal([]byte(body), &jsonOut); err != nil {
    return nil, errors.New("Error decoding JSON response")
  }

  return jsonOut, nil
}

func (m *Metric) shouldPass(field string) bool {

  if m.Pass != nil {

    for _, pass := range m.Pass{
      if strings.HasPrefix(field, pass) {
				return true
			}
    }

    return false
  }

  if m.Drop != nil {

    for _, drop := range m.Drop{
      if strings.HasPrefix(field, drop) {
				return false
			}
    }

    return true
  }

  return true
}

func (m *Metric) filterFields(fields map[string]interface{}) map[string]interface{} {

  for field, _ := range fields{
    if !m.shouldPass(field) {
			delete(fields, field)
		}
  }

  return fields
}

func (j *Jolokia) Gather(acc plugins.Accumulator) error {

  context := j.Context //"/jolokia/read"
  servers := j.Servers
  metrics := j.Metrics
	tags := j.Tags

	if tags == nil{
			tags = map[string]string{}
	}

  for _, server := range servers {
    for _, metric := range metrics {

      measurement := metric.Name
      jmxPath := metric.Jmx

      tags["server"] = server.Name
			tags["port"] = server.Port
			tags["host"] = server.Host

      url := "http://" + server.Host + ":" + server.Port + context + jmxPath
      //fmt.Println(url)
      out, _ := getAttr(url)

      if values, ok := out["value"]; ok {
        switch values.(type) {
          case map[string]interface{}:
            acc.AddFields(measurement, metric.filterFields(values.(map[string]interface{})), tags)
          case interface{}:
            acc.Add(measurement, values.(interface{}), tags)
        }
      }else{
        fmt.Printf("Missing key 'value' in '%s' output response\n", url)
      }
    }
  }

  return nil
}

func init() {
	plugins.Add("jolokia", func() plugins.Plugin {
		return &Jolokia{}
	})
}
<|endoftext|>