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 { | ||||
| 	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 { | ||||
|  | ||||
							
								
								
									
										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. | ||||
| // 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) | ||||
|  | ||||
| @ -21,6 +21,7 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| type fakeConfigContainer struct { | ||||
| 	BaseConfiger | ||||
| 	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. | ||||
| // 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. | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user