<commit_before>// Copyright 2013 Patrice FERLET
// Ue of this source code is governed by MIT-style
// license that can be found in the LICENSE file
package verbalexpressions

import "testing"
import "strings"

func TestChaining(t *testing.T) {

	exp := "http://www.google.com"
	v := New().StartOfLine().
		Then("http").
		Maybe("s").
		Then("://").
		Maybe("www.").
		Word().
		Then(".").
		Word().
		Maybe("/").
		EndOfLine()
	if !v.Test(exp) {
		t.Errorf("%v regexp doesn't match %s", v.Regex(), exp)
	}
}

func TestRange(t *testing.T) {

	exp := "abcdef 123"

	v := New().Range("a", "z", 0, 9)
	if v.Regex().String() != "(?m)[a-z0-9]" {
		t.Errorf("%s is not (?m)[a-z0-9]", v.Regex())
	}
	if !v.Test(exp) {
		t.Errorf("%v regexp doesn't match %s", v.Regex(), exp)
	}
	exp = "ABCDEF"
	if v.Test(exp) {
		t.Errorf("%v regexp should not match %s", v.Regex(), exp)
	}

}

func TestPanicOnRangeOddParams(t *testing.T) {

	defer func() {
		// if no panic... the test fails
		if r := recover(); r == nil {
			t.Errorf("Call must panic !")
		}
	}()

	New().Range("a", "z", 0, 9, 10)
}

func TestOneLine(t *testing.T) {
	s := "atlanta\narkansas\nalabama\narachnophobia"

	v := New().SearchOneLine(true).Find("a").EndOfLine().Regex()
	res := v.FindAllStringIndex(s, -1)
	if len(res) != 1 {
		t.Errorf("%v should be length 1, %d instead", res, len(res))
	}
	if len(res[0]) != 2 {
		t.Errorf("%v should be length 2, %d instead", res[0], len(res[0]))
	}

	v = New().SearchOneLine(false).Find("a").EndOfLine().Regex()
	res = v.FindAllStringIndex(s, -1)
	if len(res) != 3 {
		t.Errorf("%v should be length 1, %d instead", res, len(res))
	}
	for _, r := range res {
		if len(r) != 2 {
			t.Errorf("%v should be length 2, %d instead", r, len(r))
		}
	}
}

func TestExcepting(t *testing.T) {

	s := "This is a simple test"
	v := New().AnythingBut("im").Regex().FindAllString(s, -1)
	for _, st := range v {
		if strings.Contains(st, "i") {
			t.Errorf("%s should not find \"i\"", st)
		}
		if strings.Contains(st, "m") {
			t.Errorf("%s should not find \"m\"", st)
		}
	}
}

func TestAny(t *testing.T) {

	s := "foo1 foo5 foobar"
	v := New().Find("foo").Any("1234567890")
	res := v.Regex().FindAllString(s, -1)
	if len(res) != 2 {
		t.Errorf("len(res) : %d isn't 2", len(res))
	}

}

func TestReplace(t *testing.T) {

	s := "foomode barmode themodebaz"
	expect := "foochanged barchanged thechangedbaz"

	v := New().Find("mode")
	res := v.Replace(s, "changed")

	if res != expect {
		t.Errorf("Replacement hasn't worked as expected %s != %s", res, expect)
	}

}
<commit_msg>Mistake for log error<commit_after>// Copyright 2013 Patrice FERLET
// Ue of this source code is governed by MIT-style
// license that can be found in the LICENSE file
package verbalexpressions

import "testing"
import "strings"

func TestChaining(t *testing.T) {

	exp := "http://www.google.com"
	v := New().StartOfLine().
		Then("http").
		Maybe("s").
		Then("://").
		Maybe("www.").
		Word().
		Then(".").
		Word().
		Maybe("/").
		EndOfLine()
	if !v.Test(exp) {
		t.Errorf("%v regexp doesn't match %s", v.Regex(), exp)
	}
}

func TestRange(t *testing.T) {

	exp := "abcdef 123"

	v := New().Range("a", "z", 0, 9)
	if v.Regex().String() != "(?m)[a-z0-9]" {
		t.Errorf("%s is not (?m)[a-z0-9]", v.Regex())
	}
	if !v.Test(exp) {
		t.Errorf("%v regexp doesn't match %s", v.Regex(), exp)
	}
	exp = "ABCDEF"
	if v.Test(exp) {
		t.Errorf("%v regexp should not match %s", v.Regex(), exp)
	}

}

func TestPanicOnRangeOddParams(t *testing.T) {

	defer func() {
		// if no panic... the test fails
		if r := recover(); r == nil {
			t.Errorf("Call must panic !")
		}
	}()

	New().Range("a", "z", 0, 9, 10)
}

func TestOneLine(t *testing.T) {
	s := "atlanta\narkansas\nalabama\narachnophobia"

	v := New().SearchOneLine(true).Find("a").EndOfLine().Regex()
	res := v.FindAllStringIndex(s, -1)
	if len(res) != 1 {
		t.Errorf("%v should be length 1, %d instead", res, len(res))
	}
	if len(res[0]) != 2 {
		t.Errorf("%v should be length 2, %d instead", res[0], len(res[0]))
	}

	v = New().SearchOneLine(false).Find("a").EndOfLine().Regex()
	res = v.FindAllStringIndex(s, -1)
	if len(res) != 3 {
		t.Errorf("%v should be length 3, %d instead", res, len(res))
	}
	for _, r := range res {
		if len(r) != 2 {
			t.Errorf("%v should be length 2, %d instead", r, len(r))
		}
	}
}

func TestExcepting(t *testing.T) {

	s := "This is a simple test"
	v := New().AnythingBut("im").Regex().FindAllString(s, -1)
	for _, st := range v {
		if strings.Contains(st, "i") {
			t.Errorf("%s should not find \"i\"", st)
		}
		if strings.Contains(st, "m") {
			t.Errorf("%s should not find \"m\"", st)
		}
	}
}

func TestAny(t *testing.T) {

	s := "foo1 foo5 foobar"
	v := New().Find("foo").Any("1234567890")
	res := v.Regex().FindAllString(s, -1)
	if len(res) != 2 {
		t.Errorf("len(res) : %d isn't 2", len(res))
	}

}

func TestReplace(t *testing.T) {

	s := "foomode barmode themodebaz"
	expect := "foochanged barchanged thechangedbaz"

	v := New().Find("mode")
	res := v.Replace(s, "changed")

	if res != expect {
		t.Errorf("Replacement hasn't worked as expected %s != %s", res, expect)
	}

}
<|endoftext|>


<commit_before>package jsref

import (
	"net/url"
	"reflect"

	"github.com/lestrrat/go-jspointer"
	"github.com/lestrrat/go-pdebug"
	"github.com/lestrrat/go-structinfo"
	"github.com/pkg/errors"
)

const ref = "$ref"
var refrv = reflect.ValueOf(ref)

type Option interface {
	Name() string
	Value() interface{}
}

type option struct {
	name  string
	value interface{}
}

func (o option) Name() string       { return o.name }
func (o option) Value() interface{} { return o.value }

// WithRecursiveResolution allows ou to enable recursive resolution
// on the *result* data structure. This means that after resolving
// the JSON reference in the structure at hand, it does another
// pass at resolving the entire data structure. Depending on your
// structure and size, this may incur significant cost.
//
// Please note that recursive resolution of the result is still
// experimental. If you find problems, please submit a pull request
// with a failing test case.
func WithRecursiveResolution(b bool) Option {
	return &option{
		name:  "recursiveResolution",
		value: b,
	}
}

var DefaultMaxRecursions = 10

// New creates a new Resolver
func New() *Resolver {
	return &Resolver{MaxRecursions: DefaultMaxRecursions}
}

// AddProvider adds a new Provider to be searched for in case
// a JSON pointer with more than just the URI fragment is given.
func (r *Resolver) AddProvider(p Provider) error {
	r.providers = append(r.providers, p)
	return nil
}

type resolveCtx struct {
	rlevel    int         // recurse level
	maxrlevel int         // max recurse level
	object    interface{} // the main object that was passed to `Resolve()`
}

// Resolve takes a target `v`, and a JSON pointer `spec`.
// spec is expected to be in the form of
//
//    [scheme://[userinfo@]host/path[?query]]#fragment
//    [scheme:opaque[?query]]#fragment
//
// where everything except for `#fragment` is optional.
// If the fragment is empty, an error is returned.
//
// If `spec` is the empty string, `v` is returned
// This method handles recursive JSON references.
//
// If `WithRecursiveResolution` option is given and its value is true,
// an attempt to resolve all references within the resulting object
// is made by traversing the structure recursively. Default is false
func (r *Resolver) Resolve(v interface{}, ptr string, options ...Option) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("Resolver.Resolve(%s)", ptr).BindError(&err)
		defer g.End()
	}
	var recursiveResolution bool
	for _, opt := range options {
		switch opt.Name() {
		case "recursiveResolution":
			recursiveResolution = opt.Value().(bool)
		}
	}

	ctx := resolveCtx{
		rlevel:    0,
		maxrlevel: r.MaxRecursions,
		object:    v,
	}

	// First, expand the target as much as we can
	v, err = expandRefRecursive(&ctx, r, v)
	if err != nil {
		return nil, errors.Wrap(err, "recursive search failed")
	}

	result, err := evalptr(&ctx, r, v, ptr)
	if err != nil {
		return nil, err
	}

	if recursiveResolution {
		rv, err := traverseExpandRefRecursive(&ctx, r, reflect.ValueOf(result))
		if err != nil {
			return nil, errors.Wrap(err, `failed to resolve result`)
		}
		result = rv.Interface()
	}

	return result, nil
}

func setPtrOrInterface(container, value reflect.Value) bool {
	switch container.Kind() {
	case reflect.Ptr:
		if !value.CanAddr() {
			return false
		}
		container.Set(value.Addr())
	case reflect.Interface:
		container.Set(value)
	default:
		return false
	}
	return true
}

func traverseExpandRefRecursive(ctx *resolveCtx, r *Resolver, rv reflect.Value) (reflect.Value, error) {
	if pdebug.Enabled {
		g := pdebug.Marker("traverseExpandRefRecursive")
		defer g.End()
	}

	switch rv.Kind() {
	case reflect.Ptr, reflect.Interface:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Array, reflect.Slice:
		for i := 0; i < rv.Len(); i++ {
			elem := rv.Index(i)
			var elemcontainer reflect.Value
			switch elem.Kind() {
			case reflect.Ptr, reflect.Interface:
				elemcontainer = elem
				elem = elem.Elem()
			}

			if elemcontainer.IsValid() {
				if !elemcontainer.CanSet() {
					continue
				}
			}
			newv, err := expandRefRecursive(ctx, r, elem.Interface())
			if err != nil {
				return zeroval, errors.Wrap(err, `failed to expand array/slice element`)
			}
			newrv, err := traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
			if err != nil {
				return zeroval, errors.Wrap(err, `failed to recurse into array/slice element`)
			}

			if elemcontainer.IsValid() {
				setPtrOrInterface(elemcontainer, newrv)
			} else {
				elem.Set(newrv)
			}
		}
	case reflect.Map:
		// No refs found in the map keys, but there could be more
		// in the values
		if _, err := findRef(rv.Interface()); err != nil {
			for _, key := range rv.MapKeys() {
				value, err := traverseExpandRefRecursive(ctx, r, rv.MapIndex(key))
				if err != nil {
					return zeroval, errors.Wrap(err, `failed to traverse map value`)
				}
				rv.SetMapIndex(key, value)
			}
			return rv, nil
		}
		newv, err := expandRefRecursive(ctx, r, rv.Interface())
		if err != nil {
			return zeroval, errors.Wrap(err, `failed to expand map element`)
		}
		return traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
	case reflect.Struct:
		// No refs found in the map keys, but there could be more
		// in the values
		if _, err := findRef(rv.Interface()); err != nil {
			for i := 0; i < rv.NumField(); i++ {
				field := rv.Field(i)
				value, err := traverseExpandRefRecursive(ctx, r, field)
				if err != nil {
					return zeroval, errors.Wrap(err, `failed to traverse struct field value`)
				}
				field.Set(value)
			}
			return rv, nil
		}
		newv, err := expandRefRecursive(ctx, r, rv.Interface())
		if err != nil {
			return zeroval, errors.Wrap(err, `failed to expand struct element`)
		}
		return traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
	}
	return rv, nil
}

// expands $ref with in v, until all $refs are expanded.
// note: DOES NOT recurse down into structures
func expandRefRecursive(ctx *resolveCtx, r *Resolver, v interface{}) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("expandRefRecursive")
		defer g.End()
	}
	for {
		ref, err := findRef(v)
		if err != nil {
			if pdebug.Enabled {
				pdebug.Printf("No refs found. bailing out of loop")
			}
			break
		}

		if pdebug.Enabled {
			pdebug.Printf("Found ref '%s'", ref)
		}

		newv, err := expandRef(ctx, r, v, ref)
		if err != nil {
			if pdebug.Enabled {
				pdebug.Printf("Failed to expand ref '%s': %s", ref, err)
			}
			return nil, errors.Wrap(err, "failed to expand ref")
		}

		v = newv
	}

	return v, nil
}

func expandRef(ctx *resolveCtx, r *Resolver, v interface{}, ref string) (ret interface{}, err error) {
	ctx.rlevel++
	if ctx.rlevel > ctx.maxrlevel {
		return nil, ErrMaxRecursion
	}

	defer func() { ctx.rlevel-- }()

	u, err := url.Parse(ref)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse ref as URL")
	}

	ptr := "#" + u.Fragment
	if u.Host == "" && u.Path == "" {
		if pdebug.Enabled {
			pdebug.Printf("ptr doesn't contain any host/path part, apply json pointer directly to object")
		}
		return evalptr(ctx, r, ctx.object, ptr)
	}

	u.Fragment = ""
	for _, p := range r.providers {
		pv, err := p.Get(u)
		if err == nil {
			if pdebug.Enabled {
				pdebug.Printf("Found object matching %s", u)
			}

			return evalptr(ctx, r, pv, ptr)
		}
	}

	return nil, errors.New("element pointed by $ref '" + ref + "' not found")
}

func findRef(v interface{}) (ref string, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("findRef").BindError(&err)
		defer g.End()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Interface, reflect.Ptr:
		rv = rv.Elem()
	}

	if pdebug.Enabled {
		pdebug.Printf("object is a '%s'", rv.Kind())
	}

	// Find if we have a "$ref" element
	var refv reflect.Value
	switch rv.Kind() {
	case reflect.Map:
		refv = rv.MapIndex(refrv)
	case reflect.Struct:
		if fn := structinfo.StructFieldFromJSONName(rv, ref); fn != "" {
			refv = rv.FieldByName(fn)
		}
	default:
		return "", errors.New("element is not a map-like container")
	}

	if !refv.IsValid() {
		return "", errors.New("$ref element not found")
	}

	switch refv.Kind() {
	case reflect.Interface, reflect.Ptr:
		refv = refv.Elem()
	}

	switch refv.Kind() {
	case reflect.String:
		// Empty string isn't a valid pointer
		if refv.Len() <= 0 {
			return "", errors.New("$ref element not found (empty)")
		}
		if pdebug.Enabled {
			pdebug.Printf("Found ref '%s'", refv)
		}
		return refv.String(), nil
	case reflect.Invalid:
		return "", errors.New("$ref element not found")
	default:
		if pdebug.Enabled {
			pdebug.Printf("'$ref' was found, but its kind is %s", refv.Kind())
		}
	}

	return "", errors.New("$ref element must be a string")
}

func evalptr(ctx *resolveCtx, r *Resolver, v interface{}, ptrspec string) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("evalptr(%s)", ptrspec).BindError(&err)
		defer g.End()
	}

	// If the reference is empty, return v
	if ptrspec == "" || ptrspec == "#" {
		if pdebug.Enabled {
			pdebug.Printf("Empty pointer, return v itself")
		}
		return v, nil
	}

	// Parse the spec.
	u, err := url.Parse(ptrspec)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse reference spec")
	}

	ptr := u.Fragment

	// We are evaluating the pointer part. That means if the
	// Fragment portion is not set, there's no point in evaluating
	if ptr == "" {
		return nil, errors.Wrap(err, "empty json pointer")
	}

	p, err := jspointer.New(ptr)
	if err != nil {
		return nil, errors.Wrap(err, "failed create a new JSON pointer")
	}
	x, err := p.Get(v)
	if err != nil {
		return nil, errors.Wrap(err, "failed to fetch value")
	}

	if pdebug.Enabled {
		pdebug.Printf("Evaulated JSON pointer, now checking if we can expand further")
	}
	// If this result contains more refs, expand that
	return expandRefRecursive(ctx, r, x)
}
<commit_msg>Pass on further processing if the value is not valid<commit_after>package jsref

import (
	"net/url"
	"reflect"

	"github.com/lestrrat/go-jspointer"
	"github.com/lestrrat/go-pdebug"
	"github.com/lestrrat/go-structinfo"
	"github.com/pkg/errors"
)

const ref = "$ref"
var refrv = reflect.ValueOf(ref)

type Option interface {
	Name() string
	Value() interface{}
}

type option struct {
	name  string
	value interface{}
}

func (o option) Name() string       { return o.name }
func (o option) Value() interface{} { return o.value }

// WithRecursiveResolution allows ou to enable recursive resolution
// on the *result* data structure. This means that after resolving
// the JSON reference in the structure at hand, it does another
// pass at resolving the entire data structure. Depending on your
// structure and size, this may incur significant cost.
//
// Please note that recursive resolution of the result is still
// experimental. If you find problems, please submit a pull request
// with a failing test case.
func WithRecursiveResolution(b bool) Option {
	return &option{
		name:  "recursiveResolution",
		value: b,
	}
}

var DefaultMaxRecursions = 10

// New creates a new Resolver
func New() *Resolver {
	return &Resolver{MaxRecursions: DefaultMaxRecursions}
}

// AddProvider adds a new Provider to be searched for in case
// a JSON pointer with more than just the URI fragment is given.
func (r *Resolver) AddProvider(p Provider) error {
	r.providers = append(r.providers, p)
	return nil
}

type resolveCtx struct {
	rlevel    int         // recurse level
	maxrlevel int         // max recurse level
	object    interface{} // the main object that was passed to `Resolve()`
}

// Resolve takes a target `v`, and a JSON pointer `spec`.
// spec is expected to be in the form of
//
//    [scheme://[userinfo@]host/path[?query]]#fragment
//    [scheme:opaque[?query]]#fragment
//
// where everything except for `#fragment` is optional.
// If the fragment is empty, an error is returned.
//
// If `spec` is the empty string, `v` is returned
// This method handles recursive JSON references.
//
// If `WithRecursiveResolution` option is given and its value is true,
// an attempt to resolve all references within the resulting object
// is made by traversing the structure recursively. Default is false
func (r *Resolver) Resolve(v interface{}, ptr string, options ...Option) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("Resolver.Resolve(%s)", ptr).BindError(&err)
		defer g.End()
	}
	var recursiveResolution bool
	for _, opt := range options {
		switch opt.Name() {
		case "recursiveResolution":
			recursiveResolution = opt.Value().(bool)
		}
	}

	ctx := resolveCtx{
		rlevel:    0,
		maxrlevel: r.MaxRecursions,
		object:    v,
	}

	// First, expand the target as much as we can
	v, err = expandRefRecursive(&ctx, r, v)
	if err != nil {
		return nil, errors.Wrap(err, "recursive search failed")
	}

	result, err := evalptr(&ctx, r, v, ptr)
	if err != nil {
		return nil, err
	}

	if recursiveResolution {
		rv, err := traverseExpandRefRecursive(&ctx, r, reflect.ValueOf(result))
		if err != nil {
			return nil, errors.Wrap(err, `failed to resolve result`)
		}
		result = rv.Interface()
	}

	return result, nil
}

func setPtrOrInterface(container, value reflect.Value) bool {
	switch container.Kind() {
	case reflect.Ptr:
		if !value.CanAddr() {
			return false
		}
		container.Set(value.Addr())
	case reflect.Interface:
		container.Set(value)
	default:
		return false
	}
	return true
}

func traverseExpandRefRecursive(ctx *resolveCtx, r *Resolver, rv reflect.Value) (reflect.Value, error) {
	if pdebug.Enabled {
		g := pdebug.Marker("traverseExpandRefRecursive")
		defer g.End()
	}

	switch rv.Kind() {
	case reflect.Ptr, reflect.Interface:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Array, reflect.Slice:
		for i := 0; i < rv.Len(); i++ {
			elem := rv.Index(i)
			var elemcontainer reflect.Value
			switch elem.Kind() {
			case reflect.Ptr, reflect.Interface:
				elemcontainer = elem
				elem = elem.Elem()
			}

			// Need to check for elem being Valid, otherwise the
			// subsequent call to Interface() will fail
			if !elem.IsValid() {
				continue
			}

			if elemcontainer.IsValid() {
				if !elemcontainer.CanSet() {
					continue
				}
			}
			newv, err := expandRefRecursive(ctx, r, elem.Interface())
			if err != nil {
				return zeroval, errors.Wrap(err, `failed to expand array/slice element`)
			}
			newrv, err := traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
			if err != nil {
				return zeroval, errors.Wrap(err, `failed to recurse into array/slice element`)
			}

			if elemcontainer.IsValid() {
				setPtrOrInterface(elemcontainer, newrv)
			} else {
				elem.Set(newrv)
			}
		}
	case reflect.Map:
		// No refs found in the map keys, but there could be more
		// in the values
		if _, err := findRef(rv.Interface()); err != nil {
			for _, key := range rv.MapKeys() {
				value, err := traverseExpandRefRecursive(ctx, r, rv.MapIndex(key))
				if err != nil {
					return zeroval, errors.Wrap(err, `failed to traverse map value`)
				}
				rv.SetMapIndex(key, value)
			}
			return rv, nil
		}
		newv, err := expandRefRecursive(ctx, r, rv.Interface())
		if err != nil {
			return zeroval, errors.Wrap(err, `failed to expand map element`)
		}
		return traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
	case reflect.Struct:
		// No refs found in the map keys, but there could be more
		// in the values
		if _, err := findRef(rv.Interface()); err != nil {
			for i := 0; i < rv.NumField(); i++ {
				field := rv.Field(i)
				value, err := traverseExpandRefRecursive(ctx, r, field)
				if err != nil {
					return zeroval, errors.Wrap(err, `failed to traverse struct field value`)
				}
				field.Set(value)
			}
			return rv, nil
		}
		newv, err := expandRefRecursive(ctx, r, rv.Interface())
		if err != nil {
			return zeroval, errors.Wrap(err, `failed to expand struct element`)
		}
		return traverseExpandRefRecursive(ctx, r, reflect.ValueOf(newv))
	}
	return rv, nil
}

// expands $ref with in v, until all $refs are expanded.
// note: DOES NOT recurse down into structures
func expandRefRecursive(ctx *resolveCtx, r *Resolver, v interface{}) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("expandRefRecursive")
		defer g.End()
	}
	for {
		ref, err := findRef(v)
		if err != nil {
			if pdebug.Enabled {
				pdebug.Printf("No refs found. bailing out of loop")
			}
			break
		}

		if pdebug.Enabled {
			pdebug.Printf("Found ref '%s'", ref)
		}

		newv, err := expandRef(ctx, r, v, ref)
		if err != nil {
			if pdebug.Enabled {
				pdebug.Printf("Failed to expand ref '%s': %s", ref, err)
			}
			return nil, errors.Wrap(err, "failed to expand ref")
		}

		v = newv
	}

	return v, nil
}

func expandRef(ctx *resolveCtx, r *Resolver, v interface{}, ref string) (ret interface{}, err error) {
	ctx.rlevel++
	if ctx.rlevel > ctx.maxrlevel {
		return nil, ErrMaxRecursion
	}

	defer func() { ctx.rlevel-- }()

	u, err := url.Parse(ref)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse ref as URL")
	}

	ptr := "#" + u.Fragment
	if u.Host == "" && u.Path == "" {
		if pdebug.Enabled {
			pdebug.Printf("ptr doesn't contain any host/path part, apply json pointer directly to object")
		}
		return evalptr(ctx, r, ctx.object, ptr)
	}

	u.Fragment = ""
	for _, p := range r.providers {
		pv, err := p.Get(u)
		if err == nil {
			if pdebug.Enabled {
				pdebug.Printf("Found object matching %s", u)
			}

			return evalptr(ctx, r, pv, ptr)
		}
	}

	return nil, errors.New("element pointed by $ref '" + ref + "' not found")
}

func findRef(v interface{}) (ref string, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("findRef").BindError(&err)
		defer g.End()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Interface, reflect.Ptr:
		rv = rv.Elem()
	}

	if pdebug.Enabled {
		pdebug.Printf("object is a '%s'", rv.Kind())
	}

	// Find if we have a "$ref" element
	var refv reflect.Value
	switch rv.Kind() {
	case reflect.Map:
		refv = rv.MapIndex(refrv)
	case reflect.Struct:
		if fn := structinfo.StructFieldFromJSONName(rv, ref); fn != "" {
			refv = rv.FieldByName(fn)
		}
	default:
		return "", errors.New("element is not a map-like container")
	}

	if !refv.IsValid() {
		return "", errors.New("$ref element not found")
	}

	switch refv.Kind() {
	case reflect.Interface, reflect.Ptr:
		refv = refv.Elem()
	}

	switch refv.Kind() {
	case reflect.String:
		// Empty string isn't a valid pointer
		if refv.Len() <= 0 {
			return "", errors.New("$ref element not found (empty)")
		}
		if pdebug.Enabled {
			pdebug.Printf("Found ref '%s'", refv)
		}
		return refv.String(), nil
	case reflect.Invalid:
		return "", errors.New("$ref element not found")
	default:
		if pdebug.Enabled {
			pdebug.Printf("'$ref' was found, but its kind is %s", refv.Kind())
		}
	}

	return "", errors.New("$ref element must be a string")
}

func evalptr(ctx *resolveCtx, r *Resolver, v interface{}, ptrspec string) (ret interface{}, err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("evalptr(%s)", ptrspec).BindError(&err)
		defer g.End()
	}

	// If the reference is empty, return v
	if ptrspec == "" || ptrspec == "#" {
		if pdebug.Enabled {
			pdebug.Printf("Empty pointer, return v itself")
		}
		return v, nil
	}

	// Parse the spec.
	u, err := url.Parse(ptrspec)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse reference spec")
	}

	ptr := u.Fragment

	// We are evaluating the pointer part. That means if the
	// Fragment portion is not set, there's no point in evaluating
	if ptr == "" {
		return nil, errors.Wrap(err, "empty json pointer")
	}

	p, err := jspointer.New(ptr)
	if err != nil {
		return nil, errors.Wrap(err, "failed create a new JSON pointer")
	}
	x, err := p.Get(v)
	if err != nil {
		return nil, errors.Wrap(err, "failed to fetch value")
	}

	if pdebug.Enabled {
		pdebug.Printf("Evaulated JSON pointer, now checking if we can expand further")
	}
	// If this result contains more refs, expand that
	return expandRefRecursive(ctx, r, x)
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

import (
	"fmt"
	"regexp"
	"strings"

	keybase1 "github.com/keybase/client/go/protocol"
	jsonw "github.com/keybase/go-jsonw"
)

//=============================================================================
// Web
//

type WebChecker struct {
	proof RemoteProofChainLink
}

var webKeybaseFiles = []string{".well-known/keybase.txt", "keybase.txt"}

func NewWebChecker(p RemoteProofChainLink) (*WebChecker, ProofError) {
	return &WebChecker{p}, nil
}

func (rc *WebChecker) GetTorError() ProofError {
	urlBase := rc.proof.ToDisplayString()
	if !strings.HasPrefix(urlBase, "https:") {
		return ProofErrorHTTPOverTor
	}
	return nil
}

func (rc *WebChecker) CheckHint(h SigHint) ProofError {

	files := webKeybaseFiles
	urlBase := rc.proof.ToDisplayString()
	theirURL := strings.ToLower(h.apiURL)

	for _, file := range files {
		ourURL := urlBase + "/" + file
		if ourURL == theirURL {
			return nil
		}
	}

	return NewProofError(keybase1.ProofStatus_BAD_API_URL,
		"Bad hint from server; didn't recognize API url: %s",
		h.apiURL)

}

func (rc *WebChecker) CheckStatus(h SigHint) ProofError {
	res, err := G.XAPI.GetText(APIArg{
		Endpoint:    h.apiURL,
		NeedSession: false,
	})

	if err != nil {
		return XapiError(err, h.apiURL)
	}

	var sigBody []byte
	sigBody, _, err = OpenSig(rc.proof.GetArmoredSig())
	var ret ProofError

	if err != nil {
		return NewProofError(keybase1.ProofStatus_BAD_SIGNATURE,
			"Bad signature: %s", err)
	}

	if !FindBase64Block(res.Body, sigBody, false) {
		ret = NewProofError(keybase1.ProofStatus_TEXT_NOT_FOUND, "signature not found in body")
	}

	return ret
}

//
//=============================================================================

type WebServiceType struct{ BaseServiceType }

func (t WebServiceType) AllStringKeys() []string     { return []string{"web", "http", "https"} }
func (t WebServiceType) PrimaryStringKeys() []string { return []string{"https", "http"} }

func ParseWeb(s string) (hostname string, prot string, err error) {
	rxx := regexp.MustCompile("^(http(s?))://(.*)$")
	if v := rxx.FindStringSubmatch(s); v != nil {
		s = v[3]
		prot = v[1]
	}
	if !IsValidHostname(s) {
		err = InvalidHostnameError{s}
	} else {
		hostname = s
	}
	return
}

func (t WebServiceType) CheckUsername(s string) error {
	_, _, e := ParseWeb(s)
	return e
}

func (t WebServiceType) NormalizeUsername(s string) (ret string, err error) {
	var prot, host string
	if host, prot, err = ParseWeb(s); err != nil {
		return
	}
	var res *APIRes
	res, err = G.API.Get(APIArg{
		Endpoint:    "remotes/check",
		NeedSession: true,
		Args: HTTPArgs{
			"hostname": S{host},
		},
	})
	if err != nil {
		return
	}
	var found string
	found, err = res.Body.AtPath("results.first").GetString()
	if err != nil {
		err = WebUnreachableError{host}
		return
	}
	if len(prot) > 0 && prot == "https" && found != "https:" {
		msg := fmt.Sprintf("You specified HTTPS for %s but only HTTP is available", host)
		err = ProtocolDowngradeError{msg}
		return
	}
	ret = found + "//" + host

	return
}

func (t WebServiceType) ToChecker() Checker {
	return t.BaseToChecker(t, "a valid domain name")
}

func (t WebServiceType) GetPrompt() string {
	return "Web site to check"
}

func (t WebServiceType) ToServiceJSON(un string) *jsonw.Wrapper {
	h, p, _ := ParseWeb(un)
	ret := jsonw.NewDictionary()
	ret.SetKey("protocol", jsonw.NewString(p+":"))
	ret.SetKey("hostname", jsonw.NewString(h))
	return ret
}

func (t WebServiceType) MarkupFilenames(un string, mkp *Markup) {
	mkp.Append(`<ul>`)
	first := true
	for _, f := range webKeybaseFiles {
		var bullet string
		if first {
			bullet = "   "
			first = false
		} else {
			bullet = "OR "
		}
		mkp.Append(`<li bullet="` + bullet + `"><url>` + un + "/" + f + `</url></li>`)
	}
	mkp.Append(`</ul>`)
}

func (t WebServiceType) PreProofWarning(un string) *Markup {
	mkp := FmtMarkup(`<p>You will be asked to post a file to:</p>`)
	t.MarkupFilenames(un, mkp)
	return mkp
}

func (t WebServiceType) PostInstructions(un string) *Markup {
	mkp := FmtMarkup(`<p>Make the following file available at:</p>`)
	t.MarkupFilenames(un, mkp)
	return mkp
}

func (t WebServiceType) DisplayName(un string) string { return "Web" }
func (t WebServiceType) GetTypeName() string          { return "web" }

func (t WebServiceType) RecheckProofPosting(tryNumber int, status keybase1.ProofStatus, _ string) (warning *Markup, err error) {
	if status == keybase1.ProofStatus_PERMISSION_DENIED {
		warning = FmtMarkup("Permission denied! Make sure your proof page is public.")
	} else {
		warning, err = t.BaseRecheckProofPosting(tryNumber, status)
	}
	return
}
func (t WebServiceType) GetProofType() string { return "web_service_binding.generic" }

func (t WebServiceType) CheckProofText(text string, id keybase1.SigID, sig string) (err error) {
	return t.BaseCheckProofTextFull(text, id, sig)
}

func (t WebServiceType) GetAPIArgKey() string { return "remote_host" }
func (t WebServiceType) LastWriterWins() bool { return false }

//=============================================================================

func init() {
	RegisterServiceType(WebServiceType{})
	RegisterSocialNetwork("web")
	RegisterProofCheckHook("http",
		func(l RemoteProofChainLink) (ProofChecker, ProofError) {
			return NewWebChecker(l)
		})
}

//=============================================================================
<commit_msg>better, use parse<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package libkb

import (
	"fmt"
	"net/url"
	"regexp"
	"strings"

	keybase1 "github.com/keybase/client/go/protocol"
	jsonw "github.com/keybase/go-jsonw"
)

//=============================================================================
// Web
//

type WebChecker struct {
	proof RemoteProofChainLink
}

var webKeybaseFiles = []string{".well-known/keybase.txt", "keybase.txt"}

func NewWebChecker(p RemoteProofChainLink) (*WebChecker, ProofError) {
	return &WebChecker{p}, nil
}

func (rc *WebChecker) GetTorError() ProofError {
	urlBase := rc.proof.ToDisplayString()

	u, err := url.Parse(urlBase)
	if err != nil || u.Scheme != "https" {
		return ProofErrorHTTPOverTor
	}

	return nil
}

func (rc *WebChecker) CheckHint(h SigHint) ProofError {

	files := webKeybaseFiles
	urlBase := rc.proof.ToDisplayString()
	theirURL := strings.ToLower(h.apiURL)

	for _, file := range files {
		ourURL := urlBase + "/" + file
		if ourURL == theirURL {
			return nil
		}
	}

	return NewProofError(keybase1.ProofStatus_BAD_API_URL,
		"Bad hint from server; didn't recognize API url: %s",
		h.apiURL)

}

func (rc *WebChecker) CheckStatus(h SigHint) ProofError {
	res, err := G.XAPI.GetText(APIArg{
		Endpoint:    h.apiURL,
		NeedSession: false,
	})

	if err != nil {
		return XapiError(err, h.apiURL)
	}

	var sigBody []byte
	sigBody, _, err = OpenSig(rc.proof.GetArmoredSig())
	var ret ProofError

	if err != nil {
		return NewProofError(keybase1.ProofStatus_BAD_SIGNATURE,
			"Bad signature: %s", err)
	}

	if !FindBase64Block(res.Body, sigBody, false) {
		ret = NewProofError(keybase1.ProofStatus_TEXT_NOT_FOUND, "signature not found in body")
	}

	return ret
}

//
//=============================================================================

type WebServiceType struct{ BaseServiceType }

func (t WebServiceType) AllStringKeys() []string     { return []string{"web", "http", "https"} }
func (t WebServiceType) PrimaryStringKeys() []string { return []string{"https", "http"} }

func ParseWeb(s string) (hostname string, prot string, err error) {
	rxx := regexp.MustCompile("^(http(s?))://(.*)$")
	if v := rxx.FindStringSubmatch(s); v != nil {
		s = v[3]
		prot = v[1]
	}
	if !IsValidHostname(s) {
		err = InvalidHostnameError{s}
	} else {
		hostname = s
	}
	return
}

func (t WebServiceType) CheckUsername(s string) error {
	_, _, e := ParseWeb(s)
	return e
}

func (t WebServiceType) NormalizeUsername(s string) (ret string, err error) {
	var prot, host string
	if host, prot, err = ParseWeb(s); err != nil {
		return
	}
	var res *APIRes
	res, err = G.API.Get(APIArg{
		Endpoint:    "remotes/check",
		NeedSession: true,
		Args: HTTPArgs{
			"hostname": S{host},
		},
	})
	if err != nil {
		return
	}
	var found string
	found, err = res.Body.AtPath("results.first").GetString()
	if err != nil {
		err = WebUnreachableError{host}
		return
	}
	if len(prot) > 0 && prot == "https" && found != "https:" {
		msg := fmt.Sprintf("You specified HTTPS for %s but only HTTP is available", host)
		err = ProtocolDowngradeError{msg}
		return
	}
	ret = found + "//" + host

	return
}

func (t WebServiceType) ToChecker() Checker {
	return t.BaseToChecker(t, "a valid domain name")
}

func (t WebServiceType) GetPrompt() string {
	return "Web site to check"
}

func (t WebServiceType) ToServiceJSON(un string) *jsonw.Wrapper {
	h, p, _ := ParseWeb(un)
	ret := jsonw.NewDictionary()
	ret.SetKey("protocol", jsonw.NewString(p+":"))
	ret.SetKey("hostname", jsonw.NewString(h))
	return ret
}

func (t WebServiceType) MarkupFilenames(un string, mkp *Markup) {
	mkp.Append(`<ul>`)
	first := true
	for _, f := range webKeybaseFiles {
		var bullet string
		if first {
			bullet = "   "
			first = false
		} else {
			bullet = "OR "
		}
		mkp.Append(`<li bullet="` + bullet + `"><url>` + un + "/" + f + `</url></li>`)
	}
	mkp.Append(`</ul>`)
}

func (t WebServiceType) PreProofWarning(un string) *Markup {
	mkp := FmtMarkup(`<p>You will be asked to post a file to:</p>`)
	t.MarkupFilenames(un, mkp)
	return mkp
}

func (t WebServiceType) PostInstructions(un string) *Markup {
	mkp := FmtMarkup(`<p>Make the following file available at:</p>`)
	t.MarkupFilenames(un, mkp)
	return mkp
}

func (t WebServiceType) DisplayName(un string) string { return "Web" }
func (t WebServiceType) GetTypeName() string          { return "web" }

func (t WebServiceType) RecheckProofPosting(tryNumber int, status keybase1.ProofStatus, _ string) (warning *Markup, err error) {
	if status == keybase1.ProofStatus_PERMISSION_DENIED {
		warning = FmtMarkup("Permission denied! Make sure your proof page is public.")
	} else {
		warning, err = t.BaseRecheckProofPosting(tryNumber, status)
	}
	return
}
func (t WebServiceType) GetProofType() string { return "web_service_binding.generic" }

func (t WebServiceType) CheckProofText(text string, id keybase1.SigID, sig string) (err error) {
	return t.BaseCheckProofTextFull(text, id, sig)
}

func (t WebServiceType) GetAPIArgKey() string { return "remote_host" }
func (t WebServiceType) LastWriterWins() bool { return false }

//=============================================================================

func init() {
	RegisterServiceType(WebServiceType{})
	RegisterSocialNetwork("web")
	RegisterProofCheckHook("http",
		func(l RemoteProofChainLink) (ProofChecker, ProofError) {
			return NewWebChecker(l)
		})
}

//=============================================================================
<|endoftext|>


<commit_before>package redis

// TODO(ttacon): make not int64 but int
func (c *Client) SAdd(key, member string, members ...string) (int64, error) {
	args := append([]string{key, member}, members...)
	resp, err := c.exec("SADD", args...)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

// TODO(ttacon): make not int64 but int
func (c *Client) SCard(key string) (int64, error) {
	// TODO(ttacon): do it
	resp, err := c.exec("SCARD", key)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) SDiff(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SDiffStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SInter(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SInterStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SIsMember(key, member string) (bool, error) {
	// TODO(ttacon): do it
	return false, nil
}

func (c *Client) SMembers(key string) ([]string, error) {
	resp, err := c.exec("SMEMBERS", key)
	if err != nil {
		return nil, err
	}
	return c.stringSlice(resp)
}

func (c *Client) SMove(source, destination, member string) (bool, error) {
	// TODO(ttacon): do it
	return false, nil
}

func (c *Client) SPop(key string) (string, error) {
	// TODO(ttacon): do it
	return "", nil
}

func (c *Client) SRandMember(key string, count int) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SRem(key, member string, members ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SUnion(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SUnionStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

// TODO(ttacon): amend to have correct function signature
func (c *Client) SScan(key string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}
<commit_msg>remove todo<commit_after>package redis

// TODO(ttacon): make not int64 but int
func (c *Client) SAdd(key, member string, members ...string) (int64, error) {
	args := append([]string{key, member}, members...)
	resp, err := c.exec("SADD", args...)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

// TODO(ttacon): make not int64 but int
func (c *Client) SCard(key string) (int64, error) {
	resp, err := c.exec("SCARD", key)
	if err != nil {
		return 0, err
	}
	return c.intResp(resp)
}

func (c *Client) SDiff(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SDiffStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SInter(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SInterStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SIsMember(key, member string) (bool, error) {
	// TODO(ttacon): do it
	return false, nil
}

func (c *Client) SMembers(key string) ([]string, error) {
	resp, err := c.exec("SMEMBERS", key)
	if err != nil {
		return nil, err
	}
	return c.stringSlice(resp)
}

func (c *Client) SMove(source, destination, member string) (bool, error) {
	// TODO(ttacon): do it
	return false, nil
}

func (c *Client) SPop(key string) (string, error) {
	// TODO(ttacon): do it
	return "", nil
}

func (c *Client) SRandMember(key string, count int) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SRem(key, member string, members ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

func (c *Client) SUnion(key string, keys ...string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}

func (c *Client) SUnionStore(destination, key string, keys ...string) (int, error) {
	// TODO(ttacon): do it
	return 0, nil
}

// TODO(ttacon): amend to have correct function signature
func (c *Client) SScan(key string) ([]string, error) {
	// TODO(ttacon): do it
	return nil, nil
}
<|endoftext|>


<commit_before>// Package old implements a plugin to remember URLs and announce duplicates.
package old

import (
	"log"
	"regexp"
	"strings"
	"time"

	"github.com/StalkR/goircbot/bot"
	"github.com/fluffle/goirc/client"
)

var linkRE = regexp.MustCompile(`(?:^|\s)(https?://[^#\s]+)`)

func readURLs(b *bot.Bot, line *client.Line, o *Old) {
	target := line.Args[0]
	if !strings.HasPrefix(target, "#") {
		return
	}
	text := line.Args[1]

	matches := linkRE.FindAllStringSubmatch(text, -1)
	if matches == nil {
		return
	}
	for _, submatches := range matches {
		url := submatches[1]
		i, err := o.Old(url)
		if err != nil {
			if err = o.Add(url, target, line.Nick); err != nil {
				log.Print(err)
			}
			return
		}
		b.Conn.Privmsg(target, i.String())
	}
}

// Register registers the plugin with a bot.
func Register(b *bot.Bot, oldfile string) {
	o := load(oldfile)

	b.Conn.HandleFunc("privmsg",
		func(conn *client.Conn, line *client.Line) { readURLs(b, line, o) })

	if len(oldfile) > 0 {
		b.AddCron("old-save", bot.Cron{
			Handler:  func(b *bot.Bot) { save(oldfile, o) },
			Duration: time.Minute})
	}

	// Every day, clean URLs older than a year so it does not grow infinitely.
	b.AddCron("old-clean", bot.Cron{
		Handler:  func(b *bot.Bot) { o.Clean(time.Hour * 24 * 365) },
		Duration: time.Hour * 24})
}
<commit_msg>plugins/old: do not highlight nicks<commit_after>// Package old implements a plugin to remember URLs and announce duplicates.
package old

import (
	"fmt"
	"log"
	"regexp"
	"strings"
	"time"

	"github.com/StalkR/goircbot/bot"
	"github.com/StalkR/goircbot/lib/nohl"
	"github.com/fluffle/goirc/client"
)

var linkRE = regexp.MustCompile(`(?:^|\s)(https?://[^#\s]+)`)

func readURLs(b *bot.Bot, line *client.Line, o *Old) {
	target := line.Args[0]
	if !strings.HasPrefix(target, "#") {
		return
	}
	text := line.Args[1]

	matches := linkRE.FindAllStringSubmatch(text, -1)
	if matches == nil {
		return
	}
	for _, submatches := range matches {
		url := submatches[1]
		i, err := o.Old(url)
		if err != nil {
			if err = o.Add(url, target, line.Nick); err != nil {
				log.Print(err)
			}
			return
		}
		duration := time.Since(i.Time) / time.Second * time.Second
		nick := nohl.Nick(b, target, i.Nick)
		b.Conn.Privmsg(target, fmt.Sprintf("old! first shared by %v %v ago", nick, duration))
	}
}

// Register registers the plugin with a bot.
func Register(b *bot.Bot, oldfile string) {
	o := load(oldfile)

	b.Conn.HandleFunc("privmsg",
		func(conn *client.Conn, line *client.Line) { readURLs(b, line, o) })

	if len(oldfile) > 0 {
		b.AddCron("old-save", bot.Cron{
			Handler:  func(b *bot.Bot) { save(oldfile, o) },
			Duration: time.Minute})
	}

	// Every day, clean URLs older than a year so it does not grow infinitely.
	b.AddCron("old-clean", bot.Cron{
		Handler:  func(b *bot.Bot) { o.Clean(time.Hour * 24 * 365) },
		Duration: time.Hour * 24})
}
<|endoftext|>


<commit_before>package postgres
<commit_msg>Add postgres cli<commit_after>package postgres

import (
	"database/sql"
	"fmt"
	"os"

	"github.com/vektra/cypress"
	"github.com/vektra/cypress/cli/commands"
)

type Send struct {
	DBName      string `long:"dbname" description:"The name of the database to connect to"`
	User        string `long:"user" description:"The user to sign in as"`
	Password    string `long:"password" description:"The user's password"`
	Host        string `long:"host" description:"The host to connect to. Values that start with / are for unix domain sockets. (default is localhost)"`
	Port        string `long:"port" description:"The port to bind to. (default is 5432)"`
	SSLMode     string `long:"sslmode" description:"Whether or not to use SSL (default is require, this is not the default for libpq)"`
	Timeout     string `long:"timeout" description:"Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely."`
	SSLCert     string `long:"sslcert" description:"Cert file location. The file must contain PEM encoded data."`
	SSLKey      string `long:"sslkey" description:"Key file location. The file must contain PEM encoded data."`
	SSLRootCert string `long:"sslrootcert" description:"The location of the root certificate file. The file must contain PEM encoded data."`
}

func (p *Send) Execute(args []string) error {
	db, err := sql.Open("postgres",
		fmt.Sprintf("dbname=%s user=%s password=%s host=%s port=%s sslmode=%s connect_timeout=%s sslcert=%s sslkey=%s sslrootcert=%s",
			p.DBName, p.User, p.Password, p.Host, p.Port, p.SSLMode, p.Timeout, p.SSLCert, p.SSLKey, p.SSLRootCert))
	if err != nil {
		return err
	}

	postgres := &Postgres{}
	postgres.Init(db)

	err = postgres.SetupDB()
	if err != nil {
		return err
	}

	dec, err := cypress.NewStreamDecoder(os.Stdin)
	if err != nil {
		return err
	}

	return cypress.Glue(dec, postgres)
}

type Recv struct {
	DBName      string `long:"dbname" description:"The name of the database to connect to"`
	User        string `long:"user" description:"The user to sign in as"`
	Password    string `long:"password" description:"The user's password"`
	Host        string `long:"host" description:"The host to connect to. Values that start with / are for unix domain sockets. (default is localhost)"`
	Port        string `long:"port" description:"The port to bind to. (default is 5432)"`
	SSLMode     string `long:"sslmode" description:"Whether or not to use SSL (default is require, this is not the default for libpq)"`
	Timeout     string `long:"timeout" description:"Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely."`
	SSLCert     string `long:"sslcert" description:"Cert file location. The file must contain PEM encoded data."`
	SSLKey      string `long:"sslkey" description:"Key file location. The file must contain PEM encoded data."`
	SSLRootCert string `long:"sslrootcert" description:"The location of the root certificate file. The file must contain PEM encoded data."`

	Start     string
	End       string
	Version   int32
	Type      uint32
	SessionId string
	Order     string
	Limit     uint

	BufferSize int `long:"buffersize" default:"100"`
}

func (g *Recv) Execute(args []string) error {
	options := &Options{
		Start:     g.Start,
		End:       g.End,
		Version:   g.Version,
		Type:      g.Type,
		SessionId: g.SessionId,
		Order:     g.Order,
		Limit:     g.Limit,
	}

	db, err := sql.Open("postgres",
		fmt.Sprintf("dbname=%s user=%s password=%s host=%s port=%s sslmode=%s connect_timeout=%s sslcert=%s sslkey=%s sslrootcert=%s",
			g.DBName, g.User, g.Password, g.Host, g.Port, g.SSLMode, g.Timeout, g.SSLCert, g.SSLKey, g.SSLRootCert))
	if err != nil {
		return err
	}

	p := &Postgres{}
	p.Init(db)

	err = p.SetupDB()
	if err != nil {
		return err
	}

	postgres, err := NewPostgresRecv(p, options, g.BufferSize)
	if err != nil {
		return err
	}

	dec, err := cypress.NewStreamDecoder(os.Stdin)
	if err != nil {
		return err
	}

	return cypress.Glue(dec, postgres)

	receiver := cypress.NewStreamEncoder(os.Stdout)

	return cypress.Glue(postgres, receiver)
}

func init() {
	short := "Send messages to Postgres"
	long := "Given a stream on stdin, the postgres command will read those messages in and send them to Postgres."

	commands.Add("send", short, long, &Send{})

	short = "Get messages from Postgres"
	long = ""

	commands.Add("recv", short, long, &Recv{})
}
<|endoftext|>


<commit_before>//Package db provides abstractions that makes it easy to interact with the ql
//database.
package db

import (
	"database/sql"

	_ "github.com/cznic/ql/driver"
)

type Kind int

const (
	QL Kind = iota
	Postgres
	MySQL
)

type DB struct {
	*sql.DB
	k Kind
}

func Open(dbName, path string) (*DB, error) {
	db, err := sql.Open(dbName, path)
	if err != nil {
		return nil, err
	}
	var k Kind
	switch dbName {
	case "q;", "ql-mem":
		k = QL
	}
	return &DB{
		DB: db,
		k:  k,
	}, nil
}

func (db *DB) Kind() Kind {
	return db.k
}
<commit_msg>Add Query interface<commit_after>//Package db provides abstractions that makes it easy to interact with the ql
//database.
package db

import (
	"database/sql"

	_ "github.com/cznic/ql/driver"
)

type Kind int

const (
	QL Kind = iota
	Postgres
	MySQL
)

//Query is an interface for SQL query string.
type Query interface {
	String() string
	IsTx() bool
	Params() []string
}

type baseQuery struct {
	s      string
	isTx   bool
	params []string
}

type DB struct {
	*sql.DB
	k Kind
}

func Open(dbName, path string) (*DB, error) {
	db, err := sql.Open(dbName, path)
	if err != nil {
		return nil, err
	}
	var k Kind
	switch dbName {
	case "q;", "ql-mem":
		k = QL
	}
	return &DB{
		DB: db,
		k:  k,
	}, nil
}

func (db *DB) Kind() Kind {
	return db.k
}
<|endoftext|>


<commit_before>package services_test

import (
	"os"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	slclientfakes "github.com/maximilien/softlayer-go/client/fakes"
	common "github.com/maximilien/softlayer-go/common"
	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

var _ = Describe("SoftLayer_Virtual_Guest_Service", func() {
	var (
		username, apiKey string
		err              error

		fakeClient *slclientfakes.FakeSoftLayerClient

		vgbdtgService softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service

		vgbdtGroup datatypes.SoftLayer_Virtual_Guest_Block_Device_Template_Group
	)

	BeforeEach(func() {
		username = os.Getenv("SL_USERNAME")
		Expect(username).ToNot(Equal(""))

		apiKey = os.Getenv("SL_API_KEY")
		Expect(apiKey).ToNot(Equal(""))

		fakeClient = slclientfakes.NewFakeSoftLayerClient(username, apiKey)
		Expect(fakeClient).ToNot(BeNil())

		vgbdtgService, err = fakeClient.GetSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service()
		Expect(err).ToNot(HaveOccurred())
		Expect(vgbdtgService).ToNot(BeNil())

		vgbdtGroup = datatypes.SoftLayer_Virtual_Guest_Block_Device_Template_Group{}
	})

	Context("#GetName", func() {
		It("returns the name for the service", func() {
			name := vgbdtgService.GetName()
			Expect(name).To(Equal("SoftLayer_Virtual_Guest_Block_Device_Template_Group"))
		})
	})

	Context("#GetObject", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 200150
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getObject.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			vgbdtg, err := vgbdtgService.GetObject(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(vgbdtg.AccountId).To(Equal(278444))
			Expect(vgbdtg.CreateDate).ToNot(BeNil())
			Expect(vgbdtg.Id).To(Equal(vgbdtGroup.Id))
			Expect(vgbdtg.Name).To(Equal("BOSH-eCPI-packer-centos-2014-08-12T15:54:16Z"))
			Expect(vgbdtg.Note).To(Equal("centos image created by packer at 2014-08-12T15:54:16Z"))
			Expect(vgbdtg.ParentId).To(BeNil())
			Expect(vgbdtg.PublicFlag).To(Equal(0))
			Expect(vgbdtg.StatusId).To(Equal(1))
			Expect(vgbdtg.Summary).To(Equal("centos image created by packer at 2014-08-12T15:54:16Z"))
			Expect(vgbdtg.TransactionId).To(BeNil())
			Expect(vgbdtg.UserRecordId).To(Equal(239954))
			Expect(vgbdtg.GlobalIdentifier).To(Equal("8071601b-5ee1-483e-a9e8-6e5582dcb9f7"))
		})
	})

	Context("#DeleteObject", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
		})

		It("sucessfully deletes the SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			fakeClient.DoRawHttpRequestResponse = []byte("true")
			deleted, err := vgbdtgService.DeleteObject(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())
		})

		It("fails to delete the SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			fakeClient.DoRawHttpRequestResponse = []byte("false")
			deleted, err := vgbdtgService.DeleteObject(vgbdtGroup.Id)
			Expect(err).To(HaveOccurred())
			Expect(deleted).To(BeFalse())
		})
	})

	Context("#GetDatacenters", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getDatacenters.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves an array of SoftLayer_Location array for virtual guest device template group", func() {
			locations, err := vgbdtgService.GetDatacenters(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(locations)).To(BeNumerically("==", 2))

			Expect(locations[0].Id).To(Equal(265592))
			Expect(locations[0].LongName).To(Equal("Amsterdam 1"))
			Expect(locations[0].Name).To(Equal("ams01"))

			Expect(locations[1].Id).To(Equal(154820))
			Expect(locations[1].LongName).To(Equal("Dallas 6"))
			Expect(locations[1].Name).To(Equal("dal06"))
		})
	})

	Context("#GetSshKeys", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getSshKeys.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves an array of SoftLayer_Security_Ssh_Key array for virtual guest device template group", func() {
			sshKeys, err := vgbdtgService.GetSshKeys(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(sshKeys)).To(BeNumerically(">", 0))

			for _, sshKey := range sshKeys {
				Expect(sshKey.CreateDate).ToNot(BeNil())
				Expect(sshKey.Fingerprint).To(Equal("f6:c2:9d:57:2f:74:be:a1:db:71:f2:e5:8e:0f:84:7e"))
				Expect(sshKey.Id).To(Equal(84386))
				Expect(sshKey.Key).ToNot(Equal(""))
				Expect(sshKey.Label).To(Equal("TEST:softlayer-go"))
				Expect(sshKey.ModifyDate).To(BeNil())
				Expect(sshKey.Label).To(Equal("TEST:softlayer-go"))
			}
		})
	})

	Context("#GetStatus", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getStatus.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Virtual_Guest_Block_Device_Template_Group instance status", func() {
			status, err := vgbdtgService.GetStatus(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(status.Description).To(Equal("The Guest Block Device Template Group is available to all accounts"))
			Expect(status.KeyName).To(Equal("ACTIVE"))
			Expect(status.Name).To(Equal("Active"))
		})
	})

	Context("#GetStorageLocations", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getStorageLocations.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Locations for the Virtual_Guest_Block_Device_Template_Group instance", func() {
			locations, err := vgbdtgService.GetStorageLocations(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(locations)).To(Equal(18))

			found := false
			for _, location := range locations {
				if location.LongName == "Paris 1" {
					Expect(location.Id).To(Equal(449500))
					Expect(location.Name).To(Equal("par01"))
					found = true
					break
				}
			}
			Expect(found).To(BeTrue())
		})
	})

	Context("#GetImageType", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getImageType.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves the image type for the instance", func() {
			imageType, err := vgbdtgService.GetImageType(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(imageType.Description).To(Equal("a disk that may be replaced on upgrade"))
			Expect(imageType.KeyName).To(Equal("SYSTEM"))
			Expect(imageType.Name).To(Equal("System"))
		})
	})

	Context("#CreateFromExternalSource", func() {
		var configuration datatypes.SoftLayer_Container_Virtual_Guest_Block_Device_Template_Configuration

		BeforeEach(func() {
			configuration = datatypes.SoftLayer_Container_Virtual_Guest_Block_Device_Template_Configuration{
				Name: "fake-configuration-name",
				Note: "fake-configuration-note",
				OperatingSystemReferenceCode: "fake-operating-system-reference-code",
				Uri: "swift://FakeObjectStorageAccountName>@fake-clusterName/fake-containerName/fake-fileName.vhd",
			}
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_createFromExternalSource.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves the image type for the instance", func() {
			vgbdtGroup, err := vgbdtgService.CreateFromExternalSource(configuration)
			Expect(err).ToNot(HaveOccurred())
			Expect(vgbdtGroup.AccountId).To(Equal(278444))
			Expect(vgbdtGroup.CreateDate).ToNot(BeNil())
			Expect(vgbdtGroup.Id).To(Equal(211582))
			Expect(vgbdtGroup.Name).To(Equal(" ubuntu-10.04-bosh-2168-IEM-itcs104-dea-stemcell"))
			Expect(vgbdtGroup.Note).To(Equal("fake-note"))
			Expect(*vgbdtGroup.ParentId).To(Equal(211578))
			Expect(vgbdtGroup.PublicFlag).To(Equal(0))
			Expect(vgbdtGroup.StatusId).To(Equal(1))
			Expect(vgbdtGroup.Summary).To(Equal("fake-summary"))
			Expect(vgbdtGroup.TransactionId).To(BeNil())
			Expect(vgbdtGroup.UserRecordId).To(Equal(180816))
			Expect(vgbdtGroup.GlobalIdentifier).To(Equal("fake-global-identifier"))
		})
	})
})
<commit_msg>fix the It(...) function description<commit_after>package services_test

import (
	"os"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	slclientfakes "github.com/maximilien/softlayer-go/client/fakes"
	common "github.com/maximilien/softlayer-go/common"
	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

var _ = Describe("SoftLayer_Virtual_Guest_Service", func() {
	var (
		username, apiKey string
		err              error

		fakeClient *slclientfakes.FakeSoftLayerClient

		vgbdtgService softlayer.SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service

		vgbdtGroup datatypes.SoftLayer_Virtual_Guest_Block_Device_Template_Group
	)

	BeforeEach(func() {
		username = os.Getenv("SL_USERNAME")
		Expect(username).ToNot(Equal(""))

		apiKey = os.Getenv("SL_API_KEY")
		Expect(apiKey).ToNot(Equal(""))

		fakeClient = slclientfakes.NewFakeSoftLayerClient(username, apiKey)
		Expect(fakeClient).ToNot(BeNil())

		vgbdtgService, err = fakeClient.GetSoftLayer_Virtual_Guest_Block_Device_Template_Group_Service()
		Expect(err).ToNot(HaveOccurred())
		Expect(vgbdtgService).ToNot(BeNil())

		vgbdtGroup = datatypes.SoftLayer_Virtual_Guest_Block_Device_Template_Group{}
	})

	Context("#GetName", func() {
		It("returns the name for the service", func() {
			name := vgbdtgService.GetName()
			Expect(name).To(Equal("SoftLayer_Virtual_Guest_Block_Device_Template_Group"))
		})
	})

	Context("#GetObject", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 200150
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getObject.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			vgbdtg, err := vgbdtgService.GetObject(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(vgbdtg.AccountId).To(Equal(278444))
			Expect(vgbdtg.CreateDate).ToNot(BeNil())
			Expect(vgbdtg.Id).To(Equal(vgbdtGroup.Id))
			Expect(vgbdtg.Name).To(Equal("BOSH-eCPI-packer-centos-2014-08-12T15:54:16Z"))
			Expect(vgbdtg.Note).To(Equal("centos image created by packer at 2014-08-12T15:54:16Z"))
			Expect(vgbdtg.ParentId).To(BeNil())
			Expect(vgbdtg.PublicFlag).To(Equal(0))
			Expect(vgbdtg.StatusId).To(Equal(1))
			Expect(vgbdtg.Summary).To(Equal("centos image created by packer at 2014-08-12T15:54:16Z"))
			Expect(vgbdtg.TransactionId).To(BeNil())
			Expect(vgbdtg.UserRecordId).To(Equal(239954))
			Expect(vgbdtg.GlobalIdentifier).To(Equal("8071601b-5ee1-483e-a9e8-6e5582dcb9f7"))
		})
	})

	Context("#DeleteObject", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
		})

		It("sucessfully deletes the SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			fakeClient.DoRawHttpRequestResponse = []byte("true")
			deleted, err := vgbdtgService.DeleteObject(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(deleted).To(BeTrue())
		})

		It("fails to delete the SoftLayer_Virtual_Guest_Block_Device_Template_Group instance", func() {
			fakeClient.DoRawHttpRequestResponse = []byte("false")
			deleted, err := vgbdtgService.DeleteObject(vgbdtGroup.Id)
			Expect(err).To(HaveOccurred())
			Expect(deleted).To(BeFalse())
		})
	})

	Context("#GetDatacenters", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getDatacenters.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves an array of SoftLayer_Location array for virtual guest device template group", func() {
			locations, err := vgbdtgService.GetDatacenters(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(locations)).To(BeNumerically("==", 2))

			Expect(locations[0].Id).To(Equal(265592))
			Expect(locations[0].LongName).To(Equal("Amsterdam 1"))
			Expect(locations[0].Name).To(Equal("ams01"))

			Expect(locations[1].Id).To(Equal(154820))
			Expect(locations[1].LongName).To(Equal("Dallas 6"))
			Expect(locations[1].Name).To(Equal("dal06"))
		})
	})

	Context("#GetSshKeys", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getSshKeys.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves an array of SoftLayer_Security_Ssh_Key array for virtual guest device template group", func() {
			sshKeys, err := vgbdtgService.GetSshKeys(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(sshKeys)).To(BeNumerically(">", 0))

			for _, sshKey := range sshKeys {
				Expect(sshKey.CreateDate).ToNot(BeNil())
				Expect(sshKey.Fingerprint).To(Equal("f6:c2:9d:57:2f:74:be:a1:db:71:f2:e5:8e:0f:84:7e"))
				Expect(sshKey.Id).To(Equal(84386))
				Expect(sshKey.Key).ToNot(Equal(""))
				Expect(sshKey.Label).To(Equal("TEST:softlayer-go"))
				Expect(sshKey.ModifyDate).To(BeNil())
				Expect(sshKey.Label).To(Equal("TEST:softlayer-go"))
			}
		})
	})

	Context("#GetStatus", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getStatus.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Virtual_Guest_Block_Device_Template_Group instance status", func() {
			status, err := vgbdtgService.GetStatus(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(status.Description).To(Equal("The Guest Block Device Template Group is available to all accounts"))
			Expect(status.KeyName).To(Equal("ACTIVE"))
			Expect(status.Name).To(Equal("Active"))
		})
	})

	Context("#GetStorageLocations", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getStorageLocations.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves SoftLayer_Locations for the Virtual_Guest_Block_Device_Template_Group instance", func() {
			locations, err := vgbdtgService.GetStorageLocations(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(len(locations)).To(Equal(18))

			found := false
			for _, location := range locations {
				if location.LongName == "Paris 1" {
					Expect(location.Id).To(Equal(449500))
					Expect(location.Name).To(Equal("par01"))
					found = true
					break
				}
			}
			Expect(found).To(BeTrue())
		})
	})

	Context("#GetImageType", func() {
		BeforeEach(func() {
			vgbdtGroup.Id = 1234567
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_getImageType.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully retrieves the image type for the instance", func() {
			imageType, err := vgbdtgService.GetImageType(vgbdtGroup.Id)
			Expect(err).ToNot(HaveOccurred())
			Expect(imageType.Description).To(Equal("a disk that may be replaced on upgrade"))
			Expect(imageType.KeyName).To(Equal("SYSTEM"))
			Expect(imageType.Name).To(Equal("System"))
		})
	})

	Context("#CreateFromExternalSource", func() {
		var configuration datatypes.SoftLayer_Container_Virtual_Guest_Block_Device_Template_Configuration

		BeforeEach(func() {
			configuration = datatypes.SoftLayer_Container_Virtual_Guest_Block_Device_Template_Configuration{
				Name: "fake-configuration-name",
				Note: "fake-configuration-note",
				OperatingSystemReferenceCode: "fake-operating-system-reference-code",
				Uri: "swift://FakeObjectStorageAccountName>@fake-clusterName/fake-containerName/fake-fileName.vhd",
			}
			fakeClient.DoRawHttpRequestResponse, err = common.ReadJsonTestFixtures("services", "SoftLayer_Virtual_Guest_Block_Device_Template_Group_Service_createFromExternalSource.json")
			Expect(err).ToNot(HaveOccurred())
		})

		It("sucessfully creates a virtual guest device templte group from a configuration from an external VHD image", func() {
			vgbdtGroup, err := vgbdtgService.CreateFromExternalSource(configuration)
			Expect(err).ToNot(HaveOccurred())
			Expect(vgbdtGroup.AccountId).To(Equal(278444))
			Expect(vgbdtGroup.CreateDate).ToNot(BeNil())
			Expect(vgbdtGroup.Id).To(Equal(211582))
			Expect(vgbdtGroup.Name).To(Equal(" ubuntu-10.04-bosh-2168-IEM-itcs104-dea-stemcell"))
			Expect(vgbdtGroup.Note).To(Equal("fake-note"))
			Expect(*vgbdtGroup.ParentId).To(Equal(211578))
			Expect(vgbdtGroup.PublicFlag).To(Equal(0))
			Expect(vgbdtGroup.StatusId).To(Equal(1))
			Expect(vgbdtGroup.Summary).To(Equal("fake-summary"))
			Expect(vgbdtGroup.TransactionId).To(BeNil())
			Expect(vgbdtGroup.UserRecordId).To(Equal(180816))
			Expect(vgbdtGroup.GlobalIdentifier).To(Equal("fake-global-identifier"))
		})
	})
})
<|endoftext|>


<commit_before>package mel

import (
	"bytes"
	"html/template"
	"log"
)

func init() {
	log.SetFlags(0)
}

// IsDebugging returns true if the framework is running in debug mode.
// Use SetMode(gin.Release) to switch to disable the debug mode.
func IsDebugging() bool {
	return true
}

func debugPrintRoute(httpMethod, absolutePath string, handlers []Handler) {
	if IsDebugging() {
		nuHandlers := len(handlers)
		handlerName := nameOfFunction(handlers[nuHandlers-1])
		debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers)
	}
}

func debugPrintLoadTemplate(tmpl *template.Template) {
	if IsDebugging() {
		var buf bytes.Buffer
		for _, tmpl := range tmpl.Templates() {
			buf.WriteString("\t- ")
			buf.WriteString(tmpl.Name())
			buf.WriteString("\n")
		}
		debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String())
	}
}

func debugPrint(format string, v ...interface{}) {
	if IsDebugging() {
		log.Printf("[GIN-debug] " + format, v...)
	}
}

func debugPrintWARNINGNew() {
	debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

`)
}

func debugPrintWARNINGSetHTMLTemplate() {
	debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called
at initialization. ie. before any route is registered or the router is listening in a socket:

	router := gin.Default()
	router.SetHTMLTemplate(template) // << good place

`)
}

func debugPrintError(err error) {
	if err != nil {
		debugPrint("[ERROR] %v\n", err)
	}
}
<commit_msg>Update debug<commit_after>package mel

import (
	"bytes"
	"html/template"
	"log"
)

func init() {
	log.SetFlags(0)
}

// IsDebugging returns true if the framework is running in debug mode.
// Use SetMode(gin.Release) to switch to disable the debug mode.
func IsDebugging() bool {
	return true
}

func debugPrintRoute(httpMethod, absolutePath string, handlers []Handler) {
	if IsDebugging() {
		nuHandlers := len(handlers)
		handlerName := nameOfFunction(handlers[nuHandlers-1])
		debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers)
	}
}

func debugPrintLoadTemplate(tmpl *template.Template) {
	if IsDebugging() {
		var buf bytes.Buffer
		for _, tmpl := range tmpl.Templates() {
			buf.WriteString("\t- ")
			buf.WriteString(tmpl.Name())
			buf.WriteString("\n")
		}
		debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String())
	}
}

func debugPrint(format string, v ...interface{}) {
	if IsDebugging() {
		log.Printf("[MEL-debug] " + format, v...)
	}
}

func debugPrintWARNINGNew() {
	debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export MEL_MODE=release
 - using code:	mel.SetMode(mel.ReleaseMode)

`)
}

func debugPrintWARNINGSetHTMLTemplate() {
	debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called
at initialization. ie. before any route is registered or the router is listening in a socket:

	router := mel.Default()
	router.SetHTMLTemplate(template) // << good place

`)
}

func debugPrintError(err error) {
	if err != nil {
		debugPrint("[ERROR] %v\n", err)
	}
}
<|endoftext|>


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

// Package compilercommon defines common types and their functions shared across the compiler.
package compilercommon

import (
	"fmt"
)

// Position represents a position in an arbitrary source file.
type Position struct {
	// LineNumber is the 0-indexed line number.
	LineNumber int

	// ColumnPosition is the 0-indexed column position on the line.
	ColumnPosition int
}

// InputSource represents the path of a source file.
type InputSource string

// RangeForRunePosition returns a source range over this source file.
func (is InputSource) RangeForRunePosition(runePosition int, mapper PositionMapper) SourceRange {
	return is.RangeForRunePositions(runePosition, runePosition, mapper)
}

// PositionForRunePosition returns a source position over this source file.
func (is InputSource) PositionForRunePosition(runePosition int, mapper PositionMapper) SourcePosition {
	return runeIndexedPosition{is, mapper, runePosition}
}

// PositionFromLineAndColumn returns a source position at the given line and column in this source file.
func (is InputSource) PositionFromLineAndColumn(lineNumber int, columnPosition int, mapper PositionMapper) SourcePosition {
	return lcIndexedPosition{is, mapper, Position{lineNumber, columnPosition}}
}

// RangeForRunePositions returns a source range over this source file.
func (is InputSource) RangeForRunePositions(startRune int, endRune int, mapper PositionMapper) SourceRange {
	return sourceRange{is, runeIndexedPosition{is, mapper, startRune}, runeIndexedPosition{is, mapper, endRune}}
}

// RangeForLineAndColPositions returns a source range over this source file.
func (is InputSource) RangeForLineAndColPositions(start Position, end Position, mapper PositionMapper) SourceRange {
	return sourceRange{is, lcIndexedPosition{is, mapper, start}, lcIndexedPosition{is, mapper, end}}
}

// SourceMappingOption defines the options for whichn source to use when position mapping.
type SourceMappingOption int

const (
	// SourceMapTracked indicates that position mapping should occur over the *tracked* source
	// contents. This is the default.
	SourceMapTracked SourceMappingOption = iota

	// SourceMapCurrent indicates that position mapping should occur over the *current* source
	// contents. This should only be used by tooling, and is likely to fail in certain cases
	// where positions have gotten desynced.
	SourceMapCurrent
)

// PositionMapper defines an interface for converting rune position <-> line+col position
// under source files.
type PositionMapper interface {
	// RunePositionToLineAndCol converts the given 0-indexed rune position under the given source file
	// into a 0-indexed line number and column position.
	RunePositionToLineAndCol(runePosition int, path InputSource, sourceOption SourceMappingOption) (int, int, error)

	// LineAndColToRunePosition converts the given 0-indexed line number and column position under the
	// given source file into a 0-indexed rune position.
	LineAndColToRunePosition(lineNumber int, colPosition int, path InputSource, sourceOption SourceMappingOption) (int, error)

	// TextForLine returns the text for the specified line number.
	TextForLine(lineNumber int, path InputSource, sourceOption SourceMappingOption) (string, error)
}

// SourceRange represents a range inside a source file.
type SourceRange interface {
	// Source is the input source for this range.
	Source() InputSource

	// Start is the starting position of the source range.
	Start() SourcePosition

	// End is the ending position (inclusive) of the source range. If the same as the Start,
	// this range represents a single position.
	End() SourcePosition
}

// SourcePosition represents a single position in a source file.
type SourcePosition interface {
	// Source is the input source for this position.
	Source() InputSource

	// RunePosition returns the 0-indexed rune position in the source file.
	RunePosition() (int, error)

	// LineAndColumn returns the 0-indexed line number and column position in the source file.
	LineAndColumn() (int, int, error)

	// LineText returns the text of the line for this position.
	LineText() (string, error)
}

// sourceRange implements the SourceRange interface.
type sourceRange struct {
	source InputSource
	start  SourcePosition
	end    SourcePosition
}

func (sr sourceRange) Source() InputSource {
	return sr.source
}

func (sr sourceRange) Start() SourcePosition {
	return sr.start
}

func (sr sourceRange) End() SourcePosition {
	return sr.end
}

// runeIndexedPosition implements the SourcePosition interface over a rune position.
type runeIndexedPosition struct {
	source       InputSource
	mapper       PositionMapper
	runePosition int
}

func (ris runeIndexedPosition) Source() InputSource {
	return ris.source
}

func (ris runeIndexedPosition) RunePosition() (int, error) {
	return ris.runePosition, nil
}

func (ris runeIndexedPosition) LineAndColumn() (int, int, error) {
	return ris.mapper.RunePositionToLineAndCol(ris.runePosition, ris.source, SourceMapTracked)
}

func (ris runeIndexedPosition) String() string {
	return fmt.Sprintf("%s@%v (rune)", ris.source, ris.runePosition)
}

func (ris runeIndexedPosition) LineText() (string, error) {
	lineNumber, _, err := ris.LineAndColumn()
	if err != nil {
		return "", err
	}

	return ris.mapper.TextForLine(lineNumber, ris.source, SourceMapTracked)
}

// lcIndexedPosition implements the SourcePosition interface over a line and colu,n position.
type lcIndexedPosition struct {
	source     InputSource
	mapper     PositionMapper
	lcPosition Position
}

func (lcip lcIndexedPosition) Source() InputSource {
	return lcip.source
}

func (lcip lcIndexedPosition) String() string {
	return fmt.Sprintf("%s@%v:%v (line/col)", lcip.source, lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition)
}

func (lcip lcIndexedPosition) RunePosition() (int, error) {
	return lcip.mapper.LineAndColToRunePosition(lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, lcip.source, SourceMapTracked)
}

func (lcip lcIndexedPosition) LineAndColumn() (int, int, error) {
	return lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, nil
}

func (lcip lcIndexedPosition) LineText() (string, error) {
	return lcip.mapper.TextForLine(lcip.lcPosition.LineNumber, lcip.source, SourceMapTracked)
}
<commit_msg>Add a ContainsPosition to the SourceRange interface<commit_after>// Copyright 2015 The Serulian Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package compilercommon defines common types and their functions shared across the compiler.
package compilercommon

import (
	"fmt"
)

// Position represents a position in an arbitrary source file.
type Position struct {
	// LineNumber is the 0-indexed line number.
	LineNumber int

	// ColumnPosition is the 0-indexed column position on the line.
	ColumnPosition int
}

// InputSource represents the path of a source file.
type InputSource string

// RangeForRunePosition returns a source range over this source file.
func (is InputSource) RangeForRunePosition(runePosition int, mapper PositionMapper) SourceRange {
	return is.RangeForRunePositions(runePosition, runePosition, mapper)
}

// PositionForRunePosition returns a source position over this source file.
func (is InputSource) PositionForRunePosition(runePosition int, mapper PositionMapper) SourcePosition {
	return runeIndexedPosition{is, mapper, runePosition}
}

// PositionFromLineAndColumn returns a source position at the given line and column in this source file.
func (is InputSource) PositionFromLineAndColumn(lineNumber int, columnPosition int, mapper PositionMapper) SourcePosition {
	return lcIndexedPosition{is, mapper, Position{lineNumber, columnPosition}}
}

// RangeForRunePositions returns a source range over this source file.
func (is InputSource) RangeForRunePositions(startRune int, endRune int, mapper PositionMapper) SourceRange {
	return sourceRange{is, runeIndexedPosition{is, mapper, startRune}, runeIndexedPosition{is, mapper, endRune}}
}

// RangeForLineAndColPositions returns a source range over this source file.
func (is InputSource) RangeForLineAndColPositions(start Position, end Position, mapper PositionMapper) SourceRange {
	return sourceRange{is, lcIndexedPosition{is, mapper, start}, lcIndexedPosition{is, mapper, end}}
}

// SourceMappingOption defines the options for whichn source to use when position mapping.
type SourceMappingOption int

const (
	// SourceMapTracked indicates that position mapping should occur over the *tracked* source
	// contents. This is the default.
	SourceMapTracked SourceMappingOption = iota

	// SourceMapCurrent indicates that position mapping should occur over the *current* source
	// contents. This should only be used by tooling, and is likely to fail in certain cases
	// where positions have gotten desynced.
	SourceMapCurrent
)

// PositionMapper defines an interface for converting rune position <-> line+col position
// under source files.
type PositionMapper interface {
	// RunePositionToLineAndCol converts the given 0-indexed rune position under the given source file
	// into a 0-indexed line number and column position.
	RunePositionToLineAndCol(runePosition int, path InputSource, sourceOption SourceMappingOption) (int, int, error)

	// LineAndColToRunePosition converts the given 0-indexed line number and column position under the
	// given source file into a 0-indexed rune position.
	LineAndColToRunePosition(lineNumber int, colPosition int, path InputSource, sourceOption SourceMappingOption) (int, error)

	// TextForLine returns the text for the specified line number.
	TextForLine(lineNumber int, path InputSource, sourceOption SourceMappingOption) (string, error)
}

// SourceRange represents a range inside a source file.
type SourceRange interface {
	// Source is the input source for this range.
	Source() InputSource

	// Start is the starting position of the source range.
	Start() SourcePosition

	// End is the ending position (inclusive) of the source range. If the same as the Start,
	// this range represents a single position.
	End() SourcePosition

	// ContainsPosition returns true if the given range contains the given position.
	ContainsPosition(position SourcePosition) (bool, error)
}

// SourcePosition represents a single position in a source file.
type SourcePosition interface {
	// Source is the input source for this position.
	Source() InputSource

	// RunePosition returns the 0-indexed rune position in the source file.
	RunePosition() (int, error)

	// LineAndColumn returns the 0-indexed line number and column position in the source file.
	LineAndColumn() (int, int, error)

	// LineText returns the text of the line for this position.
	LineText() (string, error)
}

// sourceRange implements the SourceRange interface.
type sourceRange struct {
	source InputSource
	start  SourcePosition
	end    SourcePosition
}

func (sr sourceRange) Source() InputSource {
	return sr.source
}

func (sr sourceRange) Start() SourcePosition {
	return sr.start
}

func (sr sourceRange) End() SourcePosition {
	return sr.end
}

func (sr sourceRange) ContainsPosition(position SourcePosition) (bool, error) {
	if position.Source() != sr.source {
		return false, nil
	}

	startRune, err := sr.start.RunePosition()
	if err != nil {
		return false, err
	}

	endRune, err := sr.end.RunePosition()
	if err != nil {
		return false, err
	}

	positionRune, err := position.RunePosition()
	if err != nil {
		return false, err
	}

	return positionRune >= startRune && positionRune <= endRune, nil
}

// runeIndexedPosition implements the SourcePosition interface over a rune position.
type runeIndexedPosition struct {
	source       InputSource
	mapper       PositionMapper
	runePosition int
}

func (ris runeIndexedPosition) Source() InputSource {
	return ris.source
}

func (ris runeIndexedPosition) RunePosition() (int, error) {
	return ris.runePosition, nil
}

func (ris runeIndexedPosition) LineAndColumn() (int, int, error) {
	return ris.mapper.RunePositionToLineAndCol(ris.runePosition, ris.source, SourceMapTracked)
}

func (ris runeIndexedPosition) String() string {
	return fmt.Sprintf("%s@%v (rune)", ris.source, ris.runePosition)
}

func (ris runeIndexedPosition) LineText() (string, error) {
	lineNumber, _, err := ris.LineAndColumn()
	if err != nil {
		return "", err
	}

	return ris.mapper.TextForLine(lineNumber, ris.source, SourceMapTracked)
}

// lcIndexedPosition implements the SourcePosition interface over a line and colu,n position.
type lcIndexedPosition struct {
	source     InputSource
	mapper     PositionMapper
	lcPosition Position
}

func (lcip lcIndexedPosition) Source() InputSource {
	return lcip.source
}

func (lcip lcIndexedPosition) String() string {
	return fmt.Sprintf("%s@%v:%v (line/col)", lcip.source, lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition)
}

func (lcip lcIndexedPosition) RunePosition() (int, error) {
	return lcip.mapper.LineAndColToRunePosition(lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, lcip.source, SourceMapTracked)
}

func (lcip lcIndexedPosition) LineAndColumn() (int, int, error) {
	return lcip.lcPosition.LineNumber, lcip.lcPosition.ColumnPosition, nil
}

func (lcip lcIndexedPosition) LineText() (string, error) {
	return lcip.mapper.TextForLine(lcip.lcPosition.LineNumber, lcip.source, SourceMapTracked)
}
<|endoftext|>


<commit_before>package simp

import (
	"database/sql"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
)

type DriverName string

const (
	MySQL      = DriverName("mysql")
	PostgreSQL = DriverName("postgres")

	defaultLocalAddress = "127.0.0.1"
	mysqlDefaultPort    = 3306
	postgresDefaultPort = 5432
)

// String returns the converted string from of DriverName.
func (dn DriverName) String() string {
	return string(dn)
}

type Dsn string
type DsnConf struct {
	UserName string
	Password string
	Protocol string
	Address  string
	Port     int
	DbName   string
	Params   map[string]string
}

// String returns the converted string from of Dsn.
func (dsn Dsn) String() string {
	return string(dsn)
}

// DSN returns Dsn based on DsnConf and DriverName.
func (dc DsnConf) DSN(dn DriverName) (dsn Dsn, err error) {
	switch {
	case len(dc.UserName) == 0:
		return "", errors.New("UserName is Empty")
	case (len(dc.Address) > 0 && dc.Address != "localhost" && dc.Address != defaultLocalAddress) &&
		len(dc.Password) == 0:
		return "", errors.New("Password is Empty")
	case len(dc.DbName) == 0:
		return "", errors.New("DbName is Empty")
	}
	switch dn {
	case MySQL:
		return Dsn(fmt.Sprintf(
			"%s%s@%s(%s:%d)/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Protocol) == 0 {
					return "tcp"
				} else {
					return dc.Protocol
				}
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return mysqlDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	case PostgreSQL:
		return Dsn(fmt.Sprintf(
			"postgres://%s%s@%s:%d/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return postgresDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			func() string {
				var buf string
				if len(dc.Params) > 0 {
					for k, v := range dc.Params {
						buf += "&" + k + "=" + v
					}
					buf = strings.Replace(buf, "&", "?", 1)
				}
				return buf
			}(),
		)), nil
	default:
		return "", errors.New("undefined driver name was used")
	}
}

// DB is a database object.
type DB struct {
	db  *sql.DB
	tx  *sql.Tx
	mx  sync.Mutex
	err error
}

// New returns a new *DB.
// If error, error is set in *DB.err.
// You can get *DB.err with *DB.Error ().
func New(dn DriverName, dsn Dsn) *DB {
	if db, err := sql.Open(dn.String(), dsn.String()); err != nil {
		return &DB{err: err}
	} else {
		return &DB{db: db}
	}
}

// Ping will check if it can connect to the specified database.
func (db *DB) Ping() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	return db.db.Ping()
}

// Begin starts transaction.
func (db *DB) Begin() error {
	var tx *sql.Tx
	tx, db.err = db.db.Begin()
	if db.err != nil {
		return db.err
	}
	db.mx.Lock()
	defer db.mx.Unlock()
	db.tx = tx
	return nil
}

// Close closes database.
func (db *DB) Close() {
	db.err = db.db.Close()
}

// Commit commits the transacrion.
// Begin needs to be executed before this method is executed.
func (db *DB) Commit() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Commit()
	db.tx = nil
	return err
}

// Rollback rolls back transaction.
// Begin needs to be executed before this method is executed.
func (db *DB) Rollback() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Rollback()
	db.tx = nil
	return err
}

// Exec executes a prepared statement with the specified arguments.
// And this method returns a Result summarizing the effect of the statement.
func (db *DB) Exec(query string, args ...interface{}) (ret sql.Result, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Exec(query, args...)
	default:
		return db.tx.Exec(query, args...)
	}
}

// The query executes a prepared query statement with the specified arguments
// and returns the query result as *sql.Rows.
func (db *DB) Query(query string, args ...interface{}) (ret *sql.Rows, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Query(query, args...)
	default:
		return db.tx.Query(query, args...)
	}
}

// QueryRow executes a prepared query statement with the specified arguments.
// Scans the first selected line and returns it as *sql.Row.
// It will be destroyed after that.
func (db *DB) QueryRow(query string, args ...interface{}) (ret *sql.Row) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret
	}

	switch db.tx {
	case nil:
		return db.db.QueryRow(query, args...)
	default:
		return db.tx.QueryRow(query, args...)
	}
}

// The error returns *DB.err.
func (db *DB) Error() error {
	return db.err
}

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
// Expired connections may be closed lazily before reuse.
// If d <= 0, connections are reused forever.
func (db *DB) SetConnMaxLifetime(d time.Duration) {
	db.db.SetConnMaxLifetime(d)
}

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
	db.db.SetMaxIdleConns(n)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
// MaxIdleConns, then MaxIdleConns will be reduced to match the new
// MaxOpenConns limit
// If n <= 0, then there is no limit on the number of open connections.
// The default is 0 (unlimited).
func (db *DB) SetMaxOpenConns(n int) {
	db.db.SetMaxOpenConns(n)
}

// Prepare creates a prepared statement for later queries or executions.
func (db *DB) Prepare(query string, args ...interface{}) (*sql.Stmt, error) {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return db.db.Prepare(query)
	} else {
		return db.tx.Prepare(query)
	}
}
<commit_msg>fixed the parameter part to always be the same string.<commit_after>package simp

import (
	"database/sql"
	"errors"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"
)

type DriverName string

const (
	MySQL      = DriverName("mysql")
	PostgreSQL = DriverName("postgres")

	defaultLocalAddress = "127.0.0.1"
	mysqlDefaultPort    = 3306
	postgresDefaultPort = 5432
)

// String returns the converted string from of DriverName.
func (dn DriverName) String() string {
	return string(dn)
}

type Dsn string
type DsnConf struct {
	UserName string
	Password string
	Protocol string
	Address  string
	Port     int
	DbName   string
	Params   map[string]string
}

func encodeParams(p map[string]string) (ret string) {
	ks := make([]string, 0, len(p))
	for k := range p {
		ks = append(ks, k)
	}
	sort.Strings(ks)

	var buf strings.Builder
	for _, k := range ks {
		if buf.Len() > 0 {
			buf.WriteByte('&')
		}
		buf.WriteString(k)
		buf.WriteByte('=')
		buf.WriteString(p[k])
	}

	if buf.Len() > 0 {
		ret = "?" + buf.String()
	}
	return
}

// String returns the converted string from of Dsn.
func (dsn Dsn) String() string {
	return string(dsn)
}

// DSN returns Dsn based on DsnConf and DriverName.
func (dc DsnConf) DSN(dn DriverName) (dsn Dsn, err error) {
	switch {
	case len(dc.UserName) == 0:
		return "", errors.New("UserName is Empty")
	case (len(dc.Address) > 0 && dc.Address != "localhost" && dc.Address != defaultLocalAddress) &&
		len(dc.Password) == 0:
		return "", errors.New("Password is Empty")
	case len(dc.DbName) == 0:
		return "", errors.New("DbName is Empty")
	}
	switch dn {
	case MySQL:
		return Dsn(fmt.Sprintf(
			"%s%s@%s(%s:%d)/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Protocol) == 0 {
					return "tcp"
				} else {
					return dc.Protocol
				}
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return mysqlDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			encodeParams(dc.Params),
		)), nil
	case PostgreSQL:
		return Dsn(fmt.Sprintf(
			"postgres://%s%s@%s:%d/%s%s",
			dc.UserName,
			func() string {
				if len(dc.Password) > 0 {
					return ":" + dc.Password
				}
				return ""
			}(),
			func() string {
				if len(dc.Address) == 0 {
					return defaultLocalAddress
				} else {
					return dc.Address
				}
			}(),
			func() int {
				switch {
				case dc.Port == 0:
					return postgresDefaultPort
				default:
					return dc.Port
				}
			}(),
			dc.DbName,
			encodeParams(dc.Params),
		)), nil
	default:
		return "", errors.New("undefined driver name was used")
	}
}

// DB is a database object.
type DB struct {
	db  *sql.DB
	tx  *sql.Tx
	mx  sync.Mutex
	err error
}

// New returns a new *DB.
// If error, error is set in *DB.err.
// You can get *DB.err with *DB.Error ().
func New(dn DriverName, dsn Dsn) *DB {
	if db, err := sql.Open(dn.String(), dsn.String()); err != nil {
		return &DB{err: err}
	} else {
		return &DB{db: db}
	}
}

// Ping will check if it can connect to the specified database.
func (db *DB) Ping() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	return db.db.Ping()
}

// Begin starts transaction.
func (db *DB) Begin() error {
	var tx *sql.Tx
	tx, db.err = db.db.Begin()
	if db.err != nil {
		return db.err
	}
	db.mx.Lock()
	defer db.mx.Unlock()
	db.tx = tx
	return nil
}

// Close closes database.
func (db *DB) Close() {
	db.err = db.db.Close()
}

// Commit commits the transacrion.
// Begin needs to be executed before this method is executed.
func (db *DB) Commit() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Commit()
	db.tx = nil
	return err
}

// Rollback rolls back transaction.
// Begin needs to be executed before this method is executed.
func (db *DB) Rollback() error {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return errors.New("The transaction has not been started or has already been committed or rolled back.")
	}
	err := db.tx.Rollback()
	db.tx = nil
	return err
}

// Exec executes a prepared statement with the specified arguments.
// And this method returns a Result summarizing the effect of the statement.
func (db *DB) Exec(query string, args ...interface{}) (ret sql.Result, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Exec(query, args...)
	default:
		return db.tx.Exec(query, args...)
	}
}

// The query executes a prepared query statement with the specified arguments
// and returns the query result as *sql.Rows.
func (db *DB) Query(query string, args ...interface{}) (ret *sql.Rows, err error) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret, db.err
	}

	switch db.tx {
	case nil:
		return db.db.Query(query, args...)
	default:
		return db.tx.Query(query, args...)
	}
}

// QueryRow executes a prepared query statement with the specified arguments.
// Scans the first selected line and returns it as *sql.Row.
// It will be destroyed after that.
func (db *DB) QueryRow(query string, args ...interface{}) (ret *sql.Row) {
	db.mx.Lock()
	defer db.mx.Unlock()

	if db.err != nil {
		return ret
	}

	switch db.tx {
	case nil:
		return db.db.QueryRow(query, args...)
	default:
		return db.tx.QueryRow(query, args...)
	}
}

// The error returns *DB.err.
func (db *DB) Error() error {
	return db.err
}

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
// Expired connections may be closed lazily before reuse.
// If d <= 0, connections are reused forever.
func (db *DB) SetConnMaxLifetime(d time.Duration) {
	db.db.SetConnMaxLifetime(d)
}

// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
	db.db.SetMaxIdleConns(n)
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
// MaxIdleConns, then MaxIdleConns will be reduced to match the new
// MaxOpenConns limit
// If n <= 0, then there is no limit on the number of open connections.
// The default is 0 (unlimited).
func (db *DB) SetMaxOpenConns(n int) {
	db.db.SetMaxOpenConns(n)
}

// Prepare creates a prepared statement for later queries or executions.
func (db *DB) Prepare(query string, args ...interface{}) (*sql.Stmt, error) {
	db.mx.Lock()
	defer db.mx.Unlock()
	if db.tx == nil {
		return db.db.Prepare(query)
	} else {
		return db.tx.Prepare(query)
	}
}
<|endoftext|>