<commit_before>package peer

import (
	"errors"
	"sync"
	"time"

	ic "github.com/jbenet/go-ipfs/p2p/crypto"

	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
	dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)

const (
	// AddressTTL is the expiration time of addresses.
	AddressTTL = time.Hour
)

// Peerstore provides a threadsafe store of Peer related
// information.
type Peerstore interface {
	KeyBook
	AddressBook
	Metrics

	// Peers returns a list of all peer.IDs in this Peerstore
	Peers() []ID

	// PeerInfo returns a peer.PeerInfo struct for given peer.ID.
	// This is a small slice of the information Peerstore has on
	// that peer, useful to other services.
	PeerInfo(ID) PeerInfo

	// AddPeerInfo absorbs the information listed in given PeerInfo.
	AddPeerInfo(PeerInfo)

	// Get/Put is a simple registry for other peer-related key/value pairs.
	// if we find something we use often, it should become its own set of
	// methods. this is a last resort.
	Get(id ID, key string) (interface{}, error)
	Put(id ID, key string, val interface{}) error
}

// AddressBook tracks the addresses of Peers
type AddressBook interface {
	Addresses(ID) []ma.Multiaddr     // returns addresses for ID
	AddAddress(ID, ma.Multiaddr)     // Adds given addr for ID
	AddAddresses(ID, []ma.Multiaddr) // Adds given addrs for ID
	SetAddresses(ID, []ma.Multiaddr) // Sets given addrs for ID (clears previously stored)
}

type expiringAddr struct {
	Addr ma.Multiaddr
	TTL  time.Time
}

func (e *expiringAddr) Expired() bool {
	return time.Now().After(e.TTL)
}

type addressMap map[string]expiringAddr

type addressbook struct {
	addrs map[ID]addressMap
	ttl   time.Duration // initial ttl
	sync.RWMutex
}

func newAddressbook() *addressbook {
	return &addressbook{
		addrs: map[ID]addressMap{},
		ttl:   AddressTTL,
	}
}

func (ab *addressbook) Peers() []ID {
	ab.RLock()
	ps := make([]ID, 0, len(ab.addrs))
	for p := range ab.addrs {
		ps = append(ps, p)
	}
	ab.RUnlock()
	return ps
}

func (ab *addressbook) Addresses(p ID) []ma.Multiaddr {
	ab.Lock()
	defer ab.Unlock()

	maddrs, found := ab.addrs[p]
	if !found {
		return nil
	}

	good := make([]ma.Multiaddr, 0, len(maddrs))
	var expired []string
	for s, m := range maddrs {
		if m.Expired() {
			expired = append(expired, s)
		} else {
			good = append(good, m.Addr)
		}
	}

	// clean up the expired ones.
	for _, s := range expired {
		delete(ab.addrs[p], s)
	}
	return good
}

func (ab *addressbook) AddAddress(p ID, m ma.Multiaddr) {
	ab.AddAddresses(p, []ma.Multiaddr{m})
}

func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
	ab.Lock()
	defer ab.Unlock()

	amap, found := ab.addrs[p]
	if !found {
		amap = addressMap{}
		ab.addrs[p] = amap
	}

	ttl := time.Now().Add(ab.ttl)
	for _, m := range ms {
		// re-set all of them for new ttl.
		amap[m.String()] = expiringAddr{
			Addr: m,
			TTL:  ttl,
		}
	}
}

func (ab *addressbook) SetAddresses(p ID, ms []ma.Multiaddr) {
	ab.Lock()
	defer ab.Unlock()

	amap := addressMap{}
	ttl := time.Now().Add(ab.ttl)
	for _, m := range ms {
		amap[m.String()] = expiringAddr{Addr: m, TTL: ttl}
	}
	ab.addrs[p] = amap // clear what was there before
}

// KeyBook tracks the Public keys of Peers.
type KeyBook interface {
	PubKey(ID) ic.PubKey
	AddPubKey(ID, ic.PubKey) error

	PrivKey(ID) ic.PrivKey
	AddPrivKey(ID, ic.PrivKey) error
}

type keybook struct {
	pks map[ID]ic.PubKey
	sks map[ID]ic.PrivKey

	sync.RWMutex // same lock. wont happen a ton.
}

func newKeybook() *keybook {
	return &keybook{
		pks: map[ID]ic.PubKey{},
		sks: map[ID]ic.PrivKey{},
	}
}

func (kb *keybook) Peers() []ID {
	kb.RLock()
	ps := make([]ID, 0, len(kb.pks)+len(kb.sks))
	for p := range kb.pks {
		ps = append(ps, p)
	}
	for p := range kb.sks {
		if _, found := kb.pks[p]; !found {
			ps = append(ps, p)
		}
	}
	kb.RUnlock()
	return ps
}

func (kb *keybook) PubKey(p ID) ic.PubKey {
	kb.RLock()
	pk := kb.pks[p]
	kb.RUnlock()
	return pk
}

func (kb *keybook) AddPubKey(p ID, pk ic.PubKey) error {

	// check it's correct first
	if !p.MatchesPublicKey(pk) {
		return errors.New("ID does not match PublicKey")
	}

	kb.Lock()
	kb.pks[p] = pk
	kb.Unlock()
	return nil
}

func (kb *keybook) PrivKey(p ID) ic.PrivKey {
	kb.RLock()
	sk := kb.sks[p]
	kb.RUnlock()
	return sk
}

func (kb *keybook) AddPrivKey(p ID, sk ic.PrivKey) error {

	if sk == nil {
		return errors.New("sk is nil (PrivKey)")
	}

	// check it's correct first
	if !p.MatchesPrivateKey(sk) {
		return errors.New("ID does not match PrivateKey")
	}

	kb.Lock()
	kb.sks[p] = sk
	kb.Unlock()
	return nil
}

type peerstore struct {
	keybook
	addressbook
	metrics

	// store other data, like versions
	ds ds.ThreadSafeDatastore
}

// NewPeerstore creates a threadsafe collection of peers.
func NewPeerstore() Peerstore {
	return &peerstore{
		keybook:     *newKeybook(),
		addressbook: *newAddressbook(),
		metrics:     *(NewMetrics()).(*metrics),
		ds:          dssync.MutexWrap(ds.NewMapDatastore()),
	}
}

func (ps *peerstore) Put(p ID, key string, val interface{}) error {
	dsk := ds.NewKey(string(p) + "/" + key)
	return ps.ds.Put(dsk, val)
}

func (ps *peerstore) Get(p ID, key string) (interface{}, error) {
	dsk := ds.NewKey(string(p) + "/" + key)
	return ps.ds.Get(dsk)
}

func (ps *peerstore) Peers() []ID {
	set := map[ID]struct{}{}
	for _, p := range ps.keybook.Peers() {
		set[p] = struct{}{}
	}
	for _, p := range ps.addressbook.Peers() {
		set[p] = struct{}{}
	}

	pps := make([]ID, 0, len(set))
	for p := range set {
		pps = append(pps, p)
	}
	return pps
}

func (ps *peerstore) PeerInfo(p ID) PeerInfo {
	return PeerInfo{
		ID:    p,
		Addrs: ps.addressbook.Addresses(p),
	}
}

func (ps *peerstore) AddPeerInfo(pi PeerInfo) {
	ps.AddAddresses(pi.ID, pi.Addrs)
}

func PeerInfos(ps Peerstore, peers []ID) []PeerInfo {
	pi := make([]PeerInfo, len(peers))
	for i, p := range peers {
		pi[i] = ps.PeerInfo(p)
	}
	return pi
}

func PeerInfoIDs(pis []PeerInfo) []ID {
	ps := make([]ID, len(pis))
	for i, pi := range pis {
		ps[i] = pi.ID
	}
	return ps
}
<commit_msg>p2p/peer/peerstore: mu position + comment<commit_after>package peer

import (
	"errors"
	"sync"
	"time"

	ic "github.com/jbenet/go-ipfs/p2p/crypto"

	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
	dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)

const (
	// AddressTTL is the expiration time of addresses.
	AddressTTL = time.Hour
)

// Peerstore provides a threadsafe store of Peer related
// information.
type Peerstore interface {
	KeyBook
	AddressBook
	Metrics

	// Peers returns a list of all peer.IDs in this Peerstore
	Peers() []ID

	// PeerInfo returns a peer.PeerInfo struct for given peer.ID.
	// This is a small slice of the information Peerstore has on
	// that peer, useful to other services.
	PeerInfo(ID) PeerInfo

	// AddPeerInfo absorbs the information listed in given PeerInfo.
	AddPeerInfo(PeerInfo)

	// Get/Put is a simple registry for other peer-related key/value pairs.
	// if we find something we use often, it should become its own set of
	// methods. this is a last resort.
	Get(id ID, key string) (interface{}, error)
	Put(id ID, key string, val interface{}) error
}

// AddressBook tracks the addresses of Peers
type AddressBook interface {
	Addresses(ID) []ma.Multiaddr     // returns addresses for ID
	AddAddress(ID, ma.Multiaddr)     // Adds given addr for ID
	AddAddresses(ID, []ma.Multiaddr) // Adds given addrs for ID
	SetAddresses(ID, []ma.Multiaddr) // Sets given addrs for ID (clears previously stored)
}

type expiringAddr struct {
	Addr ma.Multiaddr
	TTL  time.Time
}

func (e *expiringAddr) Expired() bool {
	return time.Now().After(e.TTL)
}

type addressMap map[string]expiringAddr

type addressbook struct {
	sync.RWMutex // guards all fields

	addrs map[ID]addressMap
	ttl   time.Duration // initial ttl
}

func newAddressbook() *addressbook {
	return &addressbook{
		addrs: map[ID]addressMap{},
		ttl:   AddressTTL,
	}
}

func (ab *addressbook) Peers() []ID {
	ab.RLock()
	ps := make([]ID, 0, len(ab.addrs))
	for p := range ab.addrs {
		ps = append(ps, p)
	}
	ab.RUnlock()
	return ps
}

func (ab *addressbook) Addresses(p ID) []ma.Multiaddr {
	ab.Lock()
	defer ab.Unlock()

	maddrs, found := ab.addrs[p]
	if !found {
		return nil
	}

	good := make([]ma.Multiaddr, 0, len(maddrs))
	var expired []string
	for s, m := range maddrs {
		if m.Expired() {
			expired = append(expired, s)
		} else {
			good = append(good, m.Addr)
		}
	}

	// clean up the expired ones.
	for _, s := range expired {
		delete(ab.addrs[p], s)
	}
	return good
}

func (ab *addressbook) AddAddress(p ID, m ma.Multiaddr) {
	ab.AddAddresses(p, []ma.Multiaddr{m})
}

func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
	ab.Lock()
	defer ab.Unlock()

	amap, found := ab.addrs[p]
	if !found {
		amap = addressMap{}
		ab.addrs[p] = amap
	}

	ttl := time.Now().Add(ab.ttl)
	for _, m := range ms {
		// re-set all of them for new ttl.
		amap[m.String()] = expiringAddr{
			Addr: m,
			TTL:  ttl,
		}
	}
}

func (ab *addressbook) SetAddresses(p ID, ms []ma.Multiaddr) {
	ab.Lock()
	defer ab.Unlock()

	amap := addressMap{}
	ttl := time.Now().Add(ab.ttl)
	for _, m := range ms {
		amap[m.String()] = expiringAddr{Addr: m, TTL: ttl}
	}
	ab.addrs[p] = amap // clear what was there before
}

// KeyBook tracks the Public keys of Peers.
type KeyBook interface {
	PubKey(ID) ic.PubKey
	AddPubKey(ID, ic.PubKey) error

	PrivKey(ID) ic.PrivKey
	AddPrivKey(ID, ic.PrivKey) error
}

type keybook struct {
	pks map[ID]ic.PubKey
	sks map[ID]ic.PrivKey

	sync.RWMutex // same lock. wont happen a ton.
}

func newKeybook() *keybook {
	return &keybook{
		pks: map[ID]ic.PubKey{},
		sks: map[ID]ic.PrivKey{},
	}
}

func (kb *keybook) Peers() []ID {
	kb.RLock()
	ps := make([]ID, 0, len(kb.pks)+len(kb.sks))
	for p := range kb.pks {
		ps = append(ps, p)
	}
	for p := range kb.sks {
		if _, found := kb.pks[p]; !found {
			ps = append(ps, p)
		}
	}
	kb.RUnlock()
	return ps
}

func (kb *keybook) PubKey(p ID) ic.PubKey {
	kb.RLock()
	pk := kb.pks[p]
	kb.RUnlock()
	return pk
}

func (kb *keybook) AddPubKey(p ID, pk ic.PubKey) error {

	// check it's correct first
	if !p.MatchesPublicKey(pk) {
		return errors.New("ID does not match PublicKey")
	}

	kb.Lock()
	kb.pks[p] = pk
	kb.Unlock()
	return nil
}

func (kb *keybook) PrivKey(p ID) ic.PrivKey {
	kb.RLock()
	sk := kb.sks[p]
	kb.RUnlock()
	return sk
}

func (kb *keybook) AddPrivKey(p ID, sk ic.PrivKey) error {

	if sk == nil {
		return errors.New("sk is nil (PrivKey)")
	}

	// check it's correct first
	if !p.MatchesPrivateKey(sk) {
		return errors.New("ID does not match PrivateKey")
	}

	kb.Lock()
	kb.sks[p] = sk
	kb.Unlock()
	return nil
}

type peerstore struct {
	keybook
	addressbook
	metrics

	// store other data, like versions
	ds ds.ThreadSafeDatastore
}

// NewPeerstore creates a threadsafe collection of peers.
func NewPeerstore() Peerstore {
	return &peerstore{
		keybook:     *newKeybook(),
		addressbook: *newAddressbook(),
		metrics:     *(NewMetrics()).(*metrics),
		ds:          dssync.MutexWrap(ds.NewMapDatastore()),
	}
}

func (ps *peerstore) Put(p ID, key string, val interface{}) error {
	dsk := ds.NewKey(string(p) + "/" + key)
	return ps.ds.Put(dsk, val)
}

func (ps *peerstore) Get(p ID, key string) (interface{}, error) {
	dsk := ds.NewKey(string(p) + "/" + key)
	return ps.ds.Get(dsk)
}

func (ps *peerstore) Peers() []ID {
	set := map[ID]struct{}{}
	for _, p := range ps.keybook.Peers() {
		set[p] = struct{}{}
	}
	for _, p := range ps.addressbook.Peers() {
		set[p] = struct{}{}
	}

	pps := make([]ID, 0, len(set))
	for p := range set {
		pps = append(pps, p)
	}
	return pps
}

func (ps *peerstore) PeerInfo(p ID) PeerInfo {
	return PeerInfo{
		ID:    p,
		Addrs: ps.addressbook.Addresses(p),
	}
}

func (ps *peerstore) AddPeerInfo(pi PeerInfo) {
	ps.AddAddresses(pi.ID, pi.Addrs)
}

func PeerInfos(ps Peerstore, peers []ID) []PeerInfo {
	pi := make([]PeerInfo, len(peers))
	for i, p := range peers {
		pi[i] = ps.PeerInfo(p)
	}
	return pi
}

func PeerInfoIDs(pis []PeerInfo) []ID {
	ps := make([]ID, len(pis))
	for i, pi := range pis {
		ps[i] = pi.ID
	}
	return ps
}
<|endoftext|>


<commit_before>// vmwatcher is an enforcer that gets various metrics (currently only
// `NetworkOut` from cloudwatch api is implemented) and stops the vm if it's
// over the limit for that metric; in addition it also exposes a http endpoint
// for various workers (kloud for now) to check if user is overlimit before
// taking an action (ie starting a vm).
//
// The goal of this worker is to prevent users from abusing the system, not be
// a secondary storage for metrics data.
package main

import (
	"log"
	"net/http"

	"github.com/robfig/cron"
)

var (
	WorkerName    = "vmwatcher"
	WorkerVersion = "0.0.1"

	NetworkOut             = "NetworkOut"
	NetworkOutLimt float64 = 7

	// defines list of metrics, all queue/fetch/save operations
	// must iterate this list and not use metric directly
	metricsToSave = []Metric{
		&Cloudwatch{Name: NetworkOut, Limit: NetworkOutLimt},
	}
)

func main() {
	c := cron.New()

	// queue to get metrics at top of every hour; uses redis set to queue
	// the usernames so multiple workers don't queue the same usernames.
	// this needs to be done at top of hour, so running multiple workers
	// won't cause a problem.
	c.AddFunc("@hourly", func() {
		err := queueUsernamesForMetricGet()
		if err != nil {
			log.Fatal(err)
		}
	})

	// get and save metrics at 15th minute of every hour
	c.AddFunc("0 15 * * * *", func() {
		err := getAndSaveQueueMachineMetrics()
		if err != nil {
			log.Fatal(err)
		}
	})

	// stop machines overlimit at 20th & 40th of every hour; there's no reason
	// for running it at a certain point except not having overlap in logs
	c.AddFunc("0 20,40 * * * *", func() {
		err := stopMachinesOverLimit()
		if err != nil {
			log.Fatal(err)
		}
	})

	c.Start()

	// expose api for workers like kloud to check if users is over limit
	http.HandleFunc("/", checkerHttp)
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>vmwatcher: add artifact<commit_after>// vmwatcher is an enforcer that gets various metrics (currently only
// `NetworkOut` from cloudwatch api is implemented) and stops the vm if it's
// over the limit for that metric; in addition it also exposes a http endpoint
// for various workers (kloud for now) to check if user is overlimit before
// taking an action (ie starting a vm).
//
// The goal of this worker is to prevent users from abusing the system, not be
// a secondary storage for metrics data.
package main

import (
	"koding/artifact"
	"log"
	"net/http"

	"github.com/robfig/cron"
)

var (
	WorkerName    = "vmwatcher"
	WorkerVersion = "0.0.1"

	NetworkOut             = "NetworkOut"
	NetworkOutLimt float64 = 7

	// defines list of metrics, all queue/fetch/save operations
	// must iterate this list and not use metric directly
	metricsToSave = []Metric{
		&Cloudwatch{Name: NetworkOut, Limit: NetworkOutLimt},
	}
)

func main() {
	c := cron.New()

	// queue to get metrics at top of every hour; uses redis set to queue
	// the usernames so multiple workers don't queue the same usernames.
	// this needs to be done at top of hour, so running multiple workers
	// won't cause a problem.
	c.AddFunc("@hourly", func() {
		err := queueUsernamesForMetricGet()
		if err != nil {
			log.Fatal(err)
		}
	})

	// get and save metrics at 15th minute of every hour
	c.AddFunc("0 15 * * * *", func() {
		err := getAndSaveQueueMachineMetrics()
		if err != nil {
			log.Fatal(err)
		}
	})

	// stop machines overlimit at 20th & 40th of every hour; there's no reason
	// for running it at a certain point except not having overlap in logs
	c.AddFunc("0 20,40 * * * *", func() {
		err := stopMachinesOverLimit()
		if err != nil {
			log.Fatal(err)
		}
	})

	c.Start()

	// expose api for workers like kloud to check if users is over limit
	http.HandleFunc("/", checkerHttp)

	http.HandleFunc("/version", artifact.VersionHandler())
	http.HandleFunc("/healthCheck", artifact.HealthCheckHandler(WorkerName))

	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>// vmwatcher is an enforcer that gets various metrics (currently only
// `NetworkOut` from cloudwatch api is implemented) and stops the vm if it's
// over the limit for that metric; in addition it also exposes a http endpoint
// for various workers (kloud for now) to check if user is overlimit before
// taking an action (ie starting a vm).
//
// The goal of this worker is to prevent users from abusing the system, not be
// a secondary storage for metrics data.
package main

import (
	"koding/artifact"
	"log"
	"net/http"

	"github.com/robfig/cron"
)

var (
	WorkerName    = "vmwatcher"
	WorkerVersion = "0.0.1"

	NetworkOut             = "NetworkOut"
	NetworkOutLimt float64 = 7

	// defines list of metrics, all queue/fetch/save operations
	// must iterate this list and not use metric directly
	metricsToSave = []Metric{
		&Cloudwatch{Name: NetworkOut, Limit: NetworkOutLimt},
	}
)

func main() {
	c := cron.New()

	// queue to get metrics at top of every hour; uses redis set to queue
	// the usernames so multiple workers don't queue the same usernames.
	// this needs to be done at top of hour, so running multiple workers
	// won't cause a problem.
	c.AddFunc("@hourly", func() {
		err := queueUsernamesForMetricGet()
		if err != nil {
			log.Fatal(err)
		}
	})

	// get and save metrics at 15th minute of every hour
	c.AddFunc("0 15 * * * *", func() {
		err := getAndSaveQueueMachineMetrics()
		if err != nil {
			log.Fatal(err)
		}
	})

	// stop machines overlimit at 20th & 40th of every hour; there's no reason
	// for running it at a certain point except not having overlap in logs
	c.AddFunc("0 20,40 * * * *", func() {
		err := stopMachinesOverLimit()
		if err != nil {
			log.Fatal(err)
		}
	})

	c.Start()

	// expose api for workers like kloud to check if users is over limit
	http.HandleFunc("/", checkerHttp)

	http.HandleFunc("/version", artifact.VersionHandler())
	http.HandleFunc("/healthCheck", artifact.HealthCheckHandler(WorkerName))

	http.ListenAndServe(":"+port, nil)
}
<commit_msg>vmwatcher: switch cron schedule to more readable version<commit_after>// vmwatcher is an enforcer that gets various metrics (currently only
// `NetworkOut` from cloudwatch api is implemented) and stops the vm if it's
// over the limit for that metric; in addition it also exposes a http endpoint
// for various workers (kloud for now) to check if user is overlimit before
// taking an action (ie starting a vm).
//
// The goal of this worker is to prevent users from abusing the system, not be
// a secondary storage for metrics data.
package main

import (
	"koding/artifact"
	"log"
	"net/http"

	"github.com/robfig/cron"
)

var (
	WorkerName    = "vmwatcher"
	WorkerVersion = "0.0.1"

	NetworkOut             = "NetworkOut"
	NetworkOutLimt float64 = 7

	// defines list of metrics, all queue/fetch/save operations
	// must iterate this list and not use metric directly
	metricsToSave = []Metric{
		&Cloudwatch{Name: NetworkOut, Limit: NetworkOutLimt},
	}
)

func main() {
	c := cron.New()

	// queue to get metrics at top of every hour; uses redis set to queue
	// the usernames so multiple workers don't queue the same usernames.
	// this needs to be done at top of hour, so running multiple workers
	// won't cause a problem.
	c.AddFunc("0 0 * * * *", func() {
		err := queueUsernamesForMetricGet()
		if err != nil {
			log.Fatal(err)
		}
	})

	// get and save metrics at 15th minute of every hour
	c.AddFunc("0 15 * * * *", func() {
		err := getAndSaveQueueMachineMetrics()
		if err != nil {
			log.Fatal(err)
		}
	})

	// stop machines overlimit at 20th & 40th of every hour; there's no reason
	// for running it at a certain point except not having overlap in logs
	c.AddFunc("0 20,40 * * * *", func() {
		err := stopMachinesOverLimit()
		if err != nil {
			log.Fatal(err)
		}
	})

	c.Start()

	// expose api for workers like kloud to check if users is over limit
	http.HandleFunc("/", checkerHttp)

	http.HandleFunc("/version", artifact.VersionHandler())
	http.HandleFunc("/healthCheck", artifact.HealthCheckHandler(WorkerName))

	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>package controller

import (
	"fmt"
	"github.com/MG-RAST/AWE/lib/core"
	e "github.com/MG-RAST/AWE/lib/errors"
	"github.com/MG-RAST/AWE/lib/logger"
	"github.com/MG-RAST/AWE/lib/logger/event"
	"github.com/MG-RAST/AWE/lib/request"
	"github.com/MG-RAST/golib/goweb"
	"net/http"
	"strconv"
)

type ClientController struct{}

// OPTIONS: /client
func (cr *ClientController) Options(cx *goweb.Context) {
	LogRequest(cx.Request)
	cx.RespondWithOK()
	return
}

// POST: /client
func (cr *ClientController) Create(cx *goweb.Context) {
	// Log Request and check for Auth
	LogRequest(cx.Request)

	_, err := request.Authenticate(cx.Request)
	if err != nil {
		if err.Error() == e.NoAuth || err.Error() == e.UnAuth {
			cx.RespondWithError(http.StatusUnauthorized)
			return
		} else {
			logger.Error("Err@user_Read: " + err.Error())
			cx.RespondWithError(http.StatusInternalServerError)
			return
		}
	}

	// Parse uploaded form
	_, files, err := ParseMultipartForm(cx.Request)
	if err != nil {
		if err.Error() != "request Content-Type isn't multipart/form-data" {
			logger.Error("Error parsing form: " + err.Error())
			cx.RespondWithError(http.StatusBadRequest)
			return
		}
	}

	client, err := core.QMgr.RegisterNewClient(files)
	if err != nil {
		msg := "Error in registering new client:" + err.Error()
		logger.Error(msg)
		cx.RespondWithErrorMessage(msg, http.StatusBadRequest)
		return
	}

	//log event about client registration (CR)
	logger.Event(event.CLIENT_REGISTRATION, "clientid="+client.Id+";name="+client.Name+";host="+client.Host+";group="+client.Group+";instanceid="+client.InstanceId)

	cx.RespondWithData(client)
	return
}

// GET: /client/{id}
func (cr *ClientController) Read(id string, cx *goweb.Context) {
	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}

	if query.Has("heartbeat") { //handle heartbeat
		hbmsg, err := core.QMgr.ClientHeartBeat(id)
		if err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData(hbmsg)
		}
		return
	}

	LogRequest(cx.Request) //skip heartbeat in access log

	client, err := core.QMgr.GetClient(id)
	if err != nil {
		if err.Error() == e.ClientNotFound {
			cx.RespondWithErrorMessage(e.ClientNotFound, http.StatusBadRequest)
		} else {
			logger.Error("Error in GET client:" + err.Error())
			cx.RespondWithError(http.StatusBadRequest)
		}
		return
	}
	cx.RespondWithData(client)
}

// GET: /client
func (cr *ClientController) ReadMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	clients := core.QMgr.GetAllClients()

	query := &Query{Li: cx.Request.URL.Query()}
	filtered := []*core.Client{}
	if query.Has("busy") {
		for _, client := range clients {
			if len(client.Current_work) > 0 {
				filtered = append(filtered, client)
			}
		}
	} else {
		filtered = clients
	}
	cx.RespondWithData(filtered)
}

// PUT: /client/{id} -> status update
func (cr *ClientController) Update(id string, cx *goweb.Context) {
	LogRequest(cx.Request)

	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}
	if query.Has("subclients") { //update the number of subclients for a proxy
		if count, err := strconv.Atoi(query.Value("subclients")); err != nil {
			cx.RespondWithError(http.StatusNotImplemented)
		} else {
			core.QMgr.UpdateSubClients(id, count)
			cx.RespondWithData("ok")
		}
		return
	}
	if query.Has("suspend") { //resume the suspended client
		if err := core.QMgr.SuspendClient(id); err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData("client suspended")
		}
		return
	}
	if query.Has("resume") { //resume the suspended client
		if err := core.QMgr.ResumeClient(id); err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData("client resumed")
		}
		return
	}
	cx.RespondWithError(http.StatusNotImplemented)
}

// PUT: /client
func (cr *ClientController) UpdateMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}
	if query.Has("resumeall") { //resume the suspended client
		num := core.QMgr.ResumeSuspendedClients()
		cx.RespondWithData(fmt.Sprintf("%d suspended clients resumed", num))
		return
	}
	if query.Has("suspendall") { //resume the suspended client
		num := core.QMgr.SuspendAllClients()
		cx.RespondWithData(fmt.Sprintf("%d clients suspended", num))
		return
	}
	cx.RespondWithError(http.StatusNotImplemented)
}

// DELETE: /client/{id}
func (cr *ClientController) Delete(id string, cx *goweb.Context) {
	LogRequest(cx.Request)
	if err := core.QMgr.DeleteClient(id); err != nil {
		cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
	} else {
		cx.RespondWithData("client deleted")
	}
}

// DELETE: /client
func (cr *ClientController) DeleteMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	cx.RespondWithError(http.StatusNotImplemented)
}
<commit_msg>more info in event.log<commit_after>package controller

import (
	"fmt"
	"github.com/MG-RAST/AWE/lib/core"
	e "github.com/MG-RAST/AWE/lib/errors"
	"github.com/MG-RAST/AWE/lib/logger"
	"github.com/MG-RAST/AWE/lib/logger/event"
	"github.com/MG-RAST/AWE/lib/request"
	"github.com/MG-RAST/golib/goweb"
	"net/http"
	"strconv"
)

type ClientController struct{}

// OPTIONS: /client
func (cr *ClientController) Options(cx *goweb.Context) {
	LogRequest(cx.Request)
	cx.RespondWithOK()
	return
}

// POST: /client
func (cr *ClientController) Create(cx *goweb.Context) {
	// Log Request and check for Auth
	LogRequest(cx.Request)

	_, err := request.Authenticate(cx.Request)
	if err != nil {
		if err.Error() == e.NoAuth || err.Error() == e.UnAuth {
			cx.RespondWithError(http.StatusUnauthorized)
			return
		} else {
			logger.Error("Err@user_Read: " + err.Error())
			cx.RespondWithError(http.StatusInternalServerError)
			return
		}
	}

	// Parse uploaded form
	_, files, err := ParseMultipartForm(cx.Request)
	if err != nil {
		if err.Error() != "request Content-Type isn't multipart/form-data" {
			logger.Error("Error parsing form: " + err.Error())
			cx.RespondWithError(http.StatusBadRequest)
			return
		}
	}

	client, err := core.QMgr.RegisterNewClient(files)
	if err != nil {
		msg := "Error in registering new client:" + err.Error()
		logger.Error(msg)
		cx.RespondWithErrorMessage(msg, http.StatusBadRequest)
		return
	}

	//log event about client registration (CR)
	logger.Event(event.CLIENT_REGISTRATION, "clientid="+client.Id+";name="+client.Name+";host="+client.Host+";group="+client.Group+";instance_id="+client.InstanceId+";instance_type="+client.InstanceType+";domain="+client.Domain)

	cx.RespondWithData(client)
	return
}

// GET: /client/{id}
func (cr *ClientController) Read(id string, cx *goweb.Context) {
	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}

	if query.Has("heartbeat") { //handle heartbeat
		hbmsg, err := core.QMgr.ClientHeartBeat(id)
		if err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData(hbmsg)
		}
		return
	}

	LogRequest(cx.Request) //skip heartbeat in access log

	client, err := core.QMgr.GetClient(id)
	if err != nil {
		if err.Error() == e.ClientNotFound {
			cx.RespondWithErrorMessage(e.ClientNotFound, http.StatusBadRequest)
		} else {
			logger.Error("Error in GET client:" + err.Error())
			cx.RespondWithError(http.StatusBadRequest)
		}
		return
	}
	cx.RespondWithData(client)
}

// GET: /client
func (cr *ClientController) ReadMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	clients := core.QMgr.GetAllClients()

	query := &Query{Li: cx.Request.URL.Query()}
	filtered := []*core.Client{}
	if query.Has("busy") {
		for _, client := range clients {
			if len(client.Current_work) > 0 {
				filtered = append(filtered, client)
			}
		}
	} else {
		filtered = clients
	}
	cx.RespondWithData(filtered)
}

// PUT: /client/{id} -> status update
func (cr *ClientController) Update(id string, cx *goweb.Context) {
	LogRequest(cx.Request)

	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}
	if query.Has("subclients") { //update the number of subclients for a proxy
		if count, err := strconv.Atoi(query.Value("subclients")); err != nil {
			cx.RespondWithError(http.StatusNotImplemented)
		} else {
			core.QMgr.UpdateSubClients(id, count)
			cx.RespondWithData("ok")
		}
		return
	}
	if query.Has("suspend") { //resume the suspended client
		if err := core.QMgr.SuspendClient(id); err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData("client suspended")
		}
		return
	}
	if query.Has("resume") { //resume the suspended client
		if err := core.QMgr.ResumeClient(id); err != nil {
			cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
		} else {
			cx.RespondWithData("client resumed")
		}
		return
	}
	cx.RespondWithError(http.StatusNotImplemented)
}

// PUT: /client
func (cr *ClientController) UpdateMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	// Gather query params
	query := &Query{Li: cx.Request.URL.Query()}
	if query.Has("resumeall") { //resume the suspended client
		num := core.QMgr.ResumeSuspendedClients()
		cx.RespondWithData(fmt.Sprintf("%d suspended clients resumed", num))
		return
	}
	if query.Has("suspendall") { //resume the suspended client
		num := core.QMgr.SuspendAllClients()
		cx.RespondWithData(fmt.Sprintf("%d clients suspended", num))
		return
	}
	cx.RespondWithError(http.StatusNotImplemented)
}

// DELETE: /client/{id}
func (cr *ClientController) Delete(id string, cx *goweb.Context) {
	LogRequest(cx.Request)
	if err := core.QMgr.DeleteClient(id); err != nil {
		cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest)
	} else {
		cx.RespondWithData("client deleted")
	}
}

// DELETE: /client
func (cr *ClientController) DeleteMany(cx *goweb.Context) {
	LogRequest(cx.Request)
	cx.RespondWithError(http.StatusNotImplemented)
}
<|endoftext|>


<commit_before>// +build integration

package riak

import (
	"fmt"
	"strings"
	"testing"
	"time"
)

func init() {
	integrationTestsBuildCluster()
}

// FetchValue

func TestFetchANotFoundFromRiakUsingDefaultBucketType(t *testing.T) {
	var err error
	var cmd Command
	builder := NewFetchValueCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey("notfound_key").Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fvc, ok := cmd.(*FetchValueCommand); ok {
		if fvc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fvc.Response
		if expected, actual := true, rsp.IsNotFound; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := false, rsp.IsUnchanged; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if rsp.VClock != nil {
			t.Errorf("expected nil VClock")
		}
		if rsp.Values != nil {
			t.Errorf("expected nil Values")
		}
		if expected, actual := 0, len(rsp.Values); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

func TestFetchAValueFromRiakUsingDefaultBucketType(t *testing.T) {
	obj := getBasicObject()
	store, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithKey("my_key1").
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(store); err != nil {
		t.Fatalf("error storing test object: %s", err.Error())
	}

	var cmd Command
	builder := NewFetchValueCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey("my_key1").Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fvc, ok := cmd.(*FetchValueCommand); ok {
		if fvc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fvc.Response
		if expected, actual := false, rsp.IsNotFound; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := false, rsp.IsUnchanged; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if rsp.VClock == nil {
			t.Errorf("expected non-nil VClock")
		}
		if rsp.Values == nil {
			t.Errorf("expected non-nil Values")
		}
		if expected, actual := 1, len(rsp.Values); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		object := rsp.Values[0]
		if expected, actual := "this is a value in Riak", string(object.Value); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "text/plain", object.ContentType; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "utf-8", object.Charset; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "utf-8", object.ContentEncoding; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// StoreValue
func TestStoreValueWithRiakGeneratedKey(t *testing.T) {
	obj := getBasicObject()
	cmd, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if svc, ok := cmd.(*StoreValueCommand); ok {
		if svc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := svc.Response
		if rsp.GeneratedKey == "" {
			t.Error("expected non empty GeneratedKey")
		} else {
			t.Logf("GeneratedKey: %s", rsp.GeneratedKey)
		}
	} else {
		t.FailNow()
	}
}

// ListBuckets

func TestListBucketsInDefaultBucketType(t *testing.T) {
	totalCount := 50
	bucketPrefix := fmt.Sprintf("LBDT_%d", time.Now().Unix())
	obj := getBasicObject()
	for i := 0; i < totalCount; i++ {
		bucket := fmt.Sprintf("%s_%d", bucketPrefix, i)
		store, err := NewStoreValueCommandBuilder().
			WithBucket(bucket).
			WithContent(obj).
			Build()
		if err != nil {
			panic(err.Error())
		}
		if err := cluster.Execute(store); err != nil {
			t.Fatalf("error storing test objects: %s", err.Error())
		}
	}

	var err error
	var cmd Command

	// non-streaming
	builder := NewListBucketsCommandBuilder()
	if cmd, err = builder.WithBucketType(defaultBucketType).WithStreaming(false).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListBucketsCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		count := 0
		rsp := lbc.Response
		for _, b := range rsp.Buckets {
			if strings.HasPrefix(b, bucketPrefix) {
				count++
			}
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}

	// streaming
	builder = NewListBucketsCommandBuilder()
	count := 0
	cb := func(buckets []string) error {
		for _, b := range buckets {
			if strings.HasPrefix(b, bucketPrefix) {
				count++
			}
		}
		return nil
	}
	if cmd, err = builder.WithStreaming(true).WithCallback(cb).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListBucketsCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// ListKeys

func TestListKeysInDefaultBucketType(t *testing.T) {
	totalCount := 50
	keyPrefix := fmt.Sprintf("LKDT_%d", time.Now().Unix())
	obj := getBasicObject()
	for i := 0; i < totalCount; i++ {
		key := fmt.Sprintf("%s_%d", keyPrefix, i)
		store, err := NewStoreValueCommandBuilder().
			WithBucket(testBucketName).
			WithKey(key).
			WithContent(obj).
			Build()
		if err != nil {
			panic(err.Error())
		}
		if err := cluster.Execute(store); err != nil {
			t.Fatalf("error storing test objects: %s", err.Error())
		}
	}
	var err error
	var cmd Command
	// non-streaming
	builder := NewListKeysCommandBuilder()
	if cmd, err = builder.WithBucketType(defaultBucketType).WithBucket(testBucketName).WithStreaming(false).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lkc, ok := cmd.(*ListKeysCommand); ok {
		if lkc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		count := 0
		rsp := lkc.Response
		for _, k := range rsp.Keys {
			if strings.HasPrefix(k, keyPrefix) {
				count++
			}
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}

	// streaming
	builder = NewListKeysCommandBuilder()
	count := 0
	cb := func(keys []string) error {
		for _, k := range keys {
			if strings.HasPrefix(k, keyPrefix) {
				count++
			}
		}
		return nil
	}
	if cmd, err = builder.WithBucket(testBucketName).WithStreaming(true).WithCallback(cb).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListKeysCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// FetchPreflist

func TestFetchPreflistForAValue(t *testing.T) {
	key := fmt.Sprintf("FetchPreflist_%d", time.Now().Unix())
	obj := getBasicObject()
	store, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithKey(key).
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(store); err != nil {
		t.Fatalf("error storing test object: %s", err.Error())
	}

	var cmd Command
	builder := NewFetchPreflistCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey(key).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fpc, ok := cmd.(*FetchPreflistCommand); ok {
		if fpc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fpc.Response
		if rsp.Preflist == nil {
			t.Errorf("expected non-nil Preflist")
		}
		if expected, actual := 3, len(rsp.Preflist); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}
<commit_msg>Add SecondaryIndexQueryCommand integration test TODOs<commit_after>// +build integration

package riak

import (
	"fmt"
	"strings"
	"testing"
	"time"
)

func init() {
	integrationTestsBuildCluster()
}

// FetchValue

func TestFetchANotFoundFromRiakUsingDefaultBucketType(t *testing.T) {
	var err error
	var cmd Command
	builder := NewFetchValueCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey("notfound_key").Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fvc, ok := cmd.(*FetchValueCommand); ok {
		if fvc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fvc.Response
		if expected, actual := true, rsp.IsNotFound; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := false, rsp.IsUnchanged; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if rsp.VClock != nil {
			t.Errorf("expected nil VClock")
		}
		if rsp.Values != nil {
			t.Errorf("expected nil Values")
		}
		if expected, actual := 0, len(rsp.Values); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

func TestFetchAValueFromRiakUsingDefaultBucketType(t *testing.T) {
	obj := getBasicObject()
	store, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithKey("my_key1").
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(store); err != nil {
		t.Fatalf("error storing test object: %s", err.Error())
	}

	var cmd Command
	builder := NewFetchValueCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey("my_key1").Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fvc, ok := cmd.(*FetchValueCommand); ok {
		if fvc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fvc.Response
		if expected, actual := false, rsp.IsNotFound; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := false, rsp.IsUnchanged; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if rsp.VClock == nil {
			t.Errorf("expected non-nil VClock")
		}
		if rsp.Values == nil {
			t.Errorf("expected non-nil Values")
		}
		if expected, actual := 1, len(rsp.Values); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		object := rsp.Values[0]
		if expected, actual := "this is a value in Riak", string(object.Value); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "text/plain", object.ContentType; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "utf-8", object.Charset; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
		if expected, actual := "utf-8", object.ContentEncoding; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// StoreValue
func TestStoreValueWithRiakGeneratedKey(t *testing.T) {
	obj := getBasicObject()
	cmd, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if svc, ok := cmd.(*StoreValueCommand); ok {
		if svc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := svc.Response
		if rsp.GeneratedKey == "" {
			t.Error("expected non empty GeneratedKey")
		} else {
			t.Logf("GeneratedKey: %s", rsp.GeneratedKey)
		}
	} else {
		t.FailNow()
	}
}

// ListBuckets

func TestListBucketsInDefaultBucketType(t *testing.T) {
	totalCount := 50
	bucketPrefix := fmt.Sprintf("LBDT_%d", time.Now().Unix())
	obj := getBasicObject()
	for i := 0; i < totalCount; i++ {
		bucket := fmt.Sprintf("%s_%d", bucketPrefix, i)
		store, err := NewStoreValueCommandBuilder().
			WithBucket(bucket).
			WithContent(obj).
			Build()
		if err != nil {
			panic(err.Error())
		}
		if err := cluster.Execute(store); err != nil {
			t.Fatalf("error storing test objects: %s", err.Error())
		}
	}

	var err error
	var cmd Command

	// non-streaming
	builder := NewListBucketsCommandBuilder()
	if cmd, err = builder.WithBucketType(defaultBucketType).WithStreaming(false).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListBucketsCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		count := 0
		rsp := lbc.Response
		for _, b := range rsp.Buckets {
			if strings.HasPrefix(b, bucketPrefix) {
				count++
			}
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}

	// streaming
	builder = NewListBucketsCommandBuilder()
	count := 0
	cb := func(buckets []string) error {
		for _, b := range buckets {
			if strings.HasPrefix(b, bucketPrefix) {
				count++
			}
		}
		return nil
	}
	if cmd, err = builder.WithStreaming(true).WithCallback(cb).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListBucketsCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// ListKeys

func TestListKeysInDefaultBucketType(t *testing.T) {
	totalCount := 50
	keyPrefix := fmt.Sprintf("LKDT_%d", time.Now().Unix())
	obj := getBasicObject()
	for i := 0; i < totalCount; i++ {
		key := fmt.Sprintf("%s_%d", keyPrefix, i)
		store, err := NewStoreValueCommandBuilder().
			WithBucket(testBucketName).
			WithKey(key).
			WithContent(obj).
			Build()
		if err != nil {
			panic(err.Error())
		}
		if err := cluster.Execute(store); err != nil {
			t.Fatalf("error storing test objects: %s", err.Error())
		}
	}
	var err error
	var cmd Command
	// non-streaming
	builder := NewListKeysCommandBuilder()
	if cmd, err = builder.WithBucketType(defaultBucketType).WithBucket(testBucketName).WithStreaming(false).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lkc, ok := cmd.(*ListKeysCommand); ok {
		if lkc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		count := 0
		rsp := lkc.Response
		for _, k := range rsp.Keys {
			if strings.HasPrefix(k, keyPrefix) {
				count++
			}
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}

	// streaming
	builder = NewListKeysCommandBuilder()
	count := 0
	cb := func(keys []string) error {
		for _, k := range keys {
			if strings.HasPrefix(k, keyPrefix) {
				count++
			}
		}
		return nil
	}
	if cmd, err = builder.WithBucket(testBucketName).WithStreaming(true).WithCallback(cb).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if lbc, ok := cmd.(*ListKeysCommand); ok {
		if lbc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		if expected, actual := totalCount, count; expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// FetchPreflist

func TestFetchPreflistForAValue(t *testing.T) {
	key := fmt.Sprintf("FetchPreflist_%d", time.Now().Unix())
	obj := getBasicObject()
	store, err := NewStoreValueCommandBuilder().
		WithBucket(testBucketName).
		WithKey(key).
		WithContent(obj).
		Build()
	if err != nil {
		t.Fatal(err.Error())
	}
	if err := cluster.Execute(store); err != nil {
		t.Fatalf("error storing test object: %s", err.Error())
	}

	var cmd Command
	builder := NewFetchPreflistCommandBuilder()
	if cmd, err = builder.WithBucket(testBucketName).WithKey(key).Build(); err != nil {
		t.Fatal(err.Error())
	}
	if err = cluster.Execute(cmd); err != nil {
		t.Fatal(err.Error())
	}
	if fpc, ok := cmd.(*FetchPreflistCommand); ok {
		if fpc.Response == nil {
			t.Errorf("expected non-nil Response")
		}
		rsp := fpc.Response
		if rsp.Preflist == nil {
			t.Errorf("expected non-nil Preflist")
		}
		if expected, actual := 3, len(rsp.Preflist); expected != actual {
			t.Errorf("expected %v, got %v", expected, actual)
		}
	} else {
		t.FailNow()
	}
}

// SecondaryIndexQueryCommand

func TestIntQueryAgainstDefaultType(t *testing.T) {
	t.Fatal("TODO")
}

func TestIntQueryAgainstNonDefaultType(t *testing.T) {
	t.Fatal("TODO")
}

func TestBinQueryAgainstDefaultType(t *testing.T) {
	t.Fatal("TODO")
}

func TestBinQueryAgainstNonDefaultType(t *testing.T) {
	t.Fatal("TODO")
}

func TestSetContinuationOnPaginatedQuery(t *testing.T) {
	t.Fatal("TODO")
}
<|endoftext|>


<commit_before>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build go1.7,amd64,!gccgo,!appengine

package chacha20poly1305

import (
	"encoding/binary"

	"golang.org/x/crypto/internal/subtle"
	"golang.org/x/sys/cpu"
)

//go:noescape
func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool

//go:noescape
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)

var (
	useASM  = cpu.X86.HasSSSE3
	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
)

// setupState writes a ChaCha20 input matrix to state. See
// https://tools.ietf.org/html/rfc7539#section-2.3.
func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) {
	state[0] = 0x61707865
	state[1] = 0x3320646e
	state[2] = 0x79622d32
	state[3] = 0x6b206574

	state[4] = key[0]
	state[5] = key[1]
	state[6] = key[2]
	state[7] = key[3]
	state[8] = key[4]
	state[9] = key[5]
	state[10] = key[6]
	state[11] = key[7]

	state[12] = 0
	state[13] = binary.LittleEndian.Uint32(nonce[:4])
	state[14] = binary.LittleEndian.Uint32(nonce[4:8])
	state[15] = binary.LittleEndian.Uint32(nonce[8:12])
}

func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
	if !useASM {
		return c.sealGeneric(dst, nonce, plaintext, additionalData)
	}

	var state [16]uint32
	setupState(&state, &c.key, nonce)

	ret, out := sliceForAppend(dst, len(plaintext)+16)
	if subtle.InexactOverlap(out, plaintext) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
	return ret
}

func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
	if !useASM {
		return c.openGeneric(dst, nonce, ciphertext, additionalData)
	}

	var state [16]uint32
	setupState(&state, &c.key, nonce)

	ciphertext = ciphertext[:len(ciphertext)-16]
	ret, out := sliceForAppend(dst, len(ciphertext))
	if subtle.InexactOverlap(out, ciphertext) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
		for i := range out {
			out[i] = 0
		}
		return nil, errOpen
	}

	return ret, nil
}
<commit_msg>chacha20poly1305: use x/sys/cpu feature variables directly<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build go1.7,amd64,!gccgo,!appengine

package chacha20poly1305

import (
	"encoding/binary"

	"golang.org/x/crypto/internal/subtle"
	"golang.org/x/sys/cpu"
)

//go:noescape
func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool

//go:noescape
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)

var (
	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
)

// setupState writes a ChaCha20 input matrix to state. See
// https://tools.ietf.org/html/rfc7539#section-2.3.
func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) {
	state[0] = 0x61707865
	state[1] = 0x3320646e
	state[2] = 0x79622d32
	state[3] = 0x6b206574

	state[4] = key[0]
	state[5] = key[1]
	state[6] = key[2]
	state[7] = key[3]
	state[8] = key[4]
	state[9] = key[5]
	state[10] = key[6]
	state[11] = key[7]

	state[12] = 0
	state[13] = binary.LittleEndian.Uint32(nonce[:4])
	state[14] = binary.LittleEndian.Uint32(nonce[4:8])
	state[15] = binary.LittleEndian.Uint32(nonce[8:12])
}

func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
	if !cpu.X86.HasSSSE3 {
		return c.sealGeneric(dst, nonce, plaintext, additionalData)
	}

	var state [16]uint32
	setupState(&state, &c.key, nonce)

	ret, out := sliceForAppend(dst, len(plaintext)+16)
	if subtle.InexactOverlap(out, plaintext) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
	return ret
}

func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
	if !cpu.X86.HasSSSE3 {
		return c.openGeneric(dst, nonce, ciphertext, additionalData)
	}

	var state [16]uint32
	setupState(&state, &c.key, nonce)

	ciphertext = ciphertext[:len(ciphertext)-16]
	ret, out := sliceForAppend(dst, len(ciphertext))
	if subtle.InexactOverlap(out, ciphertext) {
		panic("chacha20poly1305: invalid buffer overlap")
	}
	if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
		for i := range out {
			out[i] = 0
		}
		return nil, errOpen
	}

	return ret, nil
}
<|endoftext|>


<commit_before>package inmem

import (
	"errors"

	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/command/agent/cache"
	"github.com/hashicorp/vault/command/agent/sink"
)

// inmemSink retains the auto-auth token in memory and exposes it via
// sink.SinkReader interface.
type inmemSink struct {
	logger     hclog.Logger
	token      string
	leaseCache *cache.LeaseCache
}

// New creates a new instance of inmemSink.
func New(conf *sink.SinkConfig, leaseCache *cache.LeaseCache) (sink.Sink, error) {
	if conf.Logger == nil {
		return nil, errors.New("nil logger provided")
	}

	return &inmemSink{
		logger:     conf.Logger,
		leaseCache: leaseCache,
	}, nil
}

func (s *inmemSink) WriteToken(token string) error {
	s.token = token

	if s.leaseCache != nil {
		s.leaseCache.RegisterAutoAuthToken(token)
	}

	return nil
}

func (s *inmemSink) Token() string {
	return s.token
}
<commit_msg>agent: fix data race on inmemSink's token (#7707)<commit_after>package inmem

import (
	"errors"

	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/command/agent/cache"
	"github.com/hashicorp/vault/command/agent/sink"
	"go.uber.org/atomic"
)

// inmemSink retains the auto-auth token in memory and exposes it via
// sink.SinkReader interface.
type inmemSink struct {
	logger     hclog.Logger
	token      *atomic.String
	leaseCache *cache.LeaseCache
}

// New creates a new instance of inmemSink.
func New(conf *sink.SinkConfig, leaseCache *cache.LeaseCache) (sink.Sink, error) {
	if conf.Logger == nil {
		return nil, errors.New("nil logger provided")
	}

	return &inmemSink{
		logger:     conf.Logger,
		leaseCache: leaseCache,
		token:      atomic.NewString(""),
	}, nil
}

func (s *inmemSink) WriteToken(token string) error {
	s.token.Store(token)

	if s.leaseCache != nil {
		s.leaseCache.RegisterAutoAuthToken(token)
	}

	return nil
}

func (s *inmemSink) Token() string {
	return s.token.Load()
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"

	"code.cloudfoundry.org/bbs/db"
	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/lager"
)

type ActualLRPHandler struct {
	db       db.ActualLRPDB
	exitChan chan<- struct{}
}

func NewActualLRPHandler(db db.ActualLRPDB, exitChan chan<- struct{}) *ActualLRPHandler {
	return &ActualLRPHandler{
		db:       db,
		exitChan: exitChan,
	}
}

func (h *ActualLRPHandler) ActualLRPs(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrps")

	request := &models.ActualLRPsRequest{}
	response := &models.ActualLRPsResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		var index *int32
		if request.IndexExists() {
			i := request.GetIndex()
			index = &i
		}
		filter := models.ActualLRPFilter{Domain: request.Domain, CellID: request.CellId, Index: index, ProcessGuid: request.ProcessGuid}
		response.ActualLrps, err = h.db.ActualLRPs(req.Context(), logger, filter)
	}

	response.Error = models.ConvertError(err)

	writeResponse(w, response)
	exitIfUnrecoverable(logger, h.exitChan, response.Error)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroups(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-groups")

	request := &models.ActualLRPGroupsRequest{}
	response := &models.ActualLRPGroupsResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	filter := models.ActualLRPFilter{Domain: request.Domain, CellID: request.CellId}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroups = models.ResolveActualLRPGroups(lrps)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroupsByProcessGuid(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-groups-by-process-guid")

	request := &models.ActualLRPGroupsByProcessGuidRequest{}
	response := &models.ActualLRPGroupsResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	filter := models.ActualLRPFilter{ProcessGuid: request.ProcessGuid}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroups = models.ResolveActualLRPGroups(lrps)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroupByProcessGuidAndIndex(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-group-by-process-guid-and-index")

	request := &models.ActualLRPGroupByProcessGuidAndIndexRequest{}
	response := &models.ActualLRPGroupResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	filter := models.ActualLRPFilter{ProcessGuid: request.ProcessGuid, Index: &request.Index}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)

	if err == nil && len(lrps) == 0 {
		err = models.ErrResourceNotFound
	}

	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroup = models.ResolveActualLRPGroup(lrps)
}
<commit_msg>Log actual-lrps endpoint start/complete<commit_after>package handlers

import (
	"net/http"

	"code.cloudfoundry.org/bbs/db"
	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/lager"
)

type ActualLRPHandler struct {
	db       db.ActualLRPDB
	exitChan chan<- struct{}
}

func NewActualLRPHandler(db db.ActualLRPDB, exitChan chan<- struct{}) *ActualLRPHandler {
	return &ActualLRPHandler{
		db:       db,
		exitChan: exitChan,
	}
}

func (h *ActualLRPHandler) ActualLRPs(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrps")
	logger.Debug("starting")
	defer logger.Debug("complete")

	request := &models.ActualLRPsRequest{}
	response := &models.ActualLRPsResponse{}

	err = parseRequest(logger, req, request)
	if err == nil {
		var index *int32
		if request.IndexExists() {
			i := request.GetIndex()
			index = &i
		}
		filter := models.ActualLRPFilter{Domain: request.Domain, CellID: request.CellId, Index: index, ProcessGuid: request.ProcessGuid}
		response.ActualLrps, err = h.db.ActualLRPs(req.Context(), logger, filter)
	}

	response.Error = models.ConvertError(err)

	writeResponse(w, response)
	exitIfUnrecoverable(logger, h.exitChan, response.Error)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroups(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-groups")

	request := &models.ActualLRPGroupsRequest{}
	response := &models.ActualLRPGroupsResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}

	filter := models.ActualLRPFilter{Domain: request.Domain, CellID: request.CellId}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroups = models.ResolveActualLRPGroups(lrps)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroupsByProcessGuid(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-groups-by-process-guid")

	request := &models.ActualLRPGroupsByProcessGuidRequest{}
	response := &models.ActualLRPGroupsResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	filter := models.ActualLRPFilter{ProcessGuid: request.ProcessGuid}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroups = models.ResolveActualLRPGroups(lrps)
}

// DEPRECATED
func (h *ActualLRPHandler) ActualLRPGroupByProcessGuidAndIndex(logger lager.Logger, w http.ResponseWriter, req *http.Request) {
	var err error
	logger = logger.Session("actual-lrp-group-by-process-guid-and-index")

	request := &models.ActualLRPGroupByProcessGuidAndIndexRequest{}
	response := &models.ActualLRPGroupResponse{}
	defer func() { exitIfUnrecoverable(logger, h.exitChan, response.Error) }()
	defer writeResponse(w, response)

	err = parseRequest(logger, req, request)
	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	filter := models.ActualLRPFilter{ProcessGuid: request.ProcessGuid, Index: &request.Index}
	lrps, err := h.db.ActualLRPs(req.Context(), logger, filter)

	if err == nil && len(lrps) == 0 {
		err = models.ErrResourceNotFound
	}

	if err != nil {
		response.Error = models.ConvertError(err)
		return
	}
	response.ActualLrpGroup = models.ResolveActualLRPGroup(lrps)
}
<|endoftext|>


<commit_before>// Copyright 2018 The LUCI 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 assertions

import (
	"bytes"
	"fmt"
	"reflect"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/smartystreets/goconvey/convey"
)

// ShouldResembleProto asserts that given two values that contain proto messages
// are equal by comparing their types and ensuring they serialize to the same
// text representation.
//
// Values can either each be a proto.Message or a slice of values that each
// implement proto.Message interface.
func ShouldResembleProto(actual interface{}, expected ...interface{}) string {
	if len(expected) != 1 {
		return fmt.Sprintf("ShouldResembleProto expects 1 value, got %d", len(expected))
	}
	exp := expected[0]

	// This is very crude... We want to be able to see a diff between expected
	// and actual protos, so we just serialize them into a string and compare
	// strings. This is much simpler than trying to achieve the same using
	// reflection, clearing of XXX_*** fields and ShouldResemble.

	if m, ok := actual.(proto.Message); ok {
		if err := convey.ShouldHaveSameTypeAs(actual, exp); err != "" {
			return err
		}
		return convey.ShouldEqual(
			proto.MarshalTextString(m),
			proto.MarshalTextString(exp.(proto.Message)))
	}

	lVal := reflect.ValueOf(actual)
	rVal := reflect.ValueOf(exp)
	if lVal.Kind() == reflect.Slice {
		if rVal.Kind() != reflect.Slice {
			return "ShouldResembleProto is expecting both arguments to be a slice if first one is a slice"
		}
		if err := convey.ShouldHaveLength(actual, rVal.Len()); err != "" {
			return err
		}

		left := bytes.Buffer{}
		right := bytes.Buffer{}

		for i := 0; i < lVal.Len(); i++ {
			l := lVal.Index(i).Interface()
			r := rVal.Index(i).Interface()
			if err := convey.ShouldHaveSameTypeAs(l, r); err != "" {
				return err
			}
			if i != 0 {
				left.WriteString("---\n")
				right.WriteString("---\n")
			}
			if err := proto.MarshalText(&left, l.(proto.Message)); err != nil {
				return err.Error()
			}
			if err := proto.MarshalText(&right, r.(proto.Message)); err != nil {
				return err.Error()
			}
		}
		return convey.ShouldEqual(left.String(), right.String())
	}

	return fmt.Sprintf(
		"ShouldResembleProto doesn't know how to handle values of type %T, "+
			"expecting a proto.Message or a slice of thereof", actual)
}

// ShouldResembleProtoText is like ShouldResembleProto, but expected
// is protobuf text.
// actual must be a message. A slice of messages is not supported.
func ShouldResembleProtoText(actual interface{}, expected ...interface{}) string {
	return shouldResembleProtoUnmarshal(proto.UnmarshalText, actual, expected...)
}

// ShouldResembleProtoJSON is like ShouldResembleProto, but expected
// is protobuf text.
// actual must be a message. A slice of messages is not supported.
func ShouldResembleProtoJSON(actual interface{}, expected ...interface{}) string {
	return shouldResembleProtoUnmarshal(jsonpb.UnmarshalString, actual, expected...)
}

func shouldResembleProtoUnmarshal(unmarshal func(string, proto.Message) error, actual interface{}, expected ...interface{}) string {
	if _, ok := actual.(proto.Message); !ok {
		return fmt.Sprintf("ShouldResembleProtoText expects a proto message, got %T", actual)
	}

	if len(expected) != 1 {
		return fmt.Sprintf("ShouldResembleProtoText expects 1 value, got %d", len(expected))
	}
	expText, ok := expected[0].(string)
	if !ok {
		return fmt.Sprintf("ShouldResembleProtoText expects a string value, got %T", expected[0])
	}

	expMsg := reflect.New(reflect.TypeOf(actual).Elem()).Interface().(proto.Message)

	if err := unmarshal(expText, expMsg); err != nil {
		return err.Error()
	}
	return ShouldResembleProto(actual, expMsg)
}
<commit_msg>[testing] upgrade ShouldResembleProto to new protobuf.<commit_after>// Copyright 2018 The LUCI 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 assertions

import (
	"fmt"
	"reflect"
	"strings"

	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/encoding/prototext"
	"google.golang.org/protobuf/proto"

	protoLegacy "github.com/golang/protobuf/proto"

	"github.com/smartystreets/assertions"
)

// ShouldResembleProto asserts that given two values that contain proto messages
// are equal by comparing their types and ensuring they serialize to the same
// text representation.
//
// Values can either each be a proto.Message or a slice of values that each
// implement proto.Message interface.
func ShouldResembleProto(actual interface{}, expected ...interface{}) string {
	if len(expected) != 1 {
		return fmt.Sprintf("ShouldResembleProto expects 1 value, got %d", len(expected))
	}
	exp := expected[0]

	// This is very crude... We want to be able to see a diff between expected
	// and actual protos, so we just serialize them into a string and compare
	// strings. This is much simpler than trying to achieve the same using
	// reflection, clearing of XXX_*** fields and ShouldResemble.

	if am, ok := protoMessage(actual); ok {
		if err := assertions.ShouldHaveSameTypeAs(actual, exp); err != "" {
			return err
		}
		em, _ := protoMessage(exp)
		return assertions.ShouldEqual(textPBMultiline.Format(am), textPBMultiline.Format(em))
	}

	lVal := reflect.ValueOf(actual)
	rVal := reflect.ValueOf(exp)
	if lVal.Kind() == reflect.Slice {
		if rVal.Kind() != reflect.Slice {
			return "ShouldResembleProto is expecting both arguments to be a slice if first one is a slice"
		}
		if err := assertions.ShouldHaveLength(actual, rVal.Len()); err != "" {
			return err
		}

		var left, right strings.Builder

		for i := 0; i < lVal.Len(); i++ {
			l := lVal.Index(i).Interface()
			r := rVal.Index(i).Interface()
			if err := assertions.ShouldHaveSameTypeAs(l, r); err != "" {
				return err
			}
			if i != 0 {
				left.WriteString("---\n")
				right.WriteString("---\n")
			}
			lm, _ := protoMessage(l)
			rm, _ := protoMessage(r)
			left.WriteString(textPBMultiline.Format(lm))
			right.WriteString(textPBMultiline.Format(rm))
		}
		return assertions.ShouldEqual(left.String(), right.String())
	}

	return fmt.Sprintf(
		"ShouldResembleProto doesn't know how to handle values of type %T, "+
			"expecting a proto.Message or a slice of thereof", actual)
}

// ShouldResembleProtoText is like ShouldResembleProto, but expected
// is protobuf text.
// actual must be a message. A slice of messages is not supported.
func ShouldResembleProtoText(actual interface{}, expected ...interface{}) string {
	return shouldResembleProtoUnmarshal(
		func(s string, m proto.Message) error {
			return prototext.Unmarshal([]byte(s), m)
		},
		actual,
		expected...)
}

// ShouldResembleProtoJSON is like ShouldResembleProto, but expected
// is protobuf text.
// actual must be a message. A slice of messages is not supported.
func ShouldResembleProtoJSON(actual interface{}, expected ...interface{}) string {
	return shouldResembleProtoUnmarshal(
		func(s string, m proto.Message) error {
			return protojson.Unmarshal([]byte(s), m)
		},
		actual,
		expected...)
}

func shouldResembleProtoUnmarshal(unmarshal func(string, proto.Message) error, actual interface{}, expected ...interface{}) string {
	if _, ok := protoMessage(actual); !ok {
		return fmt.Sprintf("ShouldResembleProtoText expects a proto message, got %T", actual)
	}

	if len(expected) != 1 {
		return fmt.Sprintf("ShouldResembleProtoText expects 1 value, got %d", len(expected))
	}
	expText, ok := expected[0].(string)
	if !ok {
		return fmt.Sprintf("ShouldResembleProtoText expects a string value, got %T", expected[0])
	}

	expMsg := reflect.New(reflect.TypeOf(actual).Elem()).Interface().(proto.Message)

	if err := unmarshal(expText, expMsg); err != nil {
		return err.Error()
	}
	return ShouldResembleProto(actual, expMsg)
}

var textPBMultiline = prototext.MarshalOptions{
	Multiline: true,
}

// protoMessage returns V2 proto message, converting v1 on the fly.
func protoMessage(a interface{}) (proto.Message, bool) {
	if m, ok := a.(proto.Message); ok {
		return m, true
	}
	if m, ok := a.(protoLegacy.Message); ok {
		return protoLegacy.MessageV2(m), true
	}
	return nil, false
}
<|endoftext|>


<commit_before>package healthcheck

import (
	"errors"
	"testing"
)

func TestHealthcheckDefault(t *testing.T) {
	h := Healthcheck{
		Type: "ping",
	}
	h.Default()
	if h.Rise != 2 {
		t.Fail()
	}
	if h.Fall != 3 {
		t.Fail()
	}
}

func TestHealthcheckValidate(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Destination: "127.0.0.1",
	}
	h.Default()
	err := h.Validate("foo")
	if err != nil {
		t.Log(err)
		t.Fail()
	}
}

func TestHealthcheckValidateFailNoDestination(t *testing.T) {
	h := Healthcheck{
		Type: "notping",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck foo has no destination set" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailDestination(t *testing.T) {
	h := Healthcheck{
		Type:        "notping",
		Destination: "www.google.com",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck foo destination 'www.google.com' does not parse as an IP address" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailType(t *testing.T) {
	h := Healthcheck{
		Type:        "notping",
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Unknown healthcheck type 'notping' in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailRise(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Fall:        1,
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "rise must be > 0 in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailFall(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Rise:        1,
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "fall must be > 0 in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func myHealthCheckConstructorFail(h Healthcheck) (HealthChecker, error) {
	return nil, errors.New("Test")
}

func TestHealthcheckRegisterNew(t *testing.T) {
	registerHealthcheck("testconstructorfail", myHealthCheckConstructorFail)
	h := Healthcheck{
		Type:        "testconstructorfail",
		Destination: "127.0.0.1",
	}
	_, err := h.GetHealthChecker()
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Test" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckGetHealthcheckNotExist(t *testing.T) {
	h := Healthcheck{
		Type:        "test_this_healthcheck_does_not_exist",
		Destination: "127.0.0.1",
	}
	_, err := h.GetHealthChecker()
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck type 'test_this_healthcheck_does_not_exist' not found in the healthcheck registry" {
		t.Log(err.Error())
		t.Fail()
	}
}

type MyFakeHealthCheck struct {
	Healthy bool
}

func (h MyFakeHealthCheck) Healthcheck() bool {
	return h.Healthy
}

func MyFakeHealthConstructorOk(h Healthcheck) (HealthChecker, error) {
	return MyFakeHealthCheck{Healthy: true}, nil
}

func MyFakeHealthConstructorFail(h Healthcheck) (HealthChecker, error) {
	return MyFakeHealthCheck{Healthy: false}, nil
}

func TestHealthcheckRunSimple(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	registerHealthcheck("test_fail", MyFakeHealthConstructorFail)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 1}
	ok, err := h_ok.GetHealthChecker()
	if err != nil {
		t.Fail()
	}
	h_fail := Healthcheck{Type: "test_fail", Destination: "127.0.0.1"}
	fail, err := h_fail.GetHealthChecker()
	if err != nil {
		t.Fail()
	}
	if !ok.Healthcheck() {
		t.Fail()
	}
	if fail.Healthcheck() {
		t.Fail()
	}
	h_ok.Default()
	h_ok.Setup()
	if h_ok.IsHealthy() {
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Fail()
	}
}

func TestHealthcheckRise(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	if h_ok.IsHealthy() {
		t.Log("Started healthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if h_ok.IsHealthy() {
		t.Log("Became healthy after 1")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Log("Never became healthy")
		t.Fail()
	}
}

func TestHealthcheckFall(t *testing.T) {
	registerHealthcheck("test_fail", MyFakeHealthConstructorFail)
	h_ok := Healthcheck{Type: "test_fail", Destination: "127.0.0.1", Fall: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.History = []bool{true, true, true, true, true, true, true, true, true, true, true}
	h_ok.isHealthy = true
	if !h_ok.IsHealthy() {
		t.Log("Started unhealthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Log("Became unhealthy after 1")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if h_ok.IsHealthy() {
		t.Log("Never became unhealthy")
		t.Fail()
	}
}

func TestHealthcheckRun(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.Run()
	if !h_ok.IsRunning() {
		t.Fail()
	}
}

func TestHealthcheckStop(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.Run()
	if !h_ok.IsRunning() {
		t.Fail()
	}
	h_ok.Stop()
	if h_ok.IsRunning() {
		t.Fail()
	}
}
<commit_msg>Test History works correctly<commit_after>package healthcheck

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

func TestHealthcheckDefault(t *testing.T) {
	h := Healthcheck{
		Type: "ping",
	}
	h.Default()
	if h.Rise != 2 {
		t.Fail()
	}
	if h.Fall != 3 {
		t.Fail()
	}
}

func TestHealthcheckValidate(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Destination: "127.0.0.1",
	}
	h.Default()
	err := h.Validate("foo")
	if err != nil {
		t.Log(err)
		t.Fail()
	}
}

func TestHealthcheckValidateFailNoDestination(t *testing.T) {
	h := Healthcheck{
		Type: "notping",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck foo has no destination set" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailDestination(t *testing.T) {
	h := Healthcheck{
		Type:        "notping",
		Destination: "www.google.com",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck foo destination 'www.google.com' does not parse as an IP address" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailType(t *testing.T) {
	h := Healthcheck{
		Type:        "notping",
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Unknown healthcheck type 'notping' in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailRise(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Fall:        1,
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "rise must be > 0 in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckValidateFailFall(t *testing.T) {
	h := Healthcheck{
		Type:        "ping",
		Rise:        1,
		Destination: "127.0.0.1",
	}
	err := h.Validate("foo")
	if err == nil {
		t.Fail()
	}
	if err.Error() != "fall must be > 0 in foo" {
		t.Log(err.Error())
		t.Fail()
	}
}

func myHealthCheckConstructorFail(h Healthcheck) (HealthChecker, error) {
	return nil, errors.New("Test")
}

func TestHealthcheckRegisterNew(t *testing.T) {
	registerHealthcheck("testconstructorfail", myHealthCheckConstructorFail)
	h := Healthcheck{
		Type:        "testconstructorfail",
		Destination: "127.0.0.1",
	}
	_, err := h.GetHealthChecker()
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Test" {
		t.Log(err.Error())
		t.Fail()
	}
}

func TestHealthcheckGetHealthcheckNotExist(t *testing.T) {
	h := Healthcheck{
		Type:        "test_this_healthcheck_does_not_exist",
		Destination: "127.0.0.1",
	}
	_, err := h.GetHealthChecker()
	if err == nil {
		t.Fail()
	}
	if err.Error() != "Healthcheck type 'test_this_healthcheck_does_not_exist' not found in the healthcheck registry" {
		t.Log(err.Error())
		t.Fail()
	}
}

type MyFakeHealthCheck struct {
	Healthy bool
}

func (h MyFakeHealthCheck) Healthcheck() bool {
	return h.Healthy
}

func MyFakeHealthConstructorOk(h Healthcheck) (HealthChecker, error) {
	return MyFakeHealthCheck{Healthy: true}, nil
}

func MyFakeHealthConstructorFail(h Healthcheck) (HealthChecker, error) {
	return MyFakeHealthCheck{Healthy: false}, nil
}

func TestHealthcheckRunSimple(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	registerHealthcheck("test_fail", MyFakeHealthConstructorFail)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 1}
	ok, err := h_ok.GetHealthChecker()
	if err != nil {
		t.Fail()
	}
	h_fail := Healthcheck{Type: "test_fail", Destination: "127.0.0.1"}
	fail, err := h_fail.GetHealthChecker()
	if err != nil {
		t.Fail()
	}
	if !ok.Healthcheck() {
		t.Fail()
	}
	if fail.Healthcheck() {
		t.Fail()
	}
	h_ok.Default()
	h_ok.Setup()
	if h_ok.IsHealthy() {
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Fail()
	}
}

func TestHealthcheckRise(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	if h_ok.IsHealthy() {
		t.Log("Started healthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if h_ok.IsHealthy() {
		t.Log("Became healthy after 1")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Log("Never became healthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck() // 3
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck() // 10
	for i, v := range h_ok.History {
		if !v {
			t.Log(fmt.Printf("Index %d was unhealthy", i))
			t.Fail()
		}
	}
}

func TestHealthcheckFall(t *testing.T) {
	registerHealthcheck("test_fail", MyFakeHealthConstructorFail)
	h_ok := Healthcheck{Type: "test_fail", Destination: "127.0.0.1", Fall: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.History = []bool{true, true, true, true, true, true, true, true, true, true}
	h_ok.isHealthy = true
	if !h_ok.IsHealthy() {
		t.Log("Started unhealthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if !h_ok.IsHealthy() {
		t.Log("Became unhealthy after 1 (expected 2)")
		t.Fail()
	}
	h_ok.PerformHealthcheck()
	if h_ok.IsHealthy() {
		t.Log("Never became unhealthy")
		t.Fail()
	}
	h_ok.PerformHealthcheck() // 3
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck()
	h_ok.PerformHealthcheck() // 10
	for i, v := range h_ok.History {
		if v {
			t.Log(fmt.Printf("Index %d was healthy", i))
			t.Fail()
		}
	}
}

func TestHealthcheckRun(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.Run()
	if !h_ok.IsRunning() {
		t.Fail()
	}
}

func TestHealthcheckStop(t *testing.T) {
	registerHealthcheck("test_ok", MyFakeHealthConstructorOk)
	h_ok := Healthcheck{Type: "test_ok", Destination: "127.0.0.1", Rise: 2}
	h_ok.Default()
	h_ok.Setup()
	h_ok.Run()
	if !h_ok.IsRunning() {
		t.Fail()
	}
	h_ok.Stop()
	if h_ok.IsRunning() {
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package healthnearme

import geo "github.com/kellydunn/golang-geo"

type HealthProvider struct {
	Name        string             `json:"name"`
	State       string             `json:"state"`
	Address     string             `json:"address"`
	City        string             `json:"city"`
	ZipCode     int                `json:"zip_code,string"`
	Location    Location           `json:"location"`
	PhoneNumber string             `json:"phone"`
	Hours       string             `json:"hours_of_operation"`
	Type        HealthProviderType `json:"provider_type"`
	Distance    float64            `json:"distance,string,omitempty"`
	TypeName	string	`json:"type_name,omitempty"`
}

type HealthProviderType int

const (
	CondomDistributionSite HealthProviderType = iota
	SubstanceAbuseProvider
	MentalHealthClinic
	STISpecialtyClinic
	WICClinic
)

func (hp *HealthProvider) FormatLocation() {
	hp.Location.FormatLocation()
}

// Return the distance, in miles, between the HealthProvider and a given Point
func (hp HealthProvider) CalcDistance(p *geo.Point) float64 {
	return p.GreatCircleDistance(geo.NewPoint(hp.Location.Latitude, hp.Location.Longitude)) * 0.621371
}

func (hp HealthProvider) FriendlyTypeName() string {
	switch hp.Type {
		case CondomDistributionSite:
			return "Condom Distribution Site"
		case SubstanceAbuseProvider:
			return "Licensed Substance Abuse Provider"
		case MentalHealthClinic:
			return "Mental Health Clinic"
		case STISpecialtyClinic:
			return "STI Specialty Clinic"
		case WICClinic:
			return "WIC Clinic"
	}

	return ""
}<commit_msg>gofmt<commit_after>package healthnearme

import geo "github.com/kellydunn/golang-geo"

type HealthProvider struct {
	Name        string             `json:"name"`
	State       string             `json:"state"`
	Address     string             `json:"address"`
	City        string             `json:"city"`
	ZipCode     int                `json:"zip_code,string"`
	Location    Location           `json:"location"`
	PhoneNumber string             `json:"phone"`
	Hours       string             `json:"hours_of_operation"`
	Type        HealthProviderType `json:"provider_type"`
	Distance    float64            `json:"distance,string,omitempty"`
	TypeName    string             `json:"type_name,omitempty"`
}

type HealthProviderType int

const (
	CondomDistributionSite HealthProviderType = iota
	SubstanceAbuseProvider
	MentalHealthClinic
	STISpecialtyClinic
	WICClinic
)

func (hp *HealthProvider) FormatLocation() {
	hp.Location.FormatLocation()
}

// Return the distance, in miles, between the HealthProvider and a given Point
func (hp HealthProvider) CalcDistance(p *geo.Point) float64 {
	return p.GreatCircleDistance(geo.NewPoint(hp.Location.Latitude, hp.Location.Longitude)) * 0.621371
}

func (hp HealthProvider) FriendlyTypeName() string {
	switch hp.Type {
	case CondomDistributionSite:
		return "Condom Distribution Site"
	case SubstanceAbuseProvider:
		return "Licensed Substance Abuse Provider"
	case MentalHealthClinic:
		return "Mental Health Clinic"
	case STISpecialtyClinic:
		return "STI Specialty Clinic"
	case WICClinic:
		return "WIC Clinic"
	}

	return ""
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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 main

import (
	"cups-connector/lib"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"time"
)

func main() {
	config, err := lib.ConfigFromFile()
	if err != nil {
		log.Fatal(err)
	}

	if _, err := os.Stat(config.MonitorSocketFilename); err != nil {
		if !os.IsNotExist(err) {
			log.Fatal(err)
		}
		log.Fatal(fmt.Sprintf(
			"No connector is running, or the monitoring socket %s is mis-configured",
			config.MonitorSocketFilename))
	}

	conn, err := net.DialTimeout("unix", config.MonitorSocketFilename, time.Second)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	buf, err := ioutil.ReadAll(conn)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf(string(buf))
}
<commit_msg>Add timeout to connector-monitor<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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 main

import (
	"cups-connector/lib"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"time"
)

func main() {
	config, err := lib.ConfigFromFile()
	if err != nil {
		log.Fatal(err)
	}

	if _, err := os.Stat(config.MonitorSocketFilename); err != nil {
		if !os.IsNotExist(err) {
			log.Fatal(err)
		}
		log.Fatal(fmt.Errorf(
			"No connector is running, or the monitoring socket %s is mis-configured",
			config.MonitorSocketFilename))
	}

	ch := make(chan bool)

	go func() {
		conn, err := net.DialTimeout("unix", config.MonitorSocketFilename, time.Second)
		if err != nil {
			log.Fatal(fmt.Errorf(
				"No connector is running, or it is not listening to socket %s",
				config.MonitorSocketFilename))
		}
		defer conn.Close()

		buf, err := ioutil.ReadAll(conn)
		if err != nil {
			log.Fatal(err)
		}

		ch <- true
		fmt.Printf(string(buf))
		<-ch
	}()

	select {
	case <-ch:
		ch <- true
		return
	case <-time.After(time.Second * 3):
		log.Fatal("timeout")
	}
}
<|endoftext|>


<commit_before>package integration_test

import (
	"fmt"
	"math/rand"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/rosenhouse/tubes/lib/awsclient"
)

const templateBody = `{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
  "NATSecurityGroup": {
    "Type": "AWS::EC2::SecurityGroup",
    "Properties": {
      "SecurityGroupIngress": [
        {
          "ToPort": "22",
          "IpProtocol": "tcp",
          "FromPort": "22",
          "CidrIp": "0.0.0.0/0"
        }
      ],
      "GroupDescription": "test-group",
      "SecurityGroupEgress": []
    }
  }
}
}`

var _ = Describe("Integration", func() {
	var (
		client    *awsclient.Client
		stackName string
	)

	BeforeEach(func() {
		client = awsclient.New(awsclient.Config{
			Region:    os.Getenv("AWS_DEFAULT_REGION"),
			AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
			SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
		})
		stackName = fmt.Sprintf("test-stack-%d", rand.Int63())
	})
	AfterEach(func() {
		client.CloudFormation.DeleteStack(&cloudformation.DeleteStackInput{
			StackName: aws.String(stackName),
		})
	})

	Describe("CloudFormation", func() {
		Describe("UpdateStack", func() {
			Context("when the stack does not exist", func() {
				It("should succeed", func() {
					_, err := client.CloudFormation.CreateStack(&cloudformation.CreateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).NotTo(HaveOccurred())
				})
			})
		})
		Describe("CreateStack", func() {
			Context("when the stack already exists", func() {
				It("should return an AlreadyExists error", func() {
					_, err := client.CloudFormation.CreateStack(&cloudformation.CreateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).NotTo(HaveOccurred())

					_, err = client.CloudFormation.CreateStack(&cloudformation.CreateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).To(HaveOccurred())
					awserr := err.(awserr.Error)
					Expect(awserr.Code()).To(Equal("AlreadyExistsException"))
				})
			})
		})
		Describe("DescribeStacks", func() {
			Context("when the stack does not exist", func() {
				It("should return a ValidationError error", func() {
					_, err := client.CloudFormation.DescribeStacks(&cloudformation.DescribeStacksInput{
						StackName: aws.String(stackName),
					})
					Expect(err).To(HaveOccurred())
					awsErr := err.(awserr.Error)
					Expect(awsErr.Code()).To(Equal("ValidationError"))
					Expect(awsErr.Message()).To(ContainSubstring("does not exist"))
				})
			})
		})
	})
})
<commit_msg>UpdateStack does, in fact, error on a non-existent stack<commit_after>package integration_test

import (
	"fmt"
	"math/rand"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/cloudformation"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/rosenhouse/tubes/lib/awsclient"
)

const templateBody = `{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
  "NATSecurityGroup": {
    "Type": "AWS::EC2::SecurityGroup",
    "Properties": {
      "SecurityGroupIngress": [
        {
          "ToPort": "22",
          "IpProtocol": "tcp",
          "FromPort": "22",
          "CidrIp": "0.0.0.0/0"
        }
      ],
      "GroupDescription": "test-group",
      "SecurityGroupEgress": []
    }
  }
}
}`

var _ = Describe("Integration", func() {
	var (
		client    *awsclient.Client
		stackName string
	)

	BeforeEach(func() {
		client = awsclient.New(awsclient.Config{
			Region:    os.Getenv("AWS_DEFAULT_REGION"),
			AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
			SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
		})
		stackName = fmt.Sprintf("test-stack-%d", rand.Int63())
	})
	AfterEach(func() {
		client.CloudFormation.DeleteStack(&cloudformation.DeleteStackInput{
			StackName: aws.String(stackName),
		})
	})

	Describe("CloudFormation", func() {
		Describe("UpdateStack", func() {
			Context("when the stack does not exist", func() {
				It("should error", func() {
					_, err := client.CloudFormation.UpdateStack(&cloudformation.UpdateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).To(HaveOccurred())
					awserr := err.(awserr.Error)
					Expect(awserr.Code()).To(Equal("ValidationError"))
					Expect(awserr.Message()).To(ContainSubstring("does not exist"))
				})
			})
		})
		Describe("CreateStack", func() {
			Context("when the stack already exists", func() {
				It("should return an AlreadyExists error", func() {
					_, err := client.CloudFormation.CreateStack(&cloudformation.CreateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).NotTo(HaveOccurred())

					_, err = client.CloudFormation.CreateStack(&cloudformation.CreateStackInput{
						StackName:    aws.String(stackName),
						TemplateBody: aws.String(templateBody),
					})
					Expect(err).To(HaveOccurred())
					awserr := err.(awserr.Error)
					Expect(awserr.Code()).To(Equal("AlreadyExistsException"))
				})
			})
		})
		Describe("DescribeStacks", func() {
			Context("when the stack does not exist", func() {
				It("should return a ValidationError error", func() {
					_, err := client.CloudFormation.DescribeStacks(&cloudformation.DescribeStacksInput{
						StackName: aws.String(stackName),
					})
					Expect(err).To(HaveOccurred())
					awsErr := err.(awserr.Error)
					Expect(awsErr.Code()).To(Equal("ValidationError"))
					Expect(awsErr.Message()).To(ContainSubstring("does not exist"))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>// Package namtransforms encrypts and decrypts filenames.
package nametransform

import (
	"crypto/aes"
	"encoding/base64"
	"fmt"

	"github.com/rfjakob/eme"

	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/internal/tlog"
)

type NameTransform struct {
	cryptoCore *cryptocore.CryptoCore
	longNames  bool
	DirIVCache dirIVCache
}

func New(c *cryptocore.CryptoCore, longNames bool) *NameTransform {
	return &NameTransform{
		cryptoCore: c,
		longNames:  longNames,
	}
}

// DecryptName - decrypt base64-encoded encrypted filename "cipherName"
// Used by DecryptPathDirIV().
// The encryption is either CBC or EME, depending on "useEME".
//
// This function is exported because it allows for a very efficient readdir
// implementation (read IV once, decrypt all names using this function).
func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error) {
	bin, err := base64.URLEncoding.DecodeString(cipherName)
	if err != nil {
		return "", err
	}
	if len(bin)%aes.BlockSize != 0 {
		return "", fmt.Errorf("Decoded length %d is not a multiple of the AES block size", len(bin))
	}
	bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionDecrypt)
	bin, err = unPad16(bin)
	if err != nil {
		tlog.Debug.Printf("pad16 error detail: %v", err)
		// unPad16 returns detailed errors including the position of the
		// incorrect bytes. Kill the padding oracle by lumping everything into
		// a generic error.
		return "", fmt.Errorf("Invalid padding")
	}
	plain := string(bin)
	return plain, err
}

// encryptName - encrypt "plainName", return base64-encoded "cipherName64".
// Used internally by EncryptPathDirIV().
// The encryption is either CBC or EME, depending on "useEME".
//
// This function is exported because fusefrontend needs access to the full (not hashed)
// name if longname is used. Otherwise you should use EncryptPathDirIV()
func (n *NameTransform) EncryptName(plainName string, iv []byte) (cipherName64 string) {
	bin := []byte(plainName)
	bin = pad16(bin)
	bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionEncrypt)
	cipherName64 = base64.URLEncoding.EncodeToString(bin)
	return cipherName64
}
<commit_msg>nametransform: return EINVAL on invalid padding<commit_after>// Package namtransforms encrypts and decrypts filenames.
package nametransform

import (
	"crypto/aes"
	"encoding/base64"
	"fmt"
	"syscall"

	"github.com/rfjakob/eme"

	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/internal/tlog"
)

type NameTransform struct {
	cryptoCore *cryptocore.CryptoCore
	longNames  bool
	DirIVCache dirIVCache
}

func New(c *cryptocore.CryptoCore, longNames bool) *NameTransform {
	return &NameTransform{
		cryptoCore: c,
		longNames:  longNames,
	}
}

// DecryptName - decrypt base64-encoded encrypted filename "cipherName"
// Used by DecryptPathDirIV().
// The encryption is either CBC or EME, depending on "useEME".
//
// This function is exported because it allows for a very efficient readdir
// implementation (read IV once, decrypt all names using this function).
func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error) {
	bin, err := base64.URLEncoding.DecodeString(cipherName)
	if err != nil {
		return "", err
	}
	if len(bin)%aes.BlockSize != 0 {
		return "", fmt.Errorf("Decoded length %d is not a multiple of the AES block size", len(bin))
	}
	bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionDecrypt)
	bin, err = unPad16(bin)
	if err != nil {
		tlog.Debug.Printf("pad16 error detail: %v", err)
		// unPad16 returns detailed errors including the position of the
		// incorrect bytes. Kill the padding oracle by lumping everything into
		// a generic error.
		return "", syscall.EINVAL
	}
	plain := string(bin)
	return plain, err
}

// encryptName - encrypt "plainName", return base64-encoded "cipherName64".
// Used internally by EncryptPathDirIV().
// The encryption is either CBC or EME, depending on "useEME".
//
// This function is exported because fusefrontend needs access to the full (not hashed)
// name if longname is used. Otherwise you should use EncryptPathDirIV()
func (n *NameTransform) EncryptName(plainName string, iv []byte) (cipherName64 string) {
	bin := []byte(plainName)
	bin = pad16(bin)
	bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionEncrypt)
	cipherName64 = base64.URLEncoding.EncodeToString(bin)
	return cipherName64
}
<|endoftext|>