<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"poliskarta/externalservices"
	"poliskarta/filterdescription"
	"poliskarta/filtertitle"
	"strconv"

	"github.com/go-martini/martini"
)

var places = map[string]string{
	"blekinge":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Blekinge/?feed=rss",
	"dalarna":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Dalarna/?feed=rss",
	"gotland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gotland/?feed=rss",
	"gavleborg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gavleborg/?feed=rss",
	"halland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Halland/?feed=rss",
	"jamtland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jamtland/?feed=rss",
	"jonkoping":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jonkoping/?feed=rss",
	"kalmar":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kalmar?feed=rss",
	"kronoberg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kronoberg?feed=rss",
	"norrbotten":     "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Norrbotten?feed=rss",
	"skane":          "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Skane?feed=rss",
	"stockholm":      "https://polisen.se/Stockholms_lan/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Stockholms-lan/?feed=rss",
	"sodermanland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Sodermanland?feed=rss",
	"uppsala":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Uppsala?feed=rss",
	"varmland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Varmland?feed=rss",
	"vasterbotten":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasterbotten?feed=rss",
	"vasternorrland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasternorrland?feed=rss",
	"vastmanland":    "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastmanland?feed=rss",
	"vastragotaland": "https://polisen.se/Vastra_Gotaland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastra-Gotaland/?feed=rss",
	"orebro":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Orebro?feed=rss",
	"ostergotland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Ostergotland?feed=rss",
}

/*
TODO:
	1. Refactor: filtermappar
	2. Felhantering: polis/mapquest = nere, errors osv

*/

func main() {
	m := martini.Classic()

	m.Group("/", func(r martini.Router) {
		r.Get(":place", allEvents)
		// r.Get(":place/(?P<number>10|[1-9])", singleEvent)
	})

	m.Run()
}

func allEvents(res http.ResponseWriter, req *http.Request, params martini.Params) {
	place, placeErr := isPlaceValid(params["place"])
	limit, limitErr := isLimitParamValid(req.FormValue("limit"))

	if placeErr != nil {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n%v", status, http.StatusText(status), placeErr.Error())
		res.Write([]byte(errorMessage))
	} else if limitErr != nil {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n%v", status, http.StatusText(status), limitErr.Error())
		res.Write([]byte(errorMessage))
	} else {
		json := callExternalServicesAndCreateJson(place, limit)
		res.Header().Add("Content-type", "application/json; charset=utf-8")

		//**********************************************
		// Detta behövs medans vi köra allt på localhost,
		// Dålig lösning som är osäker, men då kan vi
		// i alla fall testa allt enkelt
		//**********************************************
		res.Header().Add("Access-Control-Allow-Origin", "*")

		res.Write([]byte(json))
	}
}

func singleEvent(params martini.Params) string {
	return params["number"]
}

func isLimitParamValid(param string) (int, error) {
	limit := 10
	var err error
	if param != "" {
		limit, err = strconv.Atoi(param)
		if err != nil {
			err = errors.New(param + " is not a valid positive number")
		}
		if limit < 1 {
			err = errors.New(param + " is not a positive number")
		} else if limit > 50 {
			limit = 50
		}
	}

	return limit, err
}

func isPlaceValid(parameter string) (string, error) {

	for place, _ := range places {
		if place == parameter {
			return place, nil
		}
	}
	return "", errors.New(parameter + " is not a valid place")

}

func callExternalServicesAndCreateJson(place string, limit int) string {
	policeEvents := externalservices.CallPoliceRSS(places[place], limit)
	filterOutLocationsWords(&policeEvents)
	filterOutTime(&policeEvents)
	filterOutEventType(&policeEvents)
	externalservices.CallMapQuest(&policeEvents)
	policeEventsAsJson := encodePoliceEventsToJSON(policeEvents)

	return string(policeEventsAsJson)
}

func filterOutTime(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, event := range eventsCopy.Events {
		eventsCopy.Events[index].Time = filtertitle.GetTime(event.Title)
	}

	*policeEvents = eventsCopy
}

func filterOutEventType(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, event := range eventsCopy.Events {
		eventsCopy.Events[index].EventType = filtertitle.GetEventType(event.Title)
	}

	*policeEvents = eventsCopy
}
func encodePoliceEventsToJSON(policeEvents externalservices.PoliceEvents) []byte {
	policeEventsAsJson, _ := json.Marshal(policeEvents)

	return policeEventsAsJson
}

func filterOutLocationsWords(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, _ := range eventsCopy.Events {
		titleWords, err := filtertitle.FilterTitleWords(eventsCopy.Events[index].Title)

		if err != nil {
			eventsCopy.Events[index].HasPossibleLocation = false
		} else {
			eventsCopy.Events[index].HasPossibleLocation = true
			descriptionWords := filterdescription.FilterDescriptionWords(eventsCopy.Events[index].Description)
			removeDuplicatesAndCombinePossibleLocationWords(titleWords, descriptionWords, &eventsCopy.Events[index].PossibleLocationWords)
		}

	}

	*policeEvents = eventsCopy
}

func removeDuplicatesAndCombinePossibleLocationWords(titleWords []string, descriptionWords []string, locationWords *[]string) {
	location := []string{}

	for _, descWord := range descriptionWords {
		location = append(location, descWord)
	}

	wordAlreadyExists := false

	for _, titleWord := range titleWords {
		for _, locationWord := range location {
			if titleWord == locationWord {
				wordAlreadyExists = true
				break
			}
		}
		if !wordAlreadyExists {
			location = append(location, titleWord)
		}
	}

	*locationWords = location
}
<commit_msg>Updated TODO-list<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"poliskarta/externalservices"
	"poliskarta/filterdescription"
	"poliskarta/filtertitle"
	"strconv"

	"github.com/go-martini/martini"
)

var places = map[string]string{
	"blekinge":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Blekinge/?feed=rss",
	"dalarna":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Dalarna/?feed=rss",
	"gotland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gotland/?feed=rss",
	"gavleborg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gavleborg/?feed=rss",
	"halland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Halland/?feed=rss",
	"jamtland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jamtland/?feed=rss",
	"jonkoping":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jonkoping/?feed=rss",
	"kalmar":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kalmar?feed=rss",
	"kronoberg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kronoberg?feed=rss",
	"norrbotten":     "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Norrbotten?feed=rss",
	"skane":          "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Skane?feed=rss",
	"stockholm":      "https://polisen.se/Stockholms_lan/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Stockholms-lan/?feed=rss",
	"sodermanland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Sodermanland?feed=rss",
	"uppsala":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Uppsala?feed=rss",
	"varmland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Varmland?feed=rss",
	"vasterbotten":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasterbotten?feed=rss",
	"vasternorrland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasternorrland?feed=rss",
	"vastmanland":    "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastmanland?feed=rss",
	"vastragotaland": "https://polisen.se/Vastra_Gotaland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastra-Gotaland/?feed=rss",
	"orebro":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Orebro?feed=rss",
	"ostergotland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Ostergotland?feed=rss",
}

/*
TODO:
	1. Refactor: filtermappar
	2. Felhantering: polis/mapquest = nere, errors osv
	3. Stockholms-undantag
	4. Norrbotten: det mesta är fel här! Fler generella regler?
	5. Lägga till HATEOAS på /, där man får en lista över tillgängliga län
		- API-länkar
		- bra namn
		- bra value-namn (utan åäö/mellanslag)
		- koordinater till "mittpunkten"?
	6. Optimera? Antingen:
		- lägga in parameter ?no-coord=true  +  /getCoord/?Norra+gränges
		- databas som sparar tidigare ord+koordinater, så att inget jobb/anrop görs utåt
		- cache i 5 minuter som standard, eller en parameter för att alltid få senaste: ?no-cache=true
	7. omstrukturera policeevents-structen så att den har objekt/grupper av saker
*/

func main() {
	m := martini.Classic()

	m.Group("/", func(r martini.Router) {
		r.Get(":place", allEvents)
		// r.Get(":place/(?P<number>10|[1-9])", singleEvent)
	})

	m.Run()
}

func allEvents(res http.ResponseWriter, req *http.Request, params martini.Params) {
	place, placeErr := isPlaceValid(params["place"])
	limit, limitErr := isLimitParamValid(req.FormValue("limit"))

	if placeErr != nil {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n%v", status, http.StatusText(status), placeErr.Error())
		res.Write([]byte(errorMessage))
	} else if limitErr != nil {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n%v", status, http.StatusText(status), limitErr.Error())
		res.Write([]byte(errorMessage))
	} else {
		json := callExternalServicesAndCreateJson(place, limit)
		res.Header().Add("Content-type", "application/json; charset=utf-8")

		//**********************************************
		// Detta behövs medans vi köra allt på localhost,
		// Dålig lösning som är osäker, men då kan vi
		// i alla fall testa allt enkelt
		//**********************************************
		res.Header().Add("Access-Control-Allow-Origin", "*")

		res.Write([]byte(json))
	}
}

func singleEvent(params martini.Params) string {
	return params["number"]
}

func isLimitParamValid(param string) (int, error) {
	limit := 10
	var err error
	if param != "" {
		limit, err = strconv.Atoi(param)
		if err != nil {
			err = errors.New(param + " is not a valid positive number")
		}
		if limit < 1 {
			err = errors.New(param + " is not a positive number")
		} else if limit > 50 {
			limit = 50
		}
	}

	return limit, err
}

func isPlaceValid(parameter string) (string, error) {

	for place, _ := range places {
		if place == parameter {
			return place, nil
		}
	}
	return "", errors.New(parameter + " is not a valid place")

}

func callExternalServicesAndCreateJson(place string, limit int) string {
	policeEvents := externalservices.CallPoliceRSS(places[place], limit)
	filterOutLocationsWords(&policeEvents)
	filterOutTime(&policeEvents)
	filterOutEventType(&policeEvents)
	externalservices.CallMapQuest(&policeEvents)
	policeEventsAsJson := encodePoliceEventsToJSON(policeEvents)

	return string(policeEventsAsJson)
}

func filterOutTime(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, event := range eventsCopy.Events {
		eventsCopy.Events[index].Time = filtertitle.GetTime(event.Title)
	}

	*policeEvents = eventsCopy
}

func filterOutEventType(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, event := range eventsCopy.Events {
		eventsCopy.Events[index].EventType = filtertitle.GetEventType(event.Title)
	}

	*policeEvents = eventsCopy
}
func encodePoliceEventsToJSON(policeEvents externalservices.PoliceEvents) []byte {
	policeEventsAsJson, _ := json.Marshal(policeEvents)

	return policeEventsAsJson
}

func filterOutLocationsWords(policeEvents *externalservices.PoliceEvents) {
	eventsCopy := *policeEvents

	for index, _ := range eventsCopy.Events {
		titleWords, err := filtertitle.FilterTitleWords(eventsCopy.Events[index].Title)

		if err != nil {
			eventsCopy.Events[index].HasPossibleLocation = false
		} else {
			eventsCopy.Events[index].HasPossibleLocation = true
			descriptionWords := filterdescription.FilterDescriptionWords(eventsCopy.Events[index].Description)
			removeDuplicatesAndCombinePossibleLocationWords(titleWords, descriptionWords, &eventsCopy.Events[index].PossibleLocationWords)
		}

	}

	*policeEvents = eventsCopy
}

func removeDuplicatesAndCombinePossibleLocationWords(titleWords []string, descriptionWords []string, locationWords *[]string) {
	location := []string{}

	for _, descWord := range descriptionWords {
		location = append(location, descWord)
	}

	wordAlreadyExists := false

	for _, titleWord := range titleWords {
		for _, locationWord := range location {
			if titleWord == locationWord {
				wordAlreadyExists = true
				break
			}
		}
		if !wordAlreadyExists {
			location = append(location, titleWord)
		}
	}

	*locationWords = location
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello World!")
}

func internalServerError(w http.ResponseWriter, r *http.Request) {
	http.Error(w, http.StatusText(http.StatusInternalServerError),
				http.StatusInternalServerError)
}

func main() {
	http.HandleFunc("/", internalServerError)
	http.ListenAndServe(":8000", nil)
}
<commit_msg>update<commit_after>package main

import (
	"io"
	"net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello World!")
}

func internalServerError(w http.ResponseWriter, r *http.Request) {
	http.Error(w, http.StatusText(http.StatusInternalServerError),
				http.StatusInternalServerError)
}

func main() {
	http.HandleFunc("/", hello)
	http.ListenAndServe(":8000", nil)
}
<|endoftext|>


<commit_before>// vm: tabstop=2 shiftwidth=2

package main

import (
	"bytes"
	"strings"
	"errors"
	"encoding/binary"
	"encoding/hex"
	"time"
	"crypto/rand"
	"github.com/crooks/yamn/keymgr"
	"code.google.com/p/go.crypto/nacl/box"
)

// timestamp creates a Mixmaster formatted timestamp, consisting of an intro
// string concatented to the number of days since Epoch (little Endian).
func timestamp() (stamp []byte) {
	d := uint16(time.Now().UTC().Unix() / 86400)
	days := make([]byte, 2)
	binary.LittleEndian.PutUint16(days, d)
	stamp = append([]byte("0000\x00"), days...)
	return
}

// Generate a public/private ECC key pair
func eccGenerate() (public, private []byte) {
	puba, priva, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	public = make([]byte, 32)
	private = make([]byte, 32)
	copy(public[:], puba[:])
	copy(private[:], priva[:])
	if len(public) != 32 {
		panic("Invalid pubkey length generated")
	}
	if len(private) != 32 {
		panic("Invalid seckey length generated")
	}
	return
}

/*
Slot Header Format
[ Recipient key ID		 16 Bytes ]
[ Sender Public key		 32 Bytes ]
[ Xsalsa20 Nonce		 24 Bytes ]
[ Encrypted data		408 Bytes ] (392 + Overhead)
[ Random padding		 32 Bytes ]
*/

type slotHead struct {
	recipientKeyid []byte
	recipientPK []byte
	//sender_pubkey []byte
	//nonce []byte
	data []byte
}

func (h *slotHead) encodeHead() []byte {
	// Generate an ECC key pair
	sendpub, sendpriv, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	var nonce [24]byte
	copy(nonce[:], randbytes(24))
	buf := new(bytes.Buffer)
	buf.Write(h.recipientKeyid)
	buf.Write(sendpub[:])
	buf.Write(nonce[:])
	var pk [32]byte
	copy(pk[:], h.recipientPK)
	buf.Write(box.Seal(nil, h.data, &nonce, &pk, sendpriv))
	err = bufLenCheck(buf.Len(), 480)
	if err != nil {
		panic(err)
	}
	buf.Write(randbytes(headerBytes - buf.Len()))
	return buf.Bytes()
}

// decodeHead decodes a slot header
func decodeHead(b []byte, secret *keymgr.Secring) (data []byte, err error) {
	/*
	Decode functions should return their associated structs but, in this
	instance, the only field of value is the decrypted data.
	*/
	err = lenCheck(len(b), headerBytes)
	if err != nil {
		return
	}
	var keyid string
	keyid = hex.EncodeToString(b[0:16])
	var sk []byte
	sk, err = secret.GetSK(keyid)
	if err != nil {
		return
	}
	var sender_pk [32]byte
	copy(sender_pk[:], b[16:48])
	var recipient_sk [32]byte
	copy(recipient_sk[:], sk)
	var nonce [24]byte
	copy(nonce[:], b[48:72])
	var auth bool
	data, auth = box.Open(nil, b[72:72+408], &nonce, &sender_pk, &recipient_sk)
	if ! auth {
		err = errors.New("Authentication failed decrypting slot data")
		return
	}
	err = lenCheck(len(data), 392)
	return
}

/*
Encrypted Data
[ Packet ID		 16 Bytes ]
[ AES-CTR key		 32 Bytes ]
[ Packet type ID	  1 Byte  ]
[ Padded packet info	256 Bytes ]
[ Timestamp		  7 Bytes ]
[ Anti-tag digest	 64 Bytes ]
[ Padding		 16 Bytes ]
Total	392 Bytes
*/

type slotData struct {
	packetID []byte
	aesKey []byte
	packetType uint8
	packetInfo []byte
	timestamp []byte
	tagHash []byte
}

func (d slotData) encodeData() (b []byte, err error) {
	err = lenCheck(len(d.packetID), 16)
	if err != nil {
		return
	}
	err = lenCheck(len(d.aesKey), 32)
	if err != nil {
		return
	}
	err = lenCheck(len(d.packetInfo), 256)
	if err != nil {
		return
	}
	err = lenCheck(len(d.tagHash), 64)
	if err != nil {
		return
	}
	buf := new(bytes.Buffer)
	buf.Write(d.packetID)
	buf.Write(d.aesKey)
	buf.WriteByte(d.packetType)
	buf.Write(d.packetInfo)
	buf.Write(d.timestamp)
	buf.Write(d.tagHash)
	err = bufLenCheck(buf.Len(), 376)
	if err != nil {
		return
	}
	buf.WriteString(strings.Repeat("\x00", 392 - buf.Len()))
	b = buf.Bytes()
	return
}

func (data *slotData) decodeData(b []byte) (err error) {
	err = lenCheck(len(b), 392)
	if err != nil {
		return
	}
	data.packetID = b[0:16]
	data.aesKey = b[16:48]
	data.packetType = uint8(b[48])
	data.packetInfo = b[49:305]
	data.timestamp = b[305:312]
	//TODO Test timestamp
	data.tagHash = b[312:376]
	//Padding[376:392]
	return
}

/*
Final Hop
[ Chunk num		  1 Byte  ]
[ Num chunks		  1 Byte  ]
[ Message ID		 16 Bytes ]
[ AES-CTR IV		 16 Bytes ]
[ Body length		  4 Bytes ]
[ Delivery method	  1 Byte  ]

Currently supported delivery methods are:-
[ SMTP				  0 ]
[ Dummy - discard 		255 ]
*/

type slotFinal struct {
	chunkNum uint8
	numChunks uint8
	messageID []byte
	aesIV []byte
	bodyBytes int
	deliveryMethod uint8
}

func (f *slotFinal) encodeFinal() []byte {
	buf := new(bytes.Buffer)
	buf.WriteByte(f.chunkNum)
	buf.WriteByte(f.numChunks)
	buf.Write(f.messageID)
	buf.Write(f.aesIV)
	tmp := make([]byte, 4)
	binary.LittleEndian.PutUint32(tmp, uint32(f.bodyBytes))
	buf.Write(tmp)
	buf.WriteByte(f.deliveryMethod)
	err := bufLenCheck(buf.Len(), 39)
	if err != nil {
		panic(err)
	}
	buf.WriteString(strings.Repeat("\x00", 256 - buf.Len()))
	return buf.Bytes()
}

func (f *slotFinal) decodeFinal(b []byte) (err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	f.chunkNum = b[0]
	f.numChunks = b[1]
	f.messageID = b[2:18]
	f.aesIV = b[18:34]
	f.bodyBytes = int(binary.LittleEndian.Uint32(b[34:38]))
	f.deliveryMethod = b[38]
	return
}

/*
Intermediate Hop
[ 11 * AES-CTR IVs		176 Bytes ]
[ Next hop address		 80 Bytes ]

IVs are 9 * header slots, payload and deterministic
*/

type slotIntermediate struct {
	aesIVs []byte
	nextHop []byte
}

func (i *slotIntermediate) setNextHop(nh string) {
	i.nextHop = []byte(nh + strings.Repeat("\x00", 80 - len(nh)))
}

func (i *slotIntermediate) getNextHop() string {
	return strings.TrimRight(string(i.nextHop), "\x00")
}

func (i *slotIntermediate) encodeIntermediate() []byte {
	var err error
	err = lenCheck(len(i.aesIVs), (maxChainLength + 1) * 16)
	if err != nil {
		panic(err)
	}
	buf := new(bytes.Buffer)
	buf.Write(i.aesIVs)
	buf.Write(i.nextHop)
	err = bufLenCheck(buf.Len(), 256)
	if err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func (i *slotIntermediate) decodeIntermediate(b []byte) (err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	i.aesIVs = b[:176]
	i.nextHop = b[176:]
	return
}
<commit_msg>Cosmetic changes to headers<commit_after>// vm: tabstop=2 shiftwidth=2

package main

import (
	"bytes"
	"strings"
	"errors"
	"encoding/binary"
	"encoding/hex"
	"time"
	"crypto/rand"
	"github.com/crooks/yamn/keymgr"
	"code.google.com/p/go.crypto/nacl/box"
)

// timestamp creates a Mixmaster formatted timestamp, consisting of an intro
// string concatented to the number of days since Epoch (little Endian).
func timestamp() (stamp []byte) {
	d := uint16(time.Now().UTC().Unix() / 86400)
	days := make([]byte, 2)
	binary.LittleEndian.PutUint16(days, d)
	stamp = append([]byte("0000\x00"), days...)
	return
}

// Generate a public/private ECC key pair
func eccGenerate() (public, private []byte) {
	puba, priva, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	public = make([]byte, 32)
	private = make([]byte, 32)
	copy(public[:], puba[:])
	copy(private[:], priva[:])
	if len(public) != 32 {
		panic("Invalid pubkey length generated")
	}
	if len(private) != 32 {
		panic("Invalid seckey length generated")
	}
	return
}

/*
Slot Header Format
[ Recipient key ID		 16 Bytes ]
[ Sender Public key		 32 Bytes ]
[ Xsalsa20 Nonce		 24 Bytes ]
[ Encrypted data		408 Bytes ] (392 + Overhead)
[ Random padding		 32 Bytes ]
*/

type slotHead struct {
	recipientKeyid []byte
	recipientPK []byte
	//sender_pubkey []byte
	//nonce []byte
	data []byte
}

func (h *slotHead) encodeHead() []byte {
	// Generate an ECC key pair
	sendpub, sendpriv, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	var nonce [24]byte
	copy(nonce[:], randbytes(24))
	buf := new(bytes.Buffer)
	buf.Write(h.recipientKeyid)
	buf.Write(sendpub[:])
	buf.Write(nonce[:])
	var pk [32]byte
	copy(pk[:], h.recipientPK)
	buf.Write(box.Seal(nil, h.data, &nonce, &pk, sendpriv))
	err = bufLenCheck(buf.Len(), 480)
	if err != nil {
		panic(err)
	}
	buf.Write(randbytes(headerBytes - buf.Len()))
	return buf.Bytes()
}

// decodeHead decodes a slot header
func decodeHead(b []byte, secret *keymgr.Secring) (data []byte, err error) {
	/*
	Decode functions should return their associated structs but, in this
	instance, the only field of value is the decrypted data.
	*/
	err = lenCheck(len(b), headerBytes)
	if err != nil {
		return
	}
	var keyid string
	keyid = hex.EncodeToString(b[0:16])
	var sk []byte
	sk, err = secret.GetSK(keyid)
	if err != nil {
		return
	}
	var sender_pk [32]byte
	copy(sender_pk[:], b[16:48])
	var recipient_sk [32]byte
	copy(recipient_sk[:], sk)
	var nonce [24]byte
	copy(nonce[:], b[48:72])
	var auth bool
	data, auth = box.Open(
		nil,
		b[72:72+408],
		&nonce,
		&sender_pk,
		&recipient_sk)
	if ! auth {
		err = errors.New("Authentication failed decrypting slot data")
		return
	}
	err = lenCheck(len(data), 392)
	return
}

/*
Encrypted Data
[ Packet ID		 16 Bytes ]
[ AES-CTR key		 32 Bytes ]
[ Packet type ID	  1 Byte  ]
[ Padded packet info	256 Bytes ]
[ Timestamp		  7 Bytes ]
[ Anti-tag digest	 64 Bytes ]
[ Padding		 16 Bytes ]
Total	392 Bytes
*/

type slotData struct {
	packetID []byte
	aesKey []byte
	packetType uint8
	packetInfo []byte
	timestamp []byte
	tagHash []byte
}

func (d slotData) encodeData() (b []byte, err error) {
	err = lenCheck(len(d.packetID), 16)
	if err != nil {
		return
	}
	err = lenCheck(len(d.aesKey), 32)
	if err != nil {
		return
	}
	err = lenCheck(len(d.packetInfo), 256)
	if err != nil {
		return
	}
	err = lenCheck(len(d.tagHash), 64)
	if err != nil {
		return
	}
	buf := new(bytes.Buffer)
	buf.Write(d.packetID)
	buf.Write(d.aesKey)
	buf.WriteByte(d.packetType)
	buf.Write(d.packetInfo)
	buf.Write(d.timestamp)
	buf.Write(d.tagHash)
	err = bufLenCheck(buf.Len(), 376)
	if err != nil {
		return
	}
	buf.WriteString(strings.Repeat("\x00", 392 - buf.Len()))
	b = buf.Bytes()
	return
}

func (data *slotData) decodeData(b []byte) (err error) {
	err = lenCheck(len(b), 392)
	if err != nil {
		return
	}
	data.packetID = b[0:16]
	data.aesKey = b[16:48]
	data.packetType = uint8(b[48])
	data.packetInfo = b[49:305]
	data.timestamp = b[305:312]
	//TODO Test timestamp
	data.tagHash = b[312:376]
	//Padding[376:392]
	return
}

/*
Final Hop
[ Chunk num		  1 Byte  ]
[ Num chunks		  1 Byte  ]
[ Message ID		 16 Bytes ]
[ AES-CTR IV		 16 Bytes ]
[ Body length		  4 Bytes ]
[ Delivery method	  1 Byte  ]

Currently supported delivery methods are:-
[ SMTP				  0 ]
[ Dummy - discard 		255 ]
*/

type slotFinal struct {
	chunkNum uint8
	numChunks uint8
	messageID []byte
	aesIV []byte
	bodyBytes int
	deliveryMethod uint8
}

func (f *slotFinal) encodeFinal() []byte {
	buf := new(bytes.Buffer)
	buf.WriteByte(f.chunkNum)
	buf.WriteByte(f.numChunks)
	buf.Write(f.messageID)
	buf.Write(f.aesIV)
	tmp := make([]byte, 4)
	binary.LittleEndian.PutUint32(tmp, uint32(f.bodyBytes))
	buf.Write(tmp)
	buf.WriteByte(f.deliveryMethod)
	err := bufLenCheck(buf.Len(), 39)
	if err != nil {
		panic(err)
	}
	buf.WriteString(strings.Repeat("\x00", 256 - buf.Len()))
	return buf.Bytes()
}

func (f *slotFinal) decodeFinal(b []byte) (err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	f.chunkNum = b[0]
	f.numChunks = b[1]
	f.messageID = b[2:18]
	f.aesIV = b[18:34]
	f.bodyBytes = int(binary.LittleEndian.Uint32(b[34:38]))
	f.deliveryMethod = b[38]
	return
}

/*
Intermediate Hop
[ 11 * AES-CTR IVs		176 Bytes ]
[ Next hop address		 80 Bytes ]

IVs are:
[ 9 * Header slots		144 Bytes ]
[ 1 * Deterministic header	 16 Bytes ]
[ 1 * Payload header		 16 Bytes ]
*/

type slotIntermediate struct {
	aesIVs []byte
	nextHop []byte
}

func (i *slotIntermediate) setNextHop(nh string) {
	i.nextHop = []byte(nh + strings.Repeat("\x00", 80 - len(nh)))
}

func (i *slotIntermediate) getNextHop() string {
	return strings.TrimRight(string(i.nextHop), "\x00")
}

func (i *slotIntermediate) encodeIntermediate() []byte {
	var err error
	err = lenCheck(len(i.aesIVs), (maxChainLength + 1) * 16)
	if err != nil {
		panic(err)
	}
	buf := new(bytes.Buffer)
	buf.Write(i.aesIVs)
	buf.Write(i.nextHop)
	err = bufLenCheck(buf.Len(), 256)
	if err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func (i *slotIntermediate) decodeIntermediate(b []byte) (err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	i.aesIVs = b[:176]
	i.nextHop = b[176:]
	return
}
<|endoftext|>


<commit_before>package napnap

type Health struct {
}

func NewHealth() *Health {
	return &Health{}
}

func (h *Health) Invoke(c *Context, next HandlerFunc) {
	if c.Request.URL.Path == "/health" {
		c.String(200, "ok")
	} else {
		next(c)
	}
}
<commit_msg>change ok to uppercase<commit_after>package napnap

type Health struct {
}

func NewHealth() *Health {
	return &Health{}
}

func (h *Health) Invoke(c *Context, next HandlerFunc) {
	if c.Request.URL.Path == "/health" {
		c.String(200, "OK")
	} else {
		next(c)
	}
}
<|endoftext|>


<commit_before>package i18n

import (
	"regexp"
	"sort"

	"github.com/volatile/core"
)

// Locale contains translations and special i18n values associated to unique keys.
type Locale map[string]string

// Locales contains locales associated to their names.
type Locales map[string]Locale

const (
	// TransNPlaceholder is the placeholder replaced by n in a translation, when using the TransN function.
	TransNPlaceholder = "{{.n}}"

	contextDataKey = "i18nLocale"
)

var (
	useCookie  bool       // Defines if the matched locale must be saved in a cookie after matching.
	cookieName = "locale" // The name of the cookie used to save the client matched locale.

	defaultLocale   string
	locales         *Locales // The map of available locales. It is ensured to not be empty.
	localeKeyRegexp = regexp.MustCompile("^[a-z]{2}$")
)

// ViewsFuncs provides i18n functions to be set for templates.
var ViewsFuncs = map[string]interface{}{
	"locale":           ClientLocale,
	"num":              Num,
	"sortedLocaleKeys": SortedLocaleKeys,
	"trans":            Trans,
	"transn":           TransN,
}

// Use registers locales l.
// On request, if none match to the client accepted languages, the locale def will be used.
// And if useCookie is true, a cookie will be used to save the most appropriate and available locale key for the client.
func Use(l *Locales, def string, cookie bool) {
	if len(*locales) == 0 {
		panic("i18n: locales map can't be empty")
	}

	for i := range *l {
		if !localeKeyRegexp.MatchString(i) {
			panic(`i18n: locale key must be an ISO 639-1 code (2 letters lowercase), so "` + i + `" is invalid`)
		}
	}
	locales = l

	if !localeExists(def) {
		panic("i18n: default locale " + def + " doesn't exist")
	}
	defaultLocale = def

	useCookie = cookie

	// Trigger ClientLocale to match and set locale at least one time.
	core.Use(func(c *core.Context) {
		ClientLocale(c)
		c.Next()
	})
}

// SortedLocaleKeys returns the sorted keys of all available locales.
func SortedLocaleKeys() (kk []string) {
	for k := range *locales {
		kk = append(kk, k)
	}
	sort.Strings(kk)
	return
}

func localeExists(l string) bool {
	_, ok := (*locales)[l]
	return ok
}
<commit_msg>Update doc<commit_after>package i18n

import (
	"regexp"
	"sort"

	"github.com/volatile/core"
)

// Locale contains translations and special i18n values associated to unique keys.
type Locale map[string]string

// Locales contains locales associated to their names.
type Locales map[string]Locale

const (
	// TransNPlaceholder is the placeholder replaced by n in a translation, when using the TransN function.
	TransNPlaceholder = "{{.n}}"

	contextDataKey = "i18nLocale"
)

var (
	useCookie  bool       // Defines if the matched locale must be saved in a cookie after matching.
	cookieName = "locale" // The name of the cookie used to save the client matched locale.

	defaultLocale   string
	locales         *Locales // The map of available locales. It is ensured to not be empty.
	localeKeyRegexp = regexp.MustCompile("^[a-z]{2}$")
)

// ViewsFuncs provides i18n functions that can be set for templates.
var ViewsFuncs = map[string]interface{}{
	"locale":           ClientLocale,
	"num":              Num,
	"sortedLocaleKeys": SortedLocaleKeys,
	"trans":            Trans,
	"transn":           TransN,
}

// Use registers locales l.
// On request, if none match to the client accepted languages, the locale def will be used.
// And if useCookie is true, a cookie will be used to save the most appropriate and available locale key for the client.
func Use(l *Locales, def string, cookie bool) {
	if len(*locales) == 0 {
		panic("i18n: locales map can't be empty")
	}

	for i := range *l {
		if !localeKeyRegexp.MatchString(i) {
			panic(`i18n: locale key must be an ISO 639-1 code (2 letters lowercase), so "` + i + `" is invalid`)
		}
	}
	locales = l

	if !localeExists(def) {
		panic("i18n: default locale " + def + " doesn't exist")
	}
	defaultLocale = def

	useCookie = cookie

	// Trigger ClientLocale to match and set locale at least one time.
	core.Use(func(c *core.Context) {
		ClientLocale(c)
		c.Next()
	})
}

// SortedLocaleKeys returns the sorted keys of all available locales.
func SortedLocaleKeys() (kk []string) {
	for k := range *locales {
		kk = append(kk, k)
	}
	sort.Strings(kk)
	return
}

func localeExists(l string) bool {
	_, ok := (*locales)[l]
	return ok
}
<|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 driver provides an external entry point to the pprof driver.
package driver

import (
	"io"
	"regexp"
	"time"

	internaldriver "github.com/google/pprof/internal/driver"
	"github.com/google/pprof/internal/plugin"
	"github.com/google/pprof/profile"
)

// PProf acquires a profile, and symbolizes it using a profile
// manager. Then it generates a report formatted according to the
// options selected through the flags package.
func PProf(o *Options) error {
	return internaldriver.PProf(o.InternalOptions())
}

func (o *Options) InternalOptions() *plugin.Options {
	var obj plugin.ObjTool
	if o.Obj != nil {
		obj = &internalObjTool{o.Obj}
	}
	var sym plugin.Symbolizer
	if o.Sym != nil {
		sym = &internalSymbolizer{o.Sym}
	}
	return &plugin.Options{
		Writer: o.Writer,
		Flagset: o.Flagset,
		Fetch: o.Fetch,
		Sym: sym,
		Obj: obj,
		UI: o.UI,
	}
}

// Options groups all the optional plugins into pprof.
type Options struct {
	Writer  Writer
	Flagset FlagSet
	Fetch   Fetcher
	Sym     Symbolizer
	Obj     ObjTool
	UI      UI
}

// Writer provides a mechanism to write data under a certain name,
// typically a filename.
type Writer interface {
	Open(name string) (io.WriteCloser, error)
}

// A FlagSet creates and parses command-line flags.
// It is similar to the standard flag.FlagSet.
type FlagSet interface {
	// Bool, Int, Float64, and String define new flags,
	// like the functions of the same name in package flag.
	Bool(name string, def bool, usage string) *bool
	Int(name string, def int, usage string) *int
	Float64(name string, def float64, usage string) *float64
	String(name string, def string, usage string) *string

	// BoolVar, IntVar, Float64Var, and StringVar define new flags referencing
	// a given pointer, like the functions of the same name in package flag.
	BoolVar(pointer *bool, name string, def bool, usage string)
	IntVar(pointer *int, name string, def int, usage string)
	Float64Var(pointer *float64, name string, def float64, usage string)
	StringVar(pointer *string, name string, def string, usage string)

	// StringList is similar to String but allows multiple values for a
	// single flag
	StringList(name string, def string, usage string) *[]*string

	// ExtraUsage returns any additional text that should be
	// printed after the standard usage message.
	// The typical use of ExtraUsage is to show any custom flags
	// defined by the specific pprof plugins being used.
	ExtraUsage() string

	// Parse initializes the flags with their values for this run
	// and returns the non-flag command line arguments.
	// If an unknown flag is encountered or there are no arguments,
	// Parse should call usage and return nil.
	Parse(usage func()) []string
}

// A Fetcher reads and returns the profile named by src, using
// the specified duration and timeout. It returns the fetched
// profile and a string indicating a URL from where the profile
// was fetched, which may be different than src.
type Fetcher interface {
	Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error)
}

// A Symbolizer introduces symbol information into a profile.
type Symbolizer interface {
	Symbolize(mode string, srcs MappingSources, prof *profile.Profile) error
}

// MappingSources map each profile.Mapping to the source of the profile.
// The key is either Mapping.File or Mapping.BuildId.
type MappingSources map[string][]struct {
	Source string // URL of the source the mapping was collected from
	Start  uint64 // delta applied to addresses from this source (to represent Merge adjustments)
}

// An ObjTool inspects shared libraries and executable files.
type ObjTool interface {
	// Open opens the named object file. If the object is a shared
	// library, start/limit/offset are the addresses where it is mapped
	// into memory in the address space being inspected.
	Open(file string, start, limit, offset uint64) (ObjFile, error)

	// Disasm disassembles the named object file, starting at
	// the start address and stopping at (before) the end address.
	Disasm(file string, start, end uint64) ([]Inst, error)
}

// An Inst is a single instruction in an assembly listing.
type Inst struct {
	Addr     uint64 // virtual address of instruction
	Text     string // instruction text
	Function string // function name
	File     string // source file
	Line     int    // source line
}

// An ObjFile is a single object file: a shared library or executable.
type ObjFile interface {
	// Name returns the underlying file name, if available.
	Name() string

	// Base returns the base address to use when looking up symbols in the file.
	Base() uint64

	// BuildID returns the GNU build ID of the file, or an empty string.
	BuildID() string

	// SourceLine reports the source line information for a given
	// address in the file. Due to inlining, the source line information
	// is in general a list of positions representing a call stack,
	// with the leaf function first.
	SourceLine(addr uint64) ([]Frame, error)

	// Symbols returns a list of symbols in the object file.
	// If r is not nil, Symbols restricts the list to symbols
	// with names matching the regular expression.
	// If addr is not zero, Symbols restricts the list to symbols
	// containing that address.
	Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error)

	// Close closes the file, releasing associated resources.
	Close() error
}

// A Frame describes a single line in a source file.
type Frame struct {
	Func string // name of function
	File string // source file name
	Line int    // line in file
}

// A Sym describes a single symbol in an object file.
type Sym struct {
	Name  []string // names of symbol (many if symbol was dedup'ed)
	File  string   // object file containing symbol
	Start uint64   // start virtual address
	End   uint64   // virtual address of last byte in sym (Start+size-1)
}

// A UI manages user interactions.
type UI interface {
	// Read returns a line of text (a command) read from the user.
	// prompt is printed before reading the command.
	ReadLine(prompt string) (string, error)

	// Print shows a message to the user.
	// It formats the text as fmt.Print would and adds a final \n if not already present.
	// For line-based UI, Print writes to standard error.
	// (Standard output is reserved for report data.)
	Print(...interface{})

	// PrintErr shows an error message to the user.
	// It formats the text as fmt.Print would and adds a final \n if not already present.
	// For line-based UI, PrintErr writes to standard error.
	PrintErr(...interface{})

	// IsTerminal returns whether the UI is known to be tied to an
	// interactive terminal (as opposed to being redirected to a file).
	IsTerminal() bool

	// SetAutoComplete instructs the UI to call complete(cmd) to obtain
	// the auto-completion of cmd, if the UI supports auto-completion at all.
	SetAutoComplete(complete func(string) string)
}

// internalObjTool is a wrapper to map from the pprof external
// interface to the internal interface.
type internalObjTool struct {
	ObjTool
}

func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
	f, err := o.ObjTool.Open(file, start, limit, offset)
	if err != nil {
		return nil, err
	}
	return &internalObjFile{f}, err
}

type internalObjFile struct {
	ObjFile
}

func (f *internalObjFile) SourceLine(frame uint64) ([]plugin.Frame, error) {
	frames, err := f.ObjFile.SourceLine(frame)
	if err != nil {
		return nil, err
	}
	var pluginFrames []plugin.Frame
	for _, f := range frames {
		pluginFrames = append(pluginFrames, plugin.Frame(f))
	}
	return pluginFrames, nil
}

func (f *internalObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
	syms, err := f.ObjFile.Symbols(r, addr)
	if err != nil {
		return nil, err
	}
	var pluginSyms []*plugin.Sym
	for _, s := range syms {
		ps := plugin.Sym(*s)
		pluginSyms = append(pluginSyms, &ps)
	}
	return pluginSyms, nil
}

func (o *internalObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
	insts, err := o.ObjTool.Disasm(file, start, end)
	if err != nil {
		return nil, err
	}
	var pluginInst []plugin.Inst
	for _, inst := range insts {
		pluginInst = append(pluginInst, plugin.Inst(inst))
	}
	return pluginInst, nil
}

// internalSymbolizer is a wrapper to map from the pprof external
// interface to the internal interface.
type internalSymbolizer struct {
	Symbolizer
}

func (s *internalSymbolizer) Symbolize(mode string, srcs plugin.MappingSources, prof *profile.Profile) error {
	isrcs := plugin.MappingSources{}
	for m, s := range srcs {
		isrcs[m] = s
	}
	return s.Symbolize(mode, isrcs, prof)
}
<commit_msg>gofmt recent changes<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 driver provides an external entry point to the pprof driver.
package driver

import (
	"io"
	"regexp"
	"time"

	internaldriver "github.com/google/pprof/internal/driver"
	"github.com/google/pprof/internal/plugin"
	"github.com/google/pprof/profile"
)

// PProf acquires a profile, and symbolizes it using a profile
// manager. Then it generates a report formatted according to the
// options selected through the flags package.
func PProf(o *Options) error {
	return internaldriver.PProf(o.InternalOptions())
}

func (o *Options) InternalOptions() *plugin.Options {
	var obj plugin.ObjTool
	if o.Obj != nil {
		obj = &internalObjTool{o.Obj}
	}
	var sym plugin.Symbolizer
	if o.Sym != nil {
		sym = &internalSymbolizer{o.Sym}
	}
	return &plugin.Options{
		Writer:  o.Writer,
		Flagset: o.Flagset,
		Fetch:   o.Fetch,
		Sym:     sym,
		Obj:     obj,
		UI:      o.UI,
	}
}

// Options groups all the optional plugins into pprof.
type Options struct {
	Writer  Writer
	Flagset FlagSet
	Fetch   Fetcher
	Sym     Symbolizer
	Obj     ObjTool
	UI      UI
}

// Writer provides a mechanism to write data under a certain name,
// typically a filename.
type Writer interface {
	Open(name string) (io.WriteCloser, error)
}

// A FlagSet creates and parses command-line flags.
// It is similar to the standard flag.FlagSet.
type FlagSet interface {
	// Bool, Int, Float64, and String define new flags,
	// like the functions of the same name in package flag.
	Bool(name string, def bool, usage string) *bool
	Int(name string, def int, usage string) *int
	Float64(name string, def float64, usage string) *float64
	String(name string, def string, usage string) *string

	// BoolVar, IntVar, Float64Var, and StringVar define new flags referencing
	// a given pointer, like the functions of the same name in package flag.
	BoolVar(pointer *bool, name string, def bool, usage string)
	IntVar(pointer *int, name string, def int, usage string)
	Float64Var(pointer *float64, name string, def float64, usage string)
	StringVar(pointer *string, name string, def string, usage string)

	// StringList is similar to String but allows multiple values for a
	// single flag
	StringList(name string, def string, usage string) *[]*string

	// ExtraUsage returns any additional text that should be
	// printed after the standard usage message.
	// The typical use of ExtraUsage is to show any custom flags
	// defined by the specific pprof plugins being used.
	ExtraUsage() string

	// Parse initializes the flags with their values for this run
	// and returns the non-flag command line arguments.
	// If an unknown flag is encountered or there are no arguments,
	// Parse should call usage and return nil.
	Parse(usage func()) []string
}

// A Fetcher reads and returns the profile named by src, using
// the specified duration and timeout. It returns the fetched
// profile and a string indicating a URL from where the profile
// was fetched, which may be different than src.
type Fetcher interface {
	Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error)
}

// A Symbolizer introduces symbol information into a profile.
type Symbolizer interface {
	Symbolize(mode string, srcs MappingSources, prof *profile.Profile) error
}

// MappingSources map each profile.Mapping to the source of the profile.
// The key is either Mapping.File or Mapping.BuildId.
type MappingSources map[string][]struct {
	Source string // URL of the source the mapping was collected from
	Start  uint64 // delta applied to addresses from this source (to represent Merge adjustments)
}

// An ObjTool inspects shared libraries and executable files.
type ObjTool interface {
	// Open opens the named object file. If the object is a shared
	// library, start/limit/offset are the addresses where it is mapped
	// into memory in the address space being inspected.
	Open(file string, start, limit, offset uint64) (ObjFile, error)

	// Disasm disassembles the named object file, starting at
	// the start address and stopping at (before) the end address.
	Disasm(file string, start, end uint64) ([]Inst, error)
}

// An Inst is a single instruction in an assembly listing.
type Inst struct {
	Addr     uint64 // virtual address of instruction
	Text     string // instruction text
	Function string // function name
	File     string // source file
	Line     int    // source line
}

// An ObjFile is a single object file: a shared library or executable.
type ObjFile interface {
	// Name returns the underlying file name, if available.
	Name() string

	// Base returns the base address to use when looking up symbols in the file.
	Base() uint64

	// BuildID returns the GNU build ID of the file, or an empty string.
	BuildID() string

	// SourceLine reports the source line information for a given
	// address in the file. Due to inlining, the source line information
	// is in general a list of positions representing a call stack,
	// with the leaf function first.
	SourceLine(addr uint64) ([]Frame, error)

	// Symbols returns a list of symbols in the object file.
	// If r is not nil, Symbols restricts the list to symbols
	// with names matching the regular expression.
	// If addr is not zero, Symbols restricts the list to symbols
	// containing that address.
	Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error)

	// Close closes the file, releasing associated resources.
	Close() error
}

// A Frame describes a single line in a source file.
type Frame struct {
	Func string // name of function
	File string // source file name
	Line int    // line in file
}

// A Sym describes a single symbol in an object file.
type Sym struct {
	Name  []string // names of symbol (many if symbol was dedup'ed)
	File  string   // object file containing symbol
	Start uint64   // start virtual address
	End   uint64   // virtual address of last byte in sym (Start+size-1)
}

// A UI manages user interactions.
type UI interface {
	// Read returns a line of text (a command) read from the user.
	// prompt is printed before reading the command.
	ReadLine(prompt string) (string, error)

	// Print shows a message to the user.
	// It formats the text as fmt.Print would and adds a final \n if not already present.
	// For line-based UI, Print writes to standard error.
	// (Standard output is reserved for report data.)
	Print(...interface{})

	// PrintErr shows an error message to the user.
	// It formats the text as fmt.Print would and adds a final \n if not already present.
	// For line-based UI, PrintErr writes to standard error.
	PrintErr(...interface{})

	// IsTerminal returns whether the UI is known to be tied to an
	// interactive terminal (as opposed to being redirected to a file).
	IsTerminal() bool

	// SetAutoComplete instructs the UI to call complete(cmd) to obtain
	// the auto-completion of cmd, if the UI supports auto-completion at all.
	SetAutoComplete(complete func(string) string)
}

// internalObjTool is a wrapper to map from the pprof external
// interface to the internal interface.
type internalObjTool struct {
	ObjTool
}

func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
	f, err := o.ObjTool.Open(file, start, limit, offset)
	if err != nil {
		return nil, err
	}
	return &internalObjFile{f}, err
}

type internalObjFile struct {
	ObjFile
}

func (f *internalObjFile) SourceLine(frame uint64) ([]plugin.Frame, error) {
	frames, err := f.ObjFile.SourceLine(frame)
	if err != nil {
		return nil, err
	}
	var pluginFrames []plugin.Frame
	for _, f := range frames {
		pluginFrames = append(pluginFrames, plugin.Frame(f))
	}
	return pluginFrames, nil
}

func (f *internalObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
	syms, err := f.ObjFile.Symbols(r, addr)
	if err != nil {
		return nil, err
	}
	var pluginSyms []*plugin.Sym
	for _, s := range syms {
		ps := plugin.Sym(*s)
		pluginSyms = append(pluginSyms, &ps)
	}
	return pluginSyms, nil
}

func (o *internalObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
	insts, err := o.ObjTool.Disasm(file, start, end)
	if err != nil {
		return nil, err
	}
	var pluginInst []plugin.Inst
	for _, inst := range insts {
		pluginInst = append(pluginInst, plugin.Inst(inst))
	}
	return pluginInst, nil
}

// internalSymbolizer is a wrapper to map from the pprof external
// interface to the internal interface.
type internalSymbolizer struct {
	Symbolizer
}

func (s *internalSymbolizer) Symbolize(mode string, srcs plugin.MappingSources, prof *profile.Profile) error {
	isrcs := plugin.MappingSources{}
	for m, s := range srcs {
		isrcs[m] = s
	}
	return s.Symbolize(mode, isrcs, prof)
}
<|endoftext|>


<commit_before>package stats

import (
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/http"
	"strings"
	"time"
)

// Put this in a separate package called stats

// PurgeInterval is the interval at which users are purged from the current list
var PurgeInterval = time.Minute * 5

// identifiers holds a hash of anonymised user records
// obviously an in-memory store is not suitable for very large sites
// but for smaller sites with a few hundred concurrent users it's fine
var identifiers = make(map[string]time.Time)

// RegisterHit registers a hit and ups user count if required
func RegisterHit(r *http.Request) {

	// Use UA as well as ip for unique values per browser session
	ua := r.Header.Get("User-Agent")
	// Ignore obvious bots (Googlebot etc)
	if strings.Contains(ua, "bot") {
		return
	}
	// Ignore requests for xml (assumed to be feeds or sitemap)
	if strings.HasSuffix(r.URL.Path, ".xml") {
		return
	}

	// Extract the IP from the address
	ip := r.RemoteAddr
	forward := r.Header.Get("X-Forwarded-For")
	if len(forward) > 0 {
		ip = forward
	}

	// Hash for anonymity in our store
	hasher := sha1.New()
	hasher.Write([]byte(ip))
	hasher.Write([]byte(ua))
	id := base64.URLEncoding.EncodeToString(hasher.Sum(nil))

	// Insert the entry with current time
	identifiers[id] = time.Now()

}

// HandleUserCount serves a get request at /stats/users/count
func HandleUserCount(w http.ResponseWriter, r *http.Request) error {
	// Render json of our count for the javascript to display
	json := fmt.Sprintf("{\"users\":%d}", len(identifiers))
	_, err := w.Write([]byte(json))
	return err
}

// UserCount returns a count of users in the last 5 minutes
func UserCount() int {
	return len(identifiers)
}

// Clean up users list at intervals
func init() {
	purgeUsers()
}

// purgeUsers clears the users list of users who last acted PurgeInterval ago
func purgeUsers() {

	for k, v := range identifiers {
		purgeTime := time.Now().Add(-PurgeInterval)
		if v.Before(purgeTime) {
			delete(identifiers, k)
		}
	}

	time.AfterFunc(time.Second*60, purgeUsers)

	//	fmt.Printf("Purged users:%d", UserCount())
}
<commit_msg>Added mutex to stats package<commit_after>package stats

import (
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/http"
	"strings"
	"sync"
	"time"
)

// Put this in a separate package called stats

// PurgeInterval is the interval at which users are purged from the current list
var PurgeInterval = time.Minute * 5

// identifiers holds a hash of anonymised user records
// obviously an in-memory store is not suitable for very large sites
// but for smaller sites with a few hundred concurrent users it's fine
var identifiers = make(map[string]time.Time)
var mu sync.RWMutex

// RegisterHit registers a hit and ups user count if required
func RegisterHit(r *http.Request) {

	// Use UA as well as ip for unique values per browser session
	ua := r.Header.Get("User-Agent")
	// Ignore obvious bots (Googlebot etc)
	if strings.Contains(ua, "bot") {
		return
	}
	// Ignore requests for xml (assumed to be feeds or sitemap)
	if strings.HasSuffix(r.URL.Path, ".xml") {
		return
	}

	// Extract the IP from the address
	ip := r.RemoteAddr
	forward := r.Header.Get("X-Forwarded-For")
	if len(forward) > 0 {
		ip = forward
	}

	// Hash for anonymity in our store
	hasher := sha1.New()
	hasher.Write([]byte(ip))
	hasher.Write([]byte(ua))
	id := base64.URLEncoding.EncodeToString(hasher.Sum(nil))

	// Insert the entry with current time
	mu.Lock()
	identifiers[id] = time.Now()
	mu.Unlock()
}

// HandleUserCount serves a get request at /stats/users/count
func HandleUserCount(w http.ResponseWriter, r *http.Request) error {

	// Render json of our count for the javascript to display
	mu.RLock()
	json := fmt.Sprintf("{\"users\":%d}", len(identifiers))
	mu.RUnlock()
	_, err := w.Write([]byte(json))
	return err
}

// UserCount returns a count of users in the last 5 minutes
func UserCount() int {
	mu.RLock()
	defer mu.RUnlock()
	return len(identifiers)
}

// Clean up users list at intervals
func init() {
	purgeUsers()
}

// purgeUsers clears the users list of users who last acted PurgeInterval ago
func purgeUsers() {

	mu.Lock()
	for k, v := range identifiers {
		purgeTime := time.Now().Add(-PurgeInterval)
		if v.Before(purgeTime) {
			delete(identifiers, k)
		}
	}
	mu.Unlock()

	time.AfterFunc(time.Second*60, purgeUsers)

	//	fmt.Printf("Purged users:%d", UserCount())
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"fmt"
	"os"
	"regexp"
	"strings"

	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

func targetList() []string {
	_ = project.Initialize()
	targetNames := []string{}
	for name, _ := range target.GetTargets() {
		// Don't display the special unittest target; this is used
		// internally by newt, so the user doesn't need to know about it.
		// XXX: This is a hack; come up with a better solution for unit
		// testing.
		if !strings.HasSuffix(name, "/unittest") {
			targetNames = append(targetNames, strings.TrimPrefix(name, "targets/"))
		}
	}
	return targetNames
}

/* return a list of all packages */
func packageList() []string {
	var list []string
	for _, repoHash := range project.GetProject().PackageList() {
		for _, pack := range *repoHash {
			lclPack := pack.(*pkg.LocalPackage)

			if pkgIsTestable(lclPack) {
				list = append(list, lclPack.FullName())
			}
		}
	}
	return list
}

func isValueInList(value string, list []string) int {
	for i, v := range list {
		if v == value {
			return i
		}
	}
	return -1
}

func completeRunCmd(cmd *cobra.Command, args []string) {
	cmd_line := os.Getenv("COMP_LINE")

	if cmd_line == "" {
		fmt.Println("This command is intended to be used as part of " +
			" bash autocomplete.  Its not intended to be called directly from " +
			" the command line ")
		return
	}

	root_cmd := cmd.Root()

	args = strings.Split(cmd_line, " ")
	found_cmd, _, _ := root_cmd.Find(args[1:])
	if found_cmd == nil {
		return
	}

	/* this is worth a long comment.  We have to find a command line
	 * with the flags removed.  To do this, I look at the command
	 * path for the command without flags, and remove anything that
	 * doesn't match */
	found_args := strings.Split(found_cmd.CommandPath(), " ")
	last_arg := found_args[len(found_args)-1]

	/* what is remaining after the last parsed argument */
	ind := strings.Index(cmd_line, last_arg)
	ind += len(last_arg)
	extra_str := cmd_line[ind:]

	if len(extra_str) == 0 {
		/* this matched an exact command with no space afterwards.  There
		 * is no autocomplete except this command (to add a space) */
		fmt.Println(found_cmd.Name())
		return
	}

	/* skip flags for now. This just removes them */
	/* skip over complete flags. So the current bash autocomplete will
	 * not complete flags */
	cmd.Flags().VisitAll(func(flag *pflag.Flag) {
		flg := fmt.Sprintf("--%s", flag.Name)
		if flag.Value.Type() == "bool" {
			/* skip the flag */
			r := regexp.MustCompile(flg + "[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		} else if flag.Value.Type() == "string" {
			/* skip the string and the next word */
			r := regexp.MustCompile(flg + "[\\W]+[^\\W]+[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		}

		sflg := fmt.Sprintf("-%s", flag.Shorthand)
		if flag.Value.Type() == "bool" {
			/* skip the flag */
			r := regexp.MustCompile(sflg + "[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		} else if flag.Value.Type() == "string" {
			/* skip the string and the next word */
			r := regexp.MustCompile(sflg + "[\\W]+[^\\W]+[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		}
	})

	if len(extra_str) == 0 {
		/* this matched an exact command with no space afterwards.  There
		 * is no autocomplete except this command (to add a space) */
		return
	}

	extra_str = strings.TrimLeft(extra_str, " ")

	/* give flag hints if the person asks for them */
	showShort := strings.HasPrefix(extra_str, "-") &&
		!strings.HasPrefix(extra_str, "--")

	showLong := strings.HasPrefix(extra_str, "--") ||
		extra_str == "-"

	if showLong {
		r := regexp.MustCompile("^--[^\\W]+")
		partial_flag := r.FindString(extra_str)
		cmd.Flags().VisitAll(func(flag *pflag.Flag) {
			flg := fmt.Sprintf("--%s", flag.Name)
			if strings.HasPrefix(flg, partial_flag) {
				fmt.Println(flg)
			}
		})
	}

	if showShort {
		r := regexp.MustCompile("^-[^\\W]+")
		partial_flag := r.FindString(extra_str)
		cmd.Flags().VisitAll(func(flag *pflag.Flag) {
			if len(flag.Shorthand) > 0 {
				flg := fmt.Sprintf("-%s", flag.Shorthand)
				if strings.HasPrefix(flg, partial_flag) {
					fmt.Println(flg)
				}
			}
		})
	}

	/* dump out valid arguments */
	for _, c := range found_cmd.ValidArgs {
		if strings.HasPrefix(c, extra_str) {
			fmt.Printf("%s\n", c)
		}
	}

	/* dump out possible sub commands */
	for _, child_cmd := range found_cmd.Commands() {
		if strings.HasPrefix(child_cmd.Name(), extra_str) {
			fmt.Printf("%s\n", child_cmd.Name())
		}
	}
}

func AddCompleteCommands(cmd *cobra.Command) {
	completeShortHelp := "Performs Bash Autocompletion (-C)"

	completeLongHelp := completeShortHelp + ".\n\n" +
		" this command reads environment variables COMP_LINE and COMP_POINT " +
		" and will send completion options out stdout as one option per line  "

	completeCmd := &cobra.Command{
		Use:   "complete",
		Short: completeShortHelp,
		Long:  completeLongHelp,
		Run:   completeRunCmd,
	}

	/* silence errors on the complete command because we have partial flags */
	completeCmd.SilenceErrors = true
	cmd.AddCommand(completeCmd)
}
<commit_msg>MYNEWT-126<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"fmt"
	"os"
	"regexp"
	"strings"

	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

func targetList() []string {
	err := project.Initialize()

	targetNames := []string{}

	if err != nil {
		return targetNames
	}

	for name, _ := range target.GetTargets() {
		// Don't display the special unittest target; this is used
		// internally by newt, so the user doesn't need to know about it.
		// XXX: This is a hack; come up with a better solution for unit
		// testing.
		if !strings.HasSuffix(name, "/unittest") {
			targetNames = append(targetNames, strings.TrimPrefix(name, "targets/"))
		}
	}
	return targetNames
}

/* return a list of all packages */
func packageList() []string {

	err := project.Initialize()

	var list []string

	if err != nil {
		return list
	}
	for _, repoHash := range project.GetProject().PackageList() {
		for _, pack := range *repoHash {
			lclPack := pack.(*pkg.LocalPackage)

			if pkgIsTestable(lclPack) {
				list = append(list, lclPack.FullName())
			}
		}
	}
	return list
}

func isValueInList(value string, list []string) int {
	for i, v := range list {
		if v == value {
			return i
		}
	}
	return -1
}

func completeRunCmd(cmd *cobra.Command, args []string) {
	cmd_line := os.Getenv("COMP_LINE")

	if cmd_line == "" {
		fmt.Println("This command is intended to be used as part of " +
			" bash autocomplete.  Its not intended to be called directly from " +
			" the command line ")
		return
	}

	root_cmd := cmd.Root()

	args = strings.Split(cmd_line, " ")
	found_cmd, _, _ := root_cmd.Find(args[1:])
	if found_cmd == nil {
		return
	}

	/* this is worth a long comment.  We have to find a command line
	 * with the flags removed.  To do this, I look at the command
	 * path for the command without flags, and remove anything that
	 * doesn't match */
	found_args := strings.Split(found_cmd.CommandPath(), " ")
	last_arg := found_args[len(found_args)-1]

	/* what is remaining after the last parsed argument */
	ind := strings.Index(cmd_line, last_arg)
	ind += len(last_arg)
	extra_str := cmd_line[ind:]

	if len(extra_str) == 0 {
		/* this matched an exact command with no space afterwards.  There
		 * is no autocomplete except this command (to add a space) */
		fmt.Println(found_cmd.Name())
		return
	}

	/* skip flags for now. This just removes them */
	/* skip over complete flags. So the current bash autocomplete will
	 * not complete flags */
	cmd.Flags().VisitAll(func(flag *pflag.Flag) {
		flg := fmt.Sprintf("--%s", flag.Name)
		if flag.Value.Type() == "bool" {
			/* skip the flag */
			r := regexp.MustCompile(flg + "[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		} else if flag.Value.Type() == "string" {
			/* skip the string and the next word */
			r := regexp.MustCompile(flg + "[\\W]+[^\\W]+[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		}

		sflg := fmt.Sprintf("-%s", flag.Shorthand)
		if flag.Value.Type() == "bool" {
			/* skip the flag */
			r := regexp.MustCompile(sflg + "[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		} else if flag.Value.Type() == "string" {
			/* skip the string and the next word */
			r := regexp.MustCompile(sflg + "[\\W]+[^\\W]+[\\W]+")
			extra_str = r.ReplaceAllString(extra_str, "")
		}
	})

	if len(extra_str) == 0 {
		/* this matched an exact command with no space afterwards.  There
		 * is no autocomplete except this command (to add a space) */
		return
	}

	extra_str = strings.TrimLeft(extra_str, " ")

	/* give flag hints if the person asks for them */
	showShort := strings.HasPrefix(extra_str, "-") &&
		!strings.HasPrefix(extra_str, "--")

	showLong := strings.HasPrefix(extra_str, "--") ||
		extra_str == "-"

	if showLong {
		r := regexp.MustCompile("^--[^\\W]+")
		partial_flag := r.FindString(extra_str)
		cmd.Flags().VisitAll(func(flag *pflag.Flag) {
			flg := fmt.Sprintf("--%s", flag.Name)
			if strings.HasPrefix(flg, partial_flag) {
				fmt.Println(flg)
			}
		})
	}

	if showShort {
		r := regexp.MustCompile("^-[^\\W]+")
		partial_flag := r.FindString(extra_str)
		cmd.Flags().VisitAll(func(flag *pflag.Flag) {
			if len(flag.Shorthand) > 0 {
				flg := fmt.Sprintf("-%s", flag.Shorthand)
				if strings.HasPrefix(flg, partial_flag) {
					fmt.Println(flg)
				}
			}
		})
	}

	/* dump out valid arguments */
	for _, c := range found_cmd.ValidArgs {
		if strings.HasPrefix(c, extra_str) {
			fmt.Printf("%s\n", c)
		}
	}

	/* dump out possible sub commands */
	for _, child_cmd := range found_cmd.Commands() {
		if strings.HasPrefix(child_cmd.Name(), extra_str) {
			fmt.Printf("%s\n", child_cmd.Name())
		}
	}
}

func AddCompleteCommands(cmd *cobra.Command) {
	completeShortHelp := "Performs Bash Autocompletion (-C)"

	completeLongHelp := completeShortHelp + ".\n\n" +
		" this command reads environment variables COMP_LINE and COMP_POINT " +
		" and will send completion options out stdout as one option per line  "

	completeCmd := &cobra.Command{
		Use:   "complete",
		Short: completeShortHelp,
		Long:  completeLongHelp,
		Run:   completeRunCmd,
	}

	/* silence errors on the complete command because we have partial flags */
	completeCmd.SilenceErrors = true
	cmd.AddCommand(completeCmd)
}
<|endoftext|>


<commit_before>package main

import (
	"golang.org/x/net/context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	// Google App Engine
	"google.golang.org/appengine/aetest"

	// Request routing
	"github.com/gorilla/mux"
)

type TestHandler struct {
	t *testing.T

	// The HTTP router to be tested.
	router func() *mux.Router

	ctx context.Context
}

// Build an HTTP request, pass it to the HTTP handler, and return the response.
func (handler TestHandler) request(method, path string, headers map[string]string) TestResponse {
	instance, err := aetest.NewInstance(nil)
	if err != nil {
		handler.t.Fatalf("Failed to create instance: %v", err)
	}
	defer instance.Close()

	request, err := instance.NewRequest(method, path, nil)
	if err != nil {
		handler.t.Fatal(err)
	}

	// Set request headers, if any.
	for header, value := range headers {
		request.Header.Set(header, value)
	}

	// Set an arbitrary remote address for logging purposes, etc.
	request.RemoteAddr = "1.2.3.4:80"

	response := httptest.NewRecorder()
	handler.router().ServeHTTP(response, request)
	return TestResponse{handler.t, response}
}

// Make a GET request to the HTTP handler, and return the response.
func (handler TestHandler) Get(path string, headers map[string]string) TestResponse {
	return handler.request(http.MethodGet, path, headers)
}

// Make a POST request to the HTTP handler, and return the response.
func (handler TestHandler) Post(path string, headers map[string]string) TestResponse {
	return handler.request(http.MethodPost, path, headers)
}

type TestResponse struct {
	t *testing.T

	// The HTTP response being asserted against.
	r *httptest.ResponseRecorder
}

// Ensure that the response contains the expected status code.
func (response TestResponse) AssertStatusEquals(expected int) {
	if response.r.Code != expected {
		response.t.Errorf(
			"Handler returned unexpected status code: got `%v` want `%v`",
			response.r.Code, expected)
	}
}

// Ensure that the response body is exactly as expected.
func (response TestResponse) AssertBodyEquals(expected string) {
	if actual := response.r.Body.String(); actual != expected {
		response.t.Errorf(
			"Handler returned unexpected body: got `%v` want `%v`",
			actual, expected)
	}
}

// Ensure that the response body contains a substring.
func (response TestResponse) AssertBodyContains(substr string) {
	if actual := response.r.Body.String(); !strings.Contains(actual, substr) {
		response.t.Errorf(
			"Handler returned unexpected body: did not find `%v` in `%v`",
			substr, actual)
	}
}

// Ensure that the response contains a specific header.
func (response TestResponse) AssertHeaderExists(header string) {
	if _, ok := response.r.Header()[header]; !ok {
		response.t.Errorf(
			"Handler did not set header `%v`",
			header)
	}
}

// Ensure that the response contains a specific header-value pair.
func (response TestResponse) AssertHeaderContains(header, expected string) {
	response.AssertHeaderExists(header)
	actuals, _ := response.r.Header()[header]
	for _, actual := range actuals {
		if actual == expected {
			return
		}
	}

	response.t.Errorf(
		"Handler returned unexpected %v: got `%v` want `%v`",
		header, actuals, expected)
}

func TestGetIndex(t *testing.T) {
	ctx, done, err := aetest.NewContext()
	if err != nil {
		t.Fatal(err)
	}
	defer done()

	response := TestHandler{t, Router, ctx}.Get("/", nil)
	response.AssertStatusEquals(http.StatusOK)
	response.AssertBodyEquals("1.2.3.4\n")
	response.AssertHeaderContains("Content-Type", "text/plain; charset=UTF-8")
}

func TestGetInvalidUrl(t *testing.T) {
	ctx, done, err := aetest.NewContext()
	if err != nil {
		t.Fatal(err)
	}
	defer done()

	response := TestHandler{t, Router, ctx}.Get("/non-existant", nil)
	response.AssertStatusEquals(http.StatusNotFound)
	response.AssertBodyEquals("404 Not Found\n")
	response.AssertHeaderContains("Content-Type", "text/plain; charset=UTF-8")
}
<commit_msg>Add specific error messages<commit_after>package main

import (
	"golang.org/x/net/context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	// Google App Engine
	"google.golang.org/appengine/aetest"

	// Request routing
	"github.com/gorilla/mux"
)

type TestHandler struct {
	t *testing.T

	// The HTTP router to be tested.
	router func() *mux.Router

	ctx context.Context
}

// Build an HTTP request, pass it to the HTTP handler, and return the response.
func (handler TestHandler) request(method, path string, headers map[string]string) TestResponse {
	instance, err := aetest.NewInstance(nil)
	if err != nil {
		handler.t.Fatalf("Failed to create instance: %v", err)
	}
	defer instance.Close()

	request, err := instance.NewRequest(method, path, nil)
	if err != nil {
		handler.t.Fatalf("Failed to create request: %v", err)
	}

	// Set request headers, if any.
	for header, value := range headers {
		request.Header.Set(header, value)
	}

	// Set an arbitrary remote address for logging purposes, etc.
	request.RemoteAddr = "1.2.3.4:80"

	response := httptest.NewRecorder()
	handler.router().ServeHTTP(response, request)
	return TestResponse{handler.t, response}
}

// Make a GET request to the HTTP handler, and return the response.
func (handler TestHandler) Get(path string, headers map[string]string) TestResponse {
	return handler.request(http.MethodGet, path, headers)
}

// Make a POST request to the HTTP handler, and return the response.
func (handler TestHandler) Post(path string, headers map[string]string) TestResponse {
	return handler.request(http.MethodPost, path, headers)
}

type TestResponse struct {
	t *testing.T

	// The HTTP response being asserted against.
	r *httptest.ResponseRecorder
}

// Ensure that the response contains the expected status code.
func (response TestResponse) AssertStatusEquals(expected int) {
	if response.r.Code != expected {
		response.t.Errorf(
			"Handler returned unexpected status code: got `%v` want `%v`",
			response.r.Code, expected)
	}
}

// Ensure that the response body is exactly as expected.
func (response TestResponse) AssertBodyEquals(expected string) {
	if actual := response.r.Body.String(); actual != expected {
		response.t.Errorf(
			"Handler returned unexpected body: got `%v` want `%v`",
			actual, expected)
	}
}

// Ensure that the response body contains a substring.
func (response TestResponse) AssertBodyContains(substr string) {
	if actual := response.r.Body.String(); !strings.Contains(actual, substr) {
		response.t.Errorf(
			"Handler returned unexpected body: did not find `%v` in `%v`",
			substr, actual)
	}
}

// Ensure that the response contains a specific header.
func (response TestResponse) AssertHeaderExists(header string) {
	if _, ok := response.r.Header()[header]; !ok {
		response.t.Errorf(
			"Handler did not set header `%v`",
			header)
	}
}

// Ensure that the response contains a specific header-value pair.
func (response TestResponse) AssertHeaderContains(header, expected string) {
	response.AssertHeaderExists(header)
	actuals, _ := response.r.Header()[header]
	for _, actual := range actuals {
		if actual == expected {
			return
		}
	}

	response.t.Errorf(
		"Handler returned unexpected %v: got `%v` want `%v`",
		header, actuals, expected)
}

func TestGetIndex(t *testing.T) {
	ctx, done, err := aetest.NewContext()
	if err != nil {
		t.Fatalf("Failed to create context: %v", err)
	}
	defer done()

	response := TestHandler{t, Router, ctx}.Get("/", nil)
	response.AssertStatusEquals(http.StatusOK)
	response.AssertBodyEquals("1.2.3.4\n")
	response.AssertHeaderContains("Content-Type", "text/plain; charset=UTF-8")
}

func TestGetInvalidUrl(t *testing.T) {
	ctx, done, err := aetest.NewContext()
	if err != nil {
		t.Fatalf("Failed to create context: %v", err)
	}
	defer done()

	response := TestHandler{t, Router, ctx}.Get("/non-existant", nil)
	response.AssertStatusEquals(http.StatusNotFound)
	response.AssertBodyEquals("404 Not Found\n")
	response.AssertHeaderContains("Content-Type", "text/plain; charset=UTF-8")
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/go-graphite/carbonapi/expr/types"
	pb "github.com/go-graphite/carbonzipper/carbonzipperpb3"
	realZipper "github.com/go-graphite/carbonzipper/zipper"
	"github.com/lomik/zapwriter"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
)

type mockCarbonZipper struct {
	z *realZipper.Zipper

	logger      *zap.Logger
	statsSender func(*realZipper.Stats)
}

func newMockCarbonZipper() *mockCarbonZipper {
	z := &mockCarbonZipper{}

	return z
}

func (z mockCarbonZipper) Find(ctx context.Context, metric string) (pb.GlobResponse, error) {
	return getGlobResponse(), nil
}

func (z mockCarbonZipper) Info(ctx context.Context, metric string) (map[string]pb.InfoResponse, error) {
	response := getMockInfoResponse()

	return response, nil
}

func (z mockCarbonZipper) Render(ctx context.Context, metric string, from, until int32) ([]*types.MetricData, error) {
	var result []*types.MetricData
	multiFetchResponse := getMultiFetchResponse()
	result = append(result, &types.MetricData{FetchResponse: multiFetchResponse.Metrics[0]})
	return result, nil
}

func getGlobResponse() pb.GlobResponse {
	globMtach := pb.GlobMatch{Path: "foo.bar", IsLeaf: true}
	var matches []pb.GlobMatch
	matches = append(matches, globMtach)
	globResponse := pb.GlobResponse{
		Name:    "foo.bar",
		Matches: matches,
	}
	return globResponse
}

func getMultiFetchResponse() pb.MultiFetchResponse {
	mfr := pb.FetchResponse{
		Name:      "foo.bar",
		StartTime: 1510913280,
		StopTime:  1510913880,
		StepTime:  60,
		Values:    []float64{0, 1510913759, 1510913818},
		IsAbsent:  []bool{true, false, false},
	}

	result := pb.MultiFetchResponse{Metrics: []pb.FetchResponse{mfr}}
	return result
}

func getMockInfoResponse() map[string]pb.InfoResponse {
	decoded := make(map[string]pb.InfoResponse)
	r := pb.Retention{
		SecondsPerPoint: 60,
		NumberOfPoints:  43200,
	}
	d := pb.InfoResponse{
		Name:              "foo.bar",
		AggregationMethod: "Average",
		MaxRetention:      157680000,
		XFilesFactor:      0.5,
		Retentions:        []pb.Retention{r},
	}
	decoded["http://127.0.0.1:8080"] = d
	return decoded
}

func init() {
	logger := zapwriter.Logger("main")

	setUpViper(logger)
	setUpConfigUpstreams(logger)
	setUpConfig(logger, newMockCarbonZipper())
	initHandlers()
}

func setUpRequest(t *testing.T, url string) (*http.Request, *httptest.ResponseRecorder) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatal(err)
	}

	// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
	rr := httptest.NewRecorder()
	return req, rr
}

func TestRenderHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/render/?target=fallbackSeries(foo.bar,foo.baz)&from=-10minutes&format=json")
	renderHandler(rr, req)

	expected := `[{"target":"foo.bar","datapoints":[[null,1510913280],[1510913759,1510913340],[1510913818,1510913400]]}]`

	// Check the status code is what we expect.
	assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	assert.Equal(t, expected, rr.Body.String(), "Http response should be same.")
}

func TestFindHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/metrics/find/?query=foo.bar&format=json")
	findHandler(rr, req)

	body := rr.Body.String()
	expected := `[{"allowChildren":0,"expandable":0,"leaf":1,"id":"foo.bar","text":"bar","context":{}}]` + "\n"
	assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	assert.Equal(t, expected, body, "Http response should be same.")
}

func TestInfoHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/info/?target=foo.bar&format=json")
	infoHandler(rr, req)

	body := rr.Body.String()
	expected := getMockInfoResponse()
	expectedJson, err := json.Marshal(expected)
	assert.Nil(t, err)

	assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	assert.Equal(t, string(expectedJson), body, "Http response should be same.")
}
<commit_msg>Verbose test output for main<commit_after>package main

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/go-graphite/carbonapi/expr/types"
	pb "github.com/go-graphite/carbonzipper/carbonzipperpb3"
	realZipper "github.com/go-graphite/carbonzipper/zipper"
	"github.com/lomik/zapwriter"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
)

type mockCarbonZipper struct {
	z *realZipper.Zipper

	logger      *zap.Logger
	statsSender func(*realZipper.Stats)
}

func newMockCarbonZipper() *mockCarbonZipper {
	z := &mockCarbonZipper{}

	return z
}

func (z mockCarbonZipper) Find(ctx context.Context, metric string) (pb.GlobResponse, error) {
	return getGlobResponse(), nil
}

func (z mockCarbonZipper) Info(ctx context.Context, metric string) (map[string]pb.InfoResponse, error) {
	response := getMockInfoResponse()

	return response, nil
}

func (z mockCarbonZipper) Render(ctx context.Context, metric string, from, until int32) ([]*types.MetricData, error) {
	var result []*types.MetricData
	multiFetchResponse := getMultiFetchResponse()
	result = append(result, &types.MetricData{FetchResponse: multiFetchResponse.Metrics[0]})
	return result, nil
}

func getGlobResponse() pb.GlobResponse {
	globMtach := pb.GlobMatch{Path: "foo.bar", IsLeaf: true}
	var matches []pb.GlobMatch
	matches = append(matches, globMtach)
	globResponse := pb.GlobResponse{
		Name:    "foo.bar",
		Matches: matches,
	}
	return globResponse
}

func getMultiFetchResponse() pb.MultiFetchResponse {
	mfr := pb.FetchResponse{
		Name:      "foo.bar",
		StartTime: 1510913280,
		StopTime:  1510913880,
		StepTime:  60,
		Values:    []float64{0, 1510913759, 1510913818},
		IsAbsent:  []bool{true, false, false},
	}

	result := pb.MultiFetchResponse{Metrics: []pb.FetchResponse{mfr}}
	return result
}

func getMockInfoResponse() map[string]pb.InfoResponse {
	decoded := make(map[string]pb.InfoResponse)
	r := pb.Retention{
		SecondsPerPoint: 60,
		NumberOfPoints:  43200,
	}
	d := pb.InfoResponse{
		Name:              "foo.bar",
		AggregationMethod: "Average",
		MaxRetention:      157680000,
		XFilesFactor:      0.5,
		Retentions:        []pb.Retention{r},
	}
	decoded["http://127.0.0.1:8080"] = d
	return decoded
}

func init() {
	cfg := defaultLoggerConfig
	cfg.Level = "debug"
	zapwriter.ApplyConfig([]zapwriter.Config{cfg})
	logger := zapwriter.Logger("main")

	setUpViper(logger)
	setUpConfigUpstreams(logger)
	setUpConfig(logger, newMockCarbonZipper())
	initHandlers()
}

func setUpRequest(t *testing.T, url string) (*http.Request, *httptest.ResponseRecorder) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatal(err)
	}

	// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
	rr := httptest.NewRecorder()
	return req, rr
}

func TestRenderHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/render/?target=fallbackSeries(foo.bar,foo.baz)&from=-10minutes&format=json")
	renderHandler(rr, req)

	expected := `[{"target":"foo.bar","datapoints":[[null,1510913280],[1510913759,1510913340],[1510913818,1510913400]]}]`

	// Check the status code is what we expect.
	r := assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	if !r {
		t.Error("HttpStatusCode should be 200 OK.")
	}
	r = assert.Equal(t, expected, rr.Body.String(), "Http response should be same.")
	if !r {
		t.Error("Http response should be same.")
	}
}

func TestFindHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/metrics/find/?query=foo.bar&format=json")
	findHandler(rr, req)

	body := rr.Body.String()
	expected := `[{"allowChildren":0,"expandable":0,"leaf":1,"id":"foo.bar","text":"bar","context":{}}]` + "\n"
	r := assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	if !r {
		t.Error("HttpStatusCode should be 200 OK.")
	}
	r = assert.Equal(t, expected, body, "Http response should be same.")
	if !r {
		t.Error("Http response should be same.")
	}
}

func TestInfoHandler(t *testing.T) {
	req, rr := setUpRequest(t, "/info/?target=foo.bar&format=json")
	infoHandler(rr, req)

	body := rr.Body.String()
	expected := getMockInfoResponse()
	expectedJson, err := json.Marshal(expected)
	r := assert.Nil(t, err)
	if !r {
		t.Errorf("err should be nil, %v instead", err)
	}

	r = assert.Equal(t, rr.Code, http.StatusOK, "HttpStatusCode should be 200 OK.")
	if !r {
		t.Error("Http response should be same.")
	}
	r = assert.Equal(t, string(expectedJson), body, "Http response should be same.")
	if !r {
		t.Error("Http response should be same.")
	}
}
<|endoftext|>


<commit_before>package manifest

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"strings"

	"gopkg.in/yaml.v2"
)

var yamlSeperator = []byte("\n---\n")

type MappingResult struct {
	Name string
	Kind string
	Content string
}

type metadata struct {
	ApiVersion string `yaml:"apiVersion"`
	Kind       string
	Metadata   struct {
		Name string
	}
}

func (m metadata) String() string {
	return fmt.Sprintf("%s, %s (%s)", m.Metadata.Name, m.Kind, m.ApiVersion)
}

func scanYamlSpecs(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	if i := bytes.Index(data, yamlSeperator); i >= 0 {
		// We have a full newline-terminated line.
		return i + len(yamlSeperator), data[0:i], nil
	}
	// If we're at EOF, we have a final, non-terminated line. Return it.
	if atEOF {
		return len(data), data, nil
	}
	// Request more data.
	return 0, nil, nil
}

func splitSpec(token string) (string, string) {
	if i := strings.Index(token, "\n"); i >= 0 {
		return token[0:i], token[i+1:]
	}
	return "", ""
}

func Parse(manifest string) map[string]*MappingResult {
	scanner := bufio.NewScanner(strings.NewReader(manifest))
	scanner.Split(scanYamlSpecs)
	//Allow for tokens (specs) up to 1M in size
	scanner.Buffer(make([]byte, bufio.MaxScanTokenSize), 1048576)
	//Discard the first result, we only care about everything after the first seperator
	scanner.Scan()

	result := make(map[string]*MappingResult)

	for scanner.Scan() {
		content := scanner.Text()
		if strings.TrimSpace(content) == "" {
			continue
		}
		var metadata metadata
		if err := yaml.Unmarshal([]byte(content), &metadata); err != nil {
			log.Fatalf("YAML unmarshal error: %s\nCan't unmarshal %s", err, content)
		}
		name := metadata.String()
		if _, ok := result[name]; ok {
			log.Println("Error: Found duplicate key %#v in manifest", name)
		} else {
			result[name] = &MappingResult{
				Name: name,
				Kind: metadata.Kind,
				Content: content,
			}
		}
	}
	return result

}
<commit_msg>fix error log<commit_after>package manifest

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"strings"

	"gopkg.in/yaml.v2"
)

var yamlSeperator = []byte("\n---\n")

type MappingResult struct {
	Name    string
	Kind    string
	Content string
}

type metadata struct {
	ApiVersion string `yaml:"apiVersion"`
	Kind       string
	Metadata   struct {
		Name string
	}
}

func (m metadata) String() string {
	return fmt.Sprintf("%s, %s (%s)", m.Metadata.Name, m.Kind, m.ApiVersion)
}

func scanYamlSpecs(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	if i := bytes.Index(data, yamlSeperator); i >= 0 {
		// We have a full newline-terminated line.
		return i + len(yamlSeperator), data[0:i], nil
	}
	// If we're at EOF, we have a final, non-terminated line. Return it.
	if atEOF {
		return len(data), data, nil
	}
	// Request more data.
	return 0, nil, nil
}

func splitSpec(token string) (string, string) {
	if i := strings.Index(token, "\n"); i >= 0 {
		return token[0:i], token[i+1:]
	}
	return "", ""
}

func Parse(manifest string) map[string]*MappingResult {
	scanner := bufio.NewScanner(strings.NewReader(manifest))
	scanner.Split(scanYamlSpecs)
	//Allow for tokens (specs) up to 1M in size
	scanner.Buffer(make([]byte, bufio.MaxScanTokenSize), 1048576)
	//Discard the first result, we only care about everything after the first seperator
	scanner.Scan()

	result := make(map[string]*MappingResult)

	for scanner.Scan() {
		content := scanner.Text()
		if strings.TrimSpace(content) == "" {
			continue
		}
		var metadata metadata
		if err := yaml.Unmarshal([]byte(content), &metadata); err != nil {
			log.Fatalf("YAML unmarshal error: %s\nCan't unmarshal %s", err, content)
		}
		name := metadata.String()
		if _, ok := result[name]; ok {
			log.Printf("Error: Found duplicate key %#v in manifest", name)
		} else {
			result[name] = &MappingResult{
				Name:    name,
				Kind:    metadata.Kind,
				Content: content,
			}
		}
	}
	return result

}
<|endoftext|>


<commit_before>// +build integration

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"testing"

	"regexp"

	"github.com/elliotchance/c2go/util"
)

var (
	cPath  = "build/a.out"
	goPath = "build/go.out"
	stdin  = "7"
	args   = []string{"some", "args"}
)

type programOut struct {
	stdout bytes.Buffer
	stderr bytes.Buffer
	isZero bool
}

// TestIntegrationScripts tests all programs in the tests directory.
//
// Integration tests are not run by default (only unit tests). These are
// indicated by the build flags at the top of the file. To include integration
// tests use:
//
//     go test -tags=integration
//
// You can also run a single file with:
//
//     go test -tags=integration -run=TestIntegrationScripts/tests/ctype/isalnum.c
//
func TestIntegrationScripts(t *testing.T) {
	testFiles, err := filepath.Glob("tests/*.c")
	if err != nil {
		t.Fatal(err)
	}

	exampleFiles, err := filepath.Glob("examples/*.c")
	if err != nil {
		t.Fatal(err)
	}

	files := append(testFiles, exampleFiles...)

	for _, file := range files {
		// Create build folder
		os.Mkdir("build/", os.ModePerm)

		t.Run(file, func(t *testing.T) {
			cProgram := programOut{}
			goProgram := programOut{}

			// Compile C.
			out, err := exec.Command("clang", "-lm", "-o", cPath, file).CombinedOutput()
			if err != nil {
				t.Fatalf("error: %s\n%s", err, out)
			}

			// Run C program
			cmd := exec.Command(cPath, args...)
			cmd.Stdin = strings.NewReader(stdin)
			cmd.Stdout = &cProgram.stdout
			cmd.Stderr = &cProgram.stderr
			err = cmd.Run()
			cProgram.isZero = err == nil

			programArgs := ProgramArgs{
				inputFile:   file,
				outputFile:  "build/main.go",
				packageName: "main",
			}

			// Compile Go
			Start(programArgs)

			buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput()
			if err != nil {
				t.Fatal(string(buildErr), err)
			}

			// Run Go program
			cmd = exec.Command(goPath, args...)
			cmd.Stdin = strings.NewReader(stdin)
			cmd.Stdout = &goProgram.stdout
			cmd.Stderr = &goProgram.stderr
			err = cmd.Run()
			goProgram.isZero = err == nil

			// Check for special exit codes that signal that tests have failed.
			if exitError, ok := err.(*exec.ExitError); ok {
				exitStatus := exitError.Sys().(syscall.WaitStatus).ExitStatus()
				if exitStatus == 101 || exitStatus == 102 {
					t.Fatal(goProgram.stdout.String())
				}
			}

			// Check if both exit codes are zero (or non-zero)
			if cProgram.isZero != goProgram.isZero {
				t.Fatalf("Exit statuses did not match.\n" + util.ShowDiff(cProgram.stdout.String(), goProgram.stdout.String()))
				// t.Fatalf("Expected: %t, Got: %t", cProgram.isZero, goProgram.isZero)
			}

			// Check stderr
			if cProgram.stderr.String() != goProgram.stderr.String() {
				t.Fatalf("Expected %q, Got: %q", cProgram.stderr.String(), goProgram.stderr.String())
			}

			// Check stdout
			if cProgram.stdout.String() != goProgram.stdout.String() {
				t.Fatalf(util.ShowDiff(cProgram.stdout.String(), goProgram.stdout.String()))
			}

			// If this is not an example we will extact the number of tests run.
			if strings.Index(file, "examples/") == -1 {
				firstLine := strings.Split(goProgram.stdout.String(), "\n")[0]

				matches := regexp.MustCompile(`1..(\d+)`).FindStringSubmatch(firstLine)
				if len(matches) == 0 {
					t.Fatalf("Test did not output tap: %s", file)
				}

				fmt.Println(file + " TAP TESTS: " + matches[1])
			}
		})
	}
}
<commit_msg>Fix regexp for TAP output<commit_after>// +build integration

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"testing"

	"regexp"

	"github.com/elliotchance/c2go/util"
)

var (
	cPath  = "build/a.out"
	goPath = "build/go.out"
	stdin  = "7"
	args   = []string{"some", "args"}
)

type programOut struct {
	stdout bytes.Buffer
	stderr bytes.Buffer
	isZero bool
}

// TestIntegrationScripts tests all programs in the tests directory.
//
// Integration tests are not run by default (only unit tests). These are
// indicated by the build flags at the top of the file. To include integration
// tests use:
//
//     go test -tags=integration
//
// You can also run a single file with:
//
//     go test -tags=integration -run=TestIntegrationScripts/tests/ctype/isalnum.c
//
func TestIntegrationScripts(t *testing.T) {
	testFiles, err := filepath.Glob("tests/*.c")
	if err != nil {
		t.Fatal(err)
	}

	exampleFiles, err := filepath.Glob("examples/*.c")
	if err != nil {
		t.Fatal(err)
	}

	files := append(testFiles, exampleFiles...)

	for _, file := range files {
		// Create build folder
		os.Mkdir("build/", os.ModePerm)

		t.Run(file, func(t *testing.T) {
			cProgram := programOut{}
			goProgram := programOut{}

			// Compile C.
			out, err := exec.Command("clang", "-lm", "-o", cPath, file).CombinedOutput()
			if err != nil {
				t.Fatalf("error: %s\n%s", err, out)
			}

			// Run C program
			cmd := exec.Command(cPath, args...)
			cmd.Stdin = strings.NewReader(stdin)
			cmd.Stdout = &cProgram.stdout
			cmd.Stderr = &cProgram.stderr
			err = cmd.Run()
			cProgram.isZero = err == nil

			programArgs := ProgramArgs{
				inputFile:   file,
				outputFile:  "build/main.go",
				packageName: "main",
			}

			// Compile Go
			Start(programArgs)

			buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput()
			if err != nil {
				t.Fatal(string(buildErr), err)
			}

			// Run Go program
			cmd = exec.Command(goPath, args...)
			cmd.Stdin = strings.NewReader(stdin)
			cmd.Stdout = &goProgram.stdout
			cmd.Stderr = &goProgram.stderr
			err = cmd.Run()
			goProgram.isZero = err == nil

			// Check for special exit codes that signal that tests have failed.
			if exitError, ok := err.(*exec.ExitError); ok {
				exitStatus := exitError.Sys().(syscall.WaitStatus).ExitStatus()
				if exitStatus == 101 || exitStatus == 102 {
					t.Fatal(goProgram.stdout.String())
				}
			}

			// Check if both exit codes are zero (or non-zero)
			if cProgram.isZero != goProgram.isZero {
				t.Fatalf("Exit statuses did not match.\n" + util.ShowDiff(cProgram.stdout.String(), goProgram.stdout.String()))
				// t.Fatalf("Expected: %t, Got: %t", cProgram.isZero, goProgram.isZero)
			}

			// Check stderr
			if cProgram.stderr.String() != goProgram.stderr.String() {
				t.Fatalf("Expected %q, Got: %q", cProgram.stderr.String(), goProgram.stderr.String())
			}

			// Check stdout
			if cProgram.stdout.String() != goProgram.stdout.String() {
				t.Fatalf(util.ShowDiff(cProgram.stdout.String(), goProgram.stdout.String()))
			}

			// If this is not an example we will extact the number of tests run.
			if strings.Index(file, "examples/") == -1 {
				firstLine := strings.Split(goProgram.stdout.String(), "\n")[0]

				matches := regexp.MustCompile(`1\.\.(\d+)`).
					FindStringSubmatch(firstLine)
				if len(matches) == 0 {
					t.Fatalf("Test did not output tap: %s", file)
				}

				fmt.Println(file + " TAP TESTS: " + matches[1])
			}
		})
	}
}
<|endoftext|>