From 1c69214142509ef25322107aa0562f4bc756defc Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Tue, 2 Feb 2021 23:25:41 +0800 Subject: [PATCH] Error code for cache module --- ERROR_SPECIFICATION.md | 4 + client/cache/cache.go | 7 +- client/cache/calc_utils.go | 39 +++--- client/cache/calc_utils_test.go | 207 ++++++++------------------------ client/cache/error_code.go | 48 ++++++++ client/cache/file.go | 33 +++-- client/cache/module.go | 17 +++ 7 files changed, 171 insertions(+), 184 deletions(-) create mode 100644 client/cache/error_code.go create mode 100644 client/cache/module.go diff --git a/ERROR_SPECIFICATION.md b/ERROR_SPECIFICATION.md index cf2f94b2..68a04bd1 100644 --- a/ERROR_SPECIFICATION.md +++ b/ERROR_SPECIFICATION.md @@ -1 +1,5 @@ # Error Module + +## Module code +- httplib 1 +- cache 2 \ No newline at end of file diff --git a/client/cache/cache.go b/client/cache/cache.go index 70c81697..3ac1aa73 100644 --- a/client/cache/cache.go +++ b/client/cache/cache.go @@ -33,8 +33,9 @@ package cache import ( "context" - "fmt" "time" + + "github.com/beego/beego/v2/core/berror" ) // Cache interface contains all behaviors for cache adapter. @@ -78,7 +79,7 @@ var adapters = make(map[string]Instance) // it panics. func Register(name string, adapter Instance) { if adapter == nil { - panic("cache: Register adapter is nil") + panic(berror.Error(NilCacheAdapter, "cache: Register adapter is nil").Error()) } if _, ok := adapters[name]; ok { panic("cache: Register called twice for adapter " + name) @@ -92,7 +93,7 @@ func Register(name string, adapter Instance) { func NewCache(adapterName, config string) (adapter Cache, err error) { instanceFunc, ok := adapters[adapterName] if !ok { - err = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName) + err = berror.Errorf(UnknownAdapter, "cache: unknown adapter name %s (forgot to import?)", adapterName) return } adapter = instanceFunc() diff --git a/client/cache/calc_utils.go b/client/cache/calc_utils.go index 733e2fc2..e18946c1 100644 --- a/client/cache/calc_utils.go +++ b/client/cache/calc_utils.go @@ -1,46 +1,55 @@ package cache import ( - "fmt" "math" + + "github.com/beego/beego/v2/core/berror" ) +var ( + ErrIncrementOverflow = berror.Error(IncrementOverflow, "this incr invocation will overflow.") + ErrDecrementOverflow = berror.Error(DecrementOverflow, "this decr invocation will overflow.") + ErrNotIntegerType = berror.Error(NotIntegerType, "item val is not (u)int (u)int32 (u)int64") +) + + + func incr(originVal interface{}) (interface{}, error) { switch val := originVal.(type) { case int: tmp := val + 1 if val > 0 && tmp < 0 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return tmp, nil case int32: if val == math.MaxInt32 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return val + 1, nil case int64: if val == math.MaxInt64 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return val + 1, nil case uint: tmp := val + 1 if tmp < val { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return tmp, nil case uint32: if val == math.MaxUint32 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return val + 1, nil case uint64: if val == math.MaxUint64 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrIncrementOverflow } return val + 1, nil default: - return nil, fmt.Errorf("item val is not (u)int (u)int32 (u)int64") + return nil, ErrNotIntegerType } } @@ -49,35 +58,35 @@ func decr(originVal interface{}) (interface{}, error) { case int: tmp := val - 1 if val < 0 && tmp > 0 { - return nil, fmt.Errorf("decrement would overflow") + return nil, ErrDecrementOverflow } return tmp, nil case int32: if val == math.MinInt32 { - return nil, fmt.Errorf("decrement would overflow") + return nil, ErrDecrementOverflow } return val - 1, nil case int64: if val == math.MinInt64 { - return nil, fmt.Errorf("decrement would overflow") + return nil, ErrDecrementOverflow } return val - 1, nil case uint: if val == 0 { - return nil, fmt.Errorf("decrement would overflow") + return nil, ErrDecrementOverflow } return val - 1, nil case uint32: if val == 0 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrDecrementOverflow } return val - 1, nil case uint64: if val == 0 { - return nil, fmt.Errorf("increment would overflow") + return nil, ErrDecrementOverflow } return val - 1, nil default: - return nil, fmt.Errorf("item val is not (u)int (u)int32 (u)int64") + return nil, ErrNotIntegerType } } diff --git a/client/cache/calc_utils_test.go b/client/cache/calc_utils_test.go index e81c463b..1f8d3377 100644 --- a/client/cache/calc_utils_test.go +++ b/client/cache/calc_utils_test.go @@ -4,6 +4,8 @@ import ( "math" "strconv" "testing" + + "github.com/stretchr/testify/assert" ) func TestIncr(t *testing.T) { @@ -11,116 +13,65 @@ func TestIncr(t *testing.T) { var originVal interface{} = int(1) var updateVal interface{} = int(2) val, err := incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(int(1<<(strconv.IntSize-1) - 1)) - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrIncrementOverflow, err) // int32 originVal = int32(1) updateVal = int32(2) val, err = incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(int32(math.MaxInt32)) - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrIncrementOverflow, err) // int64 originVal = int64(1) updateVal = int64(2) val, err = incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(int64(math.MaxInt64)) - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrIncrementOverflow, err) // uint originVal = uint(1) updateVal = uint(2) val, err = incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } + + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(uint(1<<(strconv.IntSize) - 1)) - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrIncrementOverflow, err) // uint32 originVal = uint32(1) updateVal = uint32(2) val, err = incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(uint32(math.MaxUint32)) - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrIncrementOverflow, err) // uint64 originVal = uint64(1) updateVal = uint64(2) val, err = incr(originVal) - if err != nil { - t.Errorf("incr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("incr failed, expect %v, but %v actually", updateVal, val) - return - } - _, err = incr(uint64(math.MaxUint64)) - if err == nil { - t.Error("incr failed") - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = incr(uint64(math.MaxUint64)) + assert.Equal(t, ErrIncrementOverflow, err) // other type _, err = incr("string") - if err == nil { - t.Error("incr failed") - return - } + assert.Equal(t, ErrNotIntegerType, err) } func TestDecr(t *testing.T) { @@ -128,114 +79,62 @@ func TestDecr(t *testing.T) { var originVal interface{} = int(2) var updateVal interface{} = int(1) val, err := decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } - _, err = decr(int(-1 << (strconv.IntSize - 1))) - if err == nil { - t.Error("decr failed") - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(int(-1 << (strconv.IntSize - 1))) + assert.Equal(t, ErrDecrementOverflow, err) // int32 originVal = int32(2) updateVal = int32(1) val, err = decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(int32(math.MinInt32)) - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrDecrementOverflow, err) // int64 originVal = int64(2) updateVal = int64(1) val, err = decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(int64(math.MinInt64)) - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrDecrementOverflow, err) // uint originVal = uint(2) updateVal = uint(1) val, err = decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(uint(0)) - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrDecrementOverflow, err) // uint32 originVal = uint32(2) updateVal = uint32(1) val, err = decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(uint32(0)) - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrDecrementOverflow, err) // uint64 originVal = uint64(2) updateVal = uint64(1) val, err = decr(originVal) - if err != nil { - t.Errorf("decr failed, err: %s", err.Error()) - return - } - if val != updateVal { - t.Errorf("decr failed, expect %v, but %v actually", updateVal, val) - return - } + assert.Nil(t, err) + assert.Equal(t, val, updateVal) + _, err = decr(uint64(0)) - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrDecrementOverflow, err) // other type _, err = decr("string") - if err == nil { - t.Error("decr failed") - return - } + assert.Equal(t, ErrNotIntegerType, err) } diff --git a/client/cache/error_code.go b/client/cache/error_code.go new file mode 100644 index 00000000..ea336d4d --- /dev/null +++ b/client/cache/error_code.go @@ -0,0 +1,48 @@ +// Copyright 2021 beego +// +// 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 cache + +import ( + "github.com/beego/beego/v2/core/berror" +) + +var NilCacheAdapter = berror.DefineCode(4002001, moduleName, "NilCacheAdapter", ` +It means that you register cache adapter by pass nil. +A cache adapter is an instance of Cache interface. +`) + +var DuplicateAdapter = berror.DefineCode(4002002, moduleName, "DuplicateAdapter", ` +You register two adapter with same name. In beego cache module, one name one adapter. +Once you got this error, please check the error stack, search adapter +`) + +var UnknownAdapter = berror.DefineCode(4002003, moduleName, "UnknownAdapter", ` +Unknown adapter, do you forget to register the adapter? +You must register adapter before use it. For example, if you want to use redis implementation, +you must import the cache/redis package. +`) + +var IncrementOverflow = berror.DefineCode(4002004, moduleName, "IncrementOverflow", ` +The increment operation will overflow. +`) + +var DecrementOverflow = berror.DefineCode(4002005, moduleName, "DecrementOverflow", ` +The decrement operation will overflow. +`) + +var NotIntegerType = berror.DefineCode(4002006, moduleName, "NotIntegerType", ` +The type of value is not (u)int (u)int32 (u)int64. +When you want to call Incr or Decr function of Cache API, you must confirm that the value's type is one of (u)int (u)int32 (u)int64. +`) \ No newline at end of file diff --git a/client/cache/file.go b/client/cache/file.go index 87e14b6c..3bf61c0f 100644 --- a/client/cache/file.go +++ b/client/cache/file.go @@ -73,22 +73,31 @@ func (fc *FileCache) StartAndGC(config string) error { if err != nil { return err } - if _, ok := cfg["CachePath"]; !ok { - cfg["CachePath"] = FileCachePath + + const cpKey = "CachePath" + const fsKey = "FileSuffix" + const dlKey = "DirectoryLevel" + const eeKey = "EmbedExpiry" + + if _, ok := cfg[cpKey]; !ok { + cfg[cpKey] = FileCachePath } - if _, ok := cfg["FileSuffix"]; !ok { - cfg["FileSuffix"] = FileCacheFileSuffix + + if _, ok := cfg[fsKey]; !ok { + cfg[fsKey] = FileCacheFileSuffix } - if _, ok := cfg["DirectoryLevel"]; !ok { - cfg["DirectoryLevel"] = strconv.Itoa(FileCacheDirectoryLevel) + + if _, ok := cfg[dlKey]; !ok { + cfg[dlKey] = strconv.Itoa(FileCacheDirectoryLevel) } - if _, ok := cfg["EmbedExpiry"]; !ok { - cfg["EmbedExpiry"] = strconv.FormatInt(int64(FileCacheEmbedExpiry.Seconds()), 10) + + if _, ok := cfg[eeKey]; !ok { + cfg[eeKey] = strconv.FormatInt(int64(FileCacheEmbedExpiry.Seconds()), 10) } - fc.CachePath = cfg["CachePath"] - fc.FileSuffix = cfg["FileSuffix"] - fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"]) - fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"]) + fc.CachePath = cfg[cpKey] + fc.FileSuffix = cfg[fsKey] + fc.DirectoryLevel, _ = strconv.Atoi(cfg[dlKey]) + fc.EmbedExpiry, _ = strconv.Atoi(cfg[eeKey]) fc.Init() return nil diff --git a/client/cache/module.go b/client/cache/module.go new file mode 100644 index 00000000..5a4e499e --- /dev/null +++ b/client/cache/module.go @@ -0,0 +1,17 @@ +// Copyright 2021 beego +// +// 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 cache + +const moduleName = "cache"