<commit_before>package assertions

import (
	"errors"
	"fmt"
	"math"
	"reflect"
	"strings"
)

import (
	"github.com/jacobsa/oglematchers"
)

// ShouldEqual receives exactly two parameters and does an equality check.
func ShouldEqual(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	return shouldEqual(actual, expected[0])
}
func shouldEqual(actual, expected interface{}) (message string) {
	defer func() {
		if r := recover(); r != nil {
			message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
			return
		}
	}()

	if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil {
		message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
		return
	}

	return success
}

// ShouldNotEqual receives exactly two parameters and does an inequality check.
func ShouldNotEqual(actual interface{}, expected ...interface{}) string {
	if fail := need(1, expected); fail != success {
		return fail
	} else if ShouldEqual(actual, expected[0]) == success {
		return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0])
	}
	return success
}

// ShouldAlmostEqual makes sure that two parameters are close enough to being equal.
// The acceptable delta may be specified with a third argument,
// or a very small default delta will be used.
func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string {
	deltaFloat := 0.0000000001

	if len(expected) == 0 {
		return "This assertion requires exactly one comparison value and an optional delta (you provided neither)"
	} else if len(expected) == 2 {
		delta, err := getFloat(expected[1])

		if err != nil {
			return "delta must be a numerical type"
		}

		deltaFloat = delta
	} else if len(expected) > 2 {
		return "This assertion requires exactly one comparison value and an optional delta (you provided more values)"
	}

	actualFloat, err := getFloat(actual)

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

	expectedFloat, err := getFloat(expected[0])

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

	return shouldAlmostEqual(actualFloat, expectedFloat, deltaFloat)
}

func shouldAlmostEqual(actual, expected, delta float64) string {
	if math.Abs(actual-expected) <= delta {
		return success
	} else {
		return fmt.Sprintf("Expected '%g' to NOT almost equal '%g' (but it did)!", actual, expected)
	}
}

// returns the float value of any real number, or error if it is not a numerical type
func getFloat(num interface{}) (float64, error) {
	numValue := reflect.ValueOf(num)
	numKind := numValue.Kind()

	fmt.Println(numKind)

	if numKind == reflect.Int ||
		numKind == reflect.Int8 ||
		numKind == reflect.Int16 ||
		numKind == reflect.Int32 ||
		numKind == reflect.Int64 {
		return float64(numValue.Int()), nil
	} else if numKind == reflect.Uint ||
		numKind == reflect.Uint8 ||
		numKind == reflect.Uint16 ||
		numKind == reflect.Uint32 ||
		numKind == reflect.Uint64 {
		return float64(numValue.Uint()), nil
	} else if numKind == reflect.Float32 ||
		numKind == reflect.Float64 {
		return numValue.Float(), nil
	} else {
		return 0.0, errors.New("must be a numerical type, but was " + numKind.String())
	}
}

// ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual)
func ShouldResemble(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}

	if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil {
		return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveResembled, expected[0], actual))
	}

	return success
}

// ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual)
func ShouldNotResemble(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	} else if ShouldResemble(actual, expected[0]) == success {
		return fmt.Sprintf(shouldNotHaveResembled, actual, expected[0])
	}
	return success
}

// ShouldPointTo receives exactly two parameters and checks to see that they point to the same address.
func ShouldPointTo(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	return shouldPointTo(actual, expected[0])

}
func shouldPointTo(actual, expected interface{}) string {
	actualValue := reflect.ValueOf(actual)
	expectedValue := reflect.ValueOf(expected)

	if ShouldNotBeNil(actual) != success {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil")
	} else if ShouldNotBeNil(expected) != success {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil")
	} else if actualValue.Kind() != reflect.Ptr {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not")
	} else if expectedValue.Kind() != reflect.Ptr {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not")
	} else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success {
		actualAddress := reflect.ValueOf(actual).Pointer()
		expectedAddress := reflect.ValueOf(expected).Pointer()
		return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo,
			actual, actualAddress,
			expected, expectedAddress))
	}
	return success
}

// ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess.
func ShouldNotPointTo(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	compare := ShouldPointTo(actual, expected[0])
	if strings.HasPrefix(compare, shouldBePointers) {
		return compare
	} else if compare == success {
		return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer())
	}
	return success
}

// ShouldBeNil receives a single parameter and ensures that it is nil.
func ShouldBeNil(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual == nil {
		return success
	} else if interfaceIsNilPointer(actual) {
		return success
	}
	return fmt.Sprintf(shouldHaveBeenNil, actual)
}
func interfaceIsNilPointer(actual interface{}) bool {
	value := reflect.ValueOf(actual)
	return value.Kind() == reflect.Ptr && value.Pointer() == 0
}

// ShouldNotBeNil receives a single parameter and ensures that it is not nil.
func ShouldNotBeNil(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if ShouldBeNil(actual) == success {
		return fmt.Sprintf(shouldNotHaveBeenNil, actual)
	}
	return success
}

// ShouldBeTrue receives a single parameter and ensures that it is true.
func ShouldBeTrue(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual != true {
		return fmt.Sprintf(shouldHaveBeenTrue, actual)
	}
	return success
}

// ShouldBeFalse receives a single parameter and ensures that it is false.
func ShouldBeFalse(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual != false {
		return fmt.Sprintf(shouldHaveBeenFalse, actual)
	}
	return success
}

// ShouldBeZeroValue receives a single parameter and ensures that it is
// the Go equivalent of the default value, or "zero" value.
func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	}
	zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface()
	if !reflect.DeepEqual(zeroVal, actual) {
		return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual))
	}
	return success
}
<commit_msg>implements ShouldNotAlmostEqual<commit_after>package assertions

import (
	"errors"
	"fmt"
	"math"
	"reflect"
	"strings"
)

import (
	"github.com/jacobsa/oglematchers"
)

// default acceptable delta for ShouldAlmostEqual
var defaultDelta = 0.0000000001

// ShouldEqual receives exactly two parameters and does an equality check.
func ShouldEqual(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	return shouldEqual(actual, expected[0])
}
func shouldEqual(actual, expected interface{}) (message string) {
	defer func() {
		if r := recover(); r != nil {
			message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
			return
		}
	}()

	if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil {
		message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
		return
	}

	return success
}

// ShouldNotEqual receives exactly two parameters and does an inequality check.
func ShouldNotEqual(actual interface{}, expected ...interface{}) string {
	if fail := need(1, expected); fail != success {
		return fail
	} else if ShouldEqual(actual, expected[0]) == success {
		return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0])
	}
	return success
}

// ShouldAlmostEqual makes sure that two parameters are close enough to being equal.
// The acceptable delta may be specified with a third argument,
// or a very small default delta will be used.
func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string {
	actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)

	if err != "" {
		return err
	}

	if math.Abs(actualFloat-expectedFloat) <= deltaFloat {
		return success
	} else {
		return fmt.Sprintf("Expected '%g' to NOT almost equal '%g' (but it did)!", actualFloat, expectedFloat)
	}
}

// ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual
func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string {
	actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...)

	if err != "" {
		return err
	}

	if math.Abs(actualFloat-expectedFloat) > deltaFloat {
		return success
	} else {
		return fmt.Sprintf("Expected '%g' to almost equal '%g' (but it didn't)!", actualFloat, expectedFloat)
	}
}

func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64, float64, float64, string) {
	deltaFloat := 0.0000000001

	if len(expected) == 0 {
		return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided neither)"
	} else if len(expected) == 2 {
		delta, err := getFloat(expected[1])

		if err != nil {
			return 0.0, 0.0, 0.0, "delta must be a numerical type"
		}

		deltaFloat = delta
	} else if len(expected) > 2 {
		return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided more values)"
	}

	actualFloat, err := getFloat(actual)

	if err != nil {
		return 0.0, 0.0, 0.0, err.Error()
	}

	expectedFloat, err := getFloat(expected[0])

	if err != nil {
		return 0.0, 0.0, 0.0, err.Error()
	}

	return actualFloat, expectedFloat, deltaFloat, ""
}

// returns the float value of any real number, or error if it is not a numerical type
func getFloat(num interface{}) (float64, error) {
	numValue := reflect.ValueOf(num)
	numKind := numValue.Kind()

	if numKind == reflect.Int ||
		numKind == reflect.Int8 ||
		numKind == reflect.Int16 ||
		numKind == reflect.Int32 ||
		numKind == reflect.Int64 {
		return float64(numValue.Int()), nil
	} else if numKind == reflect.Uint ||
		numKind == reflect.Uint8 ||
		numKind == reflect.Uint16 ||
		numKind == reflect.Uint32 ||
		numKind == reflect.Uint64 {
		return float64(numValue.Uint()), nil
	} else if numKind == reflect.Float32 ||
		numKind == reflect.Float64 {
		return numValue.Float(), nil
	} else {
		return 0.0, errors.New("must be a numerical type, but was " + numKind.String())
	}
}

// ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual)
func ShouldResemble(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}

	if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil {
		return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveResembled, expected[0], actual))
	}

	return success
}

// ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual)
func ShouldNotResemble(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	} else if ShouldResemble(actual, expected[0]) == success {
		return fmt.Sprintf(shouldNotHaveResembled, actual, expected[0])
	}
	return success
}

// ShouldPointTo receives exactly two parameters and checks to see that they point to the same address.
func ShouldPointTo(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	return shouldPointTo(actual, expected[0])

}
func shouldPointTo(actual, expected interface{}) string {
	actualValue := reflect.ValueOf(actual)
	expectedValue := reflect.ValueOf(expected)

	if ShouldNotBeNil(actual) != success {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil")
	} else if ShouldNotBeNil(expected) != success {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil")
	} else if actualValue.Kind() != reflect.Ptr {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not")
	} else if expectedValue.Kind() != reflect.Ptr {
		return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not")
	} else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success {
		actualAddress := reflect.ValueOf(actual).Pointer()
		expectedAddress := reflect.ValueOf(expected).Pointer()
		return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo,
			actual, actualAddress,
			expected, expectedAddress))
	}
	return success
}

// ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess.
func ShouldNotPointTo(actual interface{}, expected ...interface{}) string {
	if message := need(1, expected); message != success {
		return message
	}
	compare := ShouldPointTo(actual, expected[0])
	if strings.HasPrefix(compare, shouldBePointers) {
		return compare
	} else if compare == success {
		return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer())
	}
	return success
}

// ShouldBeNil receives a single parameter and ensures that it is nil.
func ShouldBeNil(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual == nil {
		return success
	} else if interfaceIsNilPointer(actual) {
		return success
	}
	return fmt.Sprintf(shouldHaveBeenNil, actual)
}
func interfaceIsNilPointer(actual interface{}) bool {
	value := reflect.ValueOf(actual)
	return value.Kind() == reflect.Ptr && value.Pointer() == 0
}

// ShouldNotBeNil receives a single parameter and ensures that it is not nil.
func ShouldNotBeNil(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if ShouldBeNil(actual) == success {
		return fmt.Sprintf(shouldNotHaveBeenNil, actual)
	}
	return success
}

// ShouldBeTrue receives a single parameter and ensures that it is true.
func ShouldBeTrue(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual != true {
		return fmt.Sprintf(shouldHaveBeenTrue, actual)
	}
	return success
}

// ShouldBeFalse receives a single parameter and ensures that it is false.
func ShouldBeFalse(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	} else if actual != false {
		return fmt.Sprintf(shouldHaveBeenFalse, actual)
	}
	return success
}

// ShouldBeZeroValue receives a single parameter and ensures that it is
// the Go equivalent of the default value, or "zero" value.
func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string {
	if fail := need(0, expected); fail != success {
		return fail
	}
	zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface()
	if !reflect.DeepEqual(zeroVal, actual) {
		return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual))
	}
	return success
}
<|endoftext|>


<commit_before>package dajarep

import (
	"strings"
	"testing"
)

func TestDajarep(t *testing.T) {

	input := `人民の人民による人民のための政治
アルミ缶の上にあるミカン
トンネルを抜けるとそこは雪国であった
智代子のチョコ
布団が吹っ飛んだ
我輩は猫である
猫が寝転んだ
その意見にはついていけん
靴を靴箱に入れる
傘を貸さない
イカは如何なものか
親譲りの無鉄砲で子供の時から損ばかりしている
マイケル・ジョーダンが冗談を言った
景気のいいケーキ
知事が縮む
鶏には取り憑かない
破壊についての和解`
	ans := `アルミ缶の上にあるミカン
智代子のチョコ
布団が吹っ飛んだ
猫が寝転んだ
その意見にはついていけん
傘を貸さない
イカは如何なものか
マイケル・ジョーダンが冗談を言った
景気のいいケーキ
知事が縮む
鶏には取り憑かない`
	d, _ := Dajarep(input)
	res := strings.Join(d, "\n")
	if res != ans {
		t.Errorf("Dajarep(x) =\n%s\n, want \n%s", res, ans)
		return
	}
}
<commit_msg>『富士急ハイランドに気軽に入らんと楽しめない』をテストケースに<commit_after>package dajarep

import (
	"strings"
	"testing"
)

func TestDajarep(t *testing.T) {

	input := `人民の人民による人民のための政治
アルミ缶の上にあるミカン
トンネルを抜けるとそこは雪国であった
智代子のチョコ
布団が吹っ飛んだ
我輩は猫である
猫が寝転んだ
その意見にはついていけん
靴を靴箱に入れる
傘を貸さない
イカは如何なものか
親譲りの無鉄砲で子供の時から損ばかりしている
マイケル・ジョーダンが冗談を言った
景気のいいケーキ
富士急ハイランドに気軽に入らんと楽しめない
知事が縮む
鶏には取り憑かない
破壊についての和解`
	ans := `アルミ缶の上にあるミカン
智代子のチョコ
布団が吹っ飛んだ
猫が寝転んだ
その意見にはついていけん
傘を貸さない
イカは如何なものか
マイケル・ジョーダンが冗談を言った
景気のいいケーキ
富士急ハイランドに気軽に入らんと楽しめない
知事が縮む
鶏には取り憑かない`
	d, _ := Dajarep(input)
	res := strings.Join(d, "\n")
	if res != ans {
		t.Errorf("Dajarep(x) =\n%s\n, want \n%s", res, ans)
		return
	}
}
<|endoftext|>


<commit_before>package http

import (
	"bytes"
	"code.google.com/p/go-uuid/uuid"
	"fmt"
	"github.com/ian-kent/go-log/log"
	"github.com/ian-kent/gotcha/config"
	"github.com/ian-kent/gotcha/router/route"
	"html/template"
	nethttp "net/http"
	neturl "net/url"
	"runtime"
)

type Session struct {
	Config   *Config.Config
	Route    *route.Route
	Request  *Request
	Response *Response
	Stash    map[string]interface{}
}

func CreateSession(conf *Config.Config, request *nethttp.Request, writer nethttp.ResponseWriter) *Session {
	session := &Session{
		Config: conf,
		Stash:  make(map[string]interface{}, 0),
	}

	// Somewhere to store internal stuff
	session.Stash["Gotcha"] = make(map[string]interface{}, 0)

	session.Request = CreateRequest(session, request)
	session.Response = CreateResponse(session, writer)

	return session
}

func (session *Session) render(asset string) error {
	asset = "assets/templates/" + asset

	var t *template.Template

	c, ok := session.Config.Cache["template:"+asset]
	if !ok {
		log.Printf("Loading asset: %s", asset)
		a, err := session.Config.AssetLoader(asset)
		log.Printf("Creating template: %s", asset)
		t = template.New(asset)
		if err != nil || a == nil {
			log.Printf("Failed loading template %s: %s", asset, err)
			return err
		}
		log.Printf("Parsing template: %s", asset)
		_, err = t.Parse(string(a))
		if err != nil {
			log.Printf("Failed parsing template %s: %s", asset, err)
			return err
		}
		log.Printf("Template parsed successfully: %s", asset)
		session.Config.Cache["template:"+asset] = t
	} else {
		t = c.(*template.Template)
		log.Printf("Template loaded from cache: %s", asset)
	}

	var b bytes.Buffer
	err := t.Execute(&b, session.Stash)
	if err != nil {
		log.Printf("Failed executing template %s: %s", asset, err)
		return err
	}

	_, err = session.Response.Write(b.Bytes())

	if err != nil {
		log.Printf("Error writing output for template %s: %s", asset, err)
		return err
	}

	return nil
}

func (session *Session) Render(asset string) {
	err := session.render(asset)
	if err != nil {
		session.RenderException(500, err)
	}
}

func (session *Session) RenderNotFound() {
	session.Stash["Gotcha"].(map[string]interface{})["Error"] = "Not found"
	session.Response.Status = 404

	e := session.render("notfound.html")
	if e != nil {
		log.Printf("Error rendering not found page: %s", e)
		session.RenderException(500, e)
	}
}

func (session *Session) RenderException(status int, err error) {
	key := uuid.NewUUID().String()
	session.Response.Status = status
	session.Stash["Gotcha"].(map[string]interface{})["Error"] = err.Error()
	session.Stash["Gotcha"].(map[string]interface{})["ErrorId"] = key

	buf := make([]byte, 1<<16)
	n := runtime.Stack(buf, true)
	session.Stash["Gotcha"].(map[string]interface{})["Stack"] = fmt.Sprintf("%s", buf[:n])

	log.Printf("Exception %s: %s\n%s", key, err.Error(), session.Stash["Gotcha"].(map[string]interface{})["Stack"])

	e := session.render("error.html")
	if e != nil {
		log.Printf("Error rendering error page: %s", e)
		session.Response.Write([]byte("[" + key + "] Internal Server Error: " + err.Error() + "\n"))
	}
}

func (session *Session) Redirect(url *neturl.URL) {
	session.Response.Redirect(url, nethttp.StatusFound)
}
<commit_msg>RenderNotFound always returns 404<commit_after>package http

import (
	"bytes"
	"code.google.com/p/go-uuid/uuid"
	"fmt"
	"github.com/ian-kent/go-log/log"
	"github.com/ian-kent/gotcha/config"
	"github.com/ian-kent/gotcha/router/route"
	"html/template"
	nethttp "net/http"
	neturl "net/url"
	"runtime"
)

type Session struct {
	Config   *Config.Config
	Route    *route.Route
	Request  *Request
	Response *Response
	Stash    map[string]interface{}
}

func CreateSession(conf *Config.Config, request *nethttp.Request, writer nethttp.ResponseWriter) *Session {
	session := &Session{
		Config: conf,
		Stash:  make(map[string]interface{}, 0),
	}

	// Somewhere to store internal stuff
	session.Stash["Gotcha"] = make(map[string]interface{}, 0)

	session.Request = CreateRequest(session, request)
	session.Response = CreateResponse(session, writer)

	return session
}

func (session *Session) render(asset string) error {
	asset = "assets/templates/" + asset

	var t *template.Template

	c, ok := session.Config.Cache["template:"+asset]
	if !ok {
		log.Printf("Loading asset: %s", asset)
		a, err := session.Config.AssetLoader(asset)
		log.Printf("Creating template: %s", asset)
		t = template.New(asset)
		if err != nil || a == nil {
			log.Printf("Failed loading template %s: %s", asset, err)
			return err
		}
		log.Printf("Parsing template: %s", asset)
		_, err = t.Parse(string(a))
		if err != nil {
			log.Printf("Failed parsing template %s: %s", asset, err)
			return err
		}
		log.Printf("Template parsed successfully: %s", asset)
		session.Config.Cache["template:"+asset] = t
	} else {
		t = c.(*template.Template)
		log.Printf("Template loaded from cache: %s", asset)
	}

	var b bytes.Buffer
	err := t.Execute(&b, session.Stash)
	if err != nil {
		log.Printf("Failed executing template %s: %s", asset, err)
		return err
	}

	_, err = session.Response.Write(b.Bytes())

	if err != nil {
		log.Printf("Error writing output for template %s: %s", asset, err)
		return err
	}

	return nil
}

func (session *Session) Render(asset string) {
	err := session.render(asset)
	if err != nil {
		session.RenderException(500, err)
	}
}

func (session *Session) RenderNotFound() {
	session.Stash["Gotcha"].(map[string]interface{})["Error"] = "Not found"
	session.Response.Status = 404

	e := session.render("notfound.html")
	if e != nil {
		log.Printf("Error rendering not found page: %s", e)
		session.Response.Status = 404
	}
}

func (session *Session) RenderException(status int, err error) {
	key := uuid.NewUUID().String()
	session.Response.Status = status
	session.Stash["Gotcha"].(map[string]interface{})["Error"] = err.Error()
	session.Stash["Gotcha"].(map[string]interface{})["ErrorId"] = key

	buf := make([]byte, 1<<16)
	n := runtime.Stack(buf, true)
	session.Stash["Gotcha"].(map[string]interface{})["Stack"] = fmt.Sprintf("%s", buf[:n])

	log.Printf("Exception %s: %s\n%s", key, err.Error(), session.Stash["Gotcha"].(map[string]interface{})["Stack"])

	e := session.render("error.html")
	if e != nil {
		log.Printf("Error rendering error page: %s", e)
		session.Response.Write([]byte("[" + key + "] Internal Server Error: " + err.Error() + "\n"))
	}
}

func (session *Session) Redirect(url *neturl.URL) {
	session.Response.Redirect(url, nethttp.StatusFound)
}
<|endoftext|>


<commit_before>package etcdstorerunner

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/cloudfoundry/gunk/workpool"
	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	etcdclient "github.com/coreos/go-etcd/etcd"
	"github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
	"github.com/pivotal-golang/clock"
)

type ETCDClusterRunner struct {
	startingPort int
	numNodes     int
	etcdSessions []*gexec.Session
	running      bool
	client       *etcdclient.Client

	mutex *sync.RWMutex
}

func NewETCDClusterRunner(startingPort int, numNodes int) *ETCDClusterRunner {
	return &ETCDClusterRunner{
		startingPort: startingPort,
		numNodes:     numNodes,

		mutex: &sync.RWMutex{},
	}
}

func (etcd *ETCDClusterRunner) Start() {
	etcd.start(true)
}

func (etcd *ETCDClusterRunner) Stop() {
	etcd.stop(true)
}

func (etcd *ETCDClusterRunner) KillWithFire() {
	etcd.kill()
}

func (etcd *ETCDClusterRunner) GoAway() {
	etcd.stop(false)
}

func (etcd *ETCDClusterRunner) ComeBack() {
	etcd.start(false)
}

func (etcd *ETCDClusterRunner) NodeURLS() []string {
	urls := make([]string, etcd.numNodes)
	for i := 0; i < etcd.numNodes; i++ {
		urls[i] = etcd.clientURL(i)
	}
	return urls
}

func (etcd *ETCDClusterRunner) DiskUsage() (bytes int64, err error) {
	fi, err := os.Stat(etcd.tmpPathTo("log", 0))
	if err != nil {
		return 0, err
	}
	return fi.Size(), nil
}

func (etcd *ETCDClusterRunner) Reset() {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		response, err := etcd.client.Get("/", false, false)
		if err == nil {
			for _, doomed := range response.Node.Nodes {
				etcd.client.Delete(doomed.Key, true)
			}
		}
	}
}

func (etcd *ETCDClusterRunner) FastForwardTime(seconds int) {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		response, err := etcd.client.Get("/", false, true)
		Ω(err).ShouldNot(HaveOccurred())
		etcd.fastForwardTime(response.Node, seconds)
	}
}

func (etcd *ETCDClusterRunner) Adapter() storeadapter.StoreAdapter {
	pool := workpool.NewWorkPool(10)
	adapter := etcdstoreadapter.NewETCDStoreAdapter(etcd.NodeURLS(), pool)
	adapter.Connect()
	return adapter
}

func (etcd *ETCDClusterRunner) RetryableAdapter() storeadapter.StoreAdapter {
	pool := workpool.NewWorkPool(10)

	adapter := storeadapter.NewRetryable(
		etcdstoreadapter.NewETCDStoreAdapter(etcd.NodeURLS(), pool),
		clock.NewClock(),
		storeadapter.ExponentialRetryPolicy{},
	)

	adapter.Connect()

	return adapter
}

func (etcd *ETCDClusterRunner) start(nuke bool) {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		return
	}

	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	etcd.etcdSessions = make([]*gexec.Session, etcd.numNodes)

	clusterURLs := make([]string, etcd.numNodes)
	for i := 0; i < etcd.numNodes; i++ {
		clusterURLs[i] = etcd.nodeName(i) + "=" + etcd.serverURL(i)
	}

	for i := 0; i < etcd.numNodes; i++ {
		if nuke {
			etcd.nukeArtifacts(i)
		}

		if etcd.detectRunningEtcd(i) {
			log.Fatalf("Detected an ETCD already running on %s", etcd.clientURL(i))
		}

		os.MkdirAll(etcd.tmpPath(i), 0700)
		args := []string{
			"--name", etcd.nodeName(i),
			"--data-dir", etcd.tmpPath(i),
			"--listen-client-urls", etcd.clientURL(i),
			"--listen-peer-urls", etcd.serverURL(i),
			"--initial-cluster", strings.Join(clusterURLs, ","),
			"--initial-advertise-peer-urls", etcd.serverURL(i),
			"--initial-cluster-state", "new",
			"--advertise-client-urls", etcd.clientURL(i),
		}

		session, err := gexec.Start(
			exec.Command("etcd", args...),
			gexec.NewPrefixedWriter("\x1b[32m[o]\x1b[33m[etcd_cluster]\x1b[0m ", ginkgo.GinkgoWriter),
			gexec.NewPrefixedWriter("\x1b[91m[e]\x1b[33m[etcd_cluster]\x1b[0m ", ginkgo.GinkgoWriter),
		)
		Ω(err).ShouldNot(HaveOccurred(), "Make sure etcd is compiled and on your $PATH.")

		etcd.etcdSessions[i] = session

		Eventually(func() bool {
			defer func() {
				// https://github.com/coreos/go-etcd/issues/114
				recover()
			}()

			return etcd.detectRunningEtcd(i)
		}, 10, 0.05).Should(BeTrue(), "Expected ETCD to be up and running")
	}

	etcd.client = etcdclient.NewClient(etcd.NodeURLS())
	etcd.running = true
}

func (etcd *ETCDClusterRunner) stop(nuke bool) {
	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	if etcd.running {
		for i := 0; i < etcd.numNodes; i++ {
			etcd.etcdSessions[i].Interrupt().Wait(5 * time.Second)
			if nuke {
				etcd.nukeArtifacts(i)
			}
		}
		etcd.markAsStopped()
	}
}

func (etcd *ETCDClusterRunner) kill() {
	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	if etcd.running {
		for i := 0; i < etcd.numNodes; i++ {
			etcd.etcdSessions[i].Kill().Wait(5 * time.Second)
			etcd.nukeArtifacts(i)
		}
		etcd.markAsStopped()
	}
}

func (etcd *ETCDClusterRunner) markAsStopped() {
	etcd.etcdSessions = nil
	etcd.running = false
	etcd.client = nil
}

func (etcd *ETCDClusterRunner) detectRunningEtcd(index int) bool {
	client := etcdclient.NewClient([]string{})
	return client.SetCluster([]string{etcd.clientURL(index)})
}

func (etcd *ETCDClusterRunner) fastForwardTime(etcdNode *etcdclient.Node, seconds int) {
	if etcdNode.Dir == true {
		for _, child := range etcdNode.Nodes {
			etcd.fastForwardTime(child, seconds)
		}
	} else {
		if etcdNode.TTL == 0 {
			return
		}
		if etcdNode.TTL <= int64(seconds) {
			_, err := etcd.client.Delete(etcdNode.Key, true)
			Ω(err).ShouldNot(HaveOccurred())
		} else {
			_, err := etcd.client.Set(etcdNode.Key, etcdNode.Value, uint64(etcdNode.TTL-int64(seconds)))
			Ω(err).ShouldNot(HaveOccurred())
		}
	}
}

func (etcd *ETCDClusterRunner) clientURL(index int) string {
	return fmt.Sprintf("http://127.0.0.1:%d", etcd.port(index))
}

func (etcd *ETCDClusterRunner) serverURL(index int) string {
	return fmt.Sprintf("http://127.0.0.1:%d", etcd.port(index)+3000)
}

func (etcd *ETCDClusterRunner) nodeName(index int) string {
	return fmt.Sprintf("node%d", index)
}

func (etcd *ETCDClusterRunner) port(index int) int {
	return etcd.startingPort + index
}

func (etcd *ETCDClusterRunner) tmpPath(index int) string {
	return fmt.Sprintf("/tmp/ETCD_%d", etcd.port(index))
}

func (etcd *ETCDClusterRunner) tmpPathTo(subdir string, index int) string {
	return fmt.Sprintf("/%s/%s", etcd.tmpPath(index), subdir)
}

func (etcd *ETCDClusterRunner) nukeArtifacts(index int) {
	os.RemoveAll(etcd.tmpPath(index))
}
<commit_msg>Use ginkgomon to run etcd cluster<commit_after>package etcdstorerunner

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"
	"sync"
	"time"

	"github.com/cloudfoundry/gunk/workpool"
	"github.com/cloudfoundry/storeadapter"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	etcdclient "github.com/coreos/go-etcd/etcd"
	. "github.com/onsi/gomega"
	"github.com/pivotal-golang/clock"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

type ETCDClusterRunner struct {
	startingPort  int
	numNodes      int
	etcdProcesses []ifrit.Process
	running       bool
	client        *etcdclient.Client

	mutex *sync.RWMutex
}

func NewETCDClusterRunner(startingPort int, numNodes int) *ETCDClusterRunner {
	return &ETCDClusterRunner{
		startingPort: startingPort,
		numNodes:     numNodes,

		mutex: &sync.RWMutex{},
	}
}

func (etcd *ETCDClusterRunner) Start() {
	etcd.start(true)
}

func (etcd *ETCDClusterRunner) Stop() {
	etcd.stop(true)
}

func (etcd *ETCDClusterRunner) KillWithFire() {
	etcd.kill()
}

func (etcd *ETCDClusterRunner) GoAway() {
	etcd.stop(false)
}

func (etcd *ETCDClusterRunner) ComeBack() {
	etcd.start(false)
}

func (etcd *ETCDClusterRunner) NodeURLS() []string {
	urls := make([]string, etcd.numNodes)
	for i := 0; i < etcd.numNodes; i++ {
		urls[i] = etcd.clientURL(i)
	}
	return urls
}

func (etcd *ETCDClusterRunner) DiskUsage() (bytes int64, err error) {
	fi, err := os.Stat(etcd.tmpPathTo("log", 0))
	if err != nil {
		return 0, err
	}
	return fi.Size(), nil
}

func (etcd *ETCDClusterRunner) Reset() {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		response, err := etcd.client.Get("/", false, false)
		if err == nil {
			for _, doomed := range response.Node.Nodes {
				etcd.client.Delete(doomed.Key, true)
			}
		}
	}
}

func (etcd *ETCDClusterRunner) FastForwardTime(seconds int) {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		response, err := etcd.client.Get("/", false, true)
		Ω(err).ShouldNot(HaveOccurred())
		etcd.fastForwardTime(response.Node, seconds)
	}
}

func (etcd *ETCDClusterRunner) Adapter() storeadapter.StoreAdapter {
	pool := workpool.NewWorkPool(10)
	adapter := etcdstoreadapter.NewETCDStoreAdapter(etcd.NodeURLS(), pool)
	adapter.Connect()
	return adapter
}

func (etcd *ETCDClusterRunner) RetryableAdapter() storeadapter.StoreAdapter {
	pool := workpool.NewWorkPool(10)

	adapter := storeadapter.NewRetryable(
		etcdstoreadapter.NewETCDStoreAdapter(etcd.NodeURLS(), pool),
		clock.NewClock(),
		storeadapter.ExponentialRetryPolicy{},
	)

	adapter.Connect()

	return adapter
}

func (etcd *ETCDClusterRunner) start(nuke bool) {
	etcd.mutex.RLock()
	running := etcd.running
	etcd.mutex.RUnlock()

	if running {
		return
	}

	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	etcd.etcdProcesses = make([]ifrit.Process, etcd.numNodes)

	clusterURLs := make([]string, etcd.numNodes)
	for i := 0; i < etcd.numNodes; i++ {
		clusterURLs[i] = etcd.nodeName(i) + "=" + etcd.serverURL(i)
	}

	for i := 0; i < etcd.numNodes; i++ {
		if nuke {
			etcd.nukeArtifacts(i)
		}

		if etcd.detectRunningEtcd(i) {
			log.Fatalf("Detected an ETCD already running on %s", etcd.clientURL(i))
		}

		os.MkdirAll(etcd.tmpPath(i), 0700)
		process := ginkgomon.Invoke(ginkgomon.New(ginkgomon.Config{
			Name:              "etcd_cluster",
			AnsiColorCode:     "33m",
			StartCheck:        "etcdserver: published",
			StartCheckTimeout: 5 * time.Second,
			Command: exec.Command(
				"etcd",
				"--name", etcd.nodeName(i),
				"--data-dir", etcd.tmpPath(i),
				"--listen-client-urls", etcd.clientURL(i),
				"--listen-peer-urls", etcd.serverURL(i),
				"--initial-cluster", strings.Join(clusterURLs, ","),
				"--initial-advertise-peer-urls", etcd.serverURL(i),
				"--initial-cluster-state", "new",
				"--advertise-client-urls", etcd.clientURL(i),
			),
		}))

		etcd.etcdProcesses[i] = process

		Eventually(func() bool {
			defer func() {
				// https://github.com/coreos/go-etcd/issues/114
				recover()
			}()

			return etcd.detectRunningEtcd(i)
		}, 10, 0.05).Should(BeTrue(), "Expected ETCD to be up and running")
	}

	etcd.client = etcdclient.NewClient(etcd.NodeURLS())
	etcd.running = true
}

func (etcd *ETCDClusterRunner) stop(nuke bool) {
	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	if etcd.running {
		for i := 0; i < etcd.numNodes; i++ {
			ginkgomon.Interrupt(etcd.etcdProcesses[i], 5*time.Second)
			if nuke {
				etcd.nukeArtifacts(i)
			}
		}
		etcd.markAsStopped()
	}
}

func (etcd *ETCDClusterRunner) kill() {
	etcd.mutex.Lock()
	defer etcd.mutex.Unlock()

	if etcd.running {
		for i := 0; i < etcd.numNodes; i++ {
			ginkgomon.Kill(etcd.etcdProcesses[i], 5*time.Second)
			etcd.nukeArtifacts(i)
		}
		etcd.markAsStopped()
	}
}

func (etcd *ETCDClusterRunner) markAsStopped() {
	etcd.etcdProcesses = nil
	etcd.running = false
	etcd.client = nil
}

func (etcd *ETCDClusterRunner) detectRunningEtcd(index int) bool {
	client := etcdclient.NewClient([]string{})
	return client.SetCluster([]string{etcd.clientURL(index)})
}

func (etcd *ETCDClusterRunner) fastForwardTime(etcdNode *etcdclient.Node, seconds int) {
	if etcdNode.Dir == true {
		for _, child := range etcdNode.Nodes {
			etcd.fastForwardTime(child, seconds)
		}
	} else {
		if etcdNode.TTL == 0 {
			return
		}
		if etcdNode.TTL <= int64(seconds) {
			_, err := etcd.client.Delete(etcdNode.Key, true)
			Ω(err).ShouldNot(HaveOccurred())
		} else {
			_, err := etcd.client.Set(etcdNode.Key, etcdNode.Value, uint64(etcdNode.TTL-int64(seconds)))
			Ω(err).ShouldNot(HaveOccurred())
		}
	}
}

func (etcd *ETCDClusterRunner) clientURL(index int) string {
	return fmt.Sprintf("http://127.0.0.1:%d", etcd.port(index))
}

func (etcd *ETCDClusterRunner) serverURL(index int) string {
	return fmt.Sprintf("http://127.0.0.1:%d", etcd.port(index)+3000)
}

func (etcd *ETCDClusterRunner) nodeName(index int) string {
	return fmt.Sprintf("node%d", index)
}

func (etcd *ETCDClusterRunner) port(index int) int {
	return etcd.startingPort + index
}

func (etcd *ETCDClusterRunner) tmpPath(index int) string {
	return fmt.Sprintf("/tmp/ETCD_%d", etcd.port(index))
}

func (etcd *ETCDClusterRunner) tmpPathTo(subdir string, index int) string {
	return fmt.Sprintf("/%s/%s", etcd.tmpPath(index), subdir)
}

func (etcd *ETCDClusterRunner) nukeArtifacts(index int) {
	os.RemoveAll(etcd.tmpPath(index))
}
<|endoftext|>


<commit_before>// +build !no_lz4
package compress

import (
	"bytes"
	"github.com/pierrec/lz4/v4"
	"github.com/xitongsys/parquet-go/parquet"
	"io/ioutil"
	"sync"
)

func init() {
	lz4WriterPool := sync.Pool{
		New: func() interface{} {
			return lz4.NewWriter(nil)
		},
	}
	compressors[parquet.CompressionCodec_LZ4] = &Compressor{
		Compress: func(buf []byte) []byte {
			lz4Writer := lz4WriterPool.Get().(*lz4.Writer)
			res := new(bytes.Buffer)
			lz4Writer.Reset(res)
			lz4Writer.Write(buf)
			lz4Writer.Close()
			lz4Writer.Reset(nil)
			lz4WriterPool.Put(lz4Writer)
			return res.Bytes()
		},
		Uncompress: func(buf []byte) (i []byte, err error) {
			rbuf := bytes.NewReader(buf)
			lz4Reader := lz4.NewReader(rbuf)
			res, err := ioutil.ReadAll(lz4Reader)
			return res, err
		},
	}
}
<commit_msg>Reformat +build tag<commit_after>// +build !no_lz4

package compress

import (
	"bytes"
	"github.com/pierrec/lz4/v4"
	"github.com/xitongsys/parquet-go/parquet"
	"io/ioutil"
	"sync"
)

func init() {
	lz4WriterPool := sync.Pool{
		New: func() interface{} {
			return lz4.NewWriter(nil)
		},
	}
	compressors[parquet.CompressionCodec_LZ4] = &Compressor{
		Compress: func(buf []byte) []byte {
			lz4Writer := lz4WriterPool.Get().(*lz4.Writer)
			res := new(bytes.Buffer)
			lz4Writer.Reset(res)
			lz4Writer.Write(buf)
			lz4Writer.Close()
			lz4Writer.Reset(nil)
			lz4WriterPool.Put(lz4Writer)
			return res.Bytes()
		},
		Uncompress: func(buf []byte) (i []byte, err error) {
			rbuf := bytes.NewReader(buf)
			lz4Reader := lz4.NewReader(rbuf)
			res, err := ioutil.ReadAll(lz4Reader)
			return res, err
		},
	}
}
<|endoftext|>


<commit_before>package compress

import (
	"net/http"
	"strings"
)

var uncompresibleTypes = map[string]struct{}{
	"":                             {},
	"application/pdf":              {},
	"application/x-gzip":           {},
	"application/x-rar-compressed": {},
	"application/zip":              {},
	"image/gif":                    {},
	"image/jpeg":                   {},
	"image/png":                    {},
	"video/mpeg":                   {},
	"video/mp4":                    {},
	"video/x-flv":                  {},
	"video/webm":                   {},
	"audio/webm":                   {},
	"audio/aac":                    {},
	"audio/mp4":                    {},
	"video/h264":                   {},
	"audio/mpeg":                   {},
	"audio/wav":                    {},
}

// compressibleContentType tells if the content type must be compressed.
// This avoids compressing already compressed content, or content without a declared type.
func compressibleContentType(w http.ResponseWriter) bool {
	if _, ok := uncompresibleTypes[strings.ToLower(w.Header().Get("Content-Type"))]; ok {
		return false
	}
	return true
}
<commit_msg>Improve readability of compressible.go<commit_after>package compress

import (
	"net/http"
	"strings"
)

var uncompresibleTypes = map[string]struct{}{
	"":                             {},
	"application/pdf":              {},
	"application/x-gzip":           {},
	"application/x-rar-compressed": {},
	"application/zip":              {},
	"image/gif":                    {},
	"image/jpeg":                   {},
	"image/png":                    {},
	"video/mpeg":                   {},
	"video/mp4":                    {},
	"video/x-flv":                  {},
	"video/webm":                   {},
	"audio/webm":                   {},
	"audio/aac":                    {},
	"audio/mp4":                    {},
	"video/h264":                   {},
	"audio/mpeg":                   {},
	"audio/wav":                    {},
}

// compressibleContentType tells if the content type must be compressed.
// This avoids compressing already compressed content, or content without a declared type.
func compressibleContentType(w http.ResponseWriter) bool {
	_, ok := uncompresibleTypes[strings.ToLower(w.Header().Get("Content-Type"))]
	return !ok
}
<|endoftext|>


<commit_before>package conf

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"strings"
	"time"

	"github.com/op/go-logging"
)

type PQueueConfigData struct {
	DefaultMessageTtl    int64
	DefaultDeliveryDelay int64
	DefaultLockTimeout   int64
	DefaultPopCountLimit int64
	ExpirationBatchSize  int64
	UnlockBatchSize      int64
	MaxPopWaitTimeout    int64
	MaxPopBatchSize      int64
}

type DSQueueConfigData struct {
	DefaultMessageTtl    int64
	DefaultDeliveryDelay int64
	DefaultLockTimeout   int64
	DefaultPopCountLimit int64
	ExpirationBatchSize  int64
	UnlockBatchSize      int64
	MaxPopWaitTimeout    int64
	MaxPopBatchSize      int64
}

type Config struct {
	Port                int
	Interface           string
	DbFlushInterval     time.Duration
	DbBufferSize        int64
	LogLevel            logging.Level
	PQueueConfig        PQueueConfigData
	DSQueueConfig       DSQueueConfigData
	UpdateInterval      time.Duration
	BinaryLogPath       string
	BinaryLogBufferSize int
	BinaryLogPageSize   uint64
}

func NewDefaultConfig() *Config {
	cfg := Config{
		Port:                9033,
		Interface:           "",
		DbFlushInterval:     100,
		DbBufferSize:        10000,
		LogLevel:            logging.INFO,
		BinaryLogPath:       "./",
		BinaryLogBufferSize: 128,
		BinaryLogPageSize:   2 * 1024 * 1024 * 1025, // 2Gb
		PQueueConfig: PQueueConfigData{
			DefaultMessageTtl:    10 * 60 * 1000,
			DefaultDeliveryDelay: 0,
			DefaultLockTimeout:   60 * 1000,
			DefaultPopCountLimit: 0,
			ExpirationBatchSize:  1000,
			UnlockBatchSize:      1000,
			MaxPopWaitTimeout:    30000,
			MaxPopBatchSize:      10,
		},
		DSQueueConfig: DSQueueConfigData{
			DefaultMessageTtl:    10 * 60 * 1000,
			DefaultDeliveryDelay: 0,
			DefaultLockTimeout:   60 * 1000,
			DefaultPopCountLimit: 0,
			ExpirationBatchSize:  1000,
			UnlockBatchSize:      1000,
			MaxPopWaitTimeout:    30000,
			MaxPopBatchSize:      10,
		},
	}
	return &cfg
}

var CFG *Config = NewDefaultConfig()

func getErrorLine(data []byte, byteOffset int64) (int64, int64, string) {
	var lineNum int64 = 1
	var lineOffset int64 = 0
	var lineData []byte
	for idx, b := range data {
		if b < 32 {
			if lineOffset > 0 {
				lineNum += 1
				lineOffset = 0
				lineData = make([]byte, 0, 32)
			}

		} else {
			lineOffset += 1
			lineData = append(lineData, b)
		}
		if int64(idx) == byteOffset {
			break
		}
	}
	return lineNum, lineOffset, string(lineData)
}

func formatTypeError(lineNum, lineOffset int64, lineText string, err *json.UnmarshalTypeError) string {
	return fmt.Sprintf(
		"Config error at line %d:%d. Unexpected data type '%s', should be '%s': '%s'",
		lineNum, lineOffset, err.Value, err.Type.String(), strings.TrimSpace(lineText))
}

func ReadConfig() error {
	confData, err := ioutil.ReadFile("firempq_cfg.json")

	if err != nil {
		return err
	}

	decoder := json.NewDecoder(bytes.NewReader(confData))
	cfg := NewDefaultConfig()
	err = decoder.Decode(cfg)
	if err != nil {
		if e, ok := err.(*json.UnmarshalTypeError); ok {
			num, offset, str := getErrorLine(confData, e.Offset)
			err = errors.New(formatTypeError(num, offset, str, e))
		}
		return err
	}
	CFG = cfg
	return nil
}
<commit_msg>Added bin log frame size config.<commit_after>package conf

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"strings"
	"time"

	"github.com/op/go-logging"
)

type PQueueConfigData struct {
	DefaultMessageTtl    int64
	DefaultDeliveryDelay int64
	DefaultLockTimeout   int64
	DefaultPopCountLimit int64
	ExpirationBatchSize  int64
	UnlockBatchSize      int64
	MaxPopWaitTimeout    int64
	MaxPopBatchSize      int64
}

type DSQueueConfigData struct {
	DefaultMessageTtl    int64
	DefaultDeliveryDelay int64
	DefaultLockTimeout   int64
	DefaultPopCountLimit int64
	ExpirationBatchSize  int64
	UnlockBatchSize      int64
	MaxPopWaitTimeout    int64
	MaxPopBatchSize      int64
}

type Config struct {
	Port                int
	Interface           string
	DbFlushInterval     time.Duration
	DbBufferSize        int64
	LogLevel            logging.Level
	PQueueConfig        PQueueConfigData
	DSQueueConfig       DSQueueConfigData
	UpdateInterval      time.Duration
	BinaryLogPath       string
	BinaryLogBufferSize int
	BinaryLogPageSize   uint64
	BinaryLogFrameSize  uint64
}

func NewDefaultConfig() *Config {
	cfg := Config{
		Port:                9033,
		Interface:           "",
		DbFlushInterval:     100,
		DbBufferSize:        10000,
		LogLevel:            logging.INFO,
		BinaryLogPath:       "./",
		BinaryLogBufferSize: 128,
		BinaryLogPageSize:   2 * 1024 * 1024 * 1025, // 2Gb
		PQueueConfig: PQueueConfigData{
			DefaultMessageTtl:    10 * 60 * 1000,
			DefaultDeliveryDelay: 0,
			DefaultLockTimeout:   60 * 1000,
			DefaultPopCountLimit: 0,
			ExpirationBatchSize:  1000,
			UnlockBatchSize:      1000,
			MaxPopWaitTimeout:    30000,
			MaxPopBatchSize:      10,
		},
		DSQueueConfig: DSQueueConfigData{
			DefaultMessageTtl:    10 * 60 * 1000,
			DefaultDeliveryDelay: 0,
			DefaultLockTimeout:   60 * 1000,
			DefaultPopCountLimit: 0,
			ExpirationBatchSize:  1000,
			UnlockBatchSize:      1000,
			MaxPopWaitTimeout:    30000,
			MaxPopBatchSize:      10,
		},
	}
	return &cfg
}

var CFG *Config = NewDefaultConfig()

func getErrorLine(data []byte, byteOffset int64) (int64, int64, string) {
	var lineNum int64 = 1
	var lineOffset int64 = 0
	var lineData []byte
	for idx, b := range data {
		if b < 32 {
			if lineOffset > 0 {
				lineNum += 1
				lineOffset = 0
				lineData = make([]byte, 0, 32)
			}

		} else {
			lineOffset += 1
			lineData = append(lineData, b)
		}
		if int64(idx) == byteOffset {
			break
		}
	}
	return lineNum, lineOffset, string(lineData)
}

func formatTypeError(lineNum, lineOffset int64, lineText string, err *json.UnmarshalTypeError) string {
	return fmt.Sprintf(
		"Config error at line %d:%d. Unexpected data type '%s', should be '%s': '%s'",
		lineNum, lineOffset, err.Value, err.Type.String(), strings.TrimSpace(lineText))
}

func ReadConfig() error {
	confData, err := ioutil.ReadFile("firempq_cfg.json")

	if err != nil {
		return err
	}

	decoder := json.NewDecoder(bytes.NewReader(confData))
	cfg := NewDefaultConfig()
	err = decoder.Decode(cfg)
	if err != nil {
		if e, ok := err.(*json.UnmarshalTypeError); ok {
			num, offset, str := getErrorLine(confData, e.Offset)
			err = errors.New(formatTypeError(num, offset, str, e))
		}
		return err
	}
	CFG = cfg
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Gravitational, Inc.

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 native

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"sync"
	"time"

	"github.com/gravitational/log"
	"github.com/gravitational/trace"

	"golang.org/x/crypto/ssh"
)

const precalculatedKeysNum = 20

type keyPair struct {
	privPem  []byte
	pubBytes []byte
}

type nauth struct {
	generatedKeys []keyPair
	*sync.Mutex
}

func New() *nauth {
	return &nauth{
		generatedKeys: make([]keyPair, 0, precalculatedKeysNum),
		Mutex:         &sync.Mutex{},
	}
}

func (n *nauth) GenerateKeyPair(passphrase string) ([]byte, []byte, error) {
	n.Lock()
	if len(n.generatedKeys) == 0 {
		n.Unlock()
		return n.generateKeyPair()
	}
	defer n.Unlock()
	go n.precalculateKey()
	key := n.generatedKeys[len(n.generatedKeys)-1]
	n.generatedKeys[len(n.generatedKeys)-1] = keyPair{}
	n.generatedKeys = n.generatedKeys[:len(n.generatedKeys)-1]

	return key.privPem, key.pubBytes, nil
}

func (n *nauth) precalculateKey() {
	for {
		privPem, pubBytes, err := n.generateKeyPair()
		if err != nil {
			log.Errorf(err.Error())
			continue
		}
		key := keyPair{
			privPem:  privPem,
			pubBytes: pubBytes,
		}
		n.Lock()
		defer n.Unlock()
		if len(n.generatedKeys) >= precalculatedKeysNum {
			return
		}
		n.generatedKeys = append(n.generatedKeys, key)
		return
	}
}

func (n *nauth) generateKeyPair() ([]byte, []byte, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}
	privDer := x509.MarshalPKCS1PrivateKey(priv)
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privDer,
	}
	privPem := pem.EncodeToMemory(&privBlock)

	pub, err := ssh.NewPublicKey(&priv.PublicKey)
	if err != nil {
		return nil, nil, err
	}
	pubBytes := ssh.MarshalAuthorizedKey(pub)
	return privPem, pubBytes, nil
}

func (n *nauth) GenerateHostCert(pkey, key []byte, id, hostname, role string, ttl time.Duration) ([]byte, error) {
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey(key)
	if err != nil {
		return nil, err
	}
	validBefore := uint64(ssh.CertTimeInfinity)
	if ttl != 0 {
		b := time.Now().Add(ttl)
		validBefore = uint64(b.UnixNano())
	}
	cert := &ssh.Certificate{
		ValidPrincipals: []string{hostname},
		Key:             pubKey,
		ValidBefore:     validBefore,
		CertType:        ssh.HostCert,
	}
	cert.Permissions.Extensions = make(map[string]string)
	cert.Permissions.Extensions["role"] = role
	signer, err := ssh.ParsePrivateKey(pkey)
	if err != nil {
		return nil, err
	}
	if err := cert.SignCert(rand.Reader, signer); err != nil {
		return nil, err
	}
	return ssh.MarshalAuthorizedKey(cert), nil
}

func (n *nauth) GenerateUserCert(pkey, key []byte, id, username string, ttl time.Duration) ([]byte, error) {
	if (ttl > MaxCertDuration) || (ttl < MinCertDuration) {
		return nil, trace.Errorf("wrong certificate ttl")
	}
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey(key)
	if err != nil {
		return nil, err
	}
	validBefore := uint64(ssh.CertTimeInfinity)
	if ttl != 0 {
		b := time.Now().Add(ttl)
		validBefore = uint64(b.Unix())
	}
	cert := &ssh.Certificate{
		ValidPrincipals: []string{username},
		Key:             pubKey,
		ValidBefore:     validBefore,
		CertType:        ssh.UserCert,
	}
	signer, err := ssh.ParsePrivateKey(pkey)
	if err != nil {
		return nil, err
	}
	if err := cert.SignCert(rand.Reader, signer); err != nil {
		return nil, err
	}
	return ssh.MarshalAuthorizedKey(cert), nil
}

const (
	MinCertDuration = time.Minute
	MaxCertDuration = 30 * time.Hour
)
<commit_msg>Modified keys precompiling<commit_after>/*
Copyright 2015 Gravitational, Inc.

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 native

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"sync"
	"time"

	"github.com/gravitational/log"
	"github.com/gravitational/trace"

	"golang.org/x/crypto/ssh"
)

const precalculatedKeysNum = 20

type keyPair struct {
	privPem  []byte
	pubBytes []byte
}

type nauth struct {
	generatedKeys []keyPair
	*sync.Mutex
}

func New() *nauth {
	n := nauth{
		generatedKeys: make([]keyPair, 0, precalculatedKeysNum),
		Mutex:         &sync.Mutex{},
	}
	go n.precalculateKey()
	return &n
}

func (n *nauth) GenerateKeyPair(passphrase string) ([]byte, []byte, error) {
	n.Lock()
	if len(n.generatedKeys) == 0 {
		n.Unlock()
		return n.generateKeyPair()
	}
	defer n.Unlock()
	key := n.generatedKeys[len(n.generatedKeys)-1]
	n.generatedKeys[len(n.generatedKeys)-1] = keyPair{}
	n.generatedKeys = n.generatedKeys[:len(n.generatedKeys)-1]

	return key.privPem, key.pubBytes, nil
}

func (n *nauth) precalculateKey() {
	for {
		privPem, pubBytes, err := n.generateKeyPair()
		if err != nil {
			log.Errorf(err.Error())
			continue
		}
		key := keyPair{
			privPem:  privPem,
			pubBytes: pubBytes,
		}
		n.Lock()
		for len(n.generatedKeys) >= precalculatedKeysNum {
			n.Unlock()
			time.Sleep(time.Second)
			n.Lock()
		}
		n.generatedKeys = append(n.generatedKeys, key)
		n.Unlock()
	}
}

func (n *nauth) generateKeyPair() ([]byte, []byte, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}
	privDer := x509.MarshalPKCS1PrivateKey(priv)
	privBlock := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil,
		Bytes:   privDer,
	}
	privPem := pem.EncodeToMemory(&privBlock)

	pub, err := ssh.NewPublicKey(&priv.PublicKey)
	if err != nil {
		return nil, nil, err
	}
	pubBytes := ssh.MarshalAuthorizedKey(pub)
	return privPem, pubBytes, nil
}

func (n *nauth) GenerateHostCert(pkey, key []byte, id, hostname, role string, ttl time.Duration) ([]byte, error) {
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey(key)
	if err != nil {
		return nil, err
	}
	validBefore := uint64(ssh.CertTimeInfinity)
	if ttl != 0 {
		b := time.Now().Add(ttl)
		validBefore = uint64(b.UnixNano())
	}
	cert := &ssh.Certificate{
		ValidPrincipals: []string{hostname},
		Key:             pubKey,
		ValidBefore:     validBefore,
		CertType:        ssh.HostCert,
	}
	cert.Permissions.Extensions = make(map[string]string)
	cert.Permissions.Extensions["role"] = role
	signer, err := ssh.ParsePrivateKey(pkey)
	if err != nil {
		return nil, err
	}
	if err := cert.SignCert(rand.Reader, signer); err != nil {
		return nil, err
	}
	return ssh.MarshalAuthorizedKey(cert), nil
}

func (n *nauth) GenerateUserCert(pkey, key []byte, id, username string, ttl time.Duration) ([]byte, error) {
	if (ttl > MaxCertDuration) || (ttl < MinCertDuration) {
		return nil, trace.Errorf("wrong certificate ttl")
	}
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey(key)
	if err != nil {
		return nil, err
	}
	validBefore := uint64(ssh.CertTimeInfinity)
	if ttl != 0 {
		b := time.Now().Add(ttl)
		validBefore = uint64(b.Unix())
	}
	cert := &ssh.Certificate{
		ValidPrincipals: []string{username},
		Key:             pubKey,
		ValidBefore:     validBefore,
		CertType:        ssh.UserCert,
	}
	signer, err := ssh.ParsePrivateKey(pkey)
	if err != nil {
		return nil, err
	}
	if err := cert.SignCert(rand.Reader, signer); err != nil {
		return nil, err
	}
	return ssh.MarshalAuthorizedKey(cert), nil
}

const (
	MinCertDuration = time.Minute
	MaxCertDuration = 30 * time.Hour
)
<|endoftext|>


<commit_before>package lfsapi

import (
	"crypto/tls"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/rubyist/tracerx"
)

var UserAgent = "git-lfs"

func (c *Client) NewRequest(method string, e Endpoint, suffix string, body interface{}) (*http.Request, error) {
	req, err := http.NewRequest(method, joinURL(e.Url, suffix), nil)
	if err != nil {
		return req, err
	}

	if body != nil {
		if merr := MarshalToRequest(req, body); merr != nil {
			return req, merr
		}
	}

	return req, err
}

const slash = "/"

func joinURL(prefix, suffix string) string {
	if strings.HasSuffix(prefix, slash) {
		return prefix + suffix
	}
	return prefix + slash + suffix
}

func (c *Client) Do(req *http.Request) (*http.Response, error) {
	req.Header.Set("User-Agent", UserAgent)

	res, err := c.doWithRedirects(c.httpClient(req.Host), req, nil)
	if err != nil {
		return res, err
	}

	return res, c.handleResponse(res)
}

func (c *Client) doWithRedirects(cli *http.Client, req *http.Request, via []*http.Request) (*http.Response, error) {
	c.traceRequest(req)
	if err := c.prepareRequestBody(req); err != nil {
		return nil, err
	}

	start := time.Now()
	res, err := cli.Do(req)
	if err != nil {
		return res, err
	}

	c.traceResponse(res)
	c.startResponseStats(res, start)

	if res.StatusCode != 307 {
		return res, err
	}

	redirectTo := res.Header.Get("Location")
	locurl, err := url.Parse(redirectTo)
	if err == nil && !locurl.IsAbs() {
		locurl = req.URL.ResolveReference(locurl)
		redirectTo = locurl.String()
	}

	via = append(via, req)
	if len(via) >= 3 {
		return res, errors.New("too many redirects")
	}

	redirectedReq, err := newRequestForRetry(req, redirectTo)
	if err != nil {
		return res, err
	}

	return c.doWithRedirects(cli, redirectedReq, via)
}

func (c *Client) httpClient(host string) *http.Client {
	c.clientMu.Lock()
	defer c.clientMu.Unlock()

	if c.gitEnv == nil {
		c.gitEnv = make(Env)
	}

	if c.osEnv == nil {
		c.osEnv = make(Env)
	}

	if c.hostClients == nil {
		c.hostClients = make(map[string]*http.Client)
	}

	if client, ok := c.hostClients[host]; ok {
		return client
	}

	concurrentTransfers := c.ConcurrentTransfers
	if concurrentTransfers < 1 {
		concurrentTransfers = 3
	}

	dialtime := c.DialTimeout
	if dialtime < 1 {
		dialtime = 30
	}

	keepalivetime := c.KeepaliveTimeout
	if keepalivetime < 1 {
		keepalivetime = 1800
	}

	tlstime := c.TLSTimeout
	if tlstime < 1 {
		tlstime = 30
	}

	tr := &http.Transport{
		Proxy: ProxyFromClient(c),
		Dial: (&net.Dialer{
			Timeout:   time.Duration(dialtime) * time.Second,
			KeepAlive: time.Duration(keepalivetime) * time.Second,
		}).Dial,
		TLSHandshakeTimeout: time.Duration(tlstime) * time.Second,
		MaxIdleConnsPerHost: concurrentTransfers,
	}

	tr.TLSClientConfig = &tls.Config{}
	if isCertVerificationDisabledForHost(c, host) {
		tr.TLSClientConfig.InsecureSkipVerify = true
	} else {
		tr.TLSClientConfig.RootCAs = getRootCAsForHost(c, host)
	}

	httpClient := &http.Client{
		Transport: tr,
		CheckRedirect: func(*http.Request, []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}

	c.hostClients[host] = httpClient
	if c.VerboseOut == nil {
		c.VerboseOut = os.Stderr
	}

	return httpClient
}

func (c *Client) CurrentUser() (string, string) {
	userName, _ := c.gitEnv.Get("user.name")
	userEmail, _ := c.gitEnv.Get("user.email")
	return userName, userEmail
}

func newRequestForRetry(req *http.Request, location string) (*http.Request, error) {
	newReq, err := http.NewRequest(req.Method, location, nil)
	if err != nil {
		return nil, err
	}

	for key := range req.Header {
		if key == "Authorization" {
			if req.URL.Scheme != newReq.URL.Scheme || req.URL.Host != newReq.URL.Host {
				continue
			}
		}
		newReq.Header.Set(key, req.Header.Get(key))
	}

	oldestURL := strings.SplitN(req.URL.String(), "?", 2)[0]
	newURL := strings.SplitN(newReq.URL.String(), "?", 2)[0]
	tracerx.Printf("api: redirect %s %s to %s", req.Method, oldestURL, newURL)

	newReq.Body = req.Body
	newReq.ContentLength = req.ContentLength
	return newReq, nil
}
<commit_msg>lfsapi: set Content-Type and Accept as necessary<commit_after>package lfsapi

import (
	"crypto/tls"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/rubyist/tracerx"
)

var UserAgent = "git-lfs"

const MediaType = "application/vnd.git-lfs+json; charset=utf-8"

func (c *Client) NewRequest(method string, e Endpoint, suffix string, body interface{}) (*http.Request, error) {
	req, err := http.NewRequest(method, joinURL(e.Url, suffix), nil)
	if err != nil {
		return req, err
	}

	req.Header.Set("Accept", MediaType)

	if body != nil {
		if merr := MarshalToRequest(req, body); merr != nil {
			return req, merr
		}
		req.Header.Set("Content-Type", MediaType)
	}

	return req, err
}

const slash = "/"

func joinURL(prefix, suffix string) string {
	if strings.HasSuffix(prefix, slash) {
		return prefix + suffix
	}
	return prefix + slash + suffix
}

func (c *Client) Do(req *http.Request) (*http.Response, error) {
	req.Header.Set("User-Agent", UserAgent)

	res, err := c.doWithRedirects(c.httpClient(req.Host), req, nil)
	if err != nil {
		return res, err
	}

	return res, c.handleResponse(res)
}

func (c *Client) doWithRedirects(cli *http.Client, req *http.Request, via []*http.Request) (*http.Response, error) {
	c.traceRequest(req)
	if err := c.prepareRequestBody(req); err != nil {
		return nil, err
	}

	start := time.Now()
	res, err := cli.Do(req)
	if err != nil {
		return res, err
	}

	c.traceResponse(res)
	c.startResponseStats(res, start)

	if res.StatusCode != 307 {
		return res, err
	}

	redirectTo := res.Header.Get("Location")
	locurl, err := url.Parse(redirectTo)
	if err == nil && !locurl.IsAbs() {
		locurl = req.URL.ResolveReference(locurl)
		redirectTo = locurl.String()
	}

	via = append(via, req)
	if len(via) >= 3 {
		return res, errors.New("too many redirects")
	}

	redirectedReq, err := newRequestForRetry(req, redirectTo)
	if err != nil {
		return res, err
	}

	return c.doWithRedirects(cli, redirectedReq, via)
}

func (c *Client) httpClient(host string) *http.Client {
	c.clientMu.Lock()
	defer c.clientMu.Unlock()

	if c.gitEnv == nil {
		c.gitEnv = make(Env)
	}

	if c.osEnv == nil {
		c.osEnv = make(Env)
	}

	if c.hostClients == nil {
		c.hostClients = make(map[string]*http.Client)
	}

	if client, ok := c.hostClients[host]; ok {
		return client
	}

	concurrentTransfers := c.ConcurrentTransfers
	if concurrentTransfers < 1 {
		concurrentTransfers = 3
	}

	dialtime := c.DialTimeout
	if dialtime < 1 {
		dialtime = 30
	}

	keepalivetime := c.KeepaliveTimeout
	if keepalivetime < 1 {
		keepalivetime = 1800
	}

	tlstime := c.TLSTimeout
	if tlstime < 1 {
		tlstime = 30
	}

	tr := &http.Transport{
		Proxy: ProxyFromClient(c),
		Dial: (&net.Dialer{
			Timeout:   time.Duration(dialtime) * time.Second,
			KeepAlive: time.Duration(keepalivetime) * time.Second,
		}).Dial,
		TLSHandshakeTimeout: time.Duration(tlstime) * time.Second,
		MaxIdleConnsPerHost: concurrentTransfers,
	}

	tr.TLSClientConfig = &tls.Config{}
	if isCertVerificationDisabledForHost(c, host) {
		tr.TLSClientConfig.InsecureSkipVerify = true
	} else {
		tr.TLSClientConfig.RootCAs = getRootCAsForHost(c, host)
	}

	httpClient := &http.Client{
		Transport: tr,
		CheckRedirect: func(*http.Request, []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}

	c.hostClients[host] = httpClient
	if c.VerboseOut == nil {
		c.VerboseOut = os.Stderr
	}

	return httpClient
}

func (c *Client) CurrentUser() (string, string) {
	userName, _ := c.gitEnv.Get("user.name")
	userEmail, _ := c.gitEnv.Get("user.email")
	return userName, userEmail
}

func newRequestForRetry(req *http.Request, location string) (*http.Request, error) {
	newReq, err := http.NewRequest(req.Method, location, nil)
	if err != nil {
		return nil, err
	}

	for key := range req.Header {
		if key == "Authorization" {
			if req.URL.Scheme != newReq.URL.Scheme || req.URL.Host != newReq.URL.Host {
				continue
			}
		}
		newReq.Header.Set(key, req.Header.Get(key))
	}

	oldestURL := strings.SplitN(req.URL.String(), "?", 2)[0]
	newURL := strings.SplitN(newReq.URL.String(), "?", 2)[0]
	tracerx.Printf("api: redirect %s %s to %s", req.Method, oldestURL, newURL)

	newReq.Body = req.Body
	newReq.ContentLength = req.ContentLength
	return newReq, nil
}
<|endoftext|>


<commit_before>// Copyright © 2017 Aaron Donovan <amdonov@gmail.com>
//
// 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 idp

import (
	"encoding/xml"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/amdonov/lite-idp/model"
	"github.com/amdonov/lite-idp/saml"
	"github.com/golang/protobuf/proto"
	log "github.com/sirupsen/logrus"
)

// DefaultArtifactResolveHandler is the default implementation for the artifact resolution handler. It can be used as is, wrapped in other handlers, or replaced completely.
func (i *IDP) DefaultArtifactResolveHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// We require transport authentication rather than message authentication
		tlsCert, err := getCertFromRequest(r)
		if err != nil {
			i.Error(w, err.Error(), http.StatusUnauthorized)
			return
		}
		log.Infof("received artifact resolution request from %s", getSubjectDN(tlsCert.Subject))
		i.processArtifactResolutionRequest(w, r)
	}
}

func (i *IDP) processArtifactResolutionRequest(w http.ResponseWriter, r *http.Request) {
	decoder := xml.NewDecoder(r.Body)
	var resolveEnv saml.ArtifactResolveEnvelope
	err := decoder.Decode(&resolveEnv)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	artifact := resolveEnv.Body.ArtifactResolve.Artifact
	data, err := i.TempCache.Get(artifact)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	artifactResponse := &model.ArtifactResponse{}
	err = proto.Unmarshal(data, artifactResponse)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	now := time.Now().UTC()
	response := i.makeAuthnResponse(artifactResponse.Request, artifactResponse.User)
	artResponseEnv := saml.ArtifactResponseEnvelope{
		Body: saml.ArtifactResponseBody{
			ArtifactResponse: saml.ArtifactResponse{
				StatusResponseType: saml.StatusResponseType{
					ID:           saml.NewID(),
					IssueInstant: now,
					InResponseTo: resolveEnv.Body.ArtifactResolve.ID,
					Version:      "2.0",
					Issuer:       saml.NewIssuer(i.entityID),
					Status: &saml.Status{
						StatusCode: saml.StatusCode{
							Value: "urn:oasis:names:tc:SAML:2.0:status:Success",
						},
					},
				},
				Response: *response,
			},
		},
	}

	notOnOrAfter := response.Assertion.Conditions.NotOnOrAfter
	if !notOnOrAfter.IsZero() && now.After(notOnOrAfter) {
		i.Error(w, fmt.Sprintf("at %s got response that cannot be processed because it expired at %s", now, notOnOrAfter), http.StatusBadRequest)
	}

	notBefore := response.Assertion.Conditions.NotBefore
	if !notBefore.IsZero() && now.Before(notBefore) {
		i.Error(w, fmt.Sprintf("at %s got response that cannot be processed before %s", now, notBefore), http.StatusBadRequest)
	}

	signature, err := i.signer.CreateSignature(response.Assertion)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	response.Assertion.Signature = signature
	// TODO handle these errors. Probably can't do anything besides log, as we've already started to write the
	// response.
	_, err = w.Write([]byte(xml.Header))
	encoder := xml.NewEncoder(w)
	err = encoder.Encode(artResponseEnv)
	err = encoder.Flush()
}

func (i *IDP) sendArtifactResponse(authRequest *model.AuthnRequest, user *model.User,
	w http.ResponseWriter, r *http.Request) error {
	target, err := url.Parse(authRequest.AssertionConsumerServiceURL)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
	}
	parameters := url.Values{}
	artifact := getArtifact(i.entityID)
	// Store required data in the cache
	response := &model.ArtifactResponse{
		User:    user,
		Request: authRequest,
	}
	data, err := proto.Marshal(response)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
	}
	i.TempCache.Set(artifact, data)
	parameters.Add("SAMLart", artifact)
	parameters.Add("RelayState", authRequest.RelayState)
	target.RawQuery = parameters.Encode()
	// Don't send temporary redirect. We don't want the post resent
	http.Redirect(w, r, target.String(), http.StatusFound)

	return nil
}
<commit_msg>Transpose retrieval of now time to get a more accurate time<commit_after>// Copyright © 2017 Aaron Donovan <amdonov@gmail.com>
//
// 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 idp

import (
	"encoding/xml"
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/amdonov/lite-idp/model"
	"github.com/amdonov/lite-idp/saml"
	"github.com/golang/protobuf/proto"
	log "github.com/sirupsen/logrus"
)

// DefaultArtifactResolveHandler is the default implementation for the artifact resolution handler. It can be used as is, wrapped in other handlers, or replaced completely.
func (i *IDP) DefaultArtifactResolveHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// We require transport authentication rather than message authentication
		tlsCert, err := getCertFromRequest(r)
		if err != nil {
			i.Error(w, err.Error(), http.StatusUnauthorized)
			return
		}
		log.Infof("received artifact resolution request from %s", getSubjectDN(tlsCert.Subject))
		i.processArtifactResolutionRequest(w, r)
	}
}

func (i *IDP) processArtifactResolutionRequest(w http.ResponseWriter, r *http.Request) {
	decoder := xml.NewDecoder(r.Body)
	var resolveEnv saml.ArtifactResolveEnvelope
	err := decoder.Decode(&resolveEnv)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	artifact := resolveEnv.Body.ArtifactResolve.Artifact
	data, err := i.TempCache.Get(artifact)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	artifactResponse := &model.ArtifactResponse{}
	err = proto.Unmarshal(data, artifactResponse)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	response := i.makeAuthnResponse(artifactResponse.Request, artifactResponse.User)
	now := time.Now().UTC()
	artResponseEnv := saml.ArtifactResponseEnvelope{
		Body: saml.ArtifactResponseBody{
			ArtifactResponse: saml.ArtifactResponse{
				StatusResponseType: saml.StatusResponseType{
					ID:           saml.NewID(),
					IssueInstant: now,
					InResponseTo: resolveEnv.Body.ArtifactResolve.ID,
					Version:      "2.0",
					Issuer:       saml.NewIssuer(i.entityID),
					Status: &saml.Status{
						StatusCode: saml.StatusCode{
							Value: "urn:oasis:names:tc:SAML:2.0:status:Success",
						},
					},
				},
				Response: *response,
			},
		},
	}

	notOnOrAfter := response.Assertion.Conditions.NotOnOrAfter
	if !notOnOrAfter.IsZero() && now.After(notOnOrAfter) {
		i.Error(w, fmt.Sprintf("at %s got response that cannot be processed because it expired at %s", now, notOnOrAfter), http.StatusBadRequest)
	}

	notBefore := response.Assertion.Conditions.NotBefore
	if !notBefore.IsZero() && now.Before(notBefore) {
		i.Error(w, fmt.Sprintf("at %s got response that cannot be processed before %s", now, notBefore), http.StatusBadRequest)
	}

	signature, err := i.signer.CreateSignature(response.Assertion)
	// TODO confirm appropriate error response for this service
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	response.Assertion.Signature = signature
	// TODO handle these errors. Probably can't do anything besides log, as we've already started to write the
	// response.
	_, err = w.Write([]byte(xml.Header))
	encoder := xml.NewEncoder(w)
	err = encoder.Encode(artResponseEnv)
	err = encoder.Flush()
}

func (i *IDP) sendArtifactResponse(authRequest *model.AuthnRequest, user *model.User,
	w http.ResponseWriter, r *http.Request) error {
	target, err := url.Parse(authRequest.AssertionConsumerServiceURL)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
	}
	parameters := url.Values{}
	artifact := getArtifact(i.entityID)
	// Store required data in the cache
	response := &model.ArtifactResponse{
		User:    user,
		Request: authRequest,
	}
	data, err := proto.Marshal(response)
	if err != nil {
		i.Error(w, err.Error(), http.StatusInternalServerError)
	}
	i.TempCache.Set(artifact, data)
	parameters.Add("SAMLart", artifact)
	parameters.Add("RelayState", authRequest.RelayState)
	target.RawQuery = parameters.Encode()
	// Don't send temporary redirect. We don't want the post resent
	http.Redirect(w, r, target.String(), http.StatusFound)

	return nil
}
<|endoftext|>


<commit_before>// 26 january 2015
package iface

// TODO settle the overloading of definitions of 'message'

// Server represents a server.
type Server interface {
	// Send and Recv return channels that send and receive, respectively, Messages to/from the server.
	// The values of these channels are guaranteed not to change during the lifetime of the Server object, and they shall not be closed during said lifetime.
	Send() chan<- Message
	Recv() <-chan Message

	// Connect establishes the connection to the Server.
	// After Connect, Send and Recv will begin processing messages.
	// A Message of type Connected will be received once the connection has been established.
	// A Message of type Error will be received if the connection fails.
	// Connect may send protocol-specific handshake messages as necessary; the Server object's actual type should define an interface for this (for instance, for establishing the initial username and identifying information about a user).
	// (TODO what happens if already connected)
	Connect()

	// Raw returns a Message that, when sent, issues the given byte sequence directly to the server.
	// TODO hostmasks
	Raw(sequence []byte) Message

	// Join returns a Message that, when sent, ask the server to join a given channel.
	// If the Join succeeds, a Message of type Joined will be received; the value of Channel() on that Message should be used for all future accesses to that channel (until the channel is left or the server is disconnected).
	Join(channel string, password string) Message

	// Query is similar to Join, except that instead of joining a channel, it initiates a private conversation ("query") with a given user.
	// Because some protocols (IRC, for instance) don't have a special state for "querying someone else", Query() requires a line to send to the user at the same time.
	// On success, the received Message type will be QueryStarted instead of Joined, but the semantics are the same.
	Query(nick string, message []byte) Message

	// QueryDo is similar to Query, except the message is sent as an action; see Channel.Do().
	QueryDo(nick string, message []byte) Message

	// Quit returns a Message that, when sent, will lead to being disconnected from the server.
	// You may specify an optional reason.
	Quit(reason []byte) Message

	// TODO Nick()?

	// SetNick returns a Message that, when sent, requests that the server change your nickname to the given nick.
	// If successful, a Message of type YourNickChanged will be received.
	SetNick(newnick string) Message

	// Format takes the given Formatted and returns the byte sequence that it is equivalent to in the given protocol.
	// Formatting styles that are not supported are merely ignored.
	Format(f Formatted) []byte

	// TODO user mode translation
}
<commit_msg>Added Server.Away() and Server.Back()<commit_after>// 26 january 2015
package iface

// TODO settle the overloading of definitions of 'message'

// Server represents a server.
type Server interface {
	// Send and Recv return channels that send and receive, respectively, Messages to/from the server.
	// The values of these channels are guaranteed not to change during the lifetime of the Server object, and they shall not be closed during said lifetime.
	Send() chan<- Message
	Recv() <-chan Message

	// Connect establishes the connection to the Server.
	// After Connect, Send and Recv will begin processing messages.
	// A Message of type Connected will be received once the connection has been established.
	// A Message of type Error will be received if the connection fails.
	// Connect may send protocol-specific handshake messages as necessary; the Server object's actual type should define an interface for this (for instance, for establishing the initial username and identifying information about a user).
	// (TODO what happens if already connected)
	Connect()

	// Raw returns a Message that, when sent, issues the given byte sequence directly to the server.
	// TODO hostmasks
	Raw(sequence []byte) Message

	// Join returns a Message that, when sent, ask the server to join a given channel.
	// If the Join succeeds, a Message of type Joined will be received; the value of Channel() on that Message should be used for all future accesses to that channel (until the channel is left or the server is disconnected).
	Join(channel string, password string) Message

	// Query is similar to Join, except that instead of joining a channel, it initiates a private conversation ("query") with a given user.
	// Because some protocols (IRC, for instance) don't have a special state for "querying someone else", Query() requires a line to send to the user at the same time.
	// On success, the received Message type will be QueryStarted instead of Joined, but the semantics are the same.
	Query(nick string, message []byte) Message

	// QueryDo is similar to Query, except the message is sent as an action; see Channel.Do().
	QueryDo(nick string, message []byte) Message

	// Quit returns a Message that, when sent, will lead to being disconnected from the server.
	// You may specify an optional reason.
	Quit(reason []byte) Message

	// TODO Nick()?

	// SetNick returns a Message that, when sent, requests that the server change your nickname to the given nick.
	// If successful, a Message of type YourNickChanged will be received.
	SetNick(newnick string) Message

	// Format takes the given Formatted and returns the byte sequence that it is equivalent to in the given protocol.
	// Formatting styles that are not supported are merely ignored.
	Format(f Formatted) []byte

	// Away returns a Message that, when sent, marks yourself as away.
	Away(reason string) Message

	// Back returns a Message that, when sent, marks yourself as no longer away.
	Back() Message

	// TODO user mode translation
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"

	"github.com/ondevice/ondevice/config/internal"
)

// KeyClientTimeout -- specifies the timeout for HTTP requests
var KeyClientTimeout = newKey("client", "timeout", "30").setValidator(
	internal.IntValidator{}.Validate,
)

// KeyDeviceID -- represents the key where we store devId ('device.devId', defaults to '')
var KeyDeviceID = newKey("device", "dev-id", "").setRO()

// CommandRSYNC -- the path to the 'rsync' command
var CommandRSYNC = newKey("command", "rsync", "rsync")

// CommandSCP -- the path to the 'scp' command
var CommandSCP = newKey("command", "scp", "scp")

// CommandSFTP -- the path to the 'sftp' command
var CommandSFTP = newKey("command", "sftp", "sftp")

// CommandSSH -- the path to the 'ssh' command
var CommandSSH = newKey("command", "ssh", "ssh")

// PathAuthJSON -- the path to 'auth.json', relative to 'ondevice.conf'
var PathAuthJSON = newKey("path", "auth_json", "auth.json")

// PathKnownHosts -- the path to our 'known_hosts' file, relative to 'ondevice.conf'
var PathKnownHosts = newKey("path", "known_hosts", "known_hosts")

// PathOndevicePID -- the path to 'ondevice.pid', relative to 'ondevice.conf'
var PathOndevicePID = newKey("path", "ondevice_pid", "ondevice.pid")

// PathOndeviceSock -- the path to 'ondevice.sock', relative to 'ondevice.conf'
var PathOndeviceSock = newKey("path", "ondevice_sock", "ondevice.sock")

// Key -- config key struct (use the predefined Key* values when using config)
type Key struct {
	section, key, defaultValue string

	ro bool

	validateFn func(val string) error
}

// setRO -- marks configKey as being read-only (to users running 'ondevice config')
func (k Key) setRO() Key {
	k.ro = true
	allKeys[k.String()].ro = true
	return k
}

// setValidator -- sets a validator for the given value
func (k Key) setValidator(fn func(val string) error) Key {
	k.validateFn = fn
	allKeys[k.String()].validateFn = fn
	return k
}

func (k Key) String() string {
	return fmt.Sprintf("%s.%s", k.section, k.key)
}

// Validate -- if the config Key has a validator set, run it and return an error if something went wrong
func (k Key) Validate(val string) error {
	if k.validateFn == nil {
		return nil
	}
	return k.validateFn(val)
}

// WithDefault -- returns a modified configKey with defaultValue set to 'val'
func (k Key) WithDefault(val string) Key {
	return Key{
		section:      k.section,
		key:          k.key,
		defaultValue: val,
		ro:           k.ro,
	}
}

func newKey(section string, key string, defaultValue string) Key {
	var rc = Key{
		section:      section,
		key:          key,
		defaultValue: defaultValue,
	}
	allKeys[rc.String()] = &rc
	return rc
}

// AllKeys -- returns all defined config Keys
//
// if withReadOnly is set to false, this will filter out values not
func AllKeys(withReadOnly bool) map[string]Key {
	var rc = make(map[string]Key, len(allKeys))

	for k, v := range allKeys {
		if withReadOnly || !v.ro {
			rc[k] = *v
		}
	}

	return rc
}

// FindKey -- returns the configKey for the given string key (or nil if not found)
func FindKey(keyName string) *Key {
	return allKeys[keyName]
}

var allKeys = make(map[string]*Key)
<commit_msg>config: replaced newKey() with regKey(Key{}) calls<commit_after>package config

import (
	"fmt"

	"github.com/ondevice/ondevice/config/internal"
)

// Key -- config key struct (use the predefined Key* values when using config)
type Key struct {
	section, key, defaultValue string

	ro bool

	validateFn func(val string) error
}

// KeyClientTimeout -- specifies the timeout for HTTP requests
var KeyClientTimeout = regKey(Key{
	section:      "client",
	key:          "timeout",
	defaultValue: "30",
	validateFn:   internal.IntValidator{}.Validate,
})

// KeyDeviceID -- represents the key where we store devId ('device.devId', defaults to '')
var KeyDeviceID = regKey(Key{
	section: "device", key: "dev-id",
	defaultValue: "",
	ro:           true,
})

// CommandRSYNC -- the path to the 'rsync' command
var CommandRSYNC = regKey(Key{
	section: "command", key: "rsync",
	defaultValue: "rsync",
})

// CommandSCP -- the path to the 'scp' command
var CommandSCP = regKey(Key{
	section: "command", key: "scp",
	defaultValue: "scp",
})

// CommandSFTP -- the path to the 'sftp' command
var CommandSFTP = regKey(Key{
	section: "command", key: "sftp",
	defaultValue: "sftp",
})

// CommandSSH -- the path to the 'ssh' command
var CommandSSH = regKey(Key{
	section: "command", key: "ssh",
	defaultValue: "ssh",
})

// PathAuthJSON -- the path to 'auth.json', relative to 'ondevice.conf'
var PathAuthJSON = regKey(Key{
	section: "path", key: "auth_json",
	defaultValue: "auth.json",
})

// PathKnownHosts -- the path to our 'known_hosts' file, relative to 'ondevice.conf'
var PathKnownHosts = regKey(Key{
	section: "path", key: "known_hosts",
	defaultValue: "known_hosts",
})

// PathOndevicePID -- the path to 'ondevice.pid', relative to 'ondevice.conf'
var PathOndevicePID = regKey(Key{
	section: "path", key: "ondevice_pid",
	defaultValue: "ondevice.pid",
})

// PathOndeviceSock -- the path to 'ondevice.sock', relative to 'ondevice.conf'
var PathOndeviceSock = regKey(Key{
	section: "path", key: "ondevice_sock",
	defaultValue: "ondevice.sock",
})

// setRO -- marks configKey as being read-only (to users running 'ondevice config')
func (k Key) setRO() Key {
	k.ro = true
	allKeys[k.String()].ro = true
	return k
}

// setValidator -- sets a validator for the given value
func (k Key) setValidator(fn func(val string) error) Key {
	k.validateFn = fn
	allKeys[k.String()].validateFn = fn
	return k
}

func (k Key) String() string {
	return fmt.Sprintf("%s.%s", k.section, k.key)
}

// Validate -- if the config Key has a validator set, run it and return an error if something went wrong
func (k Key) Validate(val string) error {
	if k.validateFn == nil {
		return nil
	}
	return k.validateFn(val)
}

// WithDefault -- returns a modified configKey with defaultValue set to 'val'
func (k Key) WithDefault(val string) Key {
	return Key{
		section:      k.section,
		key:          k.key,
		defaultValue: val,
		ro:           k.ro,
	}
}

func regKey(key Key) Key {
	allKeys[key.String()] = &key
	return key
}

// AllKeys -- returns all defined config Keys
//
// if withReadOnly is set to false, this will filter out values not
func AllKeys(withReadOnly bool) map[string]Key {
	var rc = make(map[string]Key, len(allKeys))

	for k, v := range allKeys {
		if withReadOnly || !v.ro {
			rc[k] = *v
		}
	}

	return rc
}

// FindKey -- returns the configKey for the given string key (or nil if not found)
func FindKey(keyName string) *Key {
	return allKeys[keyName]
}

var allKeys = make(map[string]*Key)
<|endoftext|>


<commit_before>package gnosis

import (
	"errors"
	"github.com/stretchr/testify/assert"
	"os"
	"path"
	"path/filepath"
	"testing"
	// "bytes"
	// "io"
	"strings"
	// "net/http"
	"html/template"
	"net/http/httptest"
	"time"
)

func TestSimpleConfig(t *testing.T) {

	defaultConfig := `{
  "Global": {
    "Port": "8080",
    "Hostname": "localhost"
  },
  "Server": [
	  {
      "Path": "/var/www/wiki/",
      "Prefix": "/",
      "Default": "index",
      "ServerType": "markdown",
      "Restricted": []
    }
  ]
}`

	filepath := path.Join(os.TempDir(), "simpleini.txt")
	f, err := os.Create(filepath)
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(filepath)
	if _, err := f.WriteString(defaultConfig); err != nil {
		t.Fatal(err)
	}
	if err := f.Close(); err != nil {
		t.Fatal(err)
	}

	success := LoadConfig(filepath)

	assert.True(t, success, "Default configuration should load without error.")

	config := GetConfig()

	//assert.Nil(t, config, "Config file could not be accessed")

	assert.Equal(t, config.Global.Port, "8080", "read Port value incorrectly")
	assert.Equal(t, config.Global.Hostname, "localhost", "read Hostname value incorrectly")

	assert.Equal(t, config.Server[0].Path, "/var/www/wiki/", "read Path value incorrectly")
	assert.Equal(t, config.Server[0].Prefix, "/", "read Prefix value incorrectly")
	assert.Equal(t, config.Server[0].Default, "index", "read Default page value incorrectly")
	assert.Equal(t, config.Server[0].ServerType, "markdown", "read ServerType value incorrectly")

	assert.Equal(t, len(config.Server[0].Restricted), 0, "incorrect number of restricted elements") // putting this comment here so sublime stops freaking out about a line with one character
}

func TestGetConfig(t *testing.T) {
	// directly put a config in the spot
	staticConfig = &Config{
		Global: GlobalSection{
			Port:        "8080",
			Hostname:    "localhost",
			TemplateDir: "/templates/",
		},
		Redirects: []RedirectSection{
			RedirectSection{
				Requested: "source",
				Target:    "dest",
				Code:      302,
			},
		},
		Server: []ServerSection{
			ServerSection{
				ServerType: "markdown",
				Prefix:     "/",
				Path:       "/var/www/",
				Default:    "readme",
				Template:   "wiki.html",
				Restricted: []string{},
			},
		},
		Indexes: []IndexSection{
			IndexSection{
				WatchDirs: map[string]string{
					"/var/www/": "/",
				},
				WatchExtension: ".md",
				IndexPath:      "/index/",
				IndexType:      "en",
				IndexName:      "wiki",
				Restricted:     []string{},
			},
		},
	}

	configLock.Lock()

	var config *Config

	go func() {
		config = GetConfig()
	}()

	assert.Nil(t, config, "Config should current be blocked and shoult not have loaded.")
	configLock.Unlock()
	time.Sleep(10)
	assert.NotNil(t, config, "Config should have loaded - is no longer blocked.")
}

func TestRenderTemplate(t *testing.T) {
	var tests = []struct {
		input    string
		template string
		expected string
	}{
		{"abc", "debug.raw", "abc"},
		{"other stuff", "debug.raw", "other stuff"},
	}

	var err error
	allTemplates, err = template.ParseGlob("./templates/*")
	if err != nil {
		t.Errorf("failed to parse templates - %s", err)
	}

	for _, testSet := range tests {
		templateLock.Lock()

		actualContent := httptest.NewRecorder()

		if allTemplates.Lookup(testSet.template) == nil {
			t.Errorf("did not find template [%q] that is needed", testSet.template)
		}

		go func() {
			err = RenderTemplate(actualContent, testSet.template, testSet.input)
		}()

		if actualContent.Body.String() != "" {
			t.Errorf("response buffer should currently be empty, but it contains [%q]",
				actualContent.Body.String())
		} else {
			templateLock.Unlock()
			time.Sleep(10)

			if string(actualContent.Body.String()) != testSet.expected {
				t.Errorf("\nexpected [%q]\ngot      [%q]", testSet.expected,
					actualContent.Body.String())
			}
		}
	}
}

func TestParseTemplates(t *testing.T) {
	ParseTemplates(GlobalSection{TemplateDir: "./templates/*"})

	files, err := filepath.Glob("./templates/*")
	if err != nil {
		t.Error(err)
	}
	if len(files) != len(allTemplates.Templates()) {
		t.Error("There are unparsed templates in the direcory")
	}

	for _, templateName := range files {
		if allTemplates.Lookup(strings.TrimPrefix(templateName, "templates/")) == nil {
			t.Errorf("Could not find template %s", templateName)
		}
	}
}

func TestBadParseTemplates(t *testing.T) {
	err := ParseTemplates(GlobalSection{TemplateDir: "./notadir/*"})
	expectedError := errors.New("html/template: pattern matches no files: `./notadir/**`")
	assert.Equal(t, err, expectedError, "got the wrong error response")
}
<commit_msg>fixed tests within config_test.go<commit_after>package gnosis

import (
	"errors"
	"github.com/stretchr/testify/assert"
	"os"
	"path"
	"path/filepath"
	"testing"
	"strings"
	"html/template"
	"net/http/httptest"
)

func TestSimpleConfig(t *testing.T) {

	defaultConfig := `{
  "Global": {
    "Port": "8080",
    "Hostname": "localhost"
  },
  "Server": [
	  {
      "Path": "/var/www/wiki/",
      "Prefix": "/",
      "Default": "index",
      "ServerType": "markdown",
      "Restricted": []
    }
  ]
}`

	filepath := path.Join(os.TempDir(), "simpleini.txt")
	f, err := os.Create(filepath)
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(filepath)
	if _, err := f.WriteString(defaultConfig); err != nil {
		t.Fatal(err)
	}
	if err := f.Close(); err != nil {
		t.Fatal(err)
	}

	success := LoadConfig(filepath)

	assert.True(t, success, "Default configuration should load without error.")

	config := GetConfig()

	//assert.Nil(t, config, "Config file could not be accessed")

	assert.Equal(t, config.Global.Port, "8080", "read Port value incorrectly")
	assert.Equal(t, config.Global.Hostname, "localhost", "read Hostname value incorrectly")

	assert.Equal(t, config.Server[0].Path, "/var/www/wiki/", "read Path value incorrectly")
	assert.Equal(t, config.Server[0].Prefix, "/", "read Prefix value incorrectly")
	assert.Equal(t, config.Server[0].Default, "index", "read Default page value incorrectly")
	assert.Equal(t, config.Server[0].ServerType, "markdown", "read ServerType value incorrectly")

	assert.Equal(t, len(config.Server[0].Restricted), 0, "incorrect number of restricted elements") // putting this comment here so sublime stops freaking out about a line with one character
}

func TestGetConfig(t *testing.T) {
	// directly put a config in the spot
	staticConfig = &Config{
		Global: GlobalSection{
			Port:        "8080",
			Hostname:    "localhost",
			TemplateDir: "/templates/",
		},
		Redirects: []RedirectSection{
			RedirectSection{
				Requested: "source",
				Target:    "dest",
				Code:      302,
			},
		},
		Server: []ServerSection{
			ServerSection{
				ServerType: "markdown",
				Prefix:     "/",
				Path:       "/var/www/",
				Default:    "readme",
				Template:   "wiki.html",
				Restricted: []string{},
			},
		},
		Indexes: []IndexSection{
			IndexSection{
				WatchDirs: map[string]string{
					"/var/www/": "/",
				},
				WatchExtension: ".md",
				IndexPath:      "/index/",
				IndexType:      "en",
				IndexName:      "wiki",
				Restricted:     []string{},
			},
		},
	}

	configLock.Lock()

	var config *Config

	ch := make(chan *Config)

	go func() {
		ch <- GetConfig()
	}()

	select {
		case config = <-ch:
		default:
	}

	assert.Nil(t, config, "Config should current be blocked and shoult not have loaded.")
	configLock.Unlock()
	select {
		case config = <-ch:
	}
	assert.NotNil(t, config, "Config should have loaded - is no longer blocked.")
}

func TestRenderTemplate(t *testing.T) {
	var tests = []struct {
		input    string
		template string
		expected string
	}{
		{"abc", "debug.raw", "abc"},
		{"other stuff", "debug.raw", "other stuff"},
	}

	var err error
	allTemplates, err = template.ParseGlob("./templates/*")
	if err != nil {
		t.Errorf("failed to parse templates - %s", err)
	}

	for _, testSet := range tests {
		templateLock.Lock()

		actualContent := httptest.NewRecorder()

		if allTemplates.Lookup(testSet.template) == nil {
			t.Errorf("did not find template [%q] that is needed", testSet.template)
		}

		ch := make(chan string)

		go func() {
			err = RenderTemplate(actualContent, testSet.template, testSet.input)
			ch <- actualContent.Body.String()
		}()

		var testResponse string

		select {
			case testResponse = <- ch:
			default:
		}

		assert.Empty(t, testResponse, "expecte empty testResponse, has [%q]", testResponse)

			templateLock.Unlock()
		select {
			case testResponse = <- ch:
		}

		assert.Equal(t, testSet.expected, testResponse,
			"expecte empty testResponse, has [%q]", testResponse)

	}
}

func TestParseTemplates(t *testing.T) {
	ParseTemplates(GlobalSection{TemplateDir: "./templates/*"})

	files, err := filepath.Glob("./templates/*")
	if err != nil {
		t.Error(err)
	}
	if len(files) != len(allTemplates.Templates()) {
		t.Error("There are unparsed templates in the direcory")
	}

	for _, templateName := range files {
		if allTemplates.Lookup(strings.TrimPrefix(templateName, "templates/")) == nil {
			t.Errorf("Could not find template %s", templateName)
		}
	}
}

func TestBadParseTemplates(t *testing.T) {
	err := ParseTemplates(GlobalSection{TemplateDir: "./notadir/*"})
	expectedError := errors.New("html/template: pattern matches no files: `./notadir/**`")
	assert.Equal(t, err, expectedError, "got the wrong error response")
}
<|endoftext|>