<commit_before>// Copyright (c) 2015 Serge Gebhardt. All rights reserved.
//
// Use of this source code is governed by the ISC
// license that can be found in the LICENSE file.

package acd

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

const (
	libraryVersion = "0.1"
	defaultBaseURL = "https://drive.amazonaws.com/drive/v1/"
	userAgent      = "go-acd/" + libraryVersion
)

// A Client manages communication with the Amazon Cloud Drive API.
type Client struct {
	// HTTP client used to communicate with the API.
	httpClient *http.Client

	// Base URL for API requests. Defaults to the public Amazon Cloud Drive API.
	// BaseURL should always be specified with a trailing slash.
	BaseURL *url.URL

	// User agent used when communicating with the API.
	UserAgent string

	// Services used for talking to different parts of the API.
	Account *AccountService
}

// NewClient returns a new Amazon Cloud Drive API client. If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by the golang.org/x/oauth2 library).
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{httpClient: httpClient, BaseURL: baseURL, UserAgent: userAgent}
	c.Account = &AccountService{client: c}
	return c
}

// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	//	req.Header.Add("Accept", mediaTypeV3)
	if c.UserAgent != "" {
		req.Header.Add("User-Agent", c.UserAgent)
	}
	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting to
// first decode it.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	//	err = CheckResponse(resp)
	//	if err != nil {
	//		// even though there was an error, we still return the response
	//		// in case the caller wants to inspect it further
	//		return resp, err
	//	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, resp.Body)
		} else {
			err = json.NewDecoder(resp.Body).Decode(v)
		}
	}
	return resp, err
}
<commit_msg>Export LibraryVersion<commit_after>// Copyright (c) 2015 Serge Gebhardt. All rights reserved.
//
// Use of this source code is governed by the ISC
// license that can be found in the LICENSE file.

package acd

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

const (
	LibraryVersion = "0.1"
	defaultBaseURL = "https://drive.amazonaws.com/drive/v1/"
	userAgent      = "go-acd/" + LibraryVersion
)

// A Client manages communication with the Amazon Cloud Drive API.
type Client struct {
	// HTTP client used to communicate with the API.
	httpClient *http.Client

	// Base URL for API requests. Defaults to the public Amazon Cloud Drive API.
	// BaseURL should always be specified with a trailing slash.
	BaseURL *url.URL

	// User agent used when communicating with the API.
	UserAgent string

	// Services used for talking to different parts of the API.
	Account *AccountService
}

// NewClient returns a new Amazon Cloud Drive API client. If a nil httpClient is
// provided, http.DefaultClient will be used. To use API methods which require
// authentication, provide an http.Client that will perform the authentication
// for you (such as that provided by the golang.org/x/oauth2 library).
func NewClient(httpClient *http.Client) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(defaultBaseURL)

	c := &Client{httpClient: httpClient, BaseURL: baseURL, UserAgent: userAgent}
	c.Account = &AccountService{client: c}
	return c
}

// NewRequest creates an API request. A relative URL can be provided in urlStr,
// in which case it is resolved relative to the BaseURL of the Client.
// Relative URLs should always be specified without a preceding slash. If
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	//	req.Header.Add("Accept", mediaTypeV3)
	if c.UserAgent != "" {
		req.Header.Add("User-Agent", c.UserAgent)
	}
	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred. If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting to
// first decode it.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	//	err = CheckResponse(resp)
	//	if err != nil {
	//		// even though there was an error, we still return the response
	//		// in case the caller wants to inspect it further
	//		return resp, err
	//	}

	if v != nil {
		if w, ok := v.(io.Writer); ok {
			io.Copy(w, resp.Body)
		} else {
			err = json.NewDecoder(resp.Body).Decode(v)
		}
	}
	return resp, err
}
<|endoftext|>


<commit_before>// Copyright 2014 The Chihaya Authors. All rights reserved.
// Use of this source code is governed by the BSD 2-Clause license,
// which can be found in the LICENSE file.

package http

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

	"github.com/julienschmidt/httprouter"

	"github.com/chihaya/chihaya/stats"
	"github.com/chihaya/chihaya/tracker/models"
)

const jsonContentType = "application/json; charset=UTF-8"

func (s *Server) check(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	if _, err := w.Write([]byte("STILL-ALIVE")); err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) stats(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	w.Header().Set("Content-Type", jsonContentType)

	e := json.NewEncoder(w)
	err := e.Encode(stats.DefaultStats)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	ann, err := NewAnnounce(s.config, r, p)
	writer := &Writer{w}

	if err == models.ErrMalformedRequest || err == models.ErrBadRequest {
		writer.WriteError(err)
		return http.StatusOK, nil
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	if err = s.tracker.HandleAnnounce(ann, writer); err != nil {
		return http.StatusInternalServerError, err
	}

	stats.RecordEvent(stats.Announce)

	return http.StatusOK, nil
}

func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	scrape, err := NewScrape(s.config, r, p)
	writer := &Writer{w}

	if err == models.ErrMalformedRequest {
		writer.WriteError(err)
		return http.StatusOK, nil
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	if err = s.tracker.HandleScrape(scrape, writer); err != nil {
		return http.StatusInternalServerError, err
	}

	stats.RecordEvent(stats.Scrape)

	return http.StatusOK, nil
}

func (s *Server) getTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	infohash, err := url.QueryUnescape(p.ByName("infohash"))
	if err != nil {
		return http.StatusNotFound, err
	}

	torrent, err := conn.FindTorrent(infohash)
	if err == models.ErrTorrentDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	w.Header().Set("Content-Type", jsonContentType)
	e := json.NewEncoder(w)
	err = e.Encode(torrent)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	var torrent models.Torrent
	err = json.Unmarshal(body, &torrent)
	if err != nil {
		return http.StatusBadRequest, err
	}

	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutTorrent(&torrent)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	infohash, err := url.QueryUnescape(p.ByName("infohash"))
	if err != nil {
		return http.StatusNotFound, err
	}

	err = conn.DeleteTorrent(infohash)
	if err == models.ErrTorrentDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) getUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	user, err := conn.FindUser(p.ByName("passkey"))
	if err == models.ErrUserDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	w.Header().Set("Content-Type", jsonContentType)
	e := json.NewEncoder(w)
	err = e.Encode(user)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	var user models.User
	err = json.Unmarshal(body, &user)
	if err != nil {
		return http.StatusBadRequest, err
	}

	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutUser(&user)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.DeleteUser(p.ByName("passkey"))
	if err == models.ErrUserDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutClient(p.ByName("clientID"))
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.DeleteClient(p.ByName("clientID"))
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}
<commit_msg>Handle ErrBadRequest after HandleAnnounce is called<commit_after>// Copyright 2014 The Chihaya Authors. All rights reserved.
// Use of this source code is governed by the BSD 2-Clause license,
// which can be found in the LICENSE file.

package http

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

	"github.com/julienschmidt/httprouter"

	"github.com/chihaya/chihaya/stats"
	"github.com/chihaya/chihaya/tracker/models"
)

const jsonContentType = "application/json; charset=UTF-8"

func (s *Server) check(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	if _, err := w.Write([]byte("STILL-ALIVE")); err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) stats(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	w.Header().Set("Content-Type", jsonContentType)

	e := json.NewEncoder(w)
	err := e.Encode(stats.DefaultStats)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	ann, err := NewAnnounce(s.config, r, p)
	writer := &Writer{w}

	if err == models.ErrMalformedRequest {
		writer.WriteError(err)
		return http.StatusOK, nil
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	err = s.tracker.HandleAnnounce(ann, writer)

	if err == models.ErrBadRequest {
		writer.WriteError(err)
		return http.StatusOK, nil
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	stats.RecordEvent(stats.Announce)
	return http.StatusOK, nil
}

func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	scrape, err := NewScrape(s.config, r, p)
	writer := &Writer{w}

	if err == models.ErrMalformedRequest {
		writer.WriteError(err)
		return http.StatusOK, nil
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	if err = s.tracker.HandleScrape(scrape, writer); err != nil {
		return http.StatusInternalServerError, err
	}

	stats.RecordEvent(stats.Scrape)

	return http.StatusOK, nil
}

func (s *Server) getTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	infohash, err := url.QueryUnescape(p.ByName("infohash"))
	if err != nil {
		return http.StatusNotFound, err
	}

	torrent, err := conn.FindTorrent(infohash)
	if err == models.ErrTorrentDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	w.Header().Set("Content-Type", jsonContentType)
	e := json.NewEncoder(w)
	err = e.Encode(torrent)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	var torrent models.Torrent
	err = json.Unmarshal(body, &torrent)
	if err != nil {
		return http.StatusBadRequest, err
	}

	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutTorrent(&torrent)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delTorrent(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	infohash, err := url.QueryUnescape(p.ByName("infohash"))
	if err != nil {
		return http.StatusNotFound, err
	}

	err = conn.DeleteTorrent(infohash)
	if err == models.ErrTorrentDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) getUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	user, err := conn.FindUser(p.ByName("passkey"))
	if err == models.ErrUserDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	w.Header().Set("Content-Type", jsonContentType)
	e := json.NewEncoder(w)
	err = e.Encode(user)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	var user models.User
	err = json.Unmarshal(body, &user)
	if err != nil {
		return http.StatusBadRequest, err
	}

	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutUser(&user)
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.DeleteUser(p.ByName("passkey"))
	if err == models.ErrUserDNE {
		return http.StatusNotFound, err
	} else if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) putClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.PutClient(p.ByName("clientID"))
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}

func (s *Server) delClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
	conn, err := s.tracker.Pool.Get()
	if err != nil {
		return http.StatusInternalServerError, err
	}

	err = conn.DeleteClient(p.ByName("clientID"))
	if err != nil {
		return http.StatusInternalServerError, err
	}

	return http.StatusOK, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
    eatonconfig "github.com/ECLabs/Eaton-Feeder/config"
	eatonevents "github.com/ECLabs/Eaton-Feeder/events"
	"log"
	"net/http"
)

func main() {
    eatonconfig.OffsetType = "oldest"
	consumer, err := eatonevents.NewEventConsumer()
	if err != nil {
		log.Fatal("failed to create kafka consumer: ", err)
	}
	out, outErr := consumer.Consume()
	go func() {
		for msg := range out {
			data, err := json.Marshal(msg)
			if err != nil {
				log.Println("failed to marshal msg: ", err)
				continue
			}
			h.broadcast <- data
		}
	}()
	go func() {
		for err := range outErr {
			log.Println("error: ", err)
		}
	}()
	go h.run()
	http.HandleFunc("/ws", serveWs)
	http.Handle("/", http.FileServer(http.Dir("./assets")))
	log.Println("Serving at localhost:5000...")
	log.Fatal(http.ListenAndServe(":5000", nil))
}
<commit_msg>correct formatting.<commit_after>package main

import (
	"encoding/json"
	eatonconfig "github.com/ECLabs/Eaton-Feeder/config"
	eatonevents "github.com/ECLabs/Eaton-Feeder/events"
	"log"
	"net/http"
)

func main() {
	eatonconfig.OffsetType = "oldest"
	consumer, err := eatonevents.NewEventConsumer()
	if err != nil {
		log.Fatal("failed to create kafka consumer: ", err)
	}
	out, outErr := consumer.Consume()
	go func() {
		for msg := range out {
			data, err := json.Marshal(msg)
			if err != nil {
				log.Println("failed to marshal msg: ", err)
				continue
			}
			h.broadcast <- data
		}
	}()
	go func() {
		for err := range outErr {
			log.Println("error: ", err)
		}
	}()
	go h.run()
	http.HandleFunc("/ws", serveWs)
	http.Handle("/", http.FileServer(http.Dir("./assets")))
	log.Println("Serving at localhost:5000...")
	log.Fatal(http.ListenAndServe(":5000", nil))
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"
	"github.com/pierrre/imageserver"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var inmHeaderRegexp, _ = regexp.Compile("^\"(.+)\"$")

var expiresHeaderLocation, _ = time.LoadLocation("GMT")

type Server struct {
	HttpServer  *http.Server
	Parser      Parser
	ImageServer *imageserver.Server

	Expire time.Duration
}

func (server *Server) Serve() {
	serveMux := http.NewServeMux()
	serveMux.HandleFunc("/", server.handleHttpRequest)
	serveMux.HandleFunc("/_ping", server.handleHttpRequestPing)
	server.HttpServer.Handler = serveMux
	server.HttpServer.ListenAndServe()
}

func (server *Server) handleHttpRequest(writer http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		server.sendError(writer, fmt.Errorf("Invalid request method"))
		return
	}

	parameters := make(imageserver.Parameters)
	if err := server.Parser.Parse(request, parameters); err != nil {
		server.sendError(writer, err)
		return
	}

	if server.checkNotModified(writer, request, parameters) {
		return
	}

	image, err := server.ImageServer.Get(parameters)
	if err != nil {
		server.sendError(writer, err)
		return
	}

	server.sendImage(writer, image, parameters)
}

func (server *Server) checkNotModified(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) bool {
	inmHeader := request.Header.Get("If-None-Match")
	if len(inmHeader) > 0 {
		matches := inmHeaderRegexp.FindStringSubmatch(inmHeader)
		if matches != nil && len(matches) == 2 {
			inm := matches[1]
			if inm == parameters.Hash() {
				writer.WriteHeader(http.StatusNotModified)
				return true
			}
		}
	}
	return false
}

func (server *Server) sendImage(writer http.ResponseWriter, image *imageserver.Image, parameters imageserver.Parameters) {
	writer.Header().Set("Content-Length", strconv.Itoa(len(image.Data)))

	if len(image.Type) > 0 {
		writer.Header().Set("Content-Type", "image/"+image.Type)
	}

	writer.Header().Set("Cache-Control", "public")

	if server.Expire != 0 {
		t := time.Now()
		t = t.Add(server.Expire)
		t = t.In(expiresHeaderLocation)
		writer.Header().Set("Expires", t.Format(time.RFC1123))
	}

	writer.Header().Set("ETag", fmt.Sprintf("\"%s\"", parameters.Hash()))

	writer.Write(image.Data)
}

func (server *Server) sendError(writer http.ResponseWriter, err error) {
	http.Error(writer, err.Error(), http.StatusBadRequest)
}

func (server *Server) handleHttpRequestPing(writer http.ResponseWriter, request *http.Request) {
	writer.WriteHeader(200)
}
<commit_msg>Fix http cache header<commit_after>package http

import (
	"fmt"
	"github.com/pierrre/imageserver"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var inmHeaderRegexp, _ = regexp.Compile("^\"(.+)\"$")

var expiresHeaderLocation, _ = time.LoadLocation("GMT")

type Server struct {
	HttpServer  *http.Server
	Parser      Parser
	ImageServer *imageserver.Server

	Expire time.Duration
}

func (server *Server) Serve() {
	serveMux := http.NewServeMux()
	serveMux.HandleFunc("/", server.handleHttpRequest)
	serveMux.HandleFunc("/_ping", server.handleHttpRequestPing)
	server.HttpServer.Handler = serveMux
	server.HttpServer.ListenAndServe()
}

func (server *Server) handleHttpRequest(writer http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		server.sendError(writer, fmt.Errorf("Invalid request method"))
		return
	}

	parameters := make(imageserver.Parameters)
	if err := server.Parser.Parse(request, parameters); err != nil {
		server.sendError(writer, err)
		return
	}

	if server.checkNotModified(writer, request, parameters) {
		return
	}

	image, err := server.ImageServer.Get(parameters)
	if err != nil {
		server.sendError(writer, err)
		return
	}

	server.sendImage(writer, image, parameters)
}

func (server *Server) checkNotModified(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) bool {
	inmHeader := request.Header.Get("If-None-Match")
	if len(inmHeader) > 0 {
		matches := inmHeaderRegexp.FindStringSubmatch(inmHeader)
		if matches != nil && len(matches) == 2 {
			inm := matches[1]
			if inm == parameters.Hash() {
				server.sendHeaderCache(writer, parameters)
				writer.WriteHeader(http.StatusNotModified)
				return true
			}
		}
	}
	return false
}

func (server *Server) sendImage(writer http.ResponseWriter, image *imageserver.Image, parameters imageserver.Parameters) {
	server.sendHeaderCache(writer, parameters)

	if len(image.Type) > 0 {
		writer.Header().Set("Content-Type", "image/"+image.Type)
	}

	writer.Header().Set("Content-Length", strconv.Itoa(len(image.Data)))

	writer.Write(image.Data)
}

func (server *Server) sendHeaderCache(writer http.ResponseWriter, parameters imageserver.Parameters) {
	writer.Header().Set("Cache-Control", "public")

	writer.Header().Set("ETag", fmt.Sprintf("\"%s\"", parameters.Hash()))

	if server.Expire != 0 {
		t := time.Now()
		t = t.Add(server.Expire)
		t = t.In(expiresHeaderLocation)
		writer.Header().Set("Expires", t.Format(time.RFC1123))
	}
}

func (server *Server) sendError(writer http.ResponseWriter, err error) {
	http.Error(writer, err.Error(), http.StatusBadRequest)
}

func (server *Server) handleHttpRequestPing(writer http.ResponseWriter, request *http.Request) {
	writer.WriteHeader(200)
}
<|endoftext|>


<commit_before>package bencode

import (
	"io"
	"math/big"
	"reflect"
	"runtime"
	"sort"
	"strconv"
	"sync"

	"github.com/anacrolix/missinggo"
)

func isEmptyValue(v reflect.Value) bool {
	return missinggo.IsEmptyValue(v)
}

type Encoder struct {
	w       io.Writer
	scratch [64]byte
}

func (e *Encoder) Encode(v interface{}) (err error) {
	if v == nil {
		return
	}
	defer func() {
		if e := recover(); e != nil {
			if _, ok := e.(runtime.Error); ok {
				panic(e)
			}
			var ok bool
			err, ok = e.(error)
			if !ok {
				panic(e)
			}
		}
	}()
	e.reflectValue(reflect.ValueOf(v))
	return nil
}

type stringValues []reflect.Value

func (sv stringValues) Len() int           { return len(sv) }
func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string   { return sv[i].String() }

func (e *Encoder) write(s []byte) {
	_, err := e.w.Write(s)
	if err != nil {
		panic(err)
	}
}

func (e *Encoder) writeString(s string) {
	for s != "" {
		n := copy(e.scratch[:], s)
		s = s[n:]
		e.write(e.scratch[:n])
	}
}

func (e *Encoder) reflectString(s string) {
	b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
	e.write(b)
	e.writeString(":")
	e.writeString(s)
}

func (e *Encoder) reflectByteSlice(s []byte) {
	b := strconv.AppendInt(e.scratch[:0], int64(len(s)), 10)
	e.write(b)
	e.writeString(":")
	e.write(s)
}

// Returns true if the value implements Marshaler interface and marshaling was
// done successfully.
func (e *Encoder) reflectMarshaler(v reflect.Value) bool {
	if !v.Type().Implements(marshalerType) {
		if v.Kind() != reflect.Ptr && v.CanAddr() && v.Addr().Type().Implements(marshalerType) {
			v = v.Addr()
		} else {
			return false
		}
	}
	m := v.Interface().(Marshaler)
	data, err := m.MarshalBencode()
	if err != nil {
		panic(&MarshalerError{v.Type(), err})
	}
	e.write(data)
	return true
}

var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()

func (e *Encoder) reflectValue(v reflect.Value) {

	if e.reflectMarshaler(v) {
		return
	}

	if v.Type() == bigIntType {
		e.writeString("i")
		bi := v.Interface().(big.Int)
		e.writeString(bi.String())
		e.writeString("e")
		return
	}

	switch v.Kind() {
	case reflect.Bool:
		if v.Bool() {
			e.writeString("i1e")
		} else {
			e.writeString("i0e")
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		e.writeString("i")
		b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
		e.write(b)
		e.writeString("e")
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		e.writeString("i")
		b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
		e.write(b)
		e.writeString("e")
	case reflect.String:
		e.reflectString(v.String())
	case reflect.Struct:
		e.writeString("d")
		for _, ef := range getEncodeFields(v.Type()) {
			fieldValue := ef.i(v)
			if !fieldValue.IsValid() {
				continue
			}
			if ef.omitEmpty && isEmptyValue(fieldValue) {
				continue
			}
			e.reflectString(ef.tag)
			e.reflectValue(fieldValue)
		}
		e.writeString("e")
	case reflect.Map:
		if v.Type().Key().Kind() != reflect.String {
			panic(&MarshalTypeError{v.Type()})
		}
		if v.IsNil() {
			e.writeString("de")
			break
		}
		e.writeString("d")
		sv := stringValues(v.MapKeys())
		sort.Sort(sv)
		for _, key := range sv {
			e.reflectString(key.String())
			e.reflectValue(v.MapIndex(key))
		}
		e.writeString("e")
	case reflect.Slice:
		e.reflectSlice(v)
	case reflect.Array:
		e.reflectSlice(v.Slice(0, v.Len()))
	case reflect.Interface:
		e.reflectValue(v.Elem())
	case reflect.Ptr:
		if v.IsNil() {
			v = reflect.Zero(v.Type().Elem())
		} else {
			v = v.Elem()
		}
		e.reflectValue(v)
	default:
		panic(&MarshalTypeError{v.Type()})
	}
}

func (e *Encoder) reflectSlice(v reflect.Value) {
	if v.Type().Elem().Kind() == reflect.Uint8 {
		// This can panic if v is not addressable, such as by passing an array of bytes by value. We
		// could copy them and make a slice to the copy, or the user could just avoid doing this. It
		// remains to be seen.
		s := v.Bytes()
		e.reflectByteSlice(s)
		return
	}
	if v.IsNil() {
		e.writeString("le")
		return
	}
	e.writeString("l")
	for i, n := 0, v.Len(); i < n; i++ {
		e.reflectValue(v.Index(i))
	}
	e.writeString("e")
}

type encodeField struct {
	i         func(v reflect.Value) reflect.Value
	tag       string
	omitEmpty bool
}

type encodeFieldsSortType []encodeField

func (ef encodeFieldsSortType) Len() int           { return len(ef) }
func (ef encodeFieldsSortType) Swap(i, j int)      { ef[i], ef[j] = ef[j], ef[i] }
func (ef encodeFieldsSortType) Less(i, j int) bool { return ef[i].tag < ef[j].tag }

var (
	typeCacheLock     sync.RWMutex
	encodeFieldsCache = make(map[reflect.Type][]encodeField)
)

func getEncodeFields(t reflect.Type) []encodeField {
	typeCacheLock.RLock()
	fs, ok := encodeFieldsCache[t]
	typeCacheLock.RUnlock()
	if ok {
		return fs
	}
	fs = makeEncodeFields(t)
	typeCacheLock.Lock()
	defer typeCacheLock.Unlock()
	encodeFieldsCache[t] = fs
	return fs
}

func makeEncodeFields(t reflect.Type) (fs []encodeField) {
	for _i, n := 0, t.NumField(); _i < n; _i++ {
		i := _i
		f := t.Field(i)
		if f.PkgPath != "" {
			continue
		}
		if f.Anonymous {
			t := f.Type
			if t.Kind() == reflect.Ptr {
				t = t.Elem()
			}
			anonEFs := makeEncodeFields(t)
			for aefi := range anonEFs {
				anonEF := anonEFs[aefi]
				bottomField := anonEF
				bottomField.i = func(v reflect.Value) reflect.Value {
					v = v.Field(i)
					if v.Kind() == reflect.Ptr {
						if v.IsNil() {
							// This will skip serializing this value.
							return reflect.Value{}
						}
						v = v.Elem()
					}
					return anonEF.i(v)
				}
				fs = append(fs, bottomField)
			}
			continue
		}
		var ef encodeField
		ef.i = func(v reflect.Value) reflect.Value {
			return v.Field(i)
		}
		ef.tag = f.Name

		tv := getTag(f.Tag)
		if tv.Ignore() {
			continue
		}
		if tv.Key() != "" {
			ef.tag = tv.Key()
		}
		ef.omitEmpty = tv.OmitEmpty()
		fs = append(fs, ef)
	}
	fss := encodeFieldsSortType(fs)
	sort.Sort(fss)
	return fs
}
<commit_msg>bencode: Fix marshalling of unaddressable array of bytes<commit_after>package bencode

import (
	"io"
	"math/big"
	"reflect"
	"runtime"
	"sort"
	"strconv"
	"sync"

	"github.com/anacrolix/missinggo"
)

func isEmptyValue(v reflect.Value) bool {
	return missinggo.IsEmptyValue(v)
}

type Encoder struct {
	w       io.Writer
	scratch [64]byte
}

func (e *Encoder) Encode(v interface{}) (err error) {
	if v == nil {
		return
	}
	defer func() {
		if e := recover(); e != nil {
			if _, ok := e.(runtime.Error); ok {
				panic(e)
			}
			var ok bool
			err, ok = e.(error)
			if !ok {
				panic(e)
			}
		}
	}()
	e.reflectValue(reflect.ValueOf(v))
	return nil
}

type stringValues []reflect.Value

func (sv stringValues) Len() int           { return len(sv) }
func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string   { return sv[i].String() }

func (e *Encoder) write(s []byte) {
	_, err := e.w.Write(s)
	if err != nil {
		panic(err)
	}
}

func (e *Encoder) writeString(s string) {
	for s != "" {
		n := copy(e.scratch[:], s)
		s = s[n:]
		e.write(e.scratch[:n])
	}
}

func (e *Encoder) reflectString(s string) {
	e.writeStringPrefix(int64(len(s)))
	e.writeString(s)
}

func (e *Encoder) writeStringPrefix(l int64) {
	b := strconv.AppendInt(e.scratch[:0], l, 10)
	e.write(b)
	e.writeString(":")
}

func (e *Encoder) reflectByteSlice(s []byte) {
	e.writeStringPrefix(int64(len(s)))
	e.write(s)
}

// Returns true if the value implements Marshaler interface and marshaling was
// done successfully.
func (e *Encoder) reflectMarshaler(v reflect.Value) bool {
	if !v.Type().Implements(marshalerType) {
		if v.Kind() != reflect.Ptr && v.CanAddr() && v.Addr().Type().Implements(marshalerType) {
			v = v.Addr()
		} else {
			return false
		}
	}
	m := v.Interface().(Marshaler)
	data, err := m.MarshalBencode()
	if err != nil {
		panic(&MarshalerError{v.Type(), err})
	}
	e.write(data)
	return true
}

var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()

func (e *Encoder) reflectValue(v reflect.Value) {

	if e.reflectMarshaler(v) {
		return
	}

	if v.Type() == bigIntType {
		e.writeString("i")
		bi := v.Interface().(big.Int)
		e.writeString(bi.String())
		e.writeString("e")
		return
	}

	switch v.Kind() {
	case reflect.Bool:
		if v.Bool() {
			e.writeString("i1e")
		} else {
			e.writeString("i0e")
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		e.writeString("i")
		b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
		e.write(b)
		e.writeString("e")
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		e.writeString("i")
		b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
		e.write(b)
		e.writeString("e")
	case reflect.String:
		e.reflectString(v.String())
	case reflect.Struct:
		e.writeString("d")
		for _, ef := range getEncodeFields(v.Type()) {
			fieldValue := ef.i(v)
			if !fieldValue.IsValid() {
				continue
			}
			if ef.omitEmpty && isEmptyValue(fieldValue) {
				continue
			}
			e.reflectString(ef.tag)
			e.reflectValue(fieldValue)
		}
		e.writeString("e")
	case reflect.Map:
		if v.Type().Key().Kind() != reflect.String {
			panic(&MarshalTypeError{v.Type()})
		}
		if v.IsNil() {
			e.writeString("de")
			break
		}
		e.writeString("d")
		sv := stringValues(v.MapKeys())
		sort.Sort(sv)
		for _, key := range sv {
			e.reflectString(key.String())
			e.reflectValue(v.MapIndex(key))
		}
		e.writeString("e")
	case reflect.Slice, reflect.Array:
		e.reflectSequence(v)
	case reflect.Interface:
		e.reflectValue(v.Elem())
	case reflect.Ptr:
		if v.IsNil() {
			v = reflect.Zero(v.Type().Elem())
		} else {
			v = v.Elem()
		}
		e.reflectValue(v)
	default:
		panic(&MarshalTypeError{v.Type()})
	}
}

func (e *Encoder) reflectSequence(v reflect.Value) {
	// Use bencode string-type
	if v.Type().Elem().Kind() == reflect.Uint8 {
		if v.Kind() != reflect.Slice {
			// Can't use []byte optimization
			if !v.CanAddr() {
				e.writeStringPrefix(int64(v.Len()))
				for i := 0; i < v.Len(); i++ {
					var b [1]byte
					b[0] = byte(v.Index(i).Uint())
					e.write(b[:])
				}
				return
			}
			v = v.Slice(0, v.Len())
		}
		s := v.Bytes()
		e.reflectByteSlice(s)
		return
	}
	if v.IsNil() {
		e.writeString("le")
		return
	}
	e.writeString("l")
	for i, n := 0, v.Len(); i < n; i++ {
		e.reflectValue(v.Index(i))
	}
	e.writeString("e")
}

type encodeField struct {
	i         func(v reflect.Value) reflect.Value
	tag       string
	omitEmpty bool
}

type encodeFieldsSortType []encodeField

func (ef encodeFieldsSortType) Len() int           { return len(ef) }
func (ef encodeFieldsSortType) Swap(i, j int)      { ef[i], ef[j] = ef[j], ef[i] }
func (ef encodeFieldsSortType) Less(i, j int) bool { return ef[i].tag < ef[j].tag }

var (
	typeCacheLock     sync.RWMutex
	encodeFieldsCache = make(map[reflect.Type][]encodeField)
)

func getEncodeFields(t reflect.Type) []encodeField {
	typeCacheLock.RLock()
	fs, ok := encodeFieldsCache[t]
	typeCacheLock.RUnlock()
	if ok {
		return fs
	}
	fs = makeEncodeFields(t)
	typeCacheLock.Lock()
	defer typeCacheLock.Unlock()
	encodeFieldsCache[t] = fs
	return fs
}

func makeEncodeFields(t reflect.Type) (fs []encodeField) {
	for _i, n := 0, t.NumField(); _i < n; _i++ {
		i := _i
		f := t.Field(i)
		if f.PkgPath != "" {
			continue
		}
		if f.Anonymous {
			t := f.Type
			if t.Kind() == reflect.Ptr {
				t = t.Elem()
			}
			anonEFs := makeEncodeFields(t)
			for aefi := range anonEFs {
				anonEF := anonEFs[aefi]
				bottomField := anonEF
				bottomField.i = func(v reflect.Value) reflect.Value {
					v = v.Field(i)
					if v.Kind() == reflect.Ptr {
						if v.IsNil() {
							// This will skip serializing this value.
							return reflect.Value{}
						}
						v = v.Elem()
					}
					return anonEF.i(v)
				}
				fs = append(fs, bottomField)
			}
			continue
		}
		var ef encodeField
		ef.i = func(v reflect.Value) reflect.Value {
			return v.Field(i)
		}
		ef.tag = f.Name

		tv := getTag(f.Tag)
		if tv.Ignore() {
			continue
		}
		if tv.Key() != "" {
			ef.tag = tv.Key()
		}
		ef.omitEmpty = tv.OmitEmpty()
		fs = append(fs, ef)
	}
	fss := encodeFieldsSortType(fs)
	sort.Sort(fss)
	return fs
}
<|endoftext|>


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

package test

import (
	"fmt"
	"net/http/httptest"
	"os"
	"strings"
	"testing"

	"shipshape/util/rpc/server"

	"github.com/golang/protobuf/proto"

	notepb "shipshape/proto/note_proto"
	ctxpb "shipshape/proto/shipshape_context_proto"
	rpcpb "shipshape/proto/shipshape_rpc_proto"
)

type Analyzer interface {
	Analyze(*ctxpb.ShipshapeContext) ([]*notepb.Note, error)
}

// CreateContext returns a new Shipshape test context
func CreateContext(testDir string, filepaths []string) (*ctxpb.ShipshapeContext, error) {
	context := &ctxpb.ShipshapeContext{
		FilePath: filepaths,
		RepoRoot: proto.String(testDir),
	}
	return context, nil
}

func CreateLocation(path string) *notepb.Location {
	return &notepb.Location{
		Path: proto.String(path),
	}
}

// RunAnalyzer does any preparation for running the analyzer, and runs
// it. Errors from setup/teardown will cause the test t to stop. Errors from the
// analysis will be returned, along with the notes
func RunAnalyzer(ctx *ctxpb.ShipshapeContext, a Analyzer, t *testing.T) ([]*notepb.Note, error) {
	oDir, err := os.Getwd()
	if err != nil {
		t.Fatalf("Could not get the current directory: %v", err)
	}

	if err := os.Chdir(*ctx.RepoRoot); err != nil {
		t.Fatalf("Could not change into test directory %s: %v", ctx.RepoRoot, err)
	}

	defer os.Chdir(oDir)

	return a.Analyze(ctx)
}

// ChangeIntoTestDir changes into test directory and returns the original.
// Note: make sure to call defer os.Chdir(original) after using this!
func ChangeIntoTestDir(testDir string) (string, error) {
	oDir, err := os.Getwd()
	if err != nil {
		return "", err
	}
	if err = os.Chdir(testDir); err != nil {
		return "", err
	}
	return oDir, nil
}

// CheckNoteContainsContent checks that there is a 1:1 mapping from expected
// notes to actual notes. The description in the execpted note needs only to be
// a substring of the actual note. Returns whether such a 1:1 mapping exists,
// and if not, a message to print to the tests of the unmatched results
func CheckNoteContainsContent(expected []*notepb.Note, actual []*notepb.Note) (bool, string) {
	var unmatched []*notepb.Note
	remaining := append([]*notepb.Note{}, actual...)
	var found bool

	for _, expect := range expected {
		found = false
		for i, act := range remaining {
			if Match(expect, act) {
				remaining = append(remaining[:i], remaining[i+1:]...)
				found = true
				break
			}
		}
		if !found {
			unmatched = append(unmatched, expect)
		}
	}
	if len(unmatched) == 0 && len(remaining) == 0 {
		return true, ""
	}
	return false, fmt.Sprintf("Had unmatched results.\nExpect: %v\nActual: %v", unmatched, remaining)
}

// CheckFailureContainsContent checks that there is a 1:1 mapping from expected
// failures to actual faulres. The description in the execpted failure needs
// only to be a substring of the actual failure. Returns whether such a 1:1
// mapping exists, and if not, a message to print to the tests of the unmatched
// results
func CheckFailureContainsContent(expected []*rpcpb.AnalysisFailure, actual []*rpcpb.AnalysisFailure) (bool, string) {
	var unmatched []*rpcpb.AnalysisFailure
	remaining := append([]*rpcpb.AnalysisFailure{}, actual...)
	var found bool

	for _, expect := range expected {
		found = false
		for i, act := range remaining {
			if MatchFailure(expect, act) {
				remaining = append(remaining[:i], remaining[i+1:]...)
				found = true
				break
			}
		}
		if !found {
			unmatched = append(unmatched, expect)
		}
	}
	if len(unmatched) == 0 && len(remaining) == 0 {
		return true, ""
	}
	return false, fmt.Sprintf("Had unmatched results.\nExpect: %v\nActual: %v", unmatched, remaining)
}

// Match determines whether the actual note matches our expected note.
// It requires that the category, subcategory, and location.path be the same, and
// it requires that the actual description contain the expected description (to make
// tests easier to write, the actual description is allowed to have more text.
// Other fields are not checked.
func Match(expect *notepb.Note, actual *notepb.Note) bool {
	// Check that the category matches what we expect.
	// Can't send nil into Category at all.
	if actual.Category == nil || *expect.Category != *actual.Category {
		return false
	}

	// Check that the subcategory matches what we expect
	if expect.Subcategory == nil && actual.Subcategory != nil {
		return false
	}
	if expect.Subcategory != nil && (actual.Subcategory == nil || *expect.Subcategory != *actual.Subcategory) {
		return false
	}

	// If we want to check location, go ahead and check it.
	// If expect.Location is nil, let any location be allowed.
	if expect.Location != nil {
		if actual.Location == nil {
			return false
		}
		if expect.Location.Path != nil && *expect.Location.Path != *actual.Location.Path {
			return false
		}
	}
	// TODO(ciera): Add other checks for the proto, like the location check above.

	return strings.Contains(*actual.Description, *expect.Description)
}

// MatchFailure determines whether the actual failure matches our expected failure.
// It requires that the category be the same, and
// it requires that the actual description contain the expected description (to make
// tests easier to write, the actual description is allowed to have more text.
func MatchFailure(expect *rpcpb.AnalysisFailure, actual *rpcpb.AnalysisFailure) bool {
	// Check that the category matches what we expect.
	// Can't send nil into Category at all.
	if actual.Category == nil || *expect.Category != *actual.Category {
		return false
	}

	return strings.Contains(*actual.FailureMessage, *expect.FailureMessage)
}

func CreatekRPCTestServer(dispatcher interface{}, name string) (string, func(), error) {
	kRPCServer := server.Service{Name: name}
	if err := kRPCServer.Register(dispatcher); err != nil {
		return "", nil, err
	}
	testServer := httptest.NewServer(server.Endpoint{&kRPCServer})
	cleanup := func() {
		testServer.CloseClientConnections()
		testServer.Close()
	}

	return testServer.URL, cleanup, nil
}
<commit_msg>Fix an unreadable error message<commit_after>/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package test

import (
	"fmt"
	"net/http/httptest"
	"os"
	"strings"
	"testing"

	"shipshape/util/rpc/server"

	"github.com/golang/protobuf/proto"

	notepb "shipshape/proto/note_proto"
	ctxpb "shipshape/proto/shipshape_context_proto"
	rpcpb "shipshape/proto/shipshape_rpc_proto"
)

type Analyzer interface {
	Analyze(*ctxpb.ShipshapeContext) ([]*notepb.Note, error)
}

// CreateContext returns a new Shipshape test context
func CreateContext(testDir string, filepaths []string) (*ctxpb.ShipshapeContext, error) {
	context := &ctxpb.ShipshapeContext{
		FilePath: filepaths,
		RepoRoot: proto.String(testDir),
	}
	return context, nil
}

func CreateLocation(path string) *notepb.Location {
	return &notepb.Location{
		Path: proto.String(path),
	}
}

// RunAnalyzer does any preparation for running the analyzer, and runs
// it. Errors from setup/teardown will cause the test t to stop. Errors from the
// analysis will be returned, along with the notes
func RunAnalyzer(ctx *ctxpb.ShipshapeContext, a Analyzer, t *testing.T) ([]*notepb.Note, error) {
	oDir, err := os.Getwd()
	if err != nil {
		t.Fatalf("Could not get the current directory: %v", err)
	}

	if err := os.Chdir(*ctx.RepoRoot); err != nil {
		t.Fatalf("Could not change into test directory %s: %v", ctx.GetRepoRoot(), err)
	}

	defer os.Chdir(oDir)

	return a.Analyze(ctx)
}

// ChangeIntoTestDir changes into test directory and returns the original.
// Note: make sure to call defer os.Chdir(original) after using this!
func ChangeIntoTestDir(testDir string) (string, error) {
	oDir, err := os.Getwd()
	if err != nil {
		return "", err
	}
	if err = os.Chdir(testDir); err != nil {
		return "", err
	}
	return oDir, nil
}

// CheckNoteContainsContent checks that there is a 1:1 mapping from expected
// notes to actual notes. The description in the execpted note needs only to be
// a substring of the actual note. Returns whether such a 1:1 mapping exists,
// and if not, a message to print to the tests of the unmatched results
func CheckNoteContainsContent(expected []*notepb.Note, actual []*notepb.Note) (bool, string) {
	var unmatched []*notepb.Note
	remaining := append([]*notepb.Note{}, actual...)
	var found bool

	for _, expect := range expected {
		found = false
		for i, act := range remaining {
			if Match(expect, act) {
				remaining = append(remaining[:i], remaining[i+1:]...)
				found = true
				break
			}
		}
		if !found {
			unmatched = append(unmatched, expect)
		}
	}
	if len(unmatched) == 0 && len(remaining) == 0 {
		return true, ""
	}
	return false, fmt.Sprintf("Had unmatched results.\nExpect: %v\nActual: %v", unmatched, remaining)
}

// CheckFailureContainsContent checks that there is a 1:1 mapping from expected
// failures to actual faulres. The description in the execpted failure needs
// only to be a substring of the actual failure. Returns whether such a 1:1
// mapping exists, and if not, a message to print to the tests of the unmatched
// results
func CheckFailureContainsContent(expected []*rpcpb.AnalysisFailure, actual []*rpcpb.AnalysisFailure) (bool, string) {
	var unmatched []*rpcpb.AnalysisFailure
	remaining := append([]*rpcpb.AnalysisFailure{}, actual...)
	var found bool

	for _, expect := range expected {
		found = false
		for i, act := range remaining {
			if MatchFailure(expect, act) {
				remaining = append(remaining[:i], remaining[i+1:]...)
				found = true
				break
			}
		}
		if !found {
			unmatched = append(unmatched, expect)
		}
	}
	if len(unmatched) == 0 && len(remaining) == 0 {
		return true, ""
	}
	return false, fmt.Sprintf("Had unmatched results.\nExpect: %v\nActual: %v", unmatched, remaining)
}

// Match determines whether the actual note matches our expected note.
// It requires that the category, subcategory, and location.path be the same, and
// it requires that the actual description contain the expected description (to make
// tests easier to write, the actual description is allowed to have more text.
// Other fields are not checked.
func Match(expect *notepb.Note, actual *notepb.Note) bool {
	// Check that the category matches what we expect.
	// Can't send nil into Category at all.
	if actual.Category == nil || *expect.Category != *actual.Category {
		return false
	}

	// Check that the subcategory matches what we expect
	if expect.Subcategory == nil && actual.Subcategory != nil {
		return false
	}
	if expect.Subcategory != nil && (actual.Subcategory == nil || *expect.Subcategory != *actual.Subcategory) {
		return false
	}

	// If we want to check location, go ahead and check it.
	// If expect.Location is nil, let any location be allowed.
	if expect.Location != nil {
		if actual.Location == nil {
			return false
		}
		if expect.Location.Path != nil && *expect.Location.Path != *actual.Location.Path {
			return false
		}
	}
	// TODO(ciera): Add other checks for the proto, like the location check above.

	return strings.Contains(*actual.Description, *expect.Description)
}

// MatchFailure determines whether the actual failure matches our expected failure.
// It requires that the category be the same, and
// it requires that the actual description contain the expected description (to make
// tests easier to write, the actual description is allowed to have more text.
func MatchFailure(expect *rpcpb.AnalysisFailure, actual *rpcpb.AnalysisFailure) bool {
	// Check that the category matches what we expect.
	// Can't send nil into Category at all.
	if actual.Category == nil || *expect.Category != *actual.Category {
		return false
	}

	return strings.Contains(*actual.FailureMessage, *expect.FailureMessage)
}

func CreatekRPCTestServer(dispatcher interface{}, name string) (string, func(), error) {
	kRPCServer := server.Service{Name: name}
	if err := kRPCServer.Register(dispatcher); err != nil {
		return "", nil, err
	}
	testServer := httptest.NewServer(server.Endpoint{&kRPCServer})
	cleanup := func() {
		testServer.CloseClientConnections()
		testServer.Close()
	}

	return testServer.URL, cleanup, nil
}
<|endoftext|>


<commit_before>package spec

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

	"github.com/summerwind/h2spec/config"
	"github.com/summerwind/h2spec/log"
)

var (
	// ErrTimeout is used when the test times out.
	ErrTimeout = errors.New("Timeout")
	// ErrSkipped is used when the test skipped.
	ErrSkipped = errors.New("Skipped")
)

// TestGroup represents a group of test case.
type TestGroup struct {
	Key         string
	Section     string
	Name        string
	Strict      bool
	Parent      *TestGroup
	Groups      []*TestGroup
	Tests       []*TestCase
	StrictTests []*TestCase

	PassedCount  int
	FailedCount  int
	SkippedCount int
}

// IsRoot returns bool as to whether it is the parent of all groups.
func (tg *TestGroup) IsRoot() bool {
	return tg.Parent == nil
}

// ID returns the unique ID of this group.
func (tg *TestGroup) ID() string {
	if tg.IsRoot() {
		return tg.Key
	}

	return fmt.Sprintf("%s/%s", tg.Key, tg.Section)
}

// Title returns the title of this group.
func (tg *TestGroup) Title() string {
	if tg.IsRoot() {
		return fmt.Sprintf("%s", tg.Name)
	} else {
		return fmt.Sprintf("%s. %s", tg.Section, tg.Name)
	}
}

// Level returns a number. Level is determined by Key and the number
// of "." included in Section.
func (tg *TestGroup) Level() int {
	if tg.IsRoot() {
		return 0
	}

	return strings.Count(tg.Section, ".") + 1
}

// Test runs all the tests included in this group.
func (tg *TestGroup) Test(c *config.Config) {
	level := tg.Level()

	if tg.Strict && !c.Strict {
		return
	}

	mode := c.RunMode(tg.ID())
	if mode == config.RunModeNone {
		return
	}

	log.SetIndentLevel(level)
	log.Println(tg.Title())
	log.SetIndentLevel(level + 1)

	tests := append(tg.Tests, tg.StrictTests...)
	tested := false

	for i, tc := range tests {
		seq := i + 1

		err := tc.Test(c, seq)
		if err != nil {
			fmt.Printf("\nError: %v\n", err)
			os.Exit(1)
		}

		if tc.Result != nil {
			if tc.Result.Failed {
				tg.FailedCount += 1
			} else if tc.Result.Skipped {
				tg.SkippedCount += 1
			} else {
				tg.PassedCount += 1
			}

			tested = true
		}
	}

	if tested {
		log.PrintBlankLine()
	}

	for _, g := range tg.Groups {
		g.Test(c)
		tg.FailedCount += g.FailedCount
		tg.SkippedCount += g.SkippedCount
		tg.PassedCount += g.PassedCount
	}
}

// AddTestGroup registers a group to this group.
func (tg *TestGroup) AddTestGroup(stg *TestGroup) {
	stg.Parent = tg
	if tg.Strict {
		stg.Strict = true
	}
	tg.Groups = append(tg.Groups, stg)
}

// AddTestCase registers a test to this group.
func (tg *TestGroup) AddTestCase(tc *TestCase) {
	tc.Parent = tg
	if tg.Strict {
		tc.Strict = true
		tg.StrictTests = append(tg.StrictTests, tc)
	} else {
		tg.Tests = append(tg.Tests, tc)
	}
}

// TestCase represents a test case.
type TestCase struct {
	Desc        string
	Requirement string
	Strict      bool
	Parent      *TestGroup
	Result      *TestResult
	Run         func(c *config.Config, conn *Conn) error
}

// Test runs itself as a test case.
func (tc *TestCase) Test(c *config.Config, seq int) error {
	if tc.Strict && !c.Strict {
		return nil
	}

	mode := c.RunMode(fmt.Sprintf("%s/%d", tc.Parent.ID(), seq))
	if mode == config.RunModeNone {
		return nil
	}

	if c.DryRun {
		msg := fmt.Sprintf("%s %s", seqStr(seq), tc.Desc)
		log.Println(msg)
		tc.Result = NewTestResult(tc, seq, nil, time.Duration(0), nil)
		return nil
	}

	if !c.Verbose {
		msg := gray(fmt.Sprintf("  %s %s", seqStr(seq), tc.Desc))
		log.Print(msg)
	}

	conn, err := Dial(c)
	if err != nil {
		msg := red(fmt.Sprintf("%s %s %s", "×", seqStr(seq), tc.Desc))
		log.ResetLine()
		log.Println(msg)
		return err
	}
	defer conn.Close()

	start := time.Now()
	err = tc.Run(c, conn)
	end := time.Now()

	log.ResetLine()

	tr := NewTestResult(tc, seq, err, end.Sub(start), conn.LocalAddr())
	tr.Print()
	tc.Result = tr

	return nil
}

// TestError represents a error result of test case and implements
// type error.
type TestError struct {
	Expected []string
	Actual   string
}

// Error returns a string containing the reason of the error.
func (e TestError) Error() string {
	return fmt.Sprintf("%s\n%s", strings.Join(e.Expected, "\n"), e.Actual)
}

// TestResult represents a result of test case.
type TestResult struct {
	TestCase   *TestCase
	Sequence   int
	Error      error
	Duration   time.Duration
	SourceAddr net.Addr

	Skipped bool
	Failed  bool
}

// NewTestResult returns a TestResult.
func NewTestResult(tc *TestCase, seq int, err error, d time.Duration, addr net.Addr) *TestResult {
	skipped := false
	failed := false

	if err != nil {
		if err == ErrSkipped {
			skipped = true
		} else {
			failed = true
		}
	}

	tr := TestResult{
		TestCase:   tc,
		Sequence:   seq,
		Error:      err,
		Duration:   d,
		SourceAddr: addr,
		Skipped:    skipped,
		Failed:     failed,
	}

	return &tr
}

// Print prints the result of test case.
func (tr *TestResult) Print() {
	tc := tr.TestCase
	desc := tc.Desc
	seq := seqStr(tr.Sequence)

	if tr.Skipped {
		log.Println(cyan(fmt.Sprintf("%s %s", seq, desc)))
		return
	}

	if !tr.Failed {
		log.Println(fmt.Sprintf("%s %s %s", green("✔"), gray(seq), gray(desc)))
		return
	}

	log.Println(red(fmt.Sprintf("using source address %s", tr.SourceAddr)))
	log.Println(red(fmt.Sprintf("%s %s %s", "×", seq, desc)))
	err, ok := tr.Error.(*TestError)
	if ok {
		level := log.IndentLevel
		log.SetIndentLevel(level + 1)
		defer func() {
			log.SetIndentLevel(level)
		}()

		log.Println(red(fmt.Sprintf("-> %s", tc.Requirement)))
		label := "Expected: "
		for i, ex := range err.Expected {
			if i != 0 {
				label = strings.Repeat(" ", len(label))
			}
			log.Println(yellow(fmt.Sprintf("   %s%s", label, ex)))
		}
		log.Println(green(fmt.Sprintf("     Actual: %s", err.Actual)))

		return
	}
	if err == nil {
		log.Println(red(fmt.Sprintf("Error: %v", tr.Error.Error())))
	} else {
		log.Println(red(fmt.Sprintf("Error: %v", err)))
	}
}

func seqStr(seq int) string {
	return fmt.Sprintf("%d:", seq)
}
<commit_msg>Move source address log to verbose output<commit_after>package spec

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

	"github.com/summerwind/h2spec/config"
	"github.com/summerwind/h2spec/log"
)

var (
	// ErrTimeout is used when the test times out.
	ErrTimeout = errors.New("Timeout")
	// ErrSkipped is used when the test skipped.
	ErrSkipped = errors.New("Skipped")
)

// TestGroup represents a group of test case.
type TestGroup struct {
	Key         string
	Section     string
	Name        string
	Strict      bool
	Parent      *TestGroup
	Groups      []*TestGroup
	Tests       []*TestCase
	StrictTests []*TestCase

	PassedCount  int
	FailedCount  int
	SkippedCount int
}

// IsRoot returns bool as to whether it is the parent of all groups.
func (tg *TestGroup) IsRoot() bool {
	return tg.Parent == nil
}

// ID returns the unique ID of this group.
func (tg *TestGroup) ID() string {
	if tg.IsRoot() {
		return tg.Key
	}

	return fmt.Sprintf("%s/%s", tg.Key, tg.Section)
}

// Title returns the title of this group.
func (tg *TestGroup) Title() string {
	if tg.IsRoot() {
		return fmt.Sprintf("%s", tg.Name)
	} else {
		return fmt.Sprintf("%s. %s", tg.Section, tg.Name)
	}
}

// Level returns a number. Level is determined by Key and the number
// of "." included in Section.
func (tg *TestGroup) Level() int {
	if tg.IsRoot() {
		return 0
	}

	return strings.Count(tg.Section, ".") + 1
}

// Test runs all the tests included in this group.
func (tg *TestGroup) Test(c *config.Config) {
	level := tg.Level()

	if tg.Strict && !c.Strict {
		return
	}

	mode := c.RunMode(tg.ID())
	if mode == config.RunModeNone {
		return
	}

	log.SetIndentLevel(level)
	log.Println(tg.Title())
	log.SetIndentLevel(level + 1)

	tests := append(tg.Tests, tg.StrictTests...)
	tested := false

	for i, tc := range tests {
		seq := i + 1

		err := tc.Test(c, seq)
		if err != nil {
			fmt.Printf("\nError: %v\n", err)
			os.Exit(1)
		}

		if tc.Result != nil {
			if tc.Result.Failed {
				tg.FailedCount += 1
			} else if tc.Result.Skipped {
				tg.SkippedCount += 1
			} else {
				tg.PassedCount += 1
			}

			tested = true
		}
	}

	if tested {
		log.PrintBlankLine()
	}

	for _, g := range tg.Groups {
		g.Test(c)
		tg.FailedCount += g.FailedCount
		tg.SkippedCount += g.SkippedCount
		tg.PassedCount += g.PassedCount
	}
}

// AddTestGroup registers a group to this group.
func (tg *TestGroup) AddTestGroup(stg *TestGroup) {
	stg.Parent = tg
	if tg.Strict {
		stg.Strict = true
	}
	tg.Groups = append(tg.Groups, stg)
}

// AddTestCase registers a test to this group.
func (tg *TestGroup) AddTestCase(tc *TestCase) {
	tc.Parent = tg
	if tg.Strict {
		tc.Strict = true
		tg.StrictTests = append(tg.StrictTests, tc)
	} else {
		tg.Tests = append(tg.Tests, tc)
	}
}

// TestCase represents a test case.
type TestCase struct {
	Desc        string
	Requirement string
	Strict      bool
	Parent      *TestGroup
	Result      *TestResult
	Run         func(c *config.Config, conn *Conn) error
}

// Test runs itself as a test case.
func (tc *TestCase) Test(c *config.Config, seq int) error {
	if tc.Strict && !c.Strict {
		return nil
	}

	mode := c.RunMode(fmt.Sprintf("%s/%d", tc.Parent.ID(), seq))
	if mode == config.RunModeNone {
		return nil
	}

	if c.DryRun {
		msg := fmt.Sprintf("%s %s", seqStr(seq), tc.Desc)
		log.Println(msg)
		tc.Result = NewTestResult(tc, seq, nil, time.Duration(0), nil)
		return nil
	}

	if !c.Verbose {
		log.Print(gray(fmt.Sprintf("  %s %s", seqStr(seq), tc.Desc)))
	}

	conn, err := Dial(c)
	if err != nil {
		msg := red(fmt.Sprintf("%s %s %s", "×", seqStr(seq), tc.Desc))
		log.ResetLine()
		log.Println(msg)
		return err
	}
	defer conn.Close()

	if c.Verbose {
		log.Println(gray(fmt.Sprintf("     source address: %s", conn.LocalAddr())))
	}

	start := time.Now()
	err = tc.Run(c, conn)
	end := time.Now()

	log.ResetLine()

	tr := NewTestResult(tc, seq, err, end.Sub(start), conn.LocalAddr())
	tr.Print()
	tc.Result = tr

	return nil
}

// TestError represents a error result of test case and implements
// type error.
type TestError struct {
	Expected []string
	Actual   string
}

// Error returns a string containing the reason of the error.
func (e TestError) Error() string {
	return fmt.Sprintf("%s\n%s", strings.Join(e.Expected, "\n"), e.Actual)
}

// TestResult represents a result of test case.
type TestResult struct {
	TestCase   *TestCase
	Sequence   int
	Error      error
	Duration   time.Duration
	SourceAddr net.Addr

	Skipped bool
	Failed  bool
}

// NewTestResult returns a TestResult.
func NewTestResult(tc *TestCase, seq int, err error, d time.Duration, addr net.Addr) *TestResult {
	skipped := false
	failed := false

	if err != nil {
		if err == ErrSkipped {
			skipped = true
		} else {
			failed = true
		}
	}

	tr := TestResult{
		TestCase:   tc,
		Sequence:   seq,
		Error:      err,
		Duration:   d,
		SourceAddr: addr,
		Skipped:    skipped,
		Failed:     failed,
	}

	return &tr
}

// Print prints the result of test case.
func (tr *TestResult) Print() {
	tc := tr.TestCase
	desc := tc.Desc
	seq := seqStr(tr.Sequence)

	if tr.Skipped {
		log.Println(cyan(fmt.Sprintf("%s %s", seq, desc)))
		return
	}

	if !tr.Failed {
		log.Println(fmt.Sprintf("%s %s %s", green("✔"), gray(seq), gray(desc)))
		return
	}

	log.Println(red(fmt.Sprintf("%s %s %s", "×", seq, desc)))
	err, ok := tr.Error.(*TestError)
	if ok {
		level := log.IndentLevel
		log.SetIndentLevel(level + 1)
		defer func() {
			log.SetIndentLevel(level)
		}()

		log.Println(red(fmt.Sprintf("-> %s", tc.Requirement)))
		label := "Expected: "
		for i, ex := range err.Expected {
			if i != 0 {
				label = strings.Repeat(" ", len(label))
			}
			log.Println(yellow(fmt.Sprintf("   %s%s", label, ex)))
		}
		log.Println(green(fmt.Sprintf("     Actual: %s", err.Actual)))

		return
	}
	if err == nil {
		log.Println(red(fmt.Sprintf("Error: %v", tr.Error.Error())))
	} else {
		log.Println(red(fmt.Sprintf("Error: %v", err)))
	}
}

func seqStr(seq int) string {
	return fmt.Sprintf("%d:", seq)
}
<|endoftext|>


<commit_before>// Package hyperloglog implements the HyperLogLog algorithm for
// cardinality estimation. In English: it counts things. It counts
// things using very small amounts of memory compared to the number of
// objects it is counting.
//
// For a full description of the algorithm, see the paper HyperLogLog:
// the analysis of a near-optimal cardinality estimation algorithm by
// Flajolet, et. al.
package hyperloglog

import (
	"fmt"
	"math"
)

var (
	exp32 = math.Pow(2, 32)
)

// A HyperLogLog is a deterministic cardinality estimator.  This version
// exports its fields so that it is suitable for saving eg. to a database.
type HyperLogLog struct {
	M         uint    // Number of registers
	B         uint32  // Number of bits used to determine register index
	Alpha     float64 // Bias correction constant
	Registers []uint8
}

// Compute bias correction alpha_m.
func getAlpha(m uint) (result float64) {
	switch m {
	case 16:
		result = 0.673
	case 32:
		result = 0.697
	case 64:
		result = 0.709
	default:
		result = 0.7213 / (1.0 + 1.079/float64(m))
	}
	return result
}

// New creates a HyperLogLog with the given number of registers. More
// registers leads to lower error in your estimated count, at the
// expense of memory.
//
// Choose a power of two number of registers, depending on the amount
// of memory you're willing to use and the error you're willing to
// tolerate. Each register uses one byte of memory.
//
// Standard error will be: σ ≈ 1.04 / sqrt(registers)
// The estimates provided by hyperloglog are expected to be within σ, 2σ, 3σ
// of the exact count in respectively 65%, 95%, 99% of all the cases.
func New(registers uint) (*HyperLogLog, error) {
	if (registers & (registers - 1)) != 0 {
		return nil, fmt.Errorf("number of registers %d not a power of two", registers)
	}
	h := &HyperLogLog{}
	h.M = registers
	h.B = uint32(math.Ceil(math.Log2(float64(registers))))
	h.Alpha = getAlpha(registers)
	h.Reset()
	return h, nil
}

// Reset all internal variables and set the count to zero.
func (h *HyperLogLog) Reset() {
	for i := range h.Registers {
		h.Registers[i] = 0
	}
}

// Calculate the position of the leftmost 1-bit.
func rho(val uint32, max uint32) uint8 {
	r := uint32(1)
	for val&0x80000000 == 0 && r <= max {
		r++
		val <<= 1
	}
	return uint8(r)
}

// Add to the count. val should be a 32 bit unsigned integer from a
// good hash function.
func (h *HyperLogLog) Add(val uint32) {
	k := 32 - h.B
	r := rho(val<<h.B, k)
	j := val >> uint(k)
	if r > h.Registers[j] {
		h.Registers[j] = r
	}
}

// Count returns the estimated cardinality.
func (h *HyperLogLog) Count() uint64 {
	sum := 0.0
	m := float64(h.M)
	for _, val := range h.Registers {
		sum += 1.0 / math.Pow(2.0, float64(val))
	}
	estimate := h.Alpha * m * m / sum
	if estimate <= 5.0/2.0*m {
		// Small range correction
		v := 0
		for _, r := range h.Registers {
			if r == 0 {
				v++
			}
		}
		if v > 0 {
			estimate = m * math.Log(m/float64(v))
		}
	} else if estimate > 1.0/30.0*exp32 {
		// Large range correction
		estimate = -exp32 * math.Log(1-estimate/exp32)
	}
	return uint64(estimate)
}

// Merge another HyperLogLog into this one. The number of registers in
// each must be the same.
func (h *HyperLogLog) Merge(other *HyperLogLog) error {
	if h.M != other.M {
		return fmt.Errorf("number of registers doesn't match: %d != %d",
			h.M, other.M)
	}
	for j, r := range other.Registers {
		if r > h.Registers[j] {
			h.Registers[j] = r
		}
	}
	return nil
}
<commit_msg>Initialize registers in new function<commit_after>// Package hyperloglog implements the HyperLogLog algorithm for
// cardinality estimation. In English: it counts things. It counts
// things using very small amounts of memory compared to the number of
// objects it is counting.
//
// For a full description of the algorithm, see the paper HyperLogLog:
// the analysis of a near-optimal cardinality estimation algorithm by
// Flajolet, et. al.
package hyperloglog

import (
	"fmt"
	"math"
)

var (
	exp32 = math.Pow(2, 32)
)

// A HyperLogLog is a deterministic cardinality estimator.  This version
// exports its fields so that it is suitable for saving eg. to a database.
type HyperLogLog struct {
	M         uint    // Number of registers
	B         uint32  // Number of bits used to determine register index
	Alpha     float64 // Bias correction constant
	Registers []uint8
}

// Compute bias correction alpha_m.
func getAlpha(m uint) (result float64) {
	switch m {
	case 16:
		result = 0.673
	case 32:
		result = 0.697
	case 64:
		result = 0.709
	default:
		result = 0.7213 / (1.0 + 1.079/float64(m))
	}
	return result
}

// New creates a HyperLogLog with the given number of registers. More
// registers leads to lower error in your estimated count, at the
// expense of memory.
//
// Choose a power of two number of registers, depending on the amount
// of memory you're willing to use and the error you're willing to
// tolerate. Each register uses one byte of memory.
//
// Standard error will be: σ ≈ 1.04 / sqrt(registers)
// The estimates provided by hyperloglog are expected to be within σ, 2σ, 3σ
// of the exact count in respectively 65%, 95%, 99% of all the cases.
func New(registers uint) (*HyperLogLog, error) {
	if (registers & (registers - 1)) != 0 {
		return nil, fmt.Errorf("number of registers %d not a power of two", registers)
	}
	h := &HyperLogLog{}
	h.M = registers
	h.B = uint32(math.Ceil(math.Log2(float64(registers))))
	h.Alpha = getAlpha(registers)
	h.Registers = make([]uint8, h.M)
	return h, nil
}

// Reset all internal variables and set the count to zero.
func (h *HyperLogLog) Reset() {
	for i := range h.Registers {
		h.Registers[i] = 0
	}
}

// Calculate the position of the leftmost 1-bit.
func rho(val uint32, max uint32) uint8 {
	r := uint32(1)
	for val&0x80000000 == 0 && r <= max {
		r++
		val <<= 1
	}
	return uint8(r)
}

// Add to the count. val should be a 32 bit unsigned integer from a
// good hash function.
func (h *HyperLogLog) Add(val uint32) {
	k := 32 - h.B
	r := rho(val<<h.B, k)
	j := val >> uint(k)
	if r > h.Registers[j] {
		h.Registers[j] = r
	}
}

// Count returns the estimated cardinality.
func (h *HyperLogLog) Count() uint64 {
	sum := 0.0
	m := float64(h.M)
	for _, val := range h.Registers {
		sum += 1.0 / math.Pow(2.0, float64(val))
	}
	estimate := h.Alpha * m * m / sum
	if estimate <= 5.0/2.0*m {
		// Small range correction
		v := 0
		for _, r := range h.Registers {
			if r == 0 {
				v++
			}
		}
		if v > 0 {
			estimate = m * math.Log(m/float64(v))
		}
	} else if estimate > 1.0/30.0*exp32 {
		// Large range correction
		estimate = -exp32 * math.Log(1-estimate/exp32)
	}
	return uint64(estimate)
}

// Merge another HyperLogLog into this one. The number of registers in
// each must be the same.
func (h *HyperLogLog) Merge(other *HyperLogLog) error {
	if h.M != other.M {
		return fmt.Errorf("number of registers doesn't match: %d != %d",
			h.M, other.M)
	}
	for j, r := range other.Registers {
		if r > h.Registers[j] {
			h.Registers[j] = r
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package libkbfs

import (
	"io"
	"sort"

	"golang.org/x/net/context"
	"golang.org/x/sync/errgroup"
)

const (
	defaultIndirectPointerPrefetchCount int = 20
	fileIndirectBlockPrefetchPriority   int = -100
	dirEntryPrefetchPriority            int = -200
)

type prefetcher interface {
	HandleBlock(b Block, kmd KeyMetadata, priority int)
	Shutdown() <-chan struct{}
}

var _ prefetcher = (*blockPrefetcher)(nil)

type blockPrefetcher struct {
	retriever  blockRetriever
	progressCh chan (<-chan error)
	eg         errgroup.Group
}

func newPrefetcher(retriever blockRetriever) prefetcher {
	p := &blockPrefetcher{
		retriever:  retriever,
		progressCh: make(chan (<-chan error)),
	}
	go p.run()
	return p
}

func (p *blockPrefetcher) run() {
	for ch := range p.progressCh {
		ch := ch
		p.eg.Go(func() error {
			return <-ch
		})
	}
}

func (p *blockPrefetcher) request(priority int, kmd KeyMetadata, ptr BlockPointer, block Block, lifetime BlockCacheLifetime) error {
	ctx, cancel := context.WithCancel(context.Background())
	ch := p.retriever.Request(ctx, priority, kmd, ptr, block, lifetime)
	select {
	case p.progressCh <- ch:
		return nil
	default:
		cancel()
		return io.EOF
	}
}

func (p *blockPrefetcher) prefetchIndirectFileBlock(b *FileBlock, kmd KeyMetadata, priority int) {
	// prefetch the first <n> indirect block pointers.
	// TODO: do something smart with subsequent blocks.
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, b.NewEmpty(), TransientEntry)
	}
}

func (p *blockPrefetcher) prefetchIndirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		_ = p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, b.NewEmpty(), TransientEntry)
	}
}

func (p *blockPrefetcher) prefetchDirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	dirEntries := dirEntriesBySizeAsc{dirEntryMapToDirEntries(b.Children)}
	sort.Sort(dirEntries)
	for i, entry := range dirEntries.dirEntries {
		// Prioritize small files
		priority := dirEntryPrefetchPriority - i
		var block Block
		switch entry.Type {
		case Dir:
			block = NewDirBlock()
		case File:
			block = NewFileBlock()
		case Exec:
			block = NewFileBlock()
		default:
			continue
		}
		p.request(priority, kmd, entry.BlockPointer,
			block, TransientEntry)
	}
}

func (p *blockPrefetcher) HandleBlock(b Block, kmd KeyMetadata, priority int) {
	switch b := b.(type) {
	case *FileBlock:
		if b.IsInd && priority >= defaultOnDemandRequestPriority {
			p.prefetchIndirectFileBlock(b, kmd, priority)
		}
	case *DirBlock:
		// If this is an on-demand request:
		// - If the block is indirect, prefetch the first <n> indirect block
		// pointers.
		// - If the block is direct (has Children), prefetch all DirEntry root
		// blocks.
		if priority >= defaultOnDemandRequestPriority {
			if b.IsInd {
				p.prefetchIndirectDirBlock(b, kmd, priority)
			} else {
				p.prefetchDirectDirBlock(b, kmd, priority)
			}
		}
	default:
	}
}

func (p *blockPrefetcher) Shutdown() <-chan struct{} {
	close(p.progressCh)
	ch := make(chan struct{})
	go func() {
		p.eg.Wait()
		close(ch)
	}()
	return ch
}
<commit_msg>prefetcher: Add comments and use default cache lifetime of TransientEntry<commit_after>package libkbfs

import (
	"io"
	"sort"

	"golang.org/x/net/context"
	"golang.org/x/sync/errgroup"
)

const (
	defaultIndirectPointerPrefetchCount int = 20
	fileIndirectBlockPrefetchPriority   int = -100
	dirEntryPrefetchPriority            int = -200
)

type prefetcher interface {
	HandleBlock(b Block, kmd KeyMetadata, priority int)
	Shutdown() <-chan struct{}
}

var _ prefetcher = (*blockPrefetcher)(nil)

type blockPrefetcher struct {
	retriever  blockRetriever
	progressCh chan (<-chan error)
	eg         errgroup.Group
}

func newPrefetcher(retriever blockRetriever) *blockPrefetcher {
	p := &blockPrefetcher{
		retriever:  retriever,
		progressCh: make(chan (<-chan error)),
	}
	go p.run()
	return p
}

func (p *blockPrefetcher) run() {
	for ch := range p.progressCh {
		ch := ch
		p.eg.Go(func() error {
			return <-ch
		})
	}
}

func (p *blockPrefetcher) request(priority int, kmd KeyMetadata, ptr BlockPointer, block Block) error {
	ctx, cancel := context.WithCancel(context.Background())
	ch := p.retriever.Request(ctx, priority, kmd, ptr, block, TransientEntry)
	select {
	case p.progressCh <- ch:
		return nil
	// TODO: fix this so that it can't race (another channel,
	// I guess)
	default:
		cancel()
		return io.EOF
	}
}

func (p *blockPrefetcher) prefetchIndirectFileBlock(b *FileBlock, kmd KeyMetadata, priority int) {
	// Prefetch the first <n> indirect block pointers.
	// TODO: do something smart with subsequent blocks.
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, b.NewEmpty())
	}
}

func (p *blockPrefetcher) prefetchIndirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	// Prefetch the first <n> indirect block pointers.
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		_ = p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, b.NewEmpty())
	}
}

func (p *blockPrefetcher) prefetchDirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	// Prefetch all DirEntry root blocks
	dirEntries := dirEntriesBySizeAsc{dirEntryMapToDirEntries(b.Children)}
	sort.Sort(dirEntries)
	for i, entry := range dirEntries.dirEntries {
		// Prioritize small files
		priority := dirEntryPrefetchPriority - i
		var block Block
		switch entry.Type {
		case Dir:
			block = NewDirBlock()
		case File:
			block = NewFileBlock()
		case Exec:
			block = NewFileBlock()
		default:
			continue
		}
		p.request(priority, kmd, entry.BlockPointer, block)
	}
}

func (p *blockPrefetcher) HandleBlock(b Block, kmd KeyMetadata, priority int) {
	switch b := b.(type) {
	case *FileBlock:
		if b.IsInd && priority >= defaultOnDemandRequestPriority {
			p.prefetchIndirectFileBlock(b, kmd, priority)
		}
	case *DirBlock:
		// If this is an on-demand request:
		if priority >= defaultOnDemandRequestPriority {
			if b.IsInd {
				p.prefetchIndirectDirBlock(b, kmd, priority)
			} else {
				p.prefetchDirectDirBlock(b, kmd, priority)
			}
		}
	default:
	}
}

func (p *blockPrefetcher) Shutdown() <-chan struct{} {
	close(p.progressCh)
	ch := make(chan struct{})
	go func() {
		p.eg.Wait()
		close(ch)
	}()
	return ch
}
<|endoftext|>


<commit_before>package gocd

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"testing"
)

func TestAgnet_Get(t *testing.T) {

	setup()
	defer teardown()

	mux.HandleFunc("/api/agents/adb9540a-b954-4571-9d9b-2f330739d4da", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		j, _ := ioutil.ReadFile("test/resources/agent.0.json")
		fmt.Fprint(w, string(j))
	})

	agent, _, err := client.Agents.Get(context.Background(), "adb9540a-b954-4571-9d9b-2f330739d4da")
	if err != nil {
		t.Error(err)
	}

	testAgent(t, agent)

	if agent.BuildDetails == nil {
		t.Error("Expected 'build_agents'. Got 'nil'.")
	}

	if agent.BuildDetails.Links.Job.String() != "https://ci.example.com/go/tab/build/detail/up42/1/up42_stage/1/up42_job" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/tab/build/detail/up42/1/up42_stage/1/up42_job",
			agent.BuildDetails.Links.Job.String(),
		)
	}

	if agent.BuildDetails.Links.Stage.String() != "https://ci.example.com/go/pipelines/up42/1/up42_stage/1" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/pipelines/up42/1/up42_stage/1",
			agent.BuildDetails.Links.Stage.String(),
		)
	}

	if agent.BuildDetails.Links.Pipeline.String() != "https://ci.example.com/go/tab/pipeline/history/up42" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/tab/pipeline/history/up42",
			agent.BuildDetails.Links.Pipeline.String(),
		)
	}

}

func TestAgent_List(t *testing.T) {

	setup()
	defer teardown()

	mux.HandleFunc("/api/agents", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		testAuth(t, r, mockAuthorization)
		j, _ := ioutil.ReadFile("test/resources/agents.1.json")
		fmt.Fprint(w, string(j))
	})

	agents, _, err := client.Agents.List(context.Background())
	if err != nil {
		t.Error(err)
	}

	if len(agents) != 1 {
		t.Errorf("Expected '1' agents. Got '%d'", len(agents))
	}

	testAgent(t, agents[0])

}

func testAgent(t *testing.T, agent *Agent) {
	for index, test := range []struct {
		got  string
		want string
	}{
		{agent.Links.Self.String(), "https://ci.example.com/go/api/agents/adb9540a-b954-4571-9d9b-2f330739d4da"},
		{agent.Links.Doc.String(), "https://api.gocd.org/#agents" },
		{agent.Links.Find.String(), "https://ci.example.com/go/api/agents/:uuid"},
		{agent.Uuid, "adb9540a-b954-4571-9d9b-2f330739d4da"},
		{agent.Hostname, "agent01.example.com"},
		{agent.IpAddress, "10.12.20.47"},
		{agent.Sandbox, "/Users/ketanpadegaonkar/projects/gocd/gocd/agent"},
		{agent.OperatingSystem, "Mac OS X" },
		{agent.AgentConfigState, "Enabled"},
		{agent.AgentState, "Idle"},
		{agent.Resources[0], "java"},
		{agent.Resources[1], "linux"},
		{agent.Resources[2], "firefox"},
		{agent.Environments[0], "perf"},
		{agent.Environments[1], "UAT"},
		{agent.BuildState, "Idle"},

	} {
		if test.got != test.want {
			t.Errorf("Expected '%s'. Got '%s' in '%d'", test.want, test.got, index)
		}
	}

	if agent.FreeSpace != 84983328768 {
		t.Errorf("Expected '84983328768'. Got '%d'.", agent.FreeSpace)
	}

}
<commit_msg>Autocommit for 'gofmt -w'.<commit_after>package gocd

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"testing"
)

func TestAgnet_Get(t *testing.T) {

	setup()
	defer teardown()

	mux.HandleFunc("/api/agents/adb9540a-b954-4571-9d9b-2f330739d4da", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		j, _ := ioutil.ReadFile("test/resources/agent.0.json")
		fmt.Fprint(w, string(j))
	})

	agent, _, err := client.Agents.Get(context.Background(), "adb9540a-b954-4571-9d9b-2f330739d4da")
	if err != nil {
		t.Error(err)
	}

	testAgent(t, agent)

	if agent.BuildDetails == nil {
		t.Error("Expected 'build_agents'. Got 'nil'.")
	}

	if agent.BuildDetails.Links.Job.String() != "https://ci.example.com/go/tab/build/detail/up42/1/up42_stage/1/up42_job" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/tab/build/detail/up42/1/up42_stage/1/up42_job",
			agent.BuildDetails.Links.Job.String(),
		)
	}

	if agent.BuildDetails.Links.Stage.String() != "https://ci.example.com/go/pipelines/up42/1/up42_stage/1" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/pipelines/up42/1/up42_stage/1",
			agent.BuildDetails.Links.Stage.String(),
		)
	}

	if agent.BuildDetails.Links.Pipeline.String() != "https://ci.example.com/go/tab/pipeline/history/up42" {
		t.Errorf(
			"Expected '%s'. Got '%s'",
			"https://ci.example.com/go/tab/pipeline/history/up42",
			agent.BuildDetails.Links.Pipeline.String(),
		)
	}

}

func TestAgent_List(t *testing.T) {

	setup()
	defer teardown()

	mux.HandleFunc("/api/agents", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, "GET")
		testAuth(t, r, mockAuthorization)
		j, _ := ioutil.ReadFile("test/resources/agents.1.json")
		fmt.Fprint(w, string(j))
	})

	agents, _, err := client.Agents.List(context.Background())
	if err != nil {
		t.Error(err)
	}

	if len(agents) != 1 {
		t.Errorf("Expected '1' agents. Got '%d'", len(agents))
	}

	testAgent(t, agents[0])

}

func testAgent(t *testing.T, agent *Agent) {
	for index, test := range []struct {
		got  string
		want string
	}{
		{agent.Links.Self.String(), "https://ci.example.com/go/api/agents/adb9540a-b954-4571-9d9b-2f330739d4da"},
		{agent.Links.Doc.String(), "https://api.gocd.org/#agents"},
		{agent.Links.Find.String(), "https://ci.example.com/go/api/agents/:uuid"},
		{agent.Uuid, "adb9540a-b954-4571-9d9b-2f330739d4da"},
		{agent.Hostname, "agent01.example.com"},
		{agent.IpAddress, "10.12.20.47"},
		{agent.Sandbox, "/Users/ketanpadegaonkar/projects/gocd/gocd/agent"},
		{agent.OperatingSystem, "Mac OS X"},
		{agent.AgentConfigState, "Enabled"},
		{agent.AgentState, "Idle"},
		{agent.Resources[0], "java"},
		{agent.Resources[1], "linux"},
		{agent.Resources[2], "firefox"},
		{agent.Environments[0], "perf"},
		{agent.Environments[1], "UAT"},
		{agent.BuildState, "Idle"},
	} {
		if test.got != test.want {
			t.Errorf("Expected '%s'. Got '%s' in '%d'", test.want, test.got, index)
		}
	}

	if agent.FreeSpace != 84983328768 {
		t.Errorf("Expected '84983328768'. Got '%d'.", agent.FreeSpace)
	}

}
<|endoftext|>


<commit_before>package health

import (
	"encoding/json"
	"github.com/Comcast/webpa-common/logging"
	"net/http"
	"net/http/httptest"
	"os"
	"reflect"
	"runtime"
	"sync"
	"testing"
	"time"
)

func setupHealth() *Health {
	h := new(Health)
	h.event = make(chan HealthFunc, 100)
	h.stats = make(Stats)
	h.statDumpInterval = time.Duration(69) * time.Second

	h.log = logging.DefaultLogger{os.Stdout}
	h.wg = &sync.WaitGroup{}
	h.osChecker = testOsChecker{"testOS"}

	h.monitor()
	time.Sleep(time.Duration(1) * time.Second)

	h.commonStats()
	time.Sleep(time.Duration(1) * time.Second)

	return h
}

func setupStats() Stats {
	result := make(Stats)
	result[CurrentMemoryUtilizationActive] = 0
	result[CurrentMemoryUtilizationAlloc] = 0
	result[CurrentMemoryUtilizationHeapSys] = 0
	result[MaxMemoryUtilizationActive] = 0
	result[MaxMemoryUtilizationAlloc] = 0
	result[MaxMemoryUtilizationHeapSys] = 0

	return result
}

func TestAddStatsListener(t *testing.T) {
	h := setupHealth()
	noOfListenersAtStart := len(h.statsListeners)

	h.AddStatsListener(*new(StatsListener))

	h.SendEvent(func(stats Stats) {
		expected := noOfListenersAtStart + 1
		noOfListenersAtEnd := len(h.statsListeners)
		if noOfListenersAtEnd != expected {
			t.Errorf("Failed to correctly add stat listener: Got: %v, Expected: %v", noOfListenersAtEnd, expected)
		}
	})
}

func TestSendEvent(t *testing.T) {
	h := setupHealth()

	done := make(chan bool)
	timer := time.NewTimer(time.Second * 5)
	defer timer.Stop()

	hf := func(s Stats) {
		close(done)
	}

	h.SendEvent(hf)

	select {
	case <-done:
		// test passed
	case <-timer.C:
		// test failed
		close(done) // this might panic, but it's a test failure anyway
		t.Errorf("HealthFunc (hf) was not called")
	}
}

func TestBundle(t *testing.T) {
	done := make(chan bool)
	defer close(done)

	h := setupHealth()

	hf1 := Set("BundleTest1", 111)
	hf2 := Set("BundleTest2", 222)
	hf3 := func(s Stats) {
		done <- true
	}
	h.SendEvent(Bundle(hf1, hf2, hf3))

	select {
	case <-done:
	}

	v1, ok1 := h.stats["BundleTest1"]
	v2, ok2 := h.stats["BundleTest2"]

	if !ok1 ||
		!ok2 ||
		v1 != 111 ||
		v2 != 222 {
		t.Errorf("Bundle test failed. Got: %v, %v, %v, %v.  Expected: true, true, 111, 222", ok1, ok2, v1, v2)
	}
}

func TestInc(t *testing.T) {
	h := setupHealth()
	expected := 4

	h.SendEvent(Inc(CurrentMemoryUtilizationActive, 4))
	time.Sleep(time.Duration(1) * time.Second)

	if h.stats[CurrentMemoryUtilizationActive] != expected {
		t.Errorf("Health Set values do not match.\nGot: %v\nExpected: %v\n", h.stats[CurrentMemoryUtilizationActive], expected)
	}
}

func TestSet(t *testing.T) {
	h := setupHealth()
	expected := 62

	h.SendEvent(Set(CurrentMemoryUtilizationActive, 62))
	time.Sleep(time.Duration(1) * time.Second)

	if h.stats[CurrentMemoryUtilizationActive] != expected {
		t.Errorf("Health Set values do not match.\nGot: %v\nExpected: %v\n", h.stats[CurrentMemoryUtilizationActive], expected)
	}
}

func TestClose(t *testing.T) {
	h := setupHealth()
	h.Close()

	if _, ok := <-h.event; ok {
		t.Error("health event channel was not closed.")
	}
}

func TestNew(t *testing.T) {
	expected := setupHealth()

	dp := 69 * time.Second
	lg := logging.DefaultLogger{os.Stdout}
	wg := &sync.WaitGroup{}

	h := New(dp, lg, wg)
	h.osChecker = testOsChecker{"testOS"}

	if reflect.TypeOf(h) != reflect.TypeOf(expected) {
		t.Error("Newly created health object not correct type: Got:%v, Expected: %v", reflect.TypeOf(h), reflect.TypeOf(expected))
	}

	if h.statDumpInterval != dp {
		t.Error("Health stat dump interval not set correctly.")
	}

	if h.log != lg {
		t.Error("Health logger not set correctly")
	}
}

func TestWaitGroupDone(t *testing.T) {
	dp := 69 * time.Second
	lg := logging.DefaultLogger{os.Stdout}
	wg := &sync.WaitGroup{}

	h := New(dp, lg, wg)
	h.osChecker = testOsChecker{"testOS"}
	h.Close()

	result := make(chan bool, 1)
	defer close(result)
	wg.Wait()
	result <- true

	timer := time.AfterFunc(
		time.Second*5, // pick something reasonable
		func() {
			result <- false
		},
	)
	defer timer.Stop()

	for success := range result {
		if !success {
			t.Errorf("WaitGroup.Done() wasn't called")
		}

		break
	}
}

func TestCommonStats(t *testing.T) {
	h := new(Health)
	h.event = make(chan HealthFunc, 100)
	h.stats = make(Stats)
	h.statDumpInterval = time.Duration(69) * time.Second

	h.log = logging.DefaultLogger{os.Stdout}
	h.wg = &sync.WaitGroup{}

	h.monitor()
	time.Sleep(time.Duration(1) * time.Second)

	h.commonStats()
	time.Sleep(time.Duration(1) * time.Second)

	expected := setupStats()
	if !reflect.DeepEqual(h.stats, expected) {
		t.Errorf("common stats not setup correctly.\n Got: %v\nExpected: %v\n", h.stats, expected)
	}
}

func TestOscheck(t *testing.T) {
	h := setupHealth()
	result := h.oscheck()

	expected := false
	if runtime.GOOS == "linux" {
		expected = true
	}

	if result != expected {
		t.Error("operating system verification failed. Got: %v, Expected: %v", result, expected)
	}
}

func TestMemory(t *testing.T) {
	h := setupHealth()

	h.memory()
	if h.stats[CurrentMemoryUtilizationAlloc] != 0 ||
		h.stats[CurrentMemoryUtilizationHeapSys] != 0 ||
		h.stats[CurrentMemoryUtilizationActive] != 0 ||
		h.stats[MaxMemoryUtilizationAlloc] != 0 ||
		h.stats[MaxMemoryUtilizationHeapSys] != 0 ||
		h.stats[MaxMemoryUtilizationActive] != 0 {

		t.Error("Bad memory value found: %v", h.stats)
	}
}

func TestMonitor(t *testing.T) {
	h := setupHealth()
	h.monitor()
	h.Close()
}

func TestGetStats(t *testing.T) {
	h := setupHealth()

	expected := setupStats()

	if !reflect.DeepEqual(h.stats, expected) {
		t.Errorf("Newly created stats to not match.\n Got: %v\nExpected: %v\n", h.stats, expected)
	}
}

func setHealthTester(h *Health) {}

func TestShare(t *testing.T) {
	h := setupHealth()
	h.Share(setHealthTester)
}

func TestServeHTTP(t *testing.T) {
	h := setupHealth()
	expected := setupStats()

	req, _ := http.NewRequest("GET", "", nil)
	rw := httptest.NewRecorder()

	h.ServeHTTP(rw, req)

	if rw.Code != 200 {
		t.Error("Status code was not 200.  got: %v", rw.Code)
	}

	result := new(Stats)
	if err := json.Unmarshal(rw.Body.Bytes(), result); err != nil {
		t.Error("json Unmarshal error: %v", err)
	}

	if !reflect.DeepEqual(*result, expected) {
		t.Errorf("ServeHTTP did not return Stats.\n Got: %v\nExpected: %v\n", result, expected)
	}
}

func TestResponseErrorJson(t *testing.T) {
	rw := httptest.NewRecorder()
	err := "Expected test error message"
	code := 2222
	lg := logging.DefaultLogger{os.Stdout}

	responseErrorJson(rw, err, code, lg)

	var js map[string]string
	if json.Unmarshal(rw.Body.Bytes(), &js) != nil {
		t.Errorf("Response error is not JSON: %v", rw.Body)
	}
}
<commit_msg>removing unneeded runtime.GOOS call from TestOsCheck<commit_after>package health

import (
	"encoding/json"
	"github.com/Comcast/webpa-common/logging"
	"net/http"
	"net/http/httptest"
	"os"
	"reflect"
	"sync"
	"testing"
	"time"
)

func setupHealth() *Health {
	h := new(Health)
	h.event = make(chan HealthFunc, 100)
	h.stats = make(Stats)
	h.statDumpInterval = time.Duration(69) * time.Second

	h.log = logging.DefaultLogger{os.Stdout}
	h.wg = &sync.WaitGroup{}
	h.osChecker = testOsChecker{"testOS"}

	h.monitor()
	time.Sleep(time.Duration(1) * time.Second)

	h.commonStats()
	time.Sleep(time.Duration(1) * time.Second)

	return h
}

func setupStats() Stats {
	result := make(Stats)
	result[CurrentMemoryUtilizationActive] = 0
	result[CurrentMemoryUtilizationAlloc] = 0
	result[CurrentMemoryUtilizationHeapSys] = 0
	result[MaxMemoryUtilizationActive] = 0
	result[MaxMemoryUtilizationAlloc] = 0
	result[MaxMemoryUtilizationHeapSys] = 0

	return result
}

func TestAddStatsListener(t *testing.T) {
	h := setupHealth()
	noOfListenersAtStart := len(h.statsListeners)

	h.AddStatsListener(*new(StatsListener))

	h.SendEvent(func(stats Stats) {
		expected := noOfListenersAtStart + 1
		noOfListenersAtEnd := len(h.statsListeners)
		if noOfListenersAtEnd != expected {
			t.Errorf("Failed to correctly add stat listener: Got: %v, Expected: %v", noOfListenersAtEnd, expected)
		}
	})
}

func TestSendEvent(t *testing.T) {
	h := setupHealth()

	done := make(chan bool)
	timer := time.NewTimer(time.Second * 5)
	defer timer.Stop()

	hf := func(s Stats) {
		close(done)
	}

	h.SendEvent(hf)

	select {
	case <-done:
		// test passed
	case <-timer.C:
		// test failed
		close(done) // this might panic, but it's a test failure anyway
		t.Errorf("HealthFunc (hf) was not called")
	}
}

func TestBundle(t *testing.T) {
	done := make(chan bool)
	defer close(done)

	h := setupHealth()

	hf1 := Set("BundleTest1", 111)
	hf2 := Set("BundleTest2", 222)
	hf3 := func(s Stats) {
		done <- true
	}
	h.SendEvent(Bundle(hf1, hf2, hf3))

	select {
	case <-done:
	}

	v1, ok1 := h.stats["BundleTest1"]
	v2, ok2 := h.stats["BundleTest2"]

	if !ok1 ||
		!ok2 ||
		v1 != 111 ||
		v2 != 222 {
		t.Errorf("Bundle test failed. Got: %v, %v, %v, %v.  Expected: true, true, 111, 222", ok1, ok2, v1, v2)
	}
}

func TestInc(t *testing.T) {
	h := setupHealth()
	expected := 4

	h.SendEvent(Inc(CurrentMemoryUtilizationActive, 4))
	time.Sleep(time.Duration(1) * time.Second)

	if h.stats[CurrentMemoryUtilizationActive] != expected {
		t.Errorf("Health Set values do not match.\nGot: %v\nExpected: %v\n", h.stats[CurrentMemoryUtilizationActive], expected)
	}
}

func TestSet(t *testing.T) {
	h := setupHealth()
	expected := 62

	h.SendEvent(Set(CurrentMemoryUtilizationActive, 62))
	time.Sleep(time.Duration(1) * time.Second)

	if h.stats[CurrentMemoryUtilizationActive] != expected {
		t.Errorf("Health Set values do not match.\nGot: %v\nExpected: %v\n", h.stats[CurrentMemoryUtilizationActive], expected)
	}
}

func TestClose(t *testing.T) {
	h := setupHealth()
	h.Close()

	if _, ok := <-h.event; ok {
		t.Error("health event channel was not closed.")
	}
}

func TestNew(t *testing.T) {
	expected := setupHealth()

	dp := 69 * time.Second
	lg := logging.DefaultLogger{os.Stdout}
	wg := &sync.WaitGroup{}

	h := New(dp, lg, wg)
	h.osChecker = testOsChecker{"testOS"}

	if reflect.TypeOf(h) != reflect.TypeOf(expected) {
		t.Error("Newly created health object not correct type: Got:%v, Expected: %v", reflect.TypeOf(h), reflect.TypeOf(expected))
	}

	if h.statDumpInterval != dp {
		t.Error("Health stat dump interval not set correctly.")
	}

	if h.log != lg {
		t.Error("Health logger not set correctly")
	}
}

func TestWaitGroupDone(t *testing.T) {
	dp := 69 * time.Second
	lg := logging.DefaultLogger{os.Stdout}
	wg := &sync.WaitGroup{}

	h := New(dp, lg, wg)
	h.osChecker = testOsChecker{"testOS"}
	h.Close()

	result := make(chan bool, 1)
	defer close(result)
	wg.Wait()
	result <- true

	timer := time.AfterFunc(
		time.Second*5, // pick something reasonable
		func() {
			result <- false
		},
	)
	defer timer.Stop()

	for success := range result {
		if !success {
			t.Errorf("WaitGroup.Done() wasn't called")
		}

		break
	}
}

func TestCommonStats(t *testing.T) {
	h := new(Health)
	h.event = make(chan HealthFunc, 100)
	h.stats = make(Stats)
	h.statDumpInterval = time.Duration(69) * time.Second

	h.log = logging.DefaultLogger{os.Stdout}
	h.wg = &sync.WaitGroup{}

	h.monitor()
	time.Sleep(time.Duration(1) * time.Second)

	h.commonStats()
	time.Sleep(time.Duration(1) * time.Second)

	expected := setupStats()
	if !reflect.DeepEqual(h.stats, expected) {
		t.Errorf("common stats not setup correctly.\n Got: %v\nExpected: %v\n", h.stats, expected)
	}
}

func TestOscheck(t *testing.T) {
	h := setupHealth()
	result := h.oscheck()
	expected := false

	if result != expected {
		t.Error("operating system verification failed. Got: %v, Expected: %v", result, expected)
	}
}

func TestMemory(t *testing.T) {
	h := setupHealth()

	h.memory()
	if h.stats[CurrentMemoryUtilizationAlloc] != 0 ||
		h.stats[CurrentMemoryUtilizationHeapSys] != 0 ||
		h.stats[CurrentMemoryUtilizationActive] != 0 ||
		h.stats[MaxMemoryUtilizationAlloc] != 0 ||
		h.stats[MaxMemoryUtilizationHeapSys] != 0 ||
		h.stats[MaxMemoryUtilizationActive] != 0 {

		t.Error("Bad memory value found: %v", h.stats)
	}
}

func TestMonitor(t *testing.T) {
	h := setupHealth()
	h.monitor()
	h.Close()
}

func TestGetStats(t *testing.T) {
	h := setupHealth()

	expected := setupStats()

	if !reflect.DeepEqual(h.stats, expected) {
		t.Errorf("Newly created stats to not match.\n Got: %v\nExpected: %v\n", h.stats, expected)
	}
}

func setHealthTester(h *Health) {}

func TestShare(t *testing.T) {
	h := setupHealth()
	h.Share(setHealthTester)
}

func TestServeHTTP(t *testing.T) {
	h := setupHealth()
	expected := setupStats()

	req, _ := http.NewRequest("GET", "", nil)
	rw := httptest.NewRecorder()

	h.ServeHTTP(rw, req)

	if rw.Code != 200 {
		t.Error("Status code was not 200.  got: %v", rw.Code)
	}

	result := new(Stats)
	if err := json.Unmarshal(rw.Body.Bytes(), result); err != nil {
		t.Error("json Unmarshal error: %v", err)
	}

	if !reflect.DeepEqual(*result, expected) {
		t.Errorf("ServeHTTP did not return Stats.\n Got: %v\nExpected: %v\n", result, expected)
	}
}

func TestResponseErrorJson(t *testing.T) {
	rw := httptest.NewRecorder()
	err := "Expected test error message"
	code := 2222
	lg := logging.DefaultLogger{os.Stdout}

	responseErrorJson(rw, err, code, lg)

	var js map[string]string
	if json.Unmarshal(rw.Body.Bytes(), &js) != nil {
		t.Errorf("Response error is not JSON: %v", rw.Body)
	}
}
<|endoftext|>