1
0
mirror of https://github.com/astaxie/beego.git synced 2024-06-28 02:54:14 +00:00

Merge branch 'astaxie/develop' into iniSaveErrorFix

# Conflicts:
#	config/ini_test.go
This commit is contained in:
ysqi 2016-01-24 11:37:43 +08:00
commit cf055c9db2
9 changed files with 219 additions and 123 deletions

View File

@ -106,3 +106,41 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) {
} }
return adapter.ParseData(data) return adapter.ParseData(data)
} }
// ParseBool returns the boolean value represented by the string.
//
// It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On,
// 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off.
// Any other value returns an error.
func ParseBool(val interface{}) (value bool, err error) {
if val != nil {
switch v := val.(type) {
case bool:
return v, nil
case string:
switch v {
case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
return true, nil
case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
return false, nil
}
case int8, int32, int64:
strV := fmt.Sprintf("%s", v)
if strV == "1" {
return true, nil
} else if strV == "0" {
return false, nil
}
case float64:
if v == 1 {
return true, nil
} else if v == 0 {
return false, nil
}
}
return false, fmt.Errorf("parsing %q: invalid syntax", val)
} else {
return false, fmt.Errorf("parsing <nil>: invalid syntax")
}
}

View File

@ -82,7 +82,7 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
} }
func (c *fakeConfigContainer) Bool(key string) (bool, error) { func (c *fakeConfigContainer) Bool(key string) (bool, error) {
return strconv.ParseBool(c.getData(key)) return ParseBool(c.getData(key))
} }
func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {

View File

@ -195,7 +195,7 @@ type IniConfigContainer struct {
// Bool returns the boolean value for a given key. // Bool returns the boolean value for a given key.
func (c *IniConfigContainer) Bool(key string) (bool, error) { func (c *IniConfigContainer) Bool(key string) (bool, error) {
return strconv.ParseBool(c.getdata(key)) return ParseBool(c.getdata(key))
} }
// DefaultBool returns the boolean value for a given key. // DefaultBool returns the boolean value for a given key.

View File

@ -15,12 +15,17 @@
package config package config
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"strings"
"testing" "testing"
) )
var inicontext = ` func TestIni(t *testing.T) {
var (
inicontext = `
;comment one ;comment one
#comment two #comment two
appname = beeapi appname = beeapi
@ -30,6 +35,13 @@ PI = 3.1415976
runmode = "dev" runmode = "dev"
autorender = false autorender = false
copyrequestbody = true copyrequestbody = true
session= on
cookieon= off
newreg = OFF
needlogin = ON
enableSession = Y
enableCookie = N
flag = 1
[demo] [demo]
key1="asta" key1="asta"
key2 = "xie" key2 = "xie"
@ -37,7 +49,31 @@ CaseInsensitive = true
peers = one;two;three peers = one;two;three
` `
func TestIni(t *testing.T) { keyValue = map[string]interface{}{
"appname": "beeapi",
"httpport": 8080,
"mysqlport": int64(3600),
"pi": 3.1415976,
"runmode": "dev",
"autorender": false,
"copyrequestbody": true,
"session": true,
"cookieon": false,
"newreg": false,
"needlogin": true,
"enableSession": true,
"enableCookie": false,
"flag": true,
"demo::key1": "asta",
"demo::key2": "xie",
"demo::CaseInsensitive": true,
"demo::peers": []string{"one", "two", "three"},
"null": "",
"demo2::key1": "",
"error": "",
}
)
f, err := os.Create("testini.conf") f, err := os.Create("testini.conf")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -53,31 +89,31 @@ func TestIni(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if iniconf.String("appname") != "beeapi" { for k, v := range keyValue {
t.Fatal("appname not equal to beeapi") var err error
} var value interface{}
if port, err := iniconf.Int("httpport"); err != nil || port != 8080 { switch v.(type) {
t.Error(port) case int:
t.Fatal(err) value, err = iniconf.Int(k)
} case int64:
if port, err := iniconf.Int64("mysqlport"); err != nil || port != 3600 { value, err = iniconf.Int64(k)
t.Error(port) case float64:
t.Fatal(err) value, err = iniconf.Float(k)
} case bool:
if pi, err := iniconf.Float("PI"); err != nil || pi != 3.1415976 { value, err = iniconf.Bool(k)
t.Error(pi) case []string:
t.Fatal(err) value = iniconf.Strings(k)
} case string:
if iniconf.String("runmode") != "dev" { value = iniconf.String(k)
t.Fatal("runmode not equal to dev") default:
} value, err = iniconf.DIY(k)
if v, err := iniconf.Bool("autorender"); err != nil || v != false { }
t.Error(v) if err != nil {
t.Fatal(err) t.Fatalf("get key %q value fail,err %s", k, err)
} } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
if v, err := iniconf.Bool("copyrequestbody"); err != nil || v != true { t.Fatalf("get key %q value, want %v got %v .", k, v, value)
t.Error(v) }
t.Fatal(err)
} }
if err = iniconf.Set("name", "astaxie"); err != nil { if err = iniconf.Set("name", "astaxie"); err != nil {
t.Fatal(err) t.Fatal(err)
@ -85,21 +121,6 @@ func TestIni(t *testing.T) {
if iniconf.String("name") != "astaxie" { if iniconf.String("name") != "astaxie" {
t.Fatal("get name error") t.Fatal("get name error")
} }
if iniconf.String("demo::key1") != "asta" {
t.Fatal("get demo.key1 error")
}
if iniconf.String("demo::key2") != "xie" {
t.Fatal("get demo.key2 error")
}
if v, err := iniconf.Bool("demo::caseinsensitive"); err != nil || v != true {
t.Fatal("get demo.caseinsensitive error")
}
if data := iniconf.Strings("demo::peers"); len(data) != 3 {
t.Fatal("get strings error", data)
} else if data[0] != "one" {
t.Fatal("get first params error not equat to one")
}
} }
@ -121,7 +142,8 @@ httpport = 8080
name = mysql name = mysql
` `
saveResult = `app=app saveResult = `
app=app
#comment one #comment one
#comment two #comment two
# comment three # comment three
@ -134,7 +156,6 @@ httpport=8080
# db type name # db type name
# suport mysql,sqlserver # suport mysql,sqlserver
name=mysql name=mysql
` `
) )
cfg, err := NewConfigData("ini", []byte(inicontext)) cfg, err := NewConfigData("ini", []byte(inicontext))
@ -149,7 +170,14 @@ name=mysql
if data, err := ioutil.ReadFile(name); err != nil { if data, err := ioutil.ReadFile(name); err != nil {
t.Fatal(err) t.Fatal(err)
} else if string(data) != saveResult { } else {
t.Fatal("different after save ini config file.") cfgData := string(data)
datas := strings.Split(saveResult, "\n")
for _, line := range datas {
if strings.Contains(cfgData, line+"\n") == false {
t.Fatalf("different after save ini config file. need contains %q", line)
}
}
} }
} }

View File

@ -17,6 +17,7 @@ package config
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"strings" "strings"
@ -70,12 +71,9 @@ type JSONConfigContainer struct {
func (c *JSONConfigContainer) Bool(key string) (bool, error) { func (c *JSONConfigContainer) Bool(key string) (bool, error) {
val := c.getData(key) val := c.getData(key)
if val != nil { if val != nil {
if v, ok := val.(bool); ok { return ParseBool(val)
return v, nil
}
return false, errors.New("not bool value")
} }
return false, errors.New("not exist key:" + key) return false, fmt.Errorf("not exist key: %q", key)
} }
// DefaultBool return the bool value if has no error // DefaultBool return the bool value if has no error

View File

@ -15,34 +15,14 @@
package config package config
import ( import (
"fmt"
"os" "os"
"testing" "testing"
) )
var jsoncontext = `{ func TestJsonStartsWithArray(t *testing.T) {
"appname": "beeapi",
"testnames": "foo;bar",
"httpport": 8080,
"mysqlport": 3600,
"PI": 3.1415976,
"runmode": "dev",
"autorender": false,
"copyrequestbody": true,
"database": {
"host": "host",
"port": "port",
"database": "database",
"username": "username",
"password": "password",
"conns":{
"maxconnection":12,
"autoconnect":true,
"connectioninfo":"info"
}
}
}`
var jsoncontextwitharray = `[ const jsoncontextwitharray = `[
{ {
"url": "user", "url": "user",
"serviceAPI": "http://www.test.com/user" "serviceAPI": "http://www.test.com/user"
@ -52,8 +32,6 @@ var jsoncontextwitharray = `[
"serviceAPI": "http://www.test.com/employee" "serviceAPI": "http://www.test.com/employee"
} }
]` ]`
func TestJsonStartsWithArray(t *testing.T) {
f, err := os.Create("testjsonWithArray.conf") f, err := os.Create("testjsonWithArray.conf")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -90,6 +68,64 @@ func TestJsonStartsWithArray(t *testing.T) {
} }
func TestJson(t *testing.T) { func TestJson(t *testing.T) {
var (
jsoncontext = `{
"appname": "beeapi",
"testnames": "foo;bar",
"httpport": 8080,
"mysqlport": 3600,
"PI": 3.1415976,
"runmode": "dev",
"autorender": false,
"copyrequestbody": true,
"session": "on",
"cookieon": "off",
"newreg": "OFF",
"needlogin": "ON",
"enableSession": "Y",
"enableCookie": "N",
"flag": 1,
"database": {
"host": "host",
"port": "port",
"database": "database",
"username": "username",
"password": "password",
"conns":{
"maxconnection":12,
"autoconnect":true,
"connectioninfo":"info"
}
}
}`
keyValue = map[string]interface{}{
"appname": "beeapi",
"testnames": []string{"foo", "bar"},
"httpport": 8080,
"mysqlport": int64(3600),
"PI": 3.1415976,
"runmode": "dev",
"autorender": false,
"copyrequestbody": true,
"session": true,
"cookieon": false,
"newreg": false,
"needlogin": true,
"enableSession": true,
"enableCookie": false,
"flag": true,
"database::host": "host",
"database::port": "port",
"database::database": "database",
"database::password": "password",
"database::conns::maxconnection": 12,
"database::conns::autoconnect": true,
"database::conns::connectioninfo": "info",
"unknown": "",
}
)
f, err := os.Create("testjson.conf") f, err := os.Create("testjson.conf")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -105,37 +141,32 @@ func TestJson(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if jsonconf.String("appname") != "beeapi" {
t.Fatal("appname not equal to beeapi") for k, v := range keyValue {
} var err error
if port, err := jsonconf.Int("httpport"); err != nil || port != 8080 { var value interface{}
t.Error(port) switch v.(type) {
t.Fatal(err) case int:
} value, err = jsonconf.Int(k)
if port, err := jsonconf.Int64("mysqlport"); err != nil || port != 3600 { case int64:
t.Error(port) value, err = jsonconf.Int64(k)
t.Fatal(err) case float64:
} value, err = jsonconf.Float(k)
if pi, err := jsonconf.Float("PI"); err != nil || pi != 3.1415976 { case bool:
t.Error(pi) value, err = jsonconf.Bool(k)
t.Fatal(err) case []string:
} value = jsonconf.Strings(k)
if jsonconf.String("runmode") != "dev" { case string:
t.Fatal("runmode not equal to dev") value = jsonconf.String(k)
} default:
if v := jsonconf.Strings("unknown"); len(v) > 0 { value, err = jsonconf.DIY(k)
t.Fatal("unknown strings, the length should be 0") }
} if err != nil {
if v := jsonconf.Strings("testnames"); len(v) != 2 { t.Fatalf("get key %q value fatal,%V err %s", k, v, err)
t.Fatal("testnames length should be 2") } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
} t.Fatalf("get key %q value, want %v got %v .", k, v, value)
if v, err := jsonconf.Bool("autorender"); err != nil || v != false { }
t.Error(v)
t.Fatal(err)
}
if v, err := jsonconf.Bool("copyrequestbody"); err != nil || v != true {
t.Error(v)
t.Fatal(err)
} }
if err = jsonconf.Set("name", "astaxie"); err != nil { if err = jsonconf.Set("name", "astaxie"); err != nil {
t.Fatal(err) t.Fatal(err)
@ -143,15 +174,7 @@ func TestJson(t *testing.T) {
if jsonconf.String("name") != "astaxie" { if jsonconf.String("name") != "astaxie" {
t.Fatal("get name error") t.Fatal("get name error")
} }
if jsonconf.String("database::host") != "host" {
t.Fatal("get database::host error")
}
if jsonconf.String("database::conns::connectioninfo") != "info" {
t.Fatal("get database::conns::connectioninfo error")
}
if maxconnection, err := jsonconf.Int("database::conns::maxconnection"); err != nil || maxconnection != 12 {
t.Fatal("get database::conns::maxconnection error")
}
if db, err := jsonconf.DIY("database"); err != nil { if db, err := jsonconf.DIY("database"); err != nil {
t.Fatal(err) t.Fatal(err)
} else if m, ok := db.(map[string]interface{}); !ok { } else if m, ok := db.(map[string]interface{}); !ok {

View File

@ -92,7 +92,11 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key. // Bool returns the boolean value for a given key.
func (c *ConfigContainer) Bool(key string) (bool, error) { func (c *ConfigContainer) Bool(key string) (bool, error) {
return strconv.ParseBool(c.data[key].(string)) if v, ok := c.data[key]; ok {
return config.ParseBool(v)
} else {
return false, fmt.Errorf("not exist key: %q", key)
}
} }
// DefaultBool return the bool value if has no error // DefaultBool return the bool value if has no error

View File

@ -121,10 +121,11 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key. // Bool returns the boolean value for a given key.
func (c *ConfigContainer) Bool(key string) (bool, error) { func (c *ConfigContainer) Bool(key string) (bool, error) {
if v, ok := c.data[key].(bool); ok { if v, ok := c.data[key]; ok {
return v, nil return config.ParseBool(v)
} else {
return false, fmt.Errorf("not exist key: %q", key)
} }
return false, errors.New("not bool value")
} }
// DefaultBool return the bool value if has no error // DefaultBool return the bool value if has no error

View File

@ -420,7 +420,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
if len(strs) == 2 { if len(strs) == 2 {
ctx.Input.SetParam(":ext", strs[1]) ctx.Input.SetParam(":ext", strs[1])
} }
ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[index:len(wildcardValues)-1]...), strs[0])) if index > (len(wildcardValues) - 1) {
ctx.Input.SetParam(":path", "")
} else {
ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[index:len(wildcardValues)-1]...), strs[0]))
}
return true return true
} }
// match :id // match :id