Merge pull request #4175 from flycash/ftr/config

Add more methods to Configer
This commit is contained in:
Ming Deng 2020-08-19 22:44:43 +08:00 committed by GitHub
commit e6ea307549
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 208 additions and 10 deletions

View File

@ -411,6 +411,7 @@ func LoadAppConfig(adapterName, configPath string) error {
}
type beegoAppConfig struct {
config.BaseConfiger
innerConfig config.Configer
}
@ -419,7 +420,7 @@ func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, err
if err != nil {
return nil, err
}
return &beegoAppConfig{ac}, nil
return &beegoAppConfig{innerConfig: ac}, nil
}
func (b *beegoAppConfig) Set(key, val string) error {

View File

@ -0,0 +1,71 @@
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
)
func TestBaseConfiger_DefaultBool(t *testing.T) {
bc := newBaseConfier("true")
assert.True(t, bc.DefaultBool("key1", false))
assert.True(t, bc.DefaultBool("key2", true))
}
func TestBaseConfiger_DefaultFloat(t *testing.T) {
bc := newBaseConfier("12.3")
assert.Equal(t, 12.3, bc.DefaultFloat("key1", 0.1))
assert.Equal(t, 0.1, bc.DefaultFloat("key2", 0.1))
}
func TestBaseConfiger_DefaultInt(t *testing.T) {
bc := newBaseConfier("10")
assert.Equal(t, 10, bc.DefaultInt("key1", 8))
assert.Equal(t, 8, bc.DefaultInt("key2", 8))
}
func TestBaseConfiger_DefaultInt64(t *testing.T) {
bc := newBaseConfier("64")
assert.Equal(t, int64(64), bc.DefaultInt64("key1", int64(8)))
assert.Equal(t, int64(8), bc.DefaultInt64("key2", int64(8)))
}
func TestBaseConfiger_DefaultString(t *testing.T) {
bc := newBaseConfier("Hello")
assert.Equal(t, "Hello", bc.DefaultString("key1", "world"))
assert.Equal(t, "world", bc.DefaultString("key2", "world"))
}
func TestBaseConfiger_DefaultStrings(t *testing.T) {
bc := newBaseConfier("Hello;world")
assert.Equal(t, []string{"Hello", "world"}, bc.DefaultStrings("key1", []string{"world"}))
assert.Equal(t, []string{"world"}, bc.DefaultStrings("key2", []string{"world"}))
}
func newBaseConfier(str1 string) *BaseConfiger {
return &BaseConfiger{
reader: func(key string) (string, error) {
if key == "key1" {
return str1, nil
} else {
return "", errors.New("mock error")
}
},
}
}

View File

@ -15,7 +15,7 @@
// Package config is used to parse config.
// Usage:
// import "github.com/astaxie/beego/config"
//Examples.
// Examples.
//
// cnf, err := config.NewConfig("ini", "config.conf")
//
@ -37,36 +37,157 @@
// cnf.DIY(key string) (interface{}, error)
// cnf.GetSection(section string) (map[string]string, error)
// cnf.SaveConfigFile(filename string) error
//More docs http://beego.me/docs/module/config.md
// More docs http://beego.me/docs/module/config.md
package config
import (
"errors"
"fmt"
"os"
"reflect"
"strconv"
"strings"
"time"
)
// Configer defines how to get and set value from configuration raw data.
type Configer interface {
Set(key, val string) error //support section::key type in given key when using ini type.
String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
Strings(key string) []string //get string slice
// support section::key type in given key when using ini type.
Set(key, val string) error
// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
String(key string) string
// get string slice
Strings(key string) []string
Int(key string) (int, error)
Int64(key string) (int64, error)
Bool(key string) (bool, error)
Float(key string) (float64, error)
DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
DefaultStrings(key string, defaultVal []string) []string //get string slice
// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
DefaultString(key string, defaultVal string) string
// get string slice
DefaultStrings(key string, defaultVal []string) []string
DefaultInt(key string, defaultVal int) int
DefaultInt64(key string, defaultVal int64) int64
DefaultBool(key string, defaultVal bool) bool
DefaultFloat(key string, defaultVal float64) float64
DIY(key string) (interface{}, error)
GetSection(section string) (map[string]string, error)
Unmarshaler(obj interface{}) error
Sub(key string) (Configer, error)
OnChange(fn func(cfg Configer))
// GetByPrefix(prefix string) ([]byte, error)
// GetSerializer() Serializer
SaveConfigFile(filename string) error
}
type BaseConfiger struct {
// The reader should support key like "a.b.c"
reader func(key string) (string, error)
}
func (c *BaseConfiger) Int(key string) (int, error) {
res, err := c.reader(key)
if err != nil {
return 0, err
}
return strconv.Atoi(res)
}
func (c *BaseConfiger) Int64(key string) (int64, error) {
res, err := c.reader(key)
if err != nil {
return 0, err
}
return strconv.ParseInt(res, 10, 64)
}
func (c *BaseConfiger) Bool(key string) (bool, error) {
res, err := c.reader(key)
if err != nil {
return false, err
}
return strconv.ParseBool(res)
}
func (c *BaseConfiger) Float(key string) (float64, error) {
res, err := c.reader(key)
if err != nil {
return 0, err
}
return strconv.ParseFloat(res, 64)
}
func (c *BaseConfiger) DefaultString(key string, defaultVal string) string {
if res := c.String(key); res != "" {
return res
}
return defaultVal
}
func (c *BaseConfiger) DefaultStrings(key string, defaultVal []string) []string {
if res := c.Strings(key); len(res) > 0 {
return res
}
return defaultVal
}
func (c *BaseConfiger) DefaultInt(key string, defaultVal int) int {
if res, err := c.Int(key); err == nil {
return res
}
return defaultVal
}
func (c *BaseConfiger) DefaultInt64(key string, defaultVal int64) int64 {
if res, err := c.Int64(key); err == nil {
return res
}
return defaultVal
}
func (c *BaseConfiger) DefaultBool(key string, defaultVal bool) bool {
if res, err := c.Bool(key); err == nil {
return res
}
return defaultVal
}
func (c *BaseConfiger) DefaultFloat(key string, defaultVal float64) float64 {
if res, err := c.Float(key); err == nil {
return res
}
return defaultVal
}
func (c *BaseConfiger) String(key string) string {
res, _ := c.reader(key)
return res
}
func (c *BaseConfiger) Strings(key string) []string {
res, err := c.reader(key)
if err != nil || res == "" {
return nil
}
return strings.Split(res, ";")
}
// TODO remove this before release v2.0.0
func (c *BaseConfiger) Unmarshaler(obj interface{}) error {
return errors.New("unsupported operation")
}
// TODO remove this before release v2.0.0
func (c *BaseConfiger) Sub(key string) (Configer, error) {
return nil, errors.New("unsupported operation")
}
// TODO remove this before release v2.0.0
func (c *BaseConfiger) OnChange(fn func(cfg Configer)) {
// do nothing
}
// Config is the adapter interface for parsing config file to get raw data to Configer.
type Config interface {
Parse(key string) (Configer, error)

View File

@ -21,6 +21,7 @@ import (
)
type fakeConfigContainer struct {
BaseConfiger
data map[string]string
}

View File

@ -225,6 +225,7 @@ func (ini *IniConfig) ParseData(data []byte) (Configer, error) {
// IniConfigContainer is a config which represents the ini configuration.
// When set and get value, support key as section:name type.
type IniConfigContainer struct {
BaseConfiger
data map[string]map[string]string // section=> key:val
sectionComment map[string]string // section : comment
keyComment map[string]string // id: []{comment, key...}; id 1 is for main comment.

View File

@ -69,6 +69,7 @@ func (js *JSONConfig) ParseData(data []byte) (config.Configer, error) {
// JSONConfigContainer is a config which represents the json configuration.
// Only when get value, support key as section:name type.
type JSONConfigContainer struct {
config.BaseConfiger
data map[string]interface{}
sync.RWMutex
}

View File

@ -74,6 +74,7 @@ func (xc *Config) ParseData(data []byte) (config.Configer, error) {
// ConfigContainer is a Config which represents the xml configuration.
type ConfigContainer struct {
config.BaseConfiger
data map[string]interface{}
sync.Mutex
}

View File

@ -118,6 +118,7 @@ func parseYML(buf []byte) (cnf map[string]interface{}, err error) {
// ConfigContainer is a config which represents the yaml configuration.
type ConfigContainer struct {
config.BaseConfiger
data map[string]interface{}
sync.RWMutex
}

View File

@ -115,7 +115,7 @@ func TestFilterOrmDecorator_Delete(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) []interface{} {
return func(ctx context.Context, inv *Invocation) []interface{} {
assert.Equal(t, "DeleteWithCtx", inv.Method)
assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "FILTER_TEST", inv.GetTableName())
@ -311,7 +311,7 @@ func TestFilterOrmDecorator_Raw(t *testing.T) {
assert.Nil(t, res)
}
func TestFilterOrmDecorator_ReadForUpdate(t *testing.T) {
func TestFilterOrmDecorator_ReadForUpdate(t *testing.T) {
register()
o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter {