pip compatible server to serve Python packages out of GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

505 lines
10 KiB

package param
import (
"net/url"
"reflect"
"strings"
"testing"
"time"
)
type Everything struct {
Bool bool
Int int
Uint uint
Float float64
Map map[string]int
Slice []int
String string
Struct Sub
Time time.Time
PBool *bool
PInt *int
PUint *uint
PFloat *float64
PMap *map[string]int
PSlice *[]int
PString *string
PStruct *Sub
PTime *time.Time
PPInt **int
ABool MyBool
AInt MyInt
AUint MyUint
AFloat MyFloat
AMap MyMap
APtr MyPtr
ASlice MySlice
AString MyString
}
type Sub struct {
A int
B int
}
type MyBool bool
type MyInt int
type MyUint uint
type MyFloat float64
type MyMap map[MyString]MyInt
type MyPtr *MyInt
type MySlice []MyInt
type MyString string
var boolAnswers = map[string]bool{
"true": true,
"false": false,
"0": false,
"1": true,
"on": true,
"": false,
}
var testTimeString = "1996-12-19T16:39:57-08:00"
var testTime time.Time
func init() {
testTime, _ = time.Parse(time.RFC3339, testTimeString)
}
func singletonErrors(t *testing.T, field, valid, invalid string) {
e := Everything{}
err := Parse(url.Values{field: {invalid}}, &e)
if err == nil {
t.Errorf("Expected error parsing %q as %s", invalid, field)
}
err = Parse(url.Values{field + "[]": {valid}}, &e)
if err == nil {
t.Errorf("Expected error parsing nested %s", field)
}
err = Parse(url.Values{field + "[nested]": {valid}}, &e)
if err == nil {
t.Errorf("Expected error parsing nested %s", field)
}
err = Parse(url.Values{field: {valid, valid}}, &e)
if err == nil {
t.Errorf("Expected error passing %s twice", field)
}
}
func TestBool(t *testing.T) {
t.Parallel()
for val, correct := range boolAnswers {
e := Everything{}
e.Bool = !correct
err := Parse(url.Values{"Bool": {val}}, &e)
if err != nil {
t.Error("Parse error on key: ", val)
}
assertEqual(t, "e.Bool", correct, e.Bool)
}
}
func TestBoolTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"ABool": {"true"}}, &e)
if err != nil {
t.Error("Parse error for typed bool")
}
assertEqual(t, "e.ABool", MyBool(true), e.ABool)
}
func TestBoolErrors(t *testing.T) {
t.Parallel()
singletonErrors(t, "Bool", "true", "llama")
}
var intAnswers = map[string]int{
"0": 0,
"9001": 9001,
"-42": -42,
}
func TestInt(t *testing.T) {
t.Parallel()
for val, correct := range intAnswers {
e := Everything{}
e.Int = 1
err := Parse(url.Values{"Int": {val}}, &e)
if err != nil {
t.Error("Parse error on key: ", val)
}
assertEqual(t, "e.Int", correct, e.Int)
}
}
func TestIntTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"AInt": {"1"}}, &e)
if err != nil {
t.Error("Parse error for typed int")
}
assertEqual(t, "e.AInt", MyInt(1), e.AInt)
}
func TestIntErrors(t *testing.T) {
t.Parallel()
singletonErrors(t, "Int", "1", "llama")
e := Everything{}
err := Parse(url.Values{"Int": {"4.2"}}, &e)
if err == nil {
t.Error("Expected error parsing float as int")
}
}
var uintAnswers = map[string]uint{
"0": 0,
"9001": 9001,
}
func TestUint(t *testing.T) {
t.Parallel()
for val, correct := range uintAnswers {
e := Everything{}
e.Uint = 1
err := Parse(url.Values{"Uint": {val}}, &e)
if err != nil {
t.Error("Parse error on key: ", val)
}
assertEqual(t, "e.Uint", correct, e.Uint)
}
}
func TestUintTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"AUint": {"1"}}, &e)
if err != nil {
t.Error("Parse error for typed uint")
}
assertEqual(t, "e.AUint", MyUint(1), e.AUint)
}
func TestUintErrors(t *testing.T) {
t.Parallel()
singletonErrors(t, "Uint", "1", "llama")
e := Everything{}
err := Parse(url.Values{"Uint": {"4.2"}}, &e)
if err == nil {
t.Error("Expected error parsing float as uint")
}
err = Parse(url.Values{"Uint": {"-42"}}, &e)
if err == nil {
t.Error("Expected error parsing negative number as uint")
}
}
var floatAnswers = map[string]float64{
"0": 0,
"9001": 9001,
"-42": -42,
"9001.0": 9001.0,
"4.2": 4.2,
"-9.000001": -9.000001,
}
func TestFloat(t *testing.T) {
t.Parallel()
for val, correct := range floatAnswers {
e := Everything{}
e.Float = 1
err := Parse(url.Values{"Float": {val}}, &e)
if err != nil {
t.Error("Parse error on key: ", val)
}
assertEqual(t, "e.Float", correct, e.Float)
}
}
func TestFloatTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"AFloat": {"1.0"}}, &e)
if err != nil {
t.Error("Parse error for typed float")
}
assertEqual(t, "e.AFloat", MyFloat(1.0), e.AFloat)
}
func TestFloatErrors(t *testing.T) {
t.Parallel()
singletonErrors(t, "Float", "1.0", "llama")
}
func TestMap(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{
"Map[one]": {"1"},
"Map[two]": {"2"},
"Map[three]": {"3"},
}, &e)
if err != nil {
t.Error("Parse error in map: ", err)
}
for k, v := range map[string]int{"one": 1, "two": 2, "three": 3} {
if mv, ok := e.Map[k]; !ok {
t.Errorf("Key %q not in map", k)
} else {
assertEqual(t, "Map["+k+"]", v, mv)
}
}
}
func TestMapTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"AMap[one]": {"1"}}, &e)
if err != nil {
t.Error("Parse error for typed map")
}
assertEqual(t, "e.AMap[one]", MyInt(1), e.AMap[MyString("one")])
}
func TestMapErrors(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Map[]": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing empty map key")
}
err = Parse(url.Values{"Map": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing map without key")
}
err = Parse(url.Values{"Map[": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing map with malformed key")
}
}
func testPtr(t *testing.T, key, in string, out interface{}) {
e := Everything{}
err := Parse(url.Values{key: {in}}, &e)
if err != nil {
t.Errorf("Parse error while parsing pointer e.%s: %v", key, err)
}
fieldKey := key
if i := strings.IndexRune(fieldKey, '['); i >= 0 {
fieldKey = fieldKey[:i]
}
v := reflect.ValueOf(e).FieldByName(fieldKey)
if v.IsNil() {
t.Errorf("Expected param to allocate pointer for e.%s", key)
} else {
assertEqual(t, "*e."+key, out, v.Elem().Interface())
}
}
func TestPtr(t *testing.T) {
t.Parallel()
testPtr(t, "PBool", "true", true)
testPtr(t, "PInt", "2", 2)
testPtr(t, "PUint", "2", uint(2))
testPtr(t, "PFloat", "2.0", 2.0)
testPtr(t, "PMap[llama]", "4", map[string]int{"llama": 4})
testPtr(t, "PSlice[]", "4", []int{4})
testPtr(t, "PString", "llama", "llama")
testPtr(t, "PStruct[B]", "2", Sub{0, 2})
testPtr(t, "PTime", testTimeString, testTime)
foo := 2
testPtr(t, "PPInt", "2", &foo)
}
func TestPtrTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"APtr": {"1"}}, &e)
if err != nil {
t.Error("Parse error for typed pointer")
}
assertEqual(t, "e.APtr", MyInt(1), *e.APtr)
}
func TestSlice(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Slice[]": {"3", "1", "4"}}, &e)
if err != nil {
t.Error("Parse error for slice")
}
if e.Slice == nil {
t.Fatal("Expected param to allocate a slice")
}
if len(e.Slice) != 3 {
t.Fatal("Expected a slice of length 3")
}
assertEqual(t, "e.Slice[0]", 3, e.Slice[0])
assertEqual(t, "e.Slice[1]", 1, e.Slice[1])
assertEqual(t, "e.Slice[2]", 4, e.Slice[2])
}
func TestSliceTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"ASlice[]": {"3", "1", "4"}}, &e)
if err != nil {
t.Error("Parse error for typed slice")
}
if e.ASlice == nil {
t.Fatal("Expected param to allocate a slice")
}
if len(e.ASlice) != 3 {
t.Fatal("Expected a slice of length 3")
}
assertEqual(t, "e.ASlice[0]", MyInt(3), e.ASlice[0])
assertEqual(t, "e.ASlice[1]", MyInt(1), e.ASlice[1])
assertEqual(t, "e.ASlice[2]", MyInt(4), e.ASlice[2])
}
func TestSliceErrors(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Slice": {"1"}}, &e)
if err == nil {
t.Error("expected error parsing slice without key")
}
err = Parse(url.Values{"Slice[llama]": {"1"}}, &e)
if err == nil {
t.Error("expected error parsing slice with string key")
}
err = Parse(url.Values{"Slice[": {"1"}}, &e)
if err == nil {
t.Error("expected error parsing malformed slice key")
}
}
var stringAnswer = "This is the world's best string"
func TestString(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"String": {stringAnswer}}, &e)
if err != nil {
t.Error("Parse error in string: ", err)
}
assertEqual(t, "e.String", stringAnswer, e.String)
}
func TestStringTyped(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"AString": {"llama"}}, &e)
if err != nil {
t.Error("Parse error for typed string")
}
assertEqual(t, "e.AString", MyString("llama"), e.AString)
}
func TestStruct(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{
"Struct[A]": {"1"},
}, &e)
if err != nil {
t.Error("Parse error in struct: ", err)
}
assertEqual(t, "e.Struct.A", 1, e.Struct.A)
assertEqual(t, "e.Struct.B", 0, e.Struct.B)
err = Parse(url.Values{
"Struct[A]": {"4"},
"Struct[B]": {"2"},
}, &e)
if err != nil {
t.Error("Parse error in struct: ", err)
}
assertEqual(t, "e.Struct.A", 4, e.Struct.A)
assertEqual(t, "e.Struct.B", 2, e.Struct.B)
}
func TestStructErrors(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Struct[]": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing empty struct key")
}
err = Parse(url.Values{"Struct": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing struct without key")
}
err = Parse(url.Values{"Struct[": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing malformed struct key")
}
err = Parse(url.Values{"Struct[C]": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing unknown")
}
}
func TestTextUnmarshaler(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Time": {testTimeString}}, &e)
if err != nil {
t.Error("parse error for TextUnmarshaler (Time): ", err)
}
assertEqual(t, "e.Time", testTime, e.Time)
}
func TestTextUnmarshalerError(t *testing.T) {
t.Parallel()
e := Everything{}
err := Parse(url.Values{"Time": {"llama"}}, &e)
if err == nil {
t.Error("expected error parsing llama as time")
}
}