<commit_before>package market

import (
	"errors"
	"fmt"
	"regexp"
	"sort"
	"time"

	"github.com/guotie/gogb2312"
	"github.com/nzai/stockrecorder/io"
)

//	中国证券市场
type China struct{}

func (m China) Name() string {
	return "China"
}

func (m China) Timezone() string {
	return "Asia/Shanghai"
}

//	更新上市公司列表
func (m China) Companies() ([]Company, error) {

	companies := make([]Company, 0)

	//	上海证券交易所
	sh, err := m.shanghaiCompanies()
	if err != nil {
		return nil, err
	}
	companies = append(companies, sh...)

	//	深圳证券交易所
	sz, err := m.shenzhenCompanies()
	if err != nil {
		return nil, err
	}
	companies = append(companies, sz...)

	//	按Code排序
	sort.Sort(CompanyList(companies))

	return companies, nil
}

//	上海证券交易所上市公司
func (m China) shanghaiCompanies() ([]Company, error) {

	urls := [...]string{
		"http://query.sse.com.cn/commonQuery.do?isPagination=false&sqlId=COMMON_SSE_ZQPZ_GPLB_MCJS_SSAG_L",
		"http://query.sse.com.cn/commonQuery.do?isPagination=false&sqlId=COMMON_SSE_ZQPZ_GPLB_MCJS_SSBG_L",
	}
	referer := "http://www.sse.com.cn/assortment/stock/list/name/"

	list := make([]Company, 0)
	for _, url := range urls {

		//	尝试从网络获取实时上市公司列表
		json, err := io.DownloadStringRefererRetry(url, referer, retryTimes, retryIntervalSeconds)
		if err != nil {
			return nil, err
		}

		//	解析json
		companies, err := m.parseShanghaiJson(json)
		if err != nil {
			return nil, err
		}

		list = append(list, companies...)
	}

	return list, nil
}

//	解析上海证券交易所上市公司
func (m China) parseShanghaiJson(json string) ([]Company, error) {

	//  使用正则分析json
	regex := regexp.MustCompile(`"PRODUCTNAME":"([^"]*?)","PRODUCTID":"(\d{6})"`)
	group := regex.FindAllStringSubmatch(json, -1)

	companies := make([]Company, 0)
	for _, section := range group {
		//log.Printf("%s\t%s\n", section[2], section[1])
		companies = append(companies, Company{Code: section[2], Name: section[1]})
	}

	if len(companies) == 0 {
		return nil, errors.New(fmt.Sprintf("错误的上海证券交易所上市公司列表内容:%s", json))
	}

	return companies, nil
}

//	深圳证券交易所上市公司
func (m China) shenzhenCompanies() ([]Company, error) {
	urls := [...]string{
		"http://www.szse.cn/szseWeb/FrontController.szse?ACTIONID=8&CATALOGID=1110&tab1PAGENUM=1&ENCODE=1&TABKEY=tab1",
	}

	list := make([]Company, 0)
	for _, url := range urls {

		//	尝试从网络获取实时上市公司列表
		html, err := io.DownloadStringRetry(url, retryTimes, retryIntervalSeconds)
		if err != nil {
			return nil, err
		}

		//	深圳证券交易所的查询结果是GBK编码的，需要转成UTF8
		html, err, _, _ = gogb2312.ConvertGB2312String(html)
		if err != nil {
			return nil, err
		}

		//	解析Html
		companies, err := m.parseShenzhenHtml(html)
		if err != nil {
			return nil, err
		}

		list = append(list, companies...)
	}

	return list, nil
}

//	解析深圳证券交易所上市公司
func (m China) parseShenzhenHtml(html string) ([]Company, error) {
	//  使用正则分析html
	regex := regexp.MustCompile(`align='center' >(\d{6})</td><td  class='cls-data-td'  align='center' >([^<]*?)</td>`)
	group := regex.FindAllStringSubmatch(html, -1)

	companies := make([]Company, 0)
	for _, section := range group {
		companies = append(companies, Company{Code: section[1], Name: section[2]})
	}

	if len(companies) == 0 {
		return nil, errors.New(fmt.Sprintf("错误的深圳证券交易所上市公司列表内容:%s", html))
	}

	return companies, nil
}

//	所有中国上市公司,在雅虎财经查询分时数据时都要带上后缀
var chineseSuffix map[string]string = map[string]string{
	"6": "SS",
	"9": "SS",
	"0": "SZ",
	"2": "SZ",
	"3": "SZ",
}

//	抓取
func (m China) Crawl(market Market, company Company, day time.Time) error {

	suffix, found := chineseSuffix[company.Code[:1]]
	if !found {
		suffix = "SS"
	}

	return DownloadCompanyDaily(market.Name(), company.Code, company.Code+"."+suffix, day)
}
<commit_msg>去除重复的上市公司<commit_after>package market

import (
	"errors"
	"fmt"
	"regexp"
	"sort"
	"time"

	"github.com/guotie/gogb2312"
	"github.com/nzai/stockrecorder/io"
)

//	中国证券市场
type China struct{}

func (m China) Name() string {
	return "China"
}

func (m China) Timezone() string {
	return "Asia/Shanghai"
}

//	更新上市公司列表
func (m China) Companies() ([]Company, error) {

	dict := make(map[string]Company, 0)

	//	上海证券交易所
	sh, err := m.shanghaiCompanies()
	if err != nil {
		return nil, err
	}
	for _, company := range sh {
		//	去重
		if _, found := dict[company.Code]; found {
			continue
		}

		dict[company.Code] = company
	}

	//	深圳证券交易所
	sz, err := m.shenzhenCompanies()
	if err != nil {
		return nil, err
	}
	for _, company := range sz {
		//	去重
		if _, found := dict[company.Code]; found {
			continue
		}

		dict[company.Code] = company
	}

	companies := make([]Company, 0)
	for _, company := range dict {
		companies = append(companies, company)
	}

	//	按Code排序
	sort.Sort(CompanyList(companies))

	return companies, nil
}

//	上海证券交易所上市公司
func (m China) shanghaiCompanies() ([]Company, error) {

	urls := [...]string{
		"http://query.sse.com.cn/commonQuery.do?isPagination=false&sqlId=COMMON_SSE_ZQPZ_GPLB_MCJS_SSAG_L",
		"http://query.sse.com.cn/commonQuery.do?isPagination=false&sqlId=COMMON_SSE_ZQPZ_GPLB_MCJS_SSBG_L",
	}
	referer := "http://www.sse.com.cn/assortment/stock/list/name/"

	list := make([]Company, 0)
	for _, url := range urls {

		//	尝试从网络获取实时上市公司列表
		json, err := io.DownloadStringRefererRetry(url, referer, retryTimes, retryIntervalSeconds)
		if err != nil {
			return nil, err
		}

		//	解析json
		companies, err := m.parseShanghaiJson(json)
		if err != nil {
			return nil, err
		}

		list = append(list, companies...)
	}

	return list, nil
}

//	解析上海证券交易所上市公司
func (m China) parseShanghaiJson(json string) ([]Company, error) {

	//  使用正则分析json
	regex := regexp.MustCompile(`"PRODUCTNAME":"([^"]*?)","PRODUCTID":"(\d{6})"`)
	group := regex.FindAllStringSubmatch(json, -1)

	companies := make([]Company, 0)
	for _, section := range group {
		//log.Printf("%s\t%s\n", section[2], section[1])
		companies = append(companies, Company{Code: section[2], Name: section[1]})
	}

	if len(companies) == 0 {
		return nil, errors.New(fmt.Sprintf("错误的上海证券交易所上市公司列表内容:%s", json))
	}

	return companies, nil
}

//	深圳证券交易所上市公司
func (m China) shenzhenCompanies() ([]Company, error) {
	urls := [...]string{
		"http://www.szse.cn/szseWeb/FrontController.szse?ACTIONID=8&CATALOGID=1110&tab1PAGENUM=1&ENCODE=1&TABKEY=tab1",
	}

	list := make([]Company, 0)
	for _, url := range urls {

		//	尝试从网络获取实时上市公司列表
		html, err := io.DownloadStringRetry(url, retryTimes, retryIntervalSeconds)
		if err != nil {
			return nil, err
		}

		//	深圳证券交易所的查询结果是GBK编码的，需要转成UTF8
		html, err, _, _ = gogb2312.ConvertGB2312String(html)
		if err != nil {
			return nil, err
		}

		//	解析Html
		companies, err := m.parseShenzhenHtml(html)
		if err != nil {
			return nil, err
		}

		list = append(list, companies...)
	}

	return list, nil
}

//	解析深圳证券交易所上市公司
func (m China) parseShenzhenHtml(html string) ([]Company, error) {
	//  使用正则分析html
	regex := regexp.MustCompile(`align='center' >(\d{6})</td><td  class='cls-data-td'  align='center' >([^<]*?)</td>`)
	group := regex.FindAllStringSubmatch(html, -1)

	companies := make([]Company, 0)
	for _, section := range group {
		companies = append(companies, Company{Code: section[1], Name: section[2]})
	}

	if len(companies) == 0 {
		return nil, errors.New(fmt.Sprintf("错误的深圳证券交易所上市公司列表内容:%s", html))
	}

	return companies, nil
}

//	所有中国上市公司,在雅虎财经查询分时数据时都要带上后缀
var chineseSuffix map[string]string = map[string]string{
	"6": "SS",
	"9": "SS",
	"0": "SZ",
	"2": "SZ",
	"3": "SZ",
}

//	抓取
func (m China) Crawl(market Market, company Company, day time.Time) error {

	suffix, found := chineseSuffix[company.Code[:1]]
	if !found {
		suffix = "SS"
	}

	return DownloadCompanyDaily(market.Name(), company.Code, company.Code+"."+suffix, day)
}
<|endoftext|>


<commit_before>package atlas

import (
	"errors"
	"github.com/bndr/gopencils"
	"log"
	"fmt"
)

var (
	allTypes = []string{
		"dns",
		"http",
		"ntp",
		"ping",
		"sslcert",
		"traceroute",
		"wifi",
	}
)

// ErrInvalidMeasurementType is a new error
var ErrInvalidMeasurementType = errors.New("invalid measurement type")

var ErrInvalidAPIKey = errors.New("invalid API key")

// -- private

// checkType verify that the type is valid
func checkType(d Definition) (valid bool) {
	valid = false
	for _, t := range allTypes {
		if d.Type == t {
			valid = true
			break
		}
	}
	return
}

// checkTypeAs is a shortcut
func checkTypeAs(d Definition, t string) (valid bool) {
	valid = true
	if checkType(d) && d.Type != t {
		valid = false
	}
	return
}

// checkAllTypesAs is a generalization of checkTypeAs
func checkAllTypesAs(dl []Definition, t string) (valid bool) {
	valid = true
	for _, d := range dl {
		if d.Type != t {
			valid = false
			break
		}
	}
	return
}

// measurementList is our main answer
type measurementList struct {
	Count    int
	Next     string
	Previous string
	Results  []Measurement
}

// fetch the given resource
func fetchOneMeasurementPage(api *gopencils.Resource, opts map[string]string) (raw *measurementList, err error) {
	r, err := api.Res("measurements", &raw).Get(opts)
	if err != nil {
		log.Printf("err: %v", err)
		err = fmt.Errorf("%v - r:%v\n", err, r)
	}
	//log.Printf(">> rawlist=%+v r=%+v Next=|%s|", rawlist, r, rawlist.Next)
	return
}

// -- public

// GetMeasurement gets info for a single one
func GetMeasurement(id int) (m *Measurement, err error) {
	key, ok := HasAPIKey()
	api := gopencils.Api(apiEndpoint, nil)

	// Add at least one option, the APIkey if present
	var opts map[string]string

	if ok {
		opts["key"] = key
	}

	r, err := api.Res("measurements").Id(id, &m).Get(opts)
	if err != nil {
		err = fmt.Errorf("%v - r:%#v\n", err, r.Raw)
		return
	}
	return
}

// GetMeasurements gets info for a set
func GetMeasurements(opts map[string]string) (m []Measurement, err error) {
	key, ok := HasAPIKey()
	api := gopencils.Api(apiEndpoint, nil)

	// Add at least one option, the APIkey if present
	if ok {
		opts["key"] = key
	}

	rawlist, err := fetchOneMeasurementPage(api, opts)

	// Empty answer
	if rawlist.Count == 0 {
		return nil, fmt.Errorf("empty measurement list")
	}

	var res []Measurement

	res = append(res, rawlist.Results...)
	if rawlist.Next != "" {
		// We have pagination
		for pn := getPageNum(rawlist.Next); rawlist.Next != ""; pn = getPageNum(rawlist.Next) {
			opts["page"] = pn

			rawlist, err = fetchOneMeasurementPage(api, opts)
			if err != nil {
				return
			}

			res = append(res, rawlist.Results...)
		}
	}
	m = res
	return
}

// DNS creates a measurement
func DNS(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "dns") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// HTTP creates a measurement
func HTTP(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "http") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// NTP creates a measurement
func NTP(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "ntp") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Ping creates a measurement
func Ping(d MeasurementRequest) (m *Measurement, err error) {
	if checkTypeAs(d.Definitions[0], "ping") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// SSLCert creates a measurement
func SSLCert(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "sslcert") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Traceroute creates a measurement
func Traceroute(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "traceroute") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Measurement-related methods

// Start is for starting a given measurement
func (m *Measurement) Start(id int) (err error) {
	return nil
}

// Stop is for stopping a given measurement
func (m *Measurement) Stop(id int) (err error) {
	return nil
}
<commit_msg>Simplify checkTypeAs().<commit_after>package atlas

import (
	"errors"
	"github.com/bndr/gopencils"
	"log"
	"fmt"
)

var (
	allTypes = []string{
		"dns",
		"http",
		"ntp",
		"ping",
		"sslcert",
		"traceroute",
		"wifi",
	}
)

// ErrInvalidMeasurementType is a new error
var ErrInvalidMeasurementType = errors.New("invalid measurement type")

var ErrInvalidAPIKey = errors.New("invalid API key")

// -- private

// checkType verify that the type is valid
func checkType(d Definition) (valid bool) {
	valid = false
	for _, t := range allTypes {
		if d.Type == t {
			valid = true
			break
		}
	}
	return
}

// checkTypeAs is a shortcut
func checkTypeAs(d Definition, t string) bool {
	valid := checkType(d)
	return valid && d.Type == t
}

// checkAllTypesAs is a generalization of checkTypeAs
func checkAllTypesAs(dl []Definition, t string) (valid bool) {
	valid = true
	for _, d := range dl {
		if d.Type != t {
			valid = false
			break
		}
	}
	return
}

// measurementList is our main answer
type measurementList struct {
	Count    int
	Next     string
	Previous string
	Results  []Measurement
}

// fetch the given resource
func fetchOneMeasurementPage(api *gopencils.Resource, opts map[string]string) (raw *measurementList, err error) {
	r, err := api.Res("measurements", &raw).Get(opts)
	if err != nil {
		log.Printf("err: %v", err)
		err = fmt.Errorf("%v - r:%v\n", err, r)
	}
	//log.Printf(">> rawlist=%+v r=%+v Next=|%s|", rawlist, r, rawlist.Next)
	return
}

// -- public

// GetMeasurement gets info for a single one
func GetMeasurement(id int) (m *Measurement, err error) {
	key, ok := HasAPIKey()
	api := gopencils.Api(apiEndpoint, nil)

	// Add at least one option, the APIkey if present
	var opts map[string]string

	if ok {
		opts["key"] = key
	}

	r, err := api.Res("measurements").Id(id, &m).Get(opts)
	if err != nil {
		err = fmt.Errorf("%v - r:%#v\n", err, r.Raw)
		return
	}
	return
}

// GetMeasurements gets info for a set
func GetMeasurements(opts map[string]string) (m []Measurement, err error) {
	key, ok := HasAPIKey()
	api := gopencils.Api(apiEndpoint, nil)

	// Add at least one option, the APIkey if present
	if ok {
		opts["key"] = key
	}

	rawlist, err := fetchOneMeasurementPage(api, opts)

	// Empty answer
	if rawlist.Count == 0 {
		return nil, fmt.Errorf("empty measurement list")
	}

	var res []Measurement

	res = append(res, rawlist.Results...)
	if rawlist.Next != "" {
		// We have pagination
		for pn := getPageNum(rawlist.Next); rawlist.Next != ""; pn = getPageNum(rawlist.Next) {
			opts["page"] = pn

			rawlist, err = fetchOneMeasurementPage(api, opts)
			if err != nil {
				return
			}

			res = append(res, rawlist.Results...)
		}
	}
	m = res
	return
}

// DNS creates a measurement
func DNS(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "dns") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// HTTP creates a measurement
func HTTP(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "http") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// NTP creates a measurement
func NTP(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "ntp") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Ping creates a measurement
func Ping(d MeasurementRequest) (m *Measurement, err error) {
	if checkTypeAs(d.Definitions[0], "ping") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// SSLCert creates a measurement
func SSLCert(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "sslcert") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Traceroute creates a measurement
func Traceroute(d Definition) (m *Measurement, err error) {
	if checkTypeAs(d, "traceroute") {
		err = ErrInvalidMeasurementType
		return
	}
	return
}

// Measurement-related methods

// Start is for starting a given measurement
func (m *Measurement) Start(id int) (err error) {
	return nil
}

// Stop is for stopping a given measurement
func (m *Measurement) Stop(id int) (err error) {
	return nil
}
<|endoftext|>


<commit_before>package main

import (
  "encoding/json"
  "fmt"
  "net/http"
  "net/url"
  "os"
  "strconv"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

var players = []*game.Player{
  &game.Player{1, "Player One"},
  &game.Player{2, "Player Two"},
}
var playerIndex = make(map[uint64]*game.Player)

func initPlayerData() {
  for _,player := range players {
    playerIndex[(uint64)(player.Id)] = player
  }
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], players)
  sessions[0].Step(players[0])
  sessions[0].Step(players[1])

  sessions[1] = session.NewSession(gameCollection.Games[1], players)
  sessions[1].Step(players[0])
  sessions[1].Step(players[1])

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

type CollectionHandler struct{}
func (h CollectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type GameHandler struct{}
func (h GameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type PlayersHandler struct{}
func (h PlayersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type PlayerHandler struct{}
func (h PlayerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  player, ok := playerIndex[player_id]
  if ok {
    err = json.NewEncoder(w).Encode(player)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type SessionsHandler struct{}
func (h SessionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

type SessionHandler struct{}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("session_id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type StepHandler struct{}
func (h StepHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  session_id_str := r.URL.Query().Get("session_id")
  session_id, err := strconv.ParseUint(session_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }
  session,ok := sessionIndex[session_id]
  if !ok {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }

  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }
  player, ok := playerIndex[player_id]
  if !ok {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }

  step_desc,err := url.QueryUnescape(r.URL.Query().Get("step_desc"))
  for _,step := range session.SetupSteps {
    if ( step.GetRule().Description == step_desc && step.CanBeOwnedBy(player) ) {
      step.Finish()  // FIXME. Should look in request data to see what to change.
      session.Step(player)
      session.Print()  // FIXME
      return
    }
  }
  http.Error(w, "Step not found", http.StatusNotFound)
}

func main() {
  initPlayerData()
  initGameData()
  initSessionData()

  var origin string
  origin = os.Getenv("MEEPLE_MOVER_ORIGIN_URL")
  if "" == origin {
    origin = "http://localhost:8000"
  }
  cors := tigertonic.NewCORSBuilder().AddAllowedOrigins(origin)

  mux := tigertonic.NewTrieServeMux()
  mux.Handle("GET", "/games", cors.Build(CollectionHandler{}))
  mux.Handle("GET", "/games/{id}", cors.Build(GameHandler{}))
  mux.Handle("GET", "/players", cors.Build(PlayersHandler{}))
  mux.Handle("GET", "/players/{player_id}", cors.Build(PlayerHandler{}))
  mux.Handle("GET", "/sessions", cors.Build(SessionsHandler{}))
  mux.Handle("GET", "/sessions/{session_id}", cors.Build(SessionHandler{}))
  mux.Handle("PUT", "/sessions/{session_id}/players/{player_id}/steps/{step_desc}", cors.Build(StepHandler{}))

  var port string
  port = os.Getenv("PORT")
  if "" == port {
    port = "8080"
  }

  http.ListenAndServe(fmt.Sprintf(":%s", port), mux)
}
<commit_msg>Test CORS fix for Heroku<commit_after>package main

import (
  "encoding/json"
  "fmt"
  "net/http"
  "net/url"
  "os"
  "strconv"
  "github.com/rcrowley/go-tigertonic"
  "github.com/rkbodenner/parallel_universe/collection"
  "github.com/rkbodenner/parallel_universe/game"
  "github.com/rkbodenner/parallel_universe/session"
)

var players = []*game.Player{
  &game.Player{1, "Player One"},
  &game.Player{2, "Player Two"},
}
var playerIndex = make(map[uint64]*game.Player)

func initPlayerData() {
  for _,player := range players {
    playerIndex[(uint64)(player.Id)] = player
  }
}

var gameCollection = collection.NewCollection()
var gameIndex = make(map[uint64]*game.Game)

func initGameData() {
  for i,game := range gameCollection.Games {
    game.Id = (uint)(i+1)
    gameIndex[(uint64)(i+1)] = game
  }
}

var sessions []*session.Session
var sessionIndex = make(map[uint64]*session.Session)

func initSessionData() {
  sessions = make([]*session.Session, 2)
  sessions[0] = session.NewSession(gameCollection.Games[0], players)
  sessions[0].Step(players[0])
  sessions[0].Step(players[1])

  sessions[1] = session.NewSession(gameCollection.Games[1], players)
  sessions[1].Step(players[0])
  sessions[1].Step(players[1])

  for i,session := range sessions {
    session.Id = (uint)(i+1)
    sessionIndex[(uint64)(i+1)] = session
  }
}

type CollectionHandler struct{}
func (h CollectionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(gameCollection)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type GameHandler struct{}
func (h GameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  game, ok := gameIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(game)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type PlayersHandler struct{}
func (h PlayersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(players)
  if ( nil != err ) {
    fmt.Fprintln(w, err)
  }
}

type PlayerHandler struct{}
func (h PlayerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  player, ok := playerIndex[player_id]
  if ok {
    err = json.NewEncoder(w).Encode(player)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type SessionsHandler struct{}
func (h SessionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  err := json.NewEncoder(w).Encode(sessions)
  if ( nil != err ) {
    http.Error(w, "Error", http.StatusInternalServerError)
  }
}

type SessionHandler struct{}
func (h SessionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  id_str := r.URL.Query().Get("session_id")
  id, err := strconv.ParseUint(id_str, 10, 64)
  if nil != err {
    http.Error(w, "Not found", http.StatusNotFound)
    return
  }

  session, ok := sessionIndex[id]
  if ok {
    err := json.NewEncoder(w).Encode(session)
    if ( nil != err ) {
      http.Error(w, "Error", http.StatusInternalServerError)
    }
  } else {
    http.Error(w, "Not found", http.StatusNotFound)
  }
}

type StepHandler struct{}
func (h StepHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  session_id_str := r.URL.Query().Get("session_id")
  session_id, err := strconv.ParseUint(session_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }
  session,ok := sessionIndex[session_id]
  if !ok {
    http.Error(w, "Session not found", http.StatusNotFound)
    return
  }

  player_id_str := r.URL.Query().Get("player_id")
  player_id, err := strconv.ParseUint(player_id_str, 10, 64)
  if nil != err {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }
  player, ok := playerIndex[player_id]
  if !ok {
    http.Error(w, "Player not found", http.StatusNotFound)
    return
  }

  step_desc,err := url.QueryUnescape(r.URL.Query().Get("step_desc"))
  for _,step := range session.SetupSteps {
    if ( step.GetRule().Description == step_desc && step.CanBeOwnedBy(player) ) {
      step.Finish()  // FIXME. Should look in request data to see what to change.
      session.Step(player)
      session.Print()  // FIXME
      return
    }
  }
  http.Error(w, "Step not found", http.StatusNotFound)
}

func main() {
  initPlayerData()
  initGameData()
  initSessionData()

  var origin string
  origin = os.Getenv("MEEPLE_MOVER_ORIGIN_URL")
  if "" == origin {
    origin = "http://arborealdesign.com"//http://localhost:8000"
  }
  cors := tigertonic.NewCORSBuilder().AddAllowedOrigins(origin)

  mux := tigertonic.NewTrieServeMux()
  mux.Handle("GET", "/games", cors.Build(CollectionHandler{}))
  mux.Handle("GET", "/games/{id}", cors.Build(GameHandler{}))
  mux.Handle("GET", "/players", cors.Build(PlayersHandler{}))
  mux.Handle("GET", "/players/{player_id}", cors.Build(PlayerHandler{}))
  mux.Handle("GET", "/sessions", cors.Build(SessionsHandler{}))
  mux.Handle("GET", "/sessions/{session_id}", cors.Build(SessionHandler{}))
  mux.Handle("PUT", "/sessions/{session_id}/players/{player_id}/steps/{step_desc}", cors.Build(StepHandler{}))

  var port string
  port = os.Getenv("PORT")
  if "" == port {
    port = "8080"
  }

  http.ListenAndServe(fmt.Sprintf(":%s", port), mux)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/bazelbuild/continuous-integration/metrics/clients"
	"github.com/bazelbuild/continuous-integration/metrics/metrics"
	"github.com/bazelbuild/continuous-integration/metrics/publishers"
	"github.com/bazelbuild/continuous-integration/metrics/service"
)

var (
	projectID             = flag.String("project_id", "bazel-untrusted", "ID of the GCP project.")
	datastoreSettingsName = flag.String("datastore_settings_name", "MetricSettings", "Name of the settings entity in Datastore.")
	testMode              = flag.Bool("test", false, "If true, the service will collect and publish all metrics immediately and only once.")
)

const megaByte = 1024 * 1024

func handleError(metricName string, err error) {
	fmt.Printf("[%s] %v\n", metricName, err)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "You should try https://bazel.build")
}

func minutes(value int) time.Duration {
	return time.Duration(value) * time.Minute
}

func logInTestMode(message string) {
	log.Printf("[Test mode] %s\n", message)
}

func main() {
	flag.Parse()

	settings, err := ReadSettingsFromDatastore(*projectID, *datastoreSettingsName)
	if err != nil {
		log.Fatalf("Could not read settings from Datastore: %v", err)
	}
	pipelines, err := settings.GetPipelineIDs()
	if err != nil {
		log.Fatalf("Could not get Buildkite pipeline IDs from Datastore: %v", err)
	}
	if len(pipelines) == 0 {
		log.Fatalf("No pipelines were specified.")
	}

	bkAPI, err := clients.CreateBuildkiteAPI(settings.BuildkiteApiToken, settings.BuildkiteDebug)
	if err != nil {
		log.Fatalf("Cannot create Buildkite API client: %v", err)
	}
	bk := clients.CreateCachedBuildkiteClient(bkAPI, time.Duration(settings.BuildkiteCacheTimeoutMinutes)*time.Minute)

	computeClient, err := clients.CreateComputeEngineClient()
	if err != nil {
		log.Fatalf("Cannot create Compute Engine client: %v", err)
	}

	storageClient, err := clients.CreateCloudStorageClient()
	if err != nil {
		log.Fatalf("Cannot create Cloud Storage client: %v", err)
	}

	stackdriverClient, err := clients.CreateStackdriverClient()
	if err != nil {
		log.Fatalf("Cannot create Stackdriver client: %v", err)
	}

	stackdriver := publishers.CreateStackdriverPublisher(stackdriverClient, *projectID)

	stdout := publishers.CreateStdoutPublisher(publishers.Csv)

	var defaultPublisher publishers.Publisher
	if *testMode {
		logInTestMode("Using stdout publisher for all metrics.")
		defaultPublisher = stdout
	} else {
		defaultPublisher, err = publishers.CreateCloudSqlPublisher(settings.CloudSqlUser, settings.CloudSqlPassword, settings.CloudSqlInstance, settings.CloudSqlDatabase, settings.CloudSqlLocalPort)
		if err != nil {
			log.Fatalf("Failed to set up Cloud SQL publisher: %v", err)
		}
	}

	srv := service.CreateService(handleError)

	buildsPerChange := metrics.CreateBuildsPerChange(bk, 500, pipelines...)
	srv.AddMetric(buildsPerChange, minutes(60), defaultPublisher)

	buildSuccess := metrics.CreateBuildSuccess(bk, 200, pipelines...)
	srv.AddMetric(buildSuccess, minutes(60), defaultPublisher)

	criticalPath := metrics.CreateCriticalPath(bk, 20, pipelines...)
	srv.AddMetric(criticalPath, minutes(60), defaultPublisher)

	flakiness := metrics.CreateFlakiness(storageClient, "bazel-buildkite-stats", "flaky-tests-bep", pipelines...)
	srv.AddMetric(flakiness, minutes(60), defaultPublisher)

	macPerformance := metrics.CreateMacPerformance(bk, 20, pipelines...)
	srv.AddMetric(macPerformance, minutes(60), defaultPublisher)

	pipelinePerformance := metrics.CreatePipelinePerformance(bk, 20, pipelines...)
	srv.AddMetric(pipelinePerformance, minutes(10), defaultPublisher)

	platformLoad := metrics.CreatePlatformLoad(bk, 100, settings.BuildkiteOrgs...)
	srv.AddMetric(platformLoad, minutes(5), defaultPublisher, stackdriver)

	platformSignificance := metrics.CreatePlatformSignificance(bk, 100, pipelines...)
	srv.AddMetric(platformSignificance, minutes(24*60), defaultPublisher)

	platformUsage := metrics.CreatePlatformUsage(bk, 100, settings.BuildkiteOrgs...)
	srv.AddMetric(platformUsage, minutes(60), defaultPublisher)

	releaseDownloads := metrics.CreateReleaseDownloads(settings.GitHubOrg,
		settings.GitHubRepo,
		settings.GitHubApiToken, megaByte)
	srv.AddMetric(releaseDownloads, minutes(12*60), defaultPublisher)

	workerAvailability := metrics.CreateWorkerAvailability(bk, settings.BuildkiteOrgs...)
	srv.AddMetric(workerAvailability, minutes(5), defaultPublisher)

	// TODO(fweikert): Read gracePeriod from Datastore
	zombieInstances := metrics.CreateZombieInstances(computeClient, settings.CloudProjects, bk, settings.BuildkiteOrgs, minutes(3))
	srv.AddMetric(zombieInstances, minutes(5), defaultPublisher)

	if *testMode {
		logInTestMode("Running all jobs exactly once...")
		srv.RunJobsOnce()
		os.Exit(0)
	}

	srv.Start()
	http.HandleFunc("/", handleRequest)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
<commit_msg>Collect platform_load metric once per minute (#821)<commit_after>package main

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

	"github.com/bazelbuild/continuous-integration/metrics/clients"
	"github.com/bazelbuild/continuous-integration/metrics/metrics"
	"github.com/bazelbuild/continuous-integration/metrics/publishers"
	"github.com/bazelbuild/continuous-integration/metrics/service"
)

var (
	projectID             = flag.String("project_id", "bazel-untrusted", "ID of the GCP project.")
	datastoreSettingsName = flag.String("datastore_settings_name", "MetricSettings", "Name of the settings entity in Datastore.")
	testMode              = flag.Bool("test", false, "If true, the service will collect and publish all metrics immediately and only once.")
)

const megaByte = 1024 * 1024

func handleError(metricName string, err error) {
	fmt.Printf("[%s] %v\n", metricName, err)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "You should try https://bazel.build")
}

func minutes(value int) time.Duration {
	return time.Duration(value) * time.Minute
}

func logInTestMode(message string) {
	log.Printf("[Test mode] %s\n", message)
}

func main() {
	flag.Parse()

	settings, err := ReadSettingsFromDatastore(*projectID, *datastoreSettingsName)
	if err != nil {
		log.Fatalf("Could not read settings from Datastore: %v", err)
	}
	pipelines, err := settings.GetPipelineIDs()
	if err != nil {
		log.Fatalf("Could not get Buildkite pipeline IDs from Datastore: %v", err)
	}
	if len(pipelines) == 0 {
		log.Fatalf("No pipelines were specified.")
	}

	bkAPI, err := clients.CreateBuildkiteAPI(settings.BuildkiteApiToken, settings.BuildkiteDebug)
	if err != nil {
		log.Fatalf("Cannot create Buildkite API client: %v", err)
	}
	bk := clients.CreateCachedBuildkiteClient(bkAPI, time.Duration(settings.BuildkiteCacheTimeoutMinutes)*time.Minute)

	computeClient, err := clients.CreateComputeEngineClient()
	if err != nil {
		log.Fatalf("Cannot create Compute Engine client: %v", err)
	}

	storageClient, err := clients.CreateCloudStorageClient()
	if err != nil {
		log.Fatalf("Cannot create Cloud Storage client: %v", err)
	}

	stackdriverClient, err := clients.CreateStackdriverClient()
	if err != nil {
		log.Fatalf("Cannot create Stackdriver client: %v", err)
	}

	stackdriver := publishers.CreateStackdriverPublisher(stackdriverClient, *projectID)

	stdout := publishers.CreateStdoutPublisher(publishers.Csv)

	var defaultPublisher publishers.Publisher
	if *testMode {
		logInTestMode("Using stdout publisher for all metrics.")
		defaultPublisher = stdout
	} else {
		defaultPublisher, err = publishers.CreateCloudSqlPublisher(settings.CloudSqlUser, settings.CloudSqlPassword, settings.CloudSqlInstance, settings.CloudSqlDatabase, settings.CloudSqlLocalPort)
		if err != nil {
			log.Fatalf("Failed to set up Cloud SQL publisher: %v", err)
		}
	}

	srv := service.CreateService(handleError)

	buildsPerChange := metrics.CreateBuildsPerChange(bk, 500, pipelines...)
	srv.AddMetric(buildsPerChange, minutes(60), defaultPublisher)

	buildSuccess := metrics.CreateBuildSuccess(bk, 200, pipelines...)
	srv.AddMetric(buildSuccess, minutes(60), defaultPublisher)

	criticalPath := metrics.CreateCriticalPath(bk, 20, pipelines...)
	srv.AddMetric(criticalPath, minutes(60), defaultPublisher)

	flakiness := metrics.CreateFlakiness(storageClient, "bazel-buildkite-stats", "flaky-tests-bep", pipelines...)
	srv.AddMetric(flakiness, minutes(60), defaultPublisher)

	macPerformance := metrics.CreateMacPerformance(bk, 20, pipelines...)
	srv.AddMetric(macPerformance, minutes(60), defaultPublisher)

	pipelinePerformance := metrics.CreatePipelinePerformance(bk, 20, pipelines...)
	srv.AddMetric(pipelinePerformance, minutes(10), defaultPublisher)

	platformLoad := metrics.CreatePlatformLoad(bk, 100, settings.BuildkiteOrgs...)
	srv.AddMetric(platformLoad, minutes(1), defaultPublisher, stackdriver)

	platformSignificance := metrics.CreatePlatformSignificance(bk, 100, pipelines...)
	srv.AddMetric(platformSignificance, minutes(24*60), defaultPublisher)

	platformUsage := metrics.CreatePlatformUsage(bk, 100, settings.BuildkiteOrgs...)
	srv.AddMetric(platformUsage, minutes(60), defaultPublisher)

	releaseDownloads := metrics.CreateReleaseDownloads(settings.GitHubOrg,
		settings.GitHubRepo,
		settings.GitHubApiToken, megaByte)
	srv.AddMetric(releaseDownloads, minutes(12*60), defaultPublisher)

	workerAvailability := metrics.CreateWorkerAvailability(bk, settings.BuildkiteOrgs...)
	srv.AddMetric(workerAvailability, minutes(5), defaultPublisher)

	// TODO(fweikert): Read gracePeriod from Datastore
	zombieInstances := metrics.CreateZombieInstances(computeClient, settings.CloudProjects, bk, settings.BuildkiteOrgs, minutes(3))
	srv.AddMetric(zombieInstances, minutes(5), defaultPublisher)

	if *testMode {
		logInTestMode("Running all jobs exactly once...")
		srv.RunJobsOnce()
		os.Exit(0)
	}

	srv.Start()
	http.HandleFunc("/", handleRequest)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", handler)
	http.HandleFunc("/api/hello", about)
	http.ListenAndServe(":8080", nil)
}

// Hello response structure
type Hello struct {
	Message string
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Cloud Native Go.")
}

func about(w http.ResponseWriter, r *http.Request) {

	m := Hello{"Welcome to Cloud Native Go."}
	b, err := json.Marshal(m)

	if err != nil {
		panic(err)
	}

	w.Header().Add("Content-Type", "application/json; charset=utf-8")
	w.Write(b)
}
<commit_msg>Renamed HTTP handler function.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", handler)
	http.HandleFunc("/api/hello", hello)
	http.ListenAndServe(":8080", nil)
}

// Hello response structure
type Hello struct {
	Message string
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Cloud Native Go.")
}

func hello(w http.ResponseWriter, r *http.Request) {

	m := Hello{"Welcome to Cloud Native Go."}
	b, err := json.Marshal(m)

	if err != nil {
		panic(err)
	}

	w.Header().Add("Content-Type", "application/json; charset=utf-8")
	w.Write(b)
}
<|endoftext|>


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

package mmap

import (
	"errors"
	"os"
	"sync"
	"syscall"
)

// mmap on Windows is a two-step process.
// First, we call CreateFileMapping to get a handle.
// Then, we call MapviewToFile to get an actual pointer into memory.
// Because we want to emulate a POSIX-style mmap, we don't want to expose
// the handle -- only the pointer. We also want to return only a byte slice,
// not a struct, so it's convenient to manipulate.

// We keep this map so that we can get back the original handle from the memory address.
var handleLock sync.Mutex
var handleMap = map[uintptr]syscall.Handle{}

func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) {
	flProtect := uint32(syscall.PAGE_READONLY)
	dwDesiredAccess := uint32(syscall.FILE_MAP_READ)
	switch {
	case prot&COPY != 0:
		flProtect = syscall.PAGE_WRITECOPY
		dwDesiredAccess = syscall.FILE_MAP_COPY
	case prot&RDWR != 0:
		flProtect = syscall.PAGE_READWRITE
		dwDesiredAccess = syscall.FILE_MAP_WRITE
	}
	if prot&EXEC != 0 {
		flProtect <<= 4
		dwDesiredAccess |= syscall.FILE_MAP_EXECUTE
	}

        // The maximum size is the area of the file, starting from 0,
        // that we wish to allow to be mappable. It is the sum of
        // the length the user requested, plus the offset where that length
        // is starting from. This does not map the data into memory.
        max_size_high := uint32((off + int64(len)) >> 32)
        max_size_low := uint32((off + int64(len)) &  0xFFFFFFFF)
	// TODO: Do we need to set some security attributes? It might help portability.
	h, errno := syscall.CreateFileMapping(syscall.Handle(hfile), nil, flProtect, max_size_high, max_size_low, nil)
	if h == 0 {
		return nil, os.NewSyscallError("CreateFileMapping", errno)
	}

        // Actually map a view of the data into memory. The view's size
        // is the length the user requested.
        file_offset_high := uint32(off >> 32)
        file_offset_low := uint32(off & 0xFFFFFFFF)
	addr, errno := syscall.MapViewOfFile(h, dwDesiredAccess, file_offset_high, file_offset_low, uintptr(len))
	if addr == 0 {
		return nil, os.NewSyscallError("MapViewOfFile", errno)
	}
	handleLock.Lock()
	handleMap[addr] = h
	handleLock.Unlock()

	m := MMap{}
	dh := m.header()
	dh.Data = addr
	dh.Len = len
	dh.Cap = dh.Len

	return m, nil
}

func flush(addr, len uintptr) error {
	errno := syscall.FlushViewOfFile(addr, len)
	return os.NewSyscallError("FlushViewOfFile", errno)
}

func lock(addr, len uintptr) error {
	errno := syscall.VirtualLock(addr, len)
	return os.NewSyscallError("VirtualLock", errno)
}

func unlock(addr, len uintptr) error {
	errno := syscall.VirtualUnlock(addr, len)
	return os.NewSyscallError("VirtualUnlock", errno)
}

func unmap(addr, len uintptr) error {
	flush(addr, len)
	err := syscall.UnmapViewOfFile(addr)
	if err != nil {
		return err
	}

	handleLock.Lock()
	defer handleLock.Unlock()
	handle, ok := handleMap[addr]
	if !ok {
		// should be impossible; we would've errored above
		return errors.New("unknown base address")
	}
	delete(handleMap, addr)

	e := syscall.CloseHandle(syscall.Handle(handle))
	return os.NewSyscallError("CloseHandle", e)
}
<commit_msg>Fix go fmt issues.<commit_after>// Copyright 2011 Evan Shaw. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mmap

import (
	"errors"
	"os"
	"sync"
	"syscall"
)

// mmap on Windows is a two-step process.
// First, we call CreateFileMapping to get a handle.
// Then, we call MapviewToFile to get an actual pointer into memory.
// Because we want to emulate a POSIX-style mmap, we don't want to expose
// the handle -- only the pointer. We also want to return only a byte slice,
// not a struct, so it's convenient to manipulate.

// We keep this map so that we can get back the original handle from the memory address.
var handleLock sync.Mutex
var handleMap = map[uintptr]syscall.Handle{}

func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) {
	flProtect := uint32(syscall.PAGE_READONLY)
	dwDesiredAccess := uint32(syscall.FILE_MAP_READ)
	switch {
	case prot&COPY != 0:
		flProtect = syscall.PAGE_WRITECOPY
		dwDesiredAccess = syscall.FILE_MAP_COPY
	case prot&RDWR != 0:
		flProtect = syscall.PAGE_READWRITE
		dwDesiredAccess = syscall.FILE_MAP_WRITE
	}
	if prot&EXEC != 0 {
		flProtect <<= 4
		dwDesiredAccess |= syscall.FILE_MAP_EXECUTE
	}

	// The maximum size is the area of the file, starting from 0,
	// that we wish to allow to be mappable. It is the sum of
	// the length the user requested, plus the offset where that length
	// is starting from. This does not map the data into memory.
	max_size_high := uint32((off + int64(len)) >> 32)
	max_size_low := uint32((off + int64(len)) & 0xFFFFFFFF)
	// TODO: Do we need to set some security attributes? It might help portability.
	h, errno := syscall.CreateFileMapping(syscall.Handle(hfile), nil, flProtect, max_size_high, max_size_low, nil)
	if h == 0 {
		return nil, os.NewSyscallError("CreateFileMapping", errno)
	}

	// Actually map a view of the data into memory. The view's size
	// is the length the user requested.
	file_offset_high := uint32(off >> 32)
	file_offset_low := uint32(off & 0xFFFFFFFF)
	addr, errno := syscall.MapViewOfFile(h, dwDesiredAccess, file_offset_high, file_offset_low, uintptr(len))
	if addr == 0 {
		return nil, os.NewSyscallError("MapViewOfFile", errno)
	}
	handleLock.Lock()
	handleMap[addr] = h
	handleLock.Unlock()

	m := MMap{}
	dh := m.header()
	dh.Data = addr
	dh.Len = len
	dh.Cap = dh.Len

	return m, nil
}

func flush(addr, len uintptr) error {
	errno := syscall.FlushViewOfFile(addr, len)
	return os.NewSyscallError("FlushViewOfFile", errno)
}

func lock(addr, len uintptr) error {
	errno := syscall.VirtualLock(addr, len)
	return os.NewSyscallError("VirtualLock", errno)
}

func unlock(addr, len uintptr) error {
	errno := syscall.VirtualUnlock(addr, len)
	return os.NewSyscallError("VirtualUnlock", errno)
}

func unmap(addr, len uintptr) error {
	flush(addr, len)
	err := syscall.UnmapViewOfFile(addr)
	if err != nil {
		return err
	}

	handleLock.Lock()
	defer handleLock.Unlock()
	handle, ok := handleMap[addr]
	if !ok {
		// should be impossible; we would've errored above
		return errors.New("unknown base address")
	}
	delete(handleMap, addr)

	e := syscall.CloseHandle(syscall.Handle(handle))
	return os.NewSyscallError("CloseHandle", e)
}
<|endoftext|>


<commit_before>package models

const (
	version = "0.13.3"

	OpenTrace   = "open_trace"
	WebVersion  = "web_version"
	Unsubscribe = "unsubscribe"

	StatusUnavaibleRecentTime = "Unavaible recent time"
	StatusUnsubscribe         = "Unsubscribe"
	StatusSending             = "Sending"
)
<commit_msg>bump version<commit_after>package models

const (
	version = "0.13.4"

	OpenTrace   = "open_trace"
	WebVersion  = "web_version"
	Unsubscribe = "unsubscribe"

	StatusUnavaibleRecentTime = "Unavaible recent time"
	StatusUnsubscribe         = "Unsubscribe"
	StatusSending             = "Sending"
)
<|endoftext|>


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

package models

import (
	"path"
	"time"

	git "github.com/speedata/gogit"
)

type RepoFile struct {
	Id      *git.Oid
	Type    int
	Name    string
	Path    string
	Message string
	Created time.Time
}

func (f *RepoFile) IsFile() bool {
	return f.Type == git.FileModeBlob || f.Type == git.FileModeBlobExec
}

func (f *RepoFile) IsDir() bool {
	return f.Type == git.FileModeTree
}

func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, error) {
	f := RepoPath(userName, reposName)

	repo, err := git.OpenRepository(f)
	if err != nil {
		return nil, err
	}

	ref, err := repo.LookupReference("refs/heads/" + branchName)
	if err != nil {
		return nil, err
	}

	lastCommit, err := repo.LookupCommit(ref.Oid)
	if err != nil {
		return nil, err
	}

	var repofiles []*RepoFile
	lastCommit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int {
		if dirname == rpath {
			repofiles = append(repofiles, &RepoFile{
				entry.Id,
				entry.Filemode,
				entry.Name,
				path.Join(dirname, entry.Name),
				lastCommit.Message(),
				lastCommit.Committer.When,
			})
		}
		return 0
	})

	return repofiles, nil
}
<commit_msg>show folder first on file list page<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models

import (
	"path"
	"time"

	git "github.com/gogits/git"
)

type RepoFile struct {
	Id      *git.Oid
	Type    int
	Name    string
	Path    string
	Message string
	Created time.Time
}

func (f *RepoFile) IsFile() bool {
	return f.Type == git.FileModeBlob || f.Type == git.FileModeBlobExec
}

func (f *RepoFile) IsDir() bool {
	return f.Type == git.FileModeTree
}

func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, error) {
	f := RepoPath(userName, reposName)

	repo, err := git.OpenRepository(f)
	if err != nil {
		return nil, err
	}

	ref, err := repo.LookupReference("refs/heads/" + branchName)
	if err != nil {
		return nil, err
	}

	lastCommit, err := repo.LookupCommit(ref.Oid)
	if err != nil {
		return nil, err
	}

	var repodirs []*RepoFile
	var repofiles []*RepoFile
	lastCommit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int {
		if dirname == rpath {
			switch entry.Filemode {
			case git.FileModeBlob, git.FileModeBlobExec:
				repofiles = append(repofiles, &RepoFile{
					entry.Id,
					entry.Filemode,
					entry.Name,
					path.Join(dirname, entry.Name),
					lastCommit.Message(),
					lastCommit.Committer.When,
				})
			case git.FileModeTree:
				repodirs = append(repodirs, &RepoFile{
					entry.Id,
					entry.Filemode,
					entry.Name,
					path.Join(dirname, entry.Name),
					lastCommit.Message(),
					lastCommit.Committer.When,
				})
			}
		}
		return 0
	})

	return append(repodirs, repofiles...), nil
}
<|endoftext|>


<commit_before>package models

import (
	"fmt"
	"regexp"
	"time"

	"github.com/mundipagg/boleto-api/util"
)

// Title título de cobrança de entrada
type Title struct {
	CreateDate     time.Time `json:"createDate,omitempty"`
	ExpireDateTime time.Time `json:"expireDateTime,omitempty"`
	ExpireDate     string    `json:"expireDate,omitempty"`
	AmountInCents  uint64    `json:"amountInCents,omitempty"`
	OurNumber      uint      `json:"ourNumber,omitempty"`
	Instructions   string    `json:"instructions,omitempty"`
	DocumentNumber string    `json:"documentNumber,omitempty"`
	NSU            string    `json:"nsu,omitempty"`
	BoletoType     string    `json:"boletoType,omitempty"`
}

//ValidateInstructionsLength valida se texto das instruções possui quantidade de caracteres corretos
func (t Title) ValidateInstructionsLength(max int) error {
	if len(t.Instructions) > max {
		return NewErrorResponse("MPInstructions", fmt.Sprintf("Instruções não podem passar de %d caracteres", max))
	}
	return nil
}

//ValidateDocumentNumber número do documento
func (t *Title) ValidateDocumentNumber() error {
	re := regexp.MustCompile("(\\D+)")
	ad := re.ReplaceAllString(t.DocumentNumber, "")
	if ad == "" {
		t.DocumentNumber = ad
	} else if len(ad) < 10 {
		t.DocumentNumber = util.PadLeft(ad, "0", 10)
	} else {
		t.DocumentNumber = ad[:10]
	}
	return nil
}

//IsExpireDateValid retorna um erro se a data de expiração for inválida
func (t *Title) IsExpireDateValid() error {
	d, err := parseDate(t.ExpireDate)
	if err != nil {
		return NewErrorResponse("MPExpireDate", fmt.Sprintf("Data em um formato inválido, esperamos AAAA-MM-DD e recebemos %s", t.ExpireDate))
	}
	n, _ := parseDate(util.BrNow().Format("2006-01-02"))
	t.CreateDate = n
	t.ExpireDateTime = d
	if t.CreateDate.After(t.ExpireDateTime) {
		return NewErrorResponse("MPExpireDate", "Data de expiração não pode ser menor que a data de hoje")
	}
	return nil
}

//IsAmountInCentsValid retorna um erro se o valor em centavos for inválido
func (t *Title) IsAmountInCentsValid() error {
	if t.AmountInCents < 1 {
		return NewErrorResponse("MPAmountInCents", "Valor não pode ser menor do que 1 centavo")
	}
	return nil
}

func parseDate(t string) (time.Time, error) {
	date, err := time.Parse("2006-01-02", t)
	if err != nil {
		return time.Now(), err
	}
	return date, nil
}
<commit_msg>:sparkles: Adiciona campo para código do BoletoType<commit_after>package models

import (
	"fmt"
	"regexp"
	"time"

	"github.com/mundipagg/boleto-api/util"
)

// Title título de cobrança de entrada
type Title struct {
	CreateDate     time.Time `json:"createDate,omitempty"`
	ExpireDateTime time.Time `json:"expireDateTime,omitempty"`
	ExpireDate     string    `json:"expireDate,omitempty"`
	AmountInCents  uint64    `json:"amountInCents,omitempty"`
	OurNumber      uint      `json:"ourNumber,omitempty"`
	Instructions   string    `json:"instructions,omitempty"`
	DocumentNumber string    `json:"documentNumber,omitempty"`
	NSU            string    `json:"nsu,omitempty"`
	BoletoType     string    `json:"boletoType,omitempty"`
	BoletoTypeCode string
}

//ValidateInstructionsLength valida se texto das instruções possui quantidade de caracteres corretos
func (t Title) ValidateInstructionsLength(max int) error {
	if len(t.Instructions) > max {
		return NewErrorResponse("MPInstructions", fmt.Sprintf("Instruções não podem passar de %d caracteres", max))
	}
	return nil
}

//ValidateDocumentNumber número do documento
func (t *Title) ValidateDocumentNumber() error {
	re := regexp.MustCompile("(\\D+)")
	ad := re.ReplaceAllString(t.DocumentNumber, "")
	if ad == "" {
		t.DocumentNumber = ad
	} else if len(ad) < 10 {
		t.DocumentNumber = util.PadLeft(ad, "0", 10)
	} else {
		t.DocumentNumber = ad[:10]
	}
	return nil
}

//IsExpireDateValid retorna um erro se a data de expiração for inválida
func (t *Title) IsExpireDateValid() error {
	d, err := parseDate(t.ExpireDate)
	if err != nil {
		return NewErrorResponse("MPExpireDate", fmt.Sprintf("Data em um formato inválido, esperamos AAAA-MM-DD e recebemos %s", t.ExpireDate))
	}
	n, _ := parseDate(util.BrNow().Format("2006-01-02"))
	t.CreateDate = n
	t.ExpireDateTime = d
	if t.CreateDate.After(t.ExpireDateTime) {
		return NewErrorResponse("MPExpireDate", "Data de expiração não pode ser menor que a data de hoje")
	}
	return nil
}

//IsAmountInCentsValid retorna um erro se o valor em centavos for inválido
func (t *Title) IsAmountInCentsValid() error {
	if t.AmountInCents < 1 {
		return NewErrorResponse("MPAmountInCents", "Valor não pode ser menor do que 1 centavo")
	}
	return nil
}

func parseDate(t string) (time.Time, error) {
	date, err := time.Parse("2006-01-02", t)
	if err != nil {
		return time.Now(), err
	}
	return date, nil
}
<|endoftext|>


<commit_before>package db

import (
	"fmt"
	"github.com/boltdb/bolt"
	"log"
)

const (
	DATABASE_NAME = "data.db"
)

var (
	db *bolt.DB
)

func init() {
	// Open the my.db data file in your current directory.
	// It will be created if it doesn't exist.
	var err error
	db, err = bolt.Open("data.db", 0600, nil)

	if err != nil {
		log.Fatal(err)
	}
}

func DatabaseInitialization() {
	db.Update(func(tx *bolt.Tx) error {
		//Users
		users, _ := tx.CreateBucketIfNotExists([]byte("user"))
		users.Put([]byte("admin"), []byte("admin")) //Default Admin User

		//Project
		tx.CreateBucketIfNotExists([]byte("project_list"))
		//
		return nil
	})
}

func NewProject(user, name, desc string) {
	db.Update(func(tx *bolt.Tx) error {
		projectList := tx.Bucket([]byte("project_list"))
		project, _ := projectList.CreateBucket([]byte(user + "/" + name))
		project.Put([]byte("name"), []byte(name))
		project.Put([]byte("desc"), []byte(desc))
		project.CreateBucket([]byte("commit"))
		project.CreateBucket([]byte("comments"))
		project.CreateBucket([]byte("files"))
		project.CreateBucket([]byte("task"))
		return nil
	})
}

func Project() []ProjectST {
	fmt.Println("Projects")
	projects := make([]ProjectST, 0)
	db.View(func(tx *bolt.Tx) error {
		projectList := tx.Bucket([]byte("project_list"))
		projectList.ForEach(func(k, v []byte) error {
			projectBK := projectList.Bucket(k)
			project := ProjectST{}
			project.Name = string(projectBK.Get([]byte("name")))
			project.Desc = string(projectBK.Get([]byte("desc")))
			project.Path = string(k)
			projects = append(projects, project)

			// string(projectList.Bucket(k).Get([]byte("name"))))
			return nil
		})
		return nil
	})
	return projects
}
func Close() {
	db.Close()
}
<commit_msg>add in db module InsertUser function<commit_after>package db

import (
	"crypto/sha512"
	"fmt"
	"github.com/boltdb/bolt"
	"io"
	"log"
)

const (
	DATABASE_NAME = "data.db"
)

var (
	db *bolt.DB
)

func init() {
	// Open the my.db data file in your current directory.
	// It will be created if it doesn't exist.
	var err error
	db, err = bolt.Open("data.db", 0600, nil)

	if err != nil {
		log.Fatal(err)
	}
}

func DatabaseInitialization() {
	db.Update(func(tx *bolt.Tx) error {
		//Users
		users, _ := tx.CreateBucketIfNotExists([]byte("user"))
		users.Put([]byte("admin"), []byte("admin")) //Default Admin User

		//Project
		tx.CreateBucketIfNotExists([]byte("project_list"))
		//
		return nil
	})
}

func InsertUser(id, password string) {
	h512 := sha512.New()
	io.WriteString(h512, password)
	db.Update(func(tx *bolt.Tx) error {
		users := tx.Bucket([]byte("user"))
		users.Put([]byte(id), h512.Sum([]byte("gotham!")))
		return nil
	})
}
func NewProject(user, name, desc string) {
	db.Update(func(tx *bolt.Tx) error {
		projectList := tx.Bucket([]byte("project_list"))
		project, _ := projectList.CreateBucket([]byte(user + "/" + name))
		project.Put([]byte("name"), []byte(name))
		project.Put([]byte("desc"), []byte(desc))
		project.CreateBucket([]byte("commit"))
		project.CreateBucket([]byte("comments"))
		project.CreateBucket([]byte("files"))
		project.CreateBucket([]byte("task"))
		return nil
	})
}

func Project() []ProjectST {
	fmt.Println("Projects")
	projects := make([]ProjectST, 0)
	db.View(func(tx *bolt.Tx) error {
		projectList := tx.Bucket([]byte("project_list"))
		projectList.ForEach(func(k, v []byte) error {
			projectBK := projectList.Bucket(k)
			project := ProjectST{}
			project.Name = string(projectBK.Get([]byte("name")))
			project.Desc = string(projectBK.Get([]byte("desc")))
			project.Path = string(k)
			projects = append(projects, project)

			// string(projectList.Bucket(k).Get([]byte("name"))))
			return nil
		})
		return nil
	})
	return projects
}
func Close() {
	db.Close()
}
<|endoftext|>


<commit_before>package main

import (
  "database/sql"
  "encoding/csv"
  "flag"
  "fmt"
  "os"
  _ "github.com/go-sql-driver/mysql"
)

func dump(tables []string, db *sql.DB, outputDir string) error {
  for _, table := range tables {
    err := dumpTable(table, db, outputDir)
    if err != nil {
      fmt.Printf("Error dumping %s: %s\n", table, err)
    }
  }
  return nil
}

func dumpTable(table string, db *sql.DB, outputDir string) error {
  f, err := os.Create(outputDir + "/" + table + ".csv")
  if err != nil {
    return err
  }
  defer f.Close()

  w := csv.NewWriter(f)

  rows, err := db.Query("SELECT * FROM " + table)   // Couldn't get placeholder expansion to work here
  if err != nil {
    return err
  }

  columns, err := rows.Columns()
  if err != nil {
    panic(err.Error())
  }
  err = w.Write(columns)   // Header
  if err != nil {
    return err
  }

  for rows.Next() {
    // Shamelessly ripped (and modified) from http://play.golang.org/p/jxza3pbqq9

    // Create interface set
    values := make([]interface{}, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // Scan for arbitrary values
    err = rows.Scan(scanArgs...)
    if err != nil {
      return err
    }

    // Print data
    csvData := make([]string, 0, len(values))
    for _, value := range values {
      switch value.(type) {
      default:
        s := fmt.Sprintf("%s", value)
        csvData = append(csvData, string(s))
      }
    }
    err = w.Write(csvData)
    if err != nil {
      return err
    }
  }

  w.Flush()
  err = w.Error()
  if err != nil {
    return err
  }

  return nil
}

func getTables(db *sql.DB) ([]string, error) {
  tables := make([]string, 0, 10)
  rows, err := db.Query("SHOW TABLES")
  if err != nil {
    return nil, err
  }
  for rows.Next() {
    var table string
    rows.Scan(&table)
    tables = append(tables, table)
  }
  return tables, nil
}

func main() {
  dbUser := flag.String("user", "root", "database user")
  dbPassword := flag.String("password", "", "database password")
  dbHost := flag.String("hostname", "", "database host")
  dbPort := flag.Int("port", 3306, "database port")
  outputDir := flag.String("outdir", "", "where output will be stored")
  //csvSep := flag.String("fields-terminated-by", "\t", "character to terminate fields by")
  //csvOptEncloser := flag.String("fields-optionally-enclosed-by", "\"", "character to enclose fields with when needed")
  //csvEscape := flag.String("fields-escaped-by", "\\", "character to escape special characters with")
  //compressCon := flag.Bool("compress-con", false, "whether compress connection or not")
  //compressFiles := flag.Bool("compress-file", false, "whether compress connection or not")

  flag.Parse()
  args := flag.Args()
  if len(args) < 1 {
    fmt.Println("Database name must be defined.")
    flag.PrintDefaults()
    os.Exit(1)
  }
  dbName := args[0]

  dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", *dbUser, *dbPassword, *dbHost, *dbPort, dbName)
  //fmt.Println("DB url:", dbUrl)
  db, err := sql.Open("mysql", dbUrl)
  if err != nil {
    fmt.Fprintf(os.Stderr, "Could not connect to server: %s\n", err)
  }
  defer db.Close()

  tx, err := db.Begin()
  if err != nil {
    panic(err)
  }
  defer tx.Rollback()

  var tables []string
  if len(args) > 1 {
    tables = args[1:]
  } else {
    tables, err = getTables(db)
  }

  err = dump(tables, db, *outputDir)
  if err != nil {
    panic(err)
  }
}
<commit_msg>Support for with/without transaction<commit_after>package main

import (
  "database/sql"
  "encoding/csv"
  "flag"
  "fmt"
  "os"
  _ "github.com/go-sql-driver/mysql"
)

// Queryable interface that matches sql.DB and sql.Tx.
type queryable interface {
  Query(query string, args ...interface{}) (*sql.Rows, error)
}

func dump(tables []string, db queryable, outputDir string) error {
  for _, table := range tables {
    err := dumpTable(table, db, outputDir)
    if err != nil {
      fmt.Printf("Error dumping %s: %s\n", table, err)
    }
  }
  return nil
}

func dumpTable(table string, db queryable, outputDir string) error {
  f, err := os.Create(outputDir + "/" + table + ".csv")
  if err != nil {
    return err
  }
  defer f.Close()

  w := csv.NewWriter(f)

  rows, err := db.Query("SELECT * FROM " + table)   // Couldn't get placeholder expansion to work here
  if err != nil {
    return err
  }

  columns, err := rows.Columns()
  if err != nil {
    panic(err.Error())
  }
  err = w.Write(columns)   // Header
  if err != nil {
    return err
  }

  for rows.Next() {
    // Shamelessly ripped (and modified) from http://play.golang.org/p/jxza3pbqq9

    // Create interface set
    values := make([]interface{}, len(columns))
    scanArgs := make([]interface{}, len(values))
    for i := range values {
      scanArgs[i] = &values[i]
    }

    // Scan for arbitrary values
    err = rows.Scan(scanArgs...)
    if err != nil {
      return err
    }

    // Print data
    csvData := make([]string, 0, len(values))
    for _, value := range values {
      switch value.(type) {
      default:
        s := fmt.Sprintf("%s", value)
        csvData = append(csvData, string(s))
      }
    }
    err = w.Write(csvData)
    if err != nil {
      return err
    }
  }

  w.Flush()
  err = w.Error()
  if err != nil {
    return err
  }

  return nil
}

func getTables(db queryable) ([]string, error) {
  tables := make([]string, 0, 10)
  rows, err := db.Query("SHOW TABLES")
  if err != nil {
    return nil, err
  }
  for rows.Next() {
    var table string
    rows.Scan(&table)
    tables = append(tables, table)
  }
  return tables, nil
}

func main() {
  dbUser := flag.String("user", "root", "database user")
  dbPassword := flag.String("password", "", "database password")
  dbHost := flag.String("hostname", "", "database host")
  dbPort := flag.Int("port", 3306, "database port")
  outputDir := flag.String("outdir", "", "where output will be stored")
  //csvSep := flag.String("fields-terminated-by", "\t", "character to terminate fields by")
  //csvOptEncloser := flag.String("fields-optionally-enclosed-by", "\"", "character to enclose fields with when needed")
  //csvEscape := flag.String("fields-escaped-by", "\\", "character to escape special characters with")
  //compressCon := flag.Bool("compress-con", false, "whether compress connection or not")
  //compressFiles := flag.Bool("compress-file", false, "whether compress connection or not")
  useTransaction := flag.Bool("single-transaction", true, "whether to wrap everything in a transaction or not.")

  flag.Parse()
  args := flag.Args()
  if len(args) < 1 {
    fmt.Println("Database name must be defined.")
    flag.PrintDefaults()
    os.Exit(1)
  }
  dbName := args[0]

  dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", *dbUser, *dbPassword, *dbHost, *dbPort, dbName)
  //fmt.Println("DB url:", dbUrl)
  db, err := sql.Open("mysql", dbUrl)
  if err != nil {
    fmt.Fprintf(os.Stderr, "Could not connect to server: %s\n", err)
  }
  defer db.Close()

  var q queryable
  if *useTransaction {
    tx, err := db.Begin()
    if err != nil {
      panic(err)
    }
    defer tx.Rollback()
    q = tx
  } else {
    q = db
  }

  var tables []string
  if len(args) > 1 {
    tables = args[1:]
  } else {
    tables, err = getTables(q)
  }

  err = dump(tables, q, *outputDir)
  if err != nil {
    panic(err)
  }
}
<|endoftext|>


<commit_before>package naming

import (
	"net"
	"time"

	"veyron.io/veyron/veyron2/context"
	"veyron.io/veyron/veyron2/verror"
)

var (
	ErrNameExists              = verror.Existsf("Name already exists")
	ErrNoSuchName              = verror.NoExistf("Name doesn't exist")
	ErrNoSuchNameRoot          = verror.NoExistf("Name doesn't exist: root of namespace")
	ErrResolutionDepthExceeded = verror.Abortedf("Resolution depth exceeded")
	ErrNoMountTable            = verror.Internalf("No mount table available")
)

// Endpoint represents unique identifiers for entities communicating over a
// network.  End users don't use endpoints - they deal solely with object names,
// with the MountTable providing translation of object names to endpoints.
type Endpoint interface {
	// Network returns "veyron" so that Endpoint can implement net.Addr.
	Network() string

	// String returns a string representation of the endpoint.
	//
	// The String method formats the endpoint as:
	//   @<version>@<version specific fields>@@
	// Where version is an unsigned integer.
	//
	// Version 1 is the current version for network address information:
	//   @1@<protocol>@<address>@<routingid>@@
	// Where protocol is the underlying network protocol (tcp, bluetooth etc.)
	// and address is the address specific to that protocol (host:port for
	// tcp, MAC address for bluetooth etc.)
	//
	// Version 2 is the current version for RPC:
	//   @2@<protocol>@<address>@<routingid>@<rpc version>@<rpc codec>@@
	//
	// Version 3 is the new version for RPC:
	//   @3@<protocol>@<address>@<routingid>@<rpc version>@<rpc codec>@m|s@@
	//
	// Along with Network, this method ensures that Endpoint implements net.Addr.
	String() string

	// VersionedString returns a string in the specified format. If the version
	// number is unsupported, the current 'default' version will be used.
	VersionedString(version int) string

	// RoutingID returns the RoutingID associated with this Endpoint.
	RoutingID() RoutingID

	// Addrs returns a net.Addr whose String method will return the
	// the underlying network address encoded in the endpoint rather than
	// the endpoint string itself.
	// For example, for TCP based endpoints it will return a net.Addr
	// whose network is "tcp" and string representation is <host>:<port>,
	// than the full Veyron endpoint as per the String method above.
	Addr() net.Addr

	// ServesMountTable returns true if this endpoint serves a mount table.
	ServesMountTable() bool
}

// MountedServer represents a server mounted under an object name.
type MountedServer struct {
	Server  string    // Server is an object address (OA): endpoint + suffix
	Expires time.Time // Absolute time after which the mount expires.
}

// MountEntry represents a name mounted in the mounttable.
type MountEntry struct {
	// Name is the mounted name.
	Name string
	// Servers (if present) specifies the mounted names (Link is empty).
	Servers []MountedServer
	// MT is true if servers refer to another mount table.
	MT bool
	// An error occurred fulfilling the request.
	Error error
}

// CacheCtl is a cache control for the resolution cache.
type CacheCtl interface {
	CacheCtl()
}

// DisbleCache disables the resolution cache when set to true and enables if false.
// As a side effect one can flush the cache by disabling and then reenabling it.
type DisableCache bool

func (DisableCache) CacheCtl() {}

// MountOpt is the interface for all Mount options.
type MountOpt interface {
	NSMountOpt()
}

// ReplaceMountOpt requests the mount to replace the previous mount.
type ReplaceMountOpt bool

func (ReplaceMountOpt) NSMountOpt() {}

// ServesMountTableOpt means the target is a mount table.
type ServesMountTableOpt bool

func (ServesMountTableOpt) NSMountOpt()  {}
func (ServesMountTableOpt) EndpointOpt() {}

// TODO(p): Perhaps add an ACL Opt.

// Namespace provides translation from object names to server object addresses.
// It represents the interface to a client side library for the MountTable
// service
type Namespace interface {
	// Mount the server object address under the object name, expiring after
	// the ttl. ttl of zero implies an implementation-specific high value
	// (essentially, forever).
	Mount(ctx context.T, name, server string, ttl time.Duration, opts ...MountOpt) error

	// Unmount the server object address from the object name, or if server
	// is empty, unmount all server OAs from the object name.
	Unmount(ctx context.T, name, server string) error

	// Resolve the object name into its mounted servers.
	Resolve(ctx context.T, name string) (names []string, err error)

	// Resolve the object name into its mounted servers.
	ResolveX(ctx context.T, name string) (entry *MountEntry, err error)

	// ResolveToMountTable resolves the object name into the mounttables
	// directly responsible for the name.
	ResolveToMountTable(ctx context.T, name string) (names []string, err error)

	// ResolveToMountTable resolves the object name into the mounttables
	// directly responsible for the name.
	ResolveToMountTableX(ctx context.T, name string) (entry *MountEntry, err error)

	// FlushCacheEntry flushes resolution information cached for the name.  If
	// anything was flushed it returns true.
	FlushCacheEntry(name string) bool

	// CacheCtl sets controls and returns the current control values.
	CacheCtl(ctls ...CacheCtl) []CacheCtl

	// TODO(caprita): consider adding a version of Unresolve to the
	// IDL-generated stub (in addition to UnresolveStep).

	// Unresolve returns the object name that resolves to the given name.
	// It can be the given name itself, though typically the service at the
	// given name will return the name of a mount table, which is then
	// followed up the namespace ancestry to obtain a name rooted at a
	// 'global' (i.e., widely accessible) mount table.
	Unresolve(ctx context.T, name string) (names []string, err error)

	// Glob returns all names matching pattern.  If recursive is true, it also
	// returns all names below the matching ones.
	Glob(ctx context.T, pattern string) (chan MountEntry, error)

	// SetRoots sets the roots that the local Namespace is
	// relative to. All relative names passed to the methods above
	// will be interpreted as relative to these roots. The roots
	// will be tried in the order that they are specified in the parameter
	// list for SetRoots.
	SetRoots(roots ...string) error

	// Roots returns the currently configured roots. An empty slice is
	// returned if no roots are configured.
	Roots() []string
}
<commit_msg>veyron/lib/flags: provide a default value for veyron.namespace.roots<commit_after>package naming

import (
	"net"
	"time"

	"veyron.io/veyron/veyron2/context"
	"veyron.io/veyron/veyron2/verror"
)

var (
	ErrNameExists              = verror.Existsf("Name already exists")
	ErrNoSuchName              = verror.NoExistf("Name doesn't exist")
	ErrNoSuchNameRoot          = verror.NoExistf("Name doesn't exist: root of namespace")
	ErrResolutionDepthExceeded = verror.Abortedf("Resolution depth exceeded")
	ErrNoMountTable            = verror.Internalf("No mount table available")
)

// Endpoint represents unique identifiers for entities communicating over a
// network.  End users don't use endpoints - they deal solely with object names,
// with the MountTable providing translation of object names to endpoints.
type Endpoint interface {
	// Network returns "veyron" so that Endpoint can implement net.Addr.
	Network() string

	// String returns a string representation of the endpoint.
	//
	// The String method formats the endpoint as:
	//   @<version>@<version specific fields>@@
	// Where version is an unsigned integer.
	//
	// Version 1 is the current version for network address information:
	//   @1@<protocol>@<address>@<routingid>@@
	// Where protocol is the underlying network protocol (tcp, bluetooth etc.)
	// and address is the address specific to that protocol (host:port for
	// tcp, MAC address for bluetooth etc.)
	//
	// Version 2 is the current version for RPC:
	//   @2@<protocol>@<address>@<routingid>@<rpc version>@<rpc codec>@@
	//
	// Version 3 is the new version for RPC:
	//   @3@<protocol>@<address>@<routingid>@<rpc version>@<rpc codec>@m|s@@
	//
	// Along with Network, this method ensures that Endpoint implements net.Addr.
	String() string

	// VersionedString returns a string in the specified format. If the version
	// number is unsupported, the current 'default' version will be used.
	VersionedString(version int) string

	// RoutingID returns the RoutingID associated with this Endpoint.
	RoutingID() RoutingID

	// Addrs returns a net.Addr whose String method will return the
	// the underlying network address encoded in the endpoint rather than
	// the endpoint string itself.
	// For example, for TCP based endpoints it will return a net.Addr
	// whose network is "tcp" and string representation is <host>:<port>,
	// than the full Veyron endpoint as per the String method above.
	Addr() net.Addr

	// ServesMountTable returns true if this endpoint serves a mount table.
	ServesMountTable() bool
}

// MountedServer represents a server mounted under an object name.
type MountedServer struct {
	Server  string    // Server is an object address (OA): endpoint + suffix
	Expires time.Time // Absolute time after which the mount expires.
}

// MountEntry represents a name mounted in the mounttable.
type MountEntry struct {
	// Name is the mounted name.
	Name string
	// Servers (if present) specifies the mounted names (Link is empty).
	Servers []MountedServer
	// MT is true if servers refer to another mount table.
	MT bool
	// An error occurred fulfilling the request.
	Error error
}

// CacheCtl is a cache control for the resolution cache.
type CacheCtl interface {
	CacheCtl()
}

// DisbleCache disables the resolution cache when set to true and enables if false.
// As a side effect one can flush the cache by disabling and then reenabling it.
type DisableCache bool

func (DisableCache) CacheCtl() {}

// MountOpt is the interface for all Mount options.
type MountOpt interface {
	NSMountOpt()
}

// ReplaceMountOpt requests the mount to replace the previous mount.
type ReplaceMountOpt bool

func (ReplaceMountOpt) NSMountOpt() {}

// ServesMountTableOpt means the target is a mount table.
type ServesMountTableOpt bool

func (ServesMountTableOpt) NSMountOpt()  {}
func (ServesMountTableOpt) EndpointOpt() {}

// TODO(p): Perhaps add an ACL Opt.

// Namespace provides translation from object names to server object addresses.
// It represents the interface to a client side library for the MountTable
// service
type Namespace interface {
	// Mount the server object address under the object name, expiring after
	// the ttl. ttl of zero implies an implementation-specific high value
	// (essentially, forever).
	Mount(ctx context.T, name, server string, ttl time.Duration, opts ...MountOpt) error

	// Unmount the server object address from the object name, or if server
	// is empty, unmount all server OAs from the object name.
	Unmount(ctx context.T, name, server string) error

	// Resolve the object name into its mounted servers.
	Resolve(ctx context.T, name string) (names []string, err error)

	// Resolve the object name into its mounted servers.
	ResolveX(ctx context.T, name string) (entry *MountEntry, err error)

	// ResolveToMountTable resolves the object name into the mounttables
	// directly responsible for the name.
	ResolveToMountTable(ctx context.T, name string) (names []string, err error)

	// ResolveToMountTable resolves the object name into the mounttables
	// directly responsible for the name.
	ResolveToMountTableX(ctx context.T, name string) (entry *MountEntry, err error)

	// FlushCacheEntry flushes resolution information cached for the name.  If
	// anything was flushed it returns true.
	FlushCacheEntry(name string) bool

	// CacheCtl sets controls and returns the current control values.
	CacheCtl(ctls ...CacheCtl) []CacheCtl

	// TODO(caprita): consider adding a version of Unresolve to the
	// IDL-generated stub (in addition to UnresolveStep).

	// Unresolve returns the object name that resolves to the given name.
	// It can be the given name itself, though typically the service at the
	// given name will return the name of a mount table, which is then
	// followed up the namespace ancestry to obtain a name rooted at a
	// 'global' (i.e., widely accessible) mount table.
	Unresolve(ctx context.T, name string) (names []string, err error)

	// Glob returns all names matching pattern.  If recursive is true, it also
	// returns all names below the matching ones.
	Glob(ctx context.T, pattern string) (chan MountEntry, error)

	// SetRoots sets the roots that the local Namespace is
	// relative to. All relative names passed to the methods above
	// will be interpreted as relative to these roots. The roots
	// will be tried in the order that they are specified in the parameter
	// list for SetRoots. Calling SetRoots with no arguments will clear the
	// currently configured set of roots.
	SetRoots(roots ...string) error

	// Roots returns the currently configured roots. An empty slice is
	// returned if no roots are configured.
	Roots() []string
}
<|endoftext|>


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

package procfs

import (
	"reflect"
	"testing"
)

//func Test_parseNetUDPLine(t *testing.T) {
//	tests := []struct {
//		fields  []string
//		name    string
//		want    *netUDPLine
//		wantErr bool
//	}{
//		{
//			name:   "reading valid lines, no issue should happened",
//			fields: []string{"11:", "00000000:0000", "00000000:0000", "0A", "00000017:0000002A", "0:0", "0", "1000"},
//			want: &netUDPLine{
//				Sl:        11,
//				LocalAddr: 0,
//				LocalPort: 0,
//				RemAddr:   0,
//				RemPort:   0,
//				St:        10,
//				TxQueue:   23,
//				RxQueue:   42,
//				UID:       1000,
//			},
//		},
//		{
//			name:    "error case - invalid line - number of fields/columns < 8",
//			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "0:0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse sl - not a valid uint",
//			fields:  []string{"a:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse local_address - not a valid hex",
//			fields:  []string{"1:", "0000000O:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse rem_address - not a valid hex",
//			fields:  []string{"1:", "00000000:0000", "0000000O:0000", "07", "00000000:00000001", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - cannot parse line - missing colon",
//			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "0000000000000001", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse tx_queue - not a valid hex",
//			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "DEADCODE:00000001", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse rx_queue - not a valid hex",
//			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:FEEDCODE", "0:0", "0", "0"},
//			want:    nil,
//			wantErr: true,
//		},
//		{
//			name:    "error case - parse UID - not a valid uint",
//			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "-10"},
//			want:    nil,
//			wantErr: true,
//		},
//	}
//	for _, tt := range tests {
//		t.Run(tt.name, func(t *testing.T) {
//			got, err := parseNetUDPLine(tt.fields)
//			if (err != nil) != tt.wantErr {
//				t.Errorf("parseNetUDPLine() error = %v, wantErr %v", err, tt.wantErr)
//				return
//			}
//			if tt.want == nil && got != nil {
//				t.Errorf("parseNetUDPLine() = %v, want %v", got, tt.want)
//			}
//			if got != nil {
//				if (got.Sl != tt.want.Sl) ||
//					(got.LocalAddr != tt.want.LocalAddr) ||
//					(got.LocalPort != tt.want.LocalPort) ||
//					(got.RemAddr != tt.want.RemAddr) ||
//					(got.RemPort != tt.want.RemPort) ||
//					(got.St != tt.want.St) ||
//					(got.TxQueue != tt.want.TxQueue) ||
//					(got.RxQueue != tt.want.RxQueue) ||
//					(got.UID != tt.want.UID) {
//
//					t.Errorf("parseNetUDPLine() = %#v, want %#v", got, tt.want)
//				}
//			}
//		})
//	}
//}

func Test_newNetUDP(t *testing.T) {
	tests := []struct {
		name    string
		file    string
		want    NetUDP
		wantErr bool
	}{
		{
			name: "udp file found, no error should come up",
			file: "fixtures/proc/net/udp",
			want: []*netUDPLine{
				&netUDPLine{
					Sl:        0,
					LocalAddr: []uint8{10, 0, 0, 5},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   0,
					RxQueue:   1,
					UID:       0,
				},
				&netUDPLine{
					Sl:        1,
					LocalAddr: []uint8{0, 0, 0, 0},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   1,
					RxQueue:   0,
					UID:       0,
				},
				&netUDPLine{
					Sl:        2,
					LocalAddr: []uint8{0, 0, 0, 0},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   1,
					RxQueue:   1,
					UID:       0,
				},
			},
			wantErr: false,
		},
		{
			name: "udp6 file found, no error should come up",
			file: "fixtures/proc/net/udp6",
			want: []*netUDPLine{
				&netUDPLine{
					Sl:        1315,
					LocalAddr: []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					LocalPort: 5355,
					RemAddr:   []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					RemPort:   0,
					St:        7,
					TxQueue:   0,
					RxQueue:   0,
					UID:       981,
				},
				&netUDPLine{
					Sl:        6073,
					LocalAddr: []uint8{0, 0, 128, 254, 0, 0, 0, 0, 255, 173, 225, 86, 9, 102, 124, 254},
					LocalPort: 51073,
					RemAddr:   []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					RemPort:   0,
					St:        7,
					TxQueue:   0,
					RxQueue:   0,
					UID:       1000,
				},
			},
			wantErr: false,
		},
		{
			name:    "error case - file not found",
			file:    "somewhere over the rainbow",
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse error",
			file:    "fixtures/proc/net/udp_broken",
			want:    nil,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := newNetUDP(tt.file)
			if (err != nil) != tt.wantErr {
				t.Errorf("newNetUDP() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("newNetUDP() = %v, want %v", got, tt.want)
			}
		})
	}
}

func Test_newNetUDPSummary(t *testing.T) {
	tests := []struct {
		name    string
		file    string
		want    *NetUDPSummary
		wantErr bool
	}{
		{
			name:    "udp file found, no error should come up",
			file:    "fixtures/proc/net/udp",
			want:    &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3},
			wantErr: false,
		},
		{
			name:    "udp6 file found, no error should come up",
			file:    "fixtures/proc/net/udp6",
			want:    &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2},
			wantErr: false,
		},
		{
			name:    "error case - file not found",
			file:    "somewhere over the rainbow",
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse error",
			file:    "fixtures/proc/net/udp_broken",
			want:    nil,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := newNetUDPSummary(tt.file)
			if (err != nil) != tt.wantErr {
				t.Errorf("newNetUDPSummary() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("newNetUDPSummary() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>Refactor tests for parsing lines<commit_after>// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package procfs

import (
	"reflect"
	"testing"
)

func Test_parseNetUDPLine(t *testing.T) {
	tests := []struct {
		fields  []string
		name    string
		want    *netUDPLine
		wantErr bool
	}{
		{
			name:   "reading valid lines, no issue should happened",
			fields: []string{"11:", "00000000:0000", "00000000:0000", "0A", "00000017:0000002A", "0:0", "0", "1000"},
			want: &netUDPLine{
				Sl:        11,
				LocalAddr: []uint8{0, 0, 0, 0},
				LocalPort: 0,
				RemAddr:   []uint8{0, 0, 0, 0},
				RemPort:   0,
				St:        10,
				TxQueue:   23,
				RxQueue:   42,
				UID:       1000,
			},
		},
		{
			name:    "error case - invalid line - number of fields/columns < 8",
			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "0:0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse sl - not a valid uint",
			fields:  []string{"a:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse local_address - not a valid hex",
			fields:  []string{"1:", "0000000O:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse rem_address - not a valid hex",
			fields:  []string{"1:", "00000000:0000", "0000000O:0000", "07", "00000000:00000001", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - cannot parse line - missing colon",
			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "0000000000000001", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse tx_queue - not a valid hex",
			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "DEADCODE:00000001", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse rx_queue - not a valid hex",
			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:FEEDCODE", "0:0", "0", "0"},
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse UID - not a valid uint",
			fields:  []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "-10"},
			want:    nil,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := parseNetUDPLine(tt.fields)
			if (err != nil) != tt.wantErr {
				t.Errorf("parseNetUDPLine() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if tt.want == nil && got != nil {
				t.Errorf("parseNetUDPLine() = %v, want %v", got, tt.want)
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("parseNetUDPLine() = %#v, want %#v", got, tt.want)
			}
		})
	}
}

func Test_newNetUDP(t *testing.T) {
	tests := []struct {
		name    string
		file    string
		want    NetUDP
		wantErr bool
	}{
		{
			name: "udp file found, no error should come up",
			file: "fixtures/proc/net/udp",
			want: []*netUDPLine{
				&netUDPLine{
					Sl:        0,
					LocalAddr: []uint8{10, 0, 0, 5},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   0,
					RxQueue:   1,
					UID:       0,
				},
				&netUDPLine{
					Sl:        1,
					LocalAddr: []uint8{0, 0, 0, 0},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   1,
					RxQueue:   0,
					UID:       0,
				},
				&netUDPLine{
					Sl:        2,
					LocalAddr: []uint8{0, 0, 0, 0},
					LocalPort: 22,
					RemAddr:   []uint8{0, 0, 0, 0},
					RemPort:   0,
					St:        10,
					TxQueue:   1,
					RxQueue:   1,
					UID:       0,
				},
			},
			wantErr: false,
		},
		{
			name: "udp6 file found, no error should come up",
			file: "fixtures/proc/net/udp6",
			want: []*netUDPLine{
				&netUDPLine{
					Sl:        1315,
					LocalAddr: []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					LocalPort: 5355,
					RemAddr:   []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					RemPort:   0,
					St:        7,
					TxQueue:   0,
					RxQueue:   0,
					UID:       981,
				},
				&netUDPLine{
					Sl:        6073,
					LocalAddr: []uint8{0, 0, 128, 254, 0, 0, 0, 0, 255, 173, 225, 86, 9, 102, 124, 254},
					LocalPort: 51073,
					RemAddr:   []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
					RemPort:   0,
					St:        7,
					TxQueue:   0,
					RxQueue:   0,
					UID:       1000,
				},
			},
			wantErr: false,
		},
		{
			name:    "error case - file not found",
			file:    "somewhere over the rainbow",
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse error",
			file:    "fixtures/proc/net/udp_broken",
			want:    nil,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := newNetUDP(tt.file)
			if (err != nil) != tt.wantErr {
				t.Errorf("newNetUDP() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("newNetUDP() = %v, want %v", got, tt.want)
			}
		})
	}
}

func Test_newNetUDPSummary(t *testing.T) {
	tests := []struct {
		name    string
		file    string
		want    *NetUDPSummary
		wantErr bool
	}{
		{
			name:    "udp file found, no error should come up",
			file:    "fixtures/proc/net/udp",
			want:    &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3},
			wantErr: false,
		},
		{
			name:    "udp6 file found, no error should come up",
			file:    "fixtures/proc/net/udp6",
			want:    &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2},
			wantErr: false,
		},
		{
			name:    "error case - file not found",
			file:    "somewhere over the rainbow",
			want:    nil,
			wantErr: true,
		},
		{
			name:    "error case - parse error",
			file:    "fixtures/proc/net/udp_broken",
			want:    nil,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := newNetUDPSummary(tt.file)
			if (err != nil) != tt.wantErr {
				t.Errorf("newNetUDPSummary() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("newNetUDPSummary() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>