<commit_before>package gonavitia

import (
	"encoding/json"
	"github.com/aabizri/gonavitia/types"
	"github.com/pkg/errors"
	"strconv"
	"time"
)

const coverageEndpoint string = "coverage"

// A CoverageResults holds results for a coverage query
type CoverageResults struct {
	// The list of regions retrieved
	Regions []types.Region `json:"Regions"`

	// Paging information
	Paging Paging `json:"Pagination"`

	// Timing information
	createdAt   time.Time
	populatedAt time.Time

	// Held session
	session *Session
}

// Coverage lists the areas covered by the Navitia API
// count is the number of items to return, if count=0, then it will return the default number
// BUG: Count doesn't work, server-side
func (s *Session) Coverage(count uint) (*CoverageResults, error) {
	var results = &CoverageResults{session: s, createdAt: time.Now()}

	// Get the request
	url := s.APIURL + "/" + coverageEndpoint
	req, err := s.newRequest(url)
	if err != nil {
		return results, err
	}

	// Add the parameters if count != 0
	if count != 0 {
		params := req.URL.Query()
		countStr := strconv.FormatUint(uint64(count), 10)
		params.Add("count", countStr)
		req.URL.RawQuery = params.Encode()
	}

	// Execute the request
	resp, err := s.client.Do(req)

	// Check it
	if err != nil {
		return results, errors.Wrap(err, "errror while executing request")
	}
	if resp.StatusCode != 200 {
		return results, parseRemoteError(resp)
	}

	// Parse it
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(results)
	if err != nil {
		return results, errors.Wrap(err, "JSON decoding failed")
	}
	results.populatedAt = time.Now()

	// Return
	return results, nil
}

// RegionByID provides information about a specific region
// If the ID provided isn't an ID of a region, this WILL fail.
func (s *Session) RegionByID(id types.ID) (*CoverageResults, error) {
	var results = &CoverageResults{session: s, createdAt: time.Now()}

	// Build the URL
	url := s.APIURL + "/" + coverageEndpoint + "/" + string(id)

	// Get the request
	req, err := s.newRequest(url)
	if err != nil {
		return results, err
	}

	// Execute the request
	resp, err := s.client.Do(req)

	// Check it
	if err != nil {
		return results, errors.Wrap(err, "errror while executing request")
	}
	if resp.StatusCode != 200 {
		return results, parseRemoteError(resp)
	}

	// Parse it
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(results)
	if err != nil {
		return results, errors.Wrap(err, "JSON decoding failed")
	}
	results.populatedAt = time.Now()

	// Return
	return results, nil
}

// RegionByPos provides information about the region englobing the specific position
func (s *Session) RegionByPos(coords types.Coordinates) (*CoverageResults, error) {
	var results = &CoverageResults{session: s, createdAt: time.Now()}

	// Build the URL
	coordsFormatted := coords.QueryEscape()
	url := s.APIURL + "/" + coverageEndpoint + "/" + coordsFormatted

	// Get the request
	req, err := s.newRequest(url)
	if err != nil {
		return results, errors.Wrap(err, "error while preparing new request")
	}

	// Execute the request
	resp, err := s.client.Do(req)

	// Check it
	if err != nil {
		return results, errors.Wrap(err, "errror while executing request")
	}
	if resp.StatusCode != 200 {
		return results, parseRemoteError(resp)
	}

	// Parse it
	dec := json.NewDecoder(resp.Body)
	err = dec.Decode(results)
	if err != nil {
		return results, errors.Wrap(err, "JSON decoding failed")
	}
	results.populatedAt = time.Now()

	// Return
	return results, nil
}
<commit_msg>Upgrade Coverage to use the new request method<commit_after>package gonavitia

import (
	"github.com/aabizri/gonavitia/types"
	"net/url"
	"strconv"
)

const coverageEndpoint string = "coverage"

// A CoverageResults holds results for a coverage query
type CoverageResults struct {
	// The list of regions retrieved
	Regions []types.Region `json:"Regions"`

	// Paging information
	Paging Paging `json:"Pagination"`

	// Timing information
	Logging

	// Held session
	session *Session
}

type coverageRequest struct {
	Count uint
}

func (req coverageRequest) toURL() (url.Values, error) {
	params := url.Values{}

	if count := req.Count; count != 0 {
		countStr := strconv.FormatUint(uint64(count), 10)
		params["count"] = []string{countStr}
	}

	return params, nil
}

func (s *Session) coverage(url string, params coverageRequest) (*CoverageResults, error) {
	var results = &CoverageResults{session: s}
	err := s.request(url, params, results)
	return results, err
}

// Coverage lists the areas covered by the Navitia API
// count is the number of items to return, if count=0, then it will return the default number
// BUG: Count doesn't work, server-side
func (s *Session) Coverage(count uint) (*CoverageResults, error) {
	// Create the URL
	url := s.APIURL + "/" + coverageEndpoint

	// Create the query
	params := coverageRequest{Count: count}

	// Call and return
	return s.coverage(url, params)
}

// RegionByID provides information about a specific region
// If the ID provided isn't an ID of a region, this WILL fail.
func (s *Session) RegionByID(id types.ID) (*CoverageResults, error) {
	// Build the URL
	url := s.APIURL + "/" + coverageEndpoint + "/" + string(id)

	// Create the query
	params := coverageRequest{}

	// Call and return
	return s.coverage(url, params)
}

// RegionByPos provides information about the region englobing the specific position
func (s *Session) RegionByPos(coords types.Coordinates) (*CoverageResults, error) {
	// Build the URL
	coordsFormatted := coords.QueryEscape()
	url := s.APIURL + "/" + coverageEndpoint + "/" + coordsFormatted

	// Create the query
	params := coverageRequest{}

	// Call and return
	return s.coverage(url, params)
}
<|endoftext|>


<commit_before>package nfa

import (
	"fmt"
	"github.com/hydroo/gomochex/basic/set"
)

type State string

func (s State) IsEqual(e set.Element) bool {
	f, ok := e.(State)
	if ok == false {
		return false
	} //else {
	return s == f
	//}
}

type Letter string

func (s Letter) IsEqual(e set.Element) bool {
	f, ok := e.(Letter)
	if ok == false {
		return false
	} //else {
	return s == f
	//}
}

type Alphabet set.Set

type StateSet set.Set

type Nfa interface {
	Alphabet() Alphabet
	SetAlphabet(Alphabet)

	InitialStates() StateSet
	SetInitialStates(StateSet)

	FinalStates() StateSet
	SetFinalStates(StateSet)

	States() StateSet
	SetStates(StateSet)

	String() string

	Transition(State, Letter) StateSet
	SetTransition(State, Letter, StateSet)
	SetTransitionFunction(func(State, Letter) StateSet)
}

func NewNfa() Nfa {
	return &simpleNfa{set.NewSet(), set.NewSet(), set.NewSet(), make(map[State]map[Letter]StateSet), set.NewSet()}
}

/*****************************************************************************/

type simpleNfa struct {
	states        set.Set
	alphabet      set.Set
	initialStates set.Set
	transitions   map[State]map[Letter]StateSet
	finalStates   set.Set
}

func (A simpleNfa) Alphabet() Alphabet {
	return A.alphabet
}

func (A *simpleNfa) SetAlphabet(sigma Alphabet) {
	A.alphabet = sigma
}

func (A simpleNfa) InitialStates() StateSet {
	return A.initialStates
}

func (A *simpleNfa) SetInitialStates(S StateSet) {
	A.initialStates = S
}

func (A simpleNfa) FinalStates() StateSet {
	return A.finalStates
}

func (A *simpleNfa) SetFinalStates(F StateSet) {
	A.finalStates = F
}

func (A simpleNfa) States() StateSet {
	return A.states
}

func (A simpleNfa) SetStates(S StateSet) {
	A.states = S
}

func (A simpleNfa) String() string {
	ret := ""
	ret += fmt.Sprintln("states:", A.States())
	ret += fmt.Sprintln("alphabet:", A.Alphabet())
	ret += fmt.Sprintln("initial states:", A.InitialStates())
	ret += fmt.Sprintln("final states:", A.FinalStates())
	ret += fmt.Sprintln("transitions:")
	for i := 0; i < A.States().Size(); i += 1 {
		for j := 0; j < A.Alphabet().Size(); j += 1 {
			s, _ := A.States().At(i)
			a, _ := A.Alphabet().At(j)
			if S := A.Transition(s.(State), a.(Letter)); S.Size() > 0 {
				ret += fmt.Sprintln(" ", s, "--", a, "-->", S)
			}
		}
	}

	return ret
}

func (A simpleNfa) Transition(s State, l Letter) StateSet {

	var m map[Letter]StateSet
	if _, ok := A.transitions[s]; ok == false {
		return set.NewSet()
	} else {
		m = A.transitions[s]
	}

	var S StateSet
	if _, ok := m[l]; ok == false {
		S = set.NewSet()
	} else {
		S = m[l]
	}

	return S
}

func (A *simpleNfa) SetTransition(s State, l Letter, S StateSet) {

	var m map[Letter]StateSet
	if _, ok := A.transitions[s]; ok == false {
		m = make(map[Letter]StateSet)
		A.transitions[s] = m
	} else {
		m = A.transitions[s]
	}

	if S.Size() == 0 {
		delete(m, l)
	} else {
		m[l] = S
	}
}

func (A *simpleNfa) SetTransitionFunction(delta func(State, Letter) StateSet) {

	A.transitions = make(map[State]map[Letter]StateSet)

	for i := 0; i < A.States().Size(); i += 1 {
		for j := 0; j < A.Alphabet().Size(); j += 1 {

			q, _ := A.States().At(i)
			a, _ := A.Alphabet().At(j)

			Q := delta(q.(State), a.(Letter))

			if Q.Size() > 0 {
				A.SetTransition(q.(State), a.(Letter), Q)
			}
		}
	}
}
<commit_msg>fix: missing * in function that modifies type contents<commit_after>package nfa

import (
	"fmt"
	"github.com/hydroo/gomochex/basic/set"
)

type State string

func (s State) IsEqual(e set.Element) bool {
	f, ok := e.(State)
	if ok == false {
		return false
	} //else {
	return s == f
	//}
}

type Letter string

func (s Letter) IsEqual(e set.Element) bool {
	f, ok := e.(Letter)
	if ok == false {
		return false
	} //else {
	return s == f
	//}
}

type Alphabet set.Set

type StateSet set.Set

type Nfa interface {
	Alphabet() Alphabet
	SetAlphabet(Alphabet)

	InitialStates() StateSet
	SetInitialStates(StateSet)

	FinalStates() StateSet
	SetFinalStates(StateSet)

	States() StateSet
	SetStates(StateSet)

	String() string

	Transition(State, Letter) StateSet
	SetTransition(State, Letter, StateSet)
	SetTransitionFunction(func(State, Letter) StateSet)
}

func NewNfa() Nfa {
	return &simpleNfa{set.NewSet(), set.NewSet(), set.NewSet(), make(map[State]map[Letter]StateSet), set.NewSet()}
}

/*****************************************************************************/

type simpleNfa struct {
	states        set.Set
	alphabet      set.Set
	initialStates set.Set
	transitions   map[State]map[Letter]StateSet
	finalStates   set.Set
}

func (A simpleNfa) Alphabet() Alphabet {
	return A.alphabet
}

func (A *simpleNfa) SetAlphabet(sigma Alphabet) {
	A.alphabet = sigma
}

func (A simpleNfa) InitialStates() StateSet {
	return A.initialStates
}

func (A *simpleNfa) SetInitialStates(S StateSet) {
	A.initialStates = S
}

func (A simpleNfa) FinalStates() StateSet {
	return A.finalStates
}

func (A *simpleNfa) SetFinalStates(F StateSet) {
	A.finalStates = F
}

func (A simpleNfa) States() StateSet {
	return A.states
}

func (A *simpleNfa) SetStates(S StateSet) {
	A.states = S
}

func (A simpleNfa) String() string {
	ret := ""
	ret += fmt.Sprintln("states:", A.States())
	ret += fmt.Sprintln("alphabet:", A.Alphabet())
	ret += fmt.Sprintln("initial states:", A.InitialStates())
	ret += fmt.Sprintln("final states:", A.FinalStates())
	ret += fmt.Sprintln("transitions:")
	for i := 0; i < A.States().Size(); i += 1 {
		for j := 0; j < A.Alphabet().Size(); j += 1 {
			s, _ := A.States().At(i)
			a, _ := A.Alphabet().At(j)
			if S := A.Transition(s.(State), a.(Letter)); S.Size() > 0 {
				ret += fmt.Sprintln(" ", s, "--", a, "-->", S)
			}
		}
	}

	return ret
}

func (A simpleNfa) Transition(s State, l Letter) StateSet {

	var m map[Letter]StateSet
	if _, ok := A.transitions[s]; ok == false {
		return set.NewSet()
	} else {
		m = A.transitions[s]
	}

	var S StateSet
	if _, ok := m[l]; ok == false {
		S = set.NewSet()
	} else {
		S = m[l]
	}

	return S
}

func (A *simpleNfa) SetTransition(s State, l Letter, S StateSet) {

	var m map[Letter]StateSet
	if _, ok := A.transitions[s]; ok == false {
		m = make(map[Letter]StateSet)
		A.transitions[s] = m
	} else {
		m = A.transitions[s]
	}

	if S.Size() == 0 {
		delete(m, l)
	} else {
		m[l] = S
	}
}

func (A *simpleNfa) SetTransitionFunction(delta func(State, Letter) StateSet) {

	A.transitions = make(map[State]map[Letter]StateSet)

	for i := 0; i < A.States().Size(); i += 1 {
		for j := 0; j < A.Alphabet().Size(); j += 1 {

			q, _ := A.States().At(i)
			a, _ := A.Alphabet().At(j)

			Q := delta(q.(State), a.(Letter))

			if Q.Size() > 0 {
				A.SetTransition(q.(State), a.(Letter), Q)
			}
		}
	}
}
<|endoftext|>


<commit_before>package checkpoint

import (
	"io/ioutil"
	"path/filepath"
	"reflect"
	"testing"
	"time"
)

func TestCheck(t *testing.T) {
	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	actual, err := Check(&CheckParams{
		Product: "test",
		Version: "1.0",
	})

	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheck_cache(t *testing.T) {
	dir, err := ioutil.TempDir("", "checkpoint")
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	var actual *CheckResponse
	for i := 0; i < 5; i++ {
		var err error
		actual, err = Check(&CheckParams{
			Product:   "test",
			Version:   "1.0",
			CacheFile: filepath.Join(dir, "cache"),
		})
		if err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheck_cacheNested(t *testing.T) {
	dir, err := ioutil.TempDir("", "checkpoint")
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	var actual *CheckResponse
	for i := 0; i < 5; i++ {
		var err error
		actual, err = Check(&CheckParams{
			Product:   "test",
			Version:   "1.0",
			CacheFile: filepath.Join(dir, "nested", "cache"),
		})
		if err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheckInterval(t *testing.T) {
	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	params := &CheckParams{
		Product: "test",
		Version: "1.0",
	}

	calledCh := make(chan struct{})
	checkFn := func(actual *CheckResponse, err error) {
		defer close(calledCh)
		if err != nil {
			t.Fatalf("err: %s", err)
		}

		if !reflect.DeepEqual(actual, expected) {
			t.Fatalf("bad: %#v", actual)
		}
	}

	doneCh := CheckInterval(params, 500*time.Millisecond, checkFn)
	defer close(doneCh)

	select {
	case <-calledCh:
	case <-time.After(time.Second):
		t.Fatalf("timeout")
	}
}

func TestRandomStagger(t *testing.T) {
	intv := 24 * time.Hour
	min := 18 * time.Hour
	max := 30 * time.Hour
	for i := 0; i < 1000; i++ {
		out := randomStagger(intv)
		if out < min || out > max {
			t.Fatalf("bad: %v", out)
		}
	}
}
<commit_msg>Add tests<commit_after>package checkpoint

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"
	"time"
)

func TestCheck(t *testing.T) {
	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	actual, err := Check(&CheckParams{
		Product: "test",
		Version: "1.0",
	})

	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheck_disabled(t *testing.T) {
	os.Setenv("CHECKPOINT_DISABLE", "1")
	defer os.Setenv("CHECKPOINT_DISABLE", "")

	expected := &CheckResponse{}

	actual, err := Check(&CheckParams{
		Product: "test",
		Version: "1.0",
	})

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

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("expected %+v to equal %+v", actual, expected)
	}
}

func TestCheck_cache(t *testing.T) {
	dir, err := ioutil.TempDir("", "checkpoint")
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	var actual *CheckResponse
	for i := 0; i < 5; i++ {
		var err error
		actual, err = Check(&CheckParams{
			Product:   "test",
			Version:   "1.0",
			CacheFile: filepath.Join(dir, "cache"),
		})
		if err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheck_cacheNested(t *testing.T) {
	dir, err := ioutil.TempDir("", "checkpoint")
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	var actual *CheckResponse
	for i := 0; i < 5; i++ {
		var err error
		actual, err = Check(&CheckParams{
			Product:   "test",
			Version:   "1.0",
			CacheFile: filepath.Join(dir, "nested", "cache"),
		})
		if err != nil {
			t.Fatalf("err: %s", err)
		}
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}

func TestCheckInterval(t *testing.T) {
	expected := &CheckResponse{
		Product:             "test",
		CurrentVersion:      "1.0",
		CurrentReleaseDate:  0,
		CurrentDownloadURL:  "http://www.hashicorp.com",
		CurrentChangelogURL: "http://www.hashicorp.com",
		ProjectWebsite:      "http://www.hashicorp.com",
		Outdated:            false,
		Alerts:              []*CheckAlert{},
	}

	params := &CheckParams{
		Product: "test",
		Version: "1.0",
	}

	calledCh := make(chan struct{})
	checkFn := func(actual *CheckResponse, err error) {
		defer close(calledCh)
		if err != nil {
			t.Fatalf("err: %s", err)
		}

		if !reflect.DeepEqual(actual, expected) {
			t.Fatalf("bad: %#v", actual)
		}
	}

	doneCh := CheckInterval(params, 500*time.Millisecond, checkFn)
	defer close(doneCh)

	select {
	case <-calledCh:
	case <-time.After(time.Second):
		t.Fatalf("timeout")
	}
}

func TestCheckInterval_disabled(t *testing.T) {
	os.Setenv("CHECKPOINT_DISABLE", "1")
	defer os.Setenv("CHECKPOINT_DISABLE", "")

	params := &CheckParams{
		Product: "test",
		Version: "1.0",
	}

	calledCh := make(chan struct{})
	checkFn := func(actual *CheckResponse, err error) {
		defer close(calledCh)
	}

	doneCh := CheckInterval(params, 500*time.Millisecond, checkFn)
	defer close(doneCh)

	select {
	case <-calledCh:
		t.Fatal("expected callback to not invoke")
	case <-time.After(time.Second):
	}
}

func TestRandomStagger(t *testing.T) {
	intv := 24 * time.Hour
	min := 18 * time.Hour
	max := 30 * time.Hour
	for i := 0; i < 1000; i++ {
		out := randomStagger(intv)
		if out < min || out > max {
			t.Fatalf("bad: %v", out)
		}
	}
}
<|endoftext|>


<commit_before>package cheshire

import (
	"github.com/trendrr/cheshire-golang/dynmap"
	"log"
)

// what Strest protocol version we are using.
const StrestVersion = float32(2)

// Standard STREST request.
// See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec
type Request struct {
	dynmap.DynMap

	// Strest struct {
	// 	Version float32        `json:"v"`
	// 	Method  string         `json:"method"`
	// 	Uri     string         `json:"uri"`
	// 	Params  *dynmap.DynMap `json:"params"`

	// 	Txn struct {
	// 		Id     string `json:"id"`
	// 		Accept string `json:"accept"`
	// 	} `json:"txn"`
	// } `json:"strest"`
}

// Create a new request object.
// Values are all set to defaults
func NewRequest(uri, method string) *Request {
	request := &Request{*dynmap.NewDynMap()}
	request.PutWithDot("strest.params", dynmap.NewDynMap())
	request.PutWithDot("strest.v", StrestVersion)
	request.PutWithDot("strest.uri", uri)
	request.PutWithDot("strest.method", method)
	request.PutWithDot("strest.txn.accept", "single")
	return request
}

func (this *Request) ToDynMap() *dynmap.DynMap {
	return &this.DynMap
}

func (this *Request) Method() string {
	return this.MustString("strest.method", "")
}

func (this *Request) SetMethod(method string) {
	this.PutWithDot("strest.method", method)
}

func (this *Request) Uri() string {
	return this.MustString("strest.uri", "")
}

func (this *Request) SetUri(uri string) {
	this.PutWithDot("strest.uri", uri)
}

func (this *Request) Params() *dynmap.DynMap {
	m, ok := this.DynMap.DynMap("strest.params")
	if !ok {
		this.PutIfAbsentWithDot("strest.params", dynmap.NewDynMap())
		m, ok = this.DynMap.DynMap("strest.params")
	}
	return m
}

func (this *Request) SetParams(params *dynmap.DynMap) {
	this.PutWithDot("strest.params", params)
}

//return the txnid.
func (this *Request) TxnId() string {
	return this.MustString("strest.txn.id", "")
}

func (this *Request) SetTxnId(id string) {
	this.PutWithDot("strest.txn.id", id)
}

func (this *Request) TxnAccept() string {
	return this.MustString("strest.txn.accept", "single")
}

func (this *Request) SetTxnAccept(accept string) {
	this.PutWithDot("strest.txn.accept", accept)
}

// Creates a new response based on this request.
// auto fills the txn id
func (this *Request) NewResponse() *Response {
	response := NewResponse()
	response.SetTxnId(this.TxnId())
	return response
}

// Standard STREST response
// See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec
type Response struct {
	dynmap.DynMap
}

func (this *Response) TxnId() string {
	return this.MustString("strest.txn.id", "")
}

func (this *Response) SetTxnId(id string) {
	this.PutWithDot("strest.txn.id", id)
}

func (this *Response) TxnStatus() string {
	return this.MustString("strest.txn.status", "")
}

func (this *Response) SetTxnStatus(status string) {
	this.PutWithDot("strest.txn.status", status)
}

func (this *Response) SetStatus(code int, message string) {
	this.SetStatusCode(code)
	this.SetStatusMessage(message)
}

func (this *Response) StatusCode() int {
	return this.MustInt("status.code", 200)
}

func (this *Response) SetStatusCode(code int) {
	this.PutWithDot("status.code", code)
}

func (this *Response) StatusMessage() string {
	return this.MustString("status.message", "")
}

func (this *Response) SetStatusMessage(message string) {
	this.PutWithDot("status.message", message)
}

func (this *Response) ToDynMap() *dynmap.DynMap {
	return &this.DynMap
}

// Create a new response object.
// Values are all set to defaults
func NewResponse() *Response {
	response := &Response{*dynmap.NewDynMap()}
	response.SetStatusMessage("OK")
	response.SetStatusCode(200)
	response.SetTxnStatus("completed")
	response.PutWithDot("strest.v", StrestVersion)
	return response
}

func NewErrorResponse(request *Request, code int, message string) *Response {
	response := request.NewResponse()
	response.SetStatus(code, message)
	return response
}

type Connection interface {
	//writes the response to the underlying channel
	// i.e. either to an http response writer or json socket.
	Write(*Response) (int, error)
}

type RouteMatcher interface {
	// A controller matches the given method, path
	Match(string, string) Controller
	// Registers a controller for the specified methods
	Register([]string, Controller)
}
type ServerConfig struct {
	*dynmap.DynMap
	Router RouteMatcher
}

// Creates a new server config with a default routematcher
func NewServerConfig() *ServerConfig {
	return &ServerConfig{dynmap.NewDynMap(), NewDefaultRouter()}
}

// Registers a controller with the RouteMatcher.
// shortcut to conf.Router.Register(controller)
func (this *ServerConfig) Register(methods []string, controller Controller) {
	log.Println("Registering: ", methods, " ", controller.Config().Route, " ", controller)
	this.Router.Register(methods, controller)
}

// Configuration for a specific controller.
type ControllerConfig struct {
	Route string
}

func NewControllerConfig(route string) *ControllerConfig {
	return &ControllerConfig{Route: route}
}

// a Controller object
type Controller interface {
	Config() *ControllerConfig
	HandleRequest(*Request, Connection)
}

type DefaultController struct {
	Handlers map[string]func(*Request, Connection)
	Conf     *ControllerConfig
}

func (this *DefaultController) Config() *ControllerConfig {
	return this.Conf
}
func (this *DefaultController) HandleRequest(request *Request, conn Connection) {
	handler := this.Handlers[request.Method()]
	if handler == nil {
		handler = this.Handlers["ALL"]
	}
	if handler == nil {
		//not found!
		//TODO: method not allowed
		return
	}
	handler(request, conn)
}

// creates a new controller for the specified route for a specific method types (GET, POST, PUT, ect)
func NewController(route string, methods []string, handler func(*Request, Connection)) *DefaultController {
	// def := new(DefaultController)
	// def.Conf = NewConfig(route)

	def := &DefaultController{Handlers: make(map[string]func(*Request, Connection)), Conf: NewControllerConfig(route)}
	for _, m := range methods {
		def.Handlers[m] = handler
	}
	return def
}

// creates a new controller that will process all method types
func NewControllerAll(route string, handler func(*Request, Connection)) *DefaultController {
	return NewController(route, []string{"ALL"}, handler)
}
<commit_msg>cleaner error response<commit_after>package cheshire

import (
	"github.com/trendrr/cheshire-golang/dynmap"
	"log"
)

// what Strest protocol version we are using.
const StrestVersion = float32(2)

// Standard STREST request.
// See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec
type Request struct {
	dynmap.DynMap

	// Strest struct {
	// 	Version float32        `json:"v"`
	// 	Method  string         `json:"method"`
	// 	Uri     string         `json:"uri"`
	// 	Params  *dynmap.DynMap `json:"params"`

	// 	Txn struct {
	// 		Id     string `json:"id"`
	// 		Accept string `json:"accept"`
	// 	} `json:"txn"`
	// } `json:"strest"`
}

// Create a new request object.
// Values are all set to defaults
func NewRequest(uri, method string) *Request {
	request := &Request{*dynmap.NewDynMap()}
	request.PutWithDot("strest.params", dynmap.NewDynMap())
	request.PutWithDot("strest.v", StrestVersion)
	request.PutWithDot("strest.uri", uri)
	request.PutWithDot("strest.method", method)
	request.PutWithDot("strest.txn.accept", "single")
	return request
}

func (this *Request) ToDynMap() *dynmap.DynMap {
	return &this.DynMap
}

func (this *Request) Method() string {
	return this.MustString("strest.method", "")
}

func (this *Request) SetMethod(method string) {
	this.PutWithDot("strest.method", method)
}

func (this *Request) Uri() string {
	return this.MustString("strest.uri", "")
}

func (this *Request) SetUri(uri string) {
	this.PutWithDot("strest.uri", uri)
}

func (this *Request) Params() *dynmap.DynMap {
	m, ok := this.DynMap.DynMap("strest.params")
	if !ok {
		this.PutIfAbsentWithDot("strest.params", dynmap.NewDynMap())
		m, ok = this.DynMap.DynMap("strest.params")
	}
	return m
}

func (this *Request) SetParams(params *dynmap.DynMap) {
	this.PutWithDot("strest.params", params)
}

//return the txnid.
func (this *Request) TxnId() string {
	return this.MustString("strest.txn.id", "")
}

func (this *Request) SetTxnId(id string) {
	this.PutWithDot("strest.txn.id", id)
}

func (this *Request) TxnAccept() string {
	return this.MustString("strest.txn.accept", "single")
}

func (this *Request) SetTxnAccept(accept string) {
	this.PutWithDot("strest.txn.accept", accept)
}

// Creates a new response based on this request.
// auto fills the txn id
func (this *Request) NewResponse() *Response {
	response := NewResponse()
	response.SetTxnId(this.TxnId())
	return response
}

func (this *Request) NewError(code int, message string) *Response {
	response := this.NewResponse()
	response.SetStatus(code, message)
	return response
}

// Standard STREST response
// See protocol spec https://github.com/trendrr/strest-server/wiki/STREST-Protocol-Spec
type Response struct {
	dynmap.DynMap
}

func (this *Response) TxnId() string {
	return this.MustString("strest.txn.id", "")
}

func (this *Response) SetTxnId(id string) {
	this.PutWithDot("strest.txn.id", id)
}

func (this *Response) TxnStatus() string {
	return this.MustString("strest.txn.status", "")
}

func (this *Response) SetTxnStatus(status string) {
	this.PutWithDot("strest.txn.status", status)
}

func (this *Response) SetStatus(code int, message string) {
	this.SetStatusCode(code)
	this.SetStatusMessage(message)
}

func (this *Response) StatusCode() int {
	return this.MustInt("status.code", 200)
}

func (this *Response) SetStatusCode(code int) {
	this.PutWithDot("status.code", code)
}

func (this *Response) StatusMessage() string {
	return this.MustString("status.message", "")
}

func (this *Response) SetStatusMessage(message string) {
	this.PutWithDot("status.message", message)
}

func (this *Response) ToDynMap() *dynmap.DynMap {
	return &this.DynMap
}

// Create a new response object.
// Values are all set to defaults
func NewResponse() *Response {
	response := &Response{*dynmap.NewDynMap()}
	response.SetStatusMessage("OK")
	response.SetStatusCode(200)
	response.SetTxnStatus("completed")
	response.PutWithDot("strest.v", StrestVersion)
	return response
}

type Connection interface {
	//writes the response to the underlying channel
	// i.e. either to an http response writer or json socket.
	Write(*Response) (int, error)
}

type RouteMatcher interface {
	// A controller matches the given method, path
	Match(string, string) Controller
	// Registers a controller for the specified methods
	Register([]string, Controller)
}
type ServerConfig struct {
	*dynmap.DynMap
	Router RouteMatcher
}

// Creates a new server config with a default routematcher
func NewServerConfig() *ServerConfig {
	return &ServerConfig{dynmap.NewDynMap(), NewDefaultRouter()}
}

// Registers a controller with the RouteMatcher.
// shortcut to conf.Router.Register(controller)
func (this *ServerConfig) Register(methods []string, controller Controller) {
	log.Println("Registering: ", methods, " ", controller.Config().Route, " ", controller)
	this.Router.Register(methods, controller)
}

// Configuration for a specific controller.
type ControllerConfig struct {
	Route string
}

func NewControllerConfig(route string) *ControllerConfig {
	return &ControllerConfig{Route: route}
}

// a Controller object
type Controller interface {
	Config() *ControllerConfig
	HandleRequest(*Request, Connection)
}

type DefaultController struct {
	Handlers map[string]func(*Request, Connection)
	Conf     *ControllerConfig
}

func (this *DefaultController) Config() *ControllerConfig {
	return this.Conf
}
func (this *DefaultController) HandleRequest(request *Request, conn Connection) {
	handler := this.Handlers[request.Method()]
	if handler == nil {
		handler = this.Handlers["ALL"]
	}
	if handler == nil {
		//not found!
		//TODO: method not allowed
		return
	}
	handler(request, conn)
}

// creates a new controller for the specified route for a specific method types (GET, POST, PUT, ect)
func NewController(route string, methods []string, handler func(*Request, Connection)) *DefaultController {
	// def := new(DefaultController)
	// def.Conf = NewConfig(route)

	def := &DefaultController{Handlers: make(map[string]func(*Request, Connection)), Conf: NewControllerConfig(route)}
	for _, m := range methods {
		def.Handlers[m] = handler
	}
	return def
}

// creates a new controller that will process all method types
func NewControllerAll(route string, handler func(*Request, Connection)) *DefaultController {
	return NewController(route, []string{"ALL"}, handler)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/golang/protobuf/proto"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	metaFile = flag.String("meta", "", "meta file generated via fs.meta.save")
)

func main() {
	flag.Parse()

	dst, err := os.OpenFile(*metaFile, os.O_RDONLY, 0644)
	if err != nil {
		log.Fatalf("failed to open %s: %v", *metaFile, err)
	}
	defer dst.Close()

	err = walkMetaFile(dst)
	if err != nil {
		log.Fatalf("failed to visit %s: %v", *metaFile, err)
	}

}

func walkMetaFile(dst *os.File) error {

	sizeBuf := make([]byte, 4)

	for {
		if n, err := dst.Read(sizeBuf); n != 4 {
			if err == io.EOF {
				return nil
			}
			return err
		}

		size := util.BytesToUint32(sizeBuf)

		data := make([]byte, int(size))

		if n, err := dst.Read(data); n != len(data) {
			return err
		}

		fullEntry := &filer_pb.FullEntry{}
		if err := proto.Unmarshal(data, fullEntry); err != nil {
			return err
		}

		fmt.Fprintf(os.Stdout, "file %s %v\n", util.FullPath(fullEntry.Dir).Child(fullEntry.Entry.Name), fullEntry.Entry.Attributes.String())
		for i, chunk := range fullEntry.Entry.Chunks {
			fmt.Fprintf(os.Stdout, "  chunk %d %v\n", i+1, chunk.String())
		}

	}

}
<commit_msg>Add the additional meta log<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/golang/protobuf/proto"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	metaFile = flag.String("meta", "", "meta file generated via fs.meta.save")
)

func main() {
	flag.Parse()

	dst, err := os.OpenFile(*metaFile, os.O_RDONLY, 0644)
	if err != nil {
		log.Fatalf("failed to open %s: %v", *metaFile, err)
	}
	defer dst.Close()

	err = walkMetaFile(dst)
	if err != nil {
		log.Fatalf("failed to visit %s: %v", *metaFile, err)
	}

}

func walkMetaFile(dst *os.File) error {

	sizeBuf := make([]byte, 4)

	for {
		if n, err := dst.Read(sizeBuf); n != 4 {
			if err == io.EOF {
				return nil
			}
			return err
		}

		size := util.BytesToUint32(sizeBuf)

		data := make([]byte, int(size))

		if n, err := dst.Read(data); n != len(data) {
			return err
		}

		fullEntry := &filer_pb.FullEntry{}
		if err := proto.Unmarshal(data, fullEntry); err != nil {
			return err
		}

		fmt.Fprintf(os.Stdout, "file %s %v\n", util.FullPath(fullEntry.Dir).Child(fullEntry.Entry.Name), fullEntry.Entry.Attributes.String())
		for i, chunk := range fullEntry.Entry.Chunks {
			fmt.Fprintf(os.Stdout, "  chunk: %d %v %d,%x%08x\n", i+1, chunk, chunk.Fid.VolumeId, chunk.Fid.FileKey, chunk.Fid.Cookie)
		}

	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	sci "github.com/samuell/scipipe"
	"runtime"
)

func main() {
	sci.InitLogAudit()

	runtime.GOMAXPROCS(4)
	cmb := NewCombinatoricsTask()

	// An abc file printer
	abc := sci.Sh("echo {p:a} {p:b} {p:c} > {o:out}; sleep 1")
	abc.Spawn = true
	abc.OutPathFuncs["out"] = func() string {
		return fmt.Sprintf(
			"%s_%s_%s.txt",
			abc.Params["a"],
			abc.Params["b"],
			abc.Params["c"],
		)
	}

	// A printer task
	prt := sci.Sh("cat {i:in} >> log.txt")
	prt.Spawn = false

	// Connection info
	abc.ParamPorts["a"] = cmb.A
	abc.ParamPorts["b"] = cmb.B
	abc.ParamPorts["c"] = cmb.C
	prt.InPorts["in"] = abc.OutPorts["out"]

	pl := sci.NewPipeline()
	pl.AddProcs(cmb, abc, prt)
	pl.Run()
}

type CombinatoricsTask struct {
	sci.BaseProcess
	A chan string
	B chan string
	C chan string
}

func NewCombinatoricsTask() *CombinatoricsTask {
	return &CombinatoricsTask{
		A: make(chan string, sci.BUFSIZE),
		B: make(chan string, sci.BUFSIZE),
		C: make(chan string, sci.BUFSIZE),
	}
}

func (proc *CombinatoricsTask) Run() {
	defer close(proc.A)
	defer close(proc.B)
	defer close(proc.C)

	for _, a := range sci.SS("a1", "a2", "a3") {
		for _, b := range sci.SS("b1", "b2", "b3") {
			for _, c := range sci.SS("c1", "c2", "c3") {
				proc.A <- a
				proc.B <- b
				proc.C <- c
			}
		}
	}
}
<commit_msg>Updating example 09 to new OutPathFunc API<commit_after>package main

import (
	"fmt"
	sci "github.com/samuell/scipipe"
	"runtime"
)

func main() {
	sci.InitLogAudit()

	runtime.GOMAXPROCS(4)
	cmb := NewCombinatoricsTask()

	// An abc file printer
	abc := sci.Sh("echo {p:a} {p:b} {p:c} > {o:out}; sleep 1")
	abc.Spawn = true
	abc.OutPathFuncs["out"] = func(t *sci.ShellTask) string {
		return fmt.Sprintf(
			"%s_%s_%s.txt",
			t.Params["a"],
			t.Params["b"],
			t.Params["c"],
		)
	}

	// A printer task
	prt := sci.Sh("cat {i:in} >> log.txt")
	prt.Spawn = false

	// Connection info
	abc.ParamPorts["a"] = cmb.A
	abc.ParamPorts["b"] = cmb.B
	abc.ParamPorts["c"] = cmb.C
	prt.InPorts["in"] = abc.OutPorts["out"]

	pl := sci.NewPipeline()
	pl.AddProcs(cmb, abc, prt)
	pl.Run()
}

type CombinatoricsTask struct {
	sci.BaseProcess
	A chan string
	B chan string
	C chan string
}

func NewCombinatoricsTask() *CombinatoricsTask {
	return &CombinatoricsTask{
		A: make(chan string, sci.BUFSIZE),
		B: make(chan string, sci.BUFSIZE),
		C: make(chan string, sci.BUFSIZE),
	}
}

func (proc *CombinatoricsTask) Run() {
	defer close(proc.A)
	defer close(proc.B)
	defer close(proc.C)

	for _, a := range sci.SS("a1", "a2", "a3") {
		for _, b := range sci.SS("b1", "b2", "b3") {
			for _, c := range sci.SS("c1", "c2", "c3") {
				proc.A <- a
				proc.B <- b
				proc.C <- c
			}
		}
	}
}
<|endoftext|>


<commit_before>package mips

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

var CPU_TESTS = map[string]string{
	"raw_hazard": `REGISTERS
R1 1
MEMORY
0 7
CODE
      LD    R2,    0(R0)
      DADDI R3,    R2,    #3
      SD    0(R1), R3
`, "branching_simple": `REGISTERS
R1 2
MEMORY
0 7
CODE
Start: DADDI R1, R1, #-1
       BNEZ  R1, Start
       LD    R4, #0
`, "basic": `REGISTERS
R1 2
R3 22
MEMORY
0 7
1 6
2 20
CODE
Loop: LD    R2,    0(R1)
      DADD  R4,    R2,    R3
      SD    0(R1), R4
`, "provided0": `REGISTERS
MEMORY
CODE
      LD    R2,     0(R1)
      DADD  R4,     R2,    R3
      SD    0(R1),  R4
      BNEZ  R4,     NEXT
NEXT: DADD  R1,     R1,    R3
      DADDI R2,     R1,    #8
`, "provided1": `REGISTERS
R1  16
R3  42
MEMORY
16  60
8   40
CODE
Loop: LD    R2,     0(R1)
      DADD  R4,     R2,     R3
      SD    0(R1),  R4
      DADDI R1,     R1,     #-8
      BNEZ  R1,     Loop
      DADD  R3,     R2,     R4
`, "provided2": `REGISTERS
R1 16
R2 16
R3 20
R4 2
R5 8
R7 8
MEMORY
16  8
8  12
CODE
Loop: LD    R2,    0(R1)
      DADD  R4,    R2,    R3
      SD    0(R1), R4
      DADDI R1,    R1,    #-8
      BNEZ  R1,   Loop
      DADDI R1,    R1,    #-8
      BNEZ  R1,    Next
      DADD  R3,    R4,    R5
Next: LD    R6,    0(R5)
      DADD  R4,    R2,    R3
      SD    0(R5), R4
      DADDI R1,    R1,    #-8
`,
}

func xTestRunningEmptyCPU(t *testing.T) {
	cpu := NewCPU()
	if cpu == nil {
		t.Error("cpu == nil")
	}
	err := cpu.Run(100)
	if err != nil {
		t.Error(err)
	}
}

func xTestRAWHazard(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["raw_hazard"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	//cpu.ForwardingEnabled = true
	err = cpu.Run(15)
	if err != nil {
		t.Error(err)
	}
	fmt.Println(cpu.RenderTiming())
	fmt.Println(cpu)

	if cpu.Ram[1] != 10 {
		t.Fatal(cpu.Ram[1], "!=", 10)
	}
}

func xTestBranching(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["branching_simple"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	cpu.ForwardingEnabled = true
	cpu.BranchMode = branchModePredictNotTaken
	cpu.BranchMode = branchModePredictTaken
	err = cpu.Run(35)
	if err != nil {
		t.Error(err)
	}
	fmt.Println(cpu.RenderTiming())

	if cpu.Registers.Get(R1) != 0 {
		t.Fatal(cpu.Registers.Get(R1), "!=", 0)
	}
}

func xTestRunningBasicProgram(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["basic"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	err = cpu.Run(100)
	if err != nil {
		t.Error(err)
	}
	expected := `REGISTERS:
R1 = 2
R2 = 20
R3 = 22
R4 = 42
MEMORY:
0x0 = 7
0x1 = 6
0x2 = 42`
	if cpu.String() != expected {
		t.Error(fmt.Sprintf("'%s' != '%s'", cpu.String(), expected))
	}
}

func TestSameOutputRegardlessOfFlags(t *testing.T) {
	for testName, test := range CPU_TESTS {
		if strings.HasPrefix(testName, "provided0") == false {
			continue
		}
		cpu, _ := ParseCPUString(test)
		if err := cpu.Run(100); err != nil{

		fmt.Println("######### PROGRAM ", testName)
		fmt.Println("######### CODE")
		fmt.Println(test)
		fmt.Println("######### Result")
		fmt.Println(cpu.String())
		fmt.Println("######### Timing")
		fmt.Println(cpu.RenderTiming())

			t.Fatal(testName, "nf", err)
		}

		a := cpu.String()

		cpu, _ = ParseCPUString(test)
		cpu.ForwardingEnabled = true
		cpu.BranchMode = branchModePredictTaken
		if err := cpu.Run(100); err != nil{
			t.Fatal(testName, "f, bt", err)
		}

		b := cpu.String()
		timing := cpu.RenderTiming()

		cpu, _ = ParseCPUString(test)
		cpu.ForwardingEnabled = true
		cpu.BranchMode = branchModePredictNotTaken
		if err := cpu.Run(100); err != nil{
			t.Fatal(testName, "f, bnt", err)
		}

		c := cpu.String()

		if a != b {
			t.Error("'%s' != '%s'", a, b)
		}
		if b != c {
			t.Error("'%s' != '%s'", b, c)
		}
		fmt.Println("######### PROGRAM ", testName)
		fmt.Println("######### CODE")
		fmt.Println(test)
		fmt.Println("######### Result")
		fmt.Println(a)
		fmt.Println("######### Timing")
		fmt.Println(timing)
	}
}
<commit_msg>Improve test output<commit_after>package mips

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

var CPU_TESTS = map[string]string{
	"raw_hazard": `REGISTERS
R1 1
MEMORY
0 7
CODE
      LD    R2,    0(R0)
      DADDI R3,    R2,    #3
      SD    0(R1), R3
`, "branching_simple": `REGISTERS
R1 2
MEMORY
0 7
CODE
Start: DADDI R1, R1, #-1
       BNEZ  R1, Start
       LD    R4, #0
`, "basic": `REGISTERS
R1 2
R3 22
MEMORY
0 7
1 6
2 20
CODE
Loop: LD    R2,    0(R1)
      DADD  R4,    R2,    R3
      SD    0(R1), R4
`, "provided0": `REGISTERS
MEMORY
CODE
      LD    R2,     0(R1)
      DADD  R4,     R2,    R3
      SD    0(R1),  R4
      BNEZ  R4,     NEXT
NEXT: DADD  R1,     R1,    R3
      DADDI R2,     R1,    #8
`, "provided1": `REGISTERS
R1  16
R3  42
MEMORY
16  60
8   40
CODE
Loop: LD    R2,     0(R1)
      DADD  R4,     R2,     R3
      SD    0(R1),  R4
      DADDI R1,     R1,     #-8
      BNEZ  R1,     Loop
      DADD  R3,     R2,     R4
`, "provided2": `REGISTERS
R1 16
R2 16
R3 20
R4 2
R5 8
R7 8
MEMORY
16  8
8  12
CODE
Loop: LD    R2,    0(R1)
      DADD  R4,    R2,    R3
      SD    0(R1), R4
      DADDI R1,    R1,    #-8
      BNEZ  R1,   Loop
      DADDI R1,    R1,    #-8
      BNEZ  R1,    Next
      DADD  R3,    R4,    R5
Next: LD    R6,    0(R5)
      DADD  R4,    R2,    R3
      SD    0(R5), R4
      DADDI R1,    R1,    #-8
`,
}

func TestRunningEmptyCPU(t *testing.T) {
	cpu := NewCPU()
	if cpu == nil {
		t.Error("cpu == nil")
	}
	err := cpu.Run(100)
	if err != nil {
		t.Error(err)
	}
}

func TestRAWHazard(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["raw_hazard"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	//cpu.ForwardingEnabled = true
	err = cpu.Run(35)
	if err != nil {
		t.Error(err)
	}
	fmt.Println(cpu.RenderTiming())
	fmt.Println(cpu)

	if cpu.Ram[1] != 10 {
		t.Fatal(cpu.Ram[1], "!=", 10)
	}
}

func TestBranching(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["branching_simple"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	cpu.ForwardingEnabled = true
	cpu.BranchMode = branchModePredictNotTaken
	cpu.BranchMode = branchModePredictTaken
	err = cpu.Run(35)
	if err != nil {
		t.Error(err)
	}
	fmt.Println(cpu.RenderTiming())

	if cpu.Registers.Get(R1) != 0 {
		t.Fatal(cpu.Registers.Get(R1), "!=", 0)
	}
}

func TestRunningBasicProgram(t *testing.T) {
	cpu, err := ParseCPUString(CPU_TESTS["basic"])
	if cpu == nil {
		t.Error("cpu == nil")
	}
	if err != nil {
		t.Error(err)
	}
	err = cpu.Run(100)
	if err != nil {
		t.Error(err)
	}
	expected := `REGISTERS:
R1 = 2
R2 = 20
R3 = 22
R4 = 42
MEMORY:
0x0 = 7
0x1 = 6
0x2 = 42`
	if cpu.String() != expected {
		t.Error(fmt.Sprintf("'%s' != '%s'", cpu.String(), expected))
	}
}

func TestSameOutputRegardlessOfFlags(t *testing.T) {
	for testName, test := range CPU_TESTS {
		if strings.HasPrefix(testName, "provided") == false {
			continue
		}
		cpu, _ := ParseCPUString(test)
		if err := cpu.Run(100); err != nil{

		/*
		fmt.Println("######### PROGRAM ", testName)
		fmt.Println("######### CODE")
		fmt.Println(test)
		fmt.Println("######### Result")
		fmt.Println(cpu.String())
		fmt.Println("######### Timing")
		fmt.Println(cpu.RenderTiming())
		*/

			t.Fatal(testName, "nf", err)
		}

		a := cpu.String()
		timing := cpu.RenderTiming()

		cpu, _ = ParseCPUString(test)
		cpu.ForwardingEnabled = true
		cpu.BranchMode = branchModePredictTaken
		if err := cpu.Run(100); err != nil{
			t.Fatal(testName, "f, bt", err)
		}

		b := cpu.String()
		timingPT := cpu.RenderTiming()

		cpu, _ = ParseCPUString(test)
		cpu.ForwardingEnabled = true
		cpu.BranchMode = branchModePredictNotTaken
		if err := cpu.Run(100); err != nil{
			t.Fatal(testName, "f, bnt", err)
		}

		c := cpu.String()
		timingPNT := cpu.RenderTiming()

		if a != b {
			t.Error("'%s' != '%s'", a, b)
		}
		if b != c {
			t.Error("'%s' != '%s'", b, c)
		}
		fmt.Println("######### PROGRAM ", testName)
		fmt.Println("######### CODE")
		fmt.Println(test)
		fmt.Println("######### Result")
		fmt.Println(a)
		fmt.Println("\n\n######### Timing No Forwarding")
		fmt.Println(timing)
		fmt.Println("\n\n######### Timing Forwarding + Predict Taken")
		fmt.Println(timingPT)
		fmt.Println("\n\n######### Timing Forwarding + Predict Not Taken")
		fmt.Println(timingPNT)

	}
}
<|endoftext|>


<commit_before>package proxy

import (
	"github.com/h2oai/steamY/master/az"
	"github.com/h2oai/steamY/master/data"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"sync"
)

type reverseProxy struct {
	clusterId int64
	host      string
	proxy     *httputil.ReverseProxy
}

func newReverseProxy(clusterId int64, host string) *reverseProxy {
	return &reverseProxy{
		clusterId,
		host,
		httputil.NewSingleHostReverseProxy(&url.URL{
			Scheme: "http",
			Host:   host,
		}),
	}
}

type ProxyHandler struct {
	mu      *sync.RWMutex
	proxies map[int64]*reverseProxy
	az      az.Az
	ds      *data.Datastore
}

func NewProxyHandler(az az.Az, ds *data.Datastore) *ProxyHandler {
	return &ProxyHandler{
		&sync.RWMutex{},
		make(map[int64]*reverseProxy),
		az,
		ds,
	}
}

func (pm *ProxyHandler) getOrCreateReverseProxy(clusterId int64, host string) *reverseProxy {
	pm.mu.RLock()
	rp, ok := pm.proxies[clusterId]
	pm.mu.RUnlock()

	if ok {
		return rp
	}

	rp = newReverseProxy(clusterId, host)
	pm.mu.Lock()
	pm.proxies[clusterId] = rp
	pm.mu.Unlock()
	return rp
}

func (pm *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	// All proxy requests require a header with key=X-Cluster; value=cluster-id (in)

	clusterHeader := r.Header.Get("X-Cluster")
	if clusterHeader == "" {
		http.Error(w, "Cluster requests via Steam requires a valid X-Cluster HTTP header", http.StatusBadRequest)
		return
	}

	clusterId, err := strconv.ParseInt(clusterHeader, 10, 64)
	if err != nil {
		http.Error(w, "Invalid X-Cluster HTTP header, expected integer", http.StatusBadRequest)
		return
	}

	// Identify the principal

	pz, azerr := pm.az.Identify(r)
	if azerr != nil {
		http.Error(w, azerr.Error(), http.StatusForbidden)
	}

	// Check if principal is allowed to use clusters

	if err := pz.CheckPermission(pm.ds.Permissions.ViewCluster); err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
	}

	// Read cluster from database.
	// This also checks if the principal has privileges to view this specific cluster.

	cluster, err := pm.ds.ReadCluster(pz, clusterId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
	}

	// Get existing proxy, or create one if missing.

	rp := pm.getOrCreateReverseProxy(clusterId, cluster.Address)

	// Forward

	rp.proxy.ServeHTTP(w, r)
}
<commit_msg>STEAM-161: return after errors<commit_after>package proxy

import (
	"net/http"
	"net/http/httputil"
	"net/url"
	"strconv"
	"sync"

	"github.com/h2oai/steamY/master/az"
	"github.com/h2oai/steamY/master/data"
)

type reverseProxy struct {
	clusterId int64
	host      string
	proxy     *httputil.ReverseProxy
}

func newReverseProxy(clusterId int64, host string) *reverseProxy {
	return &reverseProxy{
		clusterId,
		host,
		httputil.NewSingleHostReverseProxy(&url.URL{
			Scheme: "http",
			Host:   host,
		}),
	}
}

type ProxyHandler struct {
	mu      *sync.RWMutex
	proxies map[int64]*reverseProxy
	az      az.Az
	ds      *data.Datastore
}

func NewProxyHandler(az az.Az, ds *data.Datastore) *ProxyHandler {
	return &ProxyHandler{
		&sync.RWMutex{},
		make(map[int64]*reverseProxy),
		az,
		ds,
	}
}

func (pm *ProxyHandler) getOrCreateReverseProxy(clusterId int64, host string) *reverseProxy {
	pm.mu.RLock()
	rp, ok := pm.proxies[clusterId]
	pm.mu.RUnlock()

	if ok {
		return rp
	}

	rp = newReverseProxy(clusterId, host)
	pm.mu.Lock()
	pm.proxies[clusterId] = rp
	pm.mu.Unlock()
	return rp
}

func (pm *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	// All proxy requests require a header with key=X-Cluster; value=cluster-id (in)

	clusterHeader := r.Header.Get("X-Cluster")
	if clusterHeader == "" {
		http.Error(w, "Cluster requests via Steam requires a valid X-Cluster HTTP header", http.StatusBadRequest)
		return
	}

	clusterId, err := strconv.ParseInt(clusterHeader, 10, 64)
	if err != nil {
		http.Error(w, "Invalid X-Cluster HTTP header, expected integer", http.StatusBadRequest)
		return
	}

	// Identify the principal

	pz, azerr := pm.az.Identify(r)
	if azerr != nil {
		http.Error(w, azerr.Error(), http.StatusForbidden)
		return
	}

	// Check if principal is allowed to use clusters

	if err := pz.CheckPermission(pm.ds.Permissions.ViewCluster); err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}

	// Read cluster from database.
	// This also checks if the principal has privileges to view this specific cluster.

	cluster, err := pm.ds.ReadCluster(pz, clusterId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusForbidden)
		return
	}

	// Get existing proxy, or create one if missing.

	rp := pm.getOrCreateReverseProxy(clusterId, cluster.Address)

	// Forward

	rp.proxy.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>// Copyright 2015 clair 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 debian

import (
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/coreos/clair/database"
	"github.com/coreos/clair/updater"
	cerrors "github.com/coreos/clair/utils/errors"
	"github.com/coreos/clair/utils/types"
	"github.com/coreos/pkg/capnslog"
)

const (
	url               = "https://security-tracker.debian.org/tracker/data/json"
	cveURLPrefix      = "https://security-tracker.debian.org/tracker"
	debianUpdaterFlag = "debianUpdater"
)

var log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater/fetchers/debian")

type jsonData map[string]map[string]jsonVuln

type jsonVuln struct {
	Description string             `json:"description"`
	Releases    map[string]jsonRel `json:"releases"`
}

type jsonRel struct {
	FixedVersion string `json:"fixed_version"`
	Status       string `json:"status"`
	Urgency      string `json:"urgency"`
}

// DebianFetcher implements updater.Fetcher for the Debian Security Tracker
// (https://security-tracker.debian.org).
type DebianFetcher struct{}

func init() {
	updater.RegisterFetcher("debian", &DebianFetcher{})
}

// FetchUpdate fetches vulnerability updates from the Debian Security Tracker.
func (fetcher *DebianFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) {
	log.Info("fetching Debian vulnerabilities")

	// Download JSON.
	r, err := http.Get(url)
	if err != nil {
		log.Errorf("could not download Debian's update: %s", err)
		return resp, cerrors.ErrCouldNotDownload
	}

	// Get the SHA-1 of the latest update's JSON data
	latestHash, err := datastore.GetKeyValue(debianUpdaterFlag)
	if err != nil {
		return resp, err
	}

	// Parse the JSON.
	resp, err = buildResponse(r.Body, latestHash)
	if err != nil {
		return resp, err
	}

	return resp, nil
}

func buildResponse(jsonReader io.Reader, latestKnownHash string) (resp updater.FetcherResponse, err error) {
	hash := latestKnownHash

	// Defer the addition of flag information to the response.
	defer func() {
		if err == nil {
			resp.FlagName = debianUpdaterFlag
			resp.FlagValue = hash
		}
	}()

	// Create a TeeReader so that we can unmarshal into JSON and write to a SHA-1
	// digest at the same time.
	jsonSHA := sha1.New()
	teedJSONReader := io.TeeReader(jsonReader, jsonSHA)

	// Unmarshal JSON.
	var data jsonData
	err = json.NewDecoder(teedJSONReader).Decode(&data)
	if err != nil {
		log.Errorf("could not unmarshal Debian's JSON: %s", err)
		return resp, cerrors.ErrCouldNotParse
	}

	// Calculate the hash and skip updating if the hash has been seen before.
	hash = hex.EncodeToString(jsonSHA.Sum(nil))
	if latestKnownHash == hash {
		log.Debug("no Debian update")
		return resp, nil
	}

	// Extract vulnerability data from Debian's JSON schema.
	var unknownReleases map[string]struct{}
	resp.Vulnerabilities, unknownReleases = parseDebianJSON(&data)

	// Log unknown releases
	for k := range unknownReleases {
		note := fmt.Sprintf("Debian %s is not mapped to any version number (eg. Jessie->8). Please update me.", k)
		resp.Notes = append(resp.Notes, note)
		log.Warning(note)
	}

	return resp, nil
}

func parseDebianJSON(data *jsonData) (vulnerabilities []database.Vulnerability, unknownReleases map[string]struct{}) {
	mvulnerabilities := make(map[string]*database.Vulnerability)
	unknownReleases = make(map[string]struct{})

	for pkgName, pkgNode := range *data {
		for vulnName, vulnNode := range pkgNode {
			for releaseName, releaseNode := range vulnNode.Releases {
				// Attempt to detect the release number.
				if _, isReleaseKnown := database.DebianReleasesMapping[releaseName]; !isReleaseKnown {
					unknownReleases[releaseName] = struct{}{}
					continue
				}

				// Skip if the status is not determined.
				if releaseNode.Status == "undetermined" {
					continue
				}

				// Get or create the vulnerability.
				namespaceName := "debian:" + database.DebianReleasesMapping[releaseName]
				index := namespaceName + ":" + vulnName
				vulnerability, vulnerabilityAlreadyExists := mvulnerabilities[index]
				if !vulnerabilityAlreadyExists {
					vulnerability = &database.Vulnerability{
						Name:        vulnName,
						Namespace:   database.Namespace{Name: namespaceName},
						Link:        strings.Join([]string{cveURLPrefix, "/", vulnName}, ""),
						Severity:    types.Unknown,
						Description: vulnNode.Description,
					}
				}

				// Set the priority of the vulnerability.
				// In the JSON, a vulnerability has one urgency per package it affects.
				// The highest urgency should be the one set.
				urgency := urgencyToSeverity(releaseNode.Urgency)
				if urgency.Compare(vulnerability.Severity) > 0 {
					vulnerability.Severity = urgency
				}

				// Determine the version of the package the vulnerability affects.
				var version types.Version
				var err error
				if releaseNode.FixedVersion == "0" {
					// This means that the package is not affected by this vulnerability.
					version = types.MinVersion
				} else if releaseNode.Status == "open" {
					// Open means that the package is currently vulnerable in the latest
					// version of this Debian release.
					version = types.MaxVersion
				} else if releaseNode.Status == "resolved" {
					// Resolved means that the vulnerability has been fixed in
					// "fixed_version" (if affected).
					version, err = types.NewVersion(releaseNode.FixedVersion)
					if err != nil {
						log.Warningf("could not parse package version '%s': %s. skipping", releaseNode.FixedVersion, err.Error())
						continue
					}
				}

				// Create and add the feature version.
				pkg := database.FeatureVersion{
					Feature: database.Feature{Name: pkgName},
					Version: version,
				}
				vulnerability.FixedIn = append(vulnerability.FixedIn, pkg)

				// Store the vulnerability.
				mvulnerabilities[index] = vulnerability
			}
		}
	}

	// Convert the vulnerabilities map to a slice
	for _, v := range mvulnerabilities {
		vulnerabilities = append(vulnerabilities, *v)
	}

	return
}

func urgencyToSeverity(urgency string) types.Priority {
	switch urgency {
	case "not yet assigned":
		return types.Unknown

	case "end-of-life":
		fallthrough
	case "unimportant":
		return types.Negligible

	case "low":
		fallthrough
	case "low*":
		fallthrough
	case "low**":
		return types.Low

	case "medium":
		fallthrough
	case "medium*":
		fallthrough
	case "medium**":
		return types.Medium

	case "high":
		fallthrough
	case "high*":
		fallthrough
	case "high**":
		return types.High

	default:
		log.Warningf("could not determine vulnerability priority from: %s", urgency)
		return types.Unknown
	}
}
<commit_msg>updater: ignore Debian's "temp" vulnerabilities<commit_after>// Copyright 2015 clair 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 debian

import (
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/coreos/clair/database"
	"github.com/coreos/clair/updater"
	cerrors "github.com/coreos/clair/utils/errors"
	"github.com/coreos/clair/utils/types"
	"github.com/coreos/pkg/capnslog"
)

const (
	url               = "https://security-tracker.debian.org/tracker/data/json"
	cveURLPrefix      = "https://security-tracker.debian.org/tracker"
	debianUpdaterFlag = "debianUpdater"
)

var log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater/fetchers/debian")

type jsonData map[string]map[string]jsonVuln

type jsonVuln struct {
	Description string             `json:"description"`
	Releases    map[string]jsonRel `json:"releases"`
}

type jsonRel struct {
	FixedVersion string `json:"fixed_version"`
	Status       string `json:"status"`
	Urgency      string `json:"urgency"`
}

// DebianFetcher implements updater.Fetcher for the Debian Security Tracker
// (https://security-tracker.debian.org).
type DebianFetcher struct{}

func init() {
	updater.RegisterFetcher("debian", &DebianFetcher{})
}

// FetchUpdate fetches vulnerability updates from the Debian Security Tracker.
func (fetcher *DebianFetcher) FetchUpdate(datastore database.Datastore) (resp updater.FetcherResponse, err error) {
	log.Info("fetching Debian vulnerabilities")

	// Download JSON.
	r, err := http.Get(url)
	if err != nil {
		log.Errorf("could not download Debian's update: %s", err)
		return resp, cerrors.ErrCouldNotDownload
	}

	// Get the SHA-1 of the latest update's JSON data
	latestHash, err := datastore.GetKeyValue(debianUpdaterFlag)
	if err != nil {
		return resp, err
	}

	// Parse the JSON.
	resp, err = buildResponse(r.Body, latestHash)
	if err != nil {
		return resp, err
	}

	return resp, nil
}

func buildResponse(jsonReader io.Reader, latestKnownHash string) (resp updater.FetcherResponse, err error) {
	hash := latestKnownHash

	// Defer the addition of flag information to the response.
	defer func() {
		if err == nil {
			resp.FlagName = debianUpdaterFlag
			resp.FlagValue = hash
		}
	}()

	// Create a TeeReader so that we can unmarshal into JSON and write to a SHA-1
	// digest at the same time.
	jsonSHA := sha1.New()
	teedJSONReader := io.TeeReader(jsonReader, jsonSHA)

	// Unmarshal JSON.
	var data jsonData
	err = json.NewDecoder(teedJSONReader).Decode(&data)
	if err != nil {
		log.Errorf("could not unmarshal Debian's JSON: %s", err)
		return resp, cerrors.ErrCouldNotParse
	}

	// Calculate the hash and skip updating if the hash has been seen before.
	hash = hex.EncodeToString(jsonSHA.Sum(nil))
	if latestKnownHash == hash {
		log.Debug("no Debian update")
		return resp, nil
	}

	// Extract vulnerability data from Debian's JSON schema.
	var unknownReleases map[string]struct{}
	resp.Vulnerabilities, unknownReleases = parseDebianJSON(&data)

	// Log unknown releases
	for k := range unknownReleases {
		note := fmt.Sprintf("Debian %s is not mapped to any version number (eg. Jessie->8). Please update me.", k)
		resp.Notes = append(resp.Notes, note)
		log.Warning(note)
	}

	return resp, nil
}

func parseDebianJSON(data *jsonData) (vulnerabilities []database.Vulnerability, unknownReleases map[string]struct{}) {
	mvulnerabilities := make(map[string]*database.Vulnerability)
	unknownReleases = make(map[string]struct{})

	for pkgName, pkgNode := range *data {
		for vulnName, vulnNode := range pkgNode {
			for releaseName, releaseNode := range vulnNode.Releases {
				// Attempt to detect the release number.
				if _, isReleaseKnown := database.DebianReleasesMapping[releaseName]; !isReleaseKnown {
					unknownReleases[releaseName] = struct{}{}
					continue
				}

				// Skip if the status is not determined or the vulnerability is a temporary one.
				if !strings.HasPrefix(vulnName, "CVE-") || releaseNode.Status == "undetermined" {
					continue
				}

				// Get or create the vulnerability.
				namespaceName := "debian:" + database.DebianReleasesMapping[releaseName]
				index := namespaceName + ":" + vulnName
				vulnerability, vulnerabilityAlreadyExists := mvulnerabilities[index]
				if !vulnerabilityAlreadyExists {
					vulnerability = &database.Vulnerability{
						Name:        vulnName,
						Namespace:   database.Namespace{Name: namespaceName},
						Link:        strings.Join([]string{cveURLPrefix, "/", vulnName}, ""),
						Severity:    types.Unknown,
						Description: vulnNode.Description,
					}
				}

				// Set the priority of the vulnerability.
				// In the JSON, a vulnerability has one urgency per package it affects.
				// The highest urgency should be the one set.
				urgency := urgencyToSeverity(releaseNode.Urgency)
				if urgency.Compare(vulnerability.Severity) > 0 {
					vulnerability.Severity = urgency
				}

				// Determine the version of the package the vulnerability affects.
				var version types.Version
				var err error
				if releaseNode.FixedVersion == "0" {
					// This means that the package is not affected by this vulnerability.
					version = types.MinVersion
				} else if releaseNode.Status == "open" {
					// Open means that the package is currently vulnerable in the latest
					// version of this Debian release.
					version = types.MaxVersion
				} else if releaseNode.Status == "resolved" {
					// Resolved means that the vulnerability has been fixed in
					// "fixed_version" (if affected).
					version, err = types.NewVersion(releaseNode.FixedVersion)
					if err != nil {
						log.Warningf("could not parse package version '%s': %s. skipping", releaseNode.FixedVersion, err.Error())
						continue
					}
				}

				// Create and add the feature version.
				pkg := database.FeatureVersion{
					Feature: database.Feature{Name: pkgName},
					Version: version,
				}
				vulnerability.FixedIn = append(vulnerability.FixedIn, pkg)

				// Store the vulnerability.
				mvulnerabilities[index] = vulnerability
			}
		}
	}

	// Convert the vulnerabilities map to a slice
	for _, v := range mvulnerabilities {
		vulnerabilities = append(vulnerabilities, *v)
	}

	return
}

func urgencyToSeverity(urgency string) types.Priority {
	switch urgency {
	case "not yet assigned":
		return types.Unknown

	case "end-of-life":
		fallthrough
	case "unimportant":
		return types.Negligible

	case "low":
		fallthrough
	case "low*":
		fallthrough
	case "low**":
		return types.Low

	case "medium":
		fallthrough
	case "medium*":
		fallthrough
	case "medium**":
		return types.Medium

	case "high":
		fallthrough
	case "high*":
		fallthrough
	case "high**":
		return types.High

	default:
		log.Warningf("could not determine vulnerability priority from: %s", urgency)
		return types.Unknown
	}
}
<|endoftext|>


<commit_before>// Package pinata is a utility to beat data out of interface{}, []interface{}
// and map[string]interface{}. It was origally designed for use with the
// encoding/json package but can be generally useful.
//
// Unlike other packages most methods do not return an error type. They become
// a no-op when the first error is found so the error can be checked after a
// series of operations instead of at each operation seperately. Because of
// this "late" error handling design special care is taken to return good
// errors so you can still find out where things went wrong.
package pinata

import (
	"bytes"
	"fmt"
	"strings"
)

// Stick offers methods for extracting data from a Pinata.
type Stick interface {
	// Error returns the first error encountered or nil if all operations so far
	// were successful.
	Error() error

	// ClearError clears the error. If there is no error the method has no effect.
	ClearError()

	// PathString gets the string value at the given path within the Pinata. The
	// last element in the path must be a string, the rest must be a
	// map[string]interface{}. The input Pinata must hold a
	// map[string]interface{} as well.
	PathString(Pinata, ...string) string

	// String returns the Pinata as a string if it is one.
	String(Pinata) string

	// IndexString gets the string value at the given index within the Pinata.
	// The input Pinata must hold a []interface{}.
	IndexString(Pinata, int) string

	// PathPinata gets the Pinata value at the given path within the Pinata. All
	// elements in the path must be of type map[string]interface{}. The input
	// Pinata must hold a map[string]interface{} as well.
	PathPinata(Pinata, ...string) Pinata

	// IndexString gets the Pinata value at the given index within the Pinata.
	// The input Pinata must hold a []interface{}.
	IndexPinata(Pinata, int) Pinata
}

type ErrorContext struct {
	method      string
	methodInput []interface{}
	next        *ErrorContext
}

// Method returns the name of the method that caused the error.
func (ec ErrorContext) Method() string {
	return ec.method
}

// MethodInput returns the input parameters of the method that caused the error.
func (ec ErrorContext) MethodInput() []interface{} {
	return ec.methodInput
}

func (ec ErrorContext) Next() *ErrorContext {
	return ec.next
}

type Pinata struct {
	context  *ErrorContext
	contents contents
}

func (p Pinata) Value() interface{} {
	return p.contents.Value()
}

func (p Pinata) Map() (map[string]interface{}, bool) {
	return p.contents.Map()
}

func (p Pinata) Slice() ([]interface{}, bool) {
	return p.contents.Slice()
}

type contents interface {
	Value() interface{}
	Map() (map[string]interface{}, bool)
	Slice() ([]interface{}, bool)
}

type otherPinata struct {
	value interface{}
}

func (p otherPinata) Value() interface{} {
	return p.value
}

func (p otherPinata) Map() (map[string]interface{}, bool) {
	return nil, false
}

func (p otherPinata) Slice() ([]interface{}, bool) {
	return nil, false
}

var _ = contents(mapPinata{})

type mapPinata struct {
	otherPinata
	value map[string]interface{}
}

func (p mapPinata) Map() (map[string]interface{}, bool) {
	return p.value, true
}

type slicePinata struct {
	otherPinata
	value []interface{}
}

func (p slicePinata) Slice() ([]interface{}, bool) {
	return p.value, true
}

// New is a starting point for a pinata celebration.
func New(contents interface{}) (Stick, Pinata) {
	return NewStick(), NewPinata(contents)
}

func NewStick() Stick {
	return &stick{}
}

// New creates a new Stick. Instances returned are not thread safe.
func NewPinata(contents interface{}) Pinata {
	return newPinataWithContext(contents, nil)
}

func newPinataWithContext(contents interface{}, context *ErrorContext) Pinata {
	switch t := contents.(type) {
	case map[string]interface{}:
		return Pinata{contents: &mapPinata{value: t}, context: context}
	case []interface{}:
		return Pinata{contents: &slicePinata{value: t}, context: context}
	default:
		return Pinata{contents: &otherPinata{value: t}, context: context}
	}
}

var _ = error(PinataError{})

// ErrorReason describes the reason for returning a PinataError.
type ErrorReason string

const (
	// ErrorReasonIncompatibleType indicates the contents of the Pinata is not compatible with the invoked method.
	ErrorReasonIncompatibleType ErrorReason = "incompatible type"
	// ErrorReasonNotFound indicates the input has not been found in the Pinata.
	ErrorReasonNotFound = "not found"
	// ErrorReasonInvalidInput indicates the input is not in the expected range or format.
	ErrorReasonInvalidInput = "invalid input"
)

// PinataError is set on the Pinata if something goes wrong.
type PinataError struct {
	reason  ErrorReason
	context *ErrorContext
	advice  string
}

// Reason indicates why the error occurred.
func (p PinataError) Reason() ErrorReason {
	return p.reason
}

// Context returns more information about the circumstances of the error.
func (p PinataError) Context() *ErrorContext {
	return p.context
}

// Advice contains a human readable hint detailing how to remedy this error.
func (p PinataError) Advice() string {
	return p.advice
}

func (p PinataError) Error() string {
	var summaries []string
	current := p.context
	for current != nil {
		var methodInput = current.MethodInput()
		var summary string
		if len(methodInput) > 0 {
			var buf bytes.Buffer
			_, _ = buf.WriteString(current.Method())
			_ = buf.WriteByte('(')
			for i := range methodInput {
				_, _ = buf.WriteString("%#v")
				if i < len(methodInput)-1 {
					_, _ = buf.WriteString(", ")
				}
			}
			_ = buf.WriteByte(')')
			summary = fmt.Sprintf(buf.String(), methodInput...)
			summaries = append(summaries, summary)
		}
		current = current.next
	}
	return fmt.Sprintf("pinata: %s (%s): \n\t%v", p.Reason(), p.Advice(), strings.Join(summaries, " :: "))
}

type stick struct {
	err error
}

func (s *stick) ClearError() {
	s.err = nil
}

func (s *stick) Error() error {
	return s.err
}

// this method assumes s.err != nil
func (s *stick) stringUnsupported(errCtx *ErrorContext, method string, input []interface{}, advice string) string {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: input,
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: advice,
	}
	return ""
}

// this method assumes s.err != nil
func (s *stick) indexUnsupported(errCtx *ErrorContext, method string, index int) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a slice pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) pathUnsupported(errCtx *ErrorContext, method string, path []string) {
	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a map pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) internalString(p Pinata, method string, input []interface{}) string {
	if _, ok := p.Map(); ok {
		return s.stringUnsupported(p.context, method, input, "this is a map")
	}
	if _, ok := p.Slice(); ok {
		return s.stringUnsupported(p.context, method, input, "this is a slice")
	}
	if v, ok := p.Value().(string); ok {
		return v
	}
	return s.stringUnsupported(p.context, method, input, "this is not a string")
}

func (s *stick) String(p Pinata) string {
	if s.err != nil {
		return ""
	}
	return s.internalString(p, "String", nil)
}

// this method assumes s.err != nil
func (s *stick) internalIndexPinata(p Pinata, method string, index int) Pinata {
	if slice, ok := p.Slice(); ok {
		if index < 0 || index >= len(slice) {
			s.err = &PinataError{
				context: &ErrorContext{
					method:      method,
					methodInput: []interface{}{index},
					next:        p.context,
				},
				reason: ErrorReasonInvalidInput,
				advice: fmt.Sprintf("specify an index from 0 to %d", len(slice)-1),
			}
			return Pinata{}
		}
		return newPinataWithContext(slice[index], &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        p.context,
		})
	}
	s.indexUnsupported(p.context, method, index)
	return Pinata{}
}

func (s *stick) IndexPinata(p Pinata, index int) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.internalIndexPinata(p, "IndexPinata", index)
}

func (s *stick) IndexString(p Pinata, index int) string {
	if s.err != nil {
		return ""
	}
	const method = "IndexString"
	pinata := s.internalIndexPinata(p, method, index)
	if s.err != nil {
		return ""
	}
	pinata.context = p.context
	return s.internalString(pinata, method, []interface{}{index})
}

// this method assumes s.err != nil
func (s *stick) internalPathPinata(p Pinata, method string, path ...string) Pinata {
	contents, ok := p.Map()

	if !ok {
		s.pathUnsupported(p.context, method, path)
		return Pinata{}
	}

	if len(path) == 0 {
		s.err = &PinataError{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonInvalidInput,
			advice: "specify a path",
		}
		return Pinata{}
	}

	for i := 0; i < len(path)-1; i++ {
		current := path[i]
		if v, ok := contents[current]; ok {
			if v, ok := v.(map[string]interface{}); ok {
				contents = v
			} else {
				s.err = &PinataError{
					context: &ErrorContext{
						method:      method,
						methodInput: toInterfaceSlice(path),
						next:        p.context,
					},
					reason: ErrorReasonIncompatibleType,
					advice: fmt.Sprintf(`"%s" does not hold a pinata`, strings.Join(path[:i+1], `", "`)),
				}
				return Pinata{}
			}
		} else {
			s.err = &PinataError{
				context: &ErrorContext{
					method:      method,
					methodInput: toInterfaceSlice(path),
					next:        p.context,
				},
				reason: ErrorReasonNotFound,
				advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path[:i+1], `", "`)),
			}
			return Pinata{}
		}
	}

	if v, ok := contents[path[len(path)-1]]; ok {
		return newPinataWithContext(v, &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		})
	}

	s.err = &PinataError{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		},
		reason: ErrorReasonNotFound,
		advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path, `", "`)),
	}
	return Pinata{}
}

func (s *stick) PathPinata(p Pinata, path ...string) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.internalPathPinata(p, "PathPinata", path...)
}

func (s *stick) PathString(p Pinata, path ...string) string {
	if s.err != nil {
		return ""
	}
	const method = "PathString"
	pinata := s.internalPathPinata(p, method, path...)
	if s.err != nil {
		return ""
	}
	pinata.context = p.context
	return s.internalString(pinata, method, toInterfaceSlice(path))
}

func toInterfaceSlice(c []string) []interface{} {
	ifaces := make([]interface{}, len(c))
	for i := range c {
		ifaces[i] = c[i]
	}
	return ifaces
}
<commit_msg>tidy up the public API<commit_after>// Package pinata is a utility to beat data out of interface{}, []interface{}
// and map[string]interface{}. It was origally designed for use with the
// encoding/json package but can be generally useful.
//
// Unlike other packages most methods do not return an error type. They become
// a no-op when the first error is found so the error can be checked after a
// series of operations instead of at each operation seperately. Because of
// this "late" error handling design special care is taken to return good
// errors so you can still find out where things went wrong.
package pinata

import (
	"bytes"
	"fmt"
	"strings"
)

// Stick offers methods for extracting data from a Pinata.
type Stick interface {
	// Error returns the first error encountered or nil if all operations so far
	// were successful.
	Error() error

	// ClearError clears the error. If there is no error the method has no effect.
	ClearError()

	// PathString gets the string value at the given path within the Pinata. The
	// last element in the path must be a string, the rest must be a
	// map[string]interface{}. The input Pinata must hold a
	// map[string]interface{} as well.
	PathString(Pinata, ...string) string

	// String returns the Pinata as a string if it is one.
	String(Pinata) string

	// IndexString gets the string value at the given index within the Pinata.
	// The input Pinata must hold a []interface{}.
	IndexString(Pinata, int) string

	// PathPinata gets the Pinata value at the given path within the Pinata. All
	// elements in the path must be of type map[string]interface{}. The input
	// Pinata must hold a map[string]interface{} as well.
	PathPinata(Pinata, ...string) Pinata

	// IndexString gets the Pinata value at the given index within the Pinata.
	// The input Pinata must hold a []interface{}.
	IndexPinata(Pinata, int) Pinata
}

type ErrorContext struct {
	method      string
	methodInput []interface{}
	next        *ErrorContext
}

// Method returns the name of the method that caused the error.
func (ec ErrorContext) Method() string {
	return ec.method
}

// MethodInput returns the input parameters of the method that caused the error.
func (ec ErrorContext) MethodInput() []interface{} {
	return ec.methodInput
}

func (ec ErrorContext) Next() ErrorContext {
	return *ec.next
}

type Pinata struct {
	context  *ErrorContext
	contents contents
}

func (p Pinata) Value() interface{} {
	return p.contents.Value()
}

func (p Pinata) Map() (map[string]interface{}, bool) {
	return p.contents.Map()
}

func (p Pinata) Slice() ([]interface{}, bool) {
	return p.contents.Slice()
}

type contents interface {
	Value() interface{}
	Map() (map[string]interface{}, bool)
	Slice() ([]interface{}, bool)
}

type otherPinata struct {
	value interface{}
}

func (p otherPinata) Value() interface{} {
	return p.value
}

func (p otherPinata) Map() (map[string]interface{}, bool) {
	return nil, false
}

func (p otherPinata) Slice() ([]interface{}, bool) {
	return nil, false
}

var _ = contents(mapPinata{})

type mapPinata struct {
	otherPinata
	value map[string]interface{}
}

func (p mapPinata) Map() (map[string]interface{}, bool) {
	return p.value, true
}

type slicePinata struct {
	otherPinata
	value []interface{}
}

func (p slicePinata) Slice() ([]interface{}, bool) {
	return p.value, true
}

// New is a starting point for a pinata celebration.
func New(contents interface{}) (Stick, Pinata) {
	return NewStick(), NewPinata(contents)
}

func NewStick() Stick {
	return &stick{}
}

// New creates a new Stick. Instances returned are not thread safe.
func NewPinata(contents interface{}) Pinata {
	return newPinataWithContext(contents, nil)
}

func newPinataWithContext(contents interface{}, context *ErrorContext) Pinata {
	switch t := contents.(type) {
	case map[string]interface{}:
		return Pinata{contents: &mapPinata{value: t}, context: context}
	case []interface{}:
		return Pinata{contents: &slicePinata{value: t}, context: context}
	default:
		return Pinata{contents: &otherPinata{value: t}, context: context}
	}
}

var _ = error(Error{})

// ErrorReason describes the reason for returning an Error.
type ErrorReason string

const (
	// ErrorReasonIncompatibleType indicates the contents of the Pinata is not compatible with the invoked method.
	ErrorReasonIncompatibleType ErrorReason = "incompatible type"
	// ErrorReasonNotFound indicates the input has not been found in the Pinata.
	ErrorReasonNotFound = "not found"
	// ErrorReasonInvalidInput indicates the input is not in the expected range or format.
	ErrorReasonInvalidInput = "invalid input"
)

// Error is set on the Pinata if something goes wrong.
type Error struct {
	reason  ErrorReason
	context *ErrorContext
	advice  string
}

// Reason indicates why the error occurred.
func (p Error) Reason() ErrorReason {
	return p.reason
}

// Context returns more information about the circumstances of the error.
func (p Error) Context() ErrorContext {
	return *p.context
}

// Advice contains a human readable hint detailing how to remedy this error.
func (p Error) Advice() string {
	return p.advice
}

func (p Error) Error() string {
	var summaries []string
	current := p.context
	for current != nil {
		var methodInput = current.MethodInput()
		var summary string
		if len(methodInput) > 0 {
			var buf bytes.Buffer
			_, _ = buf.WriteString(current.Method())
			_ = buf.WriteByte('(')
			for i := range methodInput {
				_, _ = buf.WriteString("%#v")
				if i < len(methodInput)-1 {
					_, _ = buf.WriteString(", ")
				}
			}
			_ = buf.WriteByte(')')
			summary = fmt.Sprintf(buf.String(), methodInput...)
			summaries = append(summaries, summary)
		}
		current = current.next
	}
	return fmt.Sprintf("pinata: %s (%s): \n\t%v", p.Reason(), p.Advice(), strings.Join(summaries, " :: "))
}

type stick struct {
	err error
}

func (s *stick) ClearError() {
	s.err = nil
}

func (s *stick) Error() error {
	return s.err
}

// this method assumes s.err != nil
func (s *stick) stringUnsupported(errCtx *ErrorContext, method string, input []interface{}, advice string) string {
	s.err = &Error{
		context: &ErrorContext{
			method:      method,
			methodInput: input,
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: advice,
	}
	return ""
}

// this method assumes s.err != nil
func (s *stick) indexUnsupported(errCtx *ErrorContext, method string, index int) {
	s.err = &Error{
		context: &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a slice pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) pathUnsupported(errCtx *ErrorContext, method string, path []string) {
	s.err = &Error{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        errCtx,
		},
		reason: ErrorReasonIncompatibleType,
		advice: "call this method on a map pinata",
	}
}

// this method assumes s.err != nil
func (s *stick) internalString(p Pinata, method string, input []interface{}) string {
	if _, ok := p.Map(); ok {
		return s.stringUnsupported(p.context, method, input, "this is a map")
	}
	if _, ok := p.Slice(); ok {
		return s.stringUnsupported(p.context, method, input, "this is a slice")
	}
	if v, ok := p.Value().(string); ok {
		return v
	}
	return s.stringUnsupported(p.context, method, input, "this is not a string")
}

func (s *stick) String(p Pinata) string {
	if s.err != nil {
		return ""
	}
	return s.internalString(p, "String", nil)
}

// this method assumes s.err != nil
func (s *stick) internalIndexPinata(p Pinata, method string, index int) Pinata {
	if slice, ok := p.Slice(); ok {
		if index < 0 || index >= len(slice) {
			s.err = &Error{
				context: &ErrorContext{
					method:      method,
					methodInput: []interface{}{index},
					next:        p.context,
				},
				reason: ErrorReasonInvalidInput,
				advice: fmt.Sprintf("specify an index from 0 to %d", len(slice)-1),
			}
			return Pinata{}
		}
		return newPinataWithContext(slice[index], &ErrorContext{
			method:      method,
			methodInput: []interface{}{index},
			next:        p.context,
		})
	}
	s.indexUnsupported(p.context, method, index)
	return Pinata{}
}

func (s *stick) IndexPinata(p Pinata, index int) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.internalIndexPinata(p, "IndexPinata", index)
}

func (s *stick) IndexString(p Pinata, index int) string {
	if s.err != nil {
		return ""
	}
	const method = "IndexString"
	pinata := s.internalIndexPinata(p, method, index)
	if s.err != nil {
		return ""
	}
	pinata.context = p.context
	return s.internalString(pinata, method, []interface{}{index})
}

// this method assumes s.err != nil
func (s *stick) internalPathPinata(p Pinata, method string, path ...string) Pinata {
	contents, ok := p.Map()

	if !ok {
		s.pathUnsupported(p.context, method, path)
		return Pinata{}
	}

	if len(path) == 0 {
		s.err = &Error{
			context: &ErrorContext{
				method:      method,
				methodInput: toInterfaceSlice(path),
				next:        p.context,
			},
			reason: ErrorReasonInvalidInput,
			advice: "specify a path",
		}
		return Pinata{}
	}

	for i := 0; i < len(path)-1; i++ {
		current := path[i]
		if v, ok := contents[current]; ok {
			if v, ok := v.(map[string]interface{}); ok {
				contents = v
			} else {
				s.err = &Error{
					context: &ErrorContext{
						method:      method,
						methodInput: toInterfaceSlice(path),
						next:        p.context,
					},
					reason: ErrorReasonIncompatibleType,
					advice: fmt.Sprintf(`"%s" does not hold a pinata`, strings.Join(path[:i+1], `", "`)),
				}
				return Pinata{}
			}
		} else {
			s.err = &Error{
				context: &ErrorContext{
					method:      method,
					methodInput: toInterfaceSlice(path),
					next:        p.context,
				},
				reason: ErrorReasonNotFound,
				advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path[:i+1], `", "`)),
			}
			return Pinata{}
		}
	}

	if v, ok := contents[path[len(path)-1]]; ok {
		return newPinataWithContext(v, &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		})
	}

	s.err = &Error{
		context: &ErrorContext{
			method:      method,
			methodInput: toInterfaceSlice(path),
			next:        p.context,
		},
		reason: ErrorReasonNotFound,
		advice: fmt.Sprintf(`"%s" does not exist`, strings.Join(path, `", "`)),
	}
	return Pinata{}
}

func (s *stick) PathPinata(p Pinata, path ...string) Pinata {
	if s.err != nil {
		return Pinata{}
	}
	return s.internalPathPinata(p, "PathPinata", path...)
}

func (s *stick) PathString(p Pinata, path ...string) string {
	if s.err != nil {
		return ""
	}
	const method = "PathString"
	pinata := s.internalPathPinata(p, method, path...)
	if s.err != nil {
		return ""
	}
	pinata.context = p.context
	return s.internalString(pinata, method, toInterfaceSlice(path))
}

func toInterfaceSlice(c []string) []interface{} {
	ifaces := make([]interface{}, len(c))
	for i := range c {
		ifaces[i] = c[i]
	}
	return ifaces
}
<|endoftext|>