From a908e4d4b1174ccd78215888fb551759cf814104 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 7 Jun 2019 22:27:37 +0800 Subject: [PATCH 01/24] fix issue in session initialization for ghttp.Server --- TODO.MD | 2 +- g/net/ghttp/ghttp_server_session.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO.MD b/TODO.MD index f68a8f50e..072b2c7d4 100644 --- a/TODO.MD +++ b/TODO.MD @@ -47,7 +47,7 @@ 1. gtimer增加DelayAdd*方法返回Entry对象,以便DelayAdd*的定时任务也能进行状态控制;gcron同理需要改进; 1. 改进gdb对pgsql/mssql/oracle的支持,使用方法覆盖的方式改进操作,而不是完全依靠正则替换的方式; 1. gdb的Cache缓存功能增加可自定义缓存接口,以便支持外部缓存功能,缓存接口可以通过io.ReadWriter接口实现; - +1. grpool增加支持阻塞添加任务接口; diff --git a/g/net/ghttp/ghttp_server_session.go b/g/net/ghttp/ghttp_server_session.go index 706b18e76..be2a6959f 100644 --- a/g/net/ghttp/ghttp_server_session.go +++ b/g/net/ghttp/ghttp_server_session.go @@ -58,7 +58,7 @@ func (s *Session) init() { // 否则执行初始化创建 s.id = s.request.Cookie.MakeSessionId() s.data = gmap.NewStrAnyMap() - s.server.sessions.Set(s.id, s.data, s.server.GetSessionMaxAge()) + s.server.sessions.Set(s.id, s.data, s.server.GetSessionMaxAge()*1000) } } From c0c97b76fb485dc04e7b55bcc4e877fbf6ffa5b7 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 7 Jun 2019 23:00:34 +0800 Subject: [PATCH 02/24] update lead string position for glog --- g/os/glog/glog_logger.go | 13 +++++++------ geg/os/glog/glog_line.go | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 7b9329c5f..5d6562d98 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -243,6 +243,13 @@ func (l *Logger) print(std io.Writer, lead string, value...interface{}) { if len(timeFormat) > 0 { buffer.WriteString(time.Now().Format(timeFormat)) } + // Lead string. + if len(lead) > 0 { + buffer.WriteString(lead) + if len(value) > 0 { + buffer.WriteByte(' ') + } + } // Caller path. callerPath := "" if l.flags & F_FILE_LONG > 0 { @@ -259,12 +266,6 @@ func (l *Logger) print(std io.Writer, lead string, value...interface{}) { buffer.WriteString(l.prefix + " ") } } - if len(lead) > 0 { - buffer.WriteString(lead) - if len(value) > 0 { - buffer.WriteByte(' ') - } - } for k, v := range value { if k > 0 { buffer.WriteByte(' ') diff --git a/geg/os/glog/glog_line.go b/geg/os/glog/glog_line.go index 41d2e0779..ab28cb622 100644 --- a/geg/os/glog/glog_line.go +++ b/geg/os/glog/glog_line.go @@ -5,6 +5,6 @@ import ( ) func main() { - glog.Line().Println("this is the short file name with its line number") - glog.Line(true).Println("lone file name with line number") + glog.Line().Debug("this is the short file name with its line number") + glog.Line(true).Debug("lone file name with line number") } From f9826104d8f566bfe8455fa335e3b7ffcec6de4c Mon Sep 17 00:00:00 2001 From: John Date: Sat, 8 Jun 2019 19:25:20 +0800 Subject: [PATCH 03/24] improve gconv --- g/util/gconv/gconv_struct.go | 28 +++++++++++++++------ g/util/gconv/gconv_z_unit_struct_test.go | 32 +++++++++++++++++++----- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/g/util/gconv/gconv_struct.go b/g/util/gconv/gconv_struct.go index 8ffe29a09..d5cc119c4 100644 --- a/g/util/gconv/gconv_struct.go +++ b/g/util/gconv/gconv_struct.go @@ -157,7 +157,9 @@ func StructDeep(params interface{}, pointer interface{}, mapping...map[string]st trv := rv.Field(i) switch trv.Kind() { case reflect.Struct: - StructDeep(params, trv, mapping...) + if err := StructDeep(params, trv, mapping...); err != nil { + return err + } } } } @@ -239,7 +241,9 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er switch structFieldValue.Kind() { // 属性为结构体 case reflect.Struct: - Struct(value, structFieldValue) + if err := Struct(value, structFieldValue); err != nil { + structFieldValue.Set(reflect.ValueOf(value)) + } // 属性为数组类型 case reflect.Slice: fallthrough @@ -253,11 +257,15 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er for i := 0; i < v.Len(); i++ { if t.Kind() == reflect.Ptr { e := reflect.New(t.Elem()).Elem() - Struct(v.Index(i).Interface(), e) + if err := Struct(v.Index(i).Interface(), e); err != nil { + e.Set(reflect.ValueOf(v.Index(i).Interface())) + } a.Index(i).Set(e.Addr()) } else { e := reflect.New(t).Elem() - Struct(v.Index(i).Interface(), e) + if err := Struct(v.Index(i).Interface(), e); err != nil { + e.Set(reflect.ValueOf(v.Index(i).Interface())) + } a.Index(i).Set(e) } } @@ -267,11 +275,15 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er t := a.Index(0).Type() if t.Kind() == reflect.Ptr { e := reflect.New(t.Elem()).Elem() - Struct(value, e) + if err := Struct(value, e); err != nil { + e.Set(reflect.ValueOf(value)) + } a.Index(0).Set(e.Addr()) } else { e := reflect.New(t).Elem() - Struct(value, e) + if err := Struct(value, e); err != nil { + e.Set(reflect.ValueOf(value)) + } a.Index(0).Set(e) } } @@ -280,7 +292,9 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er // 属性为指针类型 case reflect.Ptr: e := reflect.New(structFieldValue.Type().Elem()).Elem() - Struct(value, e) + if err := Struct(value, e); err != nil { + e.Set(reflect.ValueOf(value)) + } structFieldValue.Set(e.Addr()) default: diff --git a/g/util/gconv/gconv_z_unit_struct_test.go b/g/util/gconv/gconv_z_unit_struct_test.go index 35d4274f8..0efe7987f 100644 --- a/g/util/gconv/gconv_z_unit_struct_test.go +++ b/g/util/gconv/gconv_z_unit_struct_test.go @@ -7,12 +7,12 @@ package gconv_test import ( - "github.com/gogf/gf/g" - "github.com/gogf/gf/g/os/gtime" - "github.com/gogf/gf/g/test/gtest" - "github.com/gogf/gf/g/util/gconv" - "testing" - "time" + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/os/gtime" + "github.com/gogf/gf/g/test/gtest" + "github.com/gogf/gf/g/util/gconv" + "testing" + "time" ) func Test_Struct_Basic1(t *testing.T) { @@ -104,6 +104,26 @@ func Test_Struct_Basic2(t *testing.T) { }) } +// 带有指针的基础类型属性 +func Test_Struct_Basic3(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Uid int + Name *string + } + user := new(User) + params := g.Map { + "uid" : 1, + "Name" : "john", + } + if err := gconv.Struct(params, user); err != nil { + gtest.Error(err) + } + gtest.Assert(user.Uid, 1) + gtest.Assert(*user.Name, "john") + }) +} + // slice类型属性的赋值 func Test_Struct_Attr_Slice(t *testing.T) { gtest.Case(t, func() { From 136ad3b0b527a233a1b92a8deee8453e634422bf Mon Sep 17 00:00:00 2001 From: John Date: Sat, 8 Jun 2019 19:38:46 +0800 Subject: [PATCH 04/24] add more unit test cases for hook feature of ghttp.Server --- g/net/ghttp/ghttp_unit_router_hook_test.go | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/g/net/ghttp/ghttp_unit_router_hook_test.go b/g/net/ghttp/ghttp_unit_router_hook_test.go index 3fb7bf3c2..581c10c8d 100644 --- a/g/net/ghttp/ghttp_unit_router_hook_test.go +++ b/g/net/ghttp/ghttp_unit_router_hook_test.go @@ -85,3 +85,36 @@ func Test_Router_Hook_Priority(t *testing.T) { }) } +func Test_Router_Hook_Multi(t *testing.T) { + p := ports.PopRand() + s := g.Server(p) + s.BindHandler("/multi-hook", func(r *ghttp.Request) { + r.Response.Write("show") + }) + + s.BindHookHandlerByMap("/multi-hook", map[string]ghttp.HandlerFunc { + "BeforeServe" : func(r *ghttp.Request) { + r.Response.Write("1") + }, + }) + s.BindHookHandlerByMap("/multi-hook", map[string]ghttp.HandlerFunc { + "BeforeServe" : func(r *ghttp.Request) { + r.Response.Write("2") + }, + }) + s.SetPort(p) + s.SetDumpRouteMap(false) + s.Start() + defer s.Shutdown() + + // 等待启动完成 + time.Sleep(time.Second) + gtest.Case(t, func() { + client := ghttp.NewClient() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) + + gtest.Assert(client.GetContent("/"), "Not Found") + gtest.Assert(client.GetContent("/multi-hook"), "12show") + }) +} + From e400a94ffb9ffb935bc38b3d681404242f2e6146 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 9 Jun 2019 10:33:16 +0800 Subject: [PATCH 05/24] improving grpool --- g/container/gchan/gchan.go | 8 +++++--- g/container/gqueue/gqueue.go | 6 +++--- g/os/grpool/grpool.go | 12 +++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/g/container/gchan/gchan.go b/g/container/gchan/gchan.go index 6b6be6da3..9e762162f 100644 --- a/g/container/gchan/gchan.go +++ b/g/container/gchan/gchan.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gchan provides graceful channel for safe operations. +// Package gchan provides graceful channel for no panic operations. // // It's safe to call Chan.Push/Close functions repeatedly. package gchan @@ -14,12 +14,13 @@ import ( "github.com/gogf/gf/g/container/gtype" ) +// Graceful channel. type Chan struct { channel chan interface{} closed *gtype.Bool } -// New creates a graceful channel with given limit. +// New creates a graceful channel with given . func New(limit int) *Chan { return &Chan { channel : make(chan interface{}, limit), @@ -31,7 +32,7 @@ func New(limit int) *Chan { // It is safe to be called repeatedly. func (c *Chan) Push(value interface{}) error { if c.closed.Val() { - return errors.New("closed") + return errors.New("channel is closed") } c.channel <- value return nil @@ -39,6 +40,7 @@ func (c *Chan) Push(value interface{}) error { // Pop pops value from channel. // If there's no value in channel, it would block to wait. +// If the channel is closed, it will return a nil value immediately. func (c *Chan) Pop() interface{} { return <- c.channel } diff --git a/g/container/gqueue/gqueue.go b/g/container/gqueue/gqueue.go index ea99c0c6f..9ec7b12c7 100644 --- a/g/container/gqueue/gqueue.go +++ b/g/container/gqueue/gqueue.go @@ -37,8 +37,8 @@ const ( ) // New returns an empty queue object. -// Optional parameter is used to limit the size of the queue, which is unlimited by default. -// When is given, the queue will be static and high performance which is comparable with stdlib chan. +// Optional parameter is used to limit the size of the queue, which is unlimited in default. +// When is given, the queue will be static and high performance which is comparable with stdlib channel. func New(limit...int) *Queue { q := &Queue { closed : make(chan struct{}, 0), @@ -103,7 +103,7 @@ func (q *Queue) Pop() interface{} { // Close closes the queue. // Notice: It would notify all goroutines return immediately, -// which are being blocked reading by Pop method. +// which are being blocked reading using Pop method. func (q *Queue) Close() { close(q.C) close(q.events) diff --git a/g/os/grpool/grpool.go b/g/os/grpool/grpool.go index 8d2bf116c..675e15193 100644 --- a/g/os/grpool/grpool.go +++ b/g/os/grpool/grpool.go @@ -14,10 +14,11 @@ import ( // Goroutine Pool type Pool struct { - limit int // Max goroutine count limit. - count *gtype.Int // Current running goroutine count. - list *glist.List // Job list. - closed *gtype.Bool // Is pool closed or not. + limit int // Max goroutine count limit. + count *gtype.Int // Current running goroutine count. + list *glist.List // Job list for asynchronous job adding purpose. + closed *gtype.Bool // Is pool closed or not. + workers chan struct{} // Goroutine workers using channel to implements blocking feature. } // Default goroutine pool. @@ -33,7 +34,7 @@ func New(limit...int) *Pool { list : glist.New(), closed : gtype.NewBool(), } - if len(limit) > 0 { + if len(limit) > 0 && limit[0] > 0 { p.limit = limit[0] } return p @@ -72,6 +73,7 @@ func (p *Pool) Add(f func()) { p.fork() } + // Size returns current goroutine count of the pool. func (p *Pool) Size() int { return p.count.Val() From 0b8c9713e690fa68d640884c3b97128934fd4033 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 9 Jun 2019 10:37:35 +0800 Subject: [PATCH 06/24] improve grpool --- g/os/grpool/grpool.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/g/os/grpool/grpool.go b/g/os/grpool/grpool.go index 675e15193..9add6fe8b 100644 --- a/g/os/grpool/grpool.go +++ b/g/os/grpool/grpool.go @@ -14,11 +14,10 @@ import ( // Goroutine Pool type Pool struct { - limit int // Max goroutine count limit. - count *gtype.Int // Current running goroutine count. - list *glist.List // Job list for asynchronous job adding purpose. - closed *gtype.Bool // Is pool closed or not. - workers chan struct{} // Goroutine workers using channel to implements blocking feature. + limit int // Max goroutine count limit. + count *gtype.Int // Current running goroutine count. + list *glist.List // Job list for asynchronous job adding purpose. + closed *gtype.Bool // Is pool closed or not. } // Default goroutine pool. From cc0a385c22d841214c96dcde04514827201786e8 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 9 Jun 2019 11:56:58 +0800 Subject: [PATCH 07/24] RELEASE updates --- RELEASE.MD | 60 +++++++++++++++++++++++++++++++++++++++++++++ g/os/gtime/gtime.go | 2 -- geg/other/test.go | 16 +++--------- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/RELEASE.MD b/RELEASE.MD index 93ce84596..31a031b1a 100644 --- a/RELEASE.MD +++ b/RELEASE.MD @@ -1,3 +1,63 @@ +# `v1.7.0` +## 新功能/改进 +1. 重构改进`glog`模块: + - 去掉日志模块所有的锁机制,改为无锁设计,执行性能更加高效 + - 增加日志内容的异步输出特性:https://goframe.org/os/glog/async + - 增加日志输出内容的`Json`格式支持:https://goframe.org/os/glog/json + - 增加`Flags`额外特性支持,包括文件行号打印、自定义时间格式、异步输出等特性控制:https://goframe.org/os/glog/flags + - 增加`Writer`接口支持,便于开发者进行自定义的日志功能扩展,或者与第三方服务/模块对接集成:https://goframe.org/os/glog/writer + - 修改`SetStdPrint`方法名为`SetStdoutPrint` + - 修改链式方法`StdPrint`方法名为`Stdout` + - 标记淘汰`*fln`日志输出方法,`*f`方法支持自动的换行输出 + - 新增更多的链式方法支持:https://goframe.org/os/glog/chain +1. 重构改进`gmap`模块: + - 增加更多数据格式支持:`HashMap`/`ListMap`/`TreeMap` + - 简化类型名称,如`gmap.StringInterfaceMap`简化为`gmap.StrAnyMap` + - 改进`Map/Keys/Values`方法以提高性能 + - 修改`BatchSet`/`BatchRemove`方法名为`Sets`/`Removes` + - 新增更多功能方法支持:https://goframe.org/container/gmap/index +1. 改进`gtime`时间模块: + - 增加并完善更多的类`PHP`时间格式支持 + - 新增更多功能方法,如`FormatTo`/`LayoutTo`等等 + - 详见开发文档:https://goframe.org/os/gtime/index +1. 改进`gdb`数据库模块: + - 增加对继承结构体的数据转换支持:https://goframe.org/database/gdb/senior + - 新增`GetLastSql`方法,用以在调试模式下获取最近一条执行的SQL语句 + - 其他的细节处理改进 +1. 改进`gtcp`通信模块: + - 完善处理细节,提高通信性能; + - 增加`TLS`服务端/客户端通信支持:https://goframe.org/net/gtcp/tls + - 增加简单协议支持,便于开发者封包/解包,并解决粘包/半包问题:https://goframe.org/net/gtcp/conn/pkg + - TCP服务端增加`Close`方法 + - 更多细节查看开发文档:https://goframe.org/net/gtcp/index +1. 改进`gconv`类型转换模块 + - 修改`gconv.TimeDuration`转换方法名称为`gconv.Duration` + - 新增`gconv.StructDeep`及`gconv.MapDeep`方法,支持递归转换 + - 详见开发文档:https://goframe.org/util/gconv/struct +1. 改进`ghttp`模块: + - 日志输出增加`http/https`字段:https://goframe.org/net/ghttp/logs + - 新增`ghttp.Server.SetKeepAlive`设置方法,用以开启/关闭`KeepAlive`特性 + - 增加`ghttp.Request.GetUrl`方法,用以获取当前完整的URL请求地址 + - `ghttp.Client`客户端支持开发者自定义`Transport`属性,`ghttp.Client.Post`方法支持`浏览器模式`:https://goframe.org/net/ghttp/client +1. 新增`gtree`树形数据结构容器支持:https://goframe.org/container/gtree/index +1. 改进`gudp`通信模块,具体请参考开发文档:https://goframe.org/net/gudp/index +1. 改进`gcfg`配置管理模块,所有`Get*`方法增加默认值支持:https://goframe.org/os/gcfg/index +1. `gredis`模块新增`DoVar`/`ReceiveVar`方法以便于开发者对执行结果进行灵活的数据格式转换:https://goframe.org/database/gredis/index +1. `gcache`模块`BatchSet`/`BatchRemove`方法名修改为`Sets`/`Removes` +1. 改进`gjson`/`gparser`模块,增加更多方法:https://goframe.org/encoding/gjson/index +1. 改进`gfile.MainPkgPath`方法,以支持不同平台的开发环境; +1. 改进`grpool`协程池模块,提高执行性能:https://goframe.org/os/grpool/index +1. 改进`TryCatch`方法,当开发者不传递`Catch`参数时,默认抑制并忽略错误的处理 +1. 改进`gmlock`模块,增加`TryLockFunc`/`TryRLockFunc`方法,并且为`gmlock.Mutex`高级互斥锁对象增加`TryLockFunc`/`TryRLockFunc`方法 +1. 去除`gvar.VarRead`接口类型支持 + +## Bug Fix +1. 解决`gdb`模块与其他第三方`ORM`模块同时使用的冲突; +1. 修复`gcron.AddOnce`方法的细节逻辑问题; +1. 修复内部`empty`模块的`IsEmpty`方法对结构体属性的空校验错误; +1. 修复`gview`模板引擎的并发安全问题; +1. 修复`ghttp.Server`的SESSION初始化过期时间问题; + # `v1.6.0` (2019-04-09) ## 新功能/改进 diff --git a/g/os/gtime/gtime.go b/g/os/gtime/gtime.go index 5e45231a9..abd557567 100644 --- a/g/os/gtime/gtime.go +++ b/g/os/gtime/gtime.go @@ -5,8 +5,6 @@ // You can obtain one at https://github.com/gogf/gf. // Package gtime provides functionality for measuring and displaying time. -// -// 时间管理. package gtime import ( diff --git a/geg/other/test.go b/geg/other/test.go index 729ac6946..9f3000841 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,19 +1,11 @@ package main import ( - "github.com/gogf/gf/g" - "github.com/gogf/gf/g/net/ghttp" + "fmt" + "github.com/gogf/gf/g/os/gtime" ) func main() { - s := g.Server() - s.BindHandler("/", func(r *ghttp.Request) { - rs :="GF(Go Frame)是一款模块化、松耦合、生产级的Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、 并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、路由注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。" - //此行压测会提示map并发错误 webbench -c 8000 -t 60 http://IP 局域网两台机器测试 - r.Response.WriteTplContent(rs, g.Map{ - "Contentb": 1, - }) - }) - s.SetPort(8199) - s.Run() + fmt.Println(gtime.Now().Format("U")) + fmt.Println(gtime.Second()) } \ No newline at end of file From aa73c5ed530f50f5736bc900b957b93847337836 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Jun 2019 09:01:19 +0800 Subject: [PATCH 08/24] version updates --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 9dae0d748..ad997480a 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package gf -const VERSION = "v1.6.17" +const VERSION = "v1.7.0" const AUTHORS = "john" From 3a7268677424514fa09e05c55c8c77499c2402a3 Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 15:05:11 +0800 Subject: [PATCH 09/24] add gcrc test --- g/crypto/gcrc32/gcrc32_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/g/crypto/gcrc32/gcrc32_test.go b/g/crypto/gcrc32/gcrc32_test.go index 32f9a3094..27c301fbc 100644 --- a/g/crypto/gcrc32/gcrc32_test.go +++ b/g/crypto/gcrc32/gcrc32_test.go @@ -15,7 +15,7 @@ import ( "github.com/gogf/gf/g/test/gtest" ) -func TestEncrypt(t *testing.T) { +func TestEncryptString(t *testing.T) { gtest.Case(t, func() { s := "pibigstar" result := 693191136 @@ -25,3 +25,14 @@ func TestEncrypt(t *testing.T) { gtest.AssertEQ(int(encrypt2), result) }) } + +func TestEncrypt(t *testing.T) { + gtest.Case(t, func() { + s := "pibigstar" + result := 693191136 + encrypt1 := gcrc32.Encrypt(s) + encrypt2 := gcrc32.Encrypt([]byte(s)) + gtest.AssertEQ(int(encrypt1), result) + gtest.AssertEQ(int(encrypt2), result) + }) +} From d5d14b7efc73153d8ac17553c813d3be69961143 Mon Sep 17 00:00:00 2001 From: zdl <381897429@qq.com> Date: Mon, 10 Jun 2019 15:49:43 +0800 Subject: [PATCH 10/24] test gset TestSet_New --- g/container/gset/gset_z_unit_test.go | 262 ++++++++++++++------------- 1 file changed, 141 insertions(+), 121 deletions(-) diff --git a/g/container/gset/gset_z_unit_test.go b/g/container/gset/gset_z_unit_test.go index a0901a070..9ee7c192e 100644 --- a/g/container/gset/gset_z_unit_test.go +++ b/g/container/gset/gset_z_unit_test.go @@ -9,152 +9,172 @@ package gset_test import ( - "github.com/gogf/gf/g/container/garray" - "github.com/gogf/gf/g/container/gset" - "github.com/gogf/gf/g/test/gtest" - "testing" + "github.com/gogf/gf/g/container/garray" + "github.com/gogf/gf/g/container/gset" + "github.com/gogf/gf/g/test/gtest" + "testing" ) +func TestSet_New(t *testing.T) { + gtest.Case(t, func() { + s := gset.New() + s.Add(1).Add(1).Add(2) + s.Add([]interface{}{3, 4}...) + gtest.Assert(s.Size(), 4) + gtest.AssertIN(1, s.Slice()) + gtest.AssertIN(2, s.Slice()) + gtest.AssertIN(3, s.Slice()) + gtest.AssertIN(4, s.Slice()) + gtest.AssertNI(0, s.Slice()) + gtest.Assert(s.Contains(4), true) + gtest.Assert(s.Contains(5), false) + s.Remove(1) + gtest.Assert(s.Size(), 3) + s.Clear() + gtest.Assert(s.Size(), 0) + }) +} + func TestSet_Basic(t *testing.T) { - gtest.Case(t, func() { - s := gset.NewSet() - s.Add(1).Add(1).Add(2) - s.Add([]interface{}{3,4}...) - gtest.Assert(s.Size(), 4) - gtest.AssertIN(1, s.Slice()) - gtest.AssertIN(2, s.Slice()) - gtest.AssertIN(3, s.Slice()) - gtest.AssertIN(4, s.Slice()) - gtest.AssertNI(0, s.Slice()) - gtest.Assert(s.Contains(4), true) - gtest.Assert(s.Contains(5), false) - s.Remove(1) - gtest.Assert(s.Size(), 3) - s.Clear() - gtest.Assert(s.Size(), 0) - }) + gtest.Case(t, func() { + s := gset.NewSet() + s.Add(1).Add(1).Add(2) + s.Add([]interface{}{3, 4}...) + gtest.Assert(s.Size(), 4) + gtest.AssertIN(1, s.Slice()) + gtest.AssertIN(2, s.Slice()) + gtest.AssertIN(3, s.Slice()) + gtest.AssertIN(4, s.Slice()) + gtest.AssertNI(0, s.Slice()) + gtest.Assert(s.Contains(4), true) + gtest.Assert(s.Contains(5), false) + s.Remove(1) + gtest.Assert(s.Size(), 3) + s.Clear() + gtest.Assert(s.Size(), 0) + }) } func TestSet_Iterator(t *testing.T) { - gtest.Case(t, func() { - s := gset.NewSet() - s.Add(1).Add(2).Add(3) - gtest.Assert(s.Size(), 3) + gtest.Case(t, func() { + s := gset.NewSet() + s.Add(1).Add(2).Add(3) + gtest.Assert(s.Size(), 3) - a1 := garray.New() - a2 := garray.New() - s.Iterator(func(v interface{}) bool { - a1.Append(1) - return false - }) - s.Iterator(func(v interface{}) bool { - a2.Append(1) - return true - }) - gtest.Assert(a1.Len(), 1) - gtest.Assert(a2.Len(), 3) - }) + a1 := garray.New() + a2 := garray.New() + s.Iterator(func(v interface{}) bool { + a1.Append(1) + return false + }) + s.Iterator(func(v interface{}) bool { + a2.Append(1) + return true + }) + gtest.Assert(a1.Len(), 1) + gtest.Assert(a2.Len(), 3) + }) } func TestSet_LockFunc(t *testing.T) { - gtest.Case(t, func() { - s := gset.NewSet() - s.Add(1).Add(2).Add(3) - gtest.Assert(s.Size(), 3) - s.LockFunc(func(m map[interface{}]struct{}) { - delete(m, 1) - }) - gtest.Assert(s.Size(), 2) - s.RLockFunc(func(m map[interface{}]struct{}) { - gtest.Assert(m, map[interface{}]struct{}{ - 3 : struct{}{}, - 2 : struct{}{}, - }) - }) - }) + gtest.Case(t, func() { + s := gset.NewSet() + s.Add(1).Add(2).Add(3) + gtest.Assert(s.Size(), 3) + s.LockFunc(func(m map[interface{}]struct{}) { + delete(m, 1) + }) + gtest.Assert(s.Size(), 2) + s.RLockFunc(func(m map[interface{}]struct{}) { + gtest.Assert(m, map[interface{}]struct{}{ + 3: struct{}{}, + 2: struct{}{}, + }) + }) + }) } func TestSet_Equal(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s3 := gset.NewSet() - s1.Add(1).Add(2).Add(3) - s2.Add(1).Add(2).Add(3) - s3.Add(1).Add(2).Add(3).Add(4) - gtest.Assert(s1.Equal(s2), true) - gtest.Assert(s1.Equal(s3), false) - }) + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s3 := gset.NewSet() + s1.Add(1).Add(2).Add(3) + s2.Add(1).Add(2).Add(3) + s3.Add(1).Add(2).Add(3).Add(4) + gtest.Assert(s1.Equal(s2), true) + gtest.Assert(s1.Equal(s3), false) + }) } func TestSet_IsSubsetOf(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s3 := gset.NewSet() - s1.Add(1).Add(2) - s2.Add(1).Add(2).Add(3) - s3.Add(1).Add(2).Add(3).Add(4) - gtest.Assert(s1.IsSubsetOf(s2), true) - gtest.Assert(s2.IsSubsetOf(s3), true) - gtest.Assert(s1.IsSubsetOf(s3), true) - gtest.Assert(s2.IsSubsetOf(s1), false) - gtest.Assert(s3.IsSubsetOf(s2), false) - }) + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s3 := gset.NewSet() + s1.Add(1).Add(2) + s2.Add(1).Add(2).Add(3) + s3.Add(1).Add(2).Add(3).Add(4) + gtest.Assert(s1.IsSubsetOf(s2), true) + gtest.Assert(s2.IsSubsetOf(s3), true) + gtest.Assert(s1.IsSubsetOf(s3), true) + gtest.Assert(s2.IsSubsetOf(s1), false) + gtest.Assert(s3.IsSubsetOf(s2), false) + }) } func TestSet_Union(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s1.Add(1).Add(2) - s2.Add(3).Add(4) - s3 := s1.Union(s2) - gtest.Assert(s3.Contains(1), true) - gtest.Assert(s3.Contains(2), true) - gtest.Assert(s3.Contains(3), true) - gtest.Assert(s3.Contains(4), true) - }) + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s1.Add(1).Add(2) + s2.Add(3).Add(4) + s3 := s1.Union(s2) + gtest.Assert(s3.Contains(1), true) + gtest.Assert(s3.Contains(2), true) + gtest.Assert(s3.Contains(3), true) + gtest.Assert(s3.Contains(4), true) + }) } func TestSet_Diff(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s1.Add(1).Add(2).Add(3) - s2.Add(3).Add(4).Add(5) - s3 := s1.Diff(s2) - gtest.Assert(s3.Contains(1), true) - gtest.Assert(s3.Contains(2), true) - gtest.Assert(s3.Contains(3), false) - gtest.Assert(s3.Contains(4), false) - }) + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s1.Add(1).Add(2).Add(3) + s2.Add(3).Add(4).Add(5) + s3 := s1.Diff(s2) + gtest.Assert(s3.Contains(1), true) + gtest.Assert(s3.Contains(2), true) + gtest.Assert(s3.Contains(3), false) + gtest.Assert(s3.Contains(4), false) + }) } func TestSet_Intersect(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s1.Add(1).Add(2).Add(3) - s2.Add(3).Add(4).Add(5) - s3 := s1.Intersect(s2) - gtest.Assert(s3.Contains(1), false) - gtest.Assert(s3.Contains(2), false) - gtest.Assert(s3.Contains(3), true) - gtest.Assert(s3.Contains(4), false) - }) + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s1.Add(1).Add(2).Add(3) + s2.Add(3).Add(4).Add(5) + s3 := s1.Intersect(s2) + gtest.Assert(s3.Contains(1), false) + gtest.Assert(s3.Contains(2), false) + gtest.Assert(s3.Contains(3), true) + gtest.Assert(s3.Contains(4), false) + }) } func TestSet_Complement(t *testing.T) { - gtest.Case(t, func() { - s1 := gset.NewSet() - s2 := gset.NewSet() - s1.Add(1).Add(2).Add(3) - s2.Add(3).Add(4).Add(5) - s3 := s1.Complement(s2) - gtest.Assert(s3.Contains(1), false) - gtest.Assert(s3.Contains(2), false) - gtest.Assert(s3.Contains(4), true) - gtest.Assert(s3.Contains(5), true) - }) -} \ No newline at end of file + gtest.Case(t, func() { + s1 := gset.NewSet() + s2 := gset.NewSet() + s1.Add(1).Add(2).Add(3) + s2.Add(3).Add(4).Add(5) + s3 := s1.Complement(s2) + gtest.Assert(s3.Contains(1), false) + gtest.Assert(s3.Contains(2), false) + gtest.Assert(s3.Contains(4), true) + gtest.Assert(s3.Contains(5), true) + }) +} From 6814372a891b699ecdd0085768dfd223f612a6cd Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 15:55:43 +0800 Subject: [PATCH 11/24] add gcrc test2 --- g/crypto/gcrc32/gcrc32_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/g/crypto/gcrc32/gcrc32_test.go b/g/crypto/gcrc32/gcrc32_test.go index 27c301fbc..7a67d1c41 100644 --- a/g/crypto/gcrc32/gcrc32_test.go +++ b/g/crypto/gcrc32/gcrc32_test.go @@ -9,6 +9,7 @@ package gcrc32_test import ( + "github.com/gogf/gf/g/crypto/gmd5" "testing" "github.com/gogf/gf/g/crypto/gcrc32" @@ -34,5 +35,10 @@ func TestEncrypt(t *testing.T) { encrypt2 := gcrc32.Encrypt([]byte(s)) gtest.AssertEQ(int(encrypt1), result) gtest.AssertEQ(int(encrypt2), result) + + strmd5 := gmd5.Encrypt(s) + test1 := gcrc32.Encrypt(strmd5) + test2 := gcrc32.Encrypt([]byte(strmd5)) + gtest.AssertEQ(test2, test1) }) } From 501c3680d931bb998950662196c48b2de8315e3d Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 17:26:32 +0800 Subject: [PATCH 12/24] add gaes test --- g/crypto/gaes/gaes_test.go | 58 ++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/g/crypto/gaes/gaes_test.go b/g/crypto/gaes/gaes_test.go index fbae75d9c..1a3fb24da 100644 --- a/g/crypto/gaes/gaes_test.go +++ b/g/crypto/gaes/gaes_test.go @@ -18,11 +18,14 @@ import ( var ( content = []byte("pibigstar") // iv 长度必须等于blockSize,只能为16 - iv = []byte("Hello My GoFrame") - key_16 = []byte("1234567891234567") - key_24 = []byte("123456789123456789123456") - key_32 = []byte("12345678912345678912345678912345") - keys = []byte("12345678912345678912345678912346") + iv = []byte("Hello My GoFrame") + key_16 = []byte("1234567891234567") + key_17 = []byte("12345678912345670") + key_24 = []byte("123456789123456789123456") + key_32 = []byte("12345678912345678912345678912345") + keys = []byte("12345678912345678912345678912346") + key_err = []byte("1234") + key_32_err = []byte("1234567891234567891234567891234 ") ) func TestEncrypt(t *testing.T) { @@ -38,6 +41,51 @@ func TestEncrypt(t *testing.T) { }) } +func TestEncryptErr(t *testing.T) { + gtest.Case(t, func() { + // encrypt key error + _, err := gaes.Encrypt(content, key_err) + gtest.AssertNE(err, nil) + }) +} + +func TestDecryptErr(t *testing.T) { + gtest.Case(t, func() { + // decrypt key error + encrypt, err := gaes.Encrypt(content, key_16) + _, err = gaes.Decrypt(encrypt, key_err) + gtest.AssertNE(err, nil) + + // decrypt content too short error + _, err = gaes.Decrypt([]byte("test"), key_16) + gtest.AssertNE(err, nil) + + // decrypt content size error + _, err = gaes.Decrypt(key_17, key_16) + gtest.AssertNE(err, nil) + }) +} + +func TestPKCS5UnPaddingErr(t *testing.T) { + gtest.Case(t, func() { + // PKCS5UnPadding blockSize zero + _, err := gaes.PKCS5UnPadding(content, 0) + gtest.AssertNE(err, nil) + + // PKCS5UnPadding src len zero + _, err = gaes.PKCS5UnPadding([]byte(""), 16) + gtest.AssertNE(err, nil) + + // PKCS5UnPadding src len > blockSize + _, err = gaes.PKCS5UnPadding(key_17, 16) + gtest.AssertNE(err, nil) + + // PKCS5UnPadding src len > blockSize + _, err = gaes.PKCS5UnPadding(key_32_err, 32) + gtest.AssertNE(err, nil) + }) +} + func TestDecrypt(t *testing.T) { gtest.Case(t, func() { encrypt, err := gaes.Encrypt(content, key_16) From 334cd7ad515ec4c553bd3acc5cfa21e1ddedd8df Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 18:59:42 +0800 Subject: [PATCH 13/24] add gregex test --- g/text/gregex/gregex_z_unit_test.go | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/g/text/gregex/gregex_z_unit_test.go b/g/text/gregex/gregex_z_unit_test.go index 64ce85489..bd2556b3b 100644 --- a/g/text/gregex/gregex_z_unit_test.go +++ b/g/text/gregex/gregex_z_unit_test.go @@ -15,6 +15,10 @@ import ( "testing" ) +var ( + PatternErr = `([\d+` +) + func Test_Quote(t *testing.T) { gtest.Case(t, func() { s1 := `[foo]` //`\[foo\]` @@ -40,6 +44,8 @@ func Test_IsMatch(t *testing.T) { gtest.Assert(gregex.IsMatch(pattern, s1), false) s1 = []byte(`sfs:`) gtest.Assert(gregex.IsMatch(pattern, s1), false) + // error pattern + gtest.Assert(gregex.IsMatch(PatternErr, s1), false) }) } @@ -52,6 +58,8 @@ func Test_IsMatchString(t *testing.T) { gtest.Assert(gregex.IsMatchString(pattern, s1), false) s1 = `sfs:` gtest.Assert(gregex.IsMatchString(pattern, s1), false) + // error pattern + gtest.Assert(gregex.IsMatchString(PatternErr, s1), false) }) } @@ -68,6 +76,9 @@ func Test_Match(t *testing.T) { if string(subs[1]) != "aab" { t.Fatalf("Match(%q)[1] = %q; want %q", s, subs[1], "aab") } + // error pattern + _, err = gregex.Match(PatternErr, []byte(s)) + gtest.AssertNE(err, nil) }) } @@ -84,6 +95,9 @@ func Test_MatchString(t *testing.T) { if string(subs[1]) != "aab" { t.Fatalf("Match(%q)[1] = %q; want %q", s, subs[1], "aab") } + // error pattern + _, err = gregex.MatchString(PatternErr, s) + gtest.AssertNE(err, nil) }) } @@ -108,6 +122,9 @@ func Test_MatchAll(t *testing.T) { if string(subs[1][1]) != "aab" { t.Fatalf("Match(%q)[1] = %q; want %q", s, subs[1][1], "aab") } + // error pattern + _, err = gregex.MatchAll(PatternErr, []byte(s)) + gtest.AssertNE(err, nil) }) } @@ -131,6 +148,9 @@ func Test_MatchAllString(t *testing.T) { if string(subs[1][1]) != "aab" { t.Fatalf("Match(%q)[1] = %q; want %q", s, subs[1][1], "aab") } + // error pattern + _, err = gregex.MatchAllString(PatternErr, s) + gtest.AssertNE(err, nil) }) } @@ -146,6 +166,9 @@ func Test_Replace(t *testing.T) { if string(replacedStr) != wanted { t.Fatalf("regex:%s,old:%s; want %q", re, s, wanted) } + // error pattern + _, err = gregex.Replace(PatternErr, []byte(replace), []byte(s)) + gtest.AssertNE(err, nil) }) } @@ -161,6 +184,9 @@ func Test_ReplaceString(t *testing.T) { if replacedStr != wanted { t.Fatalf("regex:%s,old:%s; want %q", re, s, wanted) } + // error pattern + _, err = gregex.ReplaceString(PatternErr, replace, s) + gtest.AssertNE(err, nil) }) } @@ -182,6 +208,11 @@ func Test_ReplaceFun(t *testing.T) { if string(replacedStr) != wanted { t.Fatalf("regex:%s,old:%s; want %q", re, s, wanted) } + // error pattern + _, err = gregex.ReplaceFunc(PatternErr, []byte(s), func(s []byte) []byte { + return []byte("") + }) + gtest.AssertNE(err, nil) }) } @@ -209,6 +240,11 @@ func Test_ReplaceFuncMatch(t *testing.T) { }) gtest.Assert(e3, nil) gtest.Assert(s3, []byte("7890")) + // error pattern + _, err := gregex.ReplaceFuncMatch(PatternErr, s, func(match [][]byte) []byte { + return match[3] + }) + gtest.AssertNE(err, nil) }) } @@ -230,6 +266,11 @@ func Test_ReplaceStringFunc(t *testing.T) { if replacedStr != wanted { t.Fatalf("regex:%s,old:%s; want %q", re, s, wanted) } + // error pattern + _, err = gregex.ReplaceStringFunc(PatternErr, s, func(s string) string { + return "" + }) + gtest.AssertNE(err, nil) }) } @@ -257,6 +298,11 @@ func Test_ReplaceStringFuncMatch(t *testing.T) { }) gtest.Assert(e3, nil) gtest.Assert(s3, "7890") + // error pattern + _, err := gregex.ReplaceStringFuncMatch(PatternErr, s, func(match []string) string { + return "" + }) + gtest.AssertNE(err, nil) }) } @@ -288,6 +334,9 @@ func Test_Split(t *testing.T) { if items[0] != s { t.Fatalf("regex:%s,Split(%q) want %q", re, s, item0) } + // error pattern + items = gregex.Split(PatternErr, s) + gtest.AssertEQ(items, nil) }) } From 59ae6217cddf7c589ad80b3b6a29129de32f414a Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 19:37:02 +0800 Subject: [PATCH 14/24] add gaes test3: add encrypt assert content --- g/crypto/gaes/gaes_test.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/g/crypto/gaes/gaes_test.go b/g/crypto/gaes/gaes_test.go index 1a3fb24da..36f0101a7 100644 --- a/g/crypto/gaes/gaes_test.go +++ b/g/crypto/gaes/gaes_test.go @@ -9,6 +9,7 @@ package gaes_test import ( + "github.com/gogf/gf/g/encoding/gbase64" "testing" "github.com/gogf/gf/g/crypto/gaes" @@ -16,7 +17,11 @@ import ( ) var ( - content = []byte("pibigstar") + content = []byte("pibigstar") + content_16, _ = gbase64.Decode("v1jqsGHId/H8onlVHR8Vaw==") + content_24, _ = gbase64.Decode("0TXOaj5KMoLhNWmJ3lxY1A==") + content_32, _ = gbase64.Decode("qM/Waw1kkWhrwzek24rCSA==") + content_16_iv, _ = gbase64.Decode("DqQUXiHgW/XFb6Qs98+hrA==") // iv 长度必须等于blockSize,只能为16 iv = []byte("Hello My GoFrame") key_16 = []byte("1234567891234567") @@ -30,14 +35,18 @@ var ( func TestEncrypt(t *testing.T) { gtest.Case(t, func() { - _, err := gaes.Encrypt(content, key_16) + data, err := gaes.Encrypt(content, key_16) gtest.Assert(err, nil) - _, err = gaes.Encrypt(content, key_24) + gtest.Assert(string(data), content_16) + data, err = gaes.Encrypt(content, key_24) gtest.Assert(err, nil) - _, err = gaes.Encrypt(content, key_32) + gtest.Assert(string(data), content_24) + data, err = gaes.Encrypt(content, key_32) gtest.Assert(err, nil) - _, err = gaes.Encrypt(content, key_16, iv) + gtest.Assert(string(data), content_32) + data, err = gaes.Encrypt(content, key_16, iv) gtest.Assert(err, nil) + gtest.Assert(string(data), content_16_iv) }) } From b0b6871bbb581cc8b2e526b979a7f38f50da5a21 Mon Sep 17 00:00:00 2001 From: zdl <381897429@qq.com> Date: Mon, 10 Jun 2019 19:50:45 +0800 Subject: [PATCH 15/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20genv=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/genv/genv_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 g/os/genv/genv_test.go diff --git a/g/os/genv/genv_test.go b/g/os/genv/genv_test.go new file mode 100644 index 000000000..e4b64062f --- /dev/null +++ b/g/os/genv/genv_test.go @@ -0,0 +1,36 @@ +package genv_test + +import ( + "github.com/gogf/gf/g/os/genv" + "github.com/gogf/gf/g/test/gtest" + "os" + "testing" + "time" +) + +func Test_Genv_All(t *testing.T) { + gtest.Case(t, func() { + gtest.Assert(os.Environ(), genv.All()) + }) +} + +func Test_Genv_Get(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ("keke", genv.Get("LLL"+time.Now().String(), "keke")) + gtest.AssertEQ("", genv.Get("LLL"+time.Now().String())) + }) +} + +func Test_Genv_Set(t *testing.T) { + gtest.Case(t, func() { + err := genv.Set("LLL", "keke") + gtest.Assert(err, nil) + }) +} + +func Test_Genv_Remove(t *testing.T) { + gtest.Case(t, func() { + err := genv.Remove("LLL") + gtest.Assert(err, nil) + }) +} From be6f522cf3c911a718948c185fe0453f4f8e0a52 Mon Sep 17 00:00:00 2001 From: zhangbiao Date: Mon, 10 Jun 2019 19:53:07 +0800 Subject: [PATCH 16/24] add gaes test4:optimize Encrypt Decrypt test --- g/crypto/gaes/gaes_test.go | 59 ++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/g/crypto/gaes/gaes_test.go b/g/crypto/gaes/gaes_test.go index 36f0101a7..9805dda4a 100644 --- a/g/crypto/gaes/gaes_test.go +++ b/g/crypto/gaes/gaes_test.go @@ -22,6 +22,7 @@ var ( content_24, _ = gbase64.Decode("0TXOaj5KMoLhNWmJ3lxY1A==") content_32, _ = gbase64.Decode("qM/Waw1kkWhrwzek24rCSA==") content_16_iv, _ = gbase64.Decode("DqQUXiHgW/XFb6Qs98+hrA==") + content_32_iv, _ = gbase64.Decode("ZuLgAOii+lrD5KJoQ7yQ8Q==") // iv 长度必须等于blockSize,只能为16 iv = []byte("Hello My GoFrame") key_16 = []byte("1234567891234567") @@ -47,6 +48,36 @@ func TestEncrypt(t *testing.T) { data, err = gaes.Encrypt(content, key_16, iv) gtest.Assert(err, nil) gtest.Assert(string(data), content_16_iv) + data, err = gaes.Encrypt(content, key_32, iv) + gtest.Assert(err, nil) + gtest.Assert(string(data), content_32_iv) + }) +} + +func TestDecrypt(t *testing.T) { + gtest.Case(t, func() { + decrypt, err := gaes.Decrypt([]byte(content_16), key_16) + gtest.Assert(err, nil) + gtest.Assert(string(decrypt), string(content)) + + decrypt, err = gaes.Decrypt([]byte(content_24), key_24) + gtest.Assert(err, nil) + gtest.Assert(string(decrypt), string(content)) + + decrypt, err = gaes.Decrypt([]byte(content_32), key_32) + gtest.Assert(err, nil) + gtest.Assert(string(decrypt), string(content)) + + decrypt, err = gaes.Decrypt([]byte(content_16_iv), key_16, iv) + gtest.Assert(err, nil) + gtest.Assert(string(decrypt), string(content)) + + decrypt, err = gaes.Decrypt([]byte(content_32_iv), key_32, iv) + gtest.Assert(err, nil) + gtest.Assert(string(decrypt), string(content)) + + decrypt, err = gaes.Decrypt([]byte(content_32_iv), keys, iv) + gtest.Assert(err, "invalid padding") }) } @@ -94,31 +125,3 @@ func TestPKCS5UnPaddingErr(t *testing.T) { gtest.AssertNE(err, nil) }) } - -func TestDecrypt(t *testing.T) { - gtest.Case(t, func() { - encrypt, err := gaes.Encrypt(content, key_16) - decrypt, err := gaes.Decrypt(encrypt, key_16) - gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) - - encrypt, err = gaes.Encrypt(content, key_24) - decrypt, err = gaes.Decrypt(encrypt, key_24) - gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) - - encrypt, err = gaes.Encrypt(content, key_32) - decrypt, err = gaes.Decrypt(encrypt, key_32) - gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) - - encrypt, err = gaes.Encrypt(content, key_32, iv) - decrypt, err = gaes.Decrypt(encrypt, key_32, iv) - gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) - - encrypt, err = gaes.Encrypt(content, key_32, iv) - decrypt, err = gaes.Decrypt(encrypt, keys, iv) - gtest.Assert(err, "invalid padding") - }) -} From 3320d12994242ecea5cc7b7c362acdd40da31902 Mon Sep 17 00:00:00 2001 From: piaohao Date: Mon, 10 Jun 2019 19:58:00 +0800 Subject: [PATCH 17/24] =?UTF-8?q?gcache=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/gcache/gcache_z_unit_1_test.go | 290 ++++++++++++++++++++++++---- 1 file changed, 249 insertions(+), 41 deletions(-) diff --git a/g/os/gcache/gcache_z_unit_1_test.go b/g/os/gcache/gcache_z_unit_1_test.go index 4f0590a66..0cd6ea07c 100644 --- a/g/os/gcache/gcache_z_unit_1_test.go +++ b/g/os/gcache/gcache_z_unit_1_test.go @@ -9,57 +9,265 @@ package gcache_test import ( - "github.com/gogf/gf/g/os/gcache" - "github.com/gogf/gf/g/test/gtest" - "testing" - "time" + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/container/gset" + "github.com/gogf/gf/g/os/gcache" + "github.com/gogf/gf/g/os/grpool" + "github.com/gogf/gf/g/test/gtest" + "testing" + "time" ) +//clear 用于清除全局缓存,因gcache api 暂未暴露 Clear 方法 +//暂定所有测试用例key的集合为1,2,3,避免不同测试用例间因全局cache共享带来的问题,每个测试用例在测试gcache.XXX之前,先调用clear() +func clear() { + gcache.Removes(g.Slice{1, 2, 3}) +} + func TestCache_Set(t *testing.T) { - gtest.Case(t, func() { - cache := gcache.New() - cache.Set(1, 11, 0) - gtest.Assert(cache.Get(1), 11) - }) + gtest.Case(t, func() { + cache := gcache.New() + cache.Set(1, 11, 0) + gtest.Assert(cache.Get(1), 11) + gtest.Assert(cache.Contains(1), true) + + clear() + gcache.Set(1, 11, 0) + gtest.Assert(gcache.Get(1), 11) + gtest.Assert(gcache.Contains(1), true) + }) } func TestCache_Set_Expire(t *testing.T) { - gtest.Case(t, func() { - cache := gcache.New() - cache.Set(2, 22, 100) - gtest.Assert(cache.Get(2), 22) - time.Sleep(200*time.Millisecond) - gtest.Assert(cache.Get(2), nil) - time.Sleep(3*time.Second) - gtest.Assert(cache.Size(), 0) - }) + gtest.Case(t, func() { + cache := gcache.New() + cache.Set(2, 22, 100) + gtest.Assert(cache.Get(2), 22) + time.Sleep(200 * time.Millisecond) + gtest.Assert(cache.Get(2), nil) + time.Sleep(3 * time.Second) + gtest.Assert(cache.Size(), 0) + cache.Close() + }) } func TestCache_Keys_Values(t *testing.T) { - gtest.Case(t, func() { - cache := gcache.New() - for i := 0; i < 10; i++ { - cache.Set(i, i*10, 0) - } - gtest.Assert(len(cache.Keys()), 10) - gtest.Assert(len(cache.Values()), 10) - gtest.AssertIN(0, cache.Keys()) - gtest.AssertIN(90, cache.Values()) - }) + gtest.Case(t, func() { + cache := gcache.New() + for i := 0; i < 10; i++ { + cache.Set(i, i*10, 0) + } + gtest.Assert(len(cache.Keys()), 10) + gtest.Assert(len(cache.Values()), 10) + gtest.AssertIN(0, cache.Keys()) + gtest.AssertIN(90, cache.Values()) + }) } func TestCache_LRU(t *testing.T) { - gtest.Case(t, func() { - cache := gcache.New(2) - for i := 0; i < 10; i++ { - cache.Set(i, i, 0) - } + gtest.Case(t, func() { + cache := gcache.New(2) + for i := 0; i < 10; i++ { + cache.Set(i, i, 0) + } + gtest.Assert(cache.Size(), 10) + gtest.Assert(cache.Get(6), 6) + time.Sleep(4 * time.Second) + gtest.Assert(cache.Size(), 2) + gtest.Assert(cache.Get(6), 6) + gtest.Assert(cache.Get(1), nil) + cache.Close() + }) +} - gtest.Assert(cache.Size(), 10) - gtest.Assert(cache.Get(6), 6) - time.Sleep(4*time.Second) - gtest.Assert(cache.Size(), 2) - gtest.Assert(cache.Get(6), 6) - gtest.Assert(cache.Get(1), nil) - }) -} \ No newline at end of file +func TestCache_LRU_expire(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New(2) + cache.Set(1, nil, 1000) + gtest.Assert(cache.Size(), 1) + gtest.Assert(cache.Get(1), nil) + }) +} + +func TestCache_SetIfNotExist(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.SetIfNotExist(1, 11, 0) + gtest.Assert(cache.Get(1), 11) + cache.SetIfNotExist(1, 22, 0) + gtest.Assert(cache.Get(1), 11) + cache.SetIfNotExist(2, 22, 0) + gtest.Assert(cache.Get(2), 22) + + clear() + gcache.SetIfNotExist(1, 11, 0) + gtest.Assert(gcache.Get(1), 11) + gcache.SetIfNotExist(1, 22, 0) + gtest.Assert(gcache.Get(1), 11) + }) +} + +func TestCache_Sets(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.Sets(g.MapAnyAny{1: 11, 2: 22}, 0) + gtest.Assert(cache.Get(1), 11) + + clear() + gcache.Sets(g.MapAnyAny{1: 11, 2: 22}, 0) + gtest.Assert(gcache.Get(1), 11) + }) +} + +func TestCache_GetOrSet(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.GetOrSet(1, 11, 0) + gtest.Assert(cache.Get(1), 11) + cache.GetOrSet(1, 111, 0) + gtest.Assert(cache.Get(1), 11) + + clear() + gcache.GetOrSet(1, 11, 0) + gtest.Assert(gcache.Get(1), 11) + gcache.GetOrSet(1, 111, 0) + gtest.Assert(gcache.Get(1), 11) + }) +} + +func TestCache_GetOrSetFunc(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.GetOrSetFunc(1, func() interface{} { + return 11 + }, 0) + gtest.Assert(cache.Get(1), 11) + cache.GetOrSetFunc(1, func() interface{} { + return 111 + }, 0) + gtest.Assert(cache.Get(1), 11) + + clear() + gcache.GetOrSetFunc(1, func() interface{} { + return 11 + }, 0) + gtest.Assert(gcache.Get(1), 11) + gcache.GetOrSetFunc(1, func() interface{} { + return 111 + }, 0) + gtest.Assert(gcache.Get(1), 11) + }) +} + +func TestCache_GetOrSetFuncLock(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.GetOrSetFuncLock(1, func() interface{} { + return 11 + }, 0) + gtest.Assert(cache.Get(1), 11) + cache.GetOrSetFuncLock(1, func() interface{} { + return 111 + }, 0) + gtest.Assert(cache.Get(1), 11) + + clear() + gcache.GetOrSetFuncLock(1, func() interface{} { + return 11 + }, 0) + gtest.Assert(gcache.Get(1), 11) + gcache.GetOrSetFuncLock(1, func() interface{} { + return 111 + }, 0) + gtest.Assert(gcache.Get(1), 11) + }) +} + +func TestCache_Clear(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + cache.Sets(g.MapAnyAny{1: 11, 2: 22}, 0) + cache.Clear() + gtest.Assert(cache.Size(), 0) + }) +} + +func TestCache_SetConcurrency(t *testing.T) { + gtest.Case(t, func() { + cache := gcache.New() + pool := grpool.New(4) + go func() { + for { + pool.Add(func() { + cache.SetIfNotExist(1, 11, 10) + }) + } + }() + select { + case <-time.After(2 * time.Second): + t.Log("first part end") + } + + go func() { + for { + pool.Add(func() { + cache.SetIfNotExist(1, nil, 10) + }) + } + }() + select { + case <-time.After(2 * time.Second): + t.Log("second part end") + } + }) +} + +func TestCache_Basic(t *testing.T) { + gtest.Case(t, func() { + { + cache := gcache.New() + cache.Sets(g.MapAnyAny{1: 11, 2: 22}, 0) + gtest.Assert(cache.Contains(1), true) + gtest.Assert(cache.Get(1), 11) + data := cache.Data() + gtest.Assert(data[1], 11) + gtest.Assert(data[2], 22) + gtest.Assert(data[3], nil) + gtest.Assert(cache.Size(), 2) + keys := cache.Keys() + gtest.Assert(gset.NewFrom(g.Slice{1, 2}).Equal(gset.NewFrom(keys)), true) + keyStrs := cache.KeyStrings() + gtest.Assert(gset.NewFrom(g.Slice{"1", "2"}).Equal(gset.NewFrom(keyStrs)), true) + values := cache.Values() + gtest.Assert(gset.NewFrom(g.Slice{11, 22}).Equal(gset.NewFrom(values)), true) + removeData1 := cache.Remove(1) + gtest.Assert(removeData1, 11) + gtest.Assert(cache.Size(), 1) + cache.Removes(g.Slice{2}) + gtest.Assert(cache.Size(), 0) + } + + clear() + { + gcache.Sets(g.MapAnyAny{1: 11, 2: 22}, 0) + gtest.Assert(gcache.Contains(1), true) + gtest.Assert(gcache.Get(1), 11) + data := gcache.Data() + gtest.Assert(data[1], 11) + gtest.Assert(data[2], 22) + gtest.Assert(data[3], nil) + gtest.Assert(gcache.Size(), 2) + keys := gcache.Keys() + gtest.Assert(gset.NewFrom(g.Slice{1, 2}).Equal(gset.NewFrom(keys)), true) + keyStrs := gcache.KeyStrings() + gtest.Assert(gset.NewFrom(g.Slice{"1", "2"}).Equal(gset.NewFrom(keyStrs)), true) + values := gcache.Values() + gtest.Assert(gset.NewFrom(g.Slice{11, 22}).Equal(gset.NewFrom(values)), true) + removeData1 := gcache.Remove(1) + gtest.Assert(removeData1, 11) + gtest.Assert(gcache.Size(), 1) + gcache.Removes(g.Slice{2}) + gtest.Assert(gcache.Size(), 0) + } + }) +} From e479c41667fceecfe486937ec0016dfa2154be7f Mon Sep 17 00:00:00 2001 From: zdl <381897429@qq.com> Date: Mon, 10 Jun 2019 20:24:11 +0800 Subject: [PATCH 18/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20genv=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/genv/genv_test.go | 17 ++++++++++++----- go.mod | 4 +++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/g/os/genv/genv_test.go b/g/os/genv/genv_test.go index e4b64062f..c67063d1c 100644 --- a/g/os/genv/genv_test.go +++ b/g/os/genv/genv_test.go @@ -5,7 +5,6 @@ import ( "github.com/gogf/gf/g/test/gtest" "os" "testing" - "time" ) func Test_Genv_All(t *testing.T) { @@ -16,21 +15,29 @@ func Test_Genv_All(t *testing.T) { func Test_Genv_Get(t *testing.T) { gtest.Case(t, func() { - gtest.AssertEQ("keke", genv.Get("LLL"+time.Now().String(), "keke")) - gtest.AssertEQ("", genv.Get("LLL"+time.Now().String())) + key := "TEST_ENV" + err := os.Setenv(key, "TEST") + gtest.Assert(err, nil) + gtest.AssertEQ(genv.Get(key), "TEST") }) } func Test_Genv_Set(t *testing.T) { gtest.Case(t, func() { - err := genv.Set("LLL", "keke") + key := "TEST_ENV" + err := genv.Set(key, "TEST") gtest.Assert(err, nil) + gtest.AssertEQ(os.Getenv(key), "TEST") }) } func Test_Genv_Remove(t *testing.T) { gtest.Case(t, func() { - err := genv.Remove("LLL") + key := "TEST_ENV" + err := os.Setenv(key, "TEST") gtest.Assert(err, nil) + err = genv.Remove(key) + gtest.Assert(err, nil) + gtest.AssertEQ(os.Getenv(key), "") }) } diff --git a/go.mod b/go.mod index fd3232e72..081d99cd0 100644 --- a/go.mod +++ b/go.mod @@ -1 +1,3 @@ -module github.com/gogf/gf \ No newline at end of file +module github.com/gogf/gf + +go 1.12 From ffd78d76e1d65040c3572aba37a7a428e65eae94 Mon Sep 17 00:00:00 2001 From: zdl <381897429@qq.com> Date: Mon, 10 Jun 2019 20:44:30 +0800 Subject: [PATCH 19/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20genv=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/genv/genv_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/g/os/genv/genv_test.go b/g/os/genv/genv_test.go index c67063d1c..9f9a894e4 100644 --- a/g/os/genv/genv_test.go +++ b/g/os/genv/genv_test.go @@ -15,7 +15,7 @@ func Test_Genv_All(t *testing.T) { func Test_Genv_Get(t *testing.T) { gtest.Case(t, func() { - key := "TEST_ENV" + key := "TEST_GET_ENV" err := os.Setenv(key, "TEST") gtest.Assert(err, nil) gtest.AssertEQ(genv.Get(key), "TEST") @@ -24,7 +24,7 @@ func Test_Genv_Get(t *testing.T) { func Test_Genv_Set(t *testing.T) { gtest.Case(t, func() { - key := "TEST_ENV" + key := "TEST_SET_ENV" err := genv.Set(key, "TEST") gtest.Assert(err, nil) gtest.AssertEQ(os.Getenv(key), "TEST") @@ -33,7 +33,7 @@ func Test_Genv_Set(t *testing.T) { func Test_Genv_Remove(t *testing.T) { gtest.Case(t, func() { - key := "TEST_ENV" + key := "TEST_REMOVE_ENV" err := os.Setenv(key, "TEST") gtest.Assert(err, nil) err = genv.Remove(key) From c695dfd92e9a23e8be8eb58c009413d0b236d4de Mon Sep 17 00:00:00 2001 From: zdl <381897429@qq.com> Date: Mon, 10 Jun 2019 20:52:06 +0800 Subject: [PATCH 20/24] delete go version --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index 081d99cd0..28729e4f6 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,2 @@ module github.com/gogf/gf -go 1.12 From f98db6d21cda8e00ebd79055ed0c27829b4579da Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Jun 2019 21:23:49 +0800 Subject: [PATCH 21/24] comments for gcache update --- g/os/gcache/gcache.go | 4 ++-- g/os/gcache/gcache_cache.go | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/g/os/gcache/gcache.go b/g/os/gcache/gcache.go index f24ccf268..3cb14481c 100644 --- a/g/os/gcache/gcache.go +++ b/g/os/gcache/gcache.go @@ -7,10 +7,10 @@ // Package gcache provides high performance and concurrent-safe in-memory cache for process. package gcache -// 全局缓存管理对象 +// Default cache object. var cache = New() -// (使用全局KV缓存对象)设置kv缓存键值对,过期时间单位为**毫秒** +// Set sets with , which is expired after milliseconds. func Set(key interface{}, value interface{}, expire int) { cache.Set(key, value, expire) } diff --git a/g/os/gcache/gcache_cache.go b/g/os/gcache/gcache_cache.go index 33ad10e74..e4456a9db 100644 --- a/g/os/gcache/gcache_cache.go +++ b/g/os/gcache/gcache_cache.go @@ -13,13 +13,12 @@ import ( "unsafe" ) -// 缓存对象。 -// 底层只有一个缓存对象,如果需要提高并发性能,可新增缓存对象无锁哈希表,用键名做固定分区。 +// Cache struct. type Cache struct { *memCache } -// Cache对象按照缓存键名首字母做了分组 +// New creates and returns a new cache object. func New(lruCap...int) *Cache { c := &Cache { memCache : newMemCache(lruCap...), @@ -28,10 +27,8 @@ func New(lruCap...int) *Cache { return c } -// 清空缓存中的所有数据 +// Clear clears all data of the cache. func (c *Cache) Clear() { - // 使用原子操作替换缓存对象 old := atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.memCache)), unsafe.Pointer(newMemCache())) - // 关闭旧的缓存对象 (*memCache)(old).Close() } \ No newline at end of file From 13eb1150a5d5c3c4d62607cd3c1d40ae288e4b32 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Jun 2019 21:32:40 +0800 Subject: [PATCH 22/24] fix issue in gfile.MainPkgPath --- g/os/gfile/gfile.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index e55e156f4..e658a869b 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -425,8 +425,7 @@ func MainPkgPath() string { continue } // separator of '/' will be converted to Separator. - path = Dir(file) - for path[len(path) - 1] != os.PathSeparator { + for path = Dir(file); len(path) > 1 && Exists(path) && path[len(path) - 1] != os.PathSeparator; { files, _ := ScanDir(path, "*.go") for _, v := range files { if gregex.IsMatchString(`package\s+main`, GetContents(v)) { From 46d46afaafe3a513682a985633c2ddc7963222c6 Mon Sep 17 00:00:00 2001 From: "zcool321@sina.com" <1234qwer> Date: Mon, 10 Jun 2019 22:42:46 +0800 Subject: [PATCH 23/24] add gaes test:update assert type --- g/crypto/gaes/gaes_test.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/g/crypto/gaes/gaes_test.go b/g/crypto/gaes/gaes_test.go index 9805dda4a..57f307a6e 100644 --- a/g/crypto/gaes/gaes_test.go +++ b/g/crypto/gaes/gaes_test.go @@ -38,19 +38,19 @@ func TestEncrypt(t *testing.T) { gtest.Case(t, func() { data, err := gaes.Encrypt(content, key_16) gtest.Assert(err, nil) - gtest.Assert(string(data), content_16) + gtest.Assert(data, []byte(content_16)) data, err = gaes.Encrypt(content, key_24) gtest.Assert(err, nil) - gtest.Assert(string(data), content_24) + gtest.Assert(data, []byte(content_24)) data, err = gaes.Encrypt(content, key_32) gtest.Assert(err, nil) - gtest.Assert(string(data), content_32) + gtest.Assert(data, []byte(content_32)) data, err = gaes.Encrypt(content, key_16, iv) gtest.Assert(err, nil) - gtest.Assert(string(data), content_16_iv) + gtest.Assert(data, []byte(content_16_iv)) data, err = gaes.Encrypt(content, key_32, iv) gtest.Assert(err, nil) - gtest.Assert(string(data), content_32_iv) + gtest.Assert(data, []byte(content_32_iv)) }) } @@ -58,23 +58,23 @@ func TestDecrypt(t *testing.T) { gtest.Case(t, func() { decrypt, err := gaes.Decrypt([]byte(content_16), key_16) gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) + gtest.Assert(decrypt, content) decrypt, err = gaes.Decrypt([]byte(content_24), key_24) gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) + gtest.Assert(decrypt, content) decrypt, err = gaes.Decrypt([]byte(content_32), key_32) gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) + gtest.Assert(decrypt, content) decrypt, err = gaes.Decrypt([]byte(content_16_iv), key_16, iv) gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) + gtest.Assert(decrypt, content) decrypt, err = gaes.Decrypt([]byte(content_32_iv), key_32, iv) gtest.Assert(err, nil) - gtest.Assert(string(decrypt), string(content)) + gtest.Assert(decrypt, content) decrypt, err = gaes.Decrypt([]byte(content_32_iv), keys, iv) gtest.Assert(err, "invalid padding") From 08aa7c4e4c82d8b7456c33b6938528e54ec279f7 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Jun 2019 23:54:40 +0800 Subject: [PATCH 24/24] comment update for gcache --- g/os/gcache/gcache.go | 51 ++++++++++++++++++++++----------- g/os/gcache/gcache_mem_cache.go | 22 ++++++++------ 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/g/os/gcache/gcache.go b/g/os/gcache/gcache.go index 3cb14481c..345adda82 100644 --- a/g/os/gcache/gcache.go +++ b/g/os/gcache/gcache.go @@ -10,78 +10,97 @@ package gcache // Default cache object. var cache = New() -// Set sets with , which is expired after milliseconds. + +// Set sets cache with - pair, which is expired after milliseconds. +// If <=0 means it does not expire. func Set(key interface{}, value interface{}, expire int) { cache.Set(key, value, expire) } -// 当键名不存在时写入,并返回true;否则返回false。 -// 常用来做对并发性要求不高的内存锁。 +// SetIfNotExist sets cache with - pair if does not exist in the cache, +// which is expired after milliseconds. +// If <=0 means it does not expire. func SetIfNotExist(key interface{}, value interface{}, expire int) bool { return cache.SetIfNotExist(key, value, expire) } -// (使用全局KV缓存对象)批量设置kv缓存键值对,过期时间单位为**毫秒** +// Sets batch sets cache with key-value pairs by , which is expired after milliseconds. +// If <=0 means it does not expire. func Sets(data map[interface{}]interface{}, expire int) { cache.Sets(data, expire) } -// (使用全局KV缓存对象)获取指定键名的值 +// Get returns the value of . +// It returns nil if it does not exist or its value is nil. func Get(key interface{}) interface{} { return cache.Get(key) } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value of , +// or sets - pair and returns if does not exist in the cache. +// The key-value pair expires after milliseconds. +// If <=0 means it does not expire. func GetOrSet(key interface{}, value interface{}, expire int) interface{} { return cache.GetOrSet(key, value, expire) } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 + +// GetOrSetFunc returns the value of , +// or sets with result of function and returns its result +// if does not exist in the cache. +// The key-value pair expires after milliseconds. +// If <=0 means it does not expire. func GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{} { return cache.GetOrSetFunc(key, f, expire) } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value of , +// or sets with result of function and returns its result +// if does not exist in the cache. +// The key-value pair expires after milliseconds. +// If <=0 means it does not expire. +// +// Note that the function is executed within writing mutex lock. func GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{} { return cache.GetOrSetFuncLock(key, f, expire) } -// 是否存在指定的键名,true表示存在,false表示不存在。 +// Contains returns true if exists in the cache, or else returns false. func Contains(key interface{}) bool { return cache.Contains(key) } -// (使用全局KV缓存对象)删除指定键值对 +// Remove deletes the in the cache, and returns its value. func Remove(key interface{}) interface{} { return cache.Remove(key) } -// (使用全局KV缓存对象)批量删除指定键值对 +// Removes deletes in the cache. func Removes(keys []interface{}) { cache.Removes(keys) } -// 返回缓存的所有数据键值对(不包含已过期数据) +// Data returns a copy of all key-value pairs in the cache as map type. func Data() map[interface{}]interface{} { return cache.Data() } -// 获得所有的键名,组成数组返回 +// Keys returns all keys in the cache as slice. func Keys() []interface{} { return cache.Keys() } -// 获得所有的键名,组成字符串数组返回 +// KeyStrings returns all keys in the cache as string slice. func KeyStrings() []string { return cache.KeyStrings() } -// 获得所有的值,组成数组返回 +// Values returns all values in the cache as slice. func Values() []interface{} { return cache.Values() } -// 获得缓存对象的键值对数量 +// Size returns the size of the cache. func Size() int { return cache.Size() } diff --git a/g/os/gcache/gcache_mem_cache.go b/g/os/gcache/gcache_mem_cache.go index 33836382e..0c4491dca 100644 --- a/g/os/gcache/gcache_mem_cache.go +++ b/g/os/gcache/gcache_mem_cache.go @@ -18,21 +18,25 @@ import ( ) -// 缓存对象 +// Internal cache object. type memCache struct { dataMu sync.RWMutex expireTimeMu sync.RWMutex expireSetMu sync.RWMutex - cap int // 控制缓存池大小,超过大小则按照LRU算法进行缓存过期处理(默认为0表示不进行限制) - data map[interface{}]memCacheItem // 缓存数据(所有的缓存数据存放哈希表) - expireTimes map[interface{}]int64 // 键名对应的分组过期时间(用于相同键名过期时间快速更新),键值为1秒级时间戳 - expireSets map[int64]*gset.Set // 分组过期时间对应的键名列表(用于自动过期快速删除),键值为1秒级时间戳 + // limits the size of the cache pool. + // If the size of the cache exceeds the , + // the cache expiration process is performed according to the LRU algorithm. + // It is 0 in default which means no limits. + cap int + data map[interface{}]memCacheItem // Underlying cache data which is stored in a hash table. + expireTimes map[interface{}]int64 // Expiring key mapping to its timestamp, which is used for quick indexing and deleting. + expireSets map[int64]*gset.Set // Expiring timestamp mapping to its key set, which is used for quick indexing and deleting. - lru *memCacheLru // LRU缓存限制(只有限定cap池大小时才启用) - lruGetList *glist.List // Get操作的LRU记录 - eventList *glist.List // 异步处理队列 - closed *gtype.Bool // 关闭事件通知 + lru *memCacheLru // LRU object, which is enabled when > 0. + lruGetList *glist.List // LRU history according with Get function. + eventList *glist.List // Asynchronous event list for internal data synchronization. + closed *gtype.Bool // Is this cache closed or not. } // 缓存数据项