<commit_before>package discover

import (
	"errors"
	"net"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/flynn/rpcplus"
)

var WaitTimeoutSecs = 10

type Service struct {
	Created int
	Name    string
	Host    string
	Port    string
	Addr    string
	Attrs   map[string]string
}

type ServiceSet struct {
	services   map[string]*Service
	filters    map[string]string
	watches    map[chan *ServiceUpdate]struct{}
	serMutex   sync.Mutex
	filMutex   sync.Mutex
	watchMutex sync.Mutex
	call       *rpcplus.Call
}

func copyService(service *Service) *Service {
	s := *service
	s.Attrs = make(map[string]string, len(service.Attrs))
	for k, v := range service.Attrs {
		s.Attrs[k] = v
	}
	return &s
}

func makeServiceSet(call *rpcplus.Call) *ServiceSet {
	return &ServiceSet{
		services: make(map[string]*Service),
		filters:  make(map[string]string),
		watches:  make(map[chan *ServiceUpdate]struct{}),
		call:     call,
	}
}

func (s *ServiceSet) bind(updates chan *ServiceUpdate) chan struct{} {
	// current is an event when enough service updates have been
	// received to bring us to "current" state (when subscribed)
	current := make(chan struct{})
	go func() {
		isCurrent := false
		for update := range updates {
			if update.Addr == "" && update.Name == "" && !isCurrent {
				close(current)
				isCurrent = true
				continue
			}
			if s.filters != nil && !s.matchFilters(update.Attrs) {
				continue
			}

			s.serMutex.Lock()
			if update.Online {
				if _, exists := s.services[update.Addr]; !exists {
					host, port, _ := net.SplitHostPort(update.Addr)
					s.services[update.Addr] = &Service{
						Name: update.Name,
						Addr: update.Addr,
						Host: host,
						Port: port,
					}
				}
				s.services[update.Addr].Attrs = update.Attrs
			} else {
				if _, exists := s.services[update.Addr]; exists {
					delete(s.services, update.Addr)
				} else {
					s.serMutex.Unlock()
					continue
				}
			}
			s.serMutex.Unlock()
			s.updateWatches(update)
		}
		s.closeWatches()
	}()
	return current
}

func (s *ServiceSet) updateWatches(update *ServiceUpdate) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	for ch := range s.watches {
		ch <- update
	}
}

func (s *ServiceSet) closeWatches() {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	for ch := range s.watches {
		close(ch)
	}
}

func (s *ServiceSet) matchFilters(attrs map[string]string) bool {
	s.filMutex.Lock()
	defer s.filMutex.Unlock()
	for key, value := range s.filters {
		if attrs[key] != value {
			return false
		}
	}
	return true
}

// deprecated
func (s *ServiceSet) Online() []*Service {
	return s.Services()
}

func (s *ServiceSet) Services() []*Service {
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	list := make([]*Service, 0, len(s.services))
	for _, service := range s.services {
		list = append(list, copyService(service))
	}
	return list
}

// deprecated
func (s *ServiceSet) OnlineAddrs() []string {
	return s.Addrs()
}

func (s *ServiceSet) Addrs() []string {
	list := make([]string, 0, len(s.services))
	for _, service := range s.Services() {
		list = append(list, service.Addr)
	}
	return list
}

func (s *ServiceSet) Select(attrs map[string]string) []*Service {
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	list := make([]*Service, 0, len(s.services))
outer:
	for _, service := range s.services {
		for key, value := range attrs {
			if service.Attrs[key] != value {
				continue outer
			}
		}
		list = append(list, service)
	}
	return list
}

func (s *ServiceSet) Filter(attrs map[string]string) {
	s.filMutex.Lock()
	s.filters = attrs
	s.filMutex.Unlock()
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	for key, service := range s.services {
		if !s.matchFilters(service.Attrs) {
			delete(s.services, key)
		}
	}
}

func (s *ServiceSet) Watch(ch chan *ServiceUpdate, bringCurrent bool) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	s.watches[ch] = struct{}{}
	if bringCurrent {
		go func() {
			s.serMutex.Lock()
			defer s.serMutex.Unlock()
			for _, service := range s.services {
				ch <- &ServiceUpdate{
					Name:   service.Name,
					Addr:   service.Addr,
					Online: true,
					Attrs:  service.Attrs,
				}
			}
		}()
	}
}

func (s *ServiceSet) Unwatch(ch chan *ServiceUpdate) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	delete(s.watches, ch)
}

func (s *ServiceSet) Wait() (*ServiceUpdate, error) {
	updateCh := make(chan *ServiceUpdate, 1)
	s.Watch(updateCh, true)
	defer s.Unwatch(updateCh)
	timeout := make(chan struct{})
	go func() {
		time.Sleep(time.Duration(WaitTimeoutSecs) * time.Second)
		timeout <- struct{}{}
	}()
	select {
	case update := <-updateCh:
		return update, nil
	case <-timeout:
		return nil, errors.New("discover: wait timeout exceeded")
	}
}

func (s *ServiceSet) Close() error {
	err := s.call.CloseStream()
	if err != nil {
		return err
	}
	return nil
}

type Client struct {
	client     *rpcplus.Client
	heartbeats map[string]chan struct{}
	hbMutex    sync.Mutex
}

func NewClient() (*Client, error) {
	addr := os.Getenv("DISCOVERD")
	if addr == "" {
		addr = "127.0.0.1:1111"
	}
	return NewClientUsingAddress(addr)
}

func NewClientUsingAddress(addr string) (*Client, error) {
	client, err := rpcplus.DialHTTP("tcp", addr)
	return &Client{
		client:     client,
		heartbeats: make(map[string]chan struct{}),
	}, err
}

func pickMostPublicIp() string {
	// TODO: prefer non 10.0.0.0, 172.16.0.0, and 192.168.0.0
	addrs, _ := net.InterfaceAddrs()
	var ip string
	for _, addr := range addrs {
		ip = strings.SplitN(addr.String(), "/", 2)[0]
		if !strings.Contains(ip, "::") && ip != "127.0.0.1" {
			return ip
		}
	}
	return ip
}

func (c *Client) ServiceSet(name string) (*ServiceSet, error) {
	updates := make(chan *ServiceUpdate)
	call := c.client.StreamGo("Agent.Subscribe", &Args{
		Name: name,
	}, updates)
	set := makeServiceSet(call)
	<-set.bind(updates)
	return set, nil
}

func (c *Client) Services(name string) ([]*Service, error) {
	set, err := c.ServiceSet(name)
	if err != nil {
		return nil, err
	}
	if len(set.Services()) == 0 {
		_, err = set.Wait()
		if err != nil {
			return nil, err
		}
	}
	set.Close()
	return set.Services(), nil

}

func (c *Client) Register(name, port string, attributes map[string]string) error {
	return c.RegisterWithHost(name, pickMostPublicIp(), port, attributes)
}

func (c *Client) RegisterWithHost(name, host, port string, attributes map[string]string) error {
	args := &Args{
		Name:  name,
		Addr:  net.JoinHostPort(host, port),
		Attrs: attributes,
	}
	var ret struct{}
	err := c.client.Call("Agent.Register", args, &ret)
	if err != nil {
		return errors.New("discover: register failed: " + err.Error())
	}
	done := make(chan struct{})
	c.hbMutex.Lock()
	c.heartbeats[args.Addr] = done
	c.hbMutex.Unlock()
	go func() {
		ticker := time.NewTicker(HeartbeatIntervalSecs * time.Second) // TODO: add jitter
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				// TODO: log error here
				c.client.Call("Agent.Heartbeat", &Args{
					Name: name,
					Addr: args.Addr,
				}, &struct{}{})
			case <-done:
				return
			}
		}
	}()
	return nil
}

func (c *Client) Unregister(name, port string) error {
	return c.UnregisterWithHost(name, pickMostPublicIp(), port)
}

func (c *Client) UnregisterWithHost(name, host, port string) error {
	args := &Args{
		Name: name,
		Addr: net.JoinHostPort(host, port),
	}
	c.hbMutex.Lock()
	close(c.heartbeats[args.Addr])
	delete(c.heartbeats, args.Addr)
	c.hbMutex.Unlock()
	err := c.client.Call("Agent.Unregister", args, &struct{}{})
	if err != nil {
		return errors.New("discover: unregister failed: " + err.Error())
	}
	return nil
}
<commit_msg>discoverd: using time.After for timeout<commit_after>package discover

import (
	"errors"
	"net"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/flynn/rpcplus"
)

var WaitTimeoutSecs = 10

type Service struct {
	Created int
	Name    string
	Host    string
	Port    string
	Addr    string
	Attrs   map[string]string
}

type ServiceSet struct {
	services   map[string]*Service
	filters    map[string]string
	watches    map[chan *ServiceUpdate]struct{}
	serMutex   sync.Mutex
	filMutex   sync.Mutex
	watchMutex sync.Mutex
	call       *rpcplus.Call
}

func copyService(service *Service) *Service {
	s := *service
	s.Attrs = make(map[string]string, len(service.Attrs))
	for k, v := range service.Attrs {
		s.Attrs[k] = v
	}
	return &s
}

func makeServiceSet(call *rpcplus.Call) *ServiceSet {
	return &ServiceSet{
		services: make(map[string]*Service),
		filters:  make(map[string]string),
		watches:  make(map[chan *ServiceUpdate]struct{}),
		call:     call,
	}
}

func (s *ServiceSet) bind(updates chan *ServiceUpdate) chan struct{} {
	// current is an event when enough service updates have been
	// received to bring us to "current" state (when subscribed)
	current := make(chan struct{})
	go func() {
		isCurrent := false
		for update := range updates {
			if update.Addr == "" && update.Name == "" && !isCurrent {
				close(current)
				isCurrent = true
				continue
			}
			if s.filters != nil && !s.matchFilters(update.Attrs) {
				continue
			}

			s.serMutex.Lock()
			if update.Online {
				if _, exists := s.services[update.Addr]; !exists {
					host, port, _ := net.SplitHostPort(update.Addr)
					s.services[update.Addr] = &Service{
						Name: update.Name,
						Addr: update.Addr,
						Host: host,
						Port: port,
					}
				}
				s.services[update.Addr].Attrs = update.Attrs
			} else {
				if _, exists := s.services[update.Addr]; exists {
					delete(s.services, update.Addr)
				} else {
					s.serMutex.Unlock()
					continue
				}
			}
			s.serMutex.Unlock()
			s.updateWatches(update)
		}
		s.closeWatches()
	}()
	return current
}

func (s *ServiceSet) updateWatches(update *ServiceUpdate) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	for ch := range s.watches {
		ch <- update
	}
}

func (s *ServiceSet) closeWatches() {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	for ch := range s.watches {
		close(ch)
	}
}

func (s *ServiceSet) matchFilters(attrs map[string]string) bool {
	s.filMutex.Lock()
	defer s.filMutex.Unlock()
	for key, value := range s.filters {
		if attrs[key] != value {
			return false
		}
	}
	return true
}

// deprecated
func (s *ServiceSet) Online() []*Service {
	return s.Services()
}

func (s *ServiceSet) Services() []*Service {
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	list := make([]*Service, 0, len(s.services))
	for _, service := range s.services {
		list = append(list, copyService(service))
	}
	return list
}

// deprecated
func (s *ServiceSet) OnlineAddrs() []string {
	return s.Addrs()
}

func (s *ServiceSet) Addrs() []string {
	list := make([]string, 0, len(s.services))
	for _, service := range s.Services() {
		list = append(list, service.Addr)
	}
	return list
}

func (s *ServiceSet) Select(attrs map[string]string) []*Service {
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	list := make([]*Service, 0, len(s.services))
outer:
	for _, service := range s.services {
		for key, value := range attrs {
			if service.Attrs[key] != value {
				continue outer
			}
		}
		list = append(list, service)
	}
	return list
}

func (s *ServiceSet) Filter(attrs map[string]string) {
	s.filMutex.Lock()
	s.filters = attrs
	s.filMutex.Unlock()
	s.serMutex.Lock()
	defer s.serMutex.Unlock()
	for key, service := range s.services {
		if !s.matchFilters(service.Attrs) {
			delete(s.services, key)
		}
	}
}

func (s *ServiceSet) Watch(ch chan *ServiceUpdate, bringCurrent bool) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	s.watches[ch] = struct{}{}
	if bringCurrent {
		go func() {
			s.serMutex.Lock()
			defer s.serMutex.Unlock()
			for _, service := range s.services {
				ch <- &ServiceUpdate{
					Name:   service.Name,
					Addr:   service.Addr,
					Online: true,
					Attrs:  service.Attrs,
				}
			}
		}()
	}
}

func (s *ServiceSet) Unwatch(ch chan *ServiceUpdate) {
	s.watchMutex.Lock()
	defer s.watchMutex.Unlock()
	delete(s.watches, ch)
}

func (s *ServiceSet) Wait() (*ServiceUpdate, error) {
	updateCh := make(chan *ServiceUpdate, 1)
	s.Watch(updateCh, true)
	defer s.Unwatch(updateCh)
	select {
	case update := <-updateCh:
		return update, nil
	case <-time.After(time.Duration(WaitTimeoutSecs) * time.Second):
		return nil, errors.New("discover: wait timeout exceeded")
	}
}

func (s *ServiceSet) Close() error {
	err := s.call.CloseStream()
	if err != nil {
		return err
	}
	return nil
}

type Client struct {
	client     *rpcplus.Client
	heartbeats map[string]chan struct{}
	hbMutex    sync.Mutex
}

func NewClient() (*Client, error) {
	addr := os.Getenv("DISCOVERD")
	if addr == "" {
		addr = "127.0.0.1:1111"
	}
	return NewClientUsingAddress(addr)
}

func NewClientUsingAddress(addr string) (*Client, error) {
	client, err := rpcplus.DialHTTP("tcp", addr)
	return &Client{
		client:     client,
		heartbeats: make(map[string]chan struct{}),
	}, err
}

func pickMostPublicIp() string {
	// TODO: prefer non 10.0.0.0, 172.16.0.0, and 192.168.0.0
	addrs, _ := net.InterfaceAddrs()
	var ip string
	for _, addr := range addrs {
		ip = strings.SplitN(addr.String(), "/", 2)[0]
		if !strings.Contains(ip, "::") && ip != "127.0.0.1" {
			return ip
		}
	}
	return ip
}

func (c *Client) ServiceSet(name string) (*ServiceSet, error) {
	updates := make(chan *ServiceUpdate)
	call := c.client.StreamGo("Agent.Subscribe", &Args{
		Name: name,
	}, updates)
	set := makeServiceSet(call)
	<-set.bind(updates)
	return set, nil
}

func (c *Client) Services(name string) ([]*Service, error) {
	set, err := c.ServiceSet(name)
	if err != nil {
		return nil, err
	}
	if len(set.Services()) == 0 {
		_, err = set.Wait()
		if err != nil {
			return nil, err
		}
	}
	set.Close()
	return set.Services(), nil

}

func (c *Client) Register(name, port string, attributes map[string]string) error {
	return c.RegisterWithHost(name, pickMostPublicIp(), port, attributes)
}

func (c *Client) RegisterWithHost(name, host, port string, attributes map[string]string) error {
	args := &Args{
		Name:  name,
		Addr:  net.JoinHostPort(host, port),
		Attrs: attributes,
	}
	var ret struct{}
	err := c.client.Call("Agent.Register", args, &ret)
	if err != nil {
		return errors.New("discover: register failed: " + err.Error())
	}
	done := make(chan struct{})
	c.hbMutex.Lock()
	c.heartbeats[args.Addr] = done
	c.hbMutex.Unlock()
	go func() {
		ticker := time.NewTicker(HeartbeatIntervalSecs * time.Second) // TODO: add jitter
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				// TODO: log error here
				c.client.Call("Agent.Heartbeat", &Args{
					Name: name,
					Addr: args.Addr,
				}, &struct{}{})
			case <-done:
				return
			}
		}
	}()
	return nil
}

func (c *Client) Unregister(name, port string) error {
	return c.UnregisterWithHost(name, pickMostPublicIp(), port)
}

func (c *Client) UnregisterWithHost(name, host, port string) error {
	args := &Args{
		Name: name,
		Addr: net.JoinHostPort(host, port),
	}
	c.hbMutex.Lock()
	close(c.heartbeats[args.Addr])
	delete(c.heartbeats, args.Addr)
	c.hbMutex.Unlock()
	err := c.client.Call("Agent.Unregister", args, &struct{}{})
	if err != nil {
		return errors.New("discover: unregister failed: " + err.Error())
	}
	return nil
}
<|endoftext|>


<commit_before>package detector

import (
	log "github.com/Sirupsen/logrus"
	"github.com/cheggaaa/pb/v3"
	"os"
	"talisman/checksumcalculator"
	"talisman/detector/detector"
	"talisman/detector/filecontent"
	"talisman/detector/filename"
	"talisman/detector/helpers"
	"talisman/detector/pattern"
	"talisman/gitrepo"
	"talisman/talismanrc"
	"talisman/utility"
)

//Chain represents a chain of Detectors.
//It is itself a detector.
type Chain struct {
	detectors []detector.Detector
}

//NewChain returns an empty DetectorChain
//It is itself a detector, but it tests nothing.
func NewChain() *Chain {
	result := Chain{make([]detector.Detector, 0)}
	return &result
}

//DefaultChain returns a DetectorChain with pre-configured detectors
func DefaultChain(tRC *talismanrc.TalismanRC) *Chain {
	result := NewChain()
	result.AddDetector(filename.DefaultFileNameDetector(tRC.Threshold))
	result.AddDetector(filecontent.NewFileContentDetector(tRC))
	result.AddDetector(pattern.NewPatternDetector(tRC.CustomPatterns))
	return result
}

//AddDetector adds the detector that is passed in to the chain
func (dc *Chain) AddDetector(d detector.Detector) *Chain {
	dc.detectors = append(dc.detectors, d)
	return dc
}

//Test validates the additions against each detector in the chain.
//The results are passed in from detector to detector and thus collect all errors from all detectors
func (dc *Chain) Test(currentAdditions []gitrepo.Addition, talismanRC *talismanrc.TalismanRC, result *helpers.DetectionResults) {
	wd, _ := os.Getwd()
	repo := gitrepo.RepoLocatedAt(wd)
	allAdditions := repo.TrackedFilesAsAdditions()
	hasher := utility.DefaultSHA256Hasher{}
	calculator := checksumcalculator.NewChecksumCalculator(hasher, append(allAdditions, currentAdditions...))
	cc := helpers.NewChecksumCompare(calculator, hasher, talismanRC)
	log.Printf("Number of files to scan: %d\n", len(currentAdditions))
	log.Printf("Number of detectors: %d\n", len(dc.detectors))
	total := len(currentAdditions) * len(dc.detectors)
	bar := pb.StartNew(total)
	for _, v := range dc.detectors {
		v.Test(cc, currentAdditions, talismanRC, result, func() {
			bar.Increment()
		})
	}
	bar.Finish()
}
<commit_msg>Formatting the Progress bar (#268)<commit_after>package detector

import (
	log "github.com/Sirupsen/logrus"
	"github.com/cheggaaa/pb/v3"
	"os"
	"talisman/checksumcalculator"
	"talisman/detector/detector"
	"talisman/detector/filecontent"
	"talisman/detector/filename"
	"talisman/detector/helpers"
	"talisman/detector/pattern"
	"talisman/gitrepo"
	"talisman/talismanrc"
	"talisman/utility"
)

//Chain represents a chain of Detectors.
//It is itself a detector.
type Chain struct {
	detectors []detector.Detector
}

//NewChain returns an empty DetectorChain
//It is itself a detector, but it tests nothing.
func NewChain() *Chain {
	result := Chain{make([]detector.Detector, 0)}
	return &result
}

//DefaultChain returns a DetectorChain with pre-configured detectors
func DefaultChain(tRC *talismanrc.TalismanRC) *Chain {
	result := NewChain()
	result.AddDetector(filename.DefaultFileNameDetector(tRC.Threshold))
	result.AddDetector(filecontent.NewFileContentDetector(tRC))
	result.AddDetector(pattern.NewPatternDetector(tRC.CustomPatterns))
	return result
}

//AddDetector adds the detector that is passed in to the chain
func (dc *Chain) AddDetector(d detector.Detector) *Chain {
	dc.detectors = append(dc.detectors, d)
	return dc
}

//Test validates the additions against each detector in the chain.
//The results are passed in from detector to detector and thus collect all errors from all detectors
func (dc *Chain) Test(currentAdditions []gitrepo.Addition, talismanRC *talismanrc.TalismanRC, result *helpers.DetectionResults) {
	wd, _ := os.Getwd()
	repo := gitrepo.RepoLocatedAt(wd)
	allAdditions := repo.TrackedFilesAsAdditions()
	hasher := utility.DefaultSHA256Hasher{}
	calculator := checksumcalculator.NewChecksumCalculator(hasher, append(allAdditions, currentAdditions...))
	cc := helpers.NewChecksumCompare(calculator, hasher, talismanRC)
	log.Printf("Number of files to scan: %d\n", len(currentAdditions))
	log.Printf("Number of detectors: %d\n", len(dc.detectors))
	total := len(currentAdditions) * len(dc.detectors)
	var progressBar = getProgressBar()
	progressBar.Start(total)
	for _, v := range dc.detectors {
		v.Test(cc, currentAdditions, talismanRC, result, func() {
			progressBar.Increment()
		})
	}
	progressBar.Finish()
}

func getProgressBar() progressBar {
	if isTerminal() {
		return &defaultProgressBar{}
	} else {
		return &noOpProgressBar{}
	}
}

func isTerminal() bool {
	fileInfo, _ := os.Stdout.Stat()
	return (fileInfo.Mode() & os.ModeCharDevice) != 0
}

type progressBar interface {
	Start(int)
	Increment()
	Finish()
}

type noOpProgressBar struct {
}

func (d *noOpProgressBar) Start(int) {}

func (d *noOpProgressBar) Increment() {}

func (d *noOpProgressBar) Finish() {}

type defaultProgressBar struct {
	bar *pb.ProgressBar
}

func (d *defaultProgressBar) Start(total int) {
	bar := pb.ProgressBarTemplate(`{{ red "Talisman Scan:" }} {{counters .}} {{ bar . "<" "-" (cycle . "↖" "↗" "↘" "↙" ) "." ">"}} {{percent . | rndcolor }} {{green}} {{blue}}`).New(total)
	bar.Set(pb.Terminal, true)
	d.bar = bar.Start()
}

func (d *defaultProgressBar) Increment() {
	d.bar.Increment()
}

func (d *defaultProgressBar) Finish() {
	d.bar.Finish()
}
<|endoftext|>


<commit_before>// Package mem is an example REST backend storage that stores everything in memory.
package mem

import (
	"sort"
	"sync"
	"time"

	"github.com/rs/rest-layer/resource"
	"golang.org/x/net/context"
)

// MemoryHandler is an example handler storing data in memory
type MemoryHandler struct {
	sync.RWMutex
	// If latency is set, the handler will introduce an artificial latency on
	// all operations
	Latency time.Duration
	items   map[interface{}]resource.Item
	ids     []interface{}
}

// NewHandler creates an empty memory handler
func NewHandler() *MemoryHandler {
	return &MemoryHandler{
		items: map[interface{}]resource.Item{},
		ids:   []interface{}{},
	}
}

// NewSlowHandler creates an empty memory handler with specified latency
func NewSlowHandler(latency time.Duration) *MemoryHandler {
	return &MemoryHandler{
		Latency: latency,
		items:   map[interface{}]resource.Item{},
		ids:     []interface{}{},
	}
}

// Insert inserts new items in memory
func (m *MemoryHandler) Insert(ctx context.Context, items []*resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, item := range items {
			if _, found := m.items[item.ID]; found {
				return resource.ErrConflict
			}
		}
		for _, item := range items {
			// Store ids in ordered slice for sorting
			m.ids = append(m.ids, item.ID)
			m.items[item.ID] = *item
		}
		return nil
	})
	return err
}

// Update replace an item by a new one in memory
func (m *MemoryHandler) Update(ctx context.Context, item *resource.Item, original *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found := m.items[original.ID]
		if !found {
			return resource.ErrNotFound
		}
		if original.ETag != o.ETag {
			return resource.ErrConflict
		}
		m.items[item.ID] = *item
		return nil
	})
	return err
}

// Delete deletes an item from memory
func (m *MemoryHandler) Delete(ctx context.Context, item *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found := m.items[item.ID]
		if !found {
			return resource.ErrNotFound
		}
		if item.ETag != o.ETag {
			return resource.ErrConflict
		}
		m.delete(item.ID)
		return nil
	})
	return err
}

// Clear clears all items from the memory store matching the lookup
func (m *MemoryHandler) Clear(ctx context.Context, lookup *resource.Lookup) (total int, err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, id := range m.ids {
			item := m.items[id]
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			m.delete(item.ID)
			total++
		}
		return nil
	})
	return total, err
}

// delete removes an item by this id with no look
func (m *MemoryHandler) delete(id interface{}) {
	delete(m.items, id)
	// Remove id from id list
	for i, _id := range m.ids {
		if _id == id {
			if i >= len(m.ids)-1 {
				m.ids = m.ids[:i]
			} else {
				m.ids = append(m.ids[:i], m.ids[i+1:]...)
			}
		}
	}
}

// Find items from memory matching the provided lookup
func (m *MemoryHandler) Find(ctx context.Context, lookup *resource.Lookup, page, perPage int) (list *resource.ItemList, err error) {
	m.RLock()
	defer m.RUnlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		items := []*resource.Item{}
		// Apply filter
		for _, id := range m.ids {
			item := m.items[id]
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			items = append(items, &item)
		}
		// Apply sort
		if len(lookup.Sort()) > 0 {
			s := sortableItems{lookup.Sort(), items}
			sort.Sort(s)
		}
		// Apply pagination
		total := len(items)
		start := (page - 1) * perPage
		end := total
		if perPage > 0 {
			end = start + perPage
			if start > total-1 {
				start = 0
				end = 0
			} else if end > total-1 {
				end = total
			}
		}
		list = &resource.ItemList{total, page, items[start:end]}
		return nil
	})
	return list, err
}
<commit_msg>Make sure we always store and return copies of the items<commit_after>// Package mem is an example REST backend storage that stores everything in memory.
package mem

import (
	"bytes"
	"encoding/gob"
	"sort"
	"sync"
	"time"

	"github.com/rs/rest-layer/resource"
	"golang.org/x/net/context"
)

// MemoryHandler is an example handler storing data in memory
type MemoryHandler struct {
	sync.RWMutex
	// If latency is set, the handler will introduce an artificial latency on
	// all operations
	Latency time.Duration
	items   map[interface{}][]byte
	ids     []interface{}
}

// NewHandler creates an empty memory handler
func NewHandler() *MemoryHandler {
	return &MemoryHandler{
		items: map[interface{}][]byte{},
		ids:   []interface{}{},
	}
}

// NewSlowHandler creates an empty memory handler with specified latency
func NewSlowHandler(latency time.Duration) *MemoryHandler {
	return &MemoryHandler{
		Latency: latency,
		items:   map[interface{}][]byte{},
		ids:     []interface{}{},
	}
}

// store serialize the item using gob and store it in the handler's items map
func (m *MemoryHandler) store(item *resource.Item) error {
	var data bytes.Buffer
	enc := gob.NewEncoder(&data)
	if err := enc.Encode(*item); err != nil {
		return err
	}
	m.items[item.ID] = data.Bytes()
	return nil
}

// fetch unserialize item's data and return a new item
func (m *MemoryHandler) fetch(id interface{}) (*resource.Item, bool, error) {
	data, found := m.items[id]
	if !found {
		return nil, false, nil
	}
	dec := gob.NewDecoder(bytes.NewBuffer(data))
	var item resource.Item
	if err := dec.Decode(&item); err != nil {
		return nil, true, err
	}
	return &item, true, nil
}

// delete removes an item by this id with no look
func (m *MemoryHandler) delete(id interface{}) {
	delete(m.items, id)
	// Remove id from id list
	for i, _id := range m.ids {
		if _id == id {
			if i >= len(m.ids)-1 {
				m.ids = m.ids[:i]
			} else {
				m.ids = append(m.ids[:i], m.ids[i+1:]...)
			}
		}
	}
}

// Insert inserts new items in memory
func (m *MemoryHandler) Insert(ctx context.Context, items []*resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, item := range items {
			if _, found := m.items[item.ID]; found {
				return resource.ErrConflict
			}
		}
		for _, item := range items {
			if err := m.store(item); err != nil {
				return err
			}
			// Store ids in ordered slice for sorting
			m.ids = append(m.ids, item.ID)
		}
		return nil
	})
	return err
}

// Update replace an item by a new one in memory
func (m *MemoryHandler) Update(ctx context.Context, item *resource.Item, original *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(original.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if original.ETag != o.ETag {
			return resource.ErrConflict
		}
		if err := m.store(item); err != nil {
			return err
		}
		return nil
	})
	return err
}

// Delete deletes an item from memory
func (m *MemoryHandler) Delete(ctx context.Context, item *resource.Item) (err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		o, found, err := m.fetch(item.ID)
		if !found {
			return resource.ErrNotFound
		}
		if err != nil {
			return err
		}
		if item.ETag != o.ETag {
			return resource.ErrConflict
		}
		m.delete(item.ID)
		return nil
	})
	return err
}

// Clear clears all items from the memory store matching the lookup
func (m *MemoryHandler) Clear(ctx context.Context, lookup *resource.Lookup) (total int, err error) {
	m.Lock()
	defer m.Unlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		for _, id := range m.ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			m.delete(item.ID)
			total++
		}
		return nil
	})
	return total, err
}

// Find items from memory matching the provided lookup
func (m *MemoryHandler) Find(ctx context.Context, lookup *resource.Lookup, page, perPage int) (list *resource.ItemList, err error) {
	m.RLock()
	defer m.RUnlock()
	err = handleWithLatency(m.Latency, ctx, func() error {
		items := []*resource.Item{}
		// Apply filter
		for _, id := range m.ids {
			item, _, err := m.fetch(id)
			if err != nil {
				return err
			}
			if !lookup.Filter().Match(item.Payload) {
				continue
			}
			items = append(items, item)
		}
		// Apply sort
		if len(lookup.Sort()) > 0 {
			s := sortableItems{lookup.Sort(), items}
			sort.Sort(s)
		}
		// Apply pagination
		total := len(items)
		start := (page - 1) * perPage
		end := total
		if perPage > 0 {
			end = start + perPage
			if start > total-1 {
				start = 0
				end = 0
			} else if end > total-1 {
				end = total
			}
		}
		list = &resource.ItemList{total, page, items[start:end]}
		return nil
	})
	return list, err
}
<|endoftext|>


<commit_before>package helpers

import (
	"fmt"
	"strconv"
	"os"
	"strings"
)

const defaultColor = "008bb9"

var adjustments = [][]int64 {{0,0,0},{0,12,13},{36,45,50}}

var colorHexStrings []string

func init(){

	colorString := os.Getenv("HEX_COLOR")

        if colorString == "" {
		fmt.Println("No color set using default")
                colorString = defaultColor
        }else if strings.ToLower(colorString) == "ffffff"{
		fmt.Println("No color set to white not valid using default")
                colorString = defaultColor

	}

	colors, err := parseColorString(colorString)

	if err != nil {
		fmt.Printf("Cannot parse string %s using default color scheme\n", colorString)

		colors, err = parseColorString("008bb9")
	}else if colors[0] == 0 && colors[1] == 0 && colors[2] == 0 {
		fmt.Printf("Color String set to Black")
	}

	if colors[0] > 219 {
	  colors[0] = 219
	}

	if colors[1] > 210 {
	  colors[1] = 210
	}

	if colors[2] > 205 {
	  colors[2] = 205
	}

	colorHexStrings = createColorScheme(colors)
}

func FetchColors()[]string{

	return colorHexStrings
}

func createColorScheme(colors []int64)[]string{
	colorHex := make([]string, 3)

	colorHex[0] = createHexColorString(colors, adjustments[0])
	colorHex[1] = createHexColorString(colors, adjustments[1])
	colorHex[2] = createHexColorString(colors, adjustments[2])

	return colorHex
}

func createHexColorString(vals []int64, adjust []int64) string{

	colors := make([]string, 3)

	for index, _ := range colors {
		colors[index] = "0" + fmt.Sprintf("%x", vals[index]+adjust[index])
		colors[index] = colors[index][len(colors[index])-2:len(colors[index])]

	}

	return "#"+colors[0]+colors[1]+colors[2]
}

func parseColorString(hexColor string)([]int64, error){

	if len(hexColor) < 6 {
		hexColor = "000000" + hexColor
		hexColor = hexColor[len(hexColor)-6:len(hexColor)]
	}

	colorRGB := make([]int64, 3)

	var err error

	for i := 0; i < 3; i++{
		colorRGB[i], err = strconv.ParseInt(hexColor[2*i:(2*i)+2], 16, 0)
		if err != nil{
			break
		}
	}

	return colorRGB, err
}

<commit_msg>add color index lookup<commit_after>package helpers

import (
	"fmt"
	"strconv"
	"os"
	"strings"
)

const defaultColor = "008bb9"

var adjustments = [][]int64 {{0,0,0},{0,12,13},{36,45,50}}

var predefinedColors = []string {"FF00FF","FF0000","8B4513","FF8C00", "A9A9A9",
	"FFFF00", "4B0082", "006400","808000","000000","800000",
	"0000FF", "00008B","B8860B", "ADFF2F", "B0C4DE", "FF1493"}

var colorHexStrings []string

func init(){

	colorString := os.Getenv("HEX_COLOR")

        if colorString == "" {
		colorString = os.Getenv("COLOR_INDX")
		if colorString != "" {
			colorIndex, indexErr := strconv.ParseInt(colorString,10,0)
			if indexErr != nil || colorIndex > int64(len(predefinedColors))  {
				fmt.Println("Invalid color index using default")
				colorString = defaultColor
			}else if colorIndex == 0 {
				colorString = defaultColor
			}else{
				colorString = predefinedColors[colorIndex-1]
			}
		}else{
			fmt.Println("No color set using default")
                	colorString = defaultColor
		}
        }else if strings.ToLower(colorString) == "ffffff"{
		fmt.Println("No color set to white not valid using default")
                colorString = defaultColor

	}

	colors, err := parseColorString(colorString)

	if err != nil {
		fmt.Printf("Cannot parse string %s using default color scheme\n", colorString)

		colors, err = parseColorString("008bb9")
	}else if colors[0] == 0 && colors[1] == 0 && colors[2] == 0 {
		fmt.Printf("Color String set to Black")
	}

	if colors[0] > 219 {
	  colors[0] = 219
	}

	if colors[1] > 210 {
	  colors[1] = 210
	}

	if colors[2] > 205 {
	  colors[2] = 205
	}

	colorHexStrings = createColorScheme(colors)
}

func FetchColors()[]string{

	return colorHexStrings
}

func createColorScheme(colors []int64)[]string{
	colorHex := make([]string, 3)

	colorHex[0] = createHexColorString(colors, adjustments[0])
	colorHex[1] = createHexColorString(colors, adjustments[1])
	colorHex[2] = createHexColorString(colors, adjustments[2])

	return colorHex
}

func createHexColorString(vals []int64, adjust []int64) string{

	colors := make([]string, 3)

	for index, _ := range colors {
		colors[index] = "0" + fmt.Sprintf("%x", vals[index]+adjust[index])
		colors[index] = colors[index][len(colors[index])-2:len(colors[index])]

	}

	return "#"+colors[0]+colors[1]+colors[2]
}

func parseColorString(hexColor string)([]int64, error){

	if len(hexColor) < 6 {
		hexColor = "000000" + hexColor
		hexColor = hexColor[len(hexColor)-6:len(hexColor)]
	}

	colorRGB := make([]int64, 3)

	var err error

	for i := 0; i < 3; i++{
		colorRGB[i], err = strconv.ParseInt(hexColor[2*i:(2*i)+2], 16, 0)
		if err != nil{
			break
		}
	}

	return colorRGB, err
}

<|endoftext|>


<commit_before>package helpers

import (
	"database/sql"
	"fmt"
	"testing"
	"time"

	mocks "github.com/ghmeier/bloodlines/_mocks/gateways"
	"github.com/ghmeier/bloodlines/gateways"
	"github.com/ghmeier/bloodlines/models"
	tmocks "github.com/jakelong95/TownCenter/_mocks"
	tmodels "github.com/jakelong95/TownCenter/models"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/pborman/uuid"
	"github.com/stretchr/testify/assert"
)

func TestReceiptGetByIDSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	receipt.SendState = models.FAILURE
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(receipt.SendState), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	res, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
	assert.Equal(receipt.ID, res.ID)
	assert.Equal(receipt.ContentID, res.ContentID)
	assert.Equal(receipt.UserID, res.UserID)
	assert.Equal(0, len(res.Values))
	assert.EqualValues(receipt.SendState, res.SendState)
	assert.Equal(receipt.Created, res.Created)
}

func TestReceiptGetByIDQueryFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	receipt.SendState = models.QUEUED
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnError(fmt.Errorf("some error"))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetByIDMapValueFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	receipt.SendState = models.SUCCESS
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().AddRow(receipt.ID.String(), receipt.Created, "", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetByIDMapFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().AddRow(receipt.ID.String(), receipt.Created, "{}", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetReceiptsSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(receipt.SendState), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished).
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(receipt.SendState), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	res, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
	assert.Equal(2, len(res))
}

func TestReceiptGetReceiptsFail(t *testing.T) {
	assert := assert.New(t)

	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnError(fmt.Errorf("some error"))

	_, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetReceiptsMapFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptInsertSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("INSERT INTO receipt").
		ExpectExec().
		WithArgs(receipt.ID, receipt.Created, "{}", string(receipt.SendState), receipt.ContentID, receipt.UserID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := c.Insert(receipt)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
}

func TestReceiptInsertFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("INSERT INTO receipt").
		ExpectExec().
		WithArgs(receipt.ID, receipt.Created, "{}", string(receipt.SendState), receipt.ContentID, receipt.UserID).
		WillReturnError(fmt.Errorf("some error"))

	err := c.Insert(receipt)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptSetStatusSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(receipt.SendState), receipt.ID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := c.SetStatus(receipt.ID, receipt.SendState)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
}

func TestReceiptSetStatusFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(receipt.SendState), receipt.ID).
		WillReturnError(fmt.Errorf("some error"))

	err := c.SetStatus(receipt.ID, receipt.SendState)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptSendSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	request := &models.SendRequest{ReceiptID: receipt.ID, ContentID: content.ID}

	s, mock, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, &mocks.SendgridI{}, &tmocks.TownCenterI{}, rabbitMock)
	rabbitMock.On("Produce", request).Return(nil)
	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(models.QUEUED), receipt.ID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := r.Send(request)

	assert.NoError(err)
}

func TestReceiptDeliverContentSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(&tmodels.User{Email: "test"}, nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(nil)

	err := r.DeliverContent(receipt, content)

	assert.NoError(err)
}

func TestReceiptDeliverContentSGFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(&tmodels.User{Email: "test"}, nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(fmt.Errorf("some error"))

	err := r.DeliverContent(receipt, content)

	assert.Error(err)
}

func TestReceiptDeliverContentTCFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(nil, fmt.Errorf("some error"))

	err := r.DeliverContent(receipt, content)

	assert.Error(err)
}

func TestReceiptDeliverContentNoopSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	content.Type = models.NOOP
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return("test", nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(nil)

	err := r.DeliverContent(receipt, content)

	assert.NoError(err)
}

func getDefaultReceipt() *models.Receipt {
	r := models.NewReceipt(make(map[string]string), uuid.NewUUID(), uuid.NewUUID())
	r.Finished = time.Now()
	return r
}

func getReceiptRows() sqlmock.Rows {
	return sqlmock.NewRows([]string{"id", "ts", "vals", "sendState", "contentId", "userId", "finished"})
}

func getMockReceipt(s *sql.DB) ReceiptI {
	rabbitMock := &mocks.RabbitI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, &mocks.SendgridI{}, &tmocks.TownCenterI{}, rabbitMock)

	return r
}
<commit_msg>Actually add receipt tests<commit_after>package helpers

import (
	"database/sql"
	"fmt"
	"testing"
	"time"

	mocks "github.com/ghmeier/bloodlines/_mocks/gateways"
	"github.com/ghmeier/bloodlines/gateways"
	"github.com/ghmeier/bloodlines/models"
	tmocks "github.com/jakelong95/TownCenter/_mocks"
	tmodels "github.com/jakelong95/TownCenter/models"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/pborman/uuid"
	"github.com/stretchr/testify/assert"
)

func TestReceiptGetByIDSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	receipt.SendState = models.FAILURE
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(receipt.SendState), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	res, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
	assert.Equal(receipt.ID, res.ID)
	assert.Equal(receipt.ContentID, res.ContentID)
	assert.Equal(receipt.UserID, res.UserID)
	assert.Equal(0, len(res.Values))
	assert.EqualValues(receipt.SendState, res.SendState)
	assert.Equal(receipt.Created, res.Created)
}

func TestReceiptGetByIDQueryFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnError(fmt.Errorf("some error"))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetByIDMapValueFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().AddRow(receipt.ID.String(), receipt.Created, "", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetByIDMapFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(receipt.ID.String()).
		WillReturnRows(getReceiptRows().AddRow(receipt.ID.String(), receipt.Created, "{}", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetByID(receipt.ID.String())

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetReceiptsSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(receipt.SendState), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished).
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(models.FAILURE), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished).
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(models.SUCCESS), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished).
			AddRow(receipt.ID.String(), receipt.Created, "{}", string(models.QUEUED), receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	res, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
	assert.Equal(2, len(res))
}

func TestReceiptGetReceiptsFail(t *testing.T) {
	assert := assert.New(t)

	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnError(fmt.Errorf("some error"))

	_, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptGetReceiptsMapFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	offset, limit := 0, 20
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectQuery("SELECT id, ts, vals, sendState, contentId, userId, finished FROM receipt").
		WithArgs(offset, limit).
		WillReturnRows(getReceiptRows().
			AddRow(receipt.ID.String(), receipt.Created, "{}", "INVALID", receipt.ContentID.String(), receipt.UserID.String(), receipt.Finished))

	_, err := c.GetAll(offset, limit)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptInsertSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("INSERT INTO receipt").
		ExpectExec().
		WithArgs(receipt.ID, receipt.Created, "{}", string(receipt.SendState), receipt.ContentID, receipt.UserID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := c.Insert(receipt)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
}

func TestReceiptInsertFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("INSERT INTO receipt").
		ExpectExec().
		WithArgs(receipt.ID, receipt.Created, "{}", string(receipt.SendState), receipt.ContentID, receipt.UserID).
		WillReturnError(fmt.Errorf("some error"))

	err := c.Insert(receipt)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptSetStatusSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(receipt.SendState), receipt.ID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := c.SetStatus(receipt.ID, receipt.SendState)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.NoError(err)
}

func TestReceiptSetStatusFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	s, mock, _ := sqlmock.New()
	c := getMockReceipt(s)

	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(receipt.SendState), receipt.ID).
		WillReturnError(fmt.Errorf("some error"))

	err := c.SetStatus(receipt.ID, receipt.SendState)

	assert.Equal(mock.ExpectationsWereMet(), nil)
	assert.Error(err)
}

func TestReceiptSendSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	request := &models.SendRequest{ReceiptID: receipt.ID, ContentID: content.ID}

	s, mock, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, &mocks.SendgridI{}, &tmocks.TownCenterI{}, rabbitMock)
	rabbitMock.On("Produce", request).Return(nil)
	mock.ExpectPrepare("UPDATE receipt").
		ExpectExec().
		WithArgs(string(models.QUEUED), receipt.ID).
		WillReturnResult(sqlmock.NewResult(1, 1))

	err := r.Send(request)

	assert.NoError(err)
}

func TestReceiptDeliverContentSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(&tmodels.User{Email: "test"}, nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(nil)

	err := r.DeliverContent(receipt, content)

	assert.NoError(err)
}

func TestReceiptDeliverContentSGFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(&tmodels.User{Email: "test"}, nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(fmt.Errorf("some error"))

	err := r.DeliverContent(receipt, content)

	assert.Error(err)
}

func TestReceiptDeliverContentTCFail(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return(nil, fmt.Errorf("some error"))

	err := r.DeliverContent(receipt, content)

	assert.Error(err)
}

func TestReceiptDeliverContentNoopSuccess(t *testing.T) {
	assert := assert.New(t)

	receipt := getDefaultReceipt()
	content := getDefaultContent()
	content.Type = models.NOOP
	s, _, _ := sqlmock.New()
	rabbitMock := &mocks.RabbitI{}
	sgMock := &mocks.SendgridI{}
	tcMock := &tmocks.TownCenterI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, sgMock, tcMock, rabbitMock)
	tcMock.On("GetUser", receipt.UserID).Return("test", nil)
	sgMock.On("SendEmail", "test", "test", "Hello").Return(nil)

	err := r.DeliverContent(receipt, content)

	assert.NoError(err)
}

func getDefaultReceipt() *models.Receipt {
	r := models.NewReceipt(make(map[string]string), uuid.NewUUID(), uuid.NewUUID())
	r.Finished = time.Now()
	return r
}

func getReceiptRows() sqlmock.Rows {
	return sqlmock.NewRows([]string{"id", "ts", "vals", "sendState", "contentId", "userId", "finished"})
}

func getMockReceipt(s *sql.DB) ReceiptI {
	rabbitMock := &mocks.RabbitI{}
	r := NewReceipt(&gateways.MySQL{DB: s}, &mocks.SendgridI{}, &tmocks.TownCenterI{}, rabbitMock)

	return r
}
<|endoftext|>


<commit_before>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("proxy", func() {
	var proxyURL string

	BeforeEach(func() {
		proxyURL = "127.0.0.1:9999"
	})

	Context("V3", func() {
		It("errors when proxy is not setup properly", func() {
			session := helpers.CFWithEnv(map[string]string{"https_proxy": proxyURL}, "orgs")
			Eventually(session.Err).Should(Say("%s.*proxy.*%s", apiURL, proxyURL))
			Eventually(session.Err).Should(Say("TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."))
			Eventually(session).Should(Exit(1))
		})
	})
})
<commit_msg>Update proxy-connection integration test<commit_after>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("proxy", func() {
	var proxyURL string

	BeforeEach(func() {
		proxyURL = "127.0.0.1:9999"
	})

	Context("V3", func() {
		It("errors when proxy is not setup properly", func() {
			session := helpers.CFWithEnv(map[string]string{"https_proxy": proxyURL}, "login")
			Eventually(session.Err).Should(Say("%s.*proxy.*%s", apiURL, proxyURL))
			Eventually(session.Err).Should(Say("TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection."))
			Eventually(session).Should(Exit(1))
		})
	})
})
<|endoftext|>


<commit_before>package openflow

import (
	"fmt"
	"sync"
)

// A Matcher interface is used by multiplexer to find the handler for
// the received request.
type Matcher interface {
	Match(*Request) bool
}

// MatcherFunc type is an adapter to allow the use of ordinary functions
// as OpenFlow request matchers.
type MatcherFunc struct {
	Func func(*Request) bool
}

// Match implements Matcher interface and calls fn(r).
func (m *MatcherFunc) Match(r *Request) bool {
	return m.Func(r)
}

// TypeMatcher used to match requests by their types.
type TypeMatcher Type

// Match implements Matcher interface and matches the request by the type.
func (t TypeMatcher) Match(r *Request) bool {
	return r.Header.Type == Type(t)
}

// MultiMatcher creates a new Matcher instance that matches the request
// by all specified criterias.
func MultiMatcher(m ...Matcher) Matcher {
	fn := func(r *Request) bool {
		for _, matcher := range m {
			if !matcher.Match(r) {
				return false
			}
		}

		return true
	}

	return &MatcherFunc{fn}
}

type muxEntry struct {
	matcher Matcher
	handler Handler

	// once means handler will be executed only once, it will
	// be removed from the list of registered handlers.
	once bool
}

// ServeMux is an OpenFlow request multiplexer.
type ServeMux struct {
	mu       sync.RWMutex
	handlers map[Matcher]*muxEntry
}

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
	return &ServeMux{handlers: make(map[Matcher]*muxEntry)}
}

// handle appends to the list of registered handlers a new one. If the
// matcher or handler of the entry is not defined, a panic function will
// be called.
func (mux *ServeMux) handle(e *muxEntry) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if e.matcher == nil {
		panic("openflow: nil matcher")
	}

	if e.handler == nil {
		panic("openflow: nil handler")
	}

	if _, dup := mux.handlers[e.matcher]; dup {
		text := "openflow: multiple registrations for %v"
		panic(fmt.Errorf(text, e.matcher))
	}

	mux.handlers[e.matcher] = e
}

// Handle registers the handler for the given pattern.
func (mux *ServeMux) Handle(m Matcher, h Handler) {
	mux.handle(&muxEntry{m, h, false})
}

// Handle registers disposable handler for the given pattern.
//
// It is not guaranteed that handler will process the first message
// exemplar of the matching message.
func (mux *ServeMux) HandleOnce(m Matcher, h Handler) {
	mux.handle(&muxEntry{m, h, true})
}

// HandleFunc registers handler function for the given pattern.
func (mux *ServeMux) HandleFunc(m Matcher, h HandlerFunc) {
	mux.Handle(m, h)
}

// HandleFunc registers handler function for the given message type.
func (mux *ServeMux) Handler(r *Request) Handler {
	var matcher Matcher
	var entry *muxEntry

	// Acquire a read lock to ensure that list would not
	// be modified during the search of registered handler.
	mux.mu.RLock()
	var matched bool

	// Try to match the processing request to any of the registered
	// filters.
	for matcher, entry = range mux.handlers {
		if matched = matcher.Match(r); matched {
			break
		}
	}

	mux.mu.RUnlock()

	// When there are no matching entries in the list, we will
	// simply drop the incoming message.
	if !matched {
		return DiscardHandler
	}

	// If the retrieved entry is not disposable one, we will
	// return it as is without any processing.
	if !entry.once {
		return entry.handler
	}

	// But when the entry is disposable, we need to remove it
	// from the list.

	// We need to acquire the write lock in order to remove the
	// entry from the root. This procedure does not guarantee,
	// that handler will process the first message.
	mux.mu.Lock()
	defer mux.mu.Unlock()

	// If the concurrent message have already started the message
	// processing, it will be no longer presented in the list.
	if _, ok := mux.handlers[matcher]; !ok {
		return DiscardHandler
	}

	// Remove the entry from the list if it is marked as disposable.
	delete(mux.handlers, matcher)
	return entry.handler
}

// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *ServeMux) Serve(rw ResponseWriter, r *Request) {
	h := mux.Handler(r)
	h.Serve(rw, r)
}

// TypeMux is an OpenFlow request multiplexer. It matches the type
// of the OpenFlow message against a list of registered handlers and calls
// the marching handler.
type TypeMux struct {
	mux *ServeMux
}

func NewTypeMux() *TypeMux {
	return &TypeMux{NewServeMux()}
}

// Handle registers the handler for the given message type.
func (mux *TypeMux) Handle(t Type, h Handler) {
	mux.mux.Handle(TypeMatcher(t), h)
}

// HandleOnce registers a disposable handler for the given message type.
func (mux *TypeMux) HandleOnce(t Type, h Handler) {
	mux.mux.HandleOnce(TypeMatcher(t), h)
}

// HandleFunc registers handler function for the given message type.
func (mux *TypeMux) HandleFunc(t Type, f HandlerFunc) {
	mux.Handle(t, f)
}

// Handle returns a Handler instance for the given OpenFlow request.
func (mux *TypeMux) Handler(r *Request) Handler {
	return mux.mux.Handler(r)
}

// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *TypeMux) Serve(rw ResponseWriter, r *Request) {
	mux.mux.Serve(rw, r)
}

// DefaultMux is an instance of the TypeMux used as
// a default handler in the DefaultServer instance.
var DefaultMux = NewTypeMux()

// Handle registers the handler for the given message type message in the
// DefaultMux. The documentation for TypeMux
func Handle(t Type, handler Handler) {
	DefaultMux.Handle(t, handler)
}

// HandleOnce registers a disposable handler for the given message type
// in the DefaultMux.
func HandleOnce(t Type, handler Handler) {
	DefaultMux.HandleOnce(t, handler)
}

// HandleFunc registers the handler function on the given message type
// in the DefaultMux.
func HandleFunc(t Type, f func(ResponseWriter, *Request)) {
	DefaultMux.HandleFunc(t, f)
}
<commit_msg>Add DefaultHandler to ServerMux (#111)<commit_after>package openflow

import (
	"fmt"
	"sync"
)

// A Matcher interface is used by multiplexer to find the handler for
// the received request.
type Matcher interface {
	Match(*Request) bool
}

// MatcherFunc type is an adapter to allow the use of ordinary functions
// as OpenFlow request matchers.
type MatcherFunc struct {
	Func func(*Request) bool
}

// Match implements Matcher interface and calls fn(r).
func (m *MatcherFunc) Match(r *Request) bool {
	return m.Func(r)
}

// TypeMatcher used to match requests by their types.
type TypeMatcher Type

// Match implements Matcher interface and matches the request by the type.
func (t TypeMatcher) Match(r *Request) bool {
	return r.Header.Type == Type(t)
}

// MultiMatcher creates a new Matcher instance that matches the request
// by all specified criterias.
func MultiMatcher(m ...Matcher) Matcher {
	fn := func(r *Request) bool {
		for _, matcher := range m {
			if !matcher.Match(r) {
				return false
			}
		}

		return true
	}

	return &MatcherFunc{fn}
}

type muxEntry struct {
	matcher Matcher
	handler Handler

	// once means handler will be executed only once, it will
	// be removed from the list of registered handlers.
	once bool
}

// ServeMux is an OpenFlow request multiplexer.
type ServeMux struct {
	mu       sync.RWMutex
	handlers map[Matcher]*muxEntry
}

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
	return &ServeMux{handlers: make(map[Matcher]*muxEntry)}
}

// DefaultHandler is the Handler used for Requests that don't have a Matcher.
var DefaultHandler = DiscardHandler

// handle appends to the list of registered handlers a new one. If the
// matcher or handler of the entry is not defined, a panic function will
// be called.
func (mux *ServeMux) handle(e *muxEntry) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if e.matcher == nil {
		panic("openflow: nil matcher")
	}

	if e.handler == nil {
		panic("openflow: nil handler")
	}

	if _, dup := mux.handlers[e.matcher]; dup {
		text := "openflow: multiple registrations for %v"
		panic(fmt.Errorf(text, e.matcher))
	}

	mux.handlers[e.matcher] = e
}

// Handle registers the handler for the given pattern.
func (mux *ServeMux) Handle(m Matcher, h Handler) {
	mux.handle(&muxEntry{m, h, false})
}

// Handle registers disposable handler for the given pattern.
//
// It is not guaranteed that handler will process the first message
// exemplar of the matching message.
func (mux *ServeMux) HandleOnce(m Matcher, h Handler) {
	mux.handle(&muxEntry{m, h, true})
}

// HandleFunc registers handler function for the given pattern.
func (mux *ServeMux) HandleFunc(m Matcher, h HandlerFunc) {
	mux.Handle(m, h)
}

// HandleFunc registers handler function for the given message type.
func (mux *ServeMux) Handler(r *Request) Handler {
	var matcher Matcher
	var entry *muxEntry

	// Acquire a read lock to ensure that list would not
	// be modified during the search of registered handler.
	mux.mu.RLock()
	var matched bool

	// Try to match the processing request to any of the registered
	// filters.
	for matcher, entry = range mux.handlers {
		if matched = matcher.Match(r); matched {
			break
		}
	}

	mux.mu.RUnlock()

	// Use the DefaultHandler when there are no matching entries in the list.
	if !matched {
		return DefaultHandler
	}

	// If the retrieved entry is not disposable one, we will
	// return it as is without any processing.
	if !entry.once {
		return entry.handler
	}

	// But when the entry is disposable, we need to remove it
	// from the list.

	// We need to acquire the write lock in order to remove the
	// entry from the root. This procedure does not guarantee,
	// that handler will process the first message.
	mux.mu.Lock()
	defer mux.mu.Unlock()

	// If the concurrent message have already started the message
	// processing, it will be no longer presented in the list.
	if _, ok := mux.handlers[matcher]; !ok {
		return DiscardHandler
	}

	// Remove the entry from the list if it is marked as disposable.
	delete(mux.handlers, matcher)
	return entry.handler
}

// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *ServeMux) Serve(rw ResponseWriter, r *Request) {
	h := mux.Handler(r)
	h.Serve(rw, r)
}

// TypeMux is an OpenFlow request multiplexer. It matches the type
// of the OpenFlow message against a list of registered handlers and calls
// the marching handler.
type TypeMux struct {
	mux *ServeMux
}

func NewTypeMux() *TypeMux {
	return &TypeMux{NewServeMux()}
}

// Handle registers the handler for the given message type.
func (mux *TypeMux) Handle(t Type, h Handler) {
	mux.mux.Handle(TypeMatcher(t), h)
}

// HandleOnce registers a disposable handler for the given message type.
func (mux *TypeMux) HandleOnce(t Type, h Handler) {
	mux.mux.HandleOnce(TypeMatcher(t), h)
}

// HandleFunc registers handler function for the given message type.
func (mux *TypeMux) HandleFunc(t Type, f HandlerFunc) {
	mux.Handle(t, f)
}

// Handle returns a Handler instance for the given OpenFlow request.
func (mux *TypeMux) Handler(r *Request) Handler {
	return mux.mux.Handler(r)
}

// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *TypeMux) Serve(rw ResponseWriter, r *Request) {
	mux.mux.Serve(rw, r)
}

// DefaultMux is an instance of the TypeMux used as
// a default handler in the DefaultServer instance.
var DefaultMux = NewTypeMux()

// Handle registers the handler for the given message type message in the
// DefaultMux. The documentation for TypeMux
func Handle(t Type, handler Handler) {
	DefaultMux.Handle(t, handler)
}

// HandleOnce registers a disposable handler for the given message type
// in the DefaultMux.
func HandleOnce(t Type, handler Handler) {
	DefaultMux.HandleOnce(t, handler)
}

// HandleFunc registers the handler function on the given message type
// in the DefaultMux.
func HandleFunc(t Type, f func(ResponseWriter, *Request)) {
	DefaultMux.HandleFunc(t, f)
}
<|endoftext|>


<commit_before>//todo: add copyright notice

package util

import (
	"bufio"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/ian-kent/go-log/log"
	"gopkg.in/yaml.v2"
)

//todo: Move to a separate package
//struct which is used to read update-descriptor.yaml
type UpdateDescriptor struct {
	Update_number    string
	Platform_version string
	Platform_name    string
	Applies_to       string
	Bug_fixes        map[string]string
	Description      string
	File_changes     struct {
				 Added_files    []string
				 Removed_files  []string
				 Modified_files []string
			 }
}

func HasZipExtension(path string) bool {
	return strings.HasSuffix(path, ".zip")
}

func HasJarExtension(path string) bool {
	return strings.HasSuffix(path, ".jar")
}

func GetParentDirectory(filepath string) string {
	parentDirectory := "./"
	if lastIndex := strings.LastIndex(filepath, string(os.PathSeparator)); lastIndex > -1 {
		parentDirectory = filepath[:lastIndex]
	}
	return parentDirectory
}

//This checks whether the distribution directory/zip exists
func IsDistributionExists(distributionPath string) (bool, error) {
	if HasZipExtension(distributionPath) {
		exists, err := IsFileExists(distributionPath)
		if err != nil {
			return false, err
		}
		if exists {
			return true, nil
		} else {
			return false, nil
		}
	} else {
		exists, err := IsDirectoryExists(distributionPath)
		if err != nil {
			return false, err
		}
		if exists {
			return true, nil
		} else {
			return false, nil
		}
	}
	return false, nil
}

func DeleteDirectory(path string) error {
	return os.RemoveAll(path)
}

func CreateDirectory(path string) error {
	return os.MkdirAll(path, 0700)
}

func IsYes(preference string) bool {
	if strings.ToLower(preference) == "yes" || (len(preference) == 1 && strings.ToLower(preference) == "y" ) {
		return true
	}
	return false
}

func IsNo(preference string) bool {
	if strings.ToLower(preference) == "no" || (len(preference) == 1 && strings.ToLower(preference) == "n" ) {
		return true
	}
	return false
}

func IsReenter(preference string) bool {
	if strings.ToLower(preference) == "reenter" || strings.ToLower(preference) == "re-enter" || (len(preference) == 1 && strings.ToLower(preference) == "r" ) {
		return true
	}
	return false
}

func HandleError(err error, customMessage ...interface{}) {
	if err != nil {
		PrintErrorAndExit(append(customMessage, "Error Message: '" + err.Error() + "'")...)
	}
}

func GetUserInput() (string, error) {
	reader := bufio.NewReader(os.Stdin)
	preference, err := reader.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(preference), nil
}

func IsUserPreferencesValid(preferences []string, availableChoices int) (bool, error) {
	length := len(preferences)
	if length == 0 {
		return false, &CustomError{What:"No preferences entered."}
	}
	first, err := strconv.Atoi(preferences[0])
	if err != nil {
		return false, err
	}
	message := "Invalid preferences. Please select indices where " + strconv.Itoa(availableChoices) + ">= index >=1."
	if first < 1 {
		return false, &CustomError{What:message}
	}
	last, err := strconv.Atoi(preferences[length - 1])
	if err != nil {
		return false, err
	}
	if last > availableChoices {
		return false, &CustomError{What:message}
	}
	return true, nil
}

//This function will read update-descriptor.yaml
func LoadUpdateDescriptor(filename, updateDirectoryPath string) (*UpdateDescriptor, error) {

	//Construct the file path
	updateDescriptorPath := filepath.Join(updateDirectoryPath, filename)
	log.Debug("updateDescriptorPath:", updateDescriptorPath)

	//Read the file
	updateDescriptor := UpdateDescriptor{}
	yamlFile, err := ioutil.ReadFile(updateDescriptorPath)
	if err != nil {
		return nil, &CustomError{What: err.Error()}
	}
	//Un-marshal the update-descriptor file to updateDescriptor struct
	err = yaml.Unmarshal(yamlFile, &updateDescriptor)
	if err != nil {
		return nil, &CustomError{What: err.Error()}
	}
	return &updateDescriptor, nil
}

func ValidateUpdateDescriptor(updateDescriptor *UpdateDescriptor) error {
	if len(updateDescriptor.Update_number) == 0 {
		return &CustomError{What: "'update_number' field not found." }
	}
	//todo: use regex to validate Update_number format
	if len(updateDescriptor.Platform_version) == 0 {
		return &CustomError{What: "'platform_version' field not found." }
	}
	//todo: use regex to validate Platform_version format
	if len(updateDescriptor.Platform_name) == 0 {
		return &CustomError{What: "'platform_name' field not found." }
	}
	if len(updateDescriptor.Applies_to) == 0 {
		return &CustomError{What: "'applies_to' field not found." }
	}
	if len(updateDescriptor.Bug_fixes) == 0 {
		return &CustomError{What: "'bug_fixes' field not found." }
	}
	if len(updateDescriptor.Description) == 0 {
		return &CustomError{What: "'description' field not found." }
	}
	return nil
}

func PrintUpdateDescriptor(updateDescriptor *UpdateDescriptor) {
	fmt.Println("----------------------------------------------------------------")
	fmt.Printf("update_number: %s\n", updateDescriptor.Update_number)
	fmt.Printf("kernel_version: %s\n", updateDescriptor.Platform_version)
	fmt.Printf("platform_version: %s\n", updateDescriptor.Platform_name)
	fmt.Printf("applies_to: %s\n", updateDescriptor.Applies_to)
	fmt.Printf("bug_fixes: %s\n", updateDescriptor.Bug_fixes)
	fmt.Printf("file_changes: %s\n", updateDescriptor.File_changes)
	fmt.Printf("description: %s\n", updateDescriptor.Description)
	fmt.Println("----------------------------------------------------------------")
}

//ok
func GetMD5(filepath string) (string, error) {
	var result []byte
	file, err := os.Open(filepath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(hash.Sum(result)), nil
}

//This function will set the update name which will be used when creating the update zip
func GetUpdateName(updateDescriptor *UpdateDescriptor, updateNamePrefix string) string {
	//Read the corresponding details
	platformVersion := updateDescriptor.Platform_version
	updateNumber := updateDescriptor.Update_number
	updateName := updateNamePrefix + "-" + platformVersion + "-" + updateNumber
	return updateName
}

//Check whether the given string is in the given slice
func IsStringIsInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

// Copies file source to destination dest.
func CopyFile(source string, dest string) (err error) {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()
	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err == nil {
		si, err := os.Stat(source)
		if err != nil {
			return os.Chmod(dest, si.Mode())
		}

	}
	return
}

//Recursively copies a directory tree, attempting to preserve permissions.
//Source directory must exist, destination directory must *not* exist.
func CopyDir(source string, dest string) (err error) {
	// get properties of source dir
	fi, err := os.Stat(source)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return &CustomError{What: "Source is not a directory"}
	}
	//Create the destination folder if it does not exist
	_, err = os.Open(dest)
	if os.IsNotExist(err) {
		// create dest dir
		err = os.MkdirAll(dest, fi.Mode())
		if err != nil {
			return &CustomError{What: err.Error()}
		}
	}
	entries, err := ioutil.ReadDir(source)
	for _, entry := range entries {
		sfp := source + "/" + entry.Name()
		dfp := dest + "/" + entry.Name()
		if entry.IsDir() {
			err = CopyDir(sfp, dfp)
			if err != nil {
				return err
			}
		} else {
			// perform copy
			err = CopyFile(sfp, dfp)
			if err != nil {
				return err
			}
		}
	}
	return
}

//A struct for returning custom error messages
type CustomError struct {
	What string
}

//Returns the error message defined in What as a string
func (e *CustomError) Error() string {
	return e.What
}

//Check whether the given location points to a directory
func IsDirectoryExists(location string) (bool, error) {
	locationInfo, err := os.Stat(location)
	if err != nil {
		return false, err
	}
	if locationInfo.IsDir() {
		return true, nil
	} else {
		return false, nil
	}
}

//Check whether the given location points to a file
func IsFileExists(location string) (bool, error) {
	locationInfo, err := os.Stat(location)
	if err != nil {
		return false, err
	}
	if locationInfo.IsDir() {
		return false, nil
	} else {
		return true, nil
	}
}

//This is used to print failure messages
func PrintError(args ...interface{}) {
	color.Set(color.FgRed, color.Bold)
	fmt.Println(append(append([]interface{}{"\n[ERROR]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print failure messages and exit
func PrintErrorAndExit(args ...interface{}) {
	//call the printFailure method and exit
	PrintError(args...)
	os.Exit(1)
}

//This is used to print warning messages
func PrintWarning(args ...interface{}) {
	//color.Set(color.FgYellow, color.Bold)
	fmt.Println(append(append([]interface{}{"[WARNING]"}, args...), "\n")...)
	//color.Unset()
}

//This is used to print info messages
func PrintInfo(args ...interface{}) {
	color.Set(color.FgYellow, color.Bold)
	fmt.Println(append(append([]interface{}{"[INFO]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print success messages
func PrintSuccess(args ...interface{}) {
	color.Set(color.FgGreen, color.Bold)
	fmt.Println(append(append([]interface{}{"[INFO]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print messages in Yellow color
func PrintInYellow(args ...interface{}) {
	color.Set(color.FgYellow, color.Bold)
	fmt.Print(args...)
	color.Unset()
}

//This is used to print messages in Red color
func PrintInRed(args ...interface{}) {
	color.Set(color.FgRed, color.Bold)
	fmt.Print(args...)
	color.Unset()
}
<commit_msg>Functions moved to Utils<commit_after>//todo: add copyright notice

package util

import (
	"bufio"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/ian-kent/go-log/log"
	"gopkg.in/yaml.v2"
)

//todo: Move to a separate package?
//struct which is used to read update-descriptor.yaml
type UpdateDescriptor struct {
	Update_number    string
	Platform_version string
	Platform_name    string
	Applies_to       string
	Bug_fixes        map[string]string
	Description      string
	File_changes     struct {
				 Added_files    []string
				 Removed_files  []string
				 Modified_files []string
			 }
}

func HasJarExtension(path string) bool {
	return strings.HasSuffix(path, ".jar")
}

func GetParentDirectory(filepath string) string {
	parentDirectory := "./"
	if lastIndex := strings.LastIndex(filepath, string(os.PathSeparator)); lastIndex > -1 {
		parentDirectory = filepath[:lastIndex]
	}
	return parentDirectory
}

//This will return the md5 hash of the file in the given filepath
func GetMD5(filepath string) (string, error) {
	var result []byte
	file, err := os.Open(filepath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(hash.Sum(result)), nil
}

//todo: check for const
//This function will set the update name which will be used when creating the update zip
func GetUpdateName(updateDescriptor *UpdateDescriptor, updateNamePrefix string) string {
	//Read the corresponding details
	platformVersion := updateDescriptor.Platform_version
	updateNumber := updateDescriptor.Update_number
	updateName := updateNamePrefix + "-" + platformVersion + "-" + updateNumber
	return updateName
}

//This checks whether the distribution directory/zip exists
func IsDistributionExists(distributionPath string) (bool, error) {
	if strings.HasSuffix(distributionPath, ".zip") {
		return IsFileExists(distributionPath)
	}
	return IsDirectoryExists(distributionPath)
}

func DeleteDirectory(path string) error {
	return os.RemoveAll(path)
}

func CreateDirectory(path string) error {
	return os.MkdirAll(path, 0700)
}

func IsYes(preference string) bool {
	if strings.ToLower(preference) == "yes" || (len(preference) == 1 && strings.ToLower(preference) == "y" ) {
		return true
	}
	return false
}

func IsNo(preference string) bool {
	if strings.ToLower(preference) == "no" || (len(preference) == 1 && strings.ToLower(preference) == "n" ) {
		return true
	}
	return false
}

func IsReenter(preference string) bool {
	if strings.ToLower(preference) == "reenter" || strings.ToLower(preference) == "re-enter" || (len(preference) == 1 && strings.ToLower(preference) == "r" ) {
		return true
	}
	return false
}

func GetUserInput() (string, error) {
	reader := bufio.NewReader(os.Stdin)
	preference, err := reader.ReadString('\n')
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(preference), nil
}

func IsUserPreferencesValid(preferences []string, availableChoices int) (bool, error) {
	length := len(preferences)
	if length == 0 {
		return false, &CustomError{What:"No preferences entered."}
	}
	first, err := strconv.Atoi(preferences[0])
	if err != nil {
		return false, err
	}
	message := "Invalid preferences. Please select indices where " + strconv.Itoa(availableChoices) + ">= index >=1."
	if first < 1 {
		return false, &CustomError{What:message}
	}
	last, err := strconv.Atoi(preferences[length - 1])
	if err != nil {
		return false, err
	}
	if last > availableChoices {
		return false, &CustomError{What:message}
	}
	return true, nil
}

//This function will read update-descriptor.yaml
func LoadUpdateDescriptor(filename, updateDirectoryPath string) (*UpdateDescriptor, error) {

	//Construct the file path
	updateDescriptorPath := filepath.Join(updateDirectoryPath, filename)
	log.Debug("updateDescriptorPath:", updateDescriptorPath)

	//Read the file
	updateDescriptor := UpdateDescriptor{}
	yamlFile, err := ioutil.ReadFile(updateDescriptorPath)
	if err != nil {
		return nil, &CustomError{What: err.Error()}
	}
	//Un-marshal the update-descriptor file to updateDescriptor struct
	err = yaml.Unmarshal(yamlFile, &updateDescriptor)
	if err != nil {
		return nil, &CustomError{What: err.Error()}
	}
	return &updateDescriptor, nil
}

//todo: change error to
func ValidateUpdateDescriptor(updateDescriptor *UpdateDescriptor) error {
	if len(updateDescriptor.Update_number) == 0 {
		return &CustomError{What: "'update_number' field not found." }
	}
	//todo: use regex to validate Update_number format

	//todo: trim
	if len(updateDescriptor.Platform_version) == 0 {
		return &CustomError{What: "'platform_version' field not found." }
	}
	//todo: use regex to validate Platform_version format
	if len(updateDescriptor.Platform_name) == 0 {
		return &CustomError{What: "'platform_name' field not found." }
	}
	if len(updateDescriptor.Applies_to) == 0 {
		return &CustomError{What: "'applies_to' field not found." }
	}
	if len(updateDescriptor.Bug_fixes) == 0 {
		return &CustomError{What: "'bug_fixes' field not found." }
	}
	if len(updateDescriptor.Description) == 0 {
		return &CustomError{What: "'description' field not found." }
	}
	return nil
}

func PrintUpdateDescriptor(updateDescriptor *UpdateDescriptor) {
	fmt.Println("----------------------------------------------------------------")
	fmt.Printf("update_number: %s\n", updateDescriptor.Update_number)
	fmt.Printf("kernel_version: %s\n", updateDescriptor.Platform_version)
	fmt.Printf("platform_version: %s\n", updateDescriptor.Platform_name)
	fmt.Printf("applies_to: %s\n", updateDescriptor.Applies_to)
	fmt.Printf("bug_fixes: %s\n", updateDescriptor.Bug_fixes)
	fmt.Printf("file_changes: %s\n", updateDescriptor.File_changes)
	fmt.Printf("description: %s\n", updateDescriptor.Description)
	fmt.Println("----------------------------------------------------------------")
}

//Check whether the given string is in the given slice
func IsStringIsInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

// Copies file source to destination dest.
func CopyFile(source string, dest string) (err error) {
	sf, err := os.Open(source)
	if err != nil {
		return err
	}
	defer sf.Close()
	df, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err == nil {
		si, err := os.Stat(source)
		if err != nil {
			return os.Chmod(dest, si.Mode())
		}

	}
	return
}

//Recursively copies a directory tree, attempting to preserve permissions.
//Source directory must exist, destination directory must *not* exist.
func CopyDir(source string, dest string) (err error) {
	// get properties of source dir
	fi, err := os.Stat(source)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return &CustomError{What: "Source is not a directory"}
	}
	//Create the destination folder if it does not exist
	_, err = os.Open(dest)
	if os.IsNotExist(err) {
		// create dest dir
		err = os.MkdirAll(dest, fi.Mode())
		if err != nil {
			return &CustomError{What: err.Error()}
		}
	}
	entries, err := ioutil.ReadDir(source)
	for _, entry := range entries {
		sfp := source + "/" + entry.Name()
		dfp := dest + "/" + entry.Name()
		if entry.IsDir() {
			err = CopyDir(sfp, dfp)
			if err != nil {
				return err
			}
		} else {
			// perform copy
			err = CopyFile(sfp, dfp)
			if err != nil {
				return err
			}
		}
	}
	return
}

func HandleError(err error, customMessage ...interface{}) {
	if err != nil {
		PrintErrorAndExit(append(customMessage, "Error Message: '" + err.Error() + "'")...)
	}
}

//A struct for returning custom error messages
type CustomError struct {
	What string
}

//Returns the error message defined in What as a string
func (e *CustomError) Error() string {
	return e.What
}

//Check whether the given location points to a directory
func IsDirectoryExists(location string) (bool, error) {
	locationInfo, err := os.Stat(location)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		} else {
			return false, err
		}
	}
	if locationInfo.IsDir() {
		return true, nil
	} else {
		return false, nil
	}
}

//Check whether the given location points to a file
func IsFileExists(location string) (bool, error) {
	locationInfo, err := os.Stat(location)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		} else {
			return false, err
		}
	}
	if locationInfo.IsDir() {
		return false, nil
	} else {
		return true, nil
	}
}

//This is used to print failure messages
func PrintError(args ...interface{}) {
	color.Set(color.FgRed, color.Bold)
	fmt.Println(append(append([]interface{}{"\n[ERROR]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print failure messages and exit
func PrintErrorAndExit(args ...interface{}) {
	//call the printFailure method and exit
	PrintError(args...)
	os.Exit(1)
}

//This is used to print warning messages
func PrintWarning(args ...interface{}) {
	//color.Set(color.FgYellow, color.Bold)
	fmt.Println(append(append([]interface{}{"[WARNING]"}, args...), "\n")...)
	//color.Unset()
}

//This is used to print info messages
func PrintInfo(args ...interface{}) {
	color.Set(color.FgYellow, color.Bold)
	fmt.Println(append(append([]interface{}{"[INFO]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print success messages
func PrintSuccess(args ...interface{}) {
	color.Set(color.FgGreen, color.Bold)
	fmt.Println(append(append([]interface{}{"[INFO]"}, args...), "\n")...)
	color.Unset()
}

//This is used to print messages in Yellow color
func PrintInYellow(args ...interface{}) {
	color.Set(color.FgYellow, color.Bold)
	fmt.Print(args...)
	color.Unset()
}

//This is used to print messages in Red color
func PrintInRed(args ...interface{}) {
	color.Set(color.FgRed, color.Bold)
	fmt.Print(args...)
	color.Unset()
}
<|endoftext|>


<commit_before>package language

import (
	"fmt"
	"testing"

	"github.com/itsabot/abot/shared/datatypes"
	"github.com/itsabot/abot/shared/log"
	"github.com/itsabot/abot/shared/nlp"
	"github.com/itsabot/abot/shared/plugin"
)

func TestExtractCities(t *testing.T) {
	log.DebugOn(true)
	db, err := plugin.ConnectDB()
	if err != nil {
		t.Error(err)
	}
	var cities []dt.City
	in := &dt.Msg{}
	in.Sentence = "I'm in New York"
	in.Tokens = nlp.TokenizeSentence(in.Sentence)
	in.Stems = nlp.StemTokens(in.Tokens)
	cities, err = ExtractCities(db, in)
	if err != nil {
		t.Error(err)
	}
	if len(cities) == 0 || cities[0].Name != "New York" {
		t.Error(fmt.Errorf("expected New York, but got %s\n", cities[0]))
	}
	in = &dt.Msg{}
	in.Sentence = "I'm in LA or San Francisco next week"
	in.Tokens = nlp.TokenizeSentence(in.Sentence)
	in.Stems = nlp.StemTokens(in.Tokens)
	cities, err = ExtractCities(db, in)
	if err != nil {
		t.Error(err)
	}
	if len(cities) < 2 {
		t.Error(fmt.Errorf("expected >2 cities, but got %d\n", len(cities)))
	}
}
<commit_msg>Use new log API<commit_after>package language

import (
	"errors"
	"fmt"
	"testing"

	"github.com/itsabot/abot/shared/datatypes"
	"github.com/itsabot/abot/shared/log"
	"github.com/itsabot/abot/shared/nlp"
	"github.com/itsabot/abot/shared/plugin"
)

func TestExtractCities(t *testing.T) {
	log.SetDebug(true)
	db, err := plugin.ConnectDB()
	if err != nil {
		t.Error(err)
	}
	var cities []dt.City
	in := &dt.Msg{}
	in.Sentence = "I'm in New York"
	in.Tokens = nlp.TokenizeSentence(in.Sentence)
	in.Stems = nlp.StemTokens(in.Tokens)
	cities, err = ExtractCities(db, in)
	if err != nil {
		t.Error(err)
	}
	if len(cities) == 0 {
		t.Error(errors.New("expected New York, extracted none"))
	}
	if cities[0].Name != "New York" {
		t.Error(fmt.Errorf("expected New York, extracted %s", cities[0].Name))
	}
	in = &dt.Msg{}
	in.Sentence = "I'm in LA or San Francisco next week"
	in.Tokens = nlp.TokenizeSentence(in.Sentence)
	in.Stems = nlp.StemTokens(in.Tokens)
	cities, err = ExtractCities(db, in)
	if err != nil {
		t.Error(err)
	}
	if len(cities) < 2 {
		t.Error(fmt.Errorf("expected >2 cities, but got %d\n", len(cities)))
	}
	in = &dt.Msg{}
	in.Sentence = "What's the weather like in San Francisco?"
	in.Tokens = nlp.TokenizeSentence(in.Sentence)
	in.Stems = nlp.StemTokens(in.Tokens)
	cities, err = ExtractCities(db, in)
	if err != nil {
		t.Error(err)
	}
	if len(cities) == 0 {
		t.Error(fmt.Errorf("expected San Francisco"))
	}
	if cities[0].Name != "San Francisco" {
	}
}
<|endoftext|>


<commit_before>package lily

// Author João Nuno.
//
// joaonrb@gmail.com
//

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

func TestLineIterator(t *testing.T) {
	tmp := "/tmp/line_iterator.txt"
	content := "line1\n1\n"
	//defer os.Remove(tmp)
	err := ioutil.WriteFile(tmp, []byte(content), 0644)
	if err != nil {
		fmt.Printf("Tmp file couldn't be written becauser error %s", err.Error())
		os.Exit(1)
	}
	iter, err := NewLineIterator(tmp)
	switch {
	case err != nil:
		t.Error(err.Error())
	case iter.Next() != "line1" && iter.HasNext():
		t.Error("Line 1 is not expected(line1).")
	case iter.Next() != "1" && iter.HasNext():
		t.Error("Line 2 is not expected(1).")
	case iter.Next() != "" && !iter.HasNext():
		t.Error("Line 3 is not expected().")
	case iter.Next() != "":
		t.Error("Line 4 is not expected at all.")
	}
}

func TestGenerateBase64StringSize(t *testing.T) {
	for i, n := range []int{0, 1, 2, 5, 10, 25, 30, 50, 75, 100} {
		hex := GenerateBase64String(n)
		if len(hex) != n {
			t.Errorf("%d - Size of GenerateBase64String(%d) should be %d, got %d instead.", i, n, n, len(hex))
			return
		}
	}
}

func BGenerateBase64StringN(n int, b *testing.B) {
	for i := 0; i < b.N; i++ {
		GenerateBase64String(n)
	}
}

func BenchmarkGenerateBase64String1(b *testing.B) {
	BGenerateBase64StringN(1, b)
}

func BenchmarkGenerateBase64String5(b *testing.B) {
	BGenerateBase64StringN(5, b)
}

func BenchmarkGenerateBase64String10(b *testing.B) {
	BGenerateBase64StringN(10, b)
}

func BenchmarkGenerateBase64String25(b *testing.B) {
	BGenerateBase64StringN(25, b)
}

func BenchmarkGenerateBase64String50(b *testing.B) {
	BGenerateBase64StringN(50, b)
}

func BenchmarkGenerateBase64String75(b *testing.B) {
	BGenerateBase64StringN(75, b)
}

func BenchmarkGenerateBase64String100(b *testing.B) {
	BGenerateBase64StringN(100, b)
}
<commit_msg>Iterator tests<commit_after>package lily

// Author João Nuno.
//
// joaonrb@gmail.com
//

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

func TestLineIterator(t *testing.T) {
	tmp := "/tmp/line_iterator.txt"
	content := "line1\n1\n"
	defer os.Remove(tmp)
	err := ioutil.WriteFile(tmp, []byte(content), 0644)
	if err != nil {
		fmt.Printf("Tmp file couldn't be written becauser error %s", err.Error())
		os.Exit(1)
	}
	iter, err := NewLineIterator(tmp)
	defer iter.Close()
	switch {
	case err != nil:
		t.Error(err.Error())
	case iter.HasNext() && "line1" != iter.Next():
		t.Error("Line 1 is not expected(line1).")
	case iter.HasNext() && iter.Next() != "1":
		t.Error("Line 2 is not expected(1).")
	case iter.HasNext() && iter.Next() != "":
		t.Error("Line 3 is not expected().")
	case iter.HasNext() && iter.Next() != "" && !iter.HasNext():
		t.Error("Line 4 is not expected at all.")
	}
}

func TestLineIteratorFileDontExist(t *testing.T) {
	tmp := "/tmp/line_iterator_not.txt"
	iter, err := NewLineIterator(tmp)
	defer iter.Close()
	switch {
	case err == nil:
		t.Error("Error do not happened")
	}
}

func TestGenerateBase64StringSize(t *testing.T) {
	for i, n := range []int{0, 1, 2, 5, 10, 25, 30, 50, 75, 100} {
		hex := GenerateBase64String(n)
		if len(hex) != n {
			t.Errorf("%d - Size of GenerateBase64String(%d) should be %d, got %d instead.", i, n, n, len(hex))
			return
		}
	}
}

func BGenerateBase64StringN(n int, b *testing.B) {
	for i := 0; i < b.N; i++ {
		GenerateBase64String(n)
	}
}

func BenchmarkGenerateBase64String1(b *testing.B) {
	BGenerateBase64StringN(1, b)
}

func BenchmarkGenerateBase64String5(b *testing.B) {
	BGenerateBase64StringN(5, b)
}

func BenchmarkGenerateBase64String10(b *testing.B) {
	BGenerateBase64StringN(10, b)
}

func BenchmarkGenerateBase64String25(b *testing.B) {
	BGenerateBase64StringN(25, b)
}

func BenchmarkGenerateBase64String50(b *testing.B) {
	BGenerateBase64StringN(50, b)
}

func BenchmarkGenerateBase64String75(b *testing.B) {
	BGenerateBase64StringN(75, b)
}

func BenchmarkGenerateBase64String100(b *testing.B) {
	BGenerateBase64StringN(100, b)
}
<|endoftext|>