Merge pull request #4175 from flycash/ftr/config
Add more methods to Configer
This commit is contained in:
		
						commit
						e6ea307549
					
				| @ -411,6 +411,7 @@ func LoadAppConfig(adapterName, configPath string) error { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type beegoAppConfig struct { | type beegoAppConfig struct { | ||||||
|  | 	config.BaseConfiger | ||||||
| 	innerConfig config.Configer | 	innerConfig config.Configer | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -419,7 +420,7 @@ func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, err | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return &beegoAppConfig{ac}, nil | 	return &beegoAppConfig{innerConfig: ac}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (b *beegoAppConfig) Set(key, val string) error { | func (b *beegoAppConfig) Set(key, val string) error { | ||||||
|  | |||||||
							
								
								
									
										71
									
								
								pkg/config/base_config_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								pkg/config/base_config_test.go
									
									
									
									
									
										Normal 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") | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -15,7 +15,7 @@ | |||||||
| // Package config is used to parse config. | // Package config is used to parse config. | ||||||
| // Usage: | // Usage: | ||||||
| //  import "github.com/astaxie/beego/config" | //  import "github.com/astaxie/beego/config" | ||||||
| //Examples. | // Examples. | ||||||
| // | // | ||||||
| //  cnf, err := config.NewConfig("ini", "config.conf") | //  cnf, err := config.NewConfig("ini", "config.conf") | ||||||
| // | // | ||||||
| @ -37,36 +37,157 @@ | |||||||
| //  cnf.DIY(key string) (interface{}, error) | //  cnf.DIY(key string) (interface{}, error) | ||||||
| //  cnf.GetSection(section string) (map[string]string, error) | //  cnf.GetSection(section string) (map[string]string, error) | ||||||
| //  cnf.SaveConfigFile(filename 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 | package config | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"reflect" | 	"reflect" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Configer defines how to get and set value from configuration raw data. | // Configer defines how to get and set value from configuration raw data. | ||||||
| type Configer interface { | type Configer interface { | ||||||
| 	Set(key, val string) error   //support section::key type in given key when using ini type. | 	// 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. | 	Set(key, val string) error | ||||||
| 	Strings(key 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. | ||||||
|  | 	String(key string) string | ||||||
|  | 	// get string slice | ||||||
|  | 	Strings(key string) []string | ||||||
| 	Int(key string) (int, error) | 	Int(key string) (int, error) | ||||||
| 	Int64(key string) (int64, error) | 	Int64(key string) (int64, error) | ||||||
| 	Bool(key string) (bool, error) | 	Bool(key string) (bool, error) | ||||||
| 	Float(key string) (float64, 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. | 	// 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 | 	DefaultString(key string, defaultVal string) string | ||||||
|  | 	// get string slice | ||||||
|  | 	DefaultStrings(key string, defaultVal []string) []string | ||||||
| 	DefaultInt(key string, defaultVal int) int | 	DefaultInt(key string, defaultVal int) int | ||||||
| 	DefaultInt64(key string, defaultVal int64) int64 | 	DefaultInt64(key string, defaultVal int64) int64 | ||||||
| 	DefaultBool(key string, defaultVal bool) bool | 	DefaultBool(key string, defaultVal bool) bool | ||||||
| 	DefaultFloat(key string, defaultVal float64) float64 | 	DefaultFloat(key string, defaultVal float64) float64 | ||||||
| 	DIY(key string) (interface{}, error) | 	DIY(key string) (interface{}, error) | ||||||
| 	GetSection(section string) (map[string]string, 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 | 	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. | // Config is the adapter interface for parsing config file to get raw data to Configer. | ||||||
| type Config interface { | type Config interface { | ||||||
| 	Parse(key string) (Configer, error) | 	Parse(key string) (Configer, error) | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type fakeConfigContainer struct { | type fakeConfigContainer struct { | ||||||
|  | 	BaseConfiger | ||||||
| 	data map[string]string | 	data map[string]string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -225,6 +225,7 @@ func (ini *IniConfig) ParseData(data []byte) (Configer, error) { | |||||||
| // IniConfigContainer is a config which represents the ini configuration. | // IniConfigContainer is a config which represents the ini configuration. | ||||||
| // When set and get value, support key as section:name type. | // When set and get value, support key as section:name type. | ||||||
| type IniConfigContainer struct { | type IniConfigContainer struct { | ||||||
|  | 	BaseConfiger | ||||||
| 	data           map[string]map[string]string // section=> key:val | 	data           map[string]map[string]string // section=> key:val | ||||||
| 	sectionComment map[string]string            // section : comment | 	sectionComment map[string]string            // section : comment | ||||||
| 	keyComment     map[string]string            // id: []{comment, key...}; id 1 is for main comment. | 	keyComment     map[string]string            // id: []{comment, key...}; id 1 is for main comment. | ||||||
|  | |||||||
| @ -69,6 +69,7 @@ func (js *JSONConfig) ParseData(data []byte) (config.Configer, error) { | |||||||
| // JSONConfigContainer is a config which represents the json configuration. | // JSONConfigContainer is a config which represents the json configuration. | ||||||
| // Only when get value, support key as section:name type. | // Only when get value, support key as section:name type. | ||||||
| type JSONConfigContainer struct { | type JSONConfigContainer struct { | ||||||
|  | 	config.BaseConfiger | ||||||
| 	data map[string]interface{} | 	data map[string]interface{} | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| } | } | ||||||
|  | |||||||
| @ -74,6 +74,7 @@ func (xc *Config) ParseData(data []byte) (config.Configer, error) { | |||||||
| 
 | 
 | ||||||
| // ConfigContainer is a Config which represents the xml configuration. | // ConfigContainer is a Config which represents the xml configuration. | ||||||
| type ConfigContainer struct { | type ConfigContainer struct { | ||||||
|  | 	config.BaseConfiger | ||||||
| 	data map[string]interface{} | 	data map[string]interface{} | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| } | } | ||||||
|  | |||||||
| @ -118,6 +118,7 @@ func parseYML(buf []byte) (cnf map[string]interface{}, err error) { | |||||||
| 
 | 
 | ||||||
| // ConfigContainer is a config which represents the yaml configuration. | // ConfigContainer is a config which represents the yaml configuration. | ||||||
| type ConfigContainer struct { | type ConfigContainer struct { | ||||||
|  | 	config.BaseConfiger | ||||||
| 	data map[string]interface{} | 	data map[string]interface{} | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| } | } | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ func TestFilterOrmDecorator_Delete(t *testing.T) { | |||||||
| 	register() | 	register() | ||||||
| 	o := &filterMockOrm{} | 	o := &filterMockOrm{} | ||||||
| 	od := NewFilterOrmDecorator(o, func(next Filter) Filter { | 	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, "DeleteWithCtx", inv.Method) | ||||||
| 			assert.Equal(t, 2, len(inv.Args)) | 			assert.Equal(t, 2, len(inv.Args)) | ||||||
| 			assert.Equal(t, "FILTER_TEST", inv.GetTableName()) | 			assert.Equal(t, "FILTER_TEST", inv.GetTableName()) | ||||||
| @ -311,7 +311,7 @@ func TestFilterOrmDecorator_Raw(t *testing.T) { | |||||||
| 	assert.Nil(t, res) | 	assert.Nil(t, res) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestFilterOrmDecorator_ReadForUpdate(t *testing.T)  { | func TestFilterOrmDecorator_ReadForUpdate(t *testing.T) { | ||||||
| 	register() | 	register() | ||||||
| 	o := &filterMockOrm{} | 	o := &filterMockOrm{} | ||||||
| 	od := NewFilterOrmDecorator(o, func(next Filter) Filter { | 	od := NewFilterOrmDecorator(o, func(next Filter) Filter { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user